More plugins, more doc,...
This commit is contained in:
parent
4a2d1a5773
commit
0bb0049f02
105 changed files with 15152 additions and 2757 deletions
BIN
libs/.DS_Store
vendored
Normal file
BIN
libs/.DS_Store
vendored
Normal file
Binary file not shown.
289
libs/LPD8.py
Normal file
289
libs/LPD8.py
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
LPD8
|
||||
v0.7.0
|
||||
|
||||
LPD8 Handler.
|
||||
Start a dedicated thread to handle incoming events from LPD8 midi controller.
|
||||
|
||||
Depending on selected destination computer (Prog Chg + Pad number) actions will be done
|
||||
locally or forwarded via OSC to given computer. Remote computer must run bhorpad or
|
||||
maxwellator.
|
||||
|
||||
# Note
|
||||
|
||||
# Program Change button selected : change destination computer
|
||||
|
||||
# CC rotary -> midi CC.
|
||||
|
||||
|
||||
by Sam Neurohack
|
||||
from /team/laser
|
||||
|
||||
|
||||
"""
|
||||
|
||||
|
||||
import time
|
||||
import rtmidi
|
||||
from rtmidi.midiutil import open_midiinput
|
||||
from threading import Thread
|
||||
from rtmidi.midiconstants import (CHANNEL_PRESSURE, CONTROLLER_CHANGE, NOTE_ON, NOTE_OFF,
|
||||
PITCH_BEND, POLY_PRESSURE, PROGRAM_CHANGE)
|
||||
|
||||
from mido import MidiFile
|
||||
import mido
|
||||
import sys
|
||||
import midi3, launchpad
|
||||
#import midimacros, maxwellmacros
|
||||
import traceback
|
||||
|
||||
from queue import Queue
|
||||
#from libs import macros
|
||||
import json, subprocess
|
||||
from OSC3 import OSCServer, OSCClient, OSCMessage
|
||||
import socket
|
||||
|
||||
print('LPD8 startup...')
|
||||
myHostName = socket.gethostname()
|
||||
print("Name of the localhost is {}".format(myHostName))
|
||||
myIP = socket.gethostbyname(myHostName)
|
||||
print("IP address of the localhost is {}".format(myIP))
|
||||
|
||||
myIP = "127.0.0.1"
|
||||
|
||||
print('Used IP', myIP)
|
||||
OSCinPort = 8080
|
||||
maxwellatorPort = 8090
|
||||
|
||||
LPD8queue = Queue()
|
||||
|
||||
mode = "maxwell"
|
||||
mididest = 'Session 1'
|
||||
|
||||
midichannel = 1
|
||||
CChannel = 0
|
||||
CCvalue = 0
|
||||
Here = -1
|
||||
|
||||
ModeCallback = ''
|
||||
computerIP = ['127.0.0.1','192.168.2.95','192.168.2.52','127.0.0.1',
|
||||
'127.0.0.1','127.0.0.1','127.0.0.1','127.0.0.1']
|
||||
computer = 0
|
||||
|
||||
|
||||
# /cc cc number value
|
||||
def cc(ccnumber, value, dest=mididest):
|
||||
|
||||
midi3.MidiMsg([CONTROLLER_CHANGE+midichannel-1,ccnumber,value], dest)
|
||||
|
||||
def NoteOn(note,velocity, dest=mididest):
|
||||
midi3.NoteOn(note,velocity, mididest)
|
||||
|
||||
def NoteOff(note, dest=mididest):
|
||||
midi3.NoteOn(note, mididest)
|
||||
|
||||
|
||||
def ComputerUpdate(comput):
|
||||
global computer
|
||||
|
||||
computer = comput
|
||||
|
||||
|
||||
|
||||
# Client to export buttons actions from LPD8 or bhoreal
|
||||
|
||||
def SendOSC(ip,port,oscaddress,oscargs=''):
|
||||
|
||||
oscmsg = OSCMessage()
|
||||
oscmsg.setAddress(oscaddress)
|
||||
oscmsg.append(oscargs)
|
||||
|
||||
osclient = OSCClient()
|
||||
osclient.connect((ip, port))
|
||||
|
||||
print("sending OSC message : ", oscmsg, "to", ip, ":", port)
|
||||
|
||||
try:
|
||||
osclient.sendto(oscmsg, (ip, port))
|
||||
oscmsg.clearData()
|
||||
return True
|
||||
except:
|
||||
print ('Connection to', ip, 'refused : died ?')
|
||||
return False
|
||||
|
||||
|
||||
#
|
||||
# Events from LPD8 buttons
|
||||
#
|
||||
|
||||
# Process events coming from LPD8 in a separate thread.
|
||||
|
||||
def MidinProcess(LPD8queue):
|
||||
global computer
|
||||
|
||||
|
||||
while True:
|
||||
LPD8queue_get = LPD8queue.get
|
||||
msg = LPD8queue_get()
|
||||
#print (msg)
|
||||
|
||||
# Note
|
||||
if msg[0]==NOTE_ON:
|
||||
|
||||
# note mode
|
||||
ModeNote(msg[1], msg[2], mididest)
|
||||
|
||||
'''
|
||||
# ModeOS
|
||||
if msg[2] > 0:
|
||||
ModeOS(msg[0])
|
||||
'''
|
||||
|
||||
|
||||
# Program Change button selected : change destination computer
|
||||
if msg[0]==PROGRAM_CHANGE:
|
||||
|
||||
print("Program change : ", str(msg[1]))
|
||||
# Change destination computer mode
|
||||
print("Destination computer",int(msg[1]))
|
||||
computer = int(msg[1])
|
||||
|
||||
|
||||
# CC rotary -> midi CC.
|
||||
if msg[0] == CONTROLLER_CHANGE:
|
||||
|
||||
print("CC :", msg[1], msg[2])
|
||||
|
||||
if computer == 0 or computer == 1:
|
||||
cc(int(msg[1]), int(msg[2]))
|
||||
|
||||
else:
|
||||
SendOSC(computerIP[computer-1], maxwellatorPort, '/cc', [int(msg[1]), int(msg[2])])
|
||||
|
||||
#
|
||||
# Notes = midi notes
|
||||
#
|
||||
|
||||
def ModeNote(note, velocity, mididest):
|
||||
|
||||
|
||||
print('computer',computer)
|
||||
|
||||
# todo : decide whether its 0 or 1 !!!
|
||||
if computer == 0 or computer == 1:
|
||||
midi3.NoteOn(arg, velocity, mididest)
|
||||
|
||||
|
||||
if velocity == 127:
|
||||
pass
|
||||
#print ('NoteON', BhorNoteXY(x,y),notename , "velocity", velocity )
|
||||
#Disp(notename)
|
||||
else:
|
||||
midi3.NoteOff(arg)
|
||||
#print ('NoteOFF', BhorNoteXY(x,y),notename , "velocity", velocity )
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Notes = OS Macros
|
||||
#
|
||||
|
||||
def ModeOS(arg):
|
||||
|
||||
|
||||
macroname = 'n'+arg
|
||||
macronumber = findMacros(macroname,'OS')
|
||||
if macronumber != -1:
|
||||
|
||||
eval(macros['OS'][macronumber]["code"])
|
||||
else:
|
||||
print("no Code yet")
|
||||
|
||||
|
||||
|
||||
LPD8queue = Queue()
|
||||
|
||||
|
||||
# LPD8 Mini call back : new msg forwarded to LPD8 queue
|
||||
class LPD8AddQueue(object):
|
||||
def __init__(self, port):
|
||||
self.port = port
|
||||
#print("LPD8AddQueue", self.port)
|
||||
self._wallclock = time.time()
|
||||
|
||||
def __call__(self, event, data=None):
|
||||
message, deltatime = event
|
||||
self._wallclock += deltatime
|
||||
print()
|
||||
print("[%s] @%0.6f %r" % (self.port, self._wallclock, message))
|
||||
LPD8queue.put(message)
|
||||
|
||||
#
|
||||
# Modes :
|
||||
#
|
||||
|
||||
# Load Matrix only macros (for the moment) in macros.json
|
||||
def LoadMacros():
|
||||
global macros
|
||||
|
||||
print()
|
||||
print("Loading LPD8 Macros...")
|
||||
f=open("macros.json","r")
|
||||
s = f.read()
|
||||
macros = json.loads(s)
|
||||
print(len(macros['OS']),"Macros")
|
||||
print("Loaded.")
|
||||
|
||||
|
||||
# return macroname number for given type 'OS', 'Maxwell'
|
||||
def findMacros(macroname,macrotype):
|
||||
|
||||
#print("searching", macroname,'...')
|
||||
position = -1
|
||||
for counter in range(len(macros[macrotype])):
|
||||
#print (counter,macros[macrotype][counter]['name'],macros[macrotype][counter]['code'])
|
||||
if macroname == macros[macrotype][counter]['name']:
|
||||
#print(macroname, "is ", counter)
|
||||
position = counter
|
||||
return position
|
||||
|
||||
|
||||
|
||||
# Not assigned buttons
|
||||
def DefaultMacro(arg):
|
||||
|
||||
print ("DefaultMacro", arg)
|
||||
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Default macros
|
||||
#
|
||||
|
||||
|
||||
LPD8macros = {
|
||||
|
||||
"n1": {"command": DefaultMacro, "default": 1},
|
||||
"n2": {"command": DefaultMacro, "default": 2},
|
||||
"n3": {"command": DefaultMacro, "default": 3},
|
||||
"n4": {"command": DefaultMacro, "default": 4},
|
||||
"n5": {"command": DefaultMacro, "default": 5},
|
||||
"n6": {"command": DefaultMacro, "default": 6},
|
||||
"n7": {"command": DefaultMacro, "default": 7},
|
||||
"n8": {"command": DefaultMacro, "default": 8}
|
||||
}
|
||||
|
||||
|
||||
def Run(macroname, macroargs=''):
|
||||
|
||||
doit = LPD8macros[macroname]["command"]
|
||||
if macroargs=='':
|
||||
macroargs = LPD8macros[macroname]["default"]
|
||||
#print("Running", doit, "with args", macroargs )
|
||||
doit(macroargs)
|
||||
|
||||
LoadMacros()
|
||||
2873
libs/OSC3.py
Executable file
2873
libs/OSC3.py
Executable file
File diff suppressed because it is too large
Load diff
0
libs/__init__.py
Normal file
0
libs/__init__.py
Normal file
BIN
libs/__init__.pyc
Normal file
BIN
libs/__init__.pyc
Normal file
Binary file not shown.
364
libs/artnet.py
Normal file
364
libs/artnet.py
Normal file
|
|
@ -0,0 +1,364 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
|
||||
"""
|
||||
|
||||
ArtNet/DMX Handler :
|
||||
v0.7.0
|
||||
|
||||
|
||||
by Sam Neurohack
|
||||
from /team/laser
|
||||
|
||||
Artnet receving code from https://github.com/kongr45gpen/simply-artnet
|
||||
Laser selection
|
||||
one universe / laser
|
||||
|
||||
Plugin selection
|
||||
banck change/scene/
|
||||
|
||||
"""
|
||||
|
||||
import random
|
||||
import pysimpledmx
|
||||
from serial.tools import list_ports
|
||||
import serial,time
|
||||
from threading import Thread
|
||||
import socket
|
||||
import struct
|
||||
import types
|
||||
from sys import platform, version
|
||||
import sys
|
||||
import argparse, traceback
|
||||
import os
|
||||
|
||||
is_py2 = version[0] == '2'
|
||||
if is_py2:
|
||||
from OSC import OSCServer, OSCClient, OSCMessage
|
||||
else:
|
||||
from OSC3 import OSCServer, OSCClient, OSCMessage
|
||||
|
||||
ljpath = r'%s' % os.getcwd().replace('\\','/')
|
||||
|
||||
# import from shell
|
||||
|
||||
#sys.path.append('../../libs')
|
||||
|
||||
#import from LJ
|
||||
sys.path.append(ljpath +'/libs/')
|
||||
|
||||
import lj23 as lj
|
||||
|
||||
|
||||
#
|
||||
# Init
|
||||
#
|
||||
|
||||
OSCinPort = 8032
|
||||
|
||||
|
||||
sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
|
||||
sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
|
||||
sock.bind(('',6454))
|
||||
|
||||
dmxeq = {}
|
||||
dmxstates = []
|
||||
dmxinit = False
|
||||
universe = []
|
||||
|
||||
|
||||
for i in range(1,514):
|
||||
dmxstates.append(-1)
|
||||
|
||||
|
||||
print ("")
|
||||
print ("Artnet v0.1")
|
||||
print ("Arguments parsing if needed...")
|
||||
argsparser = argparse.ArgumentParser(description="Artnet & DMX for LJ")
|
||||
argsparser.add_argument("-u","--universe",help="Universe, not implemented (0 by default)",type=int)
|
||||
argsparser.add_argument("-s","--subuniverse",help="Subniverse, not implemented (0 by default)",type=int)
|
||||
argsparser.add_argument("-r","--redisIP",help="IP of the Redis server used by LJ (127.0.0.1 by default) ",type=str)
|
||||
argsparser.add_argument("-m","--myIP",help="Local IP (127.0.0.1 by default) ",type=str)
|
||||
argsparser.add_argument("-v","--verbose",help="Verbosity level (0 by default)",type=int)
|
||||
|
||||
args = argsparser.parse_args()
|
||||
|
||||
|
||||
# Universe
|
||||
if args.universe:
|
||||
universenb = args.universe
|
||||
else:
|
||||
universenb = 0
|
||||
|
||||
# Universe
|
||||
if args.subuniverse:
|
||||
subuniversenb = args.subuniverse
|
||||
else:
|
||||
subuniversenb = 0
|
||||
|
||||
# Debug level
|
||||
if args.verbose:
|
||||
debug = args.verbose
|
||||
else:
|
||||
debug = 0
|
||||
|
||||
# Redis Computer IP
|
||||
if args.redisIP != None:
|
||||
redisIP = args.redisIP
|
||||
else:
|
||||
redisIP = '127.0.0.1'
|
||||
|
||||
# myIP
|
||||
if args.myIP != None:
|
||||
myIP = args.myIP
|
||||
else:
|
||||
myIP = '127.0.0.1'
|
||||
|
||||
r = lj.Config(redisIP, 255, "artnet")
|
||||
|
||||
lj.WebStatus("Artnet init...")
|
||||
|
||||
def lhex(h):
|
||||
return ':'.join(x.encode('hex') for x in h)
|
||||
|
||||
|
||||
def senddmx0():
|
||||
for channel in range (1,512):
|
||||
senddmx(channel,0)
|
||||
|
||||
def senddmx(channel, value):
|
||||
|
||||
print("Setting channel %d to %d" % (i,value))
|
||||
#mydmx.setChannel((channel + 1 ), value, autorender=True)
|
||||
# calling render() is better more reliable to actually sending data
|
||||
# Some strange bug. Need to add one to required dmx channel is done automatically
|
||||
mydmx.setChannel((channel ), value)
|
||||
mydmx.render()
|
||||
print("Sending DMX Channel : ", str(channel), " value : ", str(value))
|
||||
|
||||
def updateDmxValue(channel, val):
|
||||
|
||||
#
|
||||
if dmxstates[channel] == -1:
|
||||
dmxstates[channel] = val
|
||||
|
||||
# DMX UPDATE!!! WOW!!!
|
||||
if dmxstates[channel] != val:
|
||||
dmxstates[channel] = val
|
||||
print("updating channel", channel, "with ", val )
|
||||
if mydmx != False:
|
||||
senddmx(channel, ord(val))
|
||||
|
||||
|
||||
# Search for DMX devices
|
||||
|
||||
#ljnozoids.WebStatus("Available serial devices")
|
||||
|
||||
print("")
|
||||
print("Available serial devices...")
|
||||
ports = list(list_ports.comports())
|
||||
|
||||
portnumber = 0
|
||||
|
||||
# Get all serial ports names
|
||||
for i, p in enumerate(ports):
|
||||
|
||||
print(i, ":", p)
|
||||
|
||||
if p[0]== "/dev/ttyUSB0":
|
||||
portname[portnumber] = p[0]
|
||||
portnumber += 1
|
||||
|
||||
|
||||
if platform == 'darwin' and p[1].find("DMX USB PRO") != -1:
|
||||
portname[portnumber] = p[0]
|
||||
portnumber += 1
|
||||
|
||||
|
||||
# ljnozoids.WebStatus("Found " + str(portnumber) +" Nozoids.")
|
||||
|
||||
print("Found", portnumber, "DMX devices")
|
||||
|
||||
|
||||
if portnumber > 0:
|
||||
|
||||
print("with serial names", portname)
|
||||
mydmx = pysimpledmx.DMXConnection(gstt.serdmx[0])
|
||||
senddmx0()
|
||||
time.sleep(1)
|
||||
|
||||
# Send a random value to channel 1
|
||||
vrand=random.randint(0,255)
|
||||
senddmx(1,vrand)
|
||||
|
||||
else:
|
||||
mydmx = False
|
||||
print("No DMX found, Art-Net receiver only.")
|
||||
|
||||
|
||||
#
|
||||
# OSC
|
||||
#
|
||||
|
||||
oscserver = OSCServer( (myIP, OSCinPort) )
|
||||
oscserver.timeout = 0
|
||||
#oscrun = True
|
||||
|
||||
# this method of reporting timeouts only works by convention
|
||||
# that before calling handle_request() field .timed_out is
|
||||
# set to False
|
||||
def handle_timeout(self):
|
||||
self.timed_out = True
|
||||
|
||||
# funny python's way to add a method to an instance of a class
|
||||
oscserver.handle_timeout = types.MethodType(handle_timeout, oscserver)
|
||||
|
||||
|
||||
# default handler
|
||||
def OSChandler(path, tags, args, source):
|
||||
|
||||
oscaddress = ''.join(path.split("/"))
|
||||
print("Default OSC Handler : msg from Client : " + str(source[0]),)
|
||||
print("OSC address", path, "with",)
|
||||
if len(args) > 0:
|
||||
print("args", args)
|
||||
else:
|
||||
print("noargs")
|
||||
#oscIPout = str(source[0])
|
||||
#osclient.connect((oscIPout, oscPORTout))
|
||||
|
||||
|
||||
# RAW OSC Frame available ?
|
||||
def OSCframe():
|
||||
|
||||
# clear timed_out flag
|
||||
print ("oscframe")
|
||||
oscserver.timed_out = False
|
||||
# handle all pending requests then return
|
||||
while not oscserver.timed_out:
|
||||
oscserver.handle_request()
|
||||
|
||||
|
||||
# Stop osc server
|
||||
def OSCstop():
|
||||
|
||||
oscrun = False
|
||||
oscserver.close()
|
||||
|
||||
|
||||
# /sendmx channel value
|
||||
def OSCsendmx(path, tags, args, source):
|
||||
|
||||
channel = args[0]
|
||||
val = args[1]
|
||||
updateDmxValue(channel, val)
|
||||
|
||||
|
||||
lj.addOSCdefaults(oscserver)
|
||||
lj.SendLJ("/pong", "artnet")
|
||||
lj.WebStatus("Artnet Running...")
|
||||
|
||||
oscserver.addMsgHandler( "/sendmx", OSCsendmx )
|
||||
|
||||
#
|
||||
# Running...
|
||||
#
|
||||
|
||||
|
||||
print ("Starting, use Ctrl+C to stop")
|
||||
print (lj.oscrun)
|
||||
|
||||
try:
|
||||
|
||||
while lj.oscrun:
|
||||
|
||||
data = sock.recv(10240)
|
||||
if len(data) < 20:
|
||||
continue
|
||||
|
||||
if data[0:7] != "Art-Net" or data[7] != "\0":
|
||||
print("artnet package")
|
||||
#lj.WebStatus("Artnet package")
|
||||
continue
|
||||
OSCframe()
|
||||
|
||||
if ord(data[8]) != 0x00 or ord(data[9]) != 0x50:
|
||||
print("OpDmx")
|
||||
continue
|
||||
|
||||
print ("oscrun", lj.oscrun)
|
||||
protverhi = ord(data[10])
|
||||
protverlo = ord(data[11])
|
||||
sequence = ord(data[12])
|
||||
physical = ord(data[13])
|
||||
subuni = ord(data[14])
|
||||
net = ord(data[15])
|
||||
lengthhi = ord(data[16])
|
||||
length = ord(data[17])
|
||||
dmx = data[18:]
|
||||
|
||||
print (data[0:7], "version :",lhex(data[10])+lhex(data[11]), "sequence :", sequence, "physical", physical, "subuni",subuni,"net", net)
|
||||
|
||||
for i in xrange(0,510):
|
||||
updateDmxValue(i+1,dmx[i])
|
||||
|
||||
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
|
||||
finally:
|
||||
|
||||
lj.ClosePlugin()
|
||||
sock.close()
|
||||
OSCstop()
|
||||
'''
|
||||
import sys, socket, math, time
|
||||
from ctypes import *
|
||||
|
||||
class Artnet:
|
||||
class ArtNetDMXOut(LittleEndianStructure):
|
||||
PORT = 0x1936
|
||||
_fields_ = [("id", c_char * 8),
|
||||
("opcode", c_ushort),
|
||||
("protverh", c_ubyte),
|
||||
("protver", c_ubyte),
|
||||
("sequence", c_ubyte),
|
||||
("physical", c_ubyte),
|
||||
("universe", c_ushort),
|
||||
("lengthhi", c_ubyte),
|
||||
("length", c_ubyte),
|
||||
("payload", c_ubyte * 512)]
|
||||
|
||||
def __init__(self):
|
||||
self.id = b"Art-Net"
|
||||
self.opcode = 0x5000
|
||||
self.protver = 14
|
||||
self.universe = 0
|
||||
self.lengthhi = 2
|
||||
|
||||
def __init__(self):
|
||||
self.artnet = Artnet.ArtNetDMXOut()
|
||||
self.S = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
|
||||
for i in range(512):
|
||||
self.artnet.payload[i] = 0
|
||||
|
||||
def send(self,data,IP,port):
|
||||
# send(送るデータ,IPアドレス,ポート番号)
|
||||
self.artnet.universe = port
|
||||
for i in range(512):
|
||||
if(i < len(data)):
|
||||
self.artnet.payload[i] = data[i]
|
||||
else:
|
||||
break
|
||||
self.S.sendto(self.artnet,(IP,Artnet.ArtNetDMXOut.PORT))
|
||||
|
||||
if __name__ == '__main__':
|
||||
artnet = Artnet()
|
||||
data = [0] * 512
|
||||
for i in range(150):
|
||||
data[i*3+0] = 0
|
||||
data[i*3+1] = 0
|
||||
data[i*3+2] = 0
|
||||
artnet.send(data,"133.15.42.111",5)
|
||||
'''
|
||||
292
libs/audio.py
Executable file
292
libs/audio.py
Executable file
|
|
@ -0,0 +1,292 @@
|
|||
|
||||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Audio Spectrum analyser
|
||||
v0.7.0
|
||||
|
||||
- summed given fft in n bands, but re normalized between 0 - 70?
|
||||
- Peaks L and R
|
||||
- amplitude for given target frequency and PEAK frequency
|
||||
- "music note" to given frequency
|
||||
- Real FFT, Imaginary FFT, Real + imaginary FFT
|
||||
- threshold detection
|
||||
|
||||
todo :
|
||||
|
||||
|
||||
by Sam Neurohack
|
||||
from /team/laser
|
||||
|
||||
for python 2 & 3
|
||||
|
||||
Stereo : CHANNELS = 2
|
||||
mono : CHANNELS = 1
|
||||
|
||||
"""
|
||||
|
||||
|
||||
import numpy as np
|
||||
import pyaudio
|
||||
from math import log, pow
|
||||
|
||||
#import matplotlib.pyplot as plt
|
||||
|
||||
#from scipy.interpolate import Akima1DInterpolator
|
||||
#import matplotlib.pyplot as plt
|
||||
|
||||
DEVICE = 3
|
||||
CHANNELS = 2
|
||||
START = 0
|
||||
RATE = 44100 # time resolution of the recording device (Hz)
|
||||
CHUNK = 4096 # number of data points to read at a time. Almost 10 update/second
|
||||
TARGET = 2100 # show only this one frequency
|
||||
|
||||
|
||||
A4 = 440
|
||||
C0 = A4*pow(2, -4.75)
|
||||
name = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"]
|
||||
data = []
|
||||
|
||||
p = pyaudio.PyAudio() # start the PyAudio class
|
||||
stream = p.open(format = pyaudio.paInt16, channels = CHANNELS, input_device_index = DEVICE, rate=RATE, input=True,
|
||||
frames_per_buffer=CHUNK) #uses default input device
|
||||
|
||||
|
||||
#
|
||||
# Audio devices & audiogen functions
|
||||
#
|
||||
|
||||
def list_devices():
|
||||
# List all audio input devices
|
||||
p = pyaudio.PyAudio()
|
||||
i = 0
|
||||
n = p.get_device_count()
|
||||
print (n,"devices found")
|
||||
while i < n:
|
||||
dev = p.get_device_info_by_index(i)
|
||||
if dev['maxInputChannels'] > 0:
|
||||
print (str(i)+'. '+dev['name'])
|
||||
i += 1
|
||||
|
||||
|
||||
def valid_input_devices(self):
|
||||
"""
|
||||
See which devices can be opened for microphone input.
|
||||
call this when no PyAudio object is loaded.
|
||||
"""
|
||||
mics=[]
|
||||
for device in range(self.p.get_device_count()):
|
||||
if self.valid_test(device):
|
||||
mics.append(device)
|
||||
if len(mics)==0:
|
||||
print("no microphone devices found!")
|
||||
else:
|
||||
print("found %d microphone devices: %s"%(len(mics),mics))
|
||||
return mics
|
||||
|
||||
|
||||
|
||||
def loop():
|
||||
try:
|
||||
|
||||
#plt.ion()
|
||||
|
||||
#plt.axis([x[0], x[-1], -0.1, max_f])
|
||||
fftbands = [0,1,2,3,4,5,6,7,8,9]
|
||||
plt.xlabel('frequencies')
|
||||
plt.ylabel('amplitude')
|
||||
data = audioinput()
|
||||
drawfreq, fft = allfft(data)
|
||||
#lines = plt.plot(drawfreq, fft)
|
||||
|
||||
#plt.axis([drawfreq[0], drawfreq[-1], 0, np.max(fft)])
|
||||
#plt.plot(drawfreq, fft)
|
||||
#plt.show()
|
||||
#line, = plt.plot(fftbands, levels(fft,10))
|
||||
line, = plt.plot(drawfreq, fft)
|
||||
#while True :
|
||||
for i in range(50):
|
||||
|
||||
data = audioinput()
|
||||
|
||||
# smooth the FFT by windowing data
|
||||
#data = data * np.hanning(len(data))
|
||||
|
||||
# conversion to -1 to +1
|
||||
# normed_samples = (data / float(np.iinfo(np.int16).max))
|
||||
|
||||
# Left is channel 0
|
||||
dataL = data[0::2]
|
||||
# Right is channel 1
|
||||
dataR = data[1::2]
|
||||
|
||||
# Peaks L and R
|
||||
peakL = np.abs(np.max(dataL)-np.min(dataL))/CHUNK
|
||||
peakR = np.abs(np.max(dataR)-np.min(dataR))/CHUNK
|
||||
# print(peakL, peakR)
|
||||
|
||||
drawfreq, fft = allfft(data)
|
||||
#fft, fftr, ffti, fftb, drawfreq = allfft(data)
|
||||
|
||||
#line.set_ydata(levels(fft,10))
|
||||
line.set_ydata(fft)
|
||||
plt.pause(0.01)
|
||||
#print(drawfreq)
|
||||
#print(fft)
|
||||
#print (levels(fft,10))
|
||||
|
||||
#line.set_ydata(fft)
|
||||
#plt.pause(0.01) # pause avec duree en secondes
|
||||
|
||||
# lines = plt.plot(x, y)
|
||||
#lines[0].set_ydata(fft)
|
||||
#plt.legend(['s=%4.2f' % s])
|
||||
#plt.draw()
|
||||
#plt.show()
|
||||
|
||||
|
||||
|
||||
'''
|
||||
targetpower,freqPeak = basicfft(audioinput(stream))
|
||||
print("amplitude", targetpower, "@", TARGET, "Hz")
|
||||
if freqPeak > 0.0:
|
||||
print("peak frequency: %d Hz"%freqPeak, pitch(freqPeak))
|
||||
'''
|
||||
plt.show()
|
||||
|
||||
except KeyboardInterrupt:
|
||||
stream.stop_stream()
|
||||
stream.close()
|
||||
p.terminate()
|
||||
|
||||
print("End...")
|
||||
|
||||
# Close properly
|
||||
def close():
|
||||
stream.stop_stream()
|
||||
stream.close()
|
||||
p.terminate()
|
||||
|
||||
|
||||
# Return "music note" to given frequency
|
||||
def pitch(freq):
|
||||
h = round(12*(log(freq/C0)/log(2)))
|
||||
octave = h // 12
|
||||
n = h % 12
|
||||
return name[n] + str(octave)
|
||||
|
||||
|
||||
# Return summed given fft in n bands, but re normalized 0 - 70
|
||||
def levels(fourier, bands):
|
||||
|
||||
size = int(len(fourier))
|
||||
levels = [0.0] * bands
|
||||
|
||||
# Add up for n bands
|
||||
# remove normalizer if you want raw added data in all bands
|
||||
normalizer = size/bands
|
||||
#print (size,bands,size/bands)
|
||||
levels = [sum(fourier[I:int(I+size/bands)])/normalizer for I in range(0, size, int(size/bands))][:bands]
|
||||
|
||||
for band in range(bands):
|
||||
if levels[band] == np.NINF:
|
||||
levels[band] =0
|
||||
|
||||
|
||||
return levels
|
||||
|
||||
|
||||
# read CHUNK size in audio buffer
|
||||
def audioinput():
|
||||
|
||||
# When reading from our 16-bit stereo stream, we receive 4 characters (0-255) per
|
||||
# sample. To get them in a more convenient form, numpy provides
|
||||
# fromstring() which will for each 16 bits convert it into a nicer form and
|
||||
# turn the string into an array.
|
||||
return np.fromstring(stream.read(CHUNK),dtype=np.int16)
|
||||
|
||||
# power for given TARGET frequency and PEAK frequency
|
||||
# do fft first. No conversion in 'powers'
|
||||
def basicfft(data):
|
||||
|
||||
#data = data * np.hanning(len(data)) # smooth the FFT by windowing data
|
||||
fft = abs(np.fft.fft(data).real)
|
||||
#fft = 10*np.log10(fft)
|
||||
fft = fft[:int(len(fft)/2)] # first half of fft
|
||||
|
||||
freq = np.fft.fftfreq(CHUNK,1.0/RATE)
|
||||
freq = freq[:int(len(freq)/2)] # first half of FFTfreq
|
||||
|
||||
assert freq[-1]>TARGET, "ERROR: increase chunk size"
|
||||
|
||||
# return power for given TARGET frequency and peak frequency
|
||||
return fft[np.where(freq > TARGET)[0][0]], freq[np.where(fft == np.max(fft))[0][0]]+1
|
||||
|
||||
|
||||
# todo : Try if data = 1024 ?
|
||||
# in "power' (0-70?) get Real FFT, Imaginary FFT, Real + imaginary FFT
|
||||
def allfft(data):
|
||||
|
||||
#print ("allfft", len(data))
|
||||
fft = np.fft.fft(data)
|
||||
#print("fft",len(fft))
|
||||
fftr = 10*np.log10(abs(fft.real))[:int(len(data)/2)]
|
||||
ffti = 10*np.log10(abs(fft.imag))[:int(len(data)/2)]
|
||||
fftb = 10*np.log10(np.sqrt(fft.imag**2+fft.real**2))[:int(len(data)/2)]
|
||||
#print("fftb",len(fftb))
|
||||
drawfreq = np.fft.fftfreq(np.arange(len(data)).shape[-1])[:int(len(data)/2)]
|
||||
drawfreq = drawfreq*RATE/1000 #make the frequency scale
|
||||
#return fft, fftr, ffti, fftb, drawfreq
|
||||
return drawfreq, fftb
|
||||
|
||||
# Draw Original datas
|
||||
# X : np.arange(len(data))/float(rate)*1000
|
||||
# Y : data
|
||||
|
||||
# Draw real FFT
|
||||
# X : drawfreq
|
||||
# Y : fftr
|
||||
|
||||
# Draw imaginary
|
||||
# X : drawfreq
|
||||
# Y : ffti
|
||||
|
||||
# Draw Real + imaginary
|
||||
# X : drawfreq
|
||||
# Y : fftb
|
||||
|
||||
|
||||
# True if any value in the data is greater than threshold and after a certain delay
|
||||
def ding(right,threshold):
|
||||
if max(right) > threshold and time.time() - last_run > min_delay:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
last_run = time.time()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
|
||||
loop()
|
||||
'''
|
||||
x = np.linspace(0, 3, 100)
|
||||
k = 2*np.pi
|
||||
w = 2*np.pi
|
||||
dt = 0.01
|
||||
|
||||
t = 0
|
||||
for i in range(50):
|
||||
y = np.cos(k*x - w*t)
|
||||
if i == 0:
|
||||
line, = plt.plot(x, y)
|
||||
else:
|
||||
line.set_ydata(y)
|
||||
plt.pause(0.01) # pause avec duree en secondes
|
||||
t = t + dt
|
||||
|
||||
plt.show()
|
||||
'''
|
||||
|
||||
271
libs/bhoreal.py
Normal file
271
libs/bhoreal.py
Normal file
|
|
@ -0,0 +1,271 @@
|
|||
# coding=UTF-8
|
||||
"""
|
||||
Bhoreal
|
||||
v0.7.0
|
||||
Bhoreal Led matrix Handler
|
||||
|
||||
Start a dedicated thread to handle incoming events from launchpad.
|
||||
|
||||
Cls()
|
||||
AllColor(color)
|
||||
StarttBhoreal(port) : Start animation
|
||||
|
||||
Led Matrix can be access with X and Y coordinates and as midi note (0-63)
|
||||
|
||||
NoteOn(note,color)
|
||||
NoteOff(note)
|
||||
NoteOnXY(x,y,color):
|
||||
NoteOffXY(x,y):
|
||||
NoteXY(x,y):
|
||||
|
||||
gstt.BhorLeds[] array stores matrix current state
|
||||
|
||||
by Sam Neurohack
|
||||
from /team/laser
|
||||
|
||||
"""
|
||||
|
||||
import time
|
||||
from rtmidi.midiconstants import (CHANNEL_PRESSURE, CONTROLLER_CHANGE, NOTE_ON, NOTE_OFF,
|
||||
PITCH_BEND, POLY_PRESSURE, PROGRAM_CHANGE)
|
||||
import gstt, midi3
|
||||
import sys
|
||||
|
||||
gstt.BhorLeds = [0]*65
|
||||
|
||||
|
||||
Here = -1
|
||||
from queue import Queue
|
||||
|
||||
def NoteOn(note,color):
|
||||
|
||||
print ("bhoreal noteon", note, color)
|
||||
msg = [NOTE_ON, note, color]
|
||||
midi3.send(msg,"Bhoreal")
|
||||
gstt.BhorLeds[note]=color
|
||||
|
||||
def NoteOff(note):
|
||||
msg = [NOTE_OFF, note, 0]
|
||||
midi3.send(msg,"Bhoreal")
|
||||
gstt.BhorLeds[note]=0
|
||||
|
||||
|
||||
def NoteOnXY(x,y,color):
|
||||
#print x,y
|
||||
msg = [NOTE_ON, NoteXY(x,y), color]
|
||||
midi3.send(msg,"Bhoreal")
|
||||
gstt.BhorLeds[NoteXY(x,y)]=color
|
||||
|
||||
def NoteOffXY(x,y):
|
||||
msg = [NOTE_OFF, NoteXY(x,y), 0]
|
||||
midi3.send(msg,"Bhoreal")
|
||||
gstt.BhorLeds[NoteXY(x,y)]=0
|
||||
|
||||
|
||||
# Leds position are humans numbers 1-8. So -1 for pythonic array position 0-7
|
||||
def NoteXY(x,y):
|
||||
note = (x -1)+ (y-1) * 8
|
||||
return note
|
||||
|
||||
def Index(note):
|
||||
y=note/8
|
||||
x=note%8
|
||||
#print "Note : ",note
|
||||
#print "BhorIndex : ", x+1,y+1
|
||||
return int(x+1),int(y+1)
|
||||
|
||||
#
|
||||
# Bhoreal Start anim
|
||||
#
|
||||
|
||||
# AllColor for bhoreal on given port
|
||||
|
||||
def AllColor(port,color):
|
||||
for led in range(0,64,1):
|
||||
msg = [NOTE_ON, led, color]
|
||||
midi3.send(msg,"Bhoreal")
|
||||
|
||||
# Cls for bhoreal on given port
|
||||
|
||||
def Cls(port):
|
||||
for led in range(0,64,1):
|
||||
msg = [NOTE_OFF, led, 0]
|
||||
midi3.send(msg,"Bhoreal")
|
||||
|
||||
|
||||
|
||||
def StartBhoreal(port):
|
||||
|
||||
Cls(port)
|
||||
time.sleep(0.2)
|
||||
for color in range(0,126,1):
|
||||
AllColor(port,color)
|
||||
time.sleep(0.02)
|
||||
time.sleep(0.2)
|
||||
Cls(port)
|
||||
|
||||
|
||||
|
||||
def UpdateLine(line,newval):
|
||||
if gstt.BhorealHere != -1:
|
||||
for led in range(8):
|
||||
NoteOffXY(led,line)
|
||||
|
||||
NoteOnXY(newval,line,64)
|
||||
|
||||
|
||||
|
||||
# Update Laser
|
||||
def Noteon_Update(note):
|
||||
|
||||
'''
|
||||
# forward new instruction ?
|
||||
if gstt.MyLaser != gstt.Laser:
|
||||
doit = jumplaser.get(gstt.Laser)
|
||||
doit("/noteon",note)
|
||||
'''
|
||||
#
|
||||
|
||||
|
||||
if note < 8:
|
||||
pass
|
||||
|
||||
#
|
||||
if note > 7 and note < 16:
|
||||
pass
|
||||
|
||||
#
|
||||
if note > 15 and note < 24:
|
||||
pass
|
||||
|
||||
# change current simulator PL
|
||||
if note > 23 and note < 32:
|
||||
pass
|
||||
|
||||
if note == 57 or note == 58:
|
||||
pass
|
||||
|
||||
if note > 58:
|
||||
pass
|
||||
|
||||
'''
|
||||
# todo 57 Color mode : Rainbow
|
||||
# 58 Color mode : RGB
|
||||
|
||||
# Notes for Curve : 0-7
|
||||
def UpdateCurve():
|
||||
print ("New Curve :", gstt.Curve)
|
||||
if gstt.BhorealHere != -1:
|
||||
for led in range(0,8):
|
||||
NoteOff(led)
|
||||
NoteOn(gstt.Curve,20)
|
||||
|
||||
# Notes for set : 8-15
|
||||
def UpdateSet():
|
||||
print ("New Set :", gstt.Set)
|
||||
if gstt.BhorealHere != -1:
|
||||
for led in range(9,17):
|
||||
NoteOff(led)
|
||||
NoteOn(gstt.Set+8,10)
|
||||
|
||||
# Note for current laser : 16-23
|
||||
def UpdateLaser():
|
||||
print ("New Laser :", gstt.Laser)
|
||||
if gstt.BhorealHere != -1:
|
||||
for led in range(16,24):
|
||||
NoteOff(led)
|
||||
NoteOn(gstt.Laser+16,30)
|
||||
|
||||
# Note for PL displayed in pygame window : 24-31
|
||||
def UpdateSimu():
|
||||
print ("New simuPL :", gstt.simuPL)
|
||||
if gstt.BhorealHere != -1:
|
||||
for led in range(24,32):
|
||||
NoteOff(led)
|
||||
NoteOn(gstt.simuPL+24,40)
|
||||
'''
|
||||
|
||||
#
|
||||
# Events from Bhoreal handling
|
||||
#
|
||||
|
||||
# Process events coming from Bhoreal in a separate thread.
|
||||
def MidinProcess(bhorqueue):
|
||||
|
||||
#print()
|
||||
#print("bhoreal midi in process started with queue", bhorqueue)
|
||||
#print()
|
||||
bhorqueue_get = bhorqueue.get
|
||||
while True:
|
||||
|
||||
msg = bhorqueue_get()
|
||||
|
||||
# Bhoreal Led pressed
|
||||
print ("Bhoreal Matrix : ", str(msg[1]), gstt.BhorLeds[msg[1]])
|
||||
|
||||
if msg[0] == NOTE_ON and msg[2] == 64:
|
||||
# led
|
||||
NoteOn(msg[1],64)
|
||||
|
||||
# Bhoreal Led depressed
|
||||
elif msg[0] == NOTE_ON and msg[2] == 0:
|
||||
NoteOn(msg[1],0)
|
||||
|
||||
'''
|
||||
|
||||
print "Bhoreal Matrix : ", str(msg[1]), str(gstt.BhorLeds[msg[1]])
|
||||
|
||||
if msg[1]< 8:
|
||||
gstt.Curve = msg[1]
|
||||
UpdateCurve()
|
||||
|
||||
if msg[1]> 7 and msg[1] < 16:
|
||||
gstt.Set = msg[1]-8
|
||||
UpdateSet()
|
||||
|
||||
if msg[1]> 15 and msg[1] < 24:
|
||||
gstt.Laser = msg[1]-16
|
||||
UpdateLaser()
|
||||
|
||||
if msg[1]> 23 and msg[1] < 31:
|
||||
gstt.simuPL = msg[1]-24
|
||||
UpdateSimu()
|
||||
|
||||
#Bhoreal send back note on and off to light up the led.
|
||||
if msg[1]> 56:
|
||||
if gstt.BhorLeds[msg[1]] < 115:
|
||||
gstt.BhorLeds[msg[1]] += 10
|
||||
#midi3.NoteOn(msg[1],gstt.BhorLeds[msg[1]])
|
||||
|
||||
#time.sleep(0.1)
|
||||
#midi3.NoteOff(msg[1])
|
||||
'''
|
||||
bhorqueue = Queue()
|
||||
|
||||
|
||||
# New Bhoreal call back : new msg forwarded to Bhoreal queue
|
||||
class AddQueue(object):
|
||||
def __init__(self, portname):
|
||||
self.portname = portname
|
||||
self._wallclock = time.time()
|
||||
|
||||
|
||||
def __call__(self, event, data=None):
|
||||
message, deltatime = event
|
||||
self._wallclock += deltatime
|
||||
print("[%s] @%0.6f %r" % (self.portname, self._wallclock, message))
|
||||
bhorqueue.put(message)
|
||||
|
||||
'''
|
||||
# Old Bhoreal call back : new msg forwarded to Bhoreal queue
|
||||
class AddQueue(object):
|
||||
def __init__(self, port):
|
||||
self.port = port
|
||||
self._wallclock = time.time()
|
||||
|
||||
def __call__(self, event, data=None):
|
||||
message, deltatime = event
|
||||
self._wallclock += deltatime
|
||||
print("[%s] @%0.6f %r" % (self.port, self._wallclock, message))
|
||||
bhorqueue.put(message)
|
||||
'''
|
||||
BIN
libs/bhoreal.pyc
Normal file
BIN
libs/bhoreal.pyc
Normal file
Binary file not shown.
164
libs/bhorunicornhat.py
Normal file
164
libs/bhorunicornhat.py
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
'''
|
||||
Bhorunicornhat
|
||||
v0.7.0
|
||||
|
||||
A library to replace unicornhat and unicorn_hat_sim to use
|
||||
any unicorn hat python script with a bhoreal or a Launchpad mini.
|
||||
|
||||
2 things to do :
|
||||
|
||||
1/ Change import in a unicorn target python program
|
||||
|
||||
import unicornhat as unicorn
|
||||
|
||||
by :
|
||||
|
||||
import bhorunicornhat as unicorn
|
||||
|
||||
2/ Set target (bhoreal or launchpad) by calling unicornhat.dest(device,rotation)
|
||||
or modify destination and rotation manually : see a few lines down.
|
||||
|
||||
|
||||
|
||||
by Sam Neurohack
|
||||
from /team/laser
|
||||
|
||||
CC NC BY
|
||||
|
||||
'''
|
||||
import colorsys,time
|
||||
import midi3,bhoreal,launchpad
|
||||
|
||||
# For Launchpad mini
|
||||
mididest = "launchpad"
|
||||
rotangle = 270
|
||||
|
||||
# For Bhoreal
|
||||
#mididest = "bhoreal"
|
||||
#rotangle = 180
|
||||
|
||||
BhorLeds = [0] * 64
|
||||
Bhuffer = [0] * 64
|
||||
HAT = (8,8)
|
||||
AUTO = (8,8)
|
||||
|
||||
# 'launchpad' with rotation 270
|
||||
# 'bhoreal' with rotation 180
|
||||
def dest(dest,rot):
|
||||
global mididest, rotangle
|
||||
|
||||
mididest = dest
|
||||
rotangle = rot
|
||||
|
||||
def set_layout(x):
|
||||
pass
|
||||
|
||||
|
||||
def rot90():
|
||||
|
||||
for notes in range(0,64):
|
||||
Bhuffer[notes] = BhorLeds[notes]
|
||||
|
||||
for y in range(1,9):
|
||||
for x in range(1,9):
|
||||
#print x,y,9-y,x,bhoreal.NoteXY(9-y,x),bhoreal.NoteXY(x,y),BhorLeds[bhoreal.NoteXY(9-y,x)],Bhuffer[bhoreal.NoteXY(x,y)]
|
||||
BhorLeds[bhoreal.NoteXY(9-y,x)]=Bhuffer[bhoreal.NoteXY(x,y)]
|
||||
|
||||
def rot180():
|
||||
|
||||
for notes in range(0,64):
|
||||
Bhuffer[notes] = BhorLeds[notes]
|
||||
|
||||
for y in range(8,0,-1):
|
||||
#print ""
|
||||
for x in range(1,9):
|
||||
#print x,y,9-y,bhoreal.NoteXY(x,9-y),bhoreal.NoteXY(x,y),BhorLeds[bhoreal.NoteXY(x,9-y)],Bhuffer[bhoreal.NoteXY(x,y)]
|
||||
BhorLeds[bhoreal.NoteXY(x,9-y)]=Bhuffer[bhoreal.NoteXY(x,y)]
|
||||
|
||||
def rotation(angle):
|
||||
if angle == 90:
|
||||
rot90()
|
||||
if angle == 180:
|
||||
rot180()
|
||||
if angle == 270:
|
||||
rot180()
|
||||
rot90()
|
||||
|
||||
def brightness(brightness):
|
||||
#like 0.5
|
||||
pass
|
||||
|
||||
def get_shape():
|
||||
return 8,8
|
||||
|
||||
def clear():
|
||||
off()
|
||||
|
||||
def hue(r,g,b):
|
||||
|
||||
h = int(127*colorsys.rgb_to_hsv(r,g,b)[0])
|
||||
v = int(127*colorsys.rgb_to_hsv(r,g,b)[2])
|
||||
if h == 0 and v != 0:
|
||||
h=127
|
||||
#should be variation of grey (v,v,v)
|
||||
#v = int(127*colorsys.rgb_to_hsv(r,g,b)[2])
|
||||
#print r,g,b,h
|
||||
return h
|
||||
|
||||
def off():
|
||||
for note in range(1,64):
|
||||
BhorLeds[note] = 0
|
||||
show()
|
||||
|
||||
def set_all(r,g,b):
|
||||
|
||||
for led in range(0,64):
|
||||
BhorLeds[led] = hue(r,g,b)
|
||||
|
||||
def set_pixel(x,y,r,g,b):
|
||||
|
||||
#print x,y,r,g,b,colorsys.rgb_to_hsv(r,g,b)
|
||||
note = (x-1)+ (y-1) * 8
|
||||
#print int(127*colorsys.rgb_to_hsv(r,g,b)[0])
|
||||
BhorLeds[note] = hue(r,g,b)
|
||||
|
||||
def set_pixels(pixels):
|
||||
led = 0
|
||||
for line in pixels:
|
||||
#print line
|
||||
for ledline in range(0,8):
|
||||
#print line[ledline]
|
||||
r,g,b = line[ledline][0],line[ledline][1],line[ledline][2]
|
||||
BhorLeds[led] = hue(r,g,b)
|
||||
led += 1
|
||||
|
||||
def clean_shutdown():
|
||||
pass
|
||||
|
||||
def show():
|
||||
|
||||
# How turn off all leds
|
||||
'''
|
||||
if bhoreal.Here != -1:
|
||||
bhoreal.Cls(0)
|
||||
|
||||
if launchpad.Here != -1:
|
||||
launchpad.Cls()
|
||||
'''
|
||||
|
||||
# Check if midi3 has been previously initiated
|
||||
if len(midi3.OutDevice) == 0:
|
||||
midi3.OutConfig()
|
||||
|
||||
|
||||
if (mididest == 'launchpad' and launchpad.Here != -1) or (mididest == 'bhoreal' and bhoreal.Here != -1):
|
||||
|
||||
rotation(rotangle)
|
||||
for note in range(1,65):
|
||||
midi3.NoteOn(note-1,BhorLeds[note-1],mididest)
|
||||
time.sleep(0.0001)
|
||||
else:
|
||||
print(mididest,'is connected ?')
|
||||
157
libs/cli.py
Normal file
157
libs/cli.py
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
# coding=UTF-8
|
||||
"""
|
||||
LJay/LJ
|
||||
|
||||
v0.8
|
||||
|
||||
Command line arguments parser
|
||||
|
||||
by Sam Neurohack
|
||||
from /team/laser
|
||||
|
||||
"""
|
||||
|
||||
|
||||
import gstt
|
||||
import argparse
|
||||
|
||||
print "-h will display help"
|
||||
print ""
|
||||
|
||||
def handle():
|
||||
|
||||
|
||||
#have to be done before importing bhorosc.py to get correct port assignment
|
||||
argsparser = argparse.ArgumentParser(description="LJ v0.8")
|
||||
argsparser.add_argument("-r","--redisIP",help="IP address to bind builtin servers (OSC and websocket) also must be the Redis server IP ",type=str)
|
||||
argsparser.add_argument("-L","--Lasers",help="Number of lasers connected (4 by default).",type=int)
|
||||
argsparser.add_argument("-v","--verbose",help="Debug mode 0,1 or 2 (0 by default)",type=int)
|
||||
argsparser.add_argument("-x","--invx",help="Invert laser 0 X axis again",action="store_true")
|
||||
argsparser.add_argument("-y","--invy",help="Invert laser 0 Y axis again",action="store_true")
|
||||
argsparser.add_argument("-d","--display",help="Point List number displayed in simulator",type=int)
|
||||
argsparser.add_argument("-a","--align",help="Reset laser 0 alignement values",action="store_true")
|
||||
argsparser.add_argument("-i","--iport",help="port number for builtin LJ OSC server (8002 by default)",type=int)
|
||||
argsparser.add_argument("-n","--nozoidIP",help="IP for llstr' Nozoid OSC server port 8003 ('127.0.0.1' by default)",type=str)
|
||||
argsparser.add_argument("-b","--bhoroscIP",help="IP for OSC output ('127.0.0.1' by default)",type=str)
|
||||
argsparser.add_argument("-o","--oport",help="OSC output port number (8001 by default)",type=int)
|
||||
|
||||
|
||||
|
||||
# Keep it ! if new features of cli.py is used in a monolaser program
|
||||
# argsparser.add_argument("-l","--laser",help="Last digit of etherdream ip address 192.168.1.0/24 (4 by default). Localhost if digit provided is 0.",type=int)
|
||||
|
||||
|
||||
args = argsparser.parse_args()
|
||||
|
||||
# Verbose = debug
|
||||
if args.verbose != None:
|
||||
#print "setting gstt.debug to", args.verbose
|
||||
gstt.debug = args.verbose
|
||||
else:
|
||||
gstt.debug = 0
|
||||
|
||||
# Ports arguments
|
||||
if args.iport:
|
||||
iport = args.iport
|
||||
gstt.iport = iport
|
||||
else:
|
||||
iport = gstt.iport
|
||||
|
||||
if args.oport:
|
||||
oport = args.oport
|
||||
gstt.oport = oport
|
||||
else:
|
||||
oport = gstt.oport
|
||||
|
||||
if gstt.debug > 0:
|
||||
print "Accept OSC on port",gstt.oport
|
||||
print "gstt.iport:",gstt.iport
|
||||
|
||||
|
||||
# X Y inversion arguments
|
||||
if args.invx == True:
|
||||
|
||||
gstt.swapX[0] = -1 * gstt.swapX[0]
|
||||
gstt.centerx[0] = 0
|
||||
gstt.centery[0] = 0
|
||||
#WriteSettings()
|
||||
print("laser 0 X new invertion Asked")
|
||||
if gstt.swapX[0] == 1:
|
||||
print ("X not Inverted")
|
||||
else:
|
||||
print ("X Inverted")
|
||||
|
||||
if args.invy == True:
|
||||
|
||||
gstt.swapY[0] = -1 * gstt.swapY[0]
|
||||
gstt.centerx[0] = 0
|
||||
gstt.centery[0] = 0
|
||||
#WriteSettings()
|
||||
print("laser 0 Y new invertion Asked")
|
||||
if gstt.swapY[0] == 1:
|
||||
print ("Y not Inverted")
|
||||
else:
|
||||
print("Y inverted")
|
||||
|
||||
# Redis Computer IP
|
||||
if args.redisIP != None:
|
||||
gstt.LjayServerIP = args.redisIP
|
||||
|
||||
|
||||
|
||||
# Point list number used by simulator
|
||||
if args.display != None:
|
||||
gstt.simuPL = args.display
|
||||
print "Display : " + str(gstt.simuPL)
|
||||
|
||||
|
||||
|
||||
# Lasers = number of laser connected
|
||||
if args.Lasers != None:
|
||||
gstt.LaserNumber = args.Lasers
|
||||
else:
|
||||
gstt.LaserNumber = 4
|
||||
|
||||
|
||||
if args.bhoroscIP != None:
|
||||
gstt.oscIPin = args.bhoroscIP
|
||||
else:
|
||||
gstt.oscIPin = '127.0.0.1'
|
||||
|
||||
|
||||
if args.nozoidIP != None:
|
||||
gstt.nozoscIP = args.nozoidIP
|
||||
else:
|
||||
gstt.nozoscIP = '127.0.0.1'
|
||||
|
||||
# Etherdream target for mono laser program
|
||||
'''
|
||||
if args.laser != None:
|
||||
lstdgtlaser = args.laser
|
||||
|
||||
if lstdgtlaser == 0:
|
||||
etherIP = "127.0.0.1"
|
||||
else:
|
||||
etherIP = "192.168.1."+str(lstdgtlaser)
|
||||
|
||||
else:
|
||||
etherIP = "192.168.1.4"
|
||||
|
||||
#print ("Laser 1 etherIP:",etherIP)
|
||||
'''
|
||||
|
||||
# Reset alignment values
|
||||
if args.align == True:
|
||||
|
||||
gstt.centerx[0] = 0
|
||||
gstt.centery[0] = 0
|
||||
gstt.zoomx[0] = 15
|
||||
gstt.zoomy[0] = 15
|
||||
gstt.sizex[0] = 32000
|
||||
gstt.sizey[0] = 32000
|
||||
gstt.finangle[0] = 0.0
|
||||
gstt.swapx[0] = 1
|
||||
gstt.swapy[0] = 1
|
||||
#Settings.Write()
|
||||
|
||||
handle()
|
||||
BIN
libs/cli.pyc
Normal file
BIN
libs/cli.pyc
Normal file
Binary file not shown.
448
libs/commands.py
Normal file
448
libs/commands.py
Normal file
|
|
@ -0,0 +1,448 @@
|
|||
# coding=UTF-8
|
||||
"""
|
||||
|
||||
LJ OSC and Websockets laser commands
|
||||
v0.7.0
|
||||
|
||||
|
||||
LICENCE : CC
|
||||
by Sam Neurohack, Loloster,
|
||||
from /team/laser
|
||||
|
||||
Commands reference. Use commands from websocket (webUI) or OSC, do not set values in redis directly except for /pl.
|
||||
|
||||
/scale/X/lasernumber value
|
||||
/scale/Y/lasernumber value
|
||||
|
||||
/client or note on < 8 : change client displayed for Current Laser
|
||||
23 < /noteon < 32 : PL number displayed on webUI simulator
|
||||
|
||||
/grid/lasernumber value (0 or 1) : switch given laser with grid display on or off
|
||||
|
||||
/black/lasernumber value (0 or 1) : set given laser to black on or off
|
||||
|
||||
/ip/lasernumber value : change given laser IP i.e '192.168.1.1'
|
||||
|
||||
/kpps/lasernumber value
|
||||
Live change of kpps is not implemented in newdac.py. Change will effect next startup.
|
||||
|
||||
/angle/lasernumber value : increase/decrease angle correction for given laser by value
|
||||
|
||||
/intens/lasernumber value : increase/decrease intensity for given laser by value
|
||||
|
||||
/resampler/lasernumber lsteps : change resampling strategy (glitch art) for given laser
|
||||
lsteps is a string like "[ (1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)]"
|
||||
|
||||
/mouse/lasernumber value (0 or 1)
|
||||
|
||||
/swap/X/lasernumber value (0 or 1)
|
||||
/swap/Y/lasernumber value (0 or 1)
|
||||
|
||||
/loffset/X/lasernumber value : change X offset of given laser by value
|
||||
/loffset/Y/lasernumber value : change Y offset of given laser by value
|
||||
|
||||
/order value : instruct tracer what to do.
|
||||
|
||||
/planet will be forwarded to planetarium client.
|
||||
/nozoid will be forwarded to nozoid client.
|
||||
|
||||
/scene/scenenumber/start 0 or 1
|
||||
|
||||
0 : display user pointlist with current client key. See below for client key.
|
||||
1 : pull in redis a new correction matrix (EDH)
|
||||
2 : display black
|
||||
3 : display grid
|
||||
4 : resampler
|
||||
5 : pull in redis a new client key
|
||||
|
||||
|
||||
/pl/clientnumber/lasernumber value : value is the pointlist to draw as string type. For string format see code in clients directory.
|
||||
|
||||
Example : client 0 send 2 point lists one for laser 0 and one for laser 1 by sending in redis :
|
||||
/pl/0/0 and /pl/0/1
|
||||
The "client key" when client 0 is selected to be displayed by lasers is "/pl/0/".
|
||||
Each tracer pull its pointlist by using the current client key "/pl/0/"
|
||||
and add its laser number at startup : /pl0/0 ant /pl/0/1
|
||||
|
||||
"Client" is a concept. Imagine in a demoparty there is 4 lasers.
|
||||
John and Paul want to draw on all lasers.
|
||||
Let's give John client 0, he will send points to /pl/0/0, /pl/0/1, /pl/0/2 and /pl/0/3.
|
||||
|
||||
Paul is client 1, so he will use /pl/1/0, /pl/1/1, /pl/1/2 and /pl/1/3.
|
||||
|
||||
Both can send their pointlists to redis server.
|
||||
When John get the lasers switch to client 0, when it's Paul turn switch to client 1.
|
||||
|
||||
But say Bob and Lisa needs only 2 lasers each. Give them client 2.
|
||||
Bob could use /pl/2/0 and /pl/2/1 and Lisa could use /pl/2/2 and /pl/2/3.
|
||||
|
||||
|
||||
"""
|
||||
from __future__ import absolute_import
|
||||
import types, time
|
||||
from libs import gstt
|
||||
import redis
|
||||
|
||||
from libs import settings, plugins, homographyp
|
||||
|
||||
|
||||
r = redis.StrictRedis(host=gstt.LjayServerIP , port=6379, db=0)
|
||||
|
||||
GenericCommands = ["start","align","ljclient","scene","addest","deldest","clientnumber","vcvrack","fft","midigen","viewgen","audiogen","noteon","cc","ljpong","ljwars","mouse","emergency","simu","status","run","nozoid","planet","live","words","ai","bank0","pose","lj","cycl","glyph","pong"]
|
||||
|
||||
|
||||
|
||||
def UserOn(laser):
|
||||
|
||||
print "User for laser ", laser
|
||||
plugins.sendWSall("/status User on laser " + str(laser))
|
||||
r.set('/order/'+str(laser), 0)
|
||||
|
||||
|
||||
def NewEDH(laser):
|
||||
|
||||
print "New EDH requested for laser ", laser
|
||||
plugins.sendWSall("/status New EDH on laser " + str(laser))
|
||||
settings.Write()
|
||||
print "Settings saving swapX ", gstt.swapX[laser]
|
||||
print "Settings saving swapY ", gstt.swapY[laser]
|
||||
|
||||
homographyp.newEDH(laser)
|
||||
|
||||
def BlackOn(laser):
|
||||
|
||||
print "Black for laser ", laser
|
||||
plugins.sendWSall("/status Black on laser " + str(laser))
|
||||
r.set('/order/'+str(laser), 2)
|
||||
|
||||
|
||||
def GridOn(laser):
|
||||
|
||||
print "Grid for laser ", laser
|
||||
plugins.sendWSall("/status Grid on laser " + str(laser))
|
||||
r.set('/order/'+str(laser), 3)
|
||||
|
||||
|
||||
def Resampler(laser,lsteps):
|
||||
|
||||
# lsteps is a string like : "[ (1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)]"
|
||||
print "Resampler change for laser ", laser
|
||||
r.set('/resampler/' + str(laser), lsteps)
|
||||
r.set('/order/'+str(laser), 4)
|
||||
|
||||
|
||||
def LasClientChange(clientnumber):
|
||||
|
||||
if r.get("/pl/"+str(clientnumber)+"/0") != None:
|
||||
|
||||
print "Switching to laser client", clientnumber
|
||||
gstt.SceneNumber = clientnumber
|
||||
plugins.sendWSall("/status Client " + str(gstt.SceneNumber) + " laser " + str(gstt.Laser))
|
||||
|
||||
r.set('/clientkey', "/pl/"+str(clientnumber)+"/")
|
||||
print "clientkey set to", "/pl/"+str(clientnumber)+"/"
|
||||
for laserid in xrange(0,gstt.LaserNumber):
|
||||
r.set('/order/'+str(laserid), 5)
|
||||
else:
|
||||
print "ERROR : Maximum number of scenes is set to ", gstt.MaxScenes
|
||||
|
||||
|
||||
def SceneChange(newscene):
|
||||
|
||||
print "Switching to scene", newscene
|
||||
gstt.SceneNumber = int(newscene)
|
||||
plugins.sendWSall("/status Scene " + newscene)
|
||||
|
||||
r.set('/clientkey', "/pl/"+ newscene +"/")
|
||||
print "clientkey set to", "/pl/" + newscene + "/"
|
||||
|
||||
for laserid in xrange(0,gstt.LaserNumber):
|
||||
r.set('/order/'+str(laserid), 5)
|
||||
plugins.sendWSall("/scene/" + str(laserid) + "/start 0")
|
||||
|
||||
plugins.sendWSall("/scene/" + newscene + "/start 1")
|
||||
|
||||
|
||||
|
||||
def NoteOn(note):
|
||||
print "NoteOn", note
|
||||
|
||||
# Change laser client
|
||||
if note < 8:
|
||||
LasClientChange(note)
|
||||
|
||||
# Change PL displayed on webui
|
||||
if note > 23 and note < 32:
|
||||
if note - 24 > gstt.LaserNumber -1:
|
||||
print "Only",gstt.LaserNumber,"lasers asked, you dum ass !"
|
||||
plugins.sendWSall("/status Not Enough Lasers")
|
||||
|
||||
else:
|
||||
gstt.Laser = note -24
|
||||
plugins.sendWSall("/status Scene " + str(gstt.SceneNumber) + " laser " + str(gstt.Laser))
|
||||
print "Current Laser switched to", gstt.Laser
|
||||
|
||||
def CC(number, value):
|
||||
print "CC", note, value
|
||||
|
||||
|
||||
def Mouse(x1,y1,x2,y2):
|
||||
print "Mouse", x1,y1,x2,y2
|
||||
|
||||
|
||||
|
||||
def handler(oscpath, args):
|
||||
|
||||
#print ""
|
||||
if gstt.debug > 0:
|
||||
print "OSC handler in commands.py got /"+ str(oscpath)+ " with args :",args
|
||||
|
||||
# 2 incoming cases : generic or specific for a given lasernumber :
|
||||
# Generic : Commands without a laser number
|
||||
|
||||
if oscpath[1] in GenericCommands:
|
||||
|
||||
if gstt.debug > 0:
|
||||
print "GenericCommand :",oscpath[1],"with args",args
|
||||
|
||||
|
||||
if oscpath[1] == "ljclient":
|
||||
#LasClientChange(int(args[0]))
|
||||
SceneChange(args[0])
|
||||
|
||||
|
||||
#/scene/scenenumber/start 0 or 1
|
||||
if oscpath[1] == "scene":
|
||||
|
||||
print oscpath[1], oscpath[2], args[0]
|
||||
if args[0] == '1' and r.get("/pl/" + oscpath[2] + "/0") != None:
|
||||
SceneChange(oscpath[2])
|
||||
else:
|
||||
print "ERROR : Maximum number of scenes is set to ", gstt.MaxScenes
|
||||
|
||||
|
||||
elif oscpath[1] == "noteon":
|
||||
NoteOn(int(args[0]))
|
||||
|
||||
|
||||
elif oscpath[1] == "CC":
|
||||
CC(int(args[0]), int(args[1]))
|
||||
|
||||
|
||||
elif oscpath[1] == "pong":
|
||||
#print "LJ commands got pong from", args
|
||||
print("/" + args[0] + "/start 1")
|
||||
plugins.sendWSall("/" + args[0] + "/start 1")
|
||||
print("/status got pong from "+ args[0] +".")
|
||||
plugins.sendWSall("/status got pong from "+ args[0] +".")
|
||||
|
||||
|
||||
elif oscpath[1] == "vcvrack":
|
||||
pass
|
||||
'''
|
||||
#print "LJ commands got /vcvrack from", args
|
||||
if oscpath[2] == "1" :
|
||||
r.set('/vcvrack/1', args[0])
|
||||
#print('/vcvrack/1', args[0])
|
||||
if oscpath[2] == "2" :
|
||||
r.set('/vcvrack/2', args[0])
|
||||
#print('/vcvrack/2', args[0])
|
||||
'''
|
||||
|
||||
elif oscpath[1] == "mouse":
|
||||
Mouse(int(args[0]),int(args[1]),int(args[2]),int(args[3]))
|
||||
|
||||
|
||||
# /emergency value (0 or 1)
|
||||
elif oscpath[1] == "emergency":
|
||||
|
||||
if args[0] == "1":
|
||||
|
||||
for laser in range(gstt.lasernumber):
|
||||
print "Black requested for laser ", laser
|
||||
BlackOn(laser)
|
||||
print "EMERGENCY MODE"
|
||||
plugins.sendWSall("/status EMERGENCY MODE")
|
||||
else:
|
||||
for laser in range(gstt.lasernumber):
|
||||
print "Back to normal for laser ", laser
|
||||
UserOn(laser)
|
||||
|
||||
|
||||
|
||||
# Commands with a laser number
|
||||
else:
|
||||
pathlength = len(oscpath)
|
||||
print("oscpath", oscpath)
|
||||
|
||||
print("pathlength", pathlength)
|
||||
|
||||
if pathlength == 3:
|
||||
laser = int(oscpath[2])
|
||||
|
||||
else:
|
||||
laser = int(oscpath[3])
|
||||
|
||||
print "args[0] :",args[0]," ", type(args[0])
|
||||
|
||||
# /grid/lasernumber value (0 or 1)
|
||||
if oscpath[1] == "grid":
|
||||
|
||||
if args[0] == "1":
|
||||
print "Grid requested for laser ", laser
|
||||
GridOn(laser)
|
||||
else:
|
||||
print "No grid for laser ", laser
|
||||
UserOn(laser)
|
||||
|
||||
|
||||
# /ip/lasernumber value
|
||||
if oscpath[1] == "ip":
|
||||
print "New IP for laser ", laser
|
||||
gstt.lasersIPS[laser]= args[0]
|
||||
settings.Write()
|
||||
|
||||
|
||||
# /kpps/lasernumber value
|
||||
# Live change of kpps is not implemented in newdac.py. Change will effect next startup.
|
||||
if oscpath[1] == "kpps":
|
||||
print "New kpps for laser ", laser, " next startup", int(args[0])
|
||||
gstt.kpps[laser]= int(args[0])
|
||||
settings.Write()
|
||||
|
||||
# /angle/lasernumber value
|
||||
if oscpath[1] == "angle":
|
||||
print "New Angle modification for laser ", oscpath[2], ":", float(args[0])
|
||||
gstt.finANGLE[laser] += float(args[0])
|
||||
NewEDH(laser)
|
||||
print "New angle", gstt.finANGLE[laser]
|
||||
|
||||
# /intens/lasernumber value
|
||||
if oscpath[1] == "intens":
|
||||
print "New intensity requested for laser ", laser, ":", int(args[0])
|
||||
print "Change not implemented yet"
|
||||
|
||||
|
||||
|
||||
# /resampler/lasernumber lsteps
|
||||
# lsteps is a string like "[ (1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)]"
|
||||
if oscpath[1] == "resampler":
|
||||
Resampler(laser,args[0])
|
||||
|
||||
|
||||
# /mouse/lasernumber value (0 or 1)
|
||||
if oscpath[1] == "mouse":
|
||||
|
||||
if args[0] == "1":
|
||||
print "Mouse requested for laser ", oscpath[2]
|
||||
gstt.Laser = oscpath[2]
|
||||
else:
|
||||
print "No mouse for laser ", oscpath[2]
|
||||
|
||||
|
||||
# /swap/X/lasernumber value (0 or 1)
|
||||
if oscpath[1] == "swap" and oscpath[2] == "X":
|
||||
|
||||
print "swapX was", gstt.swapX[laser]
|
||||
if args[0] == "0":
|
||||
print "swap X -1 for laser ", laser
|
||||
gstt.swapX[laser]= -1
|
||||
NewEDH(laser)
|
||||
|
||||
else:
|
||||
print "swap X 1 for laser ", laser
|
||||
gstt.swapX[laser]= 1
|
||||
NewEDH(laser)
|
||||
|
||||
# /swap/Y/lasernumber value (0 or 1)
|
||||
if oscpath[1] == "swap" and oscpath[2] == "Y":
|
||||
|
||||
print "swapY was", gstt.swapX[laser]
|
||||
if args[0] == "0":
|
||||
print "swap Y -1 for laser ", laser
|
||||
gstt.swapY[laser]= -1
|
||||
NewEDH(laser)
|
||||
else:
|
||||
print "swap Y 1 for laser ", laser
|
||||
gstt.swapY[laser]= 1
|
||||
NewEDH(laser)
|
||||
|
||||
# /loffset/X/lasernumber value
|
||||
if oscpath[1] == "loffset" and oscpath[2] == "X":
|
||||
print "offset/X laser", laser, "modified to", args[0]
|
||||
gstt.centerX[laser] -= int(args[0])
|
||||
NewEDH(laser)
|
||||
|
||||
# /loffset/Y/lasernumber value
|
||||
if oscpath[1] == "loffset" and oscpath[2] == "Y":
|
||||
print "offset/Y laser", laser, "modified to", args[0]
|
||||
gstt.centerY[laser] -= int(args[0])
|
||||
NewEDH(laser)
|
||||
|
||||
|
||||
# /scale/X/lasernumber value
|
||||
if oscpath[1] == "scale" and oscpath[2] == "X":
|
||||
if gstt.zoomX[laser] + int(args[0]) > 0:
|
||||
gstt.zoomX[laser] += int(args[0])
|
||||
print "scale/X laser", laser , "modified to", gstt.zoomX[laser]
|
||||
NewEDH(laser)
|
||||
|
||||
# /scale/Y/lasernumber value
|
||||
if oscpath[1] == "scale" and oscpath[2] == "Y":
|
||||
if gstt.zoomY[laser] + int(args[0]) > 0:
|
||||
gstt.zoomY[laser] += int(args[0])
|
||||
print "scale/Y laser", laser, "modified to", gstt.zoomY[laser]
|
||||
NewEDH(laser)
|
||||
|
||||
'''
|
||||
For reference values of EDH modifier if assign to keyboard keys (was alignp)
|
||||
|
||||
gstt.centerY[gstt.Laser] -= 20
|
||||
|
||||
gstt.centerY[gstt.Laser] += 20
|
||||
|
||||
gstt.zoomX[gstt.Laser]-= 0.1
|
||||
|
||||
gstt.zoomX[gstt.Laser] += 0.1
|
||||
gstt.zoomY[gstt.Laser] -= 0.1
|
||||
|
||||
gstt.zoomY[gstt.Laser] += 0.1
|
||||
|
||||
gstt.sizeX[gstt.Laser] -= 50
|
||||
|
||||
gstt.sizeX[gstt.Laser] += 50
|
||||
|
||||
gstt.sizeY[gstt.Laser] -= 50
|
||||
|
||||
gstt.sizeY[gstt.Laser] += 50
|
||||
|
||||
gstt.finANGLE[gstt.Laser] -= 0.001
|
||||
|
||||
gstt.finANGLE[gstt.Laser] += 0.001
|
||||
|
||||
Code for bit analysis 2 bits / laser to encode order.
|
||||
|
||||
# Grid PL is Laser bit 0 = 1 and bit 1 = 1
|
||||
#order = r.get('/order')
|
||||
#neworder = order | (1<<laser*2)
|
||||
#neworder = neworder | (1<< 1+laser*2)
|
||||
#r.set('/order', str(neworder))
|
||||
|
||||
# Laser bit 0 = 0 and bit 1 = 0 : USER PL
|
||||
#order = r.get('/order')
|
||||
#neworder = order & ~(1<< laser*2)
|
||||
#neworder = neworder & ~(1<< 1+ laser*2)
|
||||
#r.set('/order', str(neworder))
|
||||
|
||||
# Laser bit 0 = 0 and bit 1 = 1 : New EDH
|
||||
#order = r.get('/order')
|
||||
#neworder = order & ~(1<< laser*2)
|
||||
#neworder = neworder | (1<< 1+laser*2)
|
||||
#r.set('/order', str(neworder))
|
||||
|
||||
# Black PL is Laser bit 0 = 1 and bit 1 = 0 :
|
||||
#order = r.get('/order')
|
||||
#neworder = order | (1<<laser*2)
|
||||
#neworder = neworder & ~(1<< 1+laser*2)
|
||||
|
||||
'''
|
||||
BIN
libs/commands.pyc
Normal file
BIN
libs/commands.pyc
Normal file
Binary file not shown.
119
libs/font1.py
Executable file
119
libs/font1.py
Executable file
|
|
@ -0,0 +1,119 @@
|
|||
# coding=UTF-8
|
||||
"""
|
||||
|
||||
LJ Font 1
|
||||
v0.7.0
|
||||
|
||||
|
||||
LICENCE : CC
|
||||
by Sam Neurohack
|
||||
from /team/laser
|
||||
|
||||
|
||||
"""
|
||||
import gstt
|
||||
|
||||
def DigitsDots(number,color):
|
||||
dots =[]
|
||||
#print ASCII_GRAPHICS[ord(char) - 48]
|
||||
for dot in ASCII_GRAPHICS[number]:
|
||||
#print dot
|
||||
dots.append((gstt.xy_center[0]+dot[0],gstt.xy_center[1]+dot[1],color))
|
||||
#self.point_list.append((xy + (c,)))
|
||||
return dots
|
||||
|
||||
ASCII_GRAPHICS = [
|
||||
|
||||
#implementé
|
||||
|
||||
[(-50,30), (-30,-30), (30,-30), (10,30), (-50,30)], #0
|
||||
[(-20,30), (0,-30), (-20,30)], #1
|
||||
[(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], #2
|
||||
[(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], #3
|
||||
[(30,10), (-30,10), (0,-30), (0,30)], #4
|
||||
[(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], #5
|
||||
[(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], #6
|
||||
[(-30,-30), (30,-30), (-30,30)], #7
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30), (-30,0), (30,0)], #8
|
||||
[(30,0), (-30,0), (-30,-10), (0,-30), (30,-30), (30,10), (0,30), (-30,30)], #9
|
||||
|
||||
# A implementer
|
||||
[(-30,10), (30,-10), (30,10), (0,30), (-30,10), (-30,-10), (0,-30), (30,-10)], #:
|
||||
[(-30,-10), (0,-30), (0,30)], [(-30,30), (30,30)], #;
|
||||
[(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], #<
|
||||
[(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], #=
|
||||
[(30,10), (-30,10), (0,-30), (0,30)], #>
|
||||
[(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], #?
|
||||
[(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], #@
|
||||
|
||||
# Implementé
|
||||
|
||||
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (30,0), (-30,0)], #A
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (30,0), (-30,0)], #A
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30), (-30,0), (30,0)], #B
|
||||
[(30,30), (-30,30), (-30,-30), (30,-30)], #C
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30)], #D
|
||||
[(30,30), (-30,30), (-30,-0), (30,0), (-30,0), (-30,-30), (30,-30)], #E
|
||||
[(-30,30), (-30,-0), (30,0), (-30,0), (-30,-30), (30,-30)], #F
|
||||
[(0,0), (30,0), (30,30), (-30,30), (-30,-30),(30,-30)], #G
|
||||
[(-30,-30), (-30,30), (-30,0), (30,0), (30,30), (30,-30)], #H
|
||||
[(0,30), (0,-30)], #I
|
||||
[(-30,30), (0,-30), (0,-30), (-30,-30), (30,-30)], #J
|
||||
[(-30,-30), (-30,30), (-30,0), (30,-30), (-30,0), (30,30)], #K
|
||||
[(30,30), (-30,30), (-30,-30)], #L
|
||||
[(-30,30), (-30,-30), (0,0), (30,-30), (30,30)], #M
|
||||
[(-30,30), (-30,-30), (30,30), (30,-30)], #N
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30)], #O
|
||||
[(-30,0), (30,0), (30,-30), (-30,-30), (-30,30)], #P
|
||||
[(30,30), (30,-30), (-30,-30), (-30,30), (30,30),(35,35)], #Q
|
||||
[(-30,30), (-30,-30), (30,-30), (30,0), (-30,0), (30,30)], #R
|
||||
[(30,-30), (-30,-30), (-30,0), (30,0), (30,30), (-30,30)], #S
|
||||
[(0,30), (0,-30), (-30,-30), (30,-30)], #T
|
||||
[(-30,-30), (-30,30), (30,30), (30,-30)], #U
|
||||
[(-30,-30), (0,30), (30,-30)], #V
|
||||
[(-30,-30), (-30,30), (0,0), (30,30), (30,-30)], #W
|
||||
[(-30,30), (30,-30)], [(-30,-30), (30,30)], #X
|
||||
[(0,30), (0,0), (30,-30), (0,0), (-30,-30)], #Y
|
||||
[(30,30), (-30,30), (30,-30), (-30,-30)], #Z
|
||||
|
||||
# A implementer
|
||||
|
||||
[(-30,-10), (0,-30), (0,30)], [(-30,30), (30,30)], #[
|
||||
[(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], #\
|
||||
[(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], #]
|
||||
[(30,10), (-30,10), (0,-30), (0,30)], #^
|
||||
[(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], #_
|
||||
[(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], #`
|
||||
|
||||
# Implementé
|
||||
|
||||
[(-20,20), (-20,-20), (20,-20), (20,20), (20,0), (-20,0)], #a
|
||||
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20), (-20,0), (20,0)], #b
|
||||
[(20,20), (-20,20), (-20,-20), (20,-20)], #c
|
||||
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20)], #d
|
||||
[(20,20), (-20,20), (-20,-0), (20,0), (-20,0), (-20,-20), (20,-20)], #e
|
||||
[(-20,20), (-20,-0), (20,0), (-20,0), (-20,-20), (20,-20)], #f
|
||||
[(0,0), (20,0), (20,20), (-20,20), (-20,-20),(20,-20)], #g
|
||||
[(-20,-20), (-20,20), (-20,0), (20,0), (20,20), (20,-20)], #H
|
||||
[(0,20), (0,-20)], #I
|
||||
[(-20,20), (0,-20), (0,-20), (-20,-20), (20,-20)], #J
|
||||
[(-20,-20), (-20,20), (-20,0), (20,-20), (-20,0), (20,20)], #K
|
||||
[(20,20), (-20,20), (-20,-20)], #L
|
||||
[(-20,20), (-20,-20), (0,0), (20,-20), (20,20)], #M
|
||||
[(-20,20), (-20,-20), (20,20), (20,-20)], #N
|
||||
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20)], #O
|
||||
[(-20,0), (20,0), (20,-20), (-20,-20), (-20,20)], #P
|
||||
[(20,20), (20,-20), (-20,-20), (-20,20), (20,20),(25,25)], #Q
|
||||
[(-20,20), (-20,-20), (20,-20), (20,0), (-20,0), (20,20)], #R
|
||||
[(20,-20), (-20,-20), (-20,0), (20,0), (20,20), (-20,20)], #S
|
||||
[(0,20), (0,-20), (-20,-20), (20,-20)], #T
|
||||
[(-20,-20), (-20,20), (20,20), (20,-20)], #U
|
||||
[(-20,-20), (0,20), (20,-20)], #V
|
||||
[(-20,-20), (-20,20), (0,0), (20,20), (20,-20)], #W
|
||||
[(-20,20), (20,-20)], [(-20,-20), (20,20)], #X
|
||||
[(0,20), (0,0), (20,-20), (0,0), (-20,-20)], #Y
|
||||
[(20,20), (-20,20), (20,-20), (-20,-20)], #Z
|
||||
|
||||
[(-2,15), (2,15)] # Point a la place de {
|
||||
]
|
||||
BIN
libs/font1.pyc
Normal file
BIN
libs/font1.pyc
Normal file
Binary file not shown.
130
libs/gstt.py
Normal file
130
libs/gstt.py
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
# coding=UTF-8
|
||||
'''
|
||||
|
||||
LJ Global state
|
||||
v0.8.0
|
||||
|
||||
**
|
||||
Almost all values here Will be overriden by LJ.conf file data
|
||||
**
|
||||
|
||||
LICENCE : CC
|
||||
by Sam Neurohack, Loloster, pclf
|
||||
from /team/laser
|
||||
|
||||
'''
|
||||
|
||||
#ConfigName = "setexample.conf"
|
||||
ConfigName = "LJ.conf"
|
||||
|
||||
debug = 0
|
||||
|
||||
anims= [[],[],[],[]]
|
||||
|
||||
# How many lasers are connected. Different that "currentlaser".
|
||||
LaserNumber = 2
|
||||
|
||||
# What laser client to listen at launch
|
||||
SceneNumber = 0
|
||||
MaxScenes = 3
|
||||
|
||||
screen_size = [400,400]
|
||||
xy_center = [screen_size[0]/2,screen_size[1]/2]
|
||||
|
||||
LjayServerIP = '192.168.1.13'
|
||||
oscIPin = '192.168.1.15'
|
||||
nozoscip = '192.168.1.15'
|
||||
|
||||
# gstt.Laser select to what laser modifcation will occur.
|
||||
# Can be changed with /noteon 16-23
|
||||
Laser = 0
|
||||
|
||||
# gstt.simuPL select what point list number to display in webUI simulator
|
||||
# Can be changed with /noteon 24-31
|
||||
simuPL = 1
|
||||
|
||||
# gstt.laserIPS.
|
||||
lasersIPS = ['192.168.1.5','192.168.1.6','192.168.1.3','192.168.1.4']
|
||||
|
||||
|
||||
|
||||
# gstt.kpps stores kpps for each laser.
|
||||
# ** Will be overridden by LJ.conf file values **
|
||||
kpps = [25000,25000,25000,25000]
|
||||
|
||||
# gstt.GridDisplay : if = 1 Curve points actually sent to PL are replaced by a grid
|
||||
GridDisplay = [0,0,0,0]
|
||||
|
||||
# Transformation Matrix for each laser
|
||||
EDH = [[], [], [], []]
|
||||
|
||||
# Etherdreams reports
|
||||
# ipconn is initial newdac to its etherdream
|
||||
lstt_ipconn = [[-1], [-1], [-1], [-1]]
|
||||
# dacstt is dac light engine state
|
||||
lstt_dacstt = [[-1], [-1], [-1], [-1]]
|
||||
# store last dac answers : ACK, not ACK,...
|
||||
lstt_dacanswers = [[-1], [-1], [-1], [-1]]
|
||||
# store last number of points sent to etherdreams buffer
|
||||
lstt_points = [[0], [0], [0], [0]]
|
||||
|
||||
swapX = [1,1,1,-1]
|
||||
swapY = [1,1,1,-1]
|
||||
|
||||
# For glitch art : change position and number of points added by tracer.py
|
||||
# shortline is for distance with next point, shorter than 4000 (in etherdream coordinates)
|
||||
# i.e (0.25,3) means add 3 points at 25% on the line.
|
||||
stepshortline = [(1.0, 8)]
|
||||
stepslongline = [(0.25, 3), (0.75, 3), (1.0, 10)]
|
||||
|
||||
#stepslongline = [(0.25,1), (0.75, 1), (1.0, 1)]
|
||||
#stepshortline = [(1.0, 8)]
|
||||
#stepslongline = [(1.0, 1)]
|
||||
#stepshortline = [(1.0, 1)]
|
||||
|
||||
point = [0,0,0]
|
||||
|
||||
cc = [0] * 256
|
||||
lfo = [0] * 10
|
||||
osc = [0] * 255
|
||||
oscInUse = [0] * 255
|
||||
knob = [0] * 33
|
||||
# Viewer distance (cc 21)
|
||||
cc[21]=60
|
||||
viewer_distance = cc[21] * 8
|
||||
|
||||
# fov (cc 22)
|
||||
cc[22]= 60
|
||||
fov = 4 * cc[22]
|
||||
|
||||
|
||||
JumpFlag =0
|
||||
|
||||
# OSC ports
|
||||
#temporaray fix hack : iport=nozoport
|
||||
iport = 8002 # LJ input port
|
||||
oport = 8001 # LJ output port
|
||||
noziport=8003 #nozosc.py receiving commands port
|
||||
nozoport=8001 #nozosc.py sending port to LJay (main.py)
|
||||
nozuport=0 #linux serial usb port connecting nozoid devices ACM0 by default
|
||||
|
||||
|
||||
angleX = 0
|
||||
angleY = 0
|
||||
angleZ = 0
|
||||
|
||||
# multilasers arrays
|
||||
centerX = [0,0,0,0]
|
||||
centerY = [0,0,0,0]
|
||||
zoomX = [0,0,0,0]
|
||||
zoomY = [0,0,0,0]
|
||||
sizeX = [0,0,0,0]
|
||||
sizeY = [0,0,0,0]
|
||||
finANGLE = [0,0,0,0]
|
||||
|
||||
warpdest = [[[ 1. , 0. , 0.],[ 0. , 1. , 0.],[ 0. , 0. , 1.]],
|
||||
[[ 1. , 0. , 0.],[ 0. , 1. , 0.],[ 0. , 0. , 1.]],
|
||||
[[ 1. , 0. , 0.],[ 0. , 1. , 0.],[ 0. , 0. , 1.]],
|
||||
[[ 1. , 0. , 0.],[ 0. , 1. , 0.],[ 0. , 0. , 1.]]
|
||||
]
|
||||
|
||||
BIN
libs/gstt.pyc
Normal file
BIN
libs/gstt.pyc
Normal file
Binary file not shown.
252
libs/homographyp.py
Executable file
252
libs/homographyp.py
Executable file
|
|
@ -0,0 +1,252 @@
|
|||
|
||||
#!/usr/bin/python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
'''
|
||||
|
||||
LJay/LJ
|
||||
v0.7.0
|
||||
|
||||
LICENCE : CC
|
||||
Sam Neurohack
|
||||
|
||||
Homographies for align + swap corrections and warp corrections
|
||||
|
||||
Align + swap homography if found with 4 original points and corrected coordinates
|
||||
Warp correction is disabled for the moment. Should be computed at warp edition : set 1 curve 1
|
||||
|
||||
Use the :
|
||||
|
||||
########################################################################
|
||||
# Module to compute homographies #
|
||||
# #
|
||||
# Author : Alexis Mignon #
|
||||
# email : alexis.mignon@info.unicaen.fr #
|
||||
# date : 10/03/2010 #
|
||||
########################################################################
|
||||
|
||||
Module to compute homographies between two sets of 2D points
|
||||
|
||||
implemented functions :
|
||||
- find_homography(points1,points2) : finds the homography between
|
||||
two sets of 2D points
|
||||
- find_affine_homography(points1,points2) : finds the affine
|
||||
homography between two sets of 2D points
|
||||
- apply_homography(H,points) : applies homography H to the set of
|
||||
2D points 'points'
|
||||
|
||||
example :
|
||||
>>> from homography import *
|
||||
>>>
|
||||
>>> points1 = np.array([[ 0., 0. ],
|
||||
>>> [ 1., 0. ],
|
||||
>>> [ 0., 1. ],
|
||||
>>> [ 1., 1. ]])
|
||||
>>>
|
||||
>>> points2 = np.array([[ 0. , 0. ],
|
||||
>>> [ 1. , 0. ],
|
||||
>>> [ 0.25, 1. ],
|
||||
>>> [ 0.75, 1. ]])
|
||||
>>>
|
||||
>>> points3 = np.array([[-1., 0.],
|
||||
>>> [ 0.,-1.],
|
||||
>>> [ 0., 1.],
|
||||
>>> [ 1., 0.]])
|
||||
>>>
|
||||
>>> H1 = find_homography(points1,points2)
|
||||
>>> print H1
|
||||
>>> print apply_homography(H1,points1)
|
||||
>>> H2 = find_affine_homography(points1,points3)
|
||||
>>> print H2
|
||||
>>> print apply_homography(H2,points1)
|
||||
'''
|
||||
|
||||
|
||||
import numpy as np
|
||||
import math
|
||||
from scipy.linalg import svd,lstsq
|
||||
import ast
|
||||
import gstt
|
||||
#from globalVars import xy_center
|
||||
import redis
|
||||
|
||||
|
||||
r = redis.StrictRedis(host=gstt.LjayServerIP, port=6379, db=0)
|
||||
|
||||
def find(points1,points2):
|
||||
if points1.shape[0] != points2.shape[0] : raise ValueError("The number of input and output points mismatches")
|
||||
if points1.shape[1] == 2 :
|
||||
p1 = np.ones((len(points1),3),'float64')
|
||||
p1[:,:2] = points1
|
||||
elif points1.shape[1] == 3 : p1 = points1
|
||||
else : raise ValueError("Bad shape for input points")
|
||||
|
||||
if points2.shape[1] == 2 :
|
||||
p2 = np.ones((len(points2),3),'float64')
|
||||
p2[:,:2] = points2
|
||||
elif points2.shape[1] == 3 : p2 = points2
|
||||
else : raise ValueError("Bad shape for output points")
|
||||
|
||||
npoints = len(points1)
|
||||
|
||||
A = np.zeros((3*npoints,9),'float64')
|
||||
|
||||
for i in xrange(npoints):
|
||||
p1i = p1[i]
|
||||
x2i,y2i,w2i = p2[i]
|
||||
xpi = x2i*p1i
|
||||
ypi = y2i*p1i
|
||||
wpi = w2i*p1i
|
||||
|
||||
A[i*3 ,3:6] = -wpi
|
||||
A[i*3 ,6:9] = ypi
|
||||
A[i*3+1,0:3] = wpi
|
||||
A[i*3+1,6:9] = -xpi
|
||||
A[i*3+2,0:3] = -ypi
|
||||
A[i*3+2,3:6] = xpi
|
||||
|
||||
U,s,Vt = svd(A,full_matrices = False, overwrite_a = True)
|
||||
del U,s
|
||||
h = Vt[-1]
|
||||
H = h.reshape(3,3)
|
||||
return H
|
||||
|
||||
def find_affine(points1,points2):
|
||||
if points1.shape[0] != points2.shape[0] : raise ValueError("The number of input and output points mismatches")
|
||||
if points1.shape[1] == 2 :
|
||||
p1 = np.ones((len(points1),3),'float64')
|
||||
p1[:,:2] = points1
|
||||
elif points1.shape[1] == 3 : p1 = points1
|
||||
else : raise ValueError("Bad shape for input points")
|
||||
|
||||
if points2.shape[1] == 2 :
|
||||
p2 = np.ones((len(points2),3),'float64')
|
||||
p2[:,:2] = points2
|
||||
elif points2.shape[1] == 3 : p2 = points2
|
||||
else : raise ValueError("Bad shape for output points")
|
||||
|
||||
npoints = len(points1)
|
||||
|
||||
A = np.zeros((3*npoints,6),'float64')
|
||||
b = np.zeros((3*npoints,1),'float64')
|
||||
for i in xrange(npoints):
|
||||
p1i = p1[i]
|
||||
x2i,y2i,w2i = p2[i]
|
||||
xpi = x2i*p1i
|
||||
ypi = y2i*p1i
|
||||
wpi = w2i*p1i
|
||||
|
||||
A[i*3 ,3:6] = -wpi
|
||||
A[i*3+1,0:3] = wpi
|
||||
A[i*3+2,0:3] = -ypi
|
||||
A[i*3+2,3:6] = xpi
|
||||
|
||||
b[i*3 ] = -y2i*p1i[2]
|
||||
b[i*3+1] = x2i*p1i[2]
|
||||
|
||||
h = lstsq(A,b,overwrite_a = True, overwrite_b = True)[0]
|
||||
H = np.zeros( (3,3) , 'float64' )
|
||||
H[:2,:] = h.reshape(2,3)
|
||||
H[2,2] = 1
|
||||
return H
|
||||
|
||||
def apply(H,points):
|
||||
|
||||
p = np.ones((len(points),3),'float64')
|
||||
p[:,:2] = points
|
||||
pp = np.dot(p,H.T)
|
||||
pp[:,:2]/=pp[:,2].reshape(len(p),1)
|
||||
return pp[:,:2]
|
||||
|
||||
# Align and axis swap corrections
|
||||
# Reference points
|
||||
pointsref = np.array([(300.0, 400.0), (500.0, 400.0), (500.0, 200.0), (300.0, 200.0)])
|
||||
|
||||
def EDpoint(mylaser,(pygamex,pygamey)):
|
||||
|
||||
#print "current point : ", pygamex, pygamey
|
||||
XX = pygamex - gstt.xy_center[0]
|
||||
YY = pygamey - gstt.xy_center[1]
|
||||
CosANGLE = math.cos(gstt.finANGLE[mylaser])
|
||||
SinANGLE = math.sin(gstt.finANGLE[mylaser])
|
||||
|
||||
x = (gstt.xy_center[0] + ((XX * CosANGLE) - (YY * SinANGLE)) - gstt.xy_center[0]) * gstt.zoomX[mylaser] + gstt.centerX[mylaser]
|
||||
y = (gstt.xy_center[1] + ((XX * SinANGLE) + (YY * CosANGLE)) - gstt.xy_center[1]) * gstt.zoomY[mylaser] + gstt.centerY[mylaser]
|
||||
|
||||
if gstt.debug >1:
|
||||
|
||||
#print "global center :", xy_center
|
||||
print "EDpoint computing..."
|
||||
print "Laser :", mylaser, "center at : ", gstt.centerX[mylaser], gstt.centerY[mylaser]
|
||||
print "Pygame point",pygamex,",",pygamey
|
||||
'''
|
||||
print "swaps : ", (gstt.swapX[mylaser]), str(gstt.swapY[mylaser])
|
||||
print "zooms : ", gstt.zoomX[mylaser], gstt.zoomY[mylaser]
|
||||
print "angles : ", gstt.finANGLE[mylaser]
|
||||
'''
|
||||
print "Result point : ", x * gstt.swapX[mylaser] , y * gstt.swapY[mylaser]
|
||||
return [x * gstt.swapX[mylaser] , y * gstt.swapY[mylaser]]
|
||||
|
||||
'''
|
||||
def EDpoint((pygamex,pygamey)):
|
||||
|
||||
XX = pygamex - xy_center[0]
|
||||
YY = pygamey - xy_center[1]
|
||||
CosANGLE = math.cos(finangle)
|
||||
SinANGLE = math.sin(finangle)
|
||||
# Multilaser style
|
||||
x = (xy_center[0] + ((XX * CosANGLE) - (YY * SinANGLE)) - xy_center[0]) * zoomx + centerx
|
||||
y = (xy_center[1] + ((XX * SinANGLE) + (YY * CosANGLE)) - xy_center[1]) * zoomy + centery
|
||||
|
||||
return [x*1, y*1]
|
||||
'''
|
||||
|
||||
|
||||
# New total homography from always the same reference points : ED (= align + swap) transform + warp transform.
|
||||
# WARP IS DISABLED. Some bug tracking is needed !
|
||||
def newEDH(mylaser):
|
||||
|
||||
EDpoints = []
|
||||
for point in xrange(4):
|
||||
EDpoints.append(EDpoint(mylaser,pointsref[point]))
|
||||
|
||||
# H matrix tansform pygame points in Etherdream system with align and swap correction,
|
||||
H = find(pointsref, np.array(EDpoints))
|
||||
|
||||
# Computer Hwarp matrix with previously reference warped points in configuration file.
|
||||
Hwarp = find(pointsref, gstt.warpdest[mylaser])
|
||||
#Hwarp = np.identity(3, dtype = float)
|
||||
# EDH matrix
|
||||
gstt.EDH[mylaser] = H
|
||||
|
||||
# EDH matrix is H x Hwarp
|
||||
#gstt.EDH[mylaser] = np.dot(H,Hwarp)
|
||||
print "Laser",mylaser,"New EDH computed, sending to redis..."
|
||||
if r.set('/EDH/'+str(mylaser), np.array2string(gstt.EDH[mylaser], separator=',')) == True:
|
||||
r.set('/order/'+str(mylaser), 1)
|
||||
print "New EDH sent."
|
||||
else:
|
||||
print "New EDH not sent."
|
||||
'''
|
||||
# Laser bit 0 = 0 and bit 1 = 1 : New EDH
|
||||
order = r.get('/order')
|
||||
print order
|
||||
neworder = order & ~(1<< mylaser*2)
|
||||
neworder = neworder | (1<< 1+mylaser*2)
|
||||
r.set('/order', str(neworder))
|
||||
'''
|
||||
|
||||
if gstt.debug >1:
|
||||
print ""
|
||||
print "laser ", mylaser
|
||||
print "reference points", pointsref
|
||||
print "laser EDpoints :", EDpoints
|
||||
print "-> Computed H :",H
|
||||
#print "warped points coordinates ", gstt.warpdest[mylaser]
|
||||
#print "-> Computed Hwarp", Hwarp
|
||||
#print "laser ", mylaser, "warpd ",ast.literal_eval(gstt.warpdest[gstt.Laser])
|
||||
#print "laser ", mylaser, "Hwarp ", Hwarp
|
||||
#print ""
|
||||
print "-> new EDH :", gstt.EDH[mylaser]
|
||||
|
||||
BIN
libs/homographyp.pyc
Normal file
BIN
libs/homographyp.pyc
Normal file
Binary file not shown.
883
libs/launchpad.py
Normal file
883
libs/launchpad.py
Normal file
|
|
@ -0,0 +1,883 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Launchpad
|
||||
v0.7.0
|
||||
|
||||
Maunchpad mini Handler.
|
||||
Start a dedicated thread to handle incoming events from launchpad.
|
||||
|
||||
Cls()
|
||||
AllColorPad(color)
|
||||
StartLaunchPad(port) : Start animation
|
||||
|
||||
Led Matrix can be access with X and Y coordinates and as midi note (0-63)
|
||||
|
||||
PadNoteOn(note,color)
|
||||
PadNoteOff(note)
|
||||
PadNoteOnXY(x,y,color):
|
||||
PadNoteOffXY(x,y):
|
||||
PadNoteXY(x,y):
|
||||
|
||||
PadLeds[], PadTops[] and PadRights arrays stores matrix current state
|
||||
|
||||
|
||||
Top raw and right column leds are numbered humanly 1-8. So -1 is for pythonic arrays position 0-7
|
||||
|
||||
PadTopOn(number,color)
|
||||
PadTopOff(number)
|
||||
PadRightOn(number)
|
||||
PadRightOff(number):
|
||||
|
||||
by Sam Neurohack
|
||||
from /team/laser
|
||||
|
||||
for python 2 & 3
|
||||
|
||||
"""
|
||||
|
||||
|
||||
import time
|
||||
import rtmidi
|
||||
from rtmidi.midiutil import open_midiinput
|
||||
from threading import Thread
|
||||
from rtmidi.midiconstants import (CHANNEL_PRESSURE, CONTROLLER_CHANGE, NOTE_ON, NOTE_OFF,
|
||||
PITCH_BEND, POLY_PRESSURE, PROGRAM_CHANGE)
|
||||
|
||||
from mido import MidiFile
|
||||
import mido
|
||||
import sys
|
||||
import midi3
|
||||
#import midimacros, maxwellmacros
|
||||
import traceback
|
||||
|
||||
from queue import Queue
|
||||
import scrolldisp
|
||||
#from libs import macros
|
||||
import json, subprocess
|
||||
from OSC3 import OSCServer, OSCClient, OSCMessage
|
||||
import socket
|
||||
|
||||
|
||||
print('Launchpad Startup..')
|
||||
myHostName = socket.gethostname()
|
||||
print("Name of the localhost is {}".format(myHostName))
|
||||
myIP = socket.gethostbyname(myHostName)
|
||||
print("IP address of the localhost is {}".format(myIP))
|
||||
|
||||
myIP = "127.0.0.1"
|
||||
|
||||
print('Used IP', myIP)
|
||||
OSCinPort = 8080
|
||||
monomePort = 8000
|
||||
maxwellatorPort = 8090
|
||||
|
||||
launchqueue = Queue()
|
||||
|
||||
mode = "maxwell"
|
||||
|
||||
mididest = 'Session 1'
|
||||
midichannel = 1
|
||||
CChannel = 0
|
||||
CCvalue = 0
|
||||
|
||||
PadLeds = [0] * 64
|
||||
PadTops= [0] * 8
|
||||
PadRights= [0] * 8
|
||||
|
||||
Here = -1
|
||||
|
||||
ModeCallback = ''
|
||||
# midi notes
|
||||
LaunchLedMatrix = [(0,1,2,3,4,5,6,7),(16,17,18,19,20,21,22,23),(32,33,34,35,36,37,38,39),(48,49,50,51,52,53,54,55),(64,65,66,67,68,69,70,71),(80,81,82,83,84,85,86,87),(96,97,98,99,100,101,102,103),(112,113,114,115,116,117,118,119)]
|
||||
# Notes
|
||||
LaunchRight = (8,24,40,56,72,88,104,120)
|
||||
# CC
|
||||
LaunchTop = (104,105,106,107,108,109,110,111)
|
||||
PadTop = [0,0,0,0,0,0,0,0]
|
||||
PadRight = [0,0,0,0,0,0,0,0]
|
||||
PadMatrix = [0] * 64
|
||||
TopSelection = [0] *8
|
||||
computerIP = ['127.0.0.1','192.168.2.95','192.168.2.52','127.0.0.1',
|
||||
'127.0.0.1','127.0.0.1','127.0.0.1','127.0.0.1']
|
||||
computer = 0
|
||||
|
||||
|
||||
|
||||
# /cc cc number value
|
||||
def cc(ccnumber, value, dest=mididest):
|
||||
|
||||
midi3.MidiMsg([CONTROLLER_CHANGE+midichannel-1,ccnumber,value], dest)
|
||||
|
||||
|
||||
|
||||
def Disp(text,device = 'Launchpad Mini'):
|
||||
|
||||
print(device,midi3.FindInDevice(device))
|
||||
|
||||
if (device == "Launchpad Mini" or device =='launchpad') and midi3.FindInDevice(device) != -1:
|
||||
scrolldisp.Display(text, color=(255,255,255), delay=0.2, mididest = 'launchpad')
|
||||
|
||||
if device == 'bhoreal' and midi3.FindInDevice('Bhoreal'):
|
||||
scrolldisp.Display(text, color=(255,255,255), delay=0.2, mididest = device)
|
||||
|
||||
|
||||
def PadNoteOn(note,color):
|
||||
(x,y) = BhorIndex(note)
|
||||
#print(note,x,y)
|
||||
PadNoteOnXY(x,y,color)
|
||||
|
||||
|
||||
def PadNoteOff(note):
|
||||
(x,y) = BhorIndex(note)
|
||||
PadNoteOffXY(x,y)
|
||||
|
||||
def PadNoteOnXY(x,y,color):
|
||||
msg= [NOTE_ON, PadNoteXY(x,y), color]
|
||||
#print msg
|
||||
midi3.send(msg,"Launchpad")
|
||||
PadLeds[BhorNoteXY(x,y)]=color
|
||||
|
||||
|
||||
def PadNoteOffXY(x,y):
|
||||
msg= [NOTE_OFF, PadNoteXY(x,y), 0]
|
||||
midi3.send(msg,"Launchpad")
|
||||
PadLeds[BhorNoteXY(x,y)]=0
|
||||
|
||||
def PadNoteXY(x,y):
|
||||
note = LaunchLedMatrix[int(y-1)][int(x-1)]
|
||||
return note
|
||||
|
||||
def PadIndex(note):
|
||||
y=note/16
|
||||
x=note%16
|
||||
return int(x+1),int(y+1)
|
||||
|
||||
def BhorIndex(note):
|
||||
y=note/8
|
||||
x=note%8
|
||||
#print "Note : ",note
|
||||
#print "BhorIndex : ", x+1,y+1
|
||||
return int(x+1),int(y+1)
|
||||
|
||||
def BhorNoteXY(x,y):
|
||||
note = (x -1)+ (y-1) * 8
|
||||
return note
|
||||
|
||||
# top raw and right column leds are numbered humanly 1-8. So -1 is for pythonic arrays position 0-7
|
||||
def PadTopOn(number,color):
|
||||
msg= [CONTROLLER_CHANGE, LaunchTop[number-1], color]
|
||||
midi3.send(msg,"Launchpad")
|
||||
PadTops[number-1]=color
|
||||
|
||||
def PadTopOff(number):
|
||||
msg= [CONTROLLER_CHANGE, LaunchTop[number-1], 0]
|
||||
midi3.send(msg,"Launchpad")
|
||||
PadTops[number-1]=0
|
||||
|
||||
def PadRightOn(number,color):
|
||||
msg= [NOTE_ON, LaunchRight[number-1], color]
|
||||
midi3.send(msg,"Launchpad")
|
||||
PadRights[number-1]=color
|
||||
|
||||
def PadRightOff(number):
|
||||
msg= [NOTE_OFF, LaunchRight[number-1], 0]
|
||||
midi3.send(msg,"Launchpad")
|
||||
PadRights[number-1]=0
|
||||
|
||||
def TopUpdate(button,color):
|
||||
#print(PadTop)
|
||||
PadTop = [0,0,0,0,0,0,0,0]
|
||||
PadTop[button] = color
|
||||
for pad in range(7):
|
||||
PadTopOn(pad+1,PadTop[pad])
|
||||
|
||||
def RightUpdate():
|
||||
for pad in range(9):
|
||||
PadRightOn(pad,PadRight[pad])
|
||||
|
||||
def MatrixUpdate():
|
||||
for pad in range(64):
|
||||
PadNoteOn(pad,PadMatrix[pad])
|
||||
|
||||
def MatrixSelect():
|
||||
MatrixUpdate()
|
||||
return
|
||||
|
||||
def ComputerUpdate(comput):
|
||||
global computer
|
||||
|
||||
computer = comput
|
||||
PadRightOn(computer+1,127)
|
||||
|
||||
|
||||
|
||||
# Client to export buttons actions from Launchpad or bhoreal
|
||||
|
||||
def SendOSC(ip,port,oscaddress,oscargs=''):
|
||||
|
||||
oscmsg = OSCMessage()
|
||||
oscmsg.setAddress(oscaddress)
|
||||
oscmsg.append(oscargs)
|
||||
|
||||
osclient = OSCClient()
|
||||
osclient.connect((ip, port))
|
||||
|
||||
print("sending OSC message : ", oscmsg, "to", ip, ":", port)
|
||||
|
||||
try:
|
||||
osclient.sendto(oscmsg, (ip, port))
|
||||
oscmsg.clearData()
|
||||
return True
|
||||
except:
|
||||
print ('Connection to', ip, 'refused : died ?')
|
||||
return False
|
||||
|
||||
|
||||
#
|
||||
# LaunchPad start anim
|
||||
#
|
||||
|
||||
# AllColor for bhoreal on given port
|
||||
def AllColorPad(color):
|
||||
|
||||
for led in range(0,64,1):
|
||||
PadNoteOn(led,color)
|
||||
'''
|
||||
for line in LaunchLedMatrix:
|
||||
for led in line:
|
||||
midiport[port].send_message([NOTE_ON, led, color])
|
||||
'''
|
||||
for rightled in range(8):
|
||||
PadRightOn(rightled+1,color)
|
||||
for topled in range(8):
|
||||
PadTopOn(topled+1,color)
|
||||
#midiport[port].send_message([CONTROLLER_CHANGE, topled, color])
|
||||
|
||||
def ClsMatrix():
|
||||
for led in range(0,64,1):
|
||||
PadNoteOff(led)
|
||||
|
||||
def ClsTop():
|
||||
for topled in range(8):
|
||||
PadTopOff(topled+1)
|
||||
|
||||
def ClsRight():
|
||||
|
||||
for rightled in range(8):
|
||||
PadRightOff(rightled+1)
|
||||
|
||||
def Cls():
|
||||
|
||||
ClsMatrix()
|
||||
ClsTop()
|
||||
ClsRight()
|
||||
ComputerUpdate(computer)
|
||||
|
||||
'''
|
||||
for line in LaunchLedMatrix:
|
||||
for led in line:
|
||||
midiport[port].send_message([NOTE_OFF, led, 0])
|
||||
'''
|
||||
|
||||
def StartLaunchPad(port):
|
||||
|
||||
#ClsPad(port)
|
||||
#time.sleep(0.3)
|
||||
AllColorPad(20)
|
||||
time.sleep(0.6)
|
||||
Cls()
|
||||
time.sleep(0.3)
|
||||
|
||||
#
|
||||
# Events from Launchpad Handling
|
||||
#
|
||||
|
||||
# Process events coming from Launchpad in a separate thread.
|
||||
def MidinProcess(launchqueue):
|
||||
global computer
|
||||
|
||||
while True:
|
||||
launchqueue_get = launchqueue.get
|
||||
msg = launchqueue_get()
|
||||
#print (msg)
|
||||
|
||||
if msg[0]==NOTE_ON:
|
||||
|
||||
(x,y) = PadIndex(msg[1])
|
||||
|
||||
# MATRIX = macros, notes, channels,...
|
||||
if x < 9:
|
||||
msg[1]= BhorNoteXY(x,y)
|
||||
macroname = "m"+str(y)+str(x)
|
||||
# Run Macro with matrix location and velocity
|
||||
Run(macroname, macroargs = int(msg[2]))
|
||||
|
||||
# RIGHT = computer, this host or other computer
|
||||
if x == 9:
|
||||
print("Right Button : ", y)
|
||||
macroname = "r"+str(y)
|
||||
print(macroname)
|
||||
ClsRight()
|
||||
PadRightOn(y,127)
|
||||
print("Destination computer",y)
|
||||
computer = y
|
||||
#time.sleep(0.1)
|
||||
#PadRightOff(y)
|
||||
|
||||
# TOP = Mode Note, CC, Os, Monome,..
|
||||
if msg[0]==CONTROLLER_CHANGE:
|
||||
print("Pad Top Button : ", str(msg[1]-103), "value",msg[2])
|
||||
TopUpdate(msg[1]-104,20)
|
||||
macroname = "t"+str(msg[1]-103)
|
||||
#print(macroname)
|
||||
Run(macroname, macroargs = (msg[1]-103,msg[2]))
|
||||
|
||||
|
||||
launchqueue = Queue()
|
||||
ModeCallback = "ModeNo"
|
||||
|
||||
|
||||
|
||||
# LaunchPad Mini call back : new msg forwarded to Launchpad queue
|
||||
class LaunchAddQueue(object):
|
||||
def __init__(self, port):
|
||||
self.port = port
|
||||
#print("LaunchAddQueue", self.port)
|
||||
self._wallclock = time.time()
|
||||
|
||||
def __call__(self, event, data=None):
|
||||
message, deltatime = event
|
||||
self._wallclock += deltatime
|
||||
print()
|
||||
print("[%s] @%0.6f %r" % (self.port, self._wallclock, message))
|
||||
launchqueue.put(message)
|
||||
|
||||
#
|
||||
# Modes : Top lines functions
|
||||
#
|
||||
|
||||
# Load Matrix only macros (for the moment) in macros.json
|
||||
def LoadMacros():
|
||||
global macros
|
||||
|
||||
print()
|
||||
print("Loading Launchpad Macros...")
|
||||
f=open("macros.json","r")
|
||||
s = f.read()
|
||||
macros = json.loads(s)
|
||||
print(len(macros['OS']),"Macros")
|
||||
print("Loaded.")
|
||||
|
||||
|
||||
# return macroname number for given type 'OS', 'Maxwell'
|
||||
def findMacros(macroname,macrotype):
|
||||
|
||||
#print("searching", macroname,'...')
|
||||
position = -1
|
||||
for counter in range(len(macros[macrotype])):
|
||||
#print (counter,macros[macrotype][counter]['name'],macros[macrotype][counter]['code'])
|
||||
if macroname == macros[macrotype][counter]['name']:
|
||||
#print(macroname, "is ", counter)
|
||||
position = counter
|
||||
return position
|
||||
|
||||
|
||||
# Default top buttons : maxwell macros
|
||||
def TopMacro(arg):
|
||||
|
||||
topbutton, value = arg
|
||||
print ("topmacro", topbutton, "value", value)
|
||||
if value == 127:
|
||||
TopUpdate(topbutton-1,20)
|
||||
Disp("Ma")
|
||||
Disp('cr', 'bhoreal')
|
||||
ModeCallback = TopCallback
|
||||
|
||||
def TopCallback(arg):
|
||||
|
||||
ClsMatrix()
|
||||
x,y,velocity = arg
|
||||
PadNoteOnXY(x,y,20)
|
||||
#print ('Macros OS', BhorNoteXY(x,y), "velocity", velocity )
|
||||
macroname = 'm'+str(y)+str(x)
|
||||
macronumber = findMacros(macroname,'Maxwell')
|
||||
if macronumber != -1:
|
||||
#print("code : ",macros['OS'][macronumber]["code"])
|
||||
eval(macros['Maxwell'][macronumber]["code"])
|
||||
else:
|
||||
print("no Code yet")
|
||||
|
||||
#
|
||||
# Notes Macros
|
||||
#
|
||||
|
||||
def ModeNote(arg):
|
||||
global ModeCallback
|
||||
|
||||
|
||||
topbutton, value = arg
|
||||
if value == 127:
|
||||
TopUpdate(topbutton-1,20)
|
||||
Disp("No")
|
||||
Disp('te', 'bhoreal')
|
||||
print("ModeNote")
|
||||
|
||||
else:
|
||||
ClsMatrix()
|
||||
|
||||
ModeCallback = "NoteCallback"
|
||||
|
||||
|
||||
def NoteCallback(arg):
|
||||
|
||||
#ClsMatrix()
|
||||
x,y,velocity = arg
|
||||
notename = midi3.midi2note(BhorNoteXY(x,y))
|
||||
|
||||
print('computer',computer)
|
||||
|
||||
# todo : decide whether its 0 or 1 !!!
|
||||
if computer == 0 or computer == 1:
|
||||
midi3.NoteOn(BhorNoteXY(x,y),velocity,'AutoTonic MIDI In')
|
||||
else:
|
||||
SendOSC(computerIP[computer-1],maxwellatorPort,'/note',[BhorNoteXY(x,y),velocity])
|
||||
|
||||
if velocity == 127:
|
||||
PadNoteOnXY(x,y,20)
|
||||
#print ('NoteON', BhorNoteXY(x,y),notename , "velocity", velocity )
|
||||
#Disp(notename)
|
||||
else:
|
||||
PadNoteOnXY(x,y,0)
|
||||
#print ('NoteOFF', BhorNoteXY(x,y),notename , "velocity", velocity )
|
||||
|
||||
#
|
||||
# CC Macros
|
||||
#
|
||||
|
||||
def ModeCC(arg):
|
||||
global ModeCallback
|
||||
|
||||
topbutton, value = arg
|
||||
if value == 127:
|
||||
TopUpdate(topbutton-1,20)
|
||||
Disp('CC')
|
||||
Disp(' ', 'bhoreal')
|
||||
print("Mode CC")
|
||||
ModeCallback = "CCSelect"
|
||||
print("Please enter CC Channel")
|
||||
#ClsMatrix()
|
||||
Disp('Ch')
|
||||
|
||||
def CCSelect(arg):
|
||||
global ModeCallback, CChannel
|
||||
|
||||
x,y, velocity = arg
|
||||
PadNoteOnXY(x,y,20)
|
||||
#print ('in CC channel callback x',x,'y',y)
|
||||
if velocity == 127:
|
||||
|
||||
CChannel = BhorNoteXY(x,y)
|
||||
print("CC Channel", CChannel)
|
||||
print("Please enter CC Value")
|
||||
ModeCallback = "CCValue"
|
||||
Disp('Va')
|
||||
|
||||
def CCValue(arg):
|
||||
#ClsMatrix()
|
||||
x,y, velocity = arg
|
||||
PadNoteOnXY(x,y,20)
|
||||
#print ('in CC value callback x',x,'y',y)
|
||||
|
||||
if velocity == 127:
|
||||
CCvalue = BhorNoteXY(x,y) * 2
|
||||
print("CC Channel", CChannel,"CC Value", CCvalue)
|
||||
|
||||
|
||||
#
|
||||
# OS Macros
|
||||
#
|
||||
|
||||
def ModeOS(arg):
|
||||
global ModeCallback
|
||||
|
||||
topbutton, value = arg
|
||||
if value == 127:
|
||||
Disp('Os')
|
||||
Disp('Ma', 'bhoreal')
|
||||
TopUpdate(topbutton-1,20)
|
||||
ModeCallback = "OSCallback"
|
||||
else:
|
||||
ClsMatrix()
|
||||
|
||||
def OSCallback(arg):
|
||||
|
||||
ClsMatrix()
|
||||
x,y,velocity = arg
|
||||
PadNoteOnXY(x,y,20)
|
||||
#print ('Macros OS', BhorNoteXY(x,y), "velocity", velocity )
|
||||
macroname = 'm'+str(y)+str(x)
|
||||
macronumber = findMacros(macroname,'OS')
|
||||
if macronumber != -1:
|
||||
#print("code : ",macros['OS'][macronumber]["code"])
|
||||
eval(macros['OS'][macronumber]["code"])
|
||||
else:
|
||||
print("no Code yet")
|
||||
|
||||
|
||||
#
|
||||
# Monome emulation
|
||||
#
|
||||
|
||||
prefix = '/box'
|
||||
|
||||
def ModeMonome(arg):
|
||||
global ModeCallback
|
||||
|
||||
topbutton, value = arg
|
||||
if value == 127:
|
||||
TopUpdate(topbutton-1,20)
|
||||
Disp('Mo')
|
||||
Disp('me', 'bhoreal')
|
||||
ModeCallback = "MonomeCallback"
|
||||
|
||||
else:
|
||||
ClsMatrix()
|
||||
|
||||
|
||||
def MonomeCallback(arg):
|
||||
|
||||
ClsMatrix()
|
||||
x,y,velocity = arg
|
||||
#PadNoteOnXY(x,y,20)
|
||||
|
||||
SendOSC('127.0.0.1', monomePort, prefix+'/press', (x,y,1))
|
||||
SendOSC('127.0.0.1', monomePort, prefix+'/grid/key', (x,y,1))
|
||||
|
||||
|
||||
#
|
||||
# StartMode
|
||||
#
|
||||
|
||||
def ModeNo(arg):
|
||||
x,y,velocity = arg
|
||||
PadNoteOnXY(x,y,20)
|
||||
print ('Mode No x',x,'y',y,"note", PadNoteXY(x,y))
|
||||
|
||||
'''
|
||||
def Mode(mode):
|
||||
global macros
|
||||
|
||||
|
||||
if mode == "maxwell":
|
||||
print("Launchpad in Maxwell mode")
|
||||
macros = maxwellmacros.buttons
|
||||
|
||||
if mode == "generic":
|
||||
print("Launchpad in generic mode")
|
||||
macros = generic
|
||||
'''
|
||||
|
||||
|
||||
#
|
||||
# Right column functions
|
||||
#
|
||||
|
||||
def RightMacro(number):
|
||||
|
||||
print ("rightmacro",number)
|
||||
|
||||
#
|
||||
# Default Pad macros
|
||||
#
|
||||
|
||||
|
||||
launchmacros = {
|
||||
|
||||
"t": {"command": TopMacro, "default": -1},
|
||||
"t1": {"command": ModeNote, "default": ''},
|
||||
"t2": {"command": ModeCC, "default": ''},
|
||||
"t3": {"command": ModeOS, "default": ''},
|
||||
"t4": {"command": ModeMonome, "default": ''},
|
||||
"t5": {"command": TopMacro, "default": 5},
|
||||
"t6": {"command": TopMacro, "default": 6},
|
||||
"t7": {"command": TopMacro, "default": 7},
|
||||
"t8": {"command": TopMacro, "default": 8},
|
||||
|
||||
"r1": {"command": RightMacro, "default": 1},
|
||||
"r2": {"command": RightMacro, "default": 2},
|
||||
"r3": {"command": RightMacro, "default": 3},
|
||||
"r4": {"command": RightMacro, "default": 4},
|
||||
"r5": {"command": RightMacro, "default": 5},
|
||||
"r6": {"command": RightMacro, "default": 6},
|
||||
"r7": {"command": RightMacro, "default": 7},
|
||||
"r8": {"command": RightMacro, "default": 8}
|
||||
}
|
||||
|
||||
#Mode("generic")
|
||||
|
||||
|
||||
def Run(macroname, macroargs=''):
|
||||
|
||||
#print ("macroargs", macroargs)
|
||||
|
||||
# Matrix button -> parameters sent to current Function in ModeCallback
|
||||
if macroname.find("m") == 0:
|
||||
doit = eval(ModeCallback)
|
||||
doit((int(macroname[2]),int(macroname[1]), macroargs))
|
||||
#eval(ModeCallback)((int(macroname[2]),int(macroname[1]), macroargs),)
|
||||
|
||||
|
||||
# Otherwise do the macro
|
||||
else:
|
||||
|
||||
doit = launchmacros[macroname]["command"]
|
||||
if macroargs=='':
|
||||
macroargs = launchmacros[macroname]["default"]
|
||||
#print("Running", doit, "with args", macroargs )
|
||||
doit(macroargs)
|
||||
|
||||
#ComputerUpdate(computer)
|
||||
LoadMacros()
|
||||
|
||||
|
||||
'''
|
||||
|
||||
Docs Community About
|
||||
monome
|
||||
osc : opensound control / serialosc protocol
|
||||
|
||||
what is serialosc? how does it work?
|
||||
discovering and connecting to serialosc devices
|
||||
|
||||
serialosc server listens on port 12002.
|
||||
|
||||
when devices are connected, serialosc spawns new ports for each device. querying the server allows you to discover the port number for each device. (this supersedes the zeroconf method, which is still in place for legacy compatibility).
|
||||
messages sent to serialosc server
|
||||
|
||||
/serialosc/list si <host> <port>
|
||||
|
||||
request a list of the currently connected devices, sent to host:port
|
||||
|
||||
/serialosc/notify si <host> <port>
|
||||
|
||||
request that next device change (connect/disconnect) is sent to host:port. to keep receiving the notifications, send another message to /serialosc/notify from the notify handler.
|
||||
messages received from serialosc server
|
||||
|
||||
/serialosc/device ssi <id> <type> <port>
|
||||
|
||||
currently connected device id and type, at this port
|
||||
|
||||
/serialosc/add s <id>
|
||||
|
||||
device added
|
||||
|
||||
/serialosc/remove s <id>
|
||||
|
||||
device removed
|
||||
to serialosc device
|
||||
sys
|
||||
|
||||
these messages can be sent to a serialosc device to change settings.
|
||||
|
||||
/sys/port i <port>
|
||||
|
||||
change computer port
|
||||
|
||||
/sys/host s <host>
|
||||
|
||||
change computer host
|
||||
|
||||
/sys/prefix s <prefix>
|
||||
|
||||
change message prefix (filtering)
|
||||
|
||||
/sys/rotation i <degrees>
|
||||
|
||||
rotate the monome by degrees, where degrees is one of 0, 90, 180, 270. this replaces /cable
|
||||
|
||||
/sys/info si <host> <port>
|
||||
|
||||
/sys/info i <port>
|
||||
|
||||
/sys/info
|
||||
|
||||
info
|
||||
|
||||
request information (settings) about this device
|
||||
|
||||
/info can take the following arguments:
|
||||
|
||||
/info si <host> <port> (send /sys/info messages to host:port)
|
||||
|
||||
/info i <port> (send to localhost:port)
|
||||
|
||||
/info (send to current computer application's host:port)
|
||||
|
||||
example:
|
||||
|
||||
to serialosc:
|
||||
/sys/info localhost 9999
|
||||
from serialosc to localhost:9999:
|
||||
/sys/id m0000045
|
||||
/sys/size 8 16
|
||||
/sys/host localhost
|
||||
/sys/port 23849
|
||||
/sys/prefix /nubs
|
||||
/sys/rotation 270
|
||||
|
||||
from serialosc
|
||||
|
||||
these messages are sent from serialosc to the computer port.
|
||||
|
||||
the messages below are sent after a /sys/info request is received.
|
||||
sys
|
||||
|
||||
/sys/port i report computer port
|
||||
|
||||
/sys/host s report computer host
|
||||
|
||||
/sys/id s report device id
|
||||
|
||||
/sys/prefix s report prefix
|
||||
|
||||
/sys/rotation i report grid device rotation
|
||||
|
||||
/sys/size ii report grid device size
|
||||
|
||||
to device
|
||||
grid
|
||||
|
||||
/grid/led/set x y s
|
||||
|
||||
set led at (x,y) to state s (0 or 1).
|
||||
|
||||
/grid/led/all s
|
||||
|
||||
set all leds to state s (0 or 1).
|
||||
|
||||
/grid/led/map x_offset y_offset s[8]
|
||||
|
||||
Set a quad (8×8, 64 buttons) in a single message.
|
||||
|
||||
Each number in the list is a bitmask of the buttons in a row, one number in the list for each row. The message will fail if the list doesn’t have 8 entries plus offsets.
|
||||
|
||||
taken apart:
|
||||
|
||||
(/grid/led/map) <- the message/route
|
||||
(8 8) <- the offsets
|
||||
(1 2 4 8 16 32 64 128) <- the bitmasks for each row
|
||||
|
||||
examples
|
||||
|
||||
/grid/led/map 0 0 4 4 4 4 8 8 8 8
|
||||
/grid/led/map 0 0 254 253 125 247 239 36 191 4
|
||||
|
||||
Offsets must be mutliples of 8.
|
||||
|
||||
/grid/led/row x_offset y s[..]
|
||||
|
||||
Set a row in a quad in a single message.
|
||||
|
||||
Each number in the list is a bitmask of the buttons in a row, one number in the list for each row being updated.
|
||||
|
||||
examples (for 256)
|
||||
|
||||
/grid/led/row 0 0 255 255
|
||||
/grid/led/row 8 5 255
|
||||
|
||||
examples (for 64)
|
||||
|
||||
/grid/led/row 0 0 232
|
||||
/grid/led/row 0 3 129
|
||||
|
||||
Offsets must be mutliples of 8. Offsets for monome64 should always be zero.
|
||||
|
||||
/grid/led/col x y_offset s[..]
|
||||
|
||||
Set a column in a quad in a single message.
|
||||
|
||||
Each number in the list is a bitmask of the buttons in a column, one number in the list for each row being updated.
|
||||
|
||||
examples (for 256)
|
||||
|
||||
/grid/led/col 0 0 255 255 (updates quads 1 and 3)
|
||||
/grid/led/col 13 8 255 (updates quad 4 due to offset.)
|
||||
|
||||
examples (for 64)
|
||||
|
||||
/grid/led/col 0 0 232
|
||||
/grid/led/col 6 0 155
|
||||
|
||||
Offsets must be mutliples of 8. Offsets for monome64 should always be zero.
|
||||
|
||||
/grid/led/intensity i
|
||||
|
||||
variable brightness:
|
||||
|
||||
Valid values for ‘l’ below are in the range [0, 15].
|
||||
|
||||
January 2011 devices only support four intensity levels (off + 3 brightness levels). The value passed in /level/ messages will be “rounded down” to the lowest available intensity as below:
|
||||
|
||||
[0, 3] - off
|
||||
[4, 7] - low intensity
|
||||
[8, 11] - medium intensity
|
||||
[12, 15] - high intensity
|
||||
|
||||
June 2012 devices allow the full 16 intensity levels.
|
||||
|
||||
/grid/led/level/set x y l
|
||||
/grid/led/level/all l
|
||||
/grid/led/level/map x_off y_off l[64]
|
||||
/grid/led/level/row x_off y l[..]
|
||||
/grid/led/level/col x y_off l[..]
|
||||
|
||||
tilt
|
||||
|
||||
/tilt/set n s
|
||||
|
||||
set active state of tilt sensor n to s (0 or 1, 1 = active, 0 = inactive).
|
||||
arc
|
||||
|
||||
led 0 is north. clockwise increases led number. These can be viewed and tested in the browser at http://nomeist.com/osc/arc/
|
||||
|
||||
/ring/set n x l
|
||||
|
||||
set led x (0-63) on encoder n (0-1 or 0-3) to level l (0-15)
|
||||
|
||||
/ring/all n l
|
||||
|
||||
set all leds on encoder n (0-1 or 0-3) to level l (0-15)
|
||||
|
||||
/ring/map n l[64]
|
||||
|
||||
set all leds on encoder n (0-1 or 0-3) to 64 member array l[64]
|
||||
|
||||
/ring/range n x1 x2 l
|
||||
|
||||
set leds on encoder n (0-1 or 0-3) between (inclusive) x1 and x3 to level l (0-15). direction of set is always clockwise, with wrapping.
|
||||
from device
|
||||
grid
|
||||
|
||||
/grid/key x y s
|
||||
|
||||
key state change at (x,y) to s (0 or 1, 1 = key down, 0 = key up).
|
||||
tilt
|
||||
|
||||
/tilt n x y z
|
||||
|
||||
position change on tilt sensor n, integer (8-bit) values (x, y, z)
|
||||
arc
|
||||
|
||||
/enc/delta n d
|
||||
|
||||
position change on encoder n by value d (signed). clockwise is positive.
|
||||
|
||||
/enc/key n s
|
||||
|
||||
key state change on encoder n to s (0 or 1, 1 = key down, 0 = key up)
|
||||
|
||||
Info@monome.org
|
||||
|
||||
'''
|
||||
BIN
libs/launchpad.pyc
Normal file
BIN
libs/launchpad.pyc
Normal file
Binary file not shown.
359
libs/lj.py
Normal file
359
libs/lj.py
Normal file
|
|
@ -0,0 +1,359 @@
|
|||
# coding=UTF-8
|
||||
|
||||
'''
|
||||
|
||||
lj v0.7.5 for LJ v0.8+
|
||||
|
||||
Some LJ functions useful for python 2.7 clients
|
||||
Functions and documentation here is low priority as python 2 support will stop soon.
|
||||
Better code your plugin with python 3 and lj3.py.
|
||||
|
||||
|
||||
Config
|
||||
PolyLineOneColor
|
||||
rPolyLineOneColor
|
||||
Text
|
||||
SendLJ : remote control
|
||||
LjClient :
|
||||
LjPl :
|
||||
DrawPL
|
||||
WebStatus
|
||||
|
||||
LICENCE : CC
|
||||
Sam Neurohack
|
||||
|
||||
'''
|
||||
|
||||
import math
|
||||
import redis
|
||||
from OSC import OSCServer, OSCClient, OSCMessage
|
||||
|
||||
print "Importing lj from libs..."
|
||||
#redisIP = '127.0.0.1'
|
||||
#r = redis.StrictRedis(host=redisIP, port=6379, db=0)
|
||||
|
||||
ClientNumber = 0
|
||||
name = "noname"
|
||||
oscrun = True
|
||||
point_list = []
|
||||
pl = [[],[],[],[]]
|
||||
|
||||
|
||||
|
||||
def SendLJ(oscaddress,oscargs=''):
|
||||
|
||||
oscmsg = OSCMessage()
|
||||
oscmsg.setAddress(oscaddress)
|
||||
oscmsg.append(oscargs)
|
||||
|
||||
osclientlj = OSCClient()
|
||||
osclientlj.connect((redisIP, 8002))
|
||||
|
||||
print "lj is sending OSC message : ",oscmsg, "to",redisIP,":8002"
|
||||
try:
|
||||
osclientlj.sendto(oscmsg, (redisIP, 8002))
|
||||
oscmsg.clearData()
|
||||
except:
|
||||
print ('Connection to LJ refused : died ?')
|
||||
pass
|
||||
#time.sleep(0.001
|
||||
|
||||
def WebStatus(message):
|
||||
SendLJ("/status", message)
|
||||
|
||||
|
||||
ASCII_GRAPHICS = [
|
||||
|
||||
#implementé
|
||||
|
||||
[(-50,30), (-30,-30), (30,-30), (10,30), (-50,30)], #0
|
||||
[(-20,30), (0,-30), (-20,30)], #1
|
||||
[(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], #2
|
||||
[(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], #3
|
||||
[(30,10), (-30,10), (0,-30), (0,30)], #4
|
||||
[(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], #5
|
||||
[(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], #6
|
||||
[(-30,-30), (30,-30), (-30,30)], #7
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30), (-30,0), (30,0)], #8
|
||||
[(30,0), (-30,0), (-30,-10), (0,-30), (30,-30), (30,10), (0,30), (-30,30)], #9
|
||||
|
||||
# A implementer
|
||||
[(-30,10), (30,-10), (30,10), (0,30), (-30,10), (-30,-10), (0,-30), (30,-10)], #:
|
||||
[(-30,-10), (0,-30), (0,30)], [(-30,30), (30,30)], #;
|
||||
[(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], #<
|
||||
[(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], #=
|
||||
[(30,10), (-30,10), (0,-30), (0,30)], #>
|
||||
[(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], #?
|
||||
[(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], #@
|
||||
|
||||
# Implementé
|
||||
|
||||
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (30,0), (-30,0)], #A
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (30,0), (-30,0)], #A
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30), (-30,0), (30,0)], #B
|
||||
[(30,30), (-30,30), (-30,-30), (30,-30)], #C
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30)], #D
|
||||
[(30,30), (-30,30), (-30,-0), (30,0), (-30,0), (-30,-30), (30,-30)], #E
|
||||
[(-30,30), (-30,-0), (30,0), (-30,0), (-30,-30), (30,-30)], #F
|
||||
[(0,0), (30,0), (30,30), (-30,30), (-30,-30),(30,-30)], #G
|
||||
[(-30,-30), (-30,30), (-30,0), (30,0), (30,30), (30,-30)], #H
|
||||
[(0,30), (0,-30)], #I
|
||||
[(-30,30), (0,-30), (0,-30), (-30,-30), (30,-30)], #J
|
||||
[(-30,-30), (-30,30), (-30,0), (30,-30), (-30,0), (30,30)], #K
|
||||
[(30,30), (-30,30), (-30,-30)], #L
|
||||
[(-30,30), (-30,-30), (0,0), (30,-30), (30,30)], #M
|
||||
[(-30,30), (-30,-30), (30,30), (30,-30)], #N
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30)], #O
|
||||
[(-30,0), (30,0), (30,-30), (-30,-30), (-30,30)], #P
|
||||
[(30,30), (30,-30), (-30,-30), (-30,30), (30,30),(35,35)], #Q
|
||||
[(-30,30), (-30,-30), (30,-30), (30,0), (-30,0), (30,30)], #R
|
||||
[(30,-30), (-30,-30), (-30,0), (30,0), (30,30), (-30,30)], #S
|
||||
[(0,30), (0,-30), (-30,-30), (30,-30)], #T
|
||||
[(-30,-30), (-30,30), (30,30), (30,-30)], #U
|
||||
[(-30,-30), (0,30), (30,-30)], #V
|
||||
[(-30,-30), (-30,30), (0,0), (30,30), (30,-30)], #W
|
||||
[(-30,30), (30,-30)], [(-30,-30), (30,30)], #X
|
||||
[(0,30), (0,0), (30,-30), (0,0), (-30,-30)], #Y
|
||||
[(30,30), (-30,30), (30,-30), (-30,-30)], #Z
|
||||
|
||||
# A implementer
|
||||
|
||||
[(-30,-10), (0,-30), (0,30)], [(-30,30), (30,30)], #[
|
||||
[(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], #\
|
||||
[(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], #]
|
||||
[(30,10), (-30,10), (0,-30), (0,30)], #^
|
||||
[(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], #_
|
||||
[(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], #`
|
||||
|
||||
# Implementé
|
||||
|
||||
[(-20,20), (-20,-20), (20,-20), (20,20), (20,0), (-20,0)], #a
|
||||
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20), (-20,0), (20,0)], #b
|
||||
[(20,20), (-20,20), (-20,-20), (20,-20)], #c
|
||||
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20)], #d
|
||||
[(20,20), (-20,20), (-20,-0), (20,0), (-20,0), (-20,-20), (20,-20)], #e
|
||||
[(-20,20), (-20,-0), (20,0), (-20,0), (-20,-20), (20,-20)], #f
|
||||
[(0,0), (20,0), (20,20), (-20,20), (-20,-20),(20,-20)], #g
|
||||
[(-20,-20), (-20,20), (-20,0), (20,0), (20,20), (20,-20)], #H
|
||||
[(0,20), (0,-20)], #I
|
||||
[(-20,20), (0,-20), (0,-20), (-20,-20), (20,-20)], #J
|
||||
[(-20,-20), (-20,20), (-20,0), (20,-20), (-20,0), (20,20)], #K
|
||||
[(20,20), (-20,20), (-20,-20)], #L
|
||||
[(-20,20), (-20,-20), (0,0), (20,-20), (20,20)], #M
|
||||
[(-20,20), (-20,-20), (20,20), (20,-20)], #N
|
||||
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20)], #O
|
||||
[(-20,0), (20,0), (20,-20), (-20,-20), (-20,20)], #P
|
||||
[(20,20), (20,-20), (-20,-20), (-20,20), (20,20),(25,25)], #Q
|
||||
[(-20,20), (-20,-20), (20,-20), (20,0), (-20,0), (20,20)], #R
|
||||
[(20,-20), (-20,-20), (-20,0), (20,0), (20,20), (-20,20)], #S
|
||||
[(0,20), (0,-20), (-20,-20), (20,-20)], #T
|
||||
[(-20,-20), (-20,20), (20,20), (20,-20)], #U
|
||||
[(-20,-20), (0,20), (20,-20)], #V
|
||||
[(-20,-20), (-20,20), (0,0), (20,20), (20,-20)], #W
|
||||
[(-20,20), (20,-20)], [(-20,-20), (20,20)], #X
|
||||
[(0,20), (0,0), (20,-20), (0,0), (-20,-20)], #Y
|
||||
[(20,20), (-20,20), (20,-20), (-20,-20)], #Z
|
||||
|
||||
[(-2,15), (2,15)] # Point a la place de {
|
||||
]
|
||||
|
||||
def Config(redIP,client,myname):
|
||||
global ClientNumber, name, redisIP
|
||||
|
||||
redisIP = redIP
|
||||
r = redis.StrictRedis(host=redisIP, port=6379, db=0)
|
||||
ClientNumber = client
|
||||
#print "client configured",ClientNumber
|
||||
name = myname
|
||||
print "Plugin declare its name",name
|
||||
|
||||
|
||||
def LjClient(client):
|
||||
global ClientNumber
|
||||
|
||||
ClientNumber = client
|
||||
|
||||
def LjPl(pl):
|
||||
global PL
|
||||
|
||||
PL = pl
|
||||
|
||||
|
||||
|
||||
# Answer to LJ pings with /pong value
|
||||
def OSCping(path, tags, args, source):
|
||||
print name,"got /ping from LJ -> reply /pong", name
|
||||
SendLJ("/pong",name)
|
||||
|
||||
|
||||
|
||||
# Closing plugin messages to LJ
|
||||
def ClosePlugin():
|
||||
WebStatus(name+" Exiting")
|
||||
SendLJ("/"+name+"/start",0)
|
||||
|
||||
|
||||
# /quit
|
||||
def OSCquit(path, tags, args, source):
|
||||
global oscrun
|
||||
|
||||
oscrun = False
|
||||
print('lj got /quit for',name)
|
||||
#WebStatus(name + " quit.")
|
||||
#SendLJ("/"+name+"/start",0)
|
||||
#print("Stopping OSC...")
|
||||
#OSCstop()
|
||||
#sys.exit()
|
||||
|
||||
|
||||
def LineTo(xy, c, PL):
|
||||
|
||||
pl[PL].append((xy + (c,)))
|
||||
|
||||
def Line(xy1, xy2, c, PL):
|
||||
LineTo(xy1, 0, PL)
|
||||
LineTo(xy2, c , PL)
|
||||
|
||||
|
||||
def PolyLineOneColor(xy_list, c, PL , closed ):
|
||||
#print "--"
|
||||
#print "c",c
|
||||
#print "xy_list",xy_list
|
||||
#print "--"
|
||||
xy0 = None
|
||||
for xy in xy_list:
|
||||
if xy0 is None:
|
||||
xy0 = xy
|
||||
#print "xy0:",xy0
|
||||
LineTo(xy0,0, PL)
|
||||
LineTo(xy0,c, PL)
|
||||
else:
|
||||
#print "xy:",xy
|
||||
LineTo(xy,c, PL)
|
||||
if closed:
|
||||
LineTo(xy0,c, PL)
|
||||
|
||||
|
||||
# Computing points coordinates for rPolyline function from 3D and around 0,0 to pygame coordinates
|
||||
def Pointransf(xy, xpos = 0, ypos =0, resize =1, rotx =0, roty =0 , rotz=0):
|
||||
|
||||
x = xy[0] * resize
|
||||
y = xy[1] * resize
|
||||
z = 0
|
||||
|
||||
rad = math.radians(rotx)
|
||||
cosaX = math.cos(rad)
|
||||
sinaX = math.sin(rad)
|
||||
|
||||
y2 = y
|
||||
y = y2 * cosaX - z * sinaX
|
||||
z = y2 * sinaX + z * cosaX
|
||||
|
||||
rad = math.radians(roty)
|
||||
cosaY = math.cos(rad)
|
||||
sinaY = math.sin(rad)
|
||||
|
||||
z2 = z
|
||||
z = z2 * cosaY - x * sinaY
|
||||
x = z2 * sinaY + x * cosaY
|
||||
|
||||
rad = math.radians(rotz)
|
||||
cosZ = math.cos(rad)
|
||||
sinZ = math.sin(rad)
|
||||
|
||||
x2 = x
|
||||
x = x2 * cosZ - y * sinZ
|
||||
y = x2 * sinZ + y * cosZ
|
||||
|
||||
#print xy, (x + xpos,y+ ypos)
|
||||
return (x + xpos,y+ ypos)
|
||||
'''
|
||||
to understand why it get negative Y
|
||||
|
||||
# 3D to 2D projection
|
||||
factor = 4 * gstt.cc[22] / ((gstt.cc[21] * 8) + z)
|
||||
print xy, (x * factor + xpos, - y * factor + ypos )
|
||||
return (x * factor + xpos, - y * factor + ypos )
|
||||
'''
|
||||
|
||||
# Send 2D point list around 0,0 with 3D rotation resizing and reposition around xpos ypos
|
||||
#def rPolyLineOneColor(self, xy_list, c, PL , closed, xpos = 0, ypos =0, resize =1, rotx =0, roty =0 , rotz=0):
|
||||
def rPolyLineOneColor(xy_list, c, PL , closed, xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0):
|
||||
xy0 = None
|
||||
for xy in xy_list:
|
||||
if xy0 is None:
|
||||
xy0 = xy
|
||||
LineTo(Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz),0, PL)
|
||||
LineTo(Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz),c, PL)
|
||||
else:
|
||||
LineTo(Pointransf(xy, xpos, ypos, resize, rotx, roty, rotz),c, PL)
|
||||
if closed:
|
||||
LineTo(Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz),c, PL)
|
||||
|
||||
|
||||
def LinesPL(PL):
|
||||
print "Stupido !! your code is to old : use DrawPL() instead of LinesPL()"
|
||||
DrawPL(PL)
|
||||
|
||||
|
||||
def DrawPL(PL):
|
||||
#print '/pl/0/'+str(PL), str(pl[PL])
|
||||
if r.set('/pl/'+str(ClientNumber)+'/'+str(PL), str(pl[PL])) == True:
|
||||
#print '/pl/'+str(ClientNumber)+'/'+str(PL), str(pl[PL])
|
||||
pl[PL] = []
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def ResetPL(self, PL):
|
||||
pl[PL] = []
|
||||
|
||||
|
||||
|
||||
def DigitsDots(number,color):
|
||||
dots =[]
|
||||
for dot in ASCII_GRAPHICS[number]:
|
||||
#print dot
|
||||
dots.append((gstt.xy_center[0]+dot[0],gstt.xy_center[1]+dot[1],color))
|
||||
#self.point_list.append((xy + (c,)))
|
||||
return dots
|
||||
|
||||
def CharDots(char,color):
|
||||
|
||||
dots =[]
|
||||
for dot in ASCII_GRAPHICS[ord(char)-46]:
|
||||
dots.append((dot[0],dot[1],color))
|
||||
return dots
|
||||
|
||||
def Text(message,c, PL, xpos, ypos, resize, rotx, roty, rotz):
|
||||
|
||||
dots =[]
|
||||
|
||||
l = len(message)
|
||||
i= 0
|
||||
#print message
|
||||
|
||||
for ch in message:
|
||||
|
||||
#print ""
|
||||
# texte centre en x automatiquement selon le nombre de lettres l
|
||||
x_offset = 26 * (- (0.9*l) + 3*i)
|
||||
# Digits
|
||||
if ord(ch)<58:
|
||||
char_pl_list = ASCII_GRAPHICS[ord(ch) - 48]
|
||||
else:
|
||||
char_pl_list = ASCII_GRAPHICS[ord(ch) - 46]
|
||||
char_draw = []
|
||||
#dots.append((char_pl_list[0][0] + x_offset,char_pl_list[0][1],0))
|
||||
|
||||
for xy in char_pl_list:
|
||||
char_draw.append((xy[0] + x_offset,xy[1],c))
|
||||
i +=1
|
||||
#print ch,char_pl_list,char_draw
|
||||
rPolyLineOneColor(char_draw, c, PL , False, xpos, ypos, resize, rotx, roty, rotz)
|
||||
#dots.append(char_draw)
|
||||
|
||||
|
||||
|
||||
|
||||
892
libs/lj23.py
Normal file
892
libs/lj23.py
Normal file
|
|
@ -0,0 +1,892 @@
|
|||
# coding=UTF-8
|
||||
'''
|
||||
|
||||
lj23 v0.7.6 for LJ v0.8+
|
||||
|
||||
Some LJ functions useful for python clients
|
||||
|
||||
|
||||
|
||||
Class management :
|
||||
|
||||
https://stackoverflow.com/questions/739882/iterating-over-object-instances-of-a-given-class-in-python
|
||||
https://stackoverflow.com/questions/8628123/counting-instances-of-a-class
|
||||
http://effbot.org/pyfaq/how-do-i-get-a-list-of-all-instances-of-a-given-class.htm
|
||||
|
||||
|
||||
|
||||
|
||||
Config(redisIP, client number,name)
|
||||
|
||||
Basic Draw :
|
||||
|
||||
- PolyLineOneColor, rPolyLineOneColor, LineTo, Line
|
||||
- PolyLineRGB, rPolyLineRGB, LineRGBTo, LineRGB
|
||||
- rgb2int(r,g,b)
|
||||
- DrawPL(point list number) : once you stacked all wanted elements, like 2 polylines, send them to lasers.
|
||||
- DrawDests(): Draw all requested destinations for each PL.
|
||||
|
||||
High level draw :
|
||||
|
||||
- Text(word, integercolor, PL, xpos, ypos, resize, rotx, roty, rotz) : Display a word
|
||||
- TextRGB(word, red, green, blue, ...)
|
||||
- Embeded font1
|
||||
|
||||
|
||||
Laser objects (name and convenient group of parameters for one or several point lists)
|
||||
|
||||
- RelativeObject
|
||||
- FixedObject
|
||||
|
||||
PL "Destinations" : tells Live what PL to draw and to what scene/Laser ("destination") to send it.
|
||||
|
||||
|
||||
OSC and plugins functions :
|
||||
|
||||
SendLJ(adress,message) : LJ remote control. See commands.py
|
||||
SendResol(address,message): Send OSC message to Resolume.
|
||||
WebStatus(message) : display message on webui
|
||||
|
||||
LjClient(client): Change Client number in redis keys
|
||||
LjPl(pl): Change pl number in redis keys = laser target.
|
||||
ClosePlugin(name): Send UI closing info of given plugin
|
||||
|
||||
OSCstart(): Start the OSC system.
|
||||
OSCframe(): Handle incoming OSC message. Calling the right callback
|
||||
OSCstop(): Properly close the OSC system
|
||||
OSCping(): /ping Answer to LJ pings by sending /pong name
|
||||
OSCquit(): /quit Exit calling script using name in terminal
|
||||
OSCadddest(): PL, scene, laser Add a destination
|
||||
OSCdeldest(): PL, scene, lasers delete a destination
|
||||
OSCobj(): /name/obj objectname attribute value for automation
|
||||
OSCvar(): /name/var variablename value for automation
|
||||
|
||||
setup_controls(joystick)
|
||||
|
||||
XboxController : getLeftHori, getLeftVert, getRightHori, getRightVert, getLeftTrigger, getRightTrigger
|
||||
Ps3Controller : getLeftHori, getLeftVert, getRightHori, getRightVert, getLeftTrigger, getRightTrigger, getUp, getDown, getLeft, getRight, getFire1, getFire2(self):
|
||||
MySaitekController : getLeftHori,getLeftVert, getRightHori,getRightVert, getLeftTrigger,getRightTrigger
|
||||
MyThrustController : getLeftHori, getLeftVert, getRightHori, getRightVert, getLeftTrigger, getRightTrigger
|
||||
CSLController : getLeftHori,getLeftVert,getRightHori, getRightVert,getLeftTrigger,getRightTrigger,getFire1,getFire2
|
||||
my USB Joystick : getUp,getDown,getLeft,getRight,etLeftTrigger, getRightTrigger,getFire1, getFire2
|
||||
|
||||
|
||||
LICENCE : CC
|
||||
Sam Neurohack
|
||||
|
||||
'''
|
||||
|
||||
import math
|
||||
import redis
|
||||
import sys
|
||||
import weakref
|
||||
import struct
|
||||
import numpy as np
|
||||
from multiprocessing import Process, Queue, TimeoutError
|
||||
|
||||
is_py2 = sys.version[0] == '2'
|
||||
if is_py2:
|
||||
from OSC import OSCServer, OSCClient, OSCMessage
|
||||
#print ("Importing lj23 and OSC from libs...")
|
||||
else:
|
||||
from OSC3 import OSCServer, OSCClient, OSCMessage
|
||||
#print ("Importing lj23 and OSC3 from libs...")
|
||||
|
||||
|
||||
#redisIP = '127.0.0.1'
|
||||
#r = redis.StrictRedis(host=redisIP, port=6379, db=0)
|
||||
|
||||
ClientNumber = 0
|
||||
name = "noname"
|
||||
oscrun = True
|
||||
point_list = []
|
||||
pl = [[],[],[],[]]
|
||||
|
||||
fft3Groups = [-1,-1,-1,-1]
|
||||
|
||||
Dests = dict()
|
||||
|
||||
oscIPresol = "127.0.0.1"
|
||||
oscPORTresol = 7000
|
||||
|
||||
|
||||
'''
|
||||
|
||||
Laser "objects"
|
||||
|
||||
|
||||
set a name and convenient group of parameters for one or several point lists
|
||||
|
||||
RelativeObject is for point lists around 0,0 with builtin move/rotation.
|
||||
|
||||
How to init with object color, xpos,... :
|
||||
osciObj = lj.RelativeObject('osciObj', True, 255, [], white, red, green,blue,0 , False, centerX , centerY , 1 , Xrot , Yrot , Zrot)
|
||||
How to use in drawing functions : you're free to use 0, some or all of any laserobject attributes
|
||||
- draw one or several pointlists with 'A' laserobject color and 'B' laserobject xpos ypos ?
|
||||
- Change color of 'main' object and all other objects using it will change also
|
||||
how to change attribute :
|
||||
osciObj.resize = 2 or /pluginame/change 'OsciObj' 'resize' 2
|
||||
|
||||
'''
|
||||
|
||||
class RelativeObject:
|
||||
|
||||
kind = 'relative'
|
||||
counter = 0
|
||||
|
||||
def __init__(self, name, active, intensity, xy, color, red, green, blue, PL , closed, xpos , ypos , resize , rotx , roty , rotz):
|
||||
self.name = name
|
||||
self.active = active # True/False
|
||||
self.intensity = intensity
|
||||
self.xy = [] # Dots list
|
||||
self.color = color # RGB color in int
|
||||
self.red = red
|
||||
self.green = green
|
||||
self.blue = blue
|
||||
self.PL = PL
|
||||
self.closed = closed
|
||||
self.xpos = xpos
|
||||
self.ypos = ypos
|
||||
self.resize = resize
|
||||
self.rotx = rotx
|
||||
self.roty = roty
|
||||
self.rotz = rotz
|
||||
|
||||
RelativeObject.counter += 1
|
||||
#type(self).counter += 1
|
||||
|
||||
def __del__(self):
|
||||
RelativeObject.counter -= 1
|
||||
|
||||
|
||||
# Fixed Laser object : point list in 'pygame' space (top left = 0,0 / bottom right)
|
||||
class FixedObject:
|
||||
|
||||
kind = 'fixed'
|
||||
counter = 0
|
||||
|
||||
def __init__(self, name, intensity, active, xy, color, red, green, blue, PL , closed):
|
||||
self.name = name
|
||||
self.active = active # True/False
|
||||
self.intensity = intensity
|
||||
self.xy = []
|
||||
self.color = color
|
||||
self.red = red
|
||||
self.green = green
|
||||
self.blue = blue
|
||||
self.PL = PL
|
||||
self.closed = closed
|
||||
|
||||
FixedObject.counter += 1
|
||||
|
||||
def __del__(self):
|
||||
FixedObject.counter -= 1
|
||||
|
||||
'''
|
||||
|
||||
class IterDest(type):
|
||||
def __new__ (cls, name, bases, dct):
|
||||
dct['_instances'] = []
|
||||
return super().__new__(cls, name, bases, dct)
|
||||
|
||||
def __call__(cls, *args, **kwargs):
|
||||
instance = super().__call__(*args, **kwargs)
|
||||
cls._instances.append(instance)
|
||||
return instance
|
||||
|
||||
def __iter__(cls):
|
||||
return iter(cls._instances)
|
||||
|
||||
class DestObject():
|
||||
|
||||
# class Destinations(metaclass=IterDest):
|
||||
__metaclass__ = IterDest
|
||||
counter = 0
|
||||
def __init__(self, name, number, active, PL , scene, laser):
|
||||
self.name = name
|
||||
self.number = number
|
||||
self.active = active
|
||||
self.PL = PL
|
||||
self.scene = scene
|
||||
self.laser = laser
|
||||
|
||||
DestObject.counter += 1
|
||||
|
||||
def __del__(self):
|
||||
DestObject.counter -= 1
|
||||
'''
|
||||
class DestObject():
|
||||
|
||||
# class Destinations(metaclass=IterDest):
|
||||
_instances = set()
|
||||
counter = 0
|
||||
|
||||
def __init__(self, name, number, active, PL , scene, laser):
|
||||
self.name = name
|
||||
self.number = number
|
||||
self.active = active
|
||||
self.PL = PL
|
||||
self.scene = scene
|
||||
self.laser = laser
|
||||
self._instances.add(weakref.ref(self))
|
||||
DestObject.counter += 1
|
||||
|
||||
@classmethod
|
||||
def getinstances(cls):
|
||||
dead = set()
|
||||
for ref in cls._instances:
|
||||
obj = ref()
|
||||
if obj is not None:
|
||||
yield obj
|
||||
else:
|
||||
dead.add(ref)
|
||||
cls._instances -= dead
|
||||
|
||||
|
||||
def __del__(self):
|
||||
DestObject.counter -= 1
|
||||
|
||||
|
||||
|
||||
def Config(redIP,client,myname):
|
||||
global ClientNumber, name, redisIP, r
|
||||
|
||||
redisIP = redIP
|
||||
r = redis.StrictRedis(host=redisIP, port=6379, db=0)
|
||||
|
||||
# ClientNumber 255 are not drawing anything like artnet
|
||||
ClientNumber = client
|
||||
#print ("client configured",ClientNumber)
|
||||
name = myname
|
||||
print ("Plugin declare its name",name)
|
||||
#print pl
|
||||
return r
|
||||
|
||||
|
||||
def LjClient(client):
|
||||
global ClientNumber
|
||||
|
||||
ClientNumber = client
|
||||
|
||||
|
||||
|
||||
def LjPl(pl):
|
||||
global PL
|
||||
|
||||
PL = pl
|
||||
|
||||
|
||||
def fromRedis(n):
|
||||
|
||||
encoded = r.get(n)
|
||||
#print("")
|
||||
#print('fromredis key',n,":",encoded)
|
||||
h, w = struct.unpack('>II',encoded[:8])
|
||||
#print("fromredis array size",n,":",h,w)
|
||||
a = np.frombuffer(encoded, dtype=np.int16, offset=8).reshape(h,w)
|
||||
#print("fromredis array",n,":",a)
|
||||
return a
|
||||
|
||||
# Store Numpy array 'a' in Redis key 'n'
|
||||
# Write also in redis key 'a' numpy array, its 2 dimensions size : h time w values
|
||||
def toRedis(n,a):
|
||||
|
||||
#print("array.shape", a.shape, len(a.shape) )
|
||||
if len(a.shape) == 1:
|
||||
h = a.shape[0]
|
||||
w = 1
|
||||
else:
|
||||
h,w = a.shape
|
||||
#print("toredis", n,"h",h,"w",w,"a",a)
|
||||
shape = struct.pack('>II',h,w)
|
||||
|
||||
#shape = struct.pack('>II',len(a),1)
|
||||
#print("toredis",n,a)
|
||||
encoded = shape + a.tobytes()
|
||||
|
||||
# Store encoded data in Redis
|
||||
return r.set(n,encoded)
|
||||
|
||||
|
||||
#
|
||||
# OSC functions
|
||||
#
|
||||
|
||||
# OSC clients
|
||||
|
||||
def SendLJ(oscaddress,oscargs=''):
|
||||
|
||||
oscmsg = OSCMessage()
|
||||
oscmsg.setAddress(oscaddress)
|
||||
oscmsg.append(oscargs)
|
||||
|
||||
osclientlj = OSCClient()
|
||||
osclientlj.connect((redisIP, 8002))
|
||||
|
||||
print("lj23 in",name," sending OSC message : ", oscmsg, "to", redisIP, ":8002")
|
||||
try:
|
||||
osclientlj.sendto(oscmsg, (redisIP, 8002))
|
||||
oscmsg.clearData()
|
||||
except:
|
||||
print ('Connection to LJ refused : died ?')
|
||||
pass
|
||||
#time.sleep(0.001
|
||||
|
||||
|
||||
|
||||
# Resolume OSC Arena client.
|
||||
# sendresol(oscaddress, [arg1, arg2,...])
|
||||
# example : sendresol("/noteon",note)
|
||||
|
||||
def SendResol(oscaddress,oscargs):
|
||||
|
||||
oscmsg = OSCMessage()
|
||||
oscmsg.setAddress(oscaddress)
|
||||
oscmsg.append(oscargs)
|
||||
|
||||
osclientresol = OSCClient()
|
||||
osclientresol.connect((oscIPresol, oscPORTresol))
|
||||
|
||||
print("lj sending OSC message : ", oscmsg, "to Resolume", oscIPresol, ":", oscPORTresol)
|
||||
try:
|
||||
osclientresol.sendto(oscmsg, (oscIPresol, oscPORTresol))
|
||||
oscmsg.clearData()
|
||||
except:
|
||||
print ('Connection to Resolume refused : died ?')
|
||||
pass
|
||||
|
||||
|
||||
|
||||
|
||||
def WebStatus(message):
|
||||
SendLJ("/status", message)
|
||||
|
||||
|
||||
# Closing plugin messages to LJ
|
||||
def ClosePlugin():
|
||||
WebStatus(name+" Exiting")
|
||||
SendLJ("/"+name+"/start",0)
|
||||
|
||||
|
||||
|
||||
|
||||
# RAW OSC Frame available ?
|
||||
def OSCframe():
|
||||
# clear timed_out flag
|
||||
#print "oscframe"
|
||||
oscserver.timed_out = False
|
||||
# handle all pending requests then return
|
||||
while not oscserver.timed_out:
|
||||
oscserver.handle_request()
|
||||
|
||||
# Answer to LJ pings with /pong value
|
||||
def OSCping(path, tags, args, source):
|
||||
#def OSCping():
|
||||
print(name, "got /ping from LJ -> reply /pong", name)
|
||||
SendLJ("/pong",name)
|
||||
|
||||
# Properly close the system. Todo
|
||||
def OSCstop():
|
||||
oscserver.close()
|
||||
|
||||
|
||||
# /quit
|
||||
def OSCquit(path, tags, args, source):
|
||||
global oscrun
|
||||
|
||||
oscrun = False
|
||||
print('lj23 got /quit for',name)
|
||||
#WebStatus(name + " quit.")
|
||||
#SendLJ("/"+name+"/start",0)
|
||||
#print("Stopping OSC...")
|
||||
#OSCstop()
|
||||
#sys.exit()
|
||||
|
||||
|
||||
# default handler
|
||||
def OSChandler(path, tags, args, source):
|
||||
|
||||
oscaddress = ''.join(path.split("/"))
|
||||
print("Default OSC Handler in",name,": msg from Client : " + str(source[0]),)
|
||||
print("OSC address", path)
|
||||
if len(args) > 0:
|
||||
print("with args", args)
|
||||
|
||||
#oscIPout = str(source[0])
|
||||
#osclient.connect((oscIPout, oscPORTout))
|
||||
|
||||
|
||||
# for any laser object : /pluginame/obj objectname attribute value
|
||||
# like : /pluginname/obj 'fft' 'xpos' 100
|
||||
# attributes for all lj Objects: name, xy_list, c, PL
|
||||
# + for RelativeObjects : closed, xpos , ypos , resize , rotx , roty , rotz
|
||||
def OSCobj(path, tags, args, source):
|
||||
|
||||
obj = eval(args[0]+"."+ args[1])
|
||||
obj = args[2]
|
||||
|
||||
|
||||
def OSCvar(path, tags, args, source):
|
||||
|
||||
obj = eval(args[0])
|
||||
obj = args[1]
|
||||
|
||||
|
||||
def addOSCdefaults(server):
|
||||
global oscserver
|
||||
|
||||
oscserver = server
|
||||
oscserver.addMsgHandler( "default", OSChandler )
|
||||
oscserver.addMsgHandler( "/ping", OSCping)
|
||||
oscserver.addMsgHandler( "/quit", OSCquit)
|
||||
oscserver.addMsgHandler( "/"+ name + "/adddest", OSCadddest)
|
||||
oscserver.addMsgHandler( "/"+ name + "/deldest", OSCdeldest)
|
||||
oscserver.addMsgHandler( "/"+ name + "/obj", OSCobj)
|
||||
oscserver.addMsgHandler( "/"+ name + "/var", OSCvar)
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Drawing basic functions
|
||||
#
|
||||
|
||||
def rgb2int(r,g,b):
|
||||
return int('0x%02x%02x%02x' % (r,g,b),0)
|
||||
|
||||
|
||||
def LineTo(xy, c, PL):
|
||||
|
||||
pl[PL].append((xy + (c,)))
|
||||
|
||||
def rLineTo(xy, c, PL, xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0):
|
||||
|
||||
pl[PL].append((Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz) + (c,)))
|
||||
|
||||
|
||||
def Line(xy1, xy2, c, PL):
|
||||
LineTo(xy1, 0, PL)
|
||||
LineTo(xy2, c , PL)
|
||||
|
||||
def rLine(xy1, xy2, c, PL, xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0):
|
||||
rLineTo(xy1, 0, PL)
|
||||
rLineTo(xy2, c , PL)
|
||||
|
||||
|
||||
def PolyLineOneColor(xy_list, c, PL , closed ):
|
||||
#print "--"
|
||||
#print "c",c
|
||||
#print "xy_list",xy_list
|
||||
#print "--"
|
||||
xy0 = None
|
||||
for xy in xy_list:
|
||||
if xy0 is None:
|
||||
xy0 = xy
|
||||
#print "xy0:",xy0
|
||||
LineTo(xy0,0, PL)
|
||||
LineTo(xy0,c, PL)
|
||||
else:
|
||||
#print "xy:",xy
|
||||
LineTo(xy,c, PL)
|
||||
if closed:
|
||||
LineTo(xy0,c, PL)
|
||||
|
||||
|
||||
|
||||
# Computing points coordinates for rPolyline function from 3D and around 0,0 to pygame coordinates
|
||||
def Pointransf(xy, xpos = 0, ypos =0, resize =1, rotx =0, roty =0 , rotz=0):
|
||||
|
||||
x = xy[0] * resize
|
||||
y = xy[1] * resize
|
||||
z = 0
|
||||
|
||||
rad = math.radians(rotx)
|
||||
cosaX = math.cos(rad)
|
||||
sinaX = math.sin(rad)
|
||||
|
||||
y2 = y
|
||||
y = y2 * cosaX - z * sinaX
|
||||
z = y2 * sinaX + z * cosaX
|
||||
|
||||
rad = math.radians(roty)
|
||||
cosaY = math.cos(rad)
|
||||
sinaY = math.sin(rad)
|
||||
|
||||
z2 = z
|
||||
z = z2 * cosaY - x * sinaY
|
||||
x = z2 * sinaY + x * cosaY
|
||||
|
||||
rad = math.radians(rotz)
|
||||
cosZ = math.cos(rad)
|
||||
sinZ = math.sin(rad)
|
||||
|
||||
x2 = x
|
||||
x = x2 * cosZ - y * sinZ
|
||||
y = x2 * sinZ + y * cosZ
|
||||
|
||||
#print xy, (x + xpos,y+ ypos)
|
||||
return (x + xpos,y+ ypos)
|
||||
'''
|
||||
to understand why it get negative Y
|
||||
|
||||
# 3D to 2D projection
|
||||
factor = 4 * gstt.cc[22] / ((gstt.cc[21] * 8) + z)
|
||||
print xy, (x * factor + xpos, - y * factor + ypos )
|
||||
return (x * factor + xpos, - y * factor + ypos )
|
||||
'''
|
||||
|
||||
def rLineTo(xy, c, PL, xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0):
|
||||
|
||||
pl[PL].append((Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz) + (c,)))
|
||||
|
||||
|
||||
def rLine(xy1, xy2, c, PL, xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0):
|
||||
|
||||
LineTo(Pointransf(xy1, xpos, ypos, resize, rotx, roty, rotz),0, PL)
|
||||
LineTo(Pointransf(xy2, xpos, ypos, resize, rotx, roty, rotz),c, PL)
|
||||
|
||||
|
||||
|
||||
# Send 2D point list around 0,0 with 3D rotation resizing and reposition around xpos ypos
|
||||
#def rPolyLineOneColor(self, xy_list, c, PL , closed, xpos = 0, ypos =0, resize =1, rotx =0, roty =0 , rotz=0):
|
||||
def rPolyLineOneColor(xy_list, c, PL , closed, xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0):
|
||||
xy0 = None
|
||||
for xy in xy_list:
|
||||
if xy0 is None:
|
||||
xy0 = xy
|
||||
LineTo(Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz),0, PL)
|
||||
LineTo(Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz),c, PL)
|
||||
else:
|
||||
LineTo(Pointransf(xy, xpos, ypos, resize, rotx, roty, rotz),c, PL)
|
||||
if closed:
|
||||
LineTo(Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz),c, PL)
|
||||
|
||||
|
||||
def LineRGBTo(xy, red, green, blue, PL):
|
||||
|
||||
LineTo(xy, int('0x%02x%02x%02x' % (red,green,blue),0), PL)
|
||||
|
||||
def LineRGB(xy1, xy2, red,green,blue, PL):
|
||||
|
||||
LineTo(xy1, 0, PL)
|
||||
LineTo(xy2, int('0x%02x%02x%02x' % (red,green,blue),0) , PL)
|
||||
|
||||
|
||||
def PolyLineRGB(xy_list, red, green, blue, PL , closed ):
|
||||
|
||||
PolyLineOneColor(xy_list, int('0x%02x%02x%02x' % (red,green,blue),0), PL , closed )
|
||||
|
||||
def rPolyLineRGB(xy_list, red, green, blue, PL , closed, xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0):
|
||||
|
||||
rPolyLineOneColor(xy_list, int('0x%02x%02x%02x' % (red,green,blue),0), PL , closed, xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0)
|
||||
|
||||
|
||||
|
||||
def LinesPL(PL):
|
||||
print("Stupido !! your code is to old : use DrawPL() instead of LinesPL()")
|
||||
DrawPL(PL)
|
||||
|
||||
|
||||
def DrawPL(PL):
|
||||
#print '/pl/0/'+str(PL), str(pl[PL])
|
||||
if r.set('/pl/'+str(ClientNumber)+'/'+str(PL), str(pl[PL])) == True:
|
||||
#print '/pl/'+str(ClientNumber)+'/'+str(PL), str(pl[PL])
|
||||
pl[PL] = []
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def ResetPL(self, PL):
|
||||
pl[PL] = []
|
||||
|
||||
|
||||
#
|
||||
# "Destinations" management for PLs
|
||||
#
|
||||
|
||||
|
||||
# Add a destination for a given PL
|
||||
def Addest(PL, scene, laser):
|
||||
|
||||
print (name,'adding',PL,scene,laser,'?')
|
||||
if Findest(PL, scene, laser) == -1:
|
||||
newdest = DestsObjects.counter + 1
|
||||
Dest0 = lj.DestObject(str(newdest), newdest, True, PL , scene, laser)
|
||||
print("New destination added with number", newdest)
|
||||
else:
|
||||
print("Destination already existed")
|
||||
|
||||
|
||||
# OSC add a destination for a given PL
|
||||
# /pluginame/dest PL, scene, laser
|
||||
def OSCadddest(path, tags, args, source):
|
||||
|
||||
Addests(int(args[0]),int(args[1]),int(args[2]))
|
||||
|
||||
|
||||
# Find PL destination with its parameters in destinations dictionnary
|
||||
def Findest(PL, scene, laser):
|
||||
|
||||
print(name, 'searching PL,scene,laser',PL,scene,laser)
|
||||
for item in DestObjects.getinstances():
|
||||
#print(item)
|
||||
if item.PL == PL and item.scene == scene and item.laser == laser:
|
||||
#Dests.append(item[0])
|
||||
print('found number',item.number)
|
||||
return item.number
|
||||
else:
|
||||
print('no destination found')
|
||||
return -1
|
||||
'''
|
||||
#Dests = list()
|
||||
allDests = Dests.items()
|
||||
for item in allDests:
|
||||
print(item)
|
||||
if item[1] == PL and item[2] == scene and item[3] == laser:
|
||||
#Dests.append(item[0])
|
||||
return Dests[item[0]]
|
||||
else:
|
||||
return -1
|
||||
'''
|
||||
|
||||
# Find and remove a PL destination with its parameters in destinations dictionnary
|
||||
def Deldest(PL, scene, laser):
|
||||
|
||||
Destnumber = Findest(PL, scene, laser)
|
||||
print(name,'deleting Destination PL, scene, laser', PL,scene, laser)
|
||||
|
||||
if Destnumber != -1:
|
||||
print('found DestObject', Destnumber)
|
||||
delattr(DestObjects, str(Destnumber))
|
||||
print("Destination", Destnumber,"was removed")
|
||||
else:
|
||||
print("Destination was not found")
|
||||
|
||||
|
||||
# OSC Delete a destination for a given PL
|
||||
# /pluginame/deldests PL, scene, laser
|
||||
def OSCdeldest(path, tags, args, source):
|
||||
|
||||
Deldests(args[0],args[1],args[2])
|
||||
|
||||
|
||||
# Replace DrawPL if Destinations paradigm is implemented in plugin code
|
||||
def DrawDests():
|
||||
|
||||
# Objects style
|
||||
|
||||
#print("DrawDest")
|
||||
|
||||
for destination in DestObject.getinstances():
|
||||
#print (destination.name, destination.number, destination.active, destination.PL, destination.scene, destination.laser, pl[destination.PL] )
|
||||
|
||||
#print(Dests[str(destination)])
|
||||
#print('/pl/'+str(Dests[str(destination)]["scene"])+'/'+str(Dests[str(destination)]["laser"]), ":", str(pl[Dests[str(destination)]["PL"]]))
|
||||
#print(len(pl[destination.PL]))
|
||||
if destination.active == True:
|
||||
if r.set('/pl/'+str(destination.scene)+'/'+str(destination.laser), str(pl[destination.PL])) == True:
|
||||
#print ('pl', destination.PL, '/pl/'+str(destination.scene)+'/'+str(destination.laser), str(pl[destination.PL]))
|
||||
pass
|
||||
else:
|
||||
print('Redis key modification failed')
|
||||
|
||||
# Maybe one PL can be sent to multiple destination so they are all reset *after* all sending.
|
||||
for pls in range(4):
|
||||
|
||||
pl[pls] = []
|
||||
|
||||
'''
|
||||
# Dictionnary style
|
||||
|
||||
#print(Dests)
|
||||
for destination in range(len(Dests)):
|
||||
#print(Dests[str(destination)])
|
||||
#print('/pl/'+str(Dests[str(destination)]["scene"])+'/'+str(Dests[str(destination)]["laser"]), ":", str(pl[Dests[str(destination)]["PL"]]))
|
||||
if r.set('/pl/'+str(Dests[str(destination)]["scene"])+'/'+str(Dests[str(destination)]["laser"]), str(pl[Dests[str(destination)]["PL"]])) == True:
|
||||
#print '/pl/'+str(ClientNumber)+'/'+str(PL), str(pl[PL])
|
||||
pass
|
||||
else:
|
||||
print('Redis key modification failed')
|
||||
|
||||
# Maybe one PL can be sent to multiple destination so they are all reset *after* all sending.
|
||||
for destination in range(len(Dests)):
|
||||
|
||||
pl[Dests[str(destination)]["PL"]] = []
|
||||
'''
|
||||
'''
|
||||
scenes = 4
|
||||
|
||||
def DrawDestsPL(PL):
|
||||
|
||||
for scene in range(scenes):
|
||||
|
||||
if Dests[laser]["scene"] != -1:
|
||||
if r.set('/pl/'+str(Dests[laser]["scene"])+'/'+str(Dests[laser]["laser"]), str(pl[Dests[laser]["laser"]])) == True:
|
||||
if r.set('/pl/'+str(ClientNumber)+'/'+str(PL), str(pl[PL])) == True:
|
||||
#print '/pl/'+str(ClientNumber)+'/'+str(PL), str(pl[PL])
|
||||
pl[Dests[laser]["laser"]] = []
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
'''
|
||||
|
||||
#
|
||||
# High level drawing functions
|
||||
#
|
||||
|
||||
|
||||
# Font1
|
||||
|
||||
|
||||
ASCII_GRAPHICS = [
|
||||
|
||||
#implementé
|
||||
|
||||
[(-50,30), (-30,-30), (30,-30), (10,30), (-50,30)], # 0
|
||||
[(-20,30), (0,-30), (-20,30)], # 1
|
||||
[(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], # 2
|
||||
[(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], # 3
|
||||
[(30,10), (-30,10), (0,-30), (0,30)], # 4
|
||||
[(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], # 5
|
||||
[(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], # 6
|
||||
[(-30,-30), (30,-30), (-30,30)], # 7
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30), (-30,0), (30,0)], # 8
|
||||
[(30,0), (-30,0), (-30,-10), (0,-30), (30,-30), (30,10), (0,30), (-30,30)], # 9
|
||||
|
||||
# A implementer
|
||||
[(-30,10), (30,-10), (30,10), (0,30), (-30,10), (-30,-10), (0,-30), (30,-10)], #:
|
||||
[(-30,-10), (0,-30), (0,30)], [(-30,30), (30,30)], # ;
|
||||
[(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], # <
|
||||
[(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], # =
|
||||
[(30,10), (-30,10), (0,-30), (0,30)], # >
|
||||
[(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], # ?
|
||||
[(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], # @
|
||||
|
||||
# Implementé
|
||||
|
||||
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (30,0), (-30,0)], # A
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (30,0), (-30,0)], # A
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30), (-30,0), (30,0)], # B
|
||||
[(30,30), (-30,30), (-30,-30), (30,-30)], # C
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30)], # D
|
||||
[(30,30), (-30,30), (-30,-0), (30,0), (-30,0), (-30,-30), (30,-30)], # E
|
||||
[(-30,30), (-30,-0), (30,0), (-30,0), (-30,-30), (30,-30)], # F
|
||||
[(0,0), (30,0), (30,30), (-30,30), (-30,-30),(30,-30)], # G
|
||||
[(-30,-30), (-30,30), (-30,0), (30,0), (30,30), (30,-30)], # H
|
||||
[(0,30), (0,-30)], # I
|
||||
[(-30,30), (0,-30), (0,-30), (-30,-30), (30,-30)], # J
|
||||
[(-30,-30), (-30,30), (-30,0), (30,-30), (-30,0), (30,30)], # K
|
||||
[(30,30), (-30,30), (-30,-30)], # L
|
||||
[(-30,30), (-30,-30), (0,0), (30,-30), (30,30)], # M
|
||||
[(-30,30), (-30,-30), (30,30), (30,-30)], # N
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30)], # O
|
||||
[(-30,0), (30,0), (30,-30), (-30,-30), (-30,30)], # P
|
||||
[(30,30), (30,-30), (-30,-30), (-30,30), (30,30),(35,35)], # Q
|
||||
[(-30,30), (-30,-30), (30,-30), (30,0), (-30,0), (30,30)], # R
|
||||
[(30,-30), (-30,-30), (-30,0), (30,0), (30,30), (-30,30)], # S
|
||||
[(0,30), (0,-30), (-30,-30), (30,-30)], # T
|
||||
[(-30,-30), (-30,30), (30,30), (30,-30)], # U
|
||||
[(-30,-30), (0,30), (30,-30)], # V
|
||||
[(-30,-30), (-30,30), (0,0), (30,30), (30,-30)], # W
|
||||
[(-30,30), (30,-30), (-30,-30), (30,30)], # X
|
||||
[(0,30), (0,0), (30,-30), (0,0), (-30,-30)], # Y
|
||||
[(30,30), (-30,30), (30,-30), (-30,-30)], # Z
|
||||
|
||||
# A implementer
|
||||
|
||||
[(-30,-10), (0,-30), (0,30)], [(-30,30), (30,30)], # [
|
||||
[(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], # \
|
||||
[(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], # ]
|
||||
[(30,10), (-30,10), (0,-30), (0,30)], # ^
|
||||
[(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], # _
|
||||
[(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], # `
|
||||
|
||||
# Implementé
|
||||
|
||||
[(-20,20), (-20,-20), (20,-20), (20,20), (20,0), (-20,0)], # a
|
||||
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20), (-20,0), (20,0)], # b
|
||||
[(20,20), (-20,20), (-20,-20), (20,-20)], # c
|
||||
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20)], # d
|
||||
[(20,20), (-20,20), (-20,-0), (20,0), (-20,0), (-20,-20), (20,-20)], # e
|
||||
[(-20,20), (-20,-0), (20,0), (-20,0), (-20,-20), (20,-20)], # f
|
||||
[(0,0), (20,0), (20,20), (-20,20), (-20,-20),(20,-20)], # g
|
||||
[(-20,-20), (-20,20), (-20,0), (20,0), (20,20), (20,-20)], # h
|
||||
[(0,20), (0,-20)], # i
|
||||
[(-20,20), (0,-20), (0,-20), (-20,-20), (20,-20)], # j
|
||||
[(-20,-20), (-20,20), (-20,0), (20,-20), (-20,0), (20,20)], # k
|
||||
[(20,20), (-20,20), (-20,-20)], # l
|
||||
[(-20,20), (-20,-20), (0,0), (20,-20), (20,20)], # m
|
||||
[(-20,20), (-20,-20), (20,20), (20,-20)], # n
|
||||
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20)], # o
|
||||
[(-20,0), (20,0), (20,-20), (-20,-20), (-20,20)], # p
|
||||
[(20,20), (20,-20), (-20,-20), (-20,20), (20,20),(25,25)], # q
|
||||
[(-20,20), (-20,-20), (20,-20), (20,0), (-20,0), (20,20)], # r
|
||||
[(20,-20), (-20,-20), (-20,0), (20,0), (20,20), (-20,20)], # s
|
||||
[(0,20), (0,-20), (-20,-20), (20,-20)], # t
|
||||
[(-20,-20), (-20,20), (20,20), (20,-20)], # u
|
||||
[(-20,-20), (0,20), (20,-20)], # v
|
||||
[(-20,-20), (-20,20), (0,0), (20,20), (20,-20)], # w
|
||||
[(-20,20), (20,-20)], [(-20,-20), (20,20)], # x
|
||||
[(0,20), (0,0), (20,-20), (0,0), (-20,-20)], # y
|
||||
[(20,20), (-20,20), (20,-20), (-20,-20)], # z
|
||||
|
||||
[(-2,15), (2,15)] # Point a la place de {
|
||||
]
|
||||
|
||||
|
||||
def DigitsDots(number,color):
|
||||
dots =[]
|
||||
for dot in ASCII_GRAPHICS[number]:
|
||||
#print dot
|
||||
dots.append((gstt.xy_center[0]+dot[0],gstt.xy_center[1]+dot[1],color))
|
||||
#self.point_list.append((xy + (c,)))
|
||||
return dots
|
||||
|
||||
def CharDots(char,color):
|
||||
|
||||
dots =[]
|
||||
for dot in ASCII_GRAPHICS[ord(char)-46]:
|
||||
dots.append((dot[0],dot[1],color))
|
||||
return dots
|
||||
|
||||
def Text(message,c, PL, xpos, ypos, resize, rotx, roty, rotz):
|
||||
|
||||
dots =[]
|
||||
|
||||
l = len(message)
|
||||
i= 0
|
||||
#print()
|
||||
# print (message)
|
||||
|
||||
for ch in message:
|
||||
|
||||
#print ""
|
||||
# texte centre en x automatiquement selon le nombre de lettres l
|
||||
x_offset = 26 * (- (0.9*l) + 3*i)
|
||||
# Digits
|
||||
if ord(ch)<58:
|
||||
char_pl_list = ASCII_GRAPHICS[ord(ch) - 48]
|
||||
else:
|
||||
char_pl_list = ASCII_GRAPHICS[ord(ch) - 46]
|
||||
|
||||
char_draw = []
|
||||
#dots.append((char_pl_list[0][0] + x_offset,char_pl_list[0][1],0))
|
||||
|
||||
for xy in char_pl_list:
|
||||
char_draw.append((xy[0] + x_offset,xy[1],c))
|
||||
i +=1
|
||||
#print ch,char_pl_list,char_draw
|
||||
rPolyLineOneColor(char_draw, c, PL , False, xpos, ypos, resize, rotx, roty, rotz)
|
||||
#dots.append(char_draw)
|
||||
|
||||
def TextRGB(message,c, PL, xpos, ypos, resize, rotx, roty, rotz):
|
||||
|
||||
Text(message,int('0x%02x%02x%02x' % (red,green,blue),0), PL, xpos, ypos, resize, rotx, roty, rotz)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
890
libs/lj23layers.py
Normal file
890
libs/lj23layers.py
Normal file
|
|
@ -0,0 +1,890 @@
|
|||
# coding=UTF-8
|
||||
'''
|
||||
|
||||
lj23layers v0.7.6 for LJ v0.8+
|
||||
|
||||
Some LJ functions useful for python clients
|
||||
|
||||
"layers" version : "PL" has been replaced by layer
|
||||
|
||||
|
||||
Class management :
|
||||
|
||||
https://stackoverflow.com/questions/739882/iterating-over-object-instances-of-a-given-class-in-python
|
||||
https://stackoverflow.com/questions/8628123/counting-instances-of-a-class
|
||||
http://effbot.org/pyfaq/how-do-i-get-a-list-of-all-instances-of-a-given-class.htm
|
||||
|
||||
Config(redisIP, client number,name)
|
||||
|
||||
Basic Draw :
|
||||
|
||||
- PolyLineOneColor, rPolyLineOneColor, LineTo, Line
|
||||
- PolyLineRGB, rPolyLineRGB, LineRGBTo, LineRGB
|
||||
- rgb2int(r,g,b)
|
||||
- Drawlayer (point list number) : once you stacked all wanted elements, like 2 polylines, send them to lasers.
|
||||
- DrawDests(): Draw all requested destinations for each layer .
|
||||
|
||||
High level draw :
|
||||
|
||||
- Text(word, integercolor, layer , xpos, ypos, resize, rotx, roty, rotz) : Display a word
|
||||
- TextRGB(word, red, green, blue, ...)
|
||||
- Embeded font1
|
||||
|
||||
|
||||
Laser objects (name and convenient group of parameters for one or several point lists)
|
||||
|
||||
- RelativeObject
|
||||
- FixedObject
|
||||
|
||||
layer "Destinations" : tells Live what layer to draw and to what scene/Laser ("destination") to send it.
|
||||
|
||||
|
||||
OSC and plugins functions :
|
||||
|
||||
SendLJ(adress,message) : LJ remote control. See commands.py
|
||||
SendResol(address,message): Send OSC message to Resolume.
|
||||
WebStatus(message) : display message on webui
|
||||
|
||||
Ljscene(client): Change scene number in redis keys
|
||||
Ljlayer(layer): Change layer number in redis keys = laser target.
|
||||
ClosePlugin(name): Send UI closing info of given plugin
|
||||
|
||||
OSCstart(): Start the OSC system.
|
||||
OSCframe(): Handle incoming OSC message. Calling the right callback
|
||||
OSCstop(): Properly close the OSC system
|
||||
OSCping(): /ping Answer to LJ pings by sending /pong name
|
||||
OSCquit(): /quit Exit calling script using name in terminal
|
||||
OSCadddest(): layer , scene, laser Add a destination
|
||||
OSCdeldest(): layer , scene, lasers delete a destination
|
||||
OSCobj(): /name/obj objectname attribute value for automation
|
||||
OSCvar(): /name/var variablename value for automation
|
||||
|
||||
setup_controls(joystick)
|
||||
|
||||
XboxController : getLeftHori, getLeftVert, getRightHori, getRightVert, getLeftTrigger, getRightTrigger
|
||||
Ps3Controller : getLeftHori, getLeftVert, getRightHori, getRightVert, getLeftTrigger, getRightTrigger, getUp, getDown, getLeft, getRight, getFire1, getFire2(self):
|
||||
MySaitekController : getLeftHori,getLeftVert, getRightHori,getRightVert, getLeftTrigger,getRightTrigger
|
||||
MyThrustController : getLeftHori, getLeftVert, getRightHori, getRightVert, getLeftTrigger, getRightTrigger
|
||||
CSLController : getLeftHori,getLeftVert,getRightHori, getRightVert,getLeftTrigger,getRightTrigger,getFire1,getFire2
|
||||
my USB Joystick : getUp,getDown,getLeft,getRight,etLeftTrigger, getRightTrigger,getFire1, getFire2
|
||||
|
||||
|
||||
LICENCE : CC
|
||||
Sam Neurohack
|
||||
|
||||
'''
|
||||
|
||||
import math
|
||||
import redis
|
||||
import sys
|
||||
import weakref
|
||||
import struct
|
||||
import numpy as np
|
||||
from multiprocessing import Process, Queue, TimeoutError
|
||||
|
||||
is_py2 = sys.version[0] == '2'
|
||||
if is_py2:
|
||||
from OSC import OSCServer, OSCClient, OSCMessage
|
||||
#print ("Importing lj23 and OSC from libs...")
|
||||
else:
|
||||
from OSC3 import OSCServer, OSCClient, OSCMessage
|
||||
#print ("Importing lj23 and OSC3 from libs...")
|
||||
|
||||
|
||||
#redisIP = '127.0.0.1'
|
||||
#r = redis.StrictRedis(host=redisIP, port=6379, db=0)
|
||||
|
||||
ClientNumber = 0
|
||||
name = "noname"
|
||||
oscrun = True
|
||||
point_list = []
|
||||
layers = [[],[],[],[]]
|
||||
|
||||
fft3Groups = [-1,-1,-1,-1]
|
||||
|
||||
Dests = dict()
|
||||
|
||||
oscIPresol = "127.0.0.1"
|
||||
oscPORTresol = 7000
|
||||
|
||||
|
||||
'''
|
||||
|
||||
Laser "objects"
|
||||
|
||||
|
||||
set a name and convenient group of parameters for one or several point lists
|
||||
|
||||
RelativeObject is for point lists around 0,0 with builtin move/rotation.
|
||||
|
||||
How to init with object color, xpos,... :
|
||||
osciObj = lj.RelativeObject('osciObj', True, 255, [], white, red, green,blue,0 , False, centerX , centerY , 1 , Xrot , Yrot , Zrot)
|
||||
How to use in drawing functions : you're free to use 0, some or all of any laserobject attributes
|
||||
- draw one or several pointlists with 'A' laserobject color and 'B' laserobject xpos ypos ?
|
||||
- Change color of 'main' object and all other objects using it will change also
|
||||
how to change attribute :
|
||||
osciObj.resize = 2 or /pluginame/change 'OsciObj' 'resize' 2
|
||||
|
||||
'''
|
||||
|
||||
class RelativeObject:
|
||||
|
||||
kind = 'relative'
|
||||
counter = 0
|
||||
|
||||
def __init__(self, name, active, intensity, xy, color, red, green, blue, layer , closed, xpos , ypos , resize , rotx , roty , rotz):
|
||||
self.name = name
|
||||
self.active = active # True/False
|
||||
self.intensity = intensity
|
||||
self.xy = [] # Dots list
|
||||
self.color = color # RGB color in int
|
||||
self.red = red
|
||||
self.green = green
|
||||
self.blue = blue
|
||||
self.layer = layer
|
||||
self.closed = closed
|
||||
self.xpos = xpos
|
||||
self.ypos = ypos
|
||||
self.resize = resize
|
||||
self.rotx = rotx
|
||||
self.roty = roty
|
||||
self.rotz = rotz
|
||||
|
||||
RelativeObject.counter += 1
|
||||
#type(self).counter += 1
|
||||
|
||||
def __del__(self):
|
||||
RelativeObject.counter -= 1
|
||||
|
||||
|
||||
# Fixed Laser object : point list in 'pygame' space (top left = 0,0 / bottom right)
|
||||
class FixedObject:
|
||||
|
||||
kind = 'fixed'
|
||||
counter = 0
|
||||
|
||||
def __init__(self, name, intensity, active, xy, color, red, green, blue, layer , closed):
|
||||
self.name = name
|
||||
self.active = active # True/False
|
||||
self.intensity = intensity
|
||||
self.xy = []
|
||||
self.color = color
|
||||
self.red = red
|
||||
self.green = green
|
||||
self.blue = blue
|
||||
self.layer = layer
|
||||
self.closed = closed
|
||||
|
||||
FixedObject.counter += 1
|
||||
|
||||
def __del__(self):
|
||||
FixedObject.counter -= 1
|
||||
|
||||
'''
|
||||
|
||||
class IterDest(type):
|
||||
def __new__ (cls, name, bases, dct):
|
||||
dct['_instances'] = []
|
||||
return super().__new__(cls, name, bases, dct)
|
||||
|
||||
def __call__(cls, *args, **kwargs):
|
||||
instance = super().__call__(*args, **kwargs)
|
||||
cls._instances.append(instance)
|
||||
return instance
|
||||
|
||||
def __iter__(cls):
|
||||
return iter(cls._instances)
|
||||
|
||||
class DestObject():
|
||||
|
||||
# class Destinations(metaclass=IterDest):
|
||||
__metaclass__ = IterDest
|
||||
counter = 0
|
||||
def __init__(self, name, number, active, layer , scene, laser):
|
||||
self.name = name
|
||||
self.number = number
|
||||
self.active = active
|
||||
self.layer = layer
|
||||
self.scene = scene
|
||||
self.laser = laser
|
||||
|
||||
DestObject.counter += 1
|
||||
|
||||
def __del__(self):
|
||||
DestObject.counter -= 1
|
||||
'''
|
||||
class DestObject():
|
||||
|
||||
# class Destinations(metaclass=IterDest):
|
||||
_instances = set()
|
||||
counter = 0
|
||||
|
||||
def __init__(self, name, number, active, layer , scene, laser):
|
||||
self.name = name
|
||||
self.number = number
|
||||
self.active = active
|
||||
self.layer = layer
|
||||
self.scene = scene
|
||||
self.laser = laser
|
||||
self._instances.add(weakref.ref(self))
|
||||
DestObject.counter += 1
|
||||
|
||||
@classmethod
|
||||
def getinstances(cls):
|
||||
dead = set()
|
||||
for ref in cls._instances:
|
||||
obj = ref()
|
||||
if obj is not None:
|
||||
yield obj
|
||||
else:
|
||||
dead.add(ref)
|
||||
cls._instances -= dead
|
||||
|
||||
|
||||
def __del__(self):
|
||||
DestObject.counter -= 1
|
||||
|
||||
|
||||
|
||||
def Config(redIP,client,myname):
|
||||
global ClientNumber, name, redisIP, r
|
||||
|
||||
redisIP = redIP
|
||||
r = redis.StrictRedis(host=redisIP, port=6379, db=0)
|
||||
|
||||
# ClientNumber 255 are not drawing anything like artnet
|
||||
ClientNumber = client
|
||||
#print ("client configured",ClientNumber)
|
||||
name = myname
|
||||
print ("Plugin declare its name",name)
|
||||
#print layer
|
||||
return r
|
||||
|
||||
|
||||
def LjClient(client):
|
||||
global ClientNumber
|
||||
|
||||
ClientNumber = client
|
||||
|
||||
|
||||
|
||||
def Ljlayer(somelayer):
|
||||
global layer
|
||||
|
||||
layer = somelayer
|
||||
|
||||
|
||||
def fromRedis(n):
|
||||
|
||||
encoded = r.get(n)
|
||||
#print("")
|
||||
#print('fromredis key',n,":",encoded)
|
||||
h, w = struct.unpack('>II',encoded[:8])
|
||||
#print("fromredis array size",n,":",h,w)
|
||||
a = np.frombuffer(encoded, dtype=np.int16, offset=8).reshape(h,w)
|
||||
#print("fromredis array",n,":",a)
|
||||
return a
|
||||
|
||||
# Store Numpy array 'a' in Redis key 'n'
|
||||
# Write also in redis key 'a' numpy array, its 2 dimensions size : h time w values
|
||||
def toRedis(n,a):
|
||||
|
||||
#print("array.shape", a.shape, len(a.shape) )
|
||||
if len(a.shape) == 1:
|
||||
h = a.shape[0]
|
||||
w = 1
|
||||
else:
|
||||
h,w = a.shape
|
||||
#print("toredis", n,"h",h,"w",w,"a",a)
|
||||
shape = struct.pack('>II',h,w)
|
||||
|
||||
#shape = struct.pack('>II',len(a),1)
|
||||
#print("toredis",n,a)
|
||||
encoded = shape + a.tobytes()
|
||||
|
||||
# Store encoded data in Redis
|
||||
return r.set(n,encoded)
|
||||
|
||||
|
||||
#
|
||||
# OSC functions
|
||||
#
|
||||
|
||||
# OSC clients
|
||||
|
||||
def SendLJ(oscaddress,oscargs=''):
|
||||
|
||||
oscmsg = OSCMessage()
|
||||
oscmsg.setAddress(oscaddress)
|
||||
oscmsg.append(oscargs)
|
||||
|
||||
osclientlj = OSCClient()
|
||||
osclientlj.connect((redisIP, 8002))
|
||||
|
||||
print("lj23 in",name," sending OSC message : ", oscmsg, "to", redisIP, ":8002")
|
||||
try:
|
||||
osclientlj.sendto(oscmsg, (redisIP, 8002))
|
||||
oscmsg.clearData()
|
||||
except:
|
||||
print ('Connection to LJ refused : died ?')
|
||||
pass
|
||||
#time.sleep(0.001
|
||||
|
||||
|
||||
|
||||
# Resolume OSC Arena client.
|
||||
# sendresol(oscaddress, [arg1, arg2,...])
|
||||
# example : sendresol("/noteon",note)
|
||||
|
||||
def SendResol(oscaddress,oscargs):
|
||||
|
||||
oscmsg = OSCMessage()
|
||||
oscmsg.setAddress(oscaddress)
|
||||
oscmsg.append(oscargs)
|
||||
|
||||
osclientresol = OSCClient()
|
||||
osclientresol.connect((oscIPresol, oscPORTresol))
|
||||
|
||||
print("lj sending OSC message : ", oscmsg, "to Resolume", oscIPresol, ":", oscPORTresol)
|
||||
try:
|
||||
osclientresol.sendto(oscmsg, (oscIPresol, oscPORTresol))
|
||||
oscmsg.clearData()
|
||||
except:
|
||||
print ('Connection to Resolume refused : died ?')
|
||||
pass
|
||||
|
||||
|
||||
|
||||
|
||||
def WebStatus(message):
|
||||
SendLJ("/status", message)
|
||||
|
||||
|
||||
# Closing plugin messages to LJ
|
||||
def ClosePlugin():
|
||||
WebStatus(name+" Exiting")
|
||||
SendLJ("/"+name+"/start",0)
|
||||
|
||||
|
||||
|
||||
|
||||
# RAW OSC Frame available ?
|
||||
def OSCframe():
|
||||
# clear timed_out flag
|
||||
#print "oscframe"
|
||||
oscserver.timed_out = False
|
||||
# handle all pending requests then return
|
||||
while not oscserver.timed_out:
|
||||
oscserver.handle_request()
|
||||
|
||||
# Answer to LJ pings with /pong value
|
||||
def OSCping(path, tags, args, source):
|
||||
#def OSCping():
|
||||
print(name, "got /ping from LJ -> reply /pong", name)
|
||||
SendLJ("/pong",name)
|
||||
|
||||
# Properly close the system. Todo
|
||||
def OSCstop():
|
||||
oscserver.close()
|
||||
|
||||
|
||||
# /quit
|
||||
def OSCquit(path, tags, args, source):
|
||||
global oscrun
|
||||
|
||||
oscrun = False
|
||||
print('lj23 got /quit for',name)
|
||||
#WebStatus(name + " quit.")
|
||||
#SendLJ("/"+name+"/start",0)
|
||||
#print("Stopping OSC...")
|
||||
#OSCstop()
|
||||
#sys.exit()
|
||||
|
||||
|
||||
# default handler
|
||||
def OSChandler(path, tags, args, source):
|
||||
|
||||
oscaddress = ''.join(path.split("/"))
|
||||
print("Default OSC Handler in",name,": msg from Client : " + str(source[0]),)
|
||||
print("OSC address", path)
|
||||
if len(args) > 0:
|
||||
print("with args", args)
|
||||
|
||||
#oscIPout = str(source[0])
|
||||
#osclient.connect((oscIPout, oscPORTout))
|
||||
|
||||
|
||||
# for any laser object : /pluginame/obj objectname attribute value
|
||||
# like : /pluginname/obj 'fft' 'xpos' 100
|
||||
# attributes for all lj Objects: name, xy_list, c, layer
|
||||
# + for RelativeObjects : closed, xpos , ypos , resize , rotx , roty , rotz
|
||||
def OSCobj(path, tags, args, source):
|
||||
|
||||
obj = eval(args[0]+"."+ args[1])
|
||||
obj = args[2]
|
||||
|
||||
|
||||
def OSCvar(path, tags, args, source):
|
||||
|
||||
obj = eval(args[0])
|
||||
obj = args[1]
|
||||
|
||||
|
||||
def addOSCdefaults(server):
|
||||
global oscserver
|
||||
|
||||
oscserver = server
|
||||
oscserver.addMsgHandler( "default", OSChandler )
|
||||
oscserver.addMsgHandler( "/ping", OSCping)
|
||||
oscserver.addMsgHandler( "/quit", OSCquit)
|
||||
oscserver.addMsgHandler( "/"+ name + "/adddest", OSCadddest)
|
||||
oscserver.addMsgHandler( "/"+ name + "/deldest", OSCdeldest)
|
||||
oscserver.addMsgHandler( "/"+ name + "/obj", OSCobj)
|
||||
oscserver.addMsgHandler( "/"+ name + "/var", OSCvar)
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Drawing basic functions
|
||||
#
|
||||
|
||||
def rgb2int(r,g,b):
|
||||
return int('0x%02x%02x%02x' % (r,g,b),0)
|
||||
|
||||
|
||||
def LineTo(xy, c, layer ):
|
||||
|
||||
layers[layer].append((xy + (c,)))
|
||||
|
||||
def rLineTo(xy, c, layer , xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0):
|
||||
|
||||
layers[layer ].append((Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz) + (c,)))
|
||||
|
||||
|
||||
def Line(xy1, xy2, c, layer ):
|
||||
LineTo(xy1, 0, layer )
|
||||
LineTo(xy2, c , layer )
|
||||
|
||||
def rLine(xy1, xy2, c, layer , xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0):
|
||||
rLineTo(xy1, 0, layer )
|
||||
rLineTo(xy2, c , layer )
|
||||
|
||||
|
||||
def PolyLineOneColor(xy_list, c, layer , closed ):
|
||||
#print "--"
|
||||
#print "c",c
|
||||
#print "xy_list",xy_list
|
||||
#print "--"
|
||||
xy0 = None
|
||||
for xy in xy_list:
|
||||
if xy0 is None:
|
||||
xy0 = xy
|
||||
#print "xy0:",xy0
|
||||
LineTo(xy0,0, layer )
|
||||
LineTo(xy0,c, layer )
|
||||
else:
|
||||
#print "xy:",xy
|
||||
LineTo(xy,c, layer )
|
||||
if closed:
|
||||
LineTo(xy0,c, layer )
|
||||
|
||||
|
||||
|
||||
# Computing points coordinates for rPolyline function from 3D and around 0,0 to pygame coordinates
|
||||
def Pointransf(xy, xpos = 0, ypos =0, resize =1, rotx =0, roty =0 , rotz=0):
|
||||
|
||||
x = xy[0] * resize
|
||||
y = xy[1] * resize
|
||||
z = 0
|
||||
|
||||
rad = math.radians(rotx)
|
||||
cosaX = math.cos(rad)
|
||||
sinaX = math.sin(rad)
|
||||
|
||||
y2 = y
|
||||
y = y2 * cosaX - z * sinaX
|
||||
z = y2 * sinaX + z * cosaX
|
||||
|
||||
rad = math.radians(roty)
|
||||
cosaY = math.cos(rad)
|
||||
sinaY = math.sin(rad)
|
||||
|
||||
z2 = z
|
||||
z = z2 * cosaY - x * sinaY
|
||||
x = z2 * sinaY + x * cosaY
|
||||
|
||||
rad = math.radians(rotz)
|
||||
cosZ = math.cos(rad)
|
||||
sinZ = math.sin(rad)
|
||||
|
||||
x2 = x
|
||||
x = x2 * cosZ - y * sinZ
|
||||
y = x2 * sinZ + y * cosZ
|
||||
|
||||
#print xy, (x + xpos,y+ ypos)
|
||||
return (x + xpos,y+ ypos)
|
||||
'''
|
||||
to understand why it get negative Y
|
||||
|
||||
# 3D to 2D projection
|
||||
factor = 4 * gstt.cc[22] / ((gstt.cc[21] * 8) + z)
|
||||
print xy, (x * factor + xpos, - y * factor + ypos )
|
||||
return (x * factor + xpos, - y * factor + ypos )
|
||||
'''
|
||||
|
||||
def rLineTo(xy, c, layer , xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0):
|
||||
|
||||
layers[layer ].append((Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz) + (c,)))
|
||||
|
||||
|
||||
def rLine(xy1, xy2, c, layer , xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0):
|
||||
|
||||
LineTo(Pointransf(xy1, xpos, ypos, resize, rotx, roty, rotz),0, layer )
|
||||
LineTo(Pointransf(xy2, xpos, ypos, resize, rotx, roty, rotz),c, layer )
|
||||
|
||||
|
||||
|
||||
# Send 2D point list around 0,0 with 3D rotation resizing and reposition around xpos ypos
|
||||
#def rPolyLineOneColor(self, xy_list, c, layer , closed, xpos = 0, ypos =0, resize =1, rotx =0, roty =0 , rotz=0):
|
||||
def rPolyLineOneColor(xy_list, c, layer , closed, xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0):
|
||||
xy0 = None
|
||||
for xy in xy_list:
|
||||
if xy0 is None:
|
||||
xy0 = xy
|
||||
LineTo(Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz),0, layer )
|
||||
LineTo(Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz),c, layer )
|
||||
else:
|
||||
LineTo(Pointransf(xy, xpos, ypos, resize, rotx, roty, rotz),c, layer )
|
||||
if closed:
|
||||
LineTo(Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz),c, layer )
|
||||
|
||||
|
||||
def LineRGBTo(xy, red, green, blue, layer ):
|
||||
|
||||
LineTo(xy, int('0x%02x%02x%02x' % (red,green,blue),0), layer )
|
||||
|
||||
def LineRGB(xy1, xy2, red,green,blue, layer ):
|
||||
|
||||
LineTo(xy1, 0, layer )
|
||||
LineTo(xy2, int('0x%02x%02x%02x' % (red,green,blue),0) , layer )
|
||||
|
||||
|
||||
def PolyLineRGB(xy_list, red, green, blue, layer , closed ):
|
||||
|
||||
PolyLineOneColor(xy_list, int('0x%02x%02x%02x' % (red,green,blue),0), layer , closed )
|
||||
|
||||
def rPolyLineRGB(xy_list, red, green, blue, layer , closed, xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0):
|
||||
|
||||
rPolyLineOneColor(xy_list, int('0x%02x%02x%02x' % (red,green,blue),0), layer , closed, xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0)
|
||||
|
||||
|
||||
|
||||
def Lineslayer(layer):
|
||||
print("Stupido !! your code is to old : use Drawlayer() instead of LinesPL()")
|
||||
Drawlayer(layer )
|
||||
|
||||
|
||||
def Draw(layer ):
|
||||
#print '/pl/0/'+str(layer), str(layers[layer])
|
||||
if r.set('/pl/'+str(ClientNumber)+'/'+str(layer), str(layers[layer])) == True:
|
||||
#print '/pl/'+str(ClientNumber)+'/'+str(layer), str(layers[layer])
|
||||
layers[layer] = []
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def Resetlayer(self, layer):
|
||||
layers[layer] = []
|
||||
|
||||
|
||||
#
|
||||
# "Destinations" management for layers
|
||||
#
|
||||
|
||||
|
||||
# Add a destination for a given layer
|
||||
def Addest(layer, scene, laser):
|
||||
|
||||
print (name,'adding',layer,scene,laser,'?')
|
||||
if Findest(layer, scene, laser) == -1:
|
||||
newdest = DestsObjects.counter + 1
|
||||
Dest0 = lj.DestObject(str(newdest), newdest, True, layer , scene, laser)
|
||||
print("New destination added with number", newdest)
|
||||
else:
|
||||
print("Destination already existed")
|
||||
|
||||
|
||||
# OSC add a destination for a given layer
|
||||
# /pluginame/dest layer, scene, laser
|
||||
def OSCadddest(path, tags, args, source):
|
||||
|
||||
Addests(int(args[0]),int(args[1]),int(args[2]))
|
||||
|
||||
|
||||
# Find layer destination with its parameters in destinations dictionnary
|
||||
def Findest(layer, scene, laser):
|
||||
|
||||
print(name, 'searching layer,scene,laser',layer,scene,laser)
|
||||
for item in DestObjects.getinstances():
|
||||
#print(item)
|
||||
if item.layer == layer and item.scene == scene and item.laser == laser:
|
||||
#Dests.append(item[0])
|
||||
print('found number',item.number)
|
||||
return item.number
|
||||
else:
|
||||
print('no destination found')
|
||||
return -1
|
||||
'''
|
||||
#Dests = list()
|
||||
allDests = Dests.items()
|
||||
for item in allDests:
|
||||
print(item)
|
||||
if item[1] == layer and item[2] == scene and item[3] == laser:
|
||||
#Dests.append(item[0])
|
||||
return Dests[item[0]]
|
||||
else:
|
||||
return -1
|
||||
'''
|
||||
|
||||
# Find and remove a layer destination with its parameters in destinations dictionnary
|
||||
def Deldest(layer, scene, laser):
|
||||
|
||||
Destnumber = Findest(layer, scene, laser)
|
||||
print(name,'deleting Destination layer, scene, laser', layer,scene, laser)
|
||||
|
||||
if Destnumber != -1:
|
||||
print('found DestObject', Destnumber)
|
||||
delattr(DestObjects, str(Destnumber))
|
||||
print("Destination", Destnumber,"was removed")
|
||||
else:
|
||||
print("Destination was not found")
|
||||
|
||||
|
||||
# OSC Delete a destination for a given layer
|
||||
# /pluginame/deldests layer, scene, laser
|
||||
def OSCdeldest(path, tags, args, source):
|
||||
|
||||
Deldests(args[0],args[1],args[2])
|
||||
|
||||
|
||||
# Replace Drawlayer if Destinations paradigm is implemented in plugin code
|
||||
def DrawDests():
|
||||
|
||||
# Objects style
|
||||
|
||||
#print("DrawDest")
|
||||
|
||||
for destination in DestObject.getinstances():
|
||||
#print (destination.name, destination.number, destination.active, destination.layer, destination.scene, destination.laser, layers[destination.layer] )
|
||||
|
||||
#print(Dests[str(destination)])
|
||||
#print('/pl/'+str(Dests[str(destination)]["scene"])+'/'+str(Dests[str(destination)]["laser"]), ":", str(layers[Dests[str(destination)]["PL"]]))
|
||||
#print(len(layers[destination.layer]))
|
||||
if destination.active == True:
|
||||
if r.set('/pl/'+str(destination.scene)+'/'+str(destination.laser), str(layers[destination.layer])) == True:
|
||||
#print ('layer', destination.layer, '/pl/'+str(destination.scene)+'/'+str(destination.laser), str(layers[destination.layer]))
|
||||
pass
|
||||
else:
|
||||
print('Redis key modification failed')
|
||||
|
||||
# Maybe one layer can be sent to multiple destination so they are all reset *after* all sending.
|
||||
for layerss in range(4):
|
||||
|
||||
layers[layerss] = []
|
||||
|
||||
'''
|
||||
# Dictionnary style
|
||||
|
||||
#print(Dests)
|
||||
for destination in range(len(Dests)):
|
||||
#print(Dests[str(destination)])
|
||||
#print('/pl/'+str(Dests[str(destination)]["scene"])+'/'+str(Dests[str(destination)]["laser"]), ":", str(layers[Dests[str(destination)]["layer"]]))
|
||||
if r.set('/pl/'+str(Dests[str(destination)]["scene"])+'/'+str(Dests[str(destination)]["laser"]), str(layers[Dests[str(destination)]["layer"]])) == True:
|
||||
#print '/pl/'+str(ClientNumber)+'/'+str(layer), str(layers[layer])
|
||||
pass
|
||||
else:
|
||||
print('Redis key modification failed')
|
||||
|
||||
# Maybe one layer can be sent to multiple destination so they are all reset *after* all sending.
|
||||
for destination in range(len(Dests)):
|
||||
|
||||
layers[Dests[str(destination)]["layer"]] = []
|
||||
'''
|
||||
'''
|
||||
scenes = 4
|
||||
|
||||
def DrawDestslayer(layer):
|
||||
|
||||
for scene in range(scenes):
|
||||
|
||||
if Dests[laser]["scene"] != -1:
|
||||
if r.set('/pl/'+str(Dests[laser]["scene"])+'/'+str(Dests[laser]["laser"]), str(layers[Dests[laser]["laser"]])) == True:
|
||||
if r.set('/pl/'+str(ClientNumber)+'/'+str(layer), str(layers[layer])) == True:
|
||||
#print '/pl/'+str(ClientNumber)+'/'+str(layer), str(layers[layer])
|
||||
layers[Dests[laser]["laser"]] = []
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
'''
|
||||
|
||||
#
|
||||
# High level drawing functions
|
||||
#
|
||||
|
||||
|
||||
# Font1
|
||||
|
||||
|
||||
ASCII_GRAPHICS = [
|
||||
|
||||
#implementé
|
||||
|
||||
[(-50,30), (-30,-30), (30,-30), (10,30), (-50,30)], # 0
|
||||
[(-20,30), (0,-30), (-20,30)], # 1
|
||||
[(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], # 2
|
||||
[(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], # 3
|
||||
[(30,10), (-30,10), (0,-30), (0,30)], # 4
|
||||
[(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], # 5
|
||||
[(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], # 6
|
||||
[(-30,-30), (30,-30), (-30,30)], # 7
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30), (-30,0), (30,0)], # 8
|
||||
[(30,0), (-30,0), (-30,-10), (0,-30), (30,-30), (30,10), (0,30), (-30,30)], # 9
|
||||
|
||||
# A implementer
|
||||
[(-30,10), (30,-10), (30,10), (0,30), (-30,10), (-30,-10), (0,-30), (30,-10)], #:
|
||||
[(-30,-10), (0,-30), (0,30)], [(-30,30), (30,30)], # ;
|
||||
[(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], # <
|
||||
[(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], # =
|
||||
[(30,10), (-30,10), (0,-30), (0,30)], # >
|
||||
[(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], # ?
|
||||
[(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], # @
|
||||
|
||||
# Implementé
|
||||
|
||||
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (30,0), (-30,0)], # A
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (30,0), (-30,0)], # A
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30), (-30,0), (30,0)], # B
|
||||
[(30,30), (-30,30), (-30,-30), (30,-30)], # C
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30)], # D
|
||||
[(30,30), (-30,30), (-30,-0), (30,0), (-30,0), (-30,-30), (30,-30)], # E
|
||||
[(-30,30), (-30,-0), (30,0), (-30,0), (-30,-30), (30,-30)], # F
|
||||
[(0,0), (30,0), (30,30), (-30,30), (-30,-30),(30,-30)], # G
|
||||
[(-30,-30), (-30,30), (-30,0), (30,0), (30,30), (30,-30)], # H
|
||||
[(0,30), (0,-30)], # I
|
||||
[(-30,30), (0,-30), (0,-30), (-30,-30), (30,-30)], # J
|
||||
[(-30,-30), (-30,30), (-30,0), (30,-30), (-30,0), (30,30)], # K
|
||||
[(30,30), (-30,30), (-30,-30)], # L
|
||||
[(-30,30), (-30,-30), (0,0), (30,-30), (30,30)], # M
|
||||
[(-30,30), (-30,-30), (30,30), (30,-30)], # N
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30)], # O
|
||||
[(-30,0), (30,0), (30,-30), (-30,-30), (-30,30)], # P
|
||||
[(30,30), (30,-30), (-30,-30), (-30,30), (30,30),(35,35)], # Q
|
||||
[(-30,30), (-30,-30), (30,-30), (30,0), (-30,0), (30,30)], # R
|
||||
[(30,-30), (-30,-30), (-30,0), (30,0), (30,30), (-30,30)], # S
|
||||
[(0,30), (0,-30), (-30,-30), (30,-30)], # T
|
||||
[(-30,-30), (-30,30), (30,30), (30,-30)], # U
|
||||
[(-30,-30), (0,30), (30,-30)], # V
|
||||
[(-30,-30), (-30,30), (0,0), (30,30), (30,-30)], # W
|
||||
[(-30,30), (30,-30), (-30,-30), (30,30)], # X
|
||||
[(0,30), (0,0), (30,-30), (0,0), (-30,-30)], # Y
|
||||
[(30,30), (-30,30), (30,-30), (-30,-30)], # Z
|
||||
|
||||
# A implementer
|
||||
|
||||
[(-30,-10), (0,-30), (0,30)], [(-30,30), (30,30)], # [
|
||||
[(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], # \
|
||||
[(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], # ]
|
||||
[(30,10), (-30,10), (0,-30), (0,30)], # ^
|
||||
[(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], # _
|
||||
[(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], # `
|
||||
|
||||
# Implementé
|
||||
|
||||
[(-20,20), (-20,-20), (20,-20), (20,20), (20,0), (-20,0)], # a
|
||||
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20), (-20,0), (20,0)], # b
|
||||
[(20,20), (-20,20), (-20,-20), (20,-20)], # c
|
||||
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20)], # d
|
||||
[(20,20), (-20,20), (-20,-0), (20,0), (-20,0), (-20,-20), (20,-20)], # e
|
||||
[(-20,20), (-20,-0), (20,0), (-20,0), (-20,-20), (20,-20)], # f
|
||||
[(0,0), (20,0), (20,20), (-20,20), (-20,-20),(20,-20)], # g
|
||||
[(-20,-20), (-20,20), (-20,0), (20,0), (20,20), (20,-20)], # h
|
||||
[(0,20), (0,-20)], # i
|
||||
[(-20,20), (0,-20), (0,-20), (-20,-20), (20,-20)], # j
|
||||
[(-20,-20), (-20,20), (-20,0), (20,-20), (-20,0), (20,20)], # k
|
||||
[(20,20), (-20,20), (-20,-20)], # l
|
||||
[(-20,20), (-20,-20), (0,0), (20,-20), (20,20)], # m
|
||||
[(-20,20), (-20,-20), (20,20), (20,-20)], # n
|
||||
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20)], # o
|
||||
[(-20,0), (20,0), (20,-20), (-20,-20), (-20,20)], # p
|
||||
[(20,20), (20,-20), (-20,-20), (-20,20), (20,20),(25,25)], # q
|
||||
[(-20,20), (-20,-20), (20,-20), (20,0), (-20,0), (20,20)], # r
|
||||
[(20,-20), (-20,-20), (-20,0), (20,0), (20,20), (-20,20)], # s
|
||||
[(0,20), (0,-20), (-20,-20), (20,-20)], # t
|
||||
[(-20,-20), (-20,20), (20,20), (20,-20)], # u
|
||||
[(-20,-20), (0,20), (20,-20)], # v
|
||||
[(-20,-20), (-20,20), (0,0), (20,20), (20,-20)], # w
|
||||
[(-20,20), (20,-20)], [(-20,-20), (20,20)], # x
|
||||
[(0,20), (0,0), (20,-20), (0,0), (-20,-20)], # y
|
||||
[(20,20), (-20,20), (20,-20), (-20,-20)], # z
|
||||
|
||||
[(-2,15), (2,15)] # Point a la place de {
|
||||
]
|
||||
|
||||
|
||||
def DigitsDots(number,color):
|
||||
dots =[]
|
||||
for dot in ASCII_GRAPHICS[number]:
|
||||
#print dot
|
||||
dots.append((gstt.xy_center[0]+dot[0],gstt.xy_center[1]+dot[1],color))
|
||||
#self.point_list.append((xy + (c,)))
|
||||
return dots
|
||||
|
||||
def CharDots(char,color):
|
||||
|
||||
dots =[]
|
||||
for dot in ASCII_GRAPHICS[ord(char)-46]:
|
||||
dots.append((dot[0],dot[1],color))
|
||||
return dots
|
||||
|
||||
def Text(message,c, layer, xpos, ypos, resize, rotx, roty, rotz):
|
||||
|
||||
dots =[]
|
||||
|
||||
l = len(message)
|
||||
i= 0
|
||||
#print()
|
||||
# print (message)
|
||||
|
||||
for ch in message:
|
||||
|
||||
#print ""
|
||||
# texte centre en x automatiquement selon le nombre de lettres l
|
||||
x_offset = 26 * (- (0.9*l) + 3*i)
|
||||
# Digits
|
||||
if ord(ch)<58:
|
||||
char_layer_list = ASCII_GRAPHICS[ord(ch) - 48]
|
||||
else:
|
||||
char_layer_list = ASCII_GRAPHICS[ord(ch) - 46]
|
||||
|
||||
char_draw = []
|
||||
#dots.append((char_layer_list[0][0] + x_offset,char_layer_list[0][1],0))
|
||||
|
||||
for xy in char_layer_list:
|
||||
char_draw.append((xy[0] + x_offset,xy[1],c))
|
||||
i +=1
|
||||
#print ch,char_layer_list,char_draw
|
||||
rPolyLineOneColor(char_draw, c, layer , False, xpos, ypos, resize, rotx, roty, rotz)
|
||||
#dots.append(char_draw)
|
||||
|
||||
def TextRGB(message,c, layer, xpos, ypos, resize, rotx, roty, rotz):
|
||||
|
||||
Text(message,int('0x%02x%02x%02x' % (red,green,blue),0), layer, xpos, ypos, resize, rotx, roty, rotz)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
657
libs/lj3.py
Normal file
657
libs/lj3.py
Normal file
|
|
@ -0,0 +1,657 @@
|
|||
|
||||
'''
|
||||
|
||||
lj3 v0.7.5 for LJ v0.8+
|
||||
|
||||
Some LJ functions useful for python clients
|
||||
|
||||
OSC functions commented, waiting working on OSC in python3
|
||||
|
||||
Config(redisIP, client number,name)
|
||||
PolyLineOneColor
|
||||
rPolyLineOneColor
|
||||
|
||||
Text(word, color, PL, xpos, ypos, resize, rotx, roty, rotz) : Display a word
|
||||
SendLJ(adress,message) : LJ remote control. See commands.py
|
||||
WebStatus(message) : display message on webui
|
||||
DrawPL(point list number) : once you stacked all wanted elements, like 2 polylines, send them to lasers.
|
||||
rgb2int(r,g,b)
|
||||
LjClient(client): Change Client number in redis keys
|
||||
LjPl(pl): Change pl number in redis keys = laser target.
|
||||
ClosePlugin(name): Send UI closing info of given plugin
|
||||
|
||||
OSCstart(): Start the OSC system.
|
||||
OSCframe(): Handle incoming OSC message. Calling the right callback
|
||||
OSCstop(): Properly close the OSC system
|
||||
OSCping(): Answer to LJ pings by sending /pong name
|
||||
OSCquit(): Exit calling script using name in terminal
|
||||
|
||||
setup_controls(joystick)
|
||||
|
||||
XboxController : getLeftHori, getLeftVert, getRightHori, getRightVert, getLeftTrigger, getRightTrigger
|
||||
Ps3Controller : getLeftHori, getLeftVert, getRightHori, getRightVert, getLeftTrigger, getRightTrigger, getUp, getDown, getLeft, getRight, getFire1, getFire2(self):
|
||||
MySaitekController : getLeftHori,getLeftVert, getRightHori,getRightVert, getLeftTrigger,getRightTrigger
|
||||
MyThrustController : getLeftHori, getLeftVert, getRightHori, getRightVert, getLeftTrigger, getRightTrigger
|
||||
CSLController : getLeftHori,getLeftVert,getRightHori, getRightVert,getLeftTrigger,getRightTrigger,getFire1,getFire2
|
||||
my USB Joystick : getUp,getDown,getLeft,getRight,etLeftTrigger, getRightTrigger,getFire1, getFire2
|
||||
|
||||
|
||||
LICENCE : CC
|
||||
Sam Neurohack
|
||||
|
||||
'''
|
||||
|
||||
import math
|
||||
import redis
|
||||
|
||||
# Import needed modules from osc4py3
|
||||
from osc4py3.as_eventloop import *
|
||||
from osc4py3 import oscbuildparse
|
||||
#from osc4py3 import oscmethod as osm
|
||||
from osc4py3.oscmethod import *
|
||||
|
||||
|
||||
#redisIP = '127.0.0.1'
|
||||
#r = redis.StrictRedis(host=redisIP, port=6379, db=0)
|
||||
|
||||
print('Importing lj3 from libs...')
|
||||
ClientNumber = 0
|
||||
name = "noname"
|
||||
point_list = []
|
||||
pl = [[],[],[],[]]
|
||||
|
||||
#
|
||||
# OSC interaction with LJ
|
||||
#
|
||||
|
||||
def OSCstart():
|
||||
# Start the system.
|
||||
osc_startup()
|
||||
#osc_udp_client(redisIP, 8002, "LJ 8002")
|
||||
|
||||
def OSCframe():
|
||||
#print("OSCprocess")
|
||||
osc_process()
|
||||
|
||||
# Properly close the system. Todo
|
||||
def OSCstop():
|
||||
osc_terminate()
|
||||
|
||||
|
||||
def SendLJ(oscaddress,oscargs=''):
|
||||
|
||||
try:
|
||||
msg = oscbuildparse.OSCMessage(oscaddress, None, [oscargs])
|
||||
# print(msg)
|
||||
print("lj3 sending OSC message to", redisIP, ":8002")
|
||||
osc_send(msg, "LJ 8002")
|
||||
OSCframe()
|
||||
|
||||
except:
|
||||
print (oscaddress,'Connection to LJ refused : died ?')
|
||||
pass
|
||||
|
||||
def WebStatus(message):
|
||||
SendLJ("/status", message)
|
||||
|
||||
|
||||
# Answer to LJ /ping 1 with /pong name
|
||||
def OSCping(value):
|
||||
print(name,"got /ping 1 from LJ -> reply /pong", name)
|
||||
SendLJ("/pong",name)
|
||||
|
||||
|
||||
# Closing plugin messages to LJ
|
||||
def ClosePlugin():
|
||||
WebStatus(name+" Exit")
|
||||
SendLJ("/"+name+"/start",0)
|
||||
print("Stopping OSC...")
|
||||
OSCstop()
|
||||
|
||||
'''
|
||||
# /quit
|
||||
def OSCquit():
|
||||
|
||||
WebStatus(name + " quit.")
|
||||
SendLJ("/"+name+"/start",0)
|
||||
print("Stopping OSC...")
|
||||
OSCstop()
|
||||
sys.exit()
|
||||
'''
|
||||
'''
|
||||
def handlerfunction(s, x, y):
|
||||
# Will receive message data unpacked in s, x, y
|
||||
pass
|
||||
|
||||
def handlerfunction2(address, s, x, y):
|
||||
# Will receive message address, and message data flattened in s, x, y
|
||||
pass
|
||||
|
||||
# Make server channels to receive packets.
|
||||
osc_udp_server("127.0.0.1", 3721, "localhost")
|
||||
osc_udp_server("0.0.0.0", 3724, "anotherserver")
|
||||
'''
|
||||
|
||||
|
||||
|
||||
ASCII_GRAPHICS = [
|
||||
|
||||
# caracteres corrects
|
||||
|
||||
[(-50,30), (-30,-30), (30,-30), (10,30), (-50,30)], #0
|
||||
[(-20,30), (0,-30), (-20,30)], #1
|
||||
[(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], #2
|
||||
[(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], #3
|
||||
[(30,10), (-30,10), (0,-30), (0,30)], #4
|
||||
[(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], #5
|
||||
[(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], #6
|
||||
[(-30,-30), (30,-30), (-30,30)], #7
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30), (-30,0), (30,0)], #8
|
||||
[(30,0), (-30,0), (-30,-10), (0,-30), (30,-30), (30,10), (0,30), (-30,30)], #9
|
||||
|
||||
# caracteres a implementer
|
||||
[(-30,10), (30,-10), (30,10), (0,30), (-30,10), (-30,-10), (0,-30), (30,-10)], #:
|
||||
[(-30,-10), (0,-30), (0,30)], [(-30,30), (30,30)], #;
|
||||
[(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], #<
|
||||
[(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], #=
|
||||
[(30,10), (-30,10), (0,-30), (0,30)], #>
|
||||
[(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], #?
|
||||
[(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], #@
|
||||
|
||||
# Caracteres corrects
|
||||
|
||||
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (30,0), (-30,0)], #A
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (30,0), (-30,0)], #A
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30), (-30,0), (30,0)], #B
|
||||
[(30,30), (-30,30), (-30,-30), (30,-30)], #C
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30)], #D
|
||||
[(30,30), (-30,30), (-30,-0), (30,0), (-30,0), (-30,-30), (30,-30)], #E
|
||||
[(-30,30), (-30,-0), (30,0), (-30,0), (-30,-30), (30,-30)], #F
|
||||
[(0,0), (30,0), (30,30), (-30,30), (-30,-30),(30,-30)], #G
|
||||
[(-30,-30), (-30,30), (-30,0), (30,0), (30,30), (30,-30)], #H
|
||||
[(0,30), (0,-30)], #I
|
||||
[(-30,30), (0,-30), (0,-30), (-30,-30), (30,-30)], #J
|
||||
[(-30,-30), (-30,30), (-30,0), (30,-30), (-30,0), (30,30)], #K
|
||||
[(30,30), (-30,30), (-30,-30)], #L
|
||||
[(-30,30), (-30,-30), (0,0), (30,-30), (30,30)], #M
|
||||
[(-30,30), (-30,-30), (30,30), (30,-30)], #N
|
||||
[(-30,30), (-30,-30), (30,-30), (30,30), (-30,30)], #O
|
||||
[(-30,0), (30,0), (30,-30), (-30,-30), (-30,30)], #P
|
||||
[(30,30), (30,-30), (-30,-30), (-30,30), (30,30),(35,35)], #Q
|
||||
[(-30,30), (-30,-30), (30,-30), (30,0), (-30,0), (30,30)], #R
|
||||
[(30,-30), (-30,-30), (-30,0), (30,0), (30,30), (-30,30)], #S
|
||||
[(0,30), (0,-30), (-30,-30), (30,-30)], #T
|
||||
[(-30,-30), (-30,30), (30,30), (30,-30)], #U
|
||||
[(-30,-30), (0,30), (30,-30)], #V
|
||||
[(-30,-30), (-30,30), (0,0), (30,30), (30,-30)], #W
|
||||
[(-30,30), (30,-30)], [(-30,-30), (30,30)], #X
|
||||
[(0,30), (0,0), (30,-30), (0,0), (-30,-30)], #Y
|
||||
[(30,30), (-30,30), (30,-30), (-30,-30)], #Z
|
||||
|
||||
# A implementer
|
||||
|
||||
[(-30,-10), (0,-30), (0,30)], [(-30,30), (30,30)], #[
|
||||
[(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], #\
|
||||
[(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], #]
|
||||
[(30,10), (-30,10), (0,-30), (0,30)], #^
|
||||
[(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], #_
|
||||
[(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], #`
|
||||
|
||||
# Implementé
|
||||
|
||||
[(-20,20), (-20,-20), (20,-20), (20,20), (20,0), (-20,0)], #a
|
||||
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20), (-20,0), (20,0)], #b
|
||||
[(20,20), (-20,20), (-20,-20), (20,-20)], #c
|
||||
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20)], #d
|
||||
[(20,20), (-20,20), (-20,-0), (20,0), (-20,0), (-20,-20), (20,-20)], #e
|
||||
[(-20,20), (-20,-0), (20,0), (-20,0), (-20,-20), (20,-20)], #f
|
||||
[(0,0), (20,0), (20,20), (-20,20), (-20,-20),(20,-20)], #g
|
||||
[(-20,-20), (-20,20), (-20,0), (20,0), (20,20), (20,-20)], #H
|
||||
[(0,20), (0,-20)], #I
|
||||
[(-20,20), (0,-20), (0,-20), (-20,-20), (20,-20)], #J
|
||||
[(-20,-20), (-20,20), (-20,0), (20,-20), (-20,0), (20,20)], #K
|
||||
[(20,20), (-20,20), (-20,-20)], #L
|
||||
[(-20,20), (-20,-20), (0,0), (20,-20), (20,20)], #M
|
||||
[(-20,20), (-20,-20), (20,20), (20,-20)], #N
|
||||
[(-20,20), (-20,-20), (20,-20), (20,20), (-20,20)], #O
|
||||
[(-20,0), (20,0), (20,-20), (-20,-20), (-20,20)], #P
|
||||
[(20,20), (20,-20), (-20,-20), (-20,20), (20,20),(25,25)], #Q
|
||||
[(-20,20), (-20,-20), (20,-20), (20,0), (-20,0), (20,20)], #R
|
||||
[(20,-20), (-20,-20), (-20,0), (20,0), (20,20), (-20,20)], #S
|
||||
[(0,20), (0,-20), (-20,-20), (20,-20)], #T
|
||||
[(-20,-20), (-20,20), (20,20), (20,-20)], #U
|
||||
[(-20,-20), (0,20), (20,-20)], #V
|
||||
[(-20,-20), (-20,20), (0,0), (20,20), (20,-20)], #W
|
||||
[(-20,20), (20,-20)], [(-20,-20), (20,20)], #X
|
||||
[(0,20), (0,0), (20,-20), (0,0), (-20,-20)], #Y
|
||||
[(20,20), (-20,20), (20,-20), (-20,-20)], #Z
|
||||
|
||||
[(-2,15), (2,15)] # Point a la place de {
|
||||
]
|
||||
|
||||
def rgb2int(r,g,b):
|
||||
return int('0x%02x%02x%02x' % (r,g,b),0)
|
||||
|
||||
|
||||
def Config(redisIP,client,myname):
|
||||
global ClientNumber, r, name
|
||||
|
||||
name = myname
|
||||
print ("lj3 got a name to use :", name)
|
||||
r = redis.StrictRedis(host=redisIP, port=6379, db=0)
|
||||
ClientNumber = client
|
||||
osc_udp_client(redisIP, 8002, "LJ 8002")
|
||||
return r
|
||||
|
||||
|
||||
def LjClient(client):
|
||||
global ClientNumber
|
||||
|
||||
ClientNumber = client
|
||||
|
||||
def LjPl(pl):
|
||||
global PL
|
||||
|
||||
PL = pl
|
||||
|
||||
|
||||
def LineTo(xy, c, PL):
|
||||
|
||||
pl[PL].append((xy + (c,)))
|
||||
|
||||
def Line(xy1, xy2, c, PL):
|
||||
LineTo(xy1, 0, PL)
|
||||
LineTo(xy2, c , PL)
|
||||
|
||||
|
||||
def PolyLineOneColor(xy_list, c, PL , closed ):
|
||||
#print "--"
|
||||
#print "c",c
|
||||
#print "xy_list",xy_list
|
||||
#print "--"
|
||||
xy0 = None
|
||||
for xy in xy_list:
|
||||
if xy0 is None:
|
||||
xy0 = xy
|
||||
#print "xy0:",xy0
|
||||
LineTo(xy0,0, PL)
|
||||
LineTo(xy0,c, PL)
|
||||
else:
|
||||
#print "xy:",xy
|
||||
LineTo(xy,c, PL)
|
||||
if closed:
|
||||
LineTo(xy0,c, PL)
|
||||
|
||||
|
||||
# Computing points coordinates for rPolyline function from 3D and around 0,0 to pygame coordinates
|
||||
def Pointransf(xy, xpos = 0, ypos =0, resize =1, rotx =0, roty =0 , rotz=0):
|
||||
|
||||
x = xy[0] * resize
|
||||
y = xy[1] * resize
|
||||
z = 0
|
||||
|
||||
rad = rotx * math.pi / 180
|
||||
cosaX = math.cos(rad)
|
||||
sinaX = math.sin(rad)
|
||||
|
||||
y2 = y
|
||||
y = y2 * cosaX - z * sinaX
|
||||
z = y2 * sinaX + z * cosaX
|
||||
|
||||
rad = roty * math.pi / 180
|
||||
cosaY = math.cos(rad)
|
||||
sinaY = math.sin(rad)
|
||||
|
||||
z2 = z
|
||||
z = z2 * cosaY - x * sinaY
|
||||
x = z2 * sinaY + x * cosaY
|
||||
|
||||
rad = rotz * math.pi / 180
|
||||
cosZ = math.cos(rad)
|
||||
sinZ = math.sin(rad)
|
||||
|
||||
x2 = x
|
||||
x = x2 * cosZ - y * sinZ
|
||||
y = x2 * sinZ + y * cosZ
|
||||
|
||||
#print xy, (x + xpos,y+ ypos)
|
||||
return (x + xpos,y+ ypos)
|
||||
'''
|
||||
to understand why it get negative Y
|
||||
|
||||
# 3D to 2D projection
|
||||
factor = 4 * gstt.cc[22] / ((gstt.cc[21] * 8) + z)
|
||||
print xy, (x * factor + xpos, - y * factor + ypos )
|
||||
return (x * factor + xpos, - y * factor + ypos )
|
||||
'''
|
||||
|
||||
# Send 2D point list around 0,0 with 3D rotation resizing and reposition around xpos ypos
|
||||
#def rPolyLineOneColor(self, xy_list, c, PL , closed, xpos = 0, ypos =0, resize =1, rotx =0, roty =0 , rotz=0):
|
||||
def rPolyLineOneColor(xy_list, c, PL , closed, xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0):
|
||||
xy0 = None
|
||||
for xy in xy_list:
|
||||
if xy0 is None:
|
||||
xy0 = xy
|
||||
LineTo(Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz),0, PL)
|
||||
LineTo(Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz),c, PL)
|
||||
else:
|
||||
LineTo(Pointransf(xy, xpos, ypos, resize, rotx, roty, rotz),c, PL)
|
||||
if closed:
|
||||
LineTo(Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz),c, PL)
|
||||
|
||||
|
||||
def LinesPL(PL):
|
||||
print ("Stupido !! your code is to old : use DrawPL() instead of LinesPL()")
|
||||
DrawPL(PL)
|
||||
|
||||
def DrawPL(PL):
|
||||
#print '/pl/0/'+str(PL), str(pl[PL])
|
||||
if r.set('/pl/'+str(ClientNumber)+'/'+str(PL), str(pl[PL])) == True:
|
||||
pl[PL] = []
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def ResetPL(self, PL):
|
||||
pl[PL] = []
|
||||
|
||||
|
||||
def DigitsDots(number,color):
|
||||
dots =[]
|
||||
for dot in ASCII_GRAPHICS[number]:
|
||||
#print dot
|
||||
dots.append((gstt.xy_center[0]+dot[0],gstt.xy_center[1]+dot[1],color))
|
||||
#self.point_list.append((xy + (c,)))
|
||||
return dots
|
||||
|
||||
|
||||
def CharDots(char,color):
|
||||
|
||||
dots =[]
|
||||
for dot in ASCII_GRAPHICS[ord(char)-46]:
|
||||
dots.append((dot[0],dot[1],color))
|
||||
return dots
|
||||
|
||||
|
||||
def Text(message,c, PL, xpos, ypos, resize, rotx, roty, rotz):
|
||||
|
||||
dots =[]
|
||||
|
||||
l = len(message)
|
||||
i= 0
|
||||
#print message
|
||||
|
||||
for ch in message:
|
||||
|
||||
#print ""
|
||||
# texte centre en x automatiquement selon le nombre de lettres l
|
||||
x_offset = 26 * (- (0.9*l) + 3*i)
|
||||
#print i,x_offset
|
||||
# if digit
|
||||
if ord(ch)<58:
|
||||
char_pl_list = ASCII_GRAPHICS[ord(ch) - 48]
|
||||
else:
|
||||
char_pl_list = ASCII_GRAPHICS[ord(ch) - 46 ]
|
||||
|
||||
char_draw = []
|
||||
#dots.append((char_pl_list[0][0] + x_offset,char_pl_list[0][1],0))
|
||||
|
||||
for xy in char_pl_list:
|
||||
char_draw.append((xy[0] + x_offset,xy[1],c))
|
||||
i +=1
|
||||
#print ch,char_pl_list,char_draw
|
||||
rPolyLineOneColor(char_draw, c, PL , False, xpos, ypos, resize, rotx, roty, rotz)
|
||||
#print ("laser",PL,"message",message)
|
||||
#dots.append(char_draw)
|
||||
|
||||
|
||||
|
||||
import re
|
||||
|
||||
def setup_controls(joystick):
|
||||
"""
|
||||
Joystick wrapper.
|
||||
"""
|
||||
if re.search('playstation', joystick.get_name(), re.I):
|
||||
return Ps3Controller(joystick)
|
||||
|
||||
elif re.search('X-box', joystick.get_name(), re.I):
|
||||
return XboxController(joystick)
|
||||
|
||||
elif re.search('Saitek', joystick.get_name(), re.I):
|
||||
return MySaitekController(joystick)
|
||||
|
||||
elif re.search('Thrustmaster dual analog 3.2', joystick.get_name(), re.I):
|
||||
return MyThrustController(joystick)
|
||||
|
||||
elif re.search('2n1 USB', joystick.get_name(), re.I):
|
||||
return CSLController(joystick)
|
||||
|
||||
elif re.search('Joystick', joystick.get_name(), re.I):
|
||||
return USBController(joystick)
|
||||
|
||||
return Controller(joystick)
|
||||
|
||||
class Controller(object):
|
||||
|
||||
def __init__(self, joystick):
|
||||
"""Pass a PyGame joystick instance."""
|
||||
self.js = joystick
|
||||
|
||||
def getLeftHori(self):
|
||||
return self.js.get_axis(2)
|
||||
|
||||
def getLeftVert(self):
|
||||
return self.js.get_axis(3)
|
||||
|
||||
def getRightHori(self):
|
||||
return self.js.get_axis(0)
|
||||
|
||||
def getRightVert(self):
|
||||
return self.js.get_axis(1)
|
||||
|
||||
def getLeftTrigger(self):
|
||||
return self.js.get_button(9)
|
||||
|
||||
def getRightTrigger(self):
|
||||
return self.js.get_button(2)
|
||||
|
||||
class XboxController(Controller):
|
||||
|
||||
def __init__(self, joystick):
|
||||
super(XboxController, self).__init__(joystick)
|
||||
|
||||
def getLeftHori(self):
|
||||
return self.js.get_axis(0)
|
||||
|
||||
def getLeftVert(self):
|
||||
return self.js.get_axis(1)
|
||||
|
||||
def getRightHori(self):
|
||||
return self.js.get_axis(3)
|
||||
|
||||
def getRightVert(self):
|
||||
return self.js.get_axis(4)
|
||||
|
||||
def getLeftTrigger(self):
|
||||
return self.js.get_axis(2)
|
||||
|
||||
def getRightTrigger(self):
|
||||
return self.js.get_button(11)
|
||||
|
||||
class Ps3Controller(Controller):
|
||||
|
||||
#up 4 _DOWN 6 left 7 right 5 croix 14 rond 13 triangle 12
|
||||
|
||||
def __init__(self, joystick):
|
||||
super(Ps3Controller, self).__init__(joystick)
|
||||
|
||||
def getLeftHori(self):
|
||||
return self.js.get_axis(0)
|
||||
|
||||
def getLeftVert(self):
|
||||
return self.js.get_axis(1)
|
||||
|
||||
def getRightHori(self):
|
||||
return self.js.get_axis(2)
|
||||
|
||||
def getRightVert(self):
|
||||
return self.js.get_axis(3)
|
||||
|
||||
def getLeftTrigger(self):
|
||||
# TODO: Verify
|
||||
return self.js.get_button(8)
|
||||
|
||||
def getRightTrigger(self):
|
||||
# TODO: Verify
|
||||
return self.js.get_button(9)
|
||||
|
||||
def getUp(self):
|
||||
return self.js.get_button(4)
|
||||
|
||||
def getDown(self):
|
||||
return self.js.get_button(6)
|
||||
|
||||
def getLeft(self):
|
||||
return self.js.get_button(7)
|
||||
|
||||
def getRight(self):
|
||||
return self.js.get_button(5)
|
||||
|
||||
def getFire1(self):
|
||||
return self.js.get_button(14)
|
||||
|
||||
def getFire2(self):
|
||||
return self.js.get_button(13)
|
||||
|
||||
|
||||
class MySaitekController(Controller):
|
||||
|
||||
def __init__(self, joystick):
|
||||
super(MySaitekController, self).__init__(joystick)
|
||||
|
||||
def getLeftHori(self):
|
||||
return self.js.get_axis(0)
|
||||
|
||||
def getLeftVert(self):
|
||||
return self.js.get_axis(1)
|
||||
|
||||
def getRightHori(self):
|
||||
return self.js.get_axis(3)
|
||||
|
||||
def getRightVert(self):
|
||||
return self.js.get_axis(2)
|
||||
|
||||
def getLeftTrigger(self):
|
||||
return self.js.get_button(6)
|
||||
|
||||
def getRightTrigger(self):
|
||||
return self.js.get_button(7)
|
||||
|
||||
class MyThrustController(Controller):
|
||||
|
||||
def __init__(self, joystick):
|
||||
super(MyThrustController, self).__init__(joystick)
|
||||
|
||||
def getLeftHori(self):
|
||||
return self.js.get_axis(0)
|
||||
|
||||
def getLeftVert(self):
|
||||
return self.js.get_axis(1)
|
||||
|
||||
def getRightHori(self):
|
||||
return self.js.get_axis(2)
|
||||
|
||||
def getRightVert(self):
|
||||
return self.js.get_axis(3)
|
||||
|
||||
def getLeftTrigger(self):
|
||||
return self.js.get_button(5)
|
||||
|
||||
def getRightTrigger(self):
|
||||
return self.js.get_button(7)
|
||||
|
||||
|
||||
class CSLController(Controller):
|
||||
|
||||
def __init__(self, joystick):
|
||||
super(CSLController, self).__init__(joystick)
|
||||
|
||||
def getLeftHori(self):
|
||||
return self.js.get_axis(2)
|
||||
|
||||
def getLeftVert(self):
|
||||
return self.js.get_axis(3)
|
||||
|
||||
def getRightHori(self):
|
||||
return self.js.get_axis(0)
|
||||
|
||||
def getRightVert(self):
|
||||
return self.js.get_axis(1)
|
||||
|
||||
def getLeftTrigger(self):
|
||||
return self.js.get_button(6)
|
||||
|
||||
def getRightTrigger(self):
|
||||
return self.js.get_button(7)
|
||||
|
||||
def getFire1(self):
|
||||
return self.js.get_button(2)
|
||||
|
||||
def getFire2(self):
|
||||
return self.js.get_button(1)
|
||||
|
||||
class USBController(Controller):
|
||||
|
||||
|
||||
# my USB Joystick
|
||||
#up axis 0 -1 DOWN axis 0 1 left axis 1 1 right axis 1 -1 bouton gauche 10 bouton droite 9
|
||||
|
||||
def __init__(self, joystick):
|
||||
super(USBController, self).__init__(joystick)
|
||||
|
||||
|
||||
def getUp(self):
|
||||
if self.js.get_axis(0) == -1:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
def getDown(self):
|
||||
if self.js.get_axis(0) > 0.9:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
def getLeft(self):
|
||||
if self.js.get_axis(1) == 1:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
def getRight(self):
|
||||
if self.js.get_axis(1) == -1:
|
||||
return 1
|
||||
else:
|
||||
return 0
|
||||
|
||||
def getLeftTrigger(self):
|
||||
return self.js.get_button(10)
|
||||
|
||||
def getRightTrigger(self):
|
||||
return self.js.get_button(9)
|
||||
|
||||
def getFire1(self):
|
||||
if self.js.get_button(10) == 1:
|
||||
print ("fire 1")
|
||||
return self.js.get_button(10)
|
||||
|
||||
def getFire2(self):
|
||||
if self.js.get_button(9) == 1:
|
||||
print ("fire 2")
|
||||
return self.js.get_button(9)
|
||||
|
||||
|
||||
|
||||
|
||||
669
libs/maxwell.json
Normal file
669
libs/maxwell.json
Normal file
|
|
@ -0,0 +1,669 @@
|
|||
{
|
||||
"ccs": [
|
||||
{
|
||||
"_comment": "Oscillator LEFT X Functions",
|
||||
"Function": "/osc/left/X/curvetype",
|
||||
"init": "sin"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/X/freq",
|
||||
"init": "1"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/X/freqlimit",
|
||||
"init": "127"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/X/amp",
|
||||
"init": "100"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/X/amplimit",
|
||||
"init": "constant"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/X/phasemod",
|
||||
"init": "64"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/X/phasemodlimit",
|
||||
"init": "linear"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/X/phaseoffset",
|
||||
"init": "64"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/X/phaseoffsetlimit",
|
||||
"init": "manual"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/X/ampoffset",
|
||||
"init": "64"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/X/ampoffsetlimit",
|
||||
"init": "manual"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/osc/left/X/inversion",
|
||||
"init": "off"
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
"_comment": "Oscillator LEFT Y Functions",
|
||||
"Function": "/osc/left/Y/curvetype",
|
||||
"init": "sin"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/Y/freq",
|
||||
"init": "1"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/Y/freqlimit",
|
||||
"init": "127"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/Y/amp",
|
||||
"init": "100"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/Y/amplimit",
|
||||
"init": "constant"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/Y/phasemod",
|
||||
"init": "64"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/Y/phasemodlimit",
|
||||
"init": "linear"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/Y/phaseoffset",
|
||||
"init": "64"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/Y/phaseoffsetlimit",
|
||||
"init": "manual"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/Y/ampoffset",
|
||||
"init": "64"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/Y/ampoffsetlimit",
|
||||
"init": "manual"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/osc/left/Y/inversion",
|
||||
"init": "off"
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
"_comment": "Oscillator LEFT Z Functions",
|
||||
"Function": "/osc/left/Z/curvetype",
|
||||
"init": "sin"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/Z/freq",
|
||||
"init": "1"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/Z/freqlimit",
|
||||
"init": "127"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/Z/amp",
|
||||
"init": "100"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/Z/amplimit",
|
||||
"init": "constant"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/Z/phasemod",
|
||||
"init": "64"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/Z/phasemodlimit",
|
||||
"init": "linear"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/Z/phaseoffset",
|
||||
"init": "64"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/Z/phaseoffsetlimit",
|
||||
"init": "manual"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/Z/ampoffset",
|
||||
"init": "64"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/left/Z/ampoffsetlimit",
|
||||
"init": "manual"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/osc/left/Z/inversion",
|
||||
"init": "off"
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
"_comment": "Oscillator RIGHT X Functions",
|
||||
"Function": "/osc/right/X/curvetype",
|
||||
"init": "sin"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/X/freq",
|
||||
"init": "1"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/X/freqlimit",
|
||||
"init": "127"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/X/amp",
|
||||
"init": "100"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/X/amplimit",
|
||||
"init": "constant"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/X/phasemod",
|
||||
"init": "64"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/X/phasemodlimit",
|
||||
"init": "linear"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/X/phaseoffset",
|
||||
"init": "64"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/X/phaseoffsetlimit",
|
||||
"init": "manual"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/X/ampoffset",
|
||||
"init": "64"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/X/ampoffsetlimit",
|
||||
"init": "manual"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/osc/right/X/inversion",
|
||||
"init": "off"
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
"_comment": "Oscillator RIGHT Y Functions",
|
||||
"Function": "/osc/right/Y/curvetype",
|
||||
"init": "sin"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/Y/freq",
|
||||
"init": "1"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/Y/freqlimit",
|
||||
"init": "127"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/Y/amp",
|
||||
"init": "100"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/Y/amplimit",
|
||||
"init": "constant"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/Y/phasemod",
|
||||
"init": "64"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/Y/phasemodlimit",
|
||||
"init": "linear"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/Y/phaseoffset",
|
||||
"init": "64"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/Y/phaseoffsetlimit",
|
||||
"init": "manual"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/Y/ampoffset",
|
||||
"init": "64"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/Y/ampoffsetlimit",
|
||||
"init": "manual"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/osc/right/Y/inversion",
|
||||
"init": "off"
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
"_comment": "Oscillator RIGHT Z Functions",
|
||||
"Function": "/osc/right/Z/curvetype",
|
||||
"init": "sin"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/Z/freq",
|
||||
"init": "1"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/Z/freqlimit",
|
||||
"init": "127"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/Z/amp",
|
||||
"init": "100"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/Z/amplimit",
|
||||
"init": "constant"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/Z/phasemod",
|
||||
"init": "64"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/Z/phasemodlimit",
|
||||
"init": "linear"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/Z/phaseoffset",
|
||||
"init": "64"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/Z/phaseoffsetlimit",
|
||||
"init": "manual"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/Z/ampoffset",
|
||||
"init": "64"
|
||||
},
|
||||
{
|
||||
"Function": "/osc/right/Z/ampoffsetlimit",
|
||||
"init": "manual"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/osc/right/Z/inversion",
|
||||
"init": "off"
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"_comment": "LFO 1 Functions",
|
||||
"Function": "/lfo/1/curvetype",
|
||||
"init": "sin"
|
||||
},
|
||||
{
|
||||
"Function": "/lfo/1/freq",
|
||||
"init": "64"
|
||||
},
|
||||
{
|
||||
"Function": "/lfo/1/freqlimit",
|
||||
"init": "127"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/lfo/1/phase",
|
||||
"init": "64"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/lfo/1/inversion",
|
||||
"init": "off"
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"_comment": "LFO 2 Functions",
|
||||
"Function": "/lfo/2/curvetype",
|
||||
"init": "sin"
|
||||
},
|
||||
{
|
||||
"Function": "/lfo/2/freq",
|
||||
"init": "64"
|
||||
},
|
||||
{
|
||||
"Function": "/lfo/2/freqlimit",
|
||||
"init": "127"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/lfo/2/phase",
|
||||
"init": "64"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/lfo/2/inversion",
|
||||
"init": "off"
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"_comment": "LFO 3 Functions",
|
||||
"Function": "/lfo/3/curvetype",
|
||||
"init": "sin"
|
||||
},
|
||||
{
|
||||
"Function": "/lfo/3/freq",
|
||||
"init": "64"
|
||||
},
|
||||
{
|
||||
"Function": "/lfo/3/freqlimit",
|
||||
"init": "127"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/lfo/3/phase",
|
||||
"init": "64"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/lfo/3/inversion",
|
||||
"init": "off"
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"_comment": "Duplicator Functions",
|
||||
"Function": "/duplicator/num",
|
||||
"init": "0"
|
||||
},
|
||||
{
|
||||
"Function": "/duplicator/offset",
|
||||
"init": "0"
|
||||
},
|
||||
|
||||
{
|
||||
"_comment": "Mixer Functions",
|
||||
"Function": "/mixer/operation",
|
||||
"init": "+"
|
||||
},
|
||||
{
|
||||
"Function": "/mixer/value",
|
||||
"init": "0"
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
"_comment": "Intensity Functions",
|
||||
"Function": "/intensity/mod",
|
||||
"init": "0"
|
||||
},
|
||||
{
|
||||
"Function": "/intensity/freq",
|
||||
"init": "0"
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
"_comment": "Scaler Functions",
|
||||
"Function": "/scaler/curvetype",
|
||||
"init": "sin"
|
||||
},
|
||||
{
|
||||
"Function": "/scaler/speed",
|
||||
"init": "64"
|
||||
},
|
||||
{
|
||||
"Function": "/scaler/switch",
|
||||
"init": "off"
|
||||
},
|
||||
{
|
||||
"Function": "/scaler/width",
|
||||
"init": "64"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/scaler/amt",
|
||||
"init": "64"
|
||||
},
|
||||
{
|
||||
"Function": "/scaler/scale",
|
||||
"init": "64"
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
"_comment": "Rotator X Functions",
|
||||
"Function": "/rotator/X/curvetype",
|
||||
"init": "sin"
|
||||
},
|
||||
{
|
||||
"Function": "/rotator/X/speed",
|
||||
"init": "64"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/rotator/X/lfo/switch",
|
||||
"init": "off"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/rotator/X/direct",
|
||||
"init": "64"
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
"_comment": "Rotator Y Functions",
|
||||
"Function": "/rotator/Y/curvetype",
|
||||
"init": "sin"
|
||||
},
|
||||
{
|
||||
"Function": "/rotator/Y/speed",
|
||||
"init": "64"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/rotator/Y/lfo/switch",
|
||||
"init": "off"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/rotator/Y/direct",
|
||||
"init": "64"
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"_comment": "Rotator Z Functions",
|
||||
"Function": "/rotator/Z/curvetype",
|
||||
"init": "sin"
|
||||
},
|
||||
{
|
||||
"Function": "/rotator/Z/speed",
|
||||
"init": "64"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/rotator/Z/lfo/switch",
|
||||
"init": "off"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/rotator/Z/direct",
|
||||
"init": "64"
|
||||
},
|
||||
|
||||
|
||||
|
||||
{
|
||||
"_comment": "Translator X Functions",
|
||||
"Function": "/translator/X/curvetype",
|
||||
"init": "sin"
|
||||
},
|
||||
{
|
||||
"Function": "/translator/X/speed",
|
||||
"init": "64"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/translator/X/lfo/switch",
|
||||
"init": "off"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/translator/X/amt",
|
||||
"init": "64"
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"_comment": "Translator Y Functions",
|
||||
"Function": "/translator/Y/curvetype",
|
||||
"init": "sin"
|
||||
},
|
||||
{
|
||||
"Function": "/translator/Y/speed",
|
||||
"init": "64"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/translator/Y/lfo/switch",
|
||||
"init": "off"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/translator/Y/amt",
|
||||
"init": "64"
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"_comment": "Translator Z Functions",
|
||||
"Function": "/translator/Z/curvetype",
|
||||
"init": "sin"
|
||||
},
|
||||
{
|
||||
"Function": "/translator/Z/speed",
|
||||
"init": "64"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/translator/Z/lfo/switch",
|
||||
"init": "off"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/translator/Z/amt",
|
||||
"init": "64"
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{
|
||||
"_comment": "Colors Functions",
|
||||
"Function": "/color/colortype",
|
||||
"init": "solid"
|
||||
},
|
||||
{
|
||||
"Function": "/color/huewidth",
|
||||
"init": "0"
|
||||
},
|
||||
{
|
||||
"Function": "/color/hueoff",
|
||||
"init": "0"
|
||||
},
|
||||
{
|
||||
"Function": "/color/huemod",
|
||||
"init": "0"
|
||||
},
|
||||
{
|
||||
"Function": "/color/huerot",
|
||||
"init": "0"
|
||||
},
|
||||
{
|
||||
"Function": "/color/intwidth",
|
||||
"init": "0"
|
||||
},
|
||||
{
|
||||
"Function": "/color/intoff",
|
||||
"init": "0"
|
||||
},
|
||||
{
|
||||
"Function": "/color/intmod",
|
||||
"init": "0"
|
||||
},
|
||||
{
|
||||
"Function": "/color/intfreq",
|
||||
"init": "0"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/color/satwidth",
|
||||
"init": "0"
|
||||
},
|
||||
|
||||
{
|
||||
"Function": "/color/satmod",
|
||||
"init": "0"
|
||||
},
|
||||
{
|
||||
"Function": "/color/saturation",
|
||||
"init": "127"
|
||||
},
|
||||
{
|
||||
"Function": "/color/modtype",
|
||||
"init": "sin"
|
||||
}
|
||||
|
||||
|
||||
]
|
||||
}
|
||||
452
libs/midi.py
Normal file
452
libs/midi.py
Normal file
|
|
@ -0,0 +1,452 @@
|
|||
#!/usr/bin/python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
LJay/LJ
|
||||
v0.7.0
|
||||
|
||||
Midi Handler
|
||||
|
||||
Deprecated, see midi3
|
||||
|
||||
by Sam Neurohack
|
||||
from /team/laser
|
||||
|
||||
"""
|
||||
|
||||
print "importing midi 0"
|
||||
import time
|
||||
|
||||
import rtmidi
|
||||
from rtmidi.midiutil import open_midiinput
|
||||
from threading import Thread
|
||||
from rtmidi.midiconstants import (CHANNEL_PRESSURE, CONTROLLER_CHANGE, NOTE_ON, NOTE_OFF,
|
||||
PITCH_BEND, POLY_PRESSURE, PROGRAM_CHANGE)
|
||||
import mido
|
||||
from mido import MidiFile
|
||||
#import mido
|
||||
import sys
|
||||
from serial.tools import list_ports
|
||||
import serial
|
||||
|
||||
from sys import platform
|
||||
import gstt
|
||||
|
||||
# import bhoroscp
|
||||
|
||||
import bhoreal
|
||||
import launchpad
|
||||
from OSC import OSCServer, OSCClient, OSCMessage
|
||||
#import orbits
|
||||
|
||||
|
||||
midiname = ["Name"] * 16
|
||||
midiport = [rtmidi.MidiOut() for i in range(16) ]
|
||||
|
||||
|
||||
|
||||
is_py2 = sys.version[0] == '2'
|
||||
if is_py2:
|
||||
from Queue import Queue
|
||||
else:
|
||||
from queue import Queue
|
||||
|
||||
# max 16 midi port array
|
||||
|
||||
midinputsname = ["Name"] * 16
|
||||
midinputsqueue = [Queue() for i in range(16) ]
|
||||
midinputs = []
|
||||
|
||||
|
||||
BhorealMidiName = "Bhoreal"
|
||||
LaunchMidiName = "Launch"
|
||||
|
||||
BhorealPort, Midi1Port, Midi2Port, VirtualPort, MPort = -1,-1,-1, -1, -1
|
||||
VirtualName = "LaunchPad Mini"
|
||||
Mser = False
|
||||
|
||||
# Myxolidian 3 notes chords list
|
||||
Myxo = [(59,51,54),(49,52,56),(49,52,56),(51,54,57),(52,56,59),(52,56,59),(54,57,48),(57,49,52)]
|
||||
MidInsNumber = 0
|
||||
|
||||
try:
|
||||
input = raw_input
|
||||
except NameError:
|
||||
# Python 3
|
||||
StandardError = Exception
|
||||
|
||||
|
||||
STATUS_MAP = {
|
||||
'noteon': NOTE_ON,
|
||||
'noteoff': NOTE_OFF,
|
||||
'programchange': PROGRAM_CHANGE,
|
||||
'controllerchange': CONTROLLER_CHANGE,
|
||||
'pitchbend': PITCH_BEND,
|
||||
'polypressure': POLY_PRESSURE,
|
||||
'channelpressure': CHANNEL_PRESSURE
|
||||
}
|
||||
|
||||
# OSC destination list for incoming midi
|
||||
midi2OSC = {
|
||||
"lj": {"oscip": "127.0.0.1", "oscport": 8002, "notes": False, "msgs": False},
|
||||
"nozoid": {"oscip": "127.0.0.1", "oscport": 8003, "notes": False, "msgs": False},
|
||||
"dump": {"oscip": "127.0.0.1", "oscport": 8040, "notes": True, "msgs": True}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#mycontroller.midiport[LaunchHere].send_message([CONTROLLER_CHANGE, LaunchTop[number-1], color])
|
||||
|
||||
def send(device,msg):
|
||||
|
||||
'''
|
||||
# if device is the midi name
|
||||
if device in midiname:
|
||||
deviceport = midiname.index(device)
|
||||
midiport[deviceport].send_message(msg)
|
||||
'''
|
||||
if device == "Launchpad":
|
||||
#print LaunchHere
|
||||
midiport[gstt.LaunchHere].send_message(msg)
|
||||
|
||||
if device == "Bhoreal":
|
||||
midiport[gstt.BhorealHere].send_message(msg)
|
||||
|
||||
def NoteOn(note, color):
|
||||
global MidInsNumber
|
||||
|
||||
gstt.note = note
|
||||
gstt.velocity = color
|
||||
|
||||
for port in range(MidInsNumber):
|
||||
|
||||
if midiname[port].find(LaunchMidiName) == 0:
|
||||
launchpad.PadNoteOn(note%64,color)
|
||||
|
||||
if midiname[port].find(BhorealMidiName) == 0:
|
||||
gstt.BhorLeds[note%64]=color
|
||||
midiport[port].send_message([NOTE_ON, note%64, color])
|
||||
#bhorosc.sendosc("/bhoreal", [note%64 , color])
|
||||
|
||||
if midiname[port].find(BhorealMidiName) != 0 and midiname[port].find(LaunchMidiName) != 0:
|
||||
midiport[port].send_message([NOTE_ON, note, color])
|
||||
|
||||
#virtual.send_message([NOTE_ON, note, color])
|
||||
|
||||
for OSCtarget in midi2OSC:
|
||||
if midi2OSC[OSCtarget]['notes']:
|
||||
pass
|
||||
#OSCsend(OSCtarget, "/noteon", [note, color])
|
||||
|
||||
|
||||
def NoteOff(note):
|
||||
global MidInsNumber
|
||||
|
||||
gstt.note = note
|
||||
gstt.velocity = 0
|
||||
for port in range(MidInsNumber):
|
||||
|
||||
if midiname[port].find(LaunchMidiName) == 0:
|
||||
launchpad.PadNoteOff(note%64)
|
||||
|
||||
if midiname[port].find(BhorealMidiName) == 0:
|
||||
midiport[port].send_message([NOTE_OFF, note%64, 0])
|
||||
gstt.BhorLeds[note%64]=0
|
||||
#bhorosc.sendosc("/bhoreal", [note%64 , 0])
|
||||
|
||||
if midiname[port].find(BhorealMidiName) != 0 and midiname[port].find(LaunchMidiName) != 0:
|
||||
midiport[port].send_message([NOTE_OFF, note, 0])
|
||||
#virtual.send_message([NOTE_OFF, note, 0])
|
||||
|
||||
for OSCtarget in midi2OSC:
|
||||
if midi2OSC[OSCtarget]["notes"]:
|
||||
pass
|
||||
#OSCsend(OSCtarget, "/noteoff", note)
|
||||
|
||||
|
||||
|
||||
def MidiMsg(midimsg):
|
||||
|
||||
print ("MidiMsg", midimsg)
|
||||
for port in range(MidInsNumber):
|
||||
if midiname[port].find(BhorealMidiName) != 0:
|
||||
midiport[port].send_message(midimsg)
|
||||
|
||||
|
||||
def OSCsend(name, oscaddress, oscargs =''):
|
||||
|
||||
|
||||
ip = midi2OSC[name]["oscip"]
|
||||
port = midi2OSC[name]["oscport"]
|
||||
osclient = OSCClient()
|
||||
osclient.connect((ip, port))
|
||||
oscmsg = OSCMessage()
|
||||
oscmsg.setAddress(oscaddress)
|
||||
oscmsg.append(oscargs)
|
||||
|
||||
try:
|
||||
if gstt.debug > 0:
|
||||
print("Midi OSCSend : sending", oscmsg, "to", name, "at", gstt.LjayServerIP, ":", PluginPort)
|
||||
osclient.sendto(oscmsg, (ip, port))
|
||||
oscmsg.clearData()
|
||||
#if gstt.debug >0:
|
||||
# print oscaddress, oscargs, "was sent to",name
|
||||
return True
|
||||
|
||||
except:
|
||||
if gstt.debug > 0:
|
||||
print ('Midi OSCSend : Connection to IP', ip ,':', port,'refused : died ?')
|
||||
#sendWSall("/status No plugin.")
|
||||
#sendWSall("/status " + name + " is offline")
|
||||
#sendWSall("/" + name + "/start 0")
|
||||
#PluginStart(name)
|
||||
return False
|
||||
|
||||
def WebStatus(message):
|
||||
OSCsend("lj","/status", message)
|
||||
|
||||
#
|
||||
# MIDI Startup and handling
|
||||
#
|
||||
|
||||
mqueue = Queue()
|
||||
inqueue = Queue()
|
||||
|
||||
#
|
||||
# Events from Generic MIDI Handling
|
||||
#
|
||||
|
||||
def midinProcess(midiqueue):
|
||||
|
||||
midiqueue_get = midiqueue.get
|
||||
while True:
|
||||
msg = midiqueue_get()
|
||||
print ("midin ", msg)
|
||||
time.sleep(0.001)
|
||||
|
||||
# Event from Bhoreal or Launchpad
|
||||
def MidinProcess(inqueue):
|
||||
|
||||
inqueue_get = inqueue.get
|
||||
while True:
|
||||
time.sleep(0.001)
|
||||
msg = inqueue_get()
|
||||
print ("Midinproces", msg[0])
|
||||
|
||||
# Note On
|
||||
if msg[0]==NOTE_ON:
|
||||
NoteOn(msg[1],msg[2])
|
||||
#if bhorosc.oscdevice == 1:
|
||||
WebStatus(''.join(("note ",msg[1]," to ",msg[2])))
|
||||
|
||||
# Note Off
|
||||
if msg[0]==NOTE_OFF:
|
||||
print ("noteoff")
|
||||
NoteOff(msg[1],msg[2])
|
||||
#if bhorosc.oscdevice == 1:
|
||||
WebStatus(''.join(("note ",msg[1]," to ",msg[2])))
|
||||
|
||||
# Midi CC message
|
||||
if msg[0] == CONTROLLER_CHANGE:
|
||||
print ("CC :", msg[1], msg[2])
|
||||
WebStatus("CC :" + str(msg[1]) + " " + str(msg[2]))
|
||||
#orbits.RotX(msg[2])
|
||||
for OSCtarget in midi2OSC:
|
||||
if OSCtarget["notes"]:
|
||||
pass
|
||||
#OSCsend(OSCtarget, "/CC", note)
|
||||
|
||||
# other midi message
|
||||
if msg[0] != NOTE_OFF and msg[0] != NOTE_ON:
|
||||
|
||||
MidiMsg(msg[0],msg[1],msg[2])
|
||||
#if bhorosc.oscdevice == 1:
|
||||
WebStatus(''.join(("msg : ",msg[0]," ",msg[1]," ",msg[2])))
|
||||
|
||||
|
||||
# Generic call back : new msg forwarded to queue
|
||||
class AddQueue(object):
|
||||
def __init__(self, port):
|
||||
self.port = port
|
||||
print ("AddQueue", port)
|
||||
self._wallclock = time.time()
|
||||
|
||||
def __call__(self, event, data=None):
|
||||
message, deltatime = event
|
||||
self._wallclock += deltatime
|
||||
print("[%s] @%0.6f %r" % (self.port, self._wallclock, message))
|
||||
inqueue.put(message)
|
||||
|
||||
|
||||
#
|
||||
# MIDI OUT Handling
|
||||
#
|
||||
|
||||
def OutConfig():
|
||||
global midiout, MidInsNumber
|
||||
|
||||
print("")
|
||||
print("MIDIout...")
|
||||
print("List and attach to available devices on host with IN port :")
|
||||
|
||||
# Display list of available midi IN devices on the host, create and start an OUT instance to talk to each of these Midi IN devices
|
||||
midiout = rtmidi.MidiOut()
|
||||
available_ports = midiout.get_ports()
|
||||
|
||||
for port, name in enumerate(available_ports):
|
||||
|
||||
midiname[port]=name
|
||||
midiport[port].open_port(port)
|
||||
print("Will send to [%i] %s" % (port, name))
|
||||
#MidIns[port][1].open_port(port)
|
||||
|
||||
# Search for a Bhoreal
|
||||
if name.find(BhorealMidiName) == 0:
|
||||
print("Bhoreal start animation")
|
||||
gstt.BhorealHere = port
|
||||
bhoreal.StartBhoreal(port)
|
||||
bhoreal.UpdateCurve()
|
||||
bhoreal.UpdateSet()
|
||||
bhoreal.UpdateLaser()
|
||||
bhoreal.UpdateSimu()
|
||||
time.sleep(0.2)
|
||||
|
||||
# Search for a LaunchPad
|
||||
if name.find(LaunchMidiName) == 0:
|
||||
print("Launchpad mini start animation")
|
||||
gstt.LaunchHere = port
|
||||
print(gstt.LaunchHere)
|
||||
launchpad.StartLaunchPad(port)
|
||||
time.sleep(0.2)
|
||||
|
||||
# Search for a Guitar Wing
|
||||
if name.find("Livid") == 0:
|
||||
print("Livid Guitar Wing start animation")
|
||||
gstt.WingHere = port
|
||||
print(gstt.WingHere)
|
||||
#guitarwing.StartWing(port)
|
||||
time.sleep(0.2)
|
||||
|
||||
print ("")
|
||||
MidInsNumber = port+1
|
||||
|
||||
|
||||
#
|
||||
# MIDI IN Handling
|
||||
# Create processing thread and queue for each device
|
||||
#
|
||||
def InConfig():
|
||||
|
||||
print("")
|
||||
print("MIDIin...")
|
||||
print("List and attach to available devices on host with OUT port :")
|
||||
if platform == 'darwin':
|
||||
mido.set_backend('mido.backends.rtmidi/MACOSX_CORE')
|
||||
for port, name in enumerate(mido.get_input_names()):
|
||||
|
||||
#print (name)
|
||||
midinputsname[port]=name
|
||||
print(port,name)
|
||||
|
||||
# Bhoreal found ?
|
||||
if name.find(BhorealMidiName) == 0:
|
||||
|
||||
# thread launch to handle all queued MIDI messages from Bhoreal device
|
||||
thread = Thread(target=bhoreal.MidinProcess, args=(bhoreal.bhorqueue,))
|
||||
thread.setDaemon(True)
|
||||
thread.start()
|
||||
try:
|
||||
bhorealin, port_name = open_midiinput(port+1) # weird rtmidi call port number is not the same in mido enumeration and here
|
||||
except (EOFError, KeyboardInterrupt):
|
||||
sys.exit()
|
||||
|
||||
midinputs.append(bhorealin)
|
||||
print("Attaching MIDI in callback handler to Bhoreal : ", name)
|
||||
midinputs[port].set_callback(bhoreal.AddQueue(name))
|
||||
print("Bhor",port,port_name)
|
||||
|
||||
# LaunchPad Mini Found ?
|
||||
if name.find(LaunchMidiName) == 0:
|
||||
|
||||
# thread launch to handle all queued MIDI messages from LauchPad device
|
||||
thread = Thread(target=launchpad.LaunchMidinProcess, args=(launchpad.launchqueue,))
|
||||
thread.setDaemon(True)
|
||||
thread.start()
|
||||
try:
|
||||
launchin, port_name = open_midiinput(port+1) # weird port number is not the same in mido enumeration and here
|
||||
except (EOFError, KeyboardInterrupt):
|
||||
sys.exit()
|
||||
|
||||
midinputs.append(launchin)
|
||||
print ("Attaching MIDI in callback handler to Launchpad : ", name)
|
||||
launchin.set_callback(launchpad.LaunchAddQueue(name))
|
||||
#print "Launch",port,port_name
|
||||
|
||||
# all other devices
|
||||
|
||||
'''
|
||||
|
||||
|
||||
port = mido.open_ioport(name,callback=AddQueue(name))
|
||||
|
||||
This doesn't work on OS X on French system "Réseau Session" has a bug with accent.
|
||||
Todo : stop using different midi framework.
|
||||
|
||||
if name.find(BhorealMidiName) != 0 and name.find(LaunchMidiName) != 0:
|
||||
thread = Thread(target=midinProcess, args=(midinputsqueue[port],))
|
||||
thread.setDaemon(True)
|
||||
thread.start()
|
||||
try:
|
||||
port = mido.open_ioport(name,callback=AddQueue(name))
|
||||
#port_port, port_name = open_midiinput(port)
|
||||
except (EOFError, KeyboardInterrupt):
|
||||
sys.exit()
|
||||
|
||||
#midinputs.append(port_port)
|
||||
print "Attaching MIDI in callback handler to : ", name
|
||||
#midinputs[port].set_callback(AddQueue(name))
|
||||
#MIDInport = mido.open_ioport("Laser",virtual=True,callback=MIDIn)
|
||||
|
||||
'''
|
||||
|
||||
if name.find(BhorealMidiName) != 0 and name.find(LaunchMidiName) != 0:
|
||||
thread = Thread(target=midinProcess, args=(midinputsqueue[port],))
|
||||
thread.setDaemon(True)
|
||||
thread.start()
|
||||
|
||||
|
||||
try:
|
||||
port_port, port_name = open_midiinput(port)
|
||||
except (EOFError, KeyboardInterrupt):
|
||||
sys.exit()
|
||||
|
||||
midinputs.append(port_port)
|
||||
print("Attaching MIDI in callback handler to : ", name)
|
||||
midinputs[port].set_callback(AddQueue(name))
|
||||
#MIDInport = mido.open_ioport("Laser",virtual=True,callback=MIDIn)
|
||||
|
||||
|
||||
def End():
|
||||
global midiout
|
||||
|
||||
#midiin.close_port()
|
||||
midiout.close_port()
|
||||
|
||||
#del virtual
|
||||
if gstt.LaunchHere != -1:
|
||||
del gstt.LaunchHere
|
||||
if gstt.BhorealHere != -1:
|
||||
del gstt.BhorealHere
|
||||
|
||||
|
||||
def listdevice(number):
|
||||
|
||||
return midiname[number]
|
||||
|
||||
def check():
|
||||
|
||||
InConfig()
|
||||
OutConfig()
|
||||
#return listdevice(255)
|
||||
|
||||
|
||||
BIN
libs/midi.pyc
Normal file
BIN
libs/midi.pyc
Normal file
Binary file not shown.
760
libs/midi3.py
Normal file
760
libs/midi3.py
Normal file
|
|
@ -0,0 +1,760 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Midi3
|
||||
v0.7.0
|
||||
|
||||
Midi Handler :
|
||||
|
||||
- Hook to the MIDI host
|
||||
- Enumerate connected midi devices and spawn a process/device to handle incoming events
|
||||
- Provide sending functions to
|
||||
- found midi devices with IN port
|
||||
- OSC targets /noteon /noteoff /cc (see midi2OSC).
|
||||
- Launchpad mini led matrix from/to, see launchpad.py
|
||||
- Bhoreal led matrix from/to, see bhoreal.py
|
||||
|
||||
|
||||
todo :
|
||||
|
||||
Midi macros : plusieurs parametres evoluant les uns apres les autres ou en meme temps.
|
||||
cadence
|
||||
|
||||
by Sam Neurohack
|
||||
from /team/laser
|
||||
|
||||
for python 2 & 3
|
||||
|
||||
Laser selection
|
||||
one universe / laser
|
||||
|
||||
Plugin selection
|
||||
bank change/scene/
|
||||
|
||||
|
||||
"""
|
||||
|
||||
|
||||
import time
|
||||
|
||||
import rtmidi
|
||||
from rtmidi.midiutil import open_midiinput
|
||||
from threading import Thread
|
||||
from rtmidi.midiconstants import (CHANNEL_PRESSURE, CONTROLLER_CHANGE, NOTE_ON, NOTE_OFF,
|
||||
PITCH_BEND, POLY_PRESSURE, PROGRAM_CHANGE)
|
||||
import mido
|
||||
from mido import MidiFile
|
||||
import traceback
|
||||
import weakref
|
||||
import sys
|
||||
from sys import platform
|
||||
|
||||
print()
|
||||
print('Midi startup...')
|
||||
|
||||
import gstt, bhoreal, launchpad, LPD8
|
||||
from queue import Queue
|
||||
#from OSC3 import OSCServer, OSCClient, OSCMessage
|
||||
|
||||
|
||||
midiname = ["Name"] * 16
|
||||
midiport = [rtmidi.MidiOut() for i in range(16) ]
|
||||
|
||||
OutDevice = []
|
||||
InDevice = []
|
||||
|
||||
# max 16 midi port array
|
||||
|
||||
midinputsname = ["Name"] * 16
|
||||
midinputsqueue = [Queue() for i in range(16) ]
|
||||
midinputs = []
|
||||
|
||||
|
||||
BhorealMidiName = "Bhoreal"
|
||||
LaunchMidiName = "Launch"
|
||||
|
||||
BhorealPort, Midi1Port, Midi2Port, VirtualPort, MPort = -1,-1,-1, -1, -1
|
||||
VirtualName = "LaunchPad Mini"
|
||||
Mser = False
|
||||
|
||||
# Myxolidian 3 notes chords list
|
||||
Myxo = [(59,51,54),(49,52,56),(49,52,56),(51,54,57),(52,56,59),(52,56,59),(54,57,48),(57,49,52)]
|
||||
MidInsNumber = 0
|
||||
|
||||
|
||||
clock = mido.Message(type="clock")
|
||||
|
||||
start = mido.Message(type ="start")
|
||||
stop = mido.Message(type ="stop")
|
||||
ccontinue = mido.Message(type ="continue")
|
||||
reset = mido.Message(type ="reset")
|
||||
songpos = mido.Message(type ="songpos")
|
||||
|
||||
mode = "maxwell"
|
||||
|
||||
'''
|
||||
print("clock",clock)
|
||||
print("start",start)
|
||||
print("continue", ccontinue)
|
||||
print("reset",reset)
|
||||
print("sonpos",songpos)
|
||||
'''
|
||||
|
||||
try:
|
||||
input = raw_input
|
||||
except NameError:
|
||||
# Python 3
|
||||
StandardError = Exception
|
||||
|
||||
|
||||
STATUS_MAP = {
|
||||
'noteon': NOTE_ON,
|
||||
'noteoff': NOTE_OFF,
|
||||
'programchange': PROGRAM_CHANGE,
|
||||
'controllerchange': CONTROLLER_CHANGE,
|
||||
'pitchbend': PITCH_BEND,
|
||||
'polypressure': POLY_PRESSURE,
|
||||
'channelpressure': CHANNEL_PRESSURE
|
||||
}
|
||||
|
||||
# OSC targets list
|
||||
midi2OSC = {
|
||||
"lj": {"oscip": "127.0.0.1", "oscport": 8002, "notes": False, "msgs": False},
|
||||
"nozoid": {"oscip": "127.0.0.1", "oscport": 8003, "notes": False, "msgs": False},
|
||||
"dump": {"oscip": "127.0.0.1", "oscport": 8040, "notes": True, "msgs": True},
|
||||
"maxwell": {"oscip": "127.0.0.1", "oscport": 8012, "notes": True, "msgs": True}
|
||||
}
|
||||
|
||||
notes = ["C","C#","D","D#","E","F","F#","G","G#","A","A#","B"]
|
||||
def midi2note(midinote):
|
||||
|
||||
print("midinote",midinote, "note", notes[midinote%12]+str(round(midinote/12)))
|
||||
return notes[midinote%12]+str(round(midinote/12))
|
||||
|
||||
|
||||
#mycontroller.midiport[LaunchHere].send_message([CONTROLLER_CHANGE, LaunchTop[number-1], color])
|
||||
|
||||
def send(msg,device):
|
||||
|
||||
'''
|
||||
# if device is the midi name
|
||||
if device in midiname:
|
||||
deviceport = midiname.index(device)
|
||||
midiport[deviceport].send_message(msg)
|
||||
'''
|
||||
if device == "Launchpad":
|
||||
#print LaunchHere
|
||||
midiport[launchpad.Here].send_message(msg)
|
||||
|
||||
if device == "Bhoreal":
|
||||
midiport[bhoreal.Here].send_message(msg)
|
||||
|
||||
# mididest : all, launchpad, bhoreal, specificname
|
||||
def NoteOn(note,color, mididest):
|
||||
global MidInsNumber
|
||||
|
||||
gstt.note = note
|
||||
gstt.velocity = color
|
||||
|
||||
for port in range(MidInsNumber):
|
||||
|
||||
# To Launchpad, if present.
|
||||
if mididest == "launchpad" and midiname[port].find(LaunchMidiName) == 0:
|
||||
launchpad.PadNoteOn(note%64,color)
|
||||
|
||||
# To Bhoreal, if present.
|
||||
elif mididest == "bhoreal" and midiname[port].find(BhorealMidiName) == 0:
|
||||
gstt.BhorLeds[note%64]=color
|
||||
midiport[port].send_message([NOTE_ON, note%64, color])
|
||||
#bhorosc.sendosc("/bhoreal", [note%64 , 0])
|
||||
|
||||
# To mididest
|
||||
elif midiname[port].find(mididest) == 0:
|
||||
midiport[port].send_message([NOTE_ON, note, color])
|
||||
|
||||
# To All
|
||||
elif mididest == "all" and midiname[port].find(mididest) != 0 and midiname[port].find(BhorealMidiName) != 0 and midiname[port].find(LaunchMidiName) != 0:
|
||||
midiport[port].send_message([NOTE_ON, note, color])
|
||||
|
||||
#virtual.send_message([NOTE_ON, note, color])
|
||||
|
||||
for OSCtarget in midi2OSC:
|
||||
if (OSCtarget == mididest or mididest == 'all') and midi2OSC[OSCtarget]["notes"]:
|
||||
OSCsend(OSCtarget, "/noteon", [note, color])
|
||||
|
||||
# mididest : all, launchpad, bhoreal, specificname
|
||||
def NoteOff(note, mididest):
|
||||
global MidInsNumber
|
||||
|
||||
gstt.note = note
|
||||
gstt.velocity = 0
|
||||
|
||||
for port in range(MidInsNumber):
|
||||
|
||||
# To Launchpad, if present.
|
||||
if mididest == "launchpad" and midiname[port].find(LaunchMidiName) == 0:
|
||||
launchpad.PadNoteOff(note%64)
|
||||
|
||||
# To Bhoreal, if present.
|
||||
elif mididest == "bhoreal" and midiname[port].find(BhorealMidiName) == 0:
|
||||
midiport[port].send_message([NOTE_OFF, note%64, 0])
|
||||
gstt.BhorLeds[note%64] = 0
|
||||
#bhorosc.sendosc("/bhoreal", [note%64 , 0])
|
||||
|
||||
# To mididest
|
||||
elif midiname[port].find(mididest) != -1:
|
||||
midiport[port].send_message([NOTE_OFF, note, 0])
|
||||
|
||||
# To All
|
||||
elif mididest == "all" and midiname[port].find(mididest) == -1 and midiname[port].find(BhorealMidiName) == -1 and midiname[port].find(LaunchMidiName) == -1:
|
||||
midiport[port].send_message([NOTE_OFF, note, 0])
|
||||
|
||||
#virtual.send_message([NOTE_OFF, note, 0])
|
||||
|
||||
for OSCtarget in midi2OSC:
|
||||
if (OSCtarget == mididest or mididest == 'all') and midi2OSC[OSCtarget]["notes"]:
|
||||
OSCsend(OSCtarget, "/noteoff", note)
|
||||
|
||||
|
||||
# mididest : all or specifiname, won't be sent to launchpad or Bhoreal.
|
||||
def MidiMsg(midimsg, mididest):
|
||||
#print("MidiMsg", midimsg, "Dest", mididest)
|
||||
|
||||
for port in range(MidInsNumber):
|
||||
##print("port",port,"midiname", midiname[port])
|
||||
|
||||
# To mididest
|
||||
if midiname[port].find(mididest) != -1:
|
||||
#print("sending to name", midiname[port],midimsg)
|
||||
midiport[port].send_message(midimsg)
|
||||
|
||||
# To All
|
||||
elif mididest == "all" and midiname[port].find(mididest) == -1 and midiname[port].find(BhorealMidiName) == -1 and midiname[port].find(LaunchMidiName) == -1:
|
||||
#print("all sending to port",port,"name", midiname[port])
|
||||
midiport[port].send_message(midimsg)
|
||||
|
||||
for OSCtarget in midi2OSC:
|
||||
if (OSCtarget == mididest or mididest == 'all') and midi2OSC[OSCtarget]["msgs"]:
|
||||
OSCsend(OSCtarget, "/cc", [midimsg[1], midimsg[2]])
|
||||
|
||||
|
||||
def OSCsend(name, oscaddress, oscargs =''):
|
||||
|
||||
|
||||
ip = midi2OSC[name]["oscip"]
|
||||
port = midi2OSC[name]["oscport"]
|
||||
osclient = OSCClient()
|
||||
osclient.connect((ip, port))
|
||||
oscmsg = OSCMessage()
|
||||
oscmsg.setAddress(oscaddress)
|
||||
oscmsg.append(oscargs)
|
||||
|
||||
try:
|
||||
if gstt.debug > 0:
|
||||
print("Midi OSCSend : sending", oscmsg,"to", name, "at", ip , ":", port)
|
||||
|
||||
osclient.sendto(oscmsg, (ip, port))
|
||||
oscmsg.clearData()
|
||||
return True
|
||||
|
||||
except:
|
||||
if gstt.debug > 0:
|
||||
print('Midi OSCSend : Connection to IP', ip ,':', port,'refused : died ?')
|
||||
#sendWSall("/status No plugin.")
|
||||
#sendWSall("/status " + name + " is offline")
|
||||
#sendWSall("/" + name + "/start 0")
|
||||
#PluginStart(name)
|
||||
return False
|
||||
|
||||
def Webstatus(message):
|
||||
OSCsend("lj","/status", message)
|
||||
|
||||
#
|
||||
# MIDI Startup and handling
|
||||
#
|
||||
|
||||
mqueue = Queue()
|
||||
inqueue = Queue()
|
||||
|
||||
#
|
||||
# Events from Generic MIDI Handling
|
||||
#
|
||||
'''
|
||||
def midinProcess(midiqueue):
|
||||
|
||||
midiqueue_get = midiqueue.get
|
||||
while True:
|
||||
msg = midiqueue_get()
|
||||
print("midin ", msg)
|
||||
time.sleep(0.001)
|
||||
'''
|
||||
# Event from Bhoreal or Launchpad
|
||||
# Or it could be the midinprocess in launchpad.py or bhoreal.py
|
||||
def MidinProcess(inqueue, portname):
|
||||
|
||||
inqueue_get = inqueue.get
|
||||
mididest = "to Maxwell 1"
|
||||
while True:
|
||||
time.sleep(0.001)
|
||||
msg = inqueue_get()
|
||||
#print("Midinprocess", msg[0])
|
||||
|
||||
# Note On
|
||||
if msg[0]==NOTE_ON:
|
||||
print ("from", portname, "noteon", msg[1])
|
||||
NoteOn(msg[1],msg[2],mididest)
|
||||
# Webstatus(''.join(("note ",msg[1]," to ",msg[2])))
|
||||
|
||||
# Note Off
|
||||
if msg[0]==NOTE_OFF:
|
||||
print("from", portname,"noteoff")
|
||||
NoteOff(msg[1],msg[2], mididest)
|
||||
# Webstatus(''.join(("note ",msg[1]," to ",msg[2])))
|
||||
|
||||
# Midi CC message
|
||||
if msg[0] == CONTROLLER_CHANGE:
|
||||
print("from", portname,"CC :", msg[1], msg[2])
|
||||
'''
|
||||
Webstatus("CC :" + str(msg[1]) + " " + str(msg[2]))
|
||||
for OSCtarget in midi2OSC:
|
||||
if OSCtarget["notes"]:
|
||||
pass
|
||||
#OSCsend(OSCtarget, "/CC", note)
|
||||
'''
|
||||
# other midi message
|
||||
if msg[0] != NOTE_OFF and msg[0] != NOTE_ON and msg[0] != CONTROLLER_CHANGE:
|
||||
print("from", portname,"other midi message")
|
||||
MidiMsg(msg[0],msg[1],msg[2],mididest)
|
||||
# Webstatus(''.join(("msg : ",msg[0]," ",msg[1]," ",msg[2])))
|
||||
|
||||
|
||||
# Generic call back : new msg forwarded to queue
|
||||
class AddQueue(object):
|
||||
def __init__(self, portname, port):
|
||||
self.portname = portname
|
||||
self.port = port
|
||||
#print("AddQueue", port)
|
||||
self._wallclock = time.time()
|
||||
|
||||
def __call__(self, event, data=None):
|
||||
message, deltatime = event
|
||||
self._wallclock += deltatime
|
||||
#print("inqueue : [%s] @%0.6f %r" % ( self.portname, self._wallclock, message))
|
||||
midinputsqueue[self.port].put(message)
|
||||
|
||||
|
||||
#
|
||||
# MIDI OUT Handling
|
||||
#
|
||||
|
||||
|
||||
class OutObject():
|
||||
|
||||
_instances = set()
|
||||
counter = 0
|
||||
|
||||
def __init__(self, name, kind, port):
|
||||
|
||||
self.name = name
|
||||
self.kind = kind
|
||||
self.port = port
|
||||
|
||||
self._instances.add(weakref.ref(self))
|
||||
OutObject.counter += 1
|
||||
|
||||
print(self.name, "kind", self.kind, "port", self.port)
|
||||
|
||||
@classmethod
|
||||
def getinstances(cls):
|
||||
dead = set()
|
||||
for ref in cls._instances:
|
||||
obj = ref()
|
||||
if obj is not None:
|
||||
yield obj
|
||||
else:
|
||||
dead.add(ref)
|
||||
cls._instances -= dead
|
||||
|
||||
def __del__(self):
|
||||
OutObject.counter -= 1
|
||||
|
||||
|
||||
|
||||
def OutConfig():
|
||||
global midiout, MidInsNumber
|
||||
|
||||
#
|
||||
if len(OutDevice) == 0:
|
||||
print("")
|
||||
print("MIDIout...")
|
||||
print("List and attach to available devices on host with IN port :")
|
||||
|
||||
# Display list of available midi IN devices on the host, create and start an OUT instance to talk to each of these Midi IN devices
|
||||
midiout = rtmidi.MidiOut()
|
||||
available_ports = midiout.get_ports()
|
||||
|
||||
for port, name in enumerate(available_ports):
|
||||
|
||||
midiname[port]=name
|
||||
midiport[port].open_port(port)
|
||||
#print("Will send to [%i] %s" % (port, name))
|
||||
#MidIns[port][1].open_port(port)
|
||||
|
||||
# Search for a Bhoreal
|
||||
if name.find(BhorealMidiName) == 0:
|
||||
|
||||
OutDevice.append(OutObject(name, "bhoreal", port))
|
||||
print("Bhoreal start animation")
|
||||
bhoreal.Here = port
|
||||
bhoreal.StartBhoreal(port)
|
||||
time.sleep(0.2)
|
||||
|
||||
# Search for a LaunchPad
|
||||
elif name.find(LaunchMidiName) == 0:
|
||||
|
||||
OutDevice.append(OutObject(name, "launchpad", port))
|
||||
print("Launchpad mini start animation")
|
||||
launchpad.Here = port
|
||||
launchpad.StartLaunchPad(port)
|
||||
time.sleep(0.2)
|
||||
|
||||
# Search for a LPD8
|
||||
elif name.find('LPD8') == 0:
|
||||
|
||||
OutDevice.append(OutObject(name, "LPD8", port))
|
||||
#print("LPD8 mini start animation")
|
||||
LPD8.Here = port
|
||||
#LPD8.StartLPD8(port)
|
||||
time.sleep(0.2)
|
||||
|
||||
# Search for a Guitar Wing
|
||||
elif name.find("Livid") == 0:
|
||||
OutDevice.append(OutObject(name, "livid", port))
|
||||
print("Livid Guitar Wing start animation")
|
||||
gstt.WingHere = port
|
||||
print(gstt.WingHere)
|
||||
|
||||
#guitarwing.StartWing(port)
|
||||
time.sleep(0.2)
|
||||
else:
|
||||
|
||||
OutDevice.append(OutObject(name, "generic", port))
|
||||
|
||||
#print("")
|
||||
print(len(OutDevice), "Out devices")
|
||||
#ListOutDevice()
|
||||
MidInsNumber = len(OutDevice)+1
|
||||
|
||||
def ListOutDevice():
|
||||
|
||||
for item in OutObject.getinstances():
|
||||
|
||||
print(item.name)
|
||||
|
||||
def FindOutDevice(name):
|
||||
|
||||
port = -1
|
||||
for item in OutObject.getinstances():
|
||||
#print("searching", name, "in", item.name)
|
||||
if name == item.name:
|
||||
#print('found port',item.port)
|
||||
port = item.port
|
||||
return port
|
||||
|
||||
|
||||
def DelOutDevice(name):
|
||||
|
||||
Outnumber = Findest(name)
|
||||
print('deleting OutDevice', name)
|
||||
|
||||
if Outnumber != -1:
|
||||
print('found OutDevice', Outnumber)
|
||||
delattr(OutObject, str(name))
|
||||
print("OutDevice", Outnumber,"was removed")
|
||||
else:
|
||||
print("OutDevice was not found")
|
||||
|
||||
|
||||
|
||||
#
|
||||
# MIDI IN Handling
|
||||
# Create processing thread and queue for each device
|
||||
#
|
||||
|
||||
class InObject():
|
||||
|
||||
_instances = set()
|
||||
counter = 0
|
||||
|
||||
def __init__(self, name, kind, port, rtmidi):
|
||||
|
||||
self.name = name
|
||||
self.kind = kind
|
||||
self.port = port
|
||||
self.rtmidi = rtmidi
|
||||
self.queue = Queue()
|
||||
|
||||
self._instances.add(weakref.ref(self))
|
||||
InObject.counter += 1
|
||||
|
||||
#print("Adding InDevice name", self.name, "kind", self.kind, "port", self.port,"rtmidi", self.rtmidi, "Queue", self.queue)
|
||||
|
||||
@classmethod
|
||||
def getinstances(cls):
|
||||
dead = set()
|
||||
for ref in cls._instances:
|
||||
obj = ref()
|
||||
if obj is not None:
|
||||
yield obj
|
||||
else:
|
||||
dead.add(ref)
|
||||
cls._instances -= dead
|
||||
|
||||
def __del__(self):
|
||||
InObject.counter -= 1
|
||||
|
||||
|
||||
def InConfig():
|
||||
|
||||
print("")
|
||||
print("MIDIin...")
|
||||
print("List and attach to available devices on host with OUT port :")
|
||||
|
||||
if platform == 'darwin':
|
||||
mido.set_backend('mido.backends.rtmidi/MACOSX_CORE')
|
||||
|
||||
genericnumber = 0
|
||||
|
||||
for port, name in enumerate(mido.get_input_names()):
|
||||
|
||||
#print()
|
||||
# Maxwell midi IN & OUT port names are different
|
||||
|
||||
if name.find("from ") == 0:
|
||||
#print ("name",name)
|
||||
name = "to "+name[5:]
|
||||
#print ("corrected to",name)
|
||||
|
||||
outport = FindOutDevice(name)
|
||||
midinputsname[port]=name
|
||||
|
||||
#print("name",name, "Port",port, "Outport", outport)
|
||||
|
||||
'''
|
||||
# New Bhoreal found ?
|
||||
if name.find(BhorealMidiName) == 0:
|
||||
|
||||
try:
|
||||
bhorealin, port_name = open_midiinput(outport) # weird rtmidi call port number is not the same in mido enumeration and here
|
||||
|
||||
BhoreralDevice = InObject(port_name, "bhoreal", outport, bhorealin)
|
||||
print("BhorealDevice.queue",BhoreralDevice.queue )
|
||||
# thread launch to handle all queued MIDI messages from Bhoreal device
|
||||
thread = Thread(target=bhoreal.MidinProcess, args=(bhoreal.bhorqueue,))
|
||||
thread.setDaemon(True)
|
||||
thread.start()
|
||||
print("Attaching MIDI in callback handler to Bhoreal : ", name, "port", port, "portname", port_name)
|
||||
BhoreralDevice.rtmidi.set_callback(bhoreal.AddQueue(port_name))
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
|
||||
'''
|
||||
# Old Bhoreal found ?
|
||||
if name.find(BhorealMidiName) == 0:
|
||||
|
||||
try:
|
||||
bhorealin, port_name = open_midiinput(outport) # weird rtmidi call port number is not the same in mido enumeration and here
|
||||
except (EOFError, KeyboardInterrupt):
|
||||
sys.exit
|
||||
|
||||
#midinputs.append(bhorealin)
|
||||
InDevice.append(InObject(name, "bhoreal", outport, bhorealin))
|
||||
# thread launch to handle all queued MIDI messages from Bhoreal device
|
||||
|
||||
thread = Thread(target=bhoreal.MidinProcess, args=(bhoreal.bhorqueue,))
|
||||
#thread = Thread(target=bhoreal.MidinProcess, args=(InDevice[port].queue,))
|
||||
thread.setDaemon(True)
|
||||
thread.start()
|
||||
#print("midinputs[port]", midinputs[port])
|
||||
print(name)
|
||||
InDevice[port].rtmidi.set_callback(bhoreal.AddQueue(name))
|
||||
#midinputs[port].set_callback(bhoreal.AddQueue(name))
|
||||
|
||||
'''
|
||||
|
||||
# New LaunchPad Mini Found ?
|
||||
if name.find(LaunchMidiName) == 0:
|
||||
|
||||
|
||||
try:
|
||||
launchin, port_name = open_midiinput(outport)
|
||||
except (EOFError, KeyboardInterrupt):
|
||||
sys.exit()
|
||||
|
||||
LaunchDevice = InObject(port_name, "launchpad", outport, launchin)
|
||||
thread = Thread(target=launchpad.MidinProcess, args=(launchpad.launchqueue,))
|
||||
thread.setDaemon(True)
|
||||
thread.start()
|
||||
print("Attaching MIDI in callback handler to Launchpad : ", name, "port", port, "portname", port_name)
|
||||
LaunchDevice.rtmidi.set_callback(launchpad.LaunchAddQueue(name))
|
||||
|
||||
'''
|
||||
|
||||
# Old LaunchPad Mini Found ?
|
||||
if name.find(LaunchMidiName) == 0:
|
||||
|
||||
|
||||
try:
|
||||
launchin, port_name = open_midiinput(outport)
|
||||
except (EOFError, KeyboardInterrupt):
|
||||
sys.exit()
|
||||
#midinputs.append(launchin)
|
||||
InDevice.append(InObject(name, "launchpad", outport, launchin))
|
||||
|
||||
thread = Thread(target=launchpad.MidinProcess, args=(launchpad.launchqueue,))
|
||||
#thread = Thread(target=launchpad.MidinProcess, args=(InDevice[port].queue,))
|
||||
thread.setDaemon(True)
|
||||
thread.start()
|
||||
print(name, "port", port, "portname", port_name)
|
||||
InDevice[port].rtmidi.set_callback(launchpad.LaunchAddQueue(name))
|
||||
#launchin.set_callback(launchpad.LaunchAddQueue(name))
|
||||
|
||||
|
||||
# LPD8 Found ?
|
||||
if name.find('LPD8') == 0:
|
||||
|
||||
print()
|
||||
print('LPD8 Found..')
|
||||
|
||||
try:
|
||||
LPD8in, port_name = open_midiinput(outport)
|
||||
except (EOFError, KeyboardInterrupt):
|
||||
sys.exit()
|
||||
#midinputs.append(LPD8in)
|
||||
InDevice.append(InObject(name, "LPD8", outport, LPD8in))
|
||||
print ("Launching LPD8 thread..")
|
||||
thread = Thread(target=LPD8.MidinProcess, args=(LPD8.LPD8queue,))
|
||||
#thread = Thread(target=LPD8.MidinProcess, args=(InDevice[port].queue,))
|
||||
thread.setDaemon(True)
|
||||
thread.start()
|
||||
print(name, "port", port, "portname", port_name)
|
||||
InDevice[port].rtmidi.set_callback(LPD8.LPD8AddQueue(name))
|
||||
|
||||
|
||||
# Everything that is not Bhoreal or Launchpad
|
||||
if name.find(BhorealMidiName) != 0 and name.find(LaunchMidiName) != 0 and name.find('LPD8') != 0:
|
||||
|
||||
try:
|
||||
#print (name, name.find("RtMidi output"))
|
||||
if name.find("RtMidi output") > -1:
|
||||
print("No thread started for device", name)
|
||||
else:
|
||||
portin = object
|
||||
port_name = ""
|
||||
portin, port_name = open_midiinput(outport)
|
||||
#midinputs.append(portin)
|
||||
InDevice.append(InObject(name, "generic", outport, portin))
|
||||
|
||||
thread = Thread(target=MidinProcess, args=(midinputsqueue[port],port_name))
|
||||
thread.setDaemon(True)
|
||||
thread.start()
|
||||
|
||||
print(name, "port", port, "portname", port_name)
|
||||
#midinputs[port].set_callback(AddQueue(name),midinputsqueue[port])
|
||||
#midinputs[port].set_callback(AddQueue(name))
|
||||
#genericnumber += 1
|
||||
InDevice[port].rtmidi.set_callback(AddQueue(name,port))
|
||||
|
||||
except Exception:
|
||||
traceback.print_exc()
|
||||
|
||||
#print("")
|
||||
print(InObject.counter, "In devices")
|
||||
#ListInDevice()
|
||||
|
||||
|
||||
def ListInDevice():
|
||||
|
||||
for item in InObject.getinstances():
|
||||
|
||||
print(item.name)
|
||||
|
||||
def FindInDevice(name):
|
||||
|
||||
port = -1
|
||||
for item in InObject.getinstances():
|
||||
#print("searching", name, "in", item.name)
|
||||
if name in item.name:
|
||||
#print('found port',item.port)
|
||||
port = item.port
|
||||
return port
|
||||
|
||||
|
||||
def DelInDevice(name):
|
||||
|
||||
Innumber = Findest(name)
|
||||
print('deleting InDevice', name)
|
||||
|
||||
if Innumber != -1:
|
||||
print('found InDevice', Innumber)
|
||||
delattr(InObject, str(name))
|
||||
print("InDevice", Innumber,"was removed")
|
||||
else:
|
||||
print("InDevice was not found")
|
||||
|
||||
|
||||
# all other devices
|
||||
|
||||
'''
|
||||
|
||||
|
||||
port = mido.open_ioport(name,callback=AddQueue(name))
|
||||
|
||||
This doesn't work on OS X on French system "Réseau Session" has a bug with accent.
|
||||
Todo : stop using different midi framework.
|
||||
|
||||
if name.find(BhorealMidiName) != 0 and name.find(LaunchMidiName) != 0:
|
||||
thread = Thread(target=midinProcess, args=(midinputsqueue[port],))
|
||||
thread.setDaemon(True)
|
||||
thread.start()
|
||||
try:
|
||||
port = mido.open_ioport(name,callback=AddQueue(name))
|
||||
#port_port, port_name = open_midiinput(port)
|
||||
except (EOFError, KeyboardInterrupt):
|
||||
sys.exit()
|
||||
|
||||
#midinputs.append(port_port)
|
||||
print "Attaching MIDI in callback handler to : ", name
|
||||
#midinputs[port].set_callback(AddQueue(name))
|
||||
#MIDInport = mido.open_ioport("Laser",virtual=True,callback=MIDIn)
|
||||
|
||||
'''
|
||||
|
||||
def End():
|
||||
global midiout
|
||||
|
||||
#midiin.close_port()
|
||||
midiout.close_port()
|
||||
|
||||
#del virtual
|
||||
if launchpad.Here != -1:
|
||||
del launchpad.Here
|
||||
if bhoreal.Here != -1:
|
||||
del bhoreal.Here
|
||||
if LPD8.Here != -1:
|
||||
del LPD8.Here
|
||||
|
||||
|
||||
def listdevice(number):
|
||||
|
||||
return midiname[number]
|
||||
|
||||
def check():
|
||||
|
||||
OutConfig()
|
||||
InConfig()
|
||||
|
||||
#return listdevice(255)
|
||||
|
||||
|
||||
212
libs/plugins.py
Normal file
212
libs/plugins.py
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
#!/usr/bin/python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
'''
|
||||
|
||||
LJ Laser Server v0.8.1
|
||||
|
||||
Plugins Handler.
|
||||
|
||||
'''
|
||||
|
||||
from OSC import OSCServer, OSCClient, OSCMessage
|
||||
from websocket_server import WebsocketServer
|
||||
import gstt
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
def Init(wserver):
|
||||
global WSserver
|
||||
|
||||
WSserver = wserver
|
||||
|
||||
|
||||
def sendWSall(message):
|
||||
#if gstt.debug >0:
|
||||
#print("WS sending %s" % (message))
|
||||
WSserver.send_message_to_all(message)
|
||||
|
||||
# What is plugin's OSC port ?
|
||||
def Port(name):
|
||||
|
||||
data = gstt.plugins.get(name)
|
||||
return data.get("OSC")
|
||||
|
||||
# How to start the plugin ?
|
||||
def Command(name):
|
||||
|
||||
data = gstt.plugins.get(name)
|
||||
return data.get("command")
|
||||
|
||||
# Get all plugin current state
|
||||
def Data(name):
|
||||
|
||||
return gstt.plugins.get(name)
|
||||
|
||||
# See LJ.conf data
|
||||
def Start(name):
|
||||
|
||||
# get Plugin configuration.
|
||||
command = Command(name)
|
||||
|
||||
sendWSall("/status Starting "+name+"...")
|
||||
# Get LJ path
|
||||
ljpath = r'%s' % os.getcwd().replace('\\','/')
|
||||
|
||||
print ""
|
||||
print "LJ is starting plugin :", name
|
||||
|
||||
# Construct the command with absolute path.
|
||||
|
||||
PluginPath = command.split(" ")
|
||||
# Launch as a subprocess
|
||||
PluginProcess = subprocess.Popen([PluginPath[0], ljpath + "/" + PluginPath[1]])
|
||||
|
||||
if gstt.debug >0:
|
||||
print "LJ path :", ljpath
|
||||
print "New process pid for ", name, ":", PluginProcess.pid
|
||||
|
||||
'''
|
||||
# Maybe it's not fully started
|
||||
data = Data(name)
|
||||
|
||||
if command != "" and "pid" not in data :
|
||||
|
||||
sendWSall("/status Starting "+name+"...")
|
||||
# Get LJ path
|
||||
ljpath = r'%s' % os.getcwd().replace('\\','/')
|
||||
|
||||
print ""
|
||||
print "LJ is starting plugin :", name
|
||||
|
||||
# Construct the command with absolute path.
|
||||
|
||||
PluginPath = command.split(" ")
|
||||
# Launch as a subprocess
|
||||
PluginProcess = subprocess.Popen([PluginPath[0], ljpath + "/" + PluginPath[1]])
|
||||
|
||||
if gstt.debug >0:
|
||||
print "LJ path :", ljpath
|
||||
print "New process pid for ", name, ":", PluginProcess.pid
|
||||
|
||||
data = Data(name)
|
||||
|
||||
data["pid"] = PluginProcess.pid
|
||||
data["process"] = PluginProcess
|
||||
|
||||
# Process can be terminated with :
|
||||
# PluginProcess.terminate()
|
||||
'''
|
||||
|
||||
def OSCsend(name, oscaddress, oscargs =''):
|
||||
|
||||
#print "OSCsend in plugins got for", name, ": oscaddress", oscaddress, "oscargs :", oscargs
|
||||
PluginPort = Port(name)
|
||||
#sendWSall("/status Checking "+ name + "...")
|
||||
|
||||
osclientplugin = OSCClient()
|
||||
osclientplugin.connect((gstt.LjayServerIP, PluginPort))
|
||||
oscmsg = OSCMessage()
|
||||
oscmsg.setAddress(oscaddress)
|
||||
oscmsg.append(oscargs)
|
||||
|
||||
try:
|
||||
if gstt.debug > 0:
|
||||
print "Plugins manager : OSCsending", oscmsg,"to plugin", name, "at", gstt.LjayServerIP, ":", PluginPort
|
||||
|
||||
osclientplugin.sendto(oscmsg, (gstt.LjayServerIP, PluginPort))
|
||||
oscmsg.clearData()
|
||||
if gstt.debug >0:
|
||||
print oscaddress, oscargs, "was sent to",name
|
||||
return True
|
||||
|
||||
except:
|
||||
if gstt.debug > 0:
|
||||
print 'OSCSend : Connection to plugin IP', gstt.LjayServerIP ,':', PluginPort,'refused : died ?'
|
||||
#sendWSall("/status No plugin.")
|
||||
#sendWSall("/status " + name + " is offline")
|
||||
#sendWSall("/" + name + "/start 0")
|
||||
#PluginStart(name)
|
||||
return False
|
||||
|
||||
|
||||
def Ping(name):
|
||||
|
||||
|
||||
sendWSall("/"+ name + "/start 0")
|
||||
return OSCsend(name,"/ping",1)
|
||||
#return True
|
||||
|
||||
|
||||
def Kill(name):
|
||||
|
||||
#data = Data(name)
|
||||
print "Killing",name
|
||||
|
||||
OSCsend(name,"/quit")
|
||||
|
||||
'''
|
||||
if data["process"] != None:
|
||||
print name, "plugin is owned by LJ."
|
||||
print "Killing plugin", name
|
||||
OSCsend(name,"/quit")
|
||||
#data["process"].terminate()
|
||||
sendWSall("/status Killing "+ name +".")
|
||||
|
||||
else:
|
||||
print "Killing asked but plugin is not owned by LJ"
|
||||
sendWSall("/status Not own plugin")
|
||||
'''
|
||||
|
||||
# Send a command to given plugin. Will also start it if command contain /start 1
|
||||
def Send(name, oscpath):
|
||||
|
||||
|
||||
if oscpath[0].find(name) != -1:
|
||||
|
||||
# Plugin is online ?
|
||||
if Ping(name):
|
||||
|
||||
# Light up the plugin button
|
||||
#sendWSall("/" + name + "/start 1")
|
||||
#sendWSall("/status " + name + " online")
|
||||
if gstt.debug > 0:
|
||||
print ''
|
||||
print "Plugins manager got", oscpath, "for plugin", name, "currently online."
|
||||
|
||||
|
||||
# If start 0, try to kill plugin
|
||||
if oscpath[0].find("start") != -1 and oscpath[1] == "0":
|
||||
|
||||
if gstt.debug >0:
|
||||
print "start 0, so killing", name, "..."
|
||||
Kill(name)
|
||||
|
||||
# Send osc command
|
||||
elif len(oscpath) == 1:
|
||||
OSCsend(name, oscpath[0], oscargs='noargs')
|
||||
elif len(oscpath) == 2:
|
||||
OSCsend(name, oscpath[0], oscargs=oscpath[1])
|
||||
elif len(oscpath) == 3:
|
||||
OSCsend(name, oscpath[0], oscargs=(oscpath[1], oscpath[2]))
|
||||
return True
|
||||
|
||||
# Plugin not online..
|
||||
else:
|
||||
|
||||
if gstt.debug >0:
|
||||
print "Plugin manager send says plugin " + name + " is offline."
|
||||
#print "Command", oscpath
|
||||
|
||||
sendWSall("/status Plugin " + name + " offline")
|
||||
sendWSall("/"+ name + "/start 0")
|
||||
|
||||
# Try to Start it if /start 1
|
||||
if oscpath[0].find("start") != -1 and oscpath[1] == "1":
|
||||
if gstt.debug >0:
|
||||
print "Plugin Manager Trying to start", name, "..."
|
||||
Start(name)
|
||||
|
||||
return False
|
||||
BIN
libs/plugins.pyc
Normal file
BIN
libs/plugins.pyc
Normal file
Binary file not shown.
803
libs/scrolldisp.py
Normal file
803
libs/scrolldisp.py
Normal file
|
|
@ -0,0 +1,803 @@
|
|||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
'''
|
||||
ScrollDisp
|
||||
v0.7.0
|
||||
|
||||
An example of an unicornhat hack for Launchpad Mini or Bhoreal.
|
||||
|
||||
This is a custom version of scrolldisp.py that display text on unicornhat
|
||||
with use of bhorunicornhat to use with a Bhoreal or a Launchpad mini mk2
|
||||
|
||||
Default device is the launchpad.
|
||||
|
||||
|
||||
Command line to display 2 chars:
|
||||
|
||||
To display 'OK' :
|
||||
python3 scrolldisp.py OK
|
||||
|
||||
To display a rainbow :
|
||||
python3 scrolldisp.py ~R
|
||||
|
||||
See the end of this script for more option like scrolling or use a bhoreal in command line.
|
||||
|
||||
|
||||
As a Library :
|
||||
|
||||
Display(text, color=(255,255,255), delay=0.2, mididest ='launchpad')
|
||||
|
||||
DisplayScroll(text, color=(255,255,255), delay=0.2, mididest = 'launchpad')
|
||||
|
||||
Remember there is Cls functions
|
||||
launchpad.Cls()
|
||||
bhoreal.Cls()
|
||||
|
||||
'''
|
||||
|
||||
#from unicorn_hat_sim import unicornhat as u
|
||||
|
||||
import bhorunicornhat as u
|
||||
import time, math, sys
|
||||
|
||||
class ScrollDisp:
|
||||
columns = []
|
||||
mappings = {'!': [" ",
|
||||
"#",
|
||||
"#",
|
||||
"#",
|
||||
"#",
|
||||
" ",
|
||||
"#",
|
||||
" "],
|
||||
'\'': [" ",
|
||||
"#",
|
||||
"#",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" "],
|
||||
'(': [" ",
|
||||
" #",
|
||||
"# ",
|
||||
"# ",
|
||||
"# ",
|
||||
"# ",
|
||||
" #",
|
||||
" "],
|
||||
')': [" ",
|
||||
"# ",
|
||||
" #",
|
||||
" #",
|
||||
" #",
|
||||
" #",
|
||||
"# ",
|
||||
" "],
|
||||
',': [" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" #",
|
||||
"# "],
|
||||
'-': [" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
"###",
|
||||
" ",
|
||||
" ",
|
||||
" "],
|
||||
'.': [" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
"#",
|
||||
" "],
|
||||
'0': [" ",
|
||||
" ## ",
|
||||
"# #",
|
||||
"# #",
|
||||
"# #",
|
||||
"# #",
|
||||
" ## ",
|
||||
" "],
|
||||
'1': [" ",
|
||||
" # ",
|
||||
"## ",
|
||||
" # ",
|
||||
" # ",
|
||||
" # ",
|
||||
"###",
|
||||
" "],
|
||||
'2': [" ",
|
||||
" ## ",
|
||||
"# #",
|
||||
" #",
|
||||
" # ",
|
||||
" # ",
|
||||
"####",
|
||||
" "],
|
||||
'3': [" ",
|
||||
"####",
|
||||
" #",
|
||||
" # ",
|
||||
" #",
|
||||
"# #",
|
||||
" ## ",
|
||||
" "],
|
||||
'4': [" ",
|
||||
"# #",
|
||||
"# #",
|
||||
"####",
|
||||
" #",
|
||||
" #",
|
||||
" #",
|
||||
" "],
|
||||
'5': [" ",
|
||||
"####",
|
||||
"# ",
|
||||
"### ",
|
||||
" #",
|
||||
"# #",
|
||||
" ## ",
|
||||
" "],
|
||||
'6': [" ",
|
||||
" ## ",
|
||||
"# ",
|
||||
"### ",
|
||||
"# #",
|
||||
"# #",
|
||||
" ## ",
|
||||
" "],
|
||||
'7': [" ",
|
||||
"####",
|
||||
" #",
|
||||
" # ",
|
||||
" # ",
|
||||
" # ",
|
||||
" # ",
|
||||
" "],
|
||||
'8': [" ",
|
||||
" ## ",
|
||||
"# #",
|
||||
" ## ",
|
||||
"# #",
|
||||
"# #",
|
||||
" ## ",
|
||||
" "],
|
||||
'9': [" ",
|
||||
" ## ",
|
||||
"# #",
|
||||
" ###",
|
||||
" #",
|
||||
" #",
|
||||
" ## ",
|
||||
" "],
|
||||
':': [" ",
|
||||
" ",
|
||||
" ",
|
||||
"#",
|
||||
" ",
|
||||
" ",
|
||||
"#",
|
||||
" "],
|
||||
'A': [" ",
|
||||
" ## ",
|
||||
"# #",
|
||||
"# #",
|
||||
"####",
|
||||
"# #",
|
||||
"# #",
|
||||
" "],
|
||||
'B': [" ",
|
||||
"### ",
|
||||
"# #",
|
||||
"### ",
|
||||
"# #",
|
||||
"# #",
|
||||
"### ",
|
||||
" "],
|
||||
'C': [" ",
|
||||
" ## ",
|
||||
"# #",
|
||||
"# ",
|
||||
"# ",
|
||||
"# #",
|
||||
" ## ",
|
||||
" "],
|
||||
'D': [" ",
|
||||
"### ",
|
||||
"# #",
|
||||
"# #",
|
||||
"# #",
|
||||
"# #",
|
||||
"### ",
|
||||
" "],
|
||||
'E': [" ",
|
||||
"####",
|
||||
"# ",
|
||||
"### ",
|
||||
"# ",
|
||||
"# ",
|
||||
"####",
|
||||
" "],
|
||||
'F': [" ",
|
||||
"####",
|
||||
"# ",
|
||||
"### ",
|
||||
"# ",
|
||||
"# ",
|
||||
"# ",
|
||||
" "],
|
||||
'G': [" ",
|
||||
" ## ",
|
||||
"# #",
|
||||
"# ",
|
||||
"# ##",
|
||||
"# #",
|
||||
" ## ",
|
||||
" "],
|
||||
'H': [" ",
|
||||
"# #",
|
||||
"# #",
|
||||
"####",
|
||||
"# #",
|
||||
"# #",
|
||||
"# #",
|
||||
" "],
|
||||
'I': [" ",
|
||||
"###",
|
||||
" # ",
|
||||
" # ",
|
||||
" # ",
|
||||
" # ",
|
||||
"###",
|
||||
" "],
|
||||
'J': [" ",
|
||||
" ###",
|
||||
" #",
|
||||
" #",
|
||||
" #",
|
||||
"# #",
|
||||
" ## ",
|
||||
" "],
|
||||
'K': [" ",
|
||||
"# #",
|
||||
"# # ",
|
||||
"## ",
|
||||
"## ",
|
||||
"# # ",
|
||||
"# #",
|
||||
" "],
|
||||
'L': [" ",
|
||||
"# ",
|
||||
"# ",
|
||||
"# ",
|
||||
"# ",
|
||||
"# ",
|
||||
"###",
|
||||
" "],
|
||||
'M': [" ",
|
||||
"# #",
|
||||
"####",
|
||||
"# #",
|
||||
"# #",
|
||||
"# #",
|
||||
"# #",
|
||||
" "],
|
||||
'N': [" ",
|
||||
"# #",
|
||||
"## #",
|
||||
"# ##",
|
||||
"# #",
|
||||
"# #",
|
||||
"# #",
|
||||
" "],
|
||||
'O': [" ",
|
||||
" ## ",
|
||||
"# #",
|
||||
"# #",
|
||||
"# #",
|
||||
"# #",
|
||||
" ## ",
|
||||
" "],
|
||||
'P': [" ",
|
||||
"### ",
|
||||
"# #",
|
||||
"### ",
|
||||
"# ",
|
||||
"# ",
|
||||
"# ",
|
||||
" "],
|
||||
'Q': [" ",
|
||||
" ## ",
|
||||
"# #",
|
||||
"# #",
|
||||
"# #",
|
||||
"# # ",
|
||||
" # #",
|
||||
" "],
|
||||
'R': [" ",
|
||||
"### ",
|
||||
"# #",
|
||||
"### ",
|
||||
"## ",
|
||||
"# # ",
|
||||
"# #",
|
||||
" "],
|
||||
'S': [" ",
|
||||
" ###",
|
||||
"# ",
|
||||
" # ",
|
||||
" # ",
|
||||
" #",
|
||||
"### ",
|
||||
" "],
|
||||
'T': [" ",
|
||||
"#####",
|
||||
" # ",
|
||||
" # ",
|
||||
" # ",
|
||||
" # ",
|
||||
" # ",
|
||||
" "],
|
||||
'U': [" ",
|
||||
"# #",
|
||||
"# #",
|
||||
"# #",
|
||||
"# #",
|
||||
"# #",
|
||||
" ## ",
|
||||
" "],
|
||||
'V': [" ",
|
||||
"# # ",
|
||||
"# # ",
|
||||
"# # ",
|
||||
"# # ",
|
||||
"# # ",
|
||||
" # ",
|
||||
" "],
|
||||
'W': [" ",
|
||||
"# #",
|
||||
"# #",
|
||||
"# #",
|
||||
"# # #",
|
||||
"## ##",
|
||||
"# #",
|
||||
" "],
|
||||
'X': [" ",
|
||||
"# #",
|
||||
"# #",
|
||||
" # ",
|
||||
" # ",
|
||||
"# #",
|
||||
"# #",
|
||||
" "],
|
||||
'Y': [" ",
|
||||
"# #",
|
||||
"# #",
|
||||
"# #",
|
||||
" # ",
|
||||
" # ",
|
||||
" # ",
|
||||
" "],
|
||||
'Z': [" ",
|
||||
"####",
|
||||
" #",
|
||||
" # ",
|
||||
" # ",
|
||||
"# ",
|
||||
"####",
|
||||
" "],
|
||||
'[': [" ",
|
||||
"##",
|
||||
"# ",
|
||||
"# ",
|
||||
"# ",
|
||||
"# ",
|
||||
"##",
|
||||
" "],
|
||||
']': [" ",
|
||||
"##",
|
||||
" #",
|
||||
" #",
|
||||
" #",
|
||||
" #",
|
||||
"##",
|
||||
" "],
|
||||
'_': [" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
" ",
|
||||
"####"],
|
||||
'a': [" ",
|
||||
" ",
|
||||
" ## ",
|
||||
" #",
|
||||
" ###",
|
||||
"# #",
|
||||
" ###",
|
||||
" "],
|
||||
'b': [" ",
|
||||
"# ",
|
||||
"# ",
|
||||
"### ",
|
||||
"# #",
|
||||
"# #",
|
||||
"### ",
|
||||
" "],
|
||||
'c': [" ",
|
||||
" ",
|
||||
" ## ",
|
||||
"# #",
|
||||
"# ",
|
||||
"# #",
|
||||
" ## ",
|
||||
" "],
|
||||
'd': [" ",
|
||||
" #",
|
||||
" #",
|
||||
" ###",
|
||||
"# #",
|
||||
"# #",
|
||||
" ###",
|
||||
" "],
|
||||
'e': [" ",
|
||||
" ",
|
||||
" ## ",
|
||||
"# #",
|
||||
"####",
|
||||
"# ",
|
||||
" ## ",
|
||||
" "],
|
||||
'f': [" ",
|
||||
" ## ",
|
||||
"# #",
|
||||
"# ",
|
||||
"## ",
|
||||
"# ",
|
||||
"# ",
|
||||
" "],
|
||||
'g': [" ",
|
||||
" ",
|
||||
" ## ",
|
||||
"# #",
|
||||
" ###",
|
||||
" #",
|
||||
"### ",
|
||||
" "],
|
||||
'h': [" ",
|
||||
"# ",
|
||||
"# ",
|
||||
"# # ",
|
||||
"## #",
|
||||
"# #",
|
||||
"# #",
|
||||
" "],
|
||||
'i': [" ",
|
||||
" # ",
|
||||
" ",
|
||||
"## ",
|
||||
" # ",
|
||||
" # ",
|
||||
"###",
|
||||
" "],
|
||||
'j': [" ",
|
||||
" #",
|
||||
" ",
|
||||
" #",
|
||||
" #",
|
||||
" #",
|
||||
"# #",
|
||||
" # "],
|
||||
'k': [" ",
|
||||
"# ",
|
||||
"# #",
|
||||
"# # ",
|
||||
"## ",
|
||||
"# # ",
|
||||
"# #",
|
||||
" "],
|
||||
'l': [" ",
|
||||
"## ",
|
||||
" # ",
|
||||
" # ",
|
||||
" # ",
|
||||
" # ",
|
||||
"###",
|
||||
" "],
|
||||
'm': [" ",
|
||||
" ",
|
||||
"## # ",
|
||||
"# # #",
|
||||
"# #",
|
||||
"# #",
|
||||
"# #",
|
||||
" "],
|
||||
'n': [" ",
|
||||
" ",
|
||||
"### ",
|
||||
"# #",
|
||||
"# #",
|
||||
"# #",
|
||||
"# #",
|
||||
" "],
|
||||
'o': [" ",
|
||||
" ",
|
||||
" ## ",
|
||||
"# #",
|
||||
"# #",
|
||||
"# #",
|
||||
" ## ",
|
||||
" "],
|
||||
'p': [" ",
|
||||
" ",
|
||||
"### ",
|
||||
"# #",
|
||||
"# #",
|
||||
"### ",
|
||||
"# ",
|
||||
"# "],
|
||||
'q': [" ",
|
||||
" ",
|
||||
" ###",
|
||||
"# #",
|
||||
"# #",
|
||||
" ###",
|
||||
" #",
|
||||
" #"],
|
||||
'r': [" ",
|
||||
" ",
|
||||
"# ##",
|
||||
"## ",
|
||||
"# ",
|
||||
"# ",
|
||||
"# ",
|
||||
" "],
|
||||
's': [" ",
|
||||
" ",
|
||||
" ###",
|
||||
"# ",
|
||||
" ## ",
|
||||
" #",
|
||||
"### ",
|
||||
" "],
|
||||
't': [" ",
|
||||
" # ",
|
||||
"####",
|
||||
" # ",
|
||||
" # ",
|
||||
" # ",
|
||||
" ##",
|
||||
" "],
|
||||
'u': [" ",
|
||||
" ",
|
||||
"# #",
|
||||
"# #",
|
||||
"# #",
|
||||
"# #",
|
||||
" ## ",
|
||||
" "],
|
||||
'v': [" ",
|
||||
" ",
|
||||
"# #",
|
||||
"# #",
|
||||
" # # ",
|
||||
" # # ",
|
||||
" # ",
|
||||
" "],
|
||||
'w': [" ",
|
||||
" ",
|
||||
"# #",
|
||||
"# #",
|
||||
"# # #",
|
||||
"# # #",
|
||||
" # # ",
|
||||
" "],
|
||||
'x': [" ",
|
||||
" ",
|
||||
"# #",
|
||||
"# #",
|
||||
" ## ",
|
||||
"# #",
|
||||
"# #",
|
||||
" "],
|
||||
'y': [" ",
|
||||
" ",
|
||||
"# #",
|
||||
"# #",
|
||||
" ###",
|
||||
" #",
|
||||
"# #",
|
||||
" ## "],
|
||||
'z': [" ",
|
||||
" ",
|
||||
"####",
|
||||
" # ",
|
||||
" # ",
|
||||
"# ",
|
||||
"####",
|
||||
" "]
|
||||
}
|
||||
sharpnotes = {
|
||||
'A': [" #",
|
||||
" ## ",
|
||||
"# #",
|
||||
"# #",
|
||||
"####",
|
||||
"# #",
|
||||
"# #",
|
||||
" "],
|
||||
'C': [" #",
|
||||
" ## ",
|
||||
"# #",
|
||||
"# ",
|
||||
"# ",
|
||||
"# #",
|
||||
" ## ",
|
||||
" "],
|
||||
'D': [" #",
|
||||
"### ",
|
||||
"# #",
|
||||
"# #",
|
||||
"# #",
|
||||
"# #",
|
||||
"### ",
|
||||
" "],
|
||||
'F': [" #",
|
||||
"### ",
|
||||
"# ",
|
||||
"### ",
|
||||
"# ",
|
||||
"# ",
|
||||
"# ",
|
||||
" "],
|
||||
'G': [" #",
|
||||
" ## ",
|
||||
"# #",
|
||||
"# ",
|
||||
"# ##",
|
||||
"# #",
|
||||
" ## ",
|
||||
" "]
|
||||
}
|
||||
def append_mapping(self, char, color):
|
||||
#self.append_space()
|
||||
bitmap = self.mappings[char]
|
||||
n = len(bitmap[0])
|
||||
for x in range(n):
|
||||
self.columns.append([(color if bitmap[i][x] == '#' else (0,0,0)) for i in range(8)])
|
||||
|
||||
def append_rainbow(self):
|
||||
for x in range(8):
|
||||
r = int((math.cos(x * math.pi / 4) + 1) * 127)
|
||||
g = int((math.cos((x - 8.0 / 3.0) * math.pi / 4) + 1) * 127)
|
||||
b = int((math.cos((x + 8.0 / 3.0) * math.pi / 4) + 1) * 127)
|
||||
self.columns.append([(r,g,b) for i in range(8)])
|
||||
|
||||
def append_space(self, n=1):
|
||||
for x in range(n):
|
||||
self.columns.append([(0,0,0) for i in range(8)])
|
||||
|
||||
def append_buffer(self):
|
||||
self.append_space(9)
|
||||
|
||||
def append_letter(self, char, color=None):
|
||||
if char == ' ':
|
||||
self.append_space(2)
|
||||
elif char == 0:
|
||||
self.append_rainbow()
|
||||
elif char in self.mappings.keys():
|
||||
self.append_mapping(char, color)
|
||||
else:
|
||||
self.columns.append([(255,255,255),(255,255,255),(255,255,255),(255,255,255),(255,255,255),(255,255,255),(255,255,255),(255,255,255)])
|
||||
print("unknown char {0} ({1})".format(char, ord(char)))
|
||||
|
||||
|
||||
def append_sharpnote(self, text, color=(255,255,255)):
|
||||
|
||||
# Note
|
||||
# Should be a better test for A-G letter.
|
||||
if text[0] in self.mappings.keys():
|
||||
bitmap = self.sharpnotes[text[0]]
|
||||
|
||||
n = len(bitmap[0])
|
||||
for x in range(n):
|
||||
self.columns.append([(color if bitmap[i][x] == '#' else (0,0,0)) for i in range(8)])
|
||||
|
||||
|
||||
# Octave
|
||||
if text[2] in self.mappings.keys():
|
||||
self.append_letter(text[2], color)
|
||||
|
||||
|
||||
def append_string(self, text, color=(255,255,255)):
|
||||
i = 0
|
||||
while i < len(text):
|
||||
if text[i] == '~':
|
||||
i += 1
|
||||
if text[i] == 'R': #rainbow
|
||||
self.append_letter(0)
|
||||
else:
|
||||
self.append_letter(text[i], color)
|
||||
i += 1
|
||||
|
||||
def set_text(self, text, color=(255,255,255)):
|
||||
self.columns = []
|
||||
#self.append_buffer()
|
||||
|
||||
if len(text) == 3 and text[1] == "#":
|
||||
self.append_sharpnote(text)
|
||||
else:
|
||||
self.append_string(text)
|
||||
|
||||
self.append_buffer()
|
||||
|
||||
def __init__(self, text=""):
|
||||
self.set_text(text)
|
||||
|
||||
def start(self, delay=0.1):
|
||||
|
||||
u.set_pixels(self.columns[0:8])
|
||||
u.show()
|
||||
time.sleep(delay)
|
||||
|
||||
def startScroll(self, delay=0.1):
|
||||
|
||||
for x in range(len(self.columns) - 8):
|
||||
u.set_pixels(self.columns[x:x+8])
|
||||
u.show()
|
||||
time.sleep(delay)
|
||||
|
||||
|
||||
def Display(text, color=(255,255,255), delay=0.2, mididest ='launchpad'):
|
||||
disp = ScrollDisp()
|
||||
#print(text)
|
||||
|
||||
if mididest == 'bhoreal':
|
||||
u.dest(mididest,180)
|
||||
else:
|
||||
u.dest(mididest,270)
|
||||
|
||||
disp.set_text(text, color)
|
||||
disp.start(delay)
|
||||
|
||||
def DisplayScroll(text, color=(255,255,255), delay=0.2, mididest = 'launchpad'):
|
||||
disp = ScrollDisp()
|
||||
if mididest == 'bhoreal':
|
||||
u.dest(mididest,180)
|
||||
else:
|
||||
u.dest(mididest,270)
|
||||
disp.set_text(text, color)
|
||||
disp.startScroll(delay)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
from libs import midi3
|
||||
|
||||
# Implemented for script compatibility but actually do nothing on supported devices
|
||||
u.brightness(0.5)
|
||||
|
||||
# 2 chars with no scrolling
|
||||
Display(' '.join(sys.argv[1:]))
|
||||
|
||||
|
||||
# text with scrolling
|
||||
# DisplayScroll(' '.join(sys.argv[1:]))
|
||||
|
||||
|
||||
|
||||
# To use with a Bhoreal just add mididest = 'bhoreal' in Display()
|
||||
# or DisplayScroll()
|
||||
|
||||
# Display(' '.join(sys.argv[1:]), mididest = 'bhoreal')
|
||||
77
libs/settings.py
Normal file
77
libs/settings.py
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
#!/usr/bin/python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
'''
|
||||
LJay/LJ
|
||||
v0.7.0
|
||||
|
||||
Settings Handler
|
||||
|
||||
LICENCE : CC
|
||||
'''
|
||||
|
||||
import ConfigParser
|
||||
import gstt
|
||||
import ast
|
||||
import numpy as np
|
||||
|
||||
|
||||
def Write():
|
||||
|
||||
config.set('General', 'lasernumber', str(gstt.LaserNumber))
|
||||
config.set('General', 'ljayserverip', str(gstt.LjayServerIP))
|
||||
config.set('General', 'bhoroscip', str(gstt.oscIPin))
|
||||
config.set('General', 'nozoscip', str(gstt.nozoscIP))
|
||||
config.set('General', 'debug', str(gstt.debug))
|
||||
|
||||
|
||||
for i in range(gstt.LaserNumber):
|
||||
laser = 'laser' + str(i)
|
||||
config.set(laser, 'ip', str(gstt.lasersIPS[i]))
|
||||
config.set(laser, 'kpps', str(gstt.kpps[i]))
|
||||
config.set(laser, 'centerx', str(gstt.centerX[i]))
|
||||
config.set(laser, 'centery', str(gstt.centerY[i]))
|
||||
config.set(laser, 'zoomx', str(gstt.zoomX[i]))
|
||||
config.set(laser, 'zoomy', str(gstt.zoomY[i]))
|
||||
config.set(laser, 'sizex', str(gstt.sizeX[i]))
|
||||
config.set(laser, 'sizey', str(gstt.sizeY[i]))
|
||||
config.set(laser, 'finangle', str(gstt.finANGLE[i]))
|
||||
config.set(laser, 'swapx', str(gstt.swapX[i]))
|
||||
config.set(laser, 'swapy', str(gstt.swapY[i]))
|
||||
config.set(laser, 'warpdest', np.array2string(gstt.warpdest[i], precision=2, separator=',',suppress_small=True))
|
||||
config.write(open(gstt.ConfigName,'w'))
|
||||
|
||||
|
||||
|
||||
def Read():
|
||||
|
||||
gstt.LaserNumber = config.getint('General', 'lasernumber')
|
||||
gstt.LjayServerIP= config.get('General', 'ljayserverip')
|
||||
gstt.oscIPin = config.get('General', 'bhoroscip')
|
||||
gstt.nozoscip = config.get('General', 'nozoscip')
|
||||
gstt.debug = config.get('General', 'debug')
|
||||
gstt.plugins = ast.literal_eval(config.get('plugins', 'plugins'))
|
||||
|
||||
|
||||
print ""
|
||||
for i in range(4):
|
||||
laser = 'laser' + str(i)
|
||||
gstt.lasersIPS[i]= config.get(laser, 'ip')
|
||||
gstt.kpps[i] = config.getint(laser, 'kpps')
|
||||
#gstt.lasersPLcolor[i] = config.getint(laser, 'color')
|
||||
gstt.centerX[i]= config.getint(laser, 'centerx')
|
||||
gstt.centerY[i] = config.getint(laser, 'centery')
|
||||
gstt.zoomX[i] = config.getfloat(laser, 'zoomx')
|
||||
gstt.zoomY[i] = config.getfloat(laser, 'zoomy')
|
||||
gstt.sizeX[i] = config.getint(laser, 'sizex')
|
||||
gstt.sizeY[i] = config.getint(laser, 'sizey')
|
||||
gstt.finANGLE[i] = config.getfloat(laser, 'finangle')
|
||||
gstt.swapX[i] = config.getint(laser, 'swapx')
|
||||
gstt.swapY[i] = config.getint(laser, 'swapy')
|
||||
gstt.warpdest[i]= np.array(ast.literal_eval(config.get(laser, 'warpdest')))
|
||||
|
||||
|
||||
print "* Reading", gstt.ConfigName, "setup file.*"
|
||||
config = ConfigParser.ConfigParser()
|
||||
config.read(gstt.ConfigName)
|
||||
|
||||
BIN
libs/settings.pyc
Normal file
BIN
libs/settings.pyc
Normal file
Binary file not shown.
467
libs/tracer.py
Normal file
467
libs/tracer.py
Normal file
|
|
@ -0,0 +1,467 @@
|
|||
#!/usr/bin/python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
'''
|
||||
LJay/LJ v0.8.0
|
||||
|
||||
tracer.py (was newdacp.py)
|
||||
Enhanced version (support for several lasers) of the etherdream python library from j4cDAC.
|
||||
|
||||
LICENCE : CC
|
||||
Sam Neurohack, pclf
|
||||
|
||||
Conversion in etherdream coordinates, geometric corrections,...
|
||||
Init call with a laser number and which point list to draw. Etherdream IP is found in conf file for given laser number
|
||||
|
||||
Uses redis keys value for live inputs/outputs
|
||||
These redis keys are read and set at each main loop.
|
||||
|
||||
Redis keys pulled to draw things :
|
||||
/order select some change to adjust
|
||||
/pl/lasernumber [(x,y,color),(x1,y1,color),...] A string of list of pygame points list.
|
||||
/resampler/lasernumber [(1.0,8), (0.25,3),(0.75,3),(1.0,10)] : a string for resampling rules.
|
||||
the first tuple (1.0,8) is for short line < 4000 in etherdream space
|
||||
(0.25,3),(0.75,3),(1.0,10) for long line > 4000
|
||||
i.e (0.25,3) means go at 25% position on the line, send 3 times this position to etherdream
|
||||
|
||||
Etherdream status reports in redis keys:
|
||||
/lstt/lasernumber value etherdream last_status.playback_state (0: idle 1: prepare 2: playing)
|
||||
/cap/lasernumber value number of empty points sent to fill etherdream buffer (up to 1799)
|
||||
/lack/lasernumber value "a": ACK "F": Full "I": invalid. 64 or 35 for no connection.
|
||||
|
||||
Geometric corrections :
|
||||
|
||||
Doctodo
|
||||
|
||||
'''
|
||||
|
||||
import socket
|
||||
import time
|
||||
import struct
|
||||
#from gstt import debug
|
||||
import gstt
|
||||
import math
|
||||
from itertools import cycle
|
||||
#from globalVars import *
|
||||
import pdb
|
||||
import ast
|
||||
import redis
|
||||
|
||||
import homographyp
|
||||
import numpy as np
|
||||
|
||||
black_points = [(278.0,225.0,0),(562.0,279.0,0),(401.0,375.0,0),(296.0,454.0,0),(298.0,165.0,0)]
|
||||
grid_points = [(300.0,200.0,0),(500.0,200.0,65280),(500.0,400.0,65280),(300.0,400.0,65280),(300.0,200.0,65280),(300.0,200.0,0),(200.0,100.0,0),(600.0,100.0,65280),(600.0,500.0,65280),(200.0,500.0,65280),(200.0,100.0,65280)]
|
||||
|
||||
r = redis.StrictRedis(host=gstt.LjayServerIP, port=6379, db=0)
|
||||
|
||||
|
||||
def pack_point(x, y, r, g, b, i = -1, u1 = 0, u2 = 0, flags = 0):
|
||||
"""Pack some color values into a struct dac_point.
|
||||
|
||||
Values must be specified for x, y, r, g, and b. If a value is not
|
||||
passed in for the other fields, i will default to max(r, g, b); the
|
||||
rest default to zero.
|
||||
"""
|
||||
|
||||
if i < 0:
|
||||
i = max(r, g, b)
|
||||
|
||||
return struct.pack("<HhhHHHHHH", flags, x, y, r, g, b, i, u1, u2)
|
||||
|
||||
|
||||
class ProtocolError(Exception):
|
||||
"""Exception used when a protocol error is detected."""
|
||||
pass
|
||||
|
||||
|
||||
class Status(object):
|
||||
"""Represents a status response from the DAC."""
|
||||
|
||||
def __init__(self, data):
|
||||
"""Initialize from a chunk of data."""
|
||||
self.protocol_version, self.le_state, self.playback_state, \
|
||||
self.source, self.le_flags, self.playback_flags, \
|
||||
self.source_flags, self.fullness, self.point_rate, \
|
||||
self.point_count = \
|
||||
struct.unpack("<BBBBHHHHII", data)
|
||||
|
||||
def dump(self, prefix = " - "):
|
||||
"""Dump to a string."""
|
||||
lines = [
|
||||
""
|
||||
"Host ",
|
||||
"Light engine: state %d, flags 0x%x" %
|
||||
(self.le_state, self.le_flags),
|
||||
"Playback: state %d, flags 0x%x" %
|
||||
(self.playback_state, self.playback_flags),
|
||||
"Buffer: %d points" %
|
||||
(self.fullness, ),
|
||||
"Playback: %d kpps, %d points played" %
|
||||
(self.point_rate, self.point_count),
|
||||
"Source: %d, flags 0x%x" %
|
||||
(self.source, self.source_flags)
|
||||
]
|
||||
'''
|
||||
if debug == 2:
|
||||
for l in lines:
|
||||
print prefix + l
|
||||
'''
|
||||
|
||||
class BroadcastPacket(object):
|
||||
"""Represents a broadcast packet from the DAC."""
|
||||
|
||||
def __init__(self, st):
|
||||
"""Initialize from a chunk of data."""
|
||||
self.mac = st[:6]
|
||||
self.hw_rev, self.sw_rev, self.buffer_capacity, \
|
||||
self.max_point_rate = struct.unpack("<HHHI", st[6:16])
|
||||
self.status = Status(st[16:36])
|
||||
|
||||
def dump(self, prefix = " - "):
|
||||
"""Dump to a string."""
|
||||
lines = [
|
||||
"MAC: " + ":".join(
|
||||
"%02x" % (ord(o), ) for o in self.mac),
|
||||
"HW %d, SW %d" %
|
||||
(self.hw_rev, self.sw_rev),
|
||||
"Capabilities: max %d points, %d kpps" %
|
||||
(self.buffer_capacity, self.max_point_rate)
|
||||
]
|
||||
for l in lines:
|
||||
print prefix + l
|
||||
if debug == 1:
|
||||
self.status.dump(prefix)
|
||||
|
||||
|
||||
class DAC(object):
|
||||
"""A connection to a DAC."""
|
||||
|
||||
|
||||
# "Laser point List" Point generator
|
||||
# each points is yielded : Getpoints() call n times OnePoint()
|
||||
|
||||
def OnePoint(self):
|
||||
|
||||
while True:
|
||||
|
||||
#pdb.set_trace()
|
||||
for indexpoint,currentpoint in enumerate(self.pl):
|
||||
#print indexpoint, currentpoint
|
||||
xyc = [currentpoint[0],currentpoint[1],currentpoint[2]]
|
||||
self.xyrgb = self.EtherPoint(xyc)
|
||||
|
||||
delta_x, delta_y = self.xyrgb[0] - self.xyrgb_prev[0], self.xyrgb[1] - self.xyrgb_prev[1]
|
||||
|
||||
#test adaptation selon longueur ligne
|
||||
if math.hypot(delta_x, delta_y) < 4000:
|
||||
|
||||
# For glitch art : decrease lsteps
|
||||
#l_steps = [ (1.0, 8)]
|
||||
l_steps = gstt.stepshortline
|
||||
|
||||
else:
|
||||
# For glitch art : decrease lsteps
|
||||
#l_steps = [ (0.25, 3), (0.75, 3), (1.0, 10)]
|
||||
l_steps = gstt.stepslongline
|
||||
|
||||
for e in l_steps:
|
||||
step = e[0]
|
||||
|
||||
for i in xrange(0,e[1]):
|
||||
|
||||
self.xyrgb_step = (self.xyrgb_prev[0] + step*delta_x, self.xyrgb_prev[1] + step*delta_y) + self.xyrgb[2:]
|
||||
yield self.xyrgb_step
|
||||
|
||||
self.xyrgb_prev = self.xyrgb
|
||||
|
||||
|
||||
def GetPoints(self, n):
|
||||
|
||||
d = [self.newstream.next() for i in xrange(n)]
|
||||
#print d
|
||||
return d
|
||||
|
||||
|
||||
# Etherpoint all transform in one matrix, with warp !!
|
||||
# xyc : x y color
|
||||
def EtherPoint(self,xyc):
|
||||
|
||||
c = xyc[2]
|
||||
|
||||
#print ""
|
||||
#print "pygame point",[(xyc[0],xyc[1],xyc[2])]
|
||||
#gstt.EDH[self.mylaser]= np.array(ast.literal_eval(r.get('/EDH/'+str(self.mylaser))))
|
||||
position = homographyp.apply(gstt.EDH[self.mylaser],np.array([(xyc[0],xyc[1])]))
|
||||
|
||||
#print "etherdream point",position[0][0], position[0][1], ((c >> 16) & 0xFF) << 8, ((c >> 8) & 0xFF) << 8, (c & 0xFF) << 8
|
||||
#print ''
|
||||
return (position[0][0], position[0][1], ((c >> 16) & 0xFF) << 8, ((c >> 8) & 0xFF) << 8, (c & 0xFF) << 8)
|
||||
|
||||
|
||||
def read(self, l):
|
||||
"""Read exactly length bytes from the connection."""
|
||||
while l > len(self.buf):
|
||||
self.buf += self.conn.recv(4096)
|
||||
|
||||
obuf = self.buf
|
||||
self.buf = obuf[l:]
|
||||
return obuf[:l]
|
||||
|
||||
def readresp(self, cmd):
|
||||
"""Read a response from the DAC."""
|
||||
data = self.read(22)
|
||||
response = data[0]
|
||||
#print "laser response", self.mylaser, response
|
||||
gstt.lstt_dacanswers[self.mylaser] = response
|
||||
cmdR = data[1]
|
||||
status = Status(data[2:])
|
||||
r.set('/lack/'+str(self.mylaser), response)
|
||||
|
||||
if cmdR != cmd:
|
||||
raise ProtocolError("expected resp for %r, got %r"
|
||||
% (cmd, cmdR))
|
||||
|
||||
if response != "a":
|
||||
raise ProtocolError("expected ACK, got %r"
|
||||
% (response, ))
|
||||
|
||||
self.last_status = status
|
||||
return status
|
||||
|
||||
def __init__(self, mylaser, PL, port = 7765):
|
||||
"""Connect to the DAC over TCP."""
|
||||
socket.setdefaulttimeout(2)
|
||||
|
||||
#print "init"
|
||||
self.mylaser = mylaser
|
||||
self.clientkey = r.get("/clientkey")
|
||||
#print "Laser",self.mylaser,"Got clientkey", self.clientkey
|
||||
#print "DAC", self.mylaser, "Handler process, connecting to", gstt.lasersIPS[mylaser]
|
||||
self.conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.connstatus = self.conn.connect_ex((gstt.lasersIPS[mylaser], port))
|
||||
#print "Connection status for", self.mylaser,":", self.connstatus
|
||||
# ipconn state is -1 at startup (see gstt) and modified here
|
||||
r.set('/lack/'+str(self.mylaser), self.connstatus)
|
||||
gstt.lstt_ipconn[self.mylaser] = self.connstatus
|
||||
|
||||
self.buf = ""
|
||||
# Upper case PL is the Point List number
|
||||
self.PL = PL
|
||||
|
||||
# Lower case pl is the actual point list coordinates
|
||||
self.pl = ast.literal_eval(r.get(self.clientkey + str(self.mylaser)))
|
||||
|
||||
if r.get('/EDH/'+str(self.mylaser)) == None:
|
||||
#print "Laser",self.mylaser,"NO EDH !! Computing one..."
|
||||
homographyp.newEDH(self.mylaser)
|
||||
else:
|
||||
gstt.EDH[self.mylaser] = np.array(ast.literal_eval(r.get('/EDH/'+str(self.mylaser))))
|
||||
#print "Laser",self.mylaser,"found its EDH in redis"
|
||||
#print gstt.EDH[self.mylaser]
|
||||
|
||||
self.xyrgb = self.xyrgb_prev = (0,0,0,0,0)
|
||||
self.newstream = self.OnePoint()
|
||||
|
||||
if gstt.debug >0:
|
||||
print "Init laser",self.mylaser,"asked for ckey", self.clientkey+str(self.mylaser)
|
||||
if self.connstatus != 0:
|
||||
#print ""
|
||||
print "Connection ERROR",self.connstatus,"with laser", str(mylaser),":",str(gstt.lasersIPS[mylaser])
|
||||
#print "first 10 points in PL",self.PL, self.GetPoints(10)
|
||||
else:
|
||||
print "Connection status for", self.mylaser,":", self.connstatus
|
||||
|
||||
|
||||
# Reference points
|
||||
# Read the "hello" message
|
||||
first_status = self.readresp("?")
|
||||
first_status.dump()
|
||||
position = []
|
||||
|
||||
|
||||
def begin(self, lwm, rate):
|
||||
cmd = struct.pack("<cHI", "b", lwm, rate)
|
||||
#print "Begin newdac : Laser ", str(self.mylaser), " PL : ", str(self.PL)
|
||||
|
||||
self.conn.sendall(cmd)
|
||||
return self.readresp("b")
|
||||
|
||||
def update(self, lwm, rate):
|
||||
cmd = struct.pack("<cHI", "u", lwm, rate)
|
||||
self.conn.sendall(cmd)
|
||||
return self.readresp("u")
|
||||
|
||||
def encode_point(self, point):
|
||||
return pack_point(*point)
|
||||
|
||||
def write(self, points):
|
||||
epoints = map(self.encode_point, points)
|
||||
cmd = struct.pack("<cH", "d", len(epoints))
|
||||
self.conn.sendall(cmd + "".join(epoints))
|
||||
return self.readresp("d")
|
||||
|
||||
def prepare(self):
|
||||
self.conn.sendall("p")
|
||||
return self.readresp("p")
|
||||
|
||||
|
||||
def stop(self):
|
||||
self.conn.sendall("s")
|
||||
return self.readresp("s")
|
||||
|
||||
def estop(self):
|
||||
self.conn.sendall("\xFF")
|
||||
return self.readresp("\xFF")
|
||||
|
||||
def clear_estop(self):
|
||||
self.conn.sendall("c")
|
||||
return self.readresp("c")
|
||||
|
||||
def ping(self):
|
||||
self.conn.sendall("?")
|
||||
return self.readresp("?")
|
||||
|
||||
|
||||
|
||||
def play_stream(self):
|
||||
|
||||
#print "laser", self.mylaser, "Pb : ",self.last_status.playback_state
|
||||
|
||||
# error if etherdream is already playing state (from other source)
|
||||
if self.last_status.playback_state == 2:
|
||||
raise Exception("already playing?!")
|
||||
|
||||
# if idle go to prepare state
|
||||
elif self.last_status.playback_state == 0:
|
||||
self.prepare()
|
||||
|
||||
started = 0
|
||||
|
||||
while True:
|
||||
|
||||
#print "laser", self.mylaser, "Pb : ",self.last_status.playback_state
|
||||
|
||||
order = int(r.get('/order/'+str(self.mylaser)))
|
||||
|
||||
if order == 0:
|
||||
|
||||
# USER point list
|
||||
self.pl = ast.literal_eval(r.get(self.clientkey+str(self.mylaser)))
|
||||
#print "laser", self.mylaser, " order 0 : pl : ",len(self.pl)
|
||||
|
||||
else:
|
||||
|
||||
# Get the new EDH
|
||||
if order == 1:
|
||||
print "Laser",self.mylaser,"new EDH ORDER in redis"
|
||||
gstt.EDH[self.mylaser]= np.array(ast.literal_eval(r.get('/EDH/'+str(self.mylaser))))
|
||||
# Back to user point list
|
||||
r.set('/order/'+str(self.mylaser), 0)
|
||||
|
||||
# BLACK point list
|
||||
if order == 2:
|
||||
print "Laser",self.mylaser,"BLACK ORDER in redis"
|
||||
self.pl = black_points
|
||||
|
||||
# GRID point list
|
||||
if order == 3:
|
||||
print "Laser",self.mylaser,"GRID ORDER in redis"
|
||||
self.pl = grid_points
|
||||
|
||||
|
||||
# Resampler Change
|
||||
if order == 4:
|
||||
self.resampler = ast.literal_eval(r.get('/resampler/'+str(self.mylaser)))
|
||||
print "tracer resetting lsteps for", self.mylaser, ":",self.resampler
|
||||
gstt.stepshortline = self.resampler[0]
|
||||
gstt.stepslongline[0] = self.resampler[1]
|
||||
gstt.stepslongline[1] = self.resampler[2]
|
||||
gstt.stepslongline[2] = self.resampler[3]
|
||||
# Back to user point list order
|
||||
r.set('/order/'+str(self.mylaser), 0)
|
||||
|
||||
# Client Key change
|
||||
if order == 5:
|
||||
print "Laser",self.mylaser,"new clientkey",
|
||||
self.clientkey = r.get('/clientkey')
|
||||
# Back to user point list order
|
||||
r.set('/order/'+str(self.mylaser), 0)
|
||||
|
||||
|
||||
|
||||
r.set('/lstt/'+str(self.mylaser), self.last_status.playback_state)
|
||||
# pdb.set_trace()
|
||||
# How much room?
|
||||
|
||||
cap = 1799 - self.last_status.fullness
|
||||
points = self.GetPoints(cap)
|
||||
|
||||
r.set('/cap/'+str(self.mylaser), cap)
|
||||
|
||||
if cap < 100:
|
||||
time.sleep(0.001)
|
||||
cap += 150
|
||||
|
||||
# print "Writing %d points" % (cap, )
|
||||
#t0 = time.time()
|
||||
#print points
|
||||
self.write(points)
|
||||
#t1 = time.time()
|
||||
# print "Took %f" % (t1 - t0, )
|
||||
|
||||
if not started:
|
||||
print "starting laser", self.mylaser, "with", gstt.kpps[self.mylaser],"kpps"
|
||||
self.begin(0, gstt.kpps[self.mylaser])
|
||||
started = 1
|
||||
|
||||
# not used in LJay.
|
||||
def find_dac():
|
||||
"""Listen for broadcast packets."""
|
||||
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.bind(("0.0.0.0", 7654))
|
||||
|
||||
while True:
|
||||
data, addr = s.recvfrom(1024)
|
||||
bp = BroadcastPacket(data)
|
||||
|
||||
print "Packet from %s: " % (addr, )
|
||||
bp.dump()
|
||||
|
||||
|
||||
'''
|
||||
#Laser order bit 0 = 0
|
||||
if not order & (1 << (self.mylaser*2)):
|
||||
#print "laser",mylaser,"bit 0 : 0"
|
||||
|
||||
# Laser bit 0 = 0 and bit 1 = 0 : USER PL
|
||||
if not order & (1 << (1+self.mylaser*2)):
|
||||
#print "laser",mylaser,"bit 1 : 0"
|
||||
self.pl = ast.literal_eval(r.get('/pl/'+str(self.mylaser)))
|
||||
|
||||
else:
|
||||
# Laser bit 0 = 0 and bit 1 = 1 : New EDH
|
||||
#print "laser",mylaser,"bit 1 : 1"
|
||||
print "Laser",self.mylaser,"new EDH ORDER in redis"
|
||||
gstt.EDH[self.mylaser]= np.array(ast.literal_eval(r.get('/EDH/'+str(self.mylaser))))
|
||||
# Back to USER PL
|
||||
order = r.get('/order')
|
||||
neworder = order & ~(1<< self.mylaser*2)
|
||||
neworder = neworder & ~(1<< 1+ self.mylaser*2)
|
||||
r.set('/order', str(neworder))
|
||||
else:
|
||||
|
||||
# Laser bit 0 = 1
|
||||
print "laser",mylaser,"bit 0 : 1"
|
||||
|
||||
# Laser bit 0 = 1 and bit 1 = 0 : Black PL
|
||||
if not order & (1 << (1+self.mylaser*2)):
|
||||
#print "laser",mylaser,"bit 1 : 0"
|
||||
self.pl = black_points
|
||||
|
||||
else:
|
||||
# Laser bit 0 = 1 and bit 1 = 1 : GRID PL
|
||||
#print "laser",mylaser,"bit 1 : 1"
|
||||
self.pl = grid_points
|
||||
'''
|
||||
BIN
libs/tracer.pyc
Normal file
BIN
libs/tracer.pyc
Normal file
Binary file not shown.
Loading…
Add table
Add a link
Reference in a new issue