More plugins, more doc,...

This commit is contained in:
leduc 2019-08-06 03:08:54 +02:00
parent 4a2d1a5773
commit 0bb0049f02
105 changed files with 15152 additions and 2757 deletions

82
LJ.conf
View File

@ -7,16 +7,16 @@ bhoroscip = 127.0.0.1
[laser0]
color = -1
ip = 127.0.0.1
ip = 192.168.1.4
kpps = 25000
centerx = -1610
centery = 0
zoomx = 26.0
zoomy = 38.0
centerx = -10485
centery = -1985
zoomx = 12.0
zoomy = 7.0
sizex = 31450
sizey = 32000
finangle = 0.0
swapx = 1
swapx = -1
swapy = -1
lsteps = [ (1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)]
warpdest = [[-1500., 1500.],
@ -28,10 +28,10 @@ warpdest = [[-1500., 1500.],
color = -1
ip = 192.168.1.3
kpps = 25000
centerx = 506
centery = 413
zoomx = 30.0
zoomy = 30.0
centerx = 1554
centery = 3573
zoomx = 42.0
zoomy = 40.0
sizex = 32000
sizey = 32000
finangle = 0.0
@ -45,32 +45,13 @@ warpdest = [[-1500., 1500.],
[laser2]
color = -1
ip = 192.168.1.6
kpps = 25000
centerx = 0
centery = 0
zoomx = 47.8
zoomy = 39.3
sizex = 30600
sizey = 32000
finangle = -0.008
swapx = 1
swapy = 1
lsteps = [(1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)]
warpdest = [[-1500., 1500.],
[ 1500., 1500.],
[ 1500.,-1500.],
[-1500.,-1500.]]
[laser3]
color = -1
ip = 192.168.1.5
kpps = 25000
centerx = -12
centery = 0
zoomx = 38.0
zoomy = 26.0
sizex = 32000
centerx = -31084
centery = -4837
zoomx = 37.8
zoomy = 13.3
sizex = 30600
sizey = 32000
finangle = 0.0
swapx = -1
@ -81,17 +62,42 @@ warpdest = [[-1500., 1500.],
[ 1500.,-1500.],
[-1500.,-1500.]]
[laser3]
color = -1
ip = 192.168.1.6
kpps = 25000
centerx = -15930
centery = -4434
zoomx = 36.0
zoomy = 54.0
sizex = 32000
sizey = 32000
finangle = 0.0
swapx = 1
swapy = 1
lsteps = [(1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)]
warpdest = [[-1500., 1500.],
[ 1500., 1500.],
[ 1500.,-1500.],
[-1500.,-1500.]]
[plugins]
plugins = {
"nozoid": {"OSC": 8003, "command": ""},
"nozoid": {"OSC": 8003, "command": "python3 plugins/audio/nozoids3.py"},
"glyph": {"OSC": 8004, "command": "python3 plugins/laserglyph.py"},
"planet": {"OSC": 8005, "command": "python3 plugins/planetarium/main.py"},
"words": {"OSC": 8006, "command": "python3 plugins/livewords.py"},
"words": {"OSC": 8006, "command": "python3 plugins/livewords3.py"},
"cycl": {"OSC": 8007, "command": "python3 plugins/textcycl.py"},
"simu": {"OSC": 8008, "command": "python plugins/pysimu.py"},
"artnet": {"OSC": 8009, "command": "python3 libs/artnet.py"},
"bank0": {"OSC": 8010, "command": "python3 plugins/VJing/bank0.py"},
"pose": {"OSC": 8011, "command": "python3 plugins/VJing/idiotia.py"},
"pose": {"OSC": 8011, "command": "python plugins/VJing/idiotia.py"},
"maxw": {"OSC": 8012, "command": "python3 plugins/maxwell.py"},
"square": {"OSC": 8013, "command": "python3 plugins/square.py"},
"ljpong": {"OSC": 8020, "command": "python plugins/games/ljpong/main.py"},
"ljwars": {"OSC": 8021, "command": "python plugins/games/ljsw/main.py"}
"ljwars": {"OSC": 8021, "command": "python plugins/games/ljsw/main.py"},
"audiogen": {"OSC": 8030, "command": "python3 plugins/audio/audiogen.py"},
"midigen": {"OSC": 8031, "command": "python3 plugins/audio/midigen.py"},
"viewgen": {"OSC": 8032, "command": "python3 plugins/audio/viewgen.py"}
}

128
README.md
View File

@ -13,20 +13,30 @@ A software laser server with GUI for up to 4 lasers live actions. Think creative
LJ has 5 main components :
- "Plugins" are points generators (to one or more lasers). Lot examples comes with LJ : planetarium, 3D anaglyph animations,... See plugins directory.
- A "tracer" per etherdream/laser that take its given point list, correct geometry, recompute in laser controller coordinates, send it to its controller and report its status to the "manager".
- A "manager" that talk to all tracers (which client number point lists to draw, new geometry correction,...), handle the webui functions, OSC commands,...
- To share the lasers between people/computers, LJ accept up to 4 virtual "clients" that can simultaneously send one point list per laser. You select in WebUI wich "client" should be used by tracers.
- A "manager" that talk to all tracers (which client number point lists to draw, new geometry correction,...), handle IOs (webui functions, OSC commands,...) and plugins.
- A web GUI in html, css, and vanilla js. No html server or js framework here : it's complex enough. This GUI has a (currently slow) simulator, but one can used a builtin python simulator (pysimu) or an etherdream/laser emulator (from nannou) to work without physical lasers !!
- A network available database (redis). "Clients" send directly their pointlists to redis and each "tracer" is instructed to get a given pointlist in redis.
- A network available database (redis). "Plugins" send directly their pointlists to redis and each "tracer" is instructed to get one of the avalaible pointlist in redis. See details right below...
4 clients can send 4 pointlists so up to 16 pointlists can be accessed at anytime from anywhere in the network. The server/network/webUI idea allows to share cpu intensive tasks and especially give tracers enough cpu to draw smoothly. Of course all this can happen in one computer. There is no real limits : 4 everything is tested and works smoothly if *you have enough cpu/computers/network ressources*.
More details :
It's obviously overkill for one laser in a garage, but for several laserS game events, laserS art, laserS competition, laserS planetarium,... LJ will handle the complexity. Content providers like artists, demomakers,... just need to send points.
LJ server accept up to 4 groups = virtual "scenes" of 4 "pointlists" so up to 16 pointlists can be sent to redis at anytime from anywhere in the network. You select in WebUI (Simu/plugins matrix) wich "scene" should be used by tracers/lasers. The all point is to easily share actual lasers. Imagine in demo party :
Needs at least : an etherdream DAC connected to an ILDA laser, RJ 45 IP network (gigabits only !! no wifi, 100 mpbs doesn't work well with several lasers)
Erica needs 4 lasers, that's the 4 pointlists of a "scene".
Paula and Jennifer use only 2 lasers each, so they can share a "scene".
And so on..
LJ is tested with Firefox, supports Linux and OS X. Windows is unkown but welcome, if someone want to jump in and care about it.
The server/network/webUI idea allows to spread cpu intensive tasks on different cpu cores and especially give tracers enough cpu to feed etherdreams DACs smoothly. Of course all this can happen in one computer. There is no real limits : 4 everything is tested and works smoothly if *you have enough cpu/computers/network ressources*.
It's obviously overkill for one laser in a garage, but for several laserS games events, laserS art, laserS competition, laserS planetarium,... LJ will handle the complexity. Content providers like artists, demomakers,... just need create plugin in whatever langage, send the points to redis. Then use the webui to select the "scene".
Registering the plugin in LJ.conf is absolutely not mandatory.
Needs at least : an etherdream DAC connected to an ILDA laser, RJ 45 IP network (gigabits only !! wifi and wired 100 mpbs doesn't work well with several lasers). Seriously : if you experience frame drops you need to upgrade your network.
LJ is tested with Firefox, supports Linux and OS X. Windows is unkown but welcome, if someone want to jump in.
LJ is in dev : versions in this repository will always be core functionnal : accept and draw pointlists. New features can be not fully implemented, wait for the next commit. Any feedback is welcome at any time.
@ -38,14 +48,19 @@ LJ is in dev : versions in this repository will always be core functionnal : acc
(Doc in progress)
- Laser alignment like in laser mapping.
- Laser alignment like in videomapping.
- OSC and websocket commands. Very cool : LJ can script or be scripted.
- Web ui : In your browser open webui/index.html. Javascript is needed. By default it connect to localhost. If you want to control a remote server, you need to change the uri line in LJ.js.
- Status update every 0.5 seconds : every etherdream DAC state, number of buffer points sent,...
- "Optimisation" points automatically added, can be changed live for glitch art. Search "resampler" commands.
- A compiled version for os x and linux of nannou.org etherdream+laser emulator is included. For more informations, like license see https://github.com/nannou-org/ether-dream
- Some fancy examples are available : 3D anaglyph, Laser Pong,...
- Midi and audio reactive, look midigen.py and fft3.py
- Openpose skeletons animations laser player.
- Resolume OSC client.
- Another project (bhorpad) has been merged in LJ : so if you a led matrix, like Launchpad mini or bhoreal, plug it you may define, launch macros as pushing on one led or use them to display informations.
- Artnet plugin.
- Maxwell laser synth emulation plugin.
@ -82,18 +97,18 @@ There is a nice websocket debug tool : websocat.
Correct launch order is :
- Dac/Laser (emulator or IRL)
- Redis server once.
- Switch on Dac/Laser (emulator or IRL)
- Redis server once : i.e redis-server &
- This server. see below.
- Load/reload webUI page from disk in a browser (webui/index.html). Javascript must be enabled.
- Run a plugin, see in clients/plugins folder for examples.
- Run a builtin plugin or your generator, to send pointlists in redis. See in clients/plugins folder for examples.
A typical server start is python main.py -L numberoflasers.
A typical LJ server start is python main.py -L numberoflasers.
Use also -h to display all possible arguments, like -v for debug informations.
CASE 1 : the laser server computer is the same that the computer running a client :
CASE 1 : the laser server computer is the same that the computer running a generator/plugin :
1/ Run LJ
@ -119,11 +134,13 @@ edit /etc/redis/redis.conf
2/ Launch LJ with -r argument :
python main.py -r 192.168.1.13 -L 1
3/ run a client/plugin on client computer, like :
3/ If the webUI is launched on "client" computer, update uri line in LJ.js
4/ run a client/plugin on client computer, like :
node nodeclient.js
4/ to monitor redis server use redis-manager/medis/... or :
5/ to monitor redis server use redis-manager/medis/... or :
redis-cli -h redisserverIP monitor
@ -140,21 +157,86 @@ A "plugin" is a software that send any number of pointlist(s). LJ comes with dif
- Planetarium : A 4 lasers planetarium.
- pySimu : A full speed laser simulator (pygame, python 2.7)
- LaserPong : Our laser Pong is back ! (python 2.7)
- Pose : Display json openpose skeleton animations ans starfields
- fft3 : Example how to make LJ audio reactive
- maxwell : A laser synth inspired by bluefang great work.
#
# Program your own "plugin"
# Client Side : Program your own "plugin"
#
The server approach is based on redis, so you write and run your laser client software in any redis capable programming langage (50+ : https://redis.io/clients). If you want some interaction with GUI, like in text status area, you also need OSC.
The server approach is based on redis, so you write and run your laser client software in any redis capable programming langage (50+ : https://redis.io/clients). An external program that just send pointlists is a "client". If you want some interactions from the webUI, like text status area support, crash detection, launch,... it's a "plugin" and some default code is needed see square.py as example and :
- Read all this readme ;-)
- There is a client and plugin folders with examples in different languages. If you want to do game especially with pygame, see ljpong in plugins/games directory.
- There is a client and plugin folders with examples in different languages. If you want to do game, especially with pygame, see ljpong in plugins/games directory.
- Generate at least one point list array (say a square) with *enough points*, one point is likely to fail for buffering reason.
- Feed your point list array in string format to redis server. i.e use "/pl/0/1" redis key to feed client 0, pointlist 1.
- Feed your point list array in string format to redis server. i.e use "/pl/0/1" redis key to feed scene 0, pointlist 1.
- Tell LJ.conf your plugin configuration : OSC port and command line to start it.
- lj3.py (python 3) and lj.py (python 2.7) have many very useful functions to not reinvent the wheel. Maybe it's better to symlink them in your directory than having a separated copy, to get future enhancements transparently.
Currently the WebUI (webui/index.html) is static so it has to be modified 'manually' and build : run python build.py in webui directory.
#
# Client side dope mode : How to use lj23
#
lj23 have many very useful functions to not reinvent the wheel for advanced point generation "client" side : layers, built in rotations,..
4 Great TRICKS with lj23.
First open square.py and learn how to declare different objects. square.py is a 2D shape example in 3D rotation (red/green anaglyph rendering) that use 2 layers : one left eye and one for right eye.
1/ How to have another laser drawing the same thing ?
That's a destination problem : just add another destination !
Dest1 = lj.DestObject('1', 1, True, 0 , 1, 1) # Dest1 will also send layer 0 points to scene 1, laser 1
2/ Different layers to different lasers ?
Say because of too much points you want Left element drawn by scene 0, laser 0 and right element by scene 0, laser 1
First define a different object/layer for each drawn element :
Leftsquare = lj.FixedObject('Leftsquare', True, 255, [], red, 255, 0, 0, 0 , True) # Left goes to layer 0
Rightsquare = lj.FixedObject('Rightsquare', True, 255, [], green, 0, 255, 0, 1 , True) # Right goes to layer 1
Define 2 destinations :
Dest0 = lj.DestObject('0', 0, True, 0 , 0, 0) # Dest0 will send layer 0 points to scene 0, laser 0
Dest1 = lj.DestObject('1', 1, True, 1 , 0, 1) # Dest1 will send layer 1 points to scene 0, laser 1
3/ Different layers to one laser ?
You should consider adding all your points to one layer, but same as 1/ it's a destination problem, just add another destination with the same scene/laser for this layer
Dest1 = lj.DestObject('1', 1, True, 1 , 0, 0) # Dest1 will also send layer 1 points to scene 0, laser 0
4/ I want to animate/modify anything on the fly : I'm doing a game and suddenly my hero change color.
It's a declared object problem : say Hero is a Fixed Object, you can directly change value of
Hero.name, Hero.active, Hero.intensity, Hero.xy, Hero.color, Hero.red, Hero.green, Hero.blue, Hero.layer, Hero.closed
For a character vanishing in one point use a relativeObject so you can decrease resize parameter,...
PNC.name, PNC.active, PNC.intensity, PNC.xy, PNC.color, PNC.red, PNC.green, PNC.blue, PNC.layer, PNC.closed, PNC.xpos, PNC.ypos, PNC.resize, PNC.rotx, PNC.roty, PNC.rotz
Remember RelativeObject points 'objectname.xy' has to be around 0,0,0. The other properties let you change the actual position (xpos, ypos), resize,..
Same for Dest0 if it's a destObject, properties are :
Dest0.name, Dest0.number, Dest0.active, Dest0.layer, Dest0.scene, Dest0.laser
DrawDests() will take care of all your declared drawn elements/"objects" and Destinations to generate a point list per scene/laser sent to redis. In client point of view a "pointlist" is the sum of all its declared "layers".
#
@ -202,7 +284,7 @@ By default LJ uses on 127.0.0.1 (localhost) :
You need to update LJ.conf to your network/etherdreams IPs and be sure to check command arguments : python main.py --help
The need for a dedicated computer to act as "laser server" usually depends on how many lasers you want to control and your main computer load. If you seen flickering with small point lists, try the dedicated computer option and/or stop process interfering like redis monitoring,...
The need for a dedicated computer to act as "laser server" usually depends on how many lasers you want to control and your main computer load. If you seen flickering with small point lists, try the dedicated computer idea and/or stop process interfering like redis monitoring,...

View File

@ -1,17 +1,21 @@
# coding=UTF-8
'''
LJ v0.8.1
Some LJ functions useful for python clients (was framy.py)
LJ v0.8.2
Some LJ functions useful for python 2.7 clients (was framy.py)
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(redisIP, client number)
Config
PolyLineOneColor
rPolyLineOneColor
Text(word, color, PL, xpos, ypos, resize, rotx, roty, rotz) : Display a word
Send(adress,message) : 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.
Text
SendLJ : remote control
LjClient :
LjPl :
DrawPL
WebStatus
LICENCE : CC
Sam Neurohack
@ -20,10 +24,11 @@ Sam Neurohack
import math
import redis
#from OSC import OSCServer, OSCClient, OSCMessage
from OSC import OSCServer, OSCClient, OSCMessage
redisIP = '127.0.0.1'
r = redis.StrictRedis(host=redisIP, port=6379, db=0)
print "Importing lj..."
#redisIP = '127.0.0.1'
#r = redis.StrictRedis(host=redisIP, port=6379, db=0)
ClientNumber = 0
@ -31,22 +36,14 @@ point_list = []
pl = [[],[],[],[]]
'''
LJIP = "127.0.0.1"
osclientlj = OSCClient()
oscmsg = OSCMessage()
osclientlj.connect((redisIP, 8002))
'''
'''
def Send(oscaddress,oscargs=''):
def SendLJ(oscaddress,oscargs=''):
oscmsg = OSCMessage()
oscmsg.setAddress(oscaddress)
oscmsg.append(oscargs)
#print ("sending to bhorosc : ",oscmsg)
print ("sending OSC message : ",oscmsg)
try:
osclientlj.sendto(oscmsg, (redisIP, 8002))
oscmsg.clearData()
@ -54,11 +51,9 @@ def Send(oscaddress,oscargs=''):
print ('Connection to LJ refused : died ?')
pass
#time.sleep(0.001
'''
def WebStatus(message):
Send("/status",message)
SendLJ("/status", message)
ASCII_GRAPHICS = [
@ -162,6 +157,47 @@ def Config(redisIP,client):
r = redis.StrictRedis(host=redisIP, port=6379, db=0)
ClientNumber = client
#print "client configured",ClientNumber
def LjClient(client):
global ClientNumber
ClientNumber = client
def LjPl(pl):
global PL
PL = pl
# Properly close the system. Todo
def OSCstop():
osc_terminate()
# Answer to LJ pings with /pong value
def OSCping(name):
SendLJ("/pong",name)
# Closing plugin messages to LJ
def ClosePlugin(name):
WebStatus(name+" Exit")
SendLJ("/"+name+"/start",0)
# /quit
def OSCquit(name):
WebStatus(name + " quit.")
print("Stopping OSC...")
OSCstop()
sys.exit()
def LineTo(xy, c, PL):
@ -199,7 +235,7 @@ def Pointransf(xy, xpos = 0, ypos =0, resize =1, rotx =0, roty =0 , rotz=0):
y = xy[1] * resize
z = 0
rad = rotx * math.pi / 180
rad = math.radians(rotx)
cosaX = math.cos(rad)
sinaX = math.sin(rad)
@ -207,7 +243,7 @@ def Pointransf(xy, xpos = 0, ypos =0, resize =1, rotx =0, roty =0 , rotz=0):
y = y2 * cosaX - z * sinaX
z = y2 * sinaX + z * cosaX
rad = roty * math.pi / 180
rad = math.radians(roty)
cosaY = math.cos(rad)
sinaY = math.sin(rad)
@ -215,7 +251,7 @@ def Pointransf(xy, xpos = 0, ypos =0, resize =1, rotx =0, roty =0 , rotz=0):
z = z2 * cosaY - x * sinaY
x = z2 * sinaY + x * cosaY
rad = rotz * math.pi / 180
rad = math.radians(rotz)
cosZ = math.cos(rad)
sinZ = math.sin(rad)
@ -250,12 +286,14 @@ def rPolyLineOneColor(xy_list, c, PL , closed, xpos = 0, ypos =0, resize =0.7, r
def LinesPL(PL):
print ("Stupido !! your code is to old : use DrawPL() instead of LinesPL()")
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:
@ -294,12 +332,11 @@ def Text(message,c, PL, xpos, ypos, resize, rotx, roty, rotz):
#print ""
# texte centre en x automatiquement selon le nombre de lettres l
x_offset = 26 * (- (0.9*l) + 3*i)
#print i,x_offset
# 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))
@ -312,4 +349,4 @@ def Text(message,c, PL, xpos, ypos, resize, rotx, roty, rotz):

View File

@ -1,44 +0,0 @@
#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
# -*- mode: Python -*-
'''
LJ Remote control via OSC in python
This is different than sending pointlist to draw. See pyclient or laserglyph for that.
Say your client want to display some information on the weUI status field or remote control any other LJ functions.
See commands.py for LJ functions list.
See Doctodo for all webUI elements.
LJ OSC server is listening on port 8002, talk to it.
'''
from OSC import OSCServer, OSCClient, OSCMessage
LJIP = "127.0.0.1"
osclientlj = OSCClient()
oscmsg = OSCMessage()
osclientlj.connect((LJIP, 8002))
def sendlj(oscaddress,oscargs=''):
oscmsg = OSCMessage()
oscmsg.setAddress(oscaddress)
oscmsg.append(oscargs)
#print ("sending to bhorosc : ",oscmsg)
try:
osclientlj.sendto(oscmsg, (LJIP, 8002))
oscmsg.clearData()
except:
print ('Connection to LJ refused : died ?')
pass
#time.sleep(0.001)
# display pouet in status display
sendlj("/status","pouet")
# switch laser 0 ack led to green
sendlj("/lack/0", 1)

BIN
libs/.DS_Store vendored Normal file

Binary file not shown.

289
libs/LPD8.py Normal file
View 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

File diff suppressed because it is too large Load Diff

0
libs/__init__.py Normal file
View File

BIN
libs/__init__.pyc Normal file

Binary file not shown.

364
libs/artnet.py Normal file
View 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
View 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
View 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

Binary file not shown.

164
libs/bhorunicornhat.py Normal file
View 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 ?')

View File

BIN
libs/cli.pyc Normal file

Binary file not shown.

View File

@ -46,6 +46,8 @@ lsteps is a string like "[ (1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)]"
/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
@ -78,16 +80,15 @@ 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
import gstt
import homographyp
import settings
from libs import gstt
import redis
import plugins
from libs import settings, plugins, homographyp
r = redis.StrictRedis(host=gstt.LjayServerIP , port=6379, db=0)
GenericCommands = ["start","ljclient","clientnumber","noteon","ljpong","ljwars","mouse","emergency","simu","status","run","nozoid","planet","live","words","ai","bank0","pose","lj","cycl","glyph","pong"]
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"]
@ -135,17 +136,33 @@ def LasClientChange(clientnumber):
if r.get("/pl/"+str(clientnumber)+"/0") != None:
print "Switching to laser client", clientnumber
gstt.LasClientNumber = clientnumber
plugins.sendWSall("/status Client " + str(gstt.LasClientNumber) + " laser " + str(gstt.Laser))
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 : MaxLasClient is set to ", gstt.MaxLasClient
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
@ -158,13 +175,17 @@ def NoteOn(note):
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 Laser")
plugins.sendWSall("/status Not Enough Lasers")
else:
gstt.Laser = note -24
plugins.sendWSall("/status Client " + str(gstt.LasClientNumber) + " laser " + str(gstt.Laser))
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
@ -173,28 +194,60 @@ def Mouse(x1,y1,x2,y2):
def handler(oscpath, args):
#print ""
print "OSC handler in commands.py got /"+ str(oscpath)+ " with args :",args
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:
print "GenericCommand :",oscpath[1],"with args",args
if gstt.debug > 0:
print "GenericCommand :",oscpath[1],"with args",args
if oscpath[1] == "ljclient":
LasClientChange(int(args[0]))
#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
plugins.sendWSall("/" + args[0] + "start 1")
#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]))
@ -220,9 +273,13 @@ def handler(oscpath, args):
# 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])

BIN
libs/commands.pyc Normal file

Binary file not shown.

BIN
libs/font1.pyc Normal file

Binary file not shown.

View File

@ -25,8 +25,8 @@ anims= [[],[],[],[]]
LaserNumber = 2
# What laser client to listen at launch
LasClientNumber = 0
MaxLasClient = 3
SceneNumber = 0
MaxScenes = 3
screen_size = [400,400]
xy_center = [screen_size[0]/2,screen_size[1]/2]

BIN
libs/gstt.pyc Normal file

Binary file not shown.

BIN
libs/homographyp.pyc Normal file

Binary file not shown.

883
libs/launchpad.py Normal file
View 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 doesnt 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

Binary file not shown.

View File

@ -1,8 +1,10 @@
# coding=UTF-8
'''
LJ v0.8.1
Some LJ functions useful for python 2.7 clients (was framy.py)
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.
@ -26,11 +28,13 @@ import math
import redis
from OSC import OSCServer, OSCClient, OSCMessage
redisIP = '127.0.0.1'
r = redis.StrictRedis(host=redisIP, port=6379, db=0)
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 = [[],[],[],[]]
@ -42,7 +46,10 @@ def SendLJ(oscaddress,oscargs=''):
oscmsg.setAddress(oscaddress)
oscmsg.append(oscargs)
print ("sending OSC message : ",oscmsg)
osclientlj = OSCClient()
osclientlj.connect((redisIP, 8002))
print "lj is sending OSC message : ",oscmsg, "to",redisIP,":8002"
try:
osclientlj.sendto(oscmsg, (redisIP, 8002))
oscmsg.clearData()
@ -151,12 +158,15 @@ ASCII_GRAPHICS = [
[(-2,15), (2,15)] # Point a la place de {
]
def Config(redisIP,client):
global ClientNumber
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):
@ -168,7 +178,34 @@ 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):

892
libs/lj23.py Normal file
View 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
View 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)

View File

@ -1,14 +1,13 @@
# coding=UTF-8
'''
lj3 v0.8.1
lj3 v0.7.5 for LJ v0.8+
Some LJ functions useful for python clients (was framy.py)
Some LJ functions useful for python clients
OSC functions commented, waiting working on OSC in python3
Config(redisIP, client number)
Config(redisIP, client number,name)
PolyLineOneColor
rPolyLineOneColor
@ -19,13 +18,13 @@ DrawPL(point list number) : once you stacked all wanted elements, like 2 polylin
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(value): Answer to LJ pings by sending /pong value
OSCquit(name): Exit calling script using name in terminal
OSCping(): Answer to LJ pings by sending /pong name
OSCquit(): Exit calling script using name in terminal
setup_controls(joystick)
@ -55,8 +54,9 @@ 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 = [[],[],[],[]]
@ -83,33 +83,41 @@ 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 ('Connection to LJ refused : died ?')
print (oscaddress,'Connection to LJ refused : died ?')
pass
def WebStatus(message):
SendLJ("/status", message)
# Answer to LJ pings
# Answer to LJ /ping 1 with /pong name
def OSCping(value):
# Will receive message address, and message data flattened in s, x, y
print("Got /ping with value", value)
SendLJ("/pong",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(name):
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
@ -226,9 +234,11 @@ def rgb2int(r,g,b):
return int('0x%02x%02x%02x' % (r,g,b),0)
def Config(redisIP,client):
global ClientNumber, r
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")

669
libs/maxwell.json Normal file
View 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
View 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

Binary file not shown.

760
libs/midi3.py Normal file
View 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)

View File

@ -45,18 +45,36 @@ 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...")
sendWSall("/status Starting "+name+"...")
# Get LJ path
ljpath = r'%s' % os.getcwd().replace('\\','/')
@ -80,6 +98,7 @@ def Start(name):
# Process can be terminated with :
# PluginProcess.terminate()
'''
def OSCsend(name, oscaddress, oscargs =''):
@ -95,12 +114,12 @@ def OSCsend(name, oscaddress, oscargs =''):
try:
if gstt.debug > 0:
print "OSCSend : sending", oscmsg,"to plugin", name, "at", gstt.LjayServerIP, ":", PluginPort
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
if gstt.debug >0:
print oscaddress, oscargs, "was sent to",name
return True
except:
@ -123,20 +142,23 @@ def Ping(name):
def Kill(name):
data = Data(name)
print ""
#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):
@ -151,7 +173,8 @@ def Send(name, oscpath):
#sendWSall("/" + name + "/start 1")
#sendWSall("/status " + name + " online")
if gstt.debug > 0:
print "Send got", oscpath, "for plugin", name, "currently online."
print ''
print "Plugins manager got", oscpath, "for plugin", name, "currently online."
# If start 0, try to kill plugin
@ -164,15 +187,17 @@ def Send(name, oscpath):
# Send osc command
elif len(oscpath) == 1:
OSCsend(name, oscpath[0], oscargs='noargs')
else:
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 "Send says plugin " + name + " is offline."
print "Plugin manager send says plugin " + name + " is offline."
#print "Command", oscpath
sendWSall("/status Plugin " + name + " offline")
@ -181,7 +206,7 @@ def Send(name, oscpath):
# Try to Start it if /start 1
if oscpath[0].find("start") != -1 and oscpath[1] == "1":
if gstt.debug >0:
print "Trying to start", name, "..."
print "Plugin Manager Trying to start", name, "..."
Start(name)
return False

BIN
libs/plugins.pyc Normal file

Binary file not shown.

803
libs/scrolldisp.py Normal file
View 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')

BIN
libs/settings.pyc Normal file

Binary file not shown.

BIN
libs/tracer.pyc Normal file

Binary file not shown.

264
main.py
View File

@ -4,12 +4,15 @@
'''
LJ Laser Server v0.8.1
Inspiration for new WebUI icon menu :
https://codepen.io/AlbertFeynman/pen/mjXeMV
Laser server + webUI servers (ws + OSC)
- get point list to draw : /pl/lasernumber
- for report /lstt/lasernumber /lack/lasernumber /cap/lasernumber
- A nice ws debug tool : websocat
- a "plugin" is a code that send point to LJ. Plugins if they have an open OSC port can be checked and restart if in the same computer.
- a "plugin" is a generator that send points to LJ. Plugins if they have an open OSC port can be checked and restart if in the same computer.
Todo :
@ -21,43 +24,42 @@ All used ports:
8002 OSC incoming
9001 WS communication with WebGUI
Plugins Ports (see LJ.conf)
Plugins OSC Ports (see LJ.conf)
'''
import time
import gstt
import redis
print ""
print ""
print "LJ Laser Server"
print "v0.8.1"
print "v0.8.2"
print ""
import settings
import redis
from libs import gstt, settings
settings.Read()
import cli
# Arguments may alter .conf file so import settings first then cli
from libs import cli
settings.Write()
from multiprocessing import Process, Queue, TimeoutError
import random, ast
import tracer
import homographyp
import commands
import font1
from libs import plugins, tracer, homographyp, commands, font1
import subprocess
import sys
import os
#import midi
from OSC import OSCServer, OSCClient, OSCMessage
from websocket_server import WebsocketServer
#import socket
import types, thread, time
import plugins
r = redis.StrictRedis(host=gstt.LjayServerIP , port=6379, db=0)
args =[0,0]
@ -88,7 +90,7 @@ def dac_process(number, pl):
# webUI server
#
print "Laser client number :",gstt.LasClientNumber
print "Laser client number :",gstt.SceneNumber
serverIP = gstt.LjayServerIP
print "Redis IP :", serverIP
@ -145,115 +147,17 @@ def handle_timeout(self):
oscserver.handle_timeout = types.MethodType(handle_timeout, oscserver)
'''
osclientext = OSCClient()
oscmsg = OSCMessage()
osclientext.connect((oscserverIPout, oscserverPORTout))
# send UI string as OSC message to oscserver 8001
# sendoscserver(oscaddress, [arg1, arg2,...])
def sendoscserver(oscaddress,oscargs=''):
oscmsg = OSCMessage()
oscmsg.setAddress(oscaddress)
oscmsg.append(oscargs)
#print ("sending to oscserver : ",oscmsg)
try:
osclientext.sendto(oscmsg, (oscserverIPout, oscserverPORTout))
oscmsg.clearData()
except:
print ('Connection to oscserver IP', oscserverIPout, 'port', oscserverPORTout,'refused : died ?')
sendWSall("/on 0")
sendWSall("/status NoLJay")
#time.sleep(0.001)
# send UI string as OSC message to Nozosc 8003
# sendnozosc(oscaddress, [arg1, arg2,...])
osclientnozoid = OSCClient()
osclientnozoid.connect((NozoscIPout, NozoscPORTout))
def sendnozosc(oscaddress,oscargs=''):
oscmsg = OSCMessage()
oscmsg.setAddress(oscaddress)
oscmsg.append(oscargs)
print "Sending OSC to Nozosc server :", oscaddress,'with args', oscargs
try:
osclientnozoid.sendto(oscmsg, (NozoscIPout, NozoscPORTout))
oscmsg.clearData()
except:
print 'Connection to nozosc IP', NozoscIPout,'port', NozoscPORTout,' refused : died ?'
sendWSall("/on 0")
sendWSall("/status No Nozosc ")
#time.sleep(0.001)
# send UI string as OSC message to Planet 8005
# sendplanet(oscaddress, [arg1, arg2,...])
osclientplanet = OSCClient()
osclientplanet.connect((planetIPout, planetPORTout))
def sendplanet(oscaddress,oscargs=''):
oscmsg = OSCMessage()
oscmsg.setAddress(oscaddress)
oscmsg.append(oscargs)
print "Sending OSC to Planet server :", oscaddress,'with args :', oscargs
try:
osclientplanet.sendto(oscmsg, (planetIPout, planetPORTout))
oscmsg.clearData()
except:
print 'OSC send to planet IP', planetIPout, 'port', planetPORTout, "refused : died ?"
sendWSall("/planet/start 0")
sendWSall("/status No Planet")
#time.sleep(0.001)
# send UI string as OSC message to Bank 0 8010
# sendbank0(oscaddress, [arg1, arg2,...])
osclientbank0 = OSCClient()
osclientbank0.connect((planetIPout, planetPORTout))
def sendbank0(oscaddress,oscargs=''):
oscmsg = OSCMessage()
oscmsg.setAddress(oscaddress)
oscmsg.append(oscargs)
print "Sending OSC to Bank0 server :", oscaddress,'with args :', oscargs
try:
osclientbank0.sendto(oscmsg, (bank0IPout, bank0PORTout))
oscmsg.clearData()
except:
print 'OSC send to bank0 IP', bank0IPout, 'port', bank0PORTout, "refused : died ?"
sendWSall("/bank0/start 0")
sendWSall("/status No Bank0")
#time.sleep(0.001)
'''
# OSC default path handler : send incoming OSC message to UI via websocket 9001
def handler(path, tags, args, source):
oscpath = path.split("/")
print ""
print "OSC handler in main said : path", path," oscpath ", oscpath," args", args
#print "debug", gstt.debug
#if gstt.debug >0:
# print "default handler"
# print "OSC said path", path," oscpath ", oscpath," args", args
sendWSall(path + " " + str(args[0]))
if gstt.debug > 0:
print ""
print "OSC handler in main said : path", path," oscpath ", oscpath," args", args
if oscpath[1] != "pong":
sendWSall(path + " " + str(args[0]))
commands.handler(oscpath,args)
@ -268,26 +172,19 @@ def osc_frame():
def PingAll():
print ("Pinging all plugins...")
for plugin in gstt.plugins.keys():
# Plugin Online
if plugins.Ping(plugin):
sendWSall("/"+ plugin + "/start 1")
if gstt.debug >0:
print "plugin", plugin, "answered."
print("pinging", plugin)
#sendWSall("/"+ plugin + "/start 0")
plugins.Ping(plugin)
# Plugin Offline
else:
sendWSall("/"+ plugin + "/start 0")
if gstt.debug >0:
print "plugin", plugin, "didn't answered."
# OSC server Thread : handler, dacs reports and simulator points sender to UI.
def osc_thread():
while True:
#while True:
try:
while True:
@ -326,9 +223,9 @@ def osc_thread():
# last number of points sent to etherdream buffer
sendWSall("/points/" + str(laserid) + " " + str(r.get('/cap/'+str(laserid))))
#print "Sending simu frame from",'/pl/'+str(gstt.LasClientNumber)+'/'+str(gstt.Laser)
#print r.get('/pl/'+str(gstt.LasClientNumber)+'/'+str(gstt.Laser))
sendWSall("/simul" +" "+ r.get('/pl/'+str(gstt.LasClientNumber)+'/'+str(gstt.Laser)))
#print "Sending simu frame from",'/pl/'+str(gstt.SceneNumber)+'/'+str(gstt.Laser)
#print r.get('/pl/'+str(gstt.SceneNumber)+'/'+str(gstt.Laser))
sendWSall("/simul" +" "+ r.get('/pl/'+str(gstt.SceneNumber)+'/'+str(gstt.Laser)))
except Exception as e:
@ -350,8 +247,10 @@ def new_client(client, wserver):
sendWSall("/status Hello %d" % client['id'])
for laserid in range(0,gstt.LaserNumber):
sendWSall("/ip/" + str(laserid) + " " + str(gstt.lasersIPS[laserid]))
sendWSall("/kpps/" + str(laserid)+ " " + str(gstt.kpps[laserid]))
sendWSall("/laser"+str(laserid)+"/start 1")
if gstt.swapX[laserid] == 1:
sendWSall("/swap/X/" + str(laserid)+ " 1")
@ -383,6 +282,7 @@ def message_received(client, wserver, message):
oscpath = message.split(" ")
if gstt.debug > 0:
print "WS Client", client['id'], "said :", message, "splitted in an oscpath :", oscpath
PingAll()
message4plugin = False
@ -394,42 +294,10 @@ def message_received(client, wserver, message):
message4plugin = True
if plugins.Send(plugin,oscpath):
print "message sent correctly to", plugin
#plugins.sendWSall("/status Running...")
print "message sent correctly to", plugin
else:
print"plugin was offline"
'''
if plugins.Send("planet",oscpath):
pass
elif plugins.Send("nozoid",oscpath):
pass
elif plugins.Send("ai",oscpath):
pass
elif plugins.Send("lissa",oscpath):
pass
elif plugins.Send("bank0",oscpath):
pass
elif plugins.Send("simu",oscpath):
pass
elif len(oscpath) > 1:
args[0] = str(oscpath[1])
commands.handler(oscpath[0].split("/"),args)
#print oscpath[0].split("/"),oscpath[1]
if oscpath[0] == "/on":
if oscpath[1] == "1":
sendoscserver("/on")
else:
sendoscserver("/off")
'''
# WS received message is an LJ command
@ -448,46 +316,6 @@ def message_received(client, wserver, message):
print ""
'''
# I message included "nozoid" forward the message as OSC to nozoid IP port 8003
elif oscpath[0].find("nozoid") != -1:
if plugins.Ping("nozoid"):
sendWSall("/nozoid/start 1")
if oscpath[0].find("start") != -1:
print "Nozoid 0",oscpath[0],"1", oscpath[1]
if len(oscpath) == 1:
sendnozosc(oscpath[0], oscargs='noargs')
else:
sendnozosc(oscpath[0], oscargs=oscpath[1])
else:
sendWSall("/status Nozoid offline")
sendWSall("/planet/start 0")
# If message included "ai" do something
elif oscpath[0].find("ai") != -1:
print "ai order ", oscpath
# If message included "lissa" do something
elif oscpath[0].find("lissa") != -1:
print "lissa order ", oscpath
# If message included "bank0" do something
elif oscpath[0].find("bank0") != -1:
if plugins.Ping("bank0"):
if len(oscpath) == 1:
sendbank0(oscpath[0], oscargs='noargs')
else:
sendbank0(oscpath[0], oscargs=oscpath[1])
else:
sendWSall("/status Bank0 offline")
'''
# if needed a loop back : WS Client -> server -> WS Client
#sendWSall("ws"+message)
@ -501,13 +329,18 @@ def sendWSall(message):
#if gstt.debug >0:
#print("WS sending %s" % (message))
wserver.send_message_to_all(message)
'''
print ""
print "Midi Configuration"
midi.InConfig()
midi.OutConfig()
'''
# Creating a startup point list for each client : 0,1,2,...
print ""
for clientid in range(0,gstt.MaxLasClient):
for clientid in range(0,gstt.MaxScenes+1):
print "Creating startup point lists for client",clientid,"..."
digit_points = font1.DigitsDots(clientid,65280)
@ -519,8 +352,8 @@ for clientid in range(0,gstt.MaxLasClient):
r.set('/order/'+str(laserid), 0)
if r.set("/clientkey","/pl/"+str(gstt.LasClientNumber)+"/")==True:
print "sent clientkey : /pl/"+str(gstt.LasClientNumber)+"/"
if r.set("/clientkey","/pl/"+str(gstt.SceneNumber)+"/")==True:
print "sent clientkey : /pl/"+str(gstt.SceneNumber)+"/"
print ""
print "Etherdream connection check is NOT DISPLAYED"
@ -579,9 +412,8 @@ try:
print "Resetting all Homographies.."
for laserid in range(0,gstt.LaserNumber):
homographyp.newEDH(laserid)
print ""
print "ws server running forver..."
print "WS server running forever..."
wserver.run_forever()

File diff suppressed because it is too large Load Diff

View File

@ -24,33 +24,67 @@ import pdb
from datetime import datetime
from random import randrange
import redis
import lj3
import sys,time,traceback
import sys
import ast
import os
import time,traceback
ljpath = r'%s' % os.getcwd().replace('\\','/')
# import from shell
sys.path.append(ljpath +'/../../libs/')
print(ljpath +'/../../libs/')
#import from LJ
sys.path.append(ljpath +'/libs/')
print (ljpath +'/libs/')
is_py2 = sys.version[0] == '2'
if is_py2:
from OSC import OSCServer, OSCClient, OSCMessage
else:
from OSC3 import OSCServer, OSCClient, OSCMessage
import lj23 as lj3
'''
from osc4py3.as_eventloop import *
from osc4py3 import oscbuildparse
#from osc4py3 import oscmethod as osm
from osc4py3.oscmethod import *
'''
import argparse
# 0.25 : each frame will be repeated 4 times.
animspeed = 0.25
animspeed = 0.1
screen_size = [700,700]
xy_center = [screen_size[0]/2,screen_size[1]/2]
message = "LO"
message = "TEAMLASER"
OSCinPort = 8011
ljclient = 0
idiotiaDisplay = [True,True,False,False]
#idiotiaDisplay = [False,False,False,False]
liveDisplay = [False,False,False,False]
#liveDisplay = [False,False,False,False]
fieldsDisplay = [False,False,True,True]
liveDisplay = [True, True, True, True]
#fieldsDisplay = [True,True,True,True]
idiotiaDisplay = [False, False, False, False]
fieldsDisplay = [False, False, False, False]
'''
fieldsDisplay = [False,False,True,True]
'''
#idiotiaDisplay = [True,True,False,False]
currentIdiotia = 0
print ("")
@ -97,10 +131,29 @@ else:
if args.Lasers != None:
LaserNumber = args.Lasers
else:
LaserNumber = 4
LaserNumber = 1
lj3.Config(redisIP,ljclient)
r = lj3.Config(redisIP,ljclient,"pose")
#
# 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
import types
oscserver.handle_timeout = types.MethodType(handle_timeout, oscserver)
@ -119,11 +172,14 @@ import json
# Get frame number for pose path describe in PoseDir
def lengthPOSE(pose_dir):
#if debug > 0:
# print("Check directory",'poses/' + pose_dir)
if os.path.exists('poses/' + pose_dir):
numfiles = sum(1 for f in os.listdir('poses/' + pose_dir) if os.path.isfile(os.path.join('poses/' + pose_dir + '/', f)) and f[0] != '.')
return numfiles
if debug > 0:
print("Checking directory",'plugins/VJing/poses/' + pose_dir)
if os.path.exists('plugins/VJing/poses/' + pose_dir):
numfiles = sum(1 for f in os.listdir('plugins/VJing/poses/' + pose_dir) if os.path.isfile(os.path.join('plugins/VJing/poses/' + pose_dir + '/', f)) and f[0] != '.')
if debug > 0:
print(numfiles, 'frames')
return numfiles
else:
if debug > 0:
print("but it doesn't even exist!")
@ -166,11 +222,108 @@ def prepareIdiotIA(currentAnim):
anim[5] = lengthPOSE(anim[0])
WebStatus("Checking "+ anim[0] +"...")
if debug > 0:
print('poses/' + anim[0], "length :", anim[5], "frames")
print('plugins/VJing/poses/' + anim[0], "length :", anim[5], "frames")
print("Current IdiotIA anim is",anims[currentIdiotia][0],"("+str(currentIdiotia)+")")
'''
pose_keypoints_2d
face_keypoints_2d
hand_left_keypoints_2d
hand_right_keypoints_2d
pose_keypoints_3d
face_keypoints_3d
hand_left_keypoints_3d
hand_right_keypoints_3d
"/0/face_keypoints_2d"
"[-0.0946419, -0.521328, 0.675269, -0.0883931, -0.413923, 0.69358, -0.0758954, -0.302815, 0.73599, -0.059232, -0.191707, 0.640398, -0.0384026, -0.0917102, 0.683398, -0.00507569, -0.00652742, 0.643006, 0.0428318, 0.0601374, 0.558626, 0.0844904, 0.108284, 0.576597, 0.142813, 0.108284, 0.621916, 0.178223, 0.0749518, 0.546389, 0.207384, 0.0193979, 0.556877, 0.22613, -0.0361562, 0.660514, 0.244876, -0.102821, 0.713871, 0.267789, -0.1843, 0.706604, 0.290701, -0.265779, 0.680418, 0.307364, -0.347258, 0.617497, 0.31153, -0.428738, 0.53877, -0.0446514, -0.547253, 0.784288, -0.00715858, -0.569474, 0.873856, 0.0303342, -0.558364, 0.835336, 0.0740758, -0.543549, 0.827985, 0.111569, -0.525031, 0.809191, 0.213632, -0.543549, 0.819012, 0.242794, -0.569474, 0.884373, 0.265706, -0.5954, 0.842317, 0.292784, -0.613918, 0.804365, 0.313613, -0.625028, 0.740405, 0.163642, -0.443552, 0.805348, 0.169891, -0.362073, 0.837128, 0.169891, -0.280594, 0.839031, 0.174057, -0.213929, 0.68711, 0.111569, -0.162078, 0.725528, 0.134481, -0.154671, 0.837339, 0.159476, -0.150968, 0.887387, 0.178223, -0.158375, 0.835752, 0.196969, -0.180597, 0.698174, 0.00950491, -0.432441, 0.864517, 0.0345001, -0.458366, 0.859197, 0.0636612, -0.46207, 0.867471, 0.0907393, -0.432441, 0.852409, 0.0636612, -0.417627, 0.876186, 0.0324172, -0.413923, 0.834265, 0.21155, -0.454663, 0.875569, 0.232379, -0.491699, 0.816674, 0.26154, -0.50281, 0.878064, 0.282369, -0.476884, 0.839634, 0.263623, -0.450959, 0.912212, 0.24071, -0.450959, 0.896937, 0.0719929, -0.047267, 0.761505, 0.101154, -0.065785, 0.864081, 0.130315, -0.0694886, 0.910774, 0.159476, -0.065785, 0.895222, 0.17614, -0.0731922, 0.846551, 0.194886, -0.0731922, 0.74389, 0.209467, -0.0731922, 0.573107, 0.194886, -0.0213418, 0.677465, 0.17614, 0.0156941, 0.755373, 0.15531, 0.0231014, 0.765641, 0.124066, 0.0231014, 0.863117, 0.0928223, -0.00282377, 0.823042, 0.0928223, -0.0398598, 0.743914, 0.128232, -0.0361562, 0.932259, 0.157393, -0.0361562, 0.877732, 0.17614, -0.0398598, 0.853163, 0.196969, -0.0620813, 0.645926, 0.17614, -0.0398598, 0.80738, 0.157393, -0.0324526, 0.872388, 0.128232, -0.0361562, 0.924673, 0.0511636, -0.450959, 0.801577, 0.244876, -0.480588, 0.915322]"
"/peopleCount"
"2"
'''
def bodyREDIS(people):
dots = []
pose = []
redispose = []
pose_points = [10,9,8,1,11,12,13]
print ("people body", people)
print ("/"+str(people)+"/pose_keypoints_2d")
#pose = np.array(ast.literal_eval(r.get("/"+str(people)+"/pose_keypoints_2d")))
redispose = r.get("/"+str(people)+"/pose_keypoints_2d")
#print ("redispose",redispose)
poseast = ast.literal_eval(redispose)
#print ("poseast",poseast)
#print (poseast[0])
pose = np.array(poseast)
#print (np.array((ast.literal_eval(strg))))
#print pose
#print(pose[0], pose[1])
#print("len pose", len(pose))
'''
for dot in range(len(pose)/3):
#print dot
dots.append(((pose[dot * 3], pose[(dot * 3)+1])))
#print((pose[dot * 3], pose[(dot * 3)+1]))
'''
for dot in range(len(pose_points)):
bodypoint = pose_points[dot]
if pose[bodypoint * 3] != -1 and pose[(bodypoint * 3)+1] != -1:
dots.append(((pose[bodypoint * 3], pose[(bodypoint * 3)+1])))
#print((pose[dot * 3], pose[(dot * 3)+1]))
#print "body point ", pose_points[dot],dot, (pose[bodypoint * 3], pose[(bodypoint * 3)+1])
print dots
return dots
# display the Realtime open pose face according to flag.
def LivePose():
laser = 0
# Old style : if display flag is True for given laser, send the face points.
# New style : should send the people points in a PL, then use the PL's dest object to describe
# what to do with it
if liveDisplay[0]:
peoplenumber = int(r.get("/peopleCount"))
print peoplenumber
for currentnumber in range(peoplenumber):
PL = 0
#print PL, anim
# Draw Pose
x_offset = 26 * (- (0.9*peoplenumber) + 3*currentnumber)
for people in range(peoplenumber):
print("people", people)
x_offset = 26 * (- (0.9*peoplenumber) + 3*currentnumber)
print x_offset
lj3.rPolyLineOneColor(bodyREDIS(people), c= white, PL = PL, closed = False, xpos = xy_center[0]+ x_offset, ypos = xy_center[1], resize = 250)
lj3.DrawPL(PL)
# get relative (-1 0 1) body position points. a position -1, -1 means doesn't exist
def getBODY(pose_json,pose_points, people):
dots = []
for dot in pose_points:
#print pose_points
if len(pose_json['people'][people]['pose_keypoints_2d']) != 0:
#print "people 0"
if pose_json['people'][people]['pose_keypoints_2d'][dot * 3] != -1 and pose_json['people'][people]['pose_keypoints_2d'][(dot * 3)+1] != -1:
dots.append((pose_json['people'][people]['pose_keypoints_2d'][dot * 3], pose_json['people'][people]['pose_keypoints_2d'][(dot * 3)+1]))
return dots
# get absolute face position points
def getFACE(pose_json,pose_points, people):
@ -185,6 +338,21 @@ def getFACE(pose_json,pose_points, people):
return dots
# Body parts
def bodyCOCO(pose_json, people):
pose_points = [10,9,8,1,11,12,13]
return getBODY(pose_json,pose_points, people)
def armCOCO(pose_json, people):
pose_points = [7,6,5,1,2,3,4]
return getBODY(pose_json,pose_points, people)
def headCOCO(pose_json, people):
pose_points = [1,0]
return getBODY(pose_json,pose_points, people)
# Face keypoints
def face(pose_json, people):
pose_points = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
@ -239,22 +407,20 @@ def IdiotIA():
anim = anims[currentIdiotia]
#print(anim)
PL = laser
#print PL, anim
dots = []
# increase current frame [4] of speed [7] frames
#print(anim[4],anim[7],anim[4]+anim[7])
# print(anim[4],anim[7],anim[4]+anim[7])
# print("frame", anim[4])
anim[4] = anim[4]+anim[7]
# print("animspeed",anim[7], "newframe", anim[4], "maximum frame", anim[5] )
# compare to total frame [5]
if anim[4] >= anim[5]:
anim[4] = 0
posename = 'poses/' + anim[0] + '/' + anim[0] +'-'+str("%05d"%int(anim[4]))+'.json'
posename = 'plugins/VJing/poses/' + anim[0] + '/' + anim[0] +'-'+str("%05d"%int(anim[4]))+'.json'
# print(posename)
posefile = open(posename , 'r')
posedatas = posefile.read()
pose_json = json.loads(posedatas)
@ -421,12 +587,47 @@ def Starfield(hori=0,verti=0):
lj3.DrawPL(laser)
# display the Realtime open pose face according to flag.
def LiveFace():
# All laser loop
for laser in range(LaserNumber):
# for anim in anims[laseranims]:
print ("laser", laser)
# if display flag is True, send the face points.
if liveDisplay[laser]:
PL = laser
#print PL, anim
dots = []
pose_json = json.loads(posedatas)
# Draw Face
for people in range(len(pose_json['people'])):
r.get(n)
lj3.rPolyLineOneColor(bodyCOCO(pose_json, people), c=colorify.rgb2hex(gstt.color), PL = 0, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
lj3.rPolyLineOneColor(armCOCO(pose_json, people), c=colorify.rgb2hex(gstt.color), PL = 0, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
lj3.rPolyLineOneColor(headCOCO(pose_json, people), c=colorify.rgb2hex(gstt.color), PL = 0, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
#lj3.rPolyLineOneColor(face(pose_json, people), c = white, PL = laser closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
lj3.rPolyLineOneColor(browL(pose_json, people), c = white, PL = laser, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
lj3.rPolyLineOneColor(browR(pose_json, people), c = white, PL = laser, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
lj3.rPolyLineOneColor(eyeR(pose_json, people), c = white, PL = laser, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
#lj3.rPolyLineOneColor(pupR(pose_json, people), c = white, PL = laser, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
lj3.rPolyLineOneColor(eyeL(pose_json, people), c = white, PL = laser, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
#lj3.rPolyLineOneColor(pupL(pose_json, people), c = white, PL = laser, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
lj3.rPolyLineOneColor(nose(pose_json, people), c = white, PL = laser, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
lj3.rPolyLineOneColor(mouth(pose_json, people), c = white, PL = laser, closed = False, xpos = anim[1], ypos = anim[2], resize = anim[3])
lj3.DrawPL(PL)
# if display flag is True, send the face points.
if liveDisplay[laser]:
@ -435,18 +636,20 @@ def LiveFace():
# /pose/idiotia/lasernumber 1
def OSCidiotia(address, value):
def OSCidiotia(path, tags, args, source):
print("pose idiotia got ",address,value)
laser = int(address[14:])
print("laser", laser, value)
print("pose idiotia got",path, args)
laser = int(args[0])
value = int(args[1])
if value == "1" or value == 1:
if value == 1:
print("switch on idiotia for laser", laser, value)
idiotiaDisplay[laser] = True
liveDisplay[laser] = False
fieldsDisplay[laser] = False
print(idiotiaDisplay,liveDisplay,fieldsDisplay)
#print(idiotiaDisplay,liveDisplay,fieldsDisplay)
else:
@ -455,58 +658,65 @@ def OSCidiotia(address, value):
UpdatePoseUI()
# /pose/anim/animnumber 1
def OSCanim(address, value):
global currentIdiotia
print("pose anim got :", address, type(value), value)
anim = int(address[11:])
print("anim", anim)
if value == "1" or value == 1:
# /pose/anim
def OSCanim(path, tags, args, source):
print("pose anim got",path, args)
anim = int(args[0])
state = int(args[1])
#print(anim, state)
if state == 1:
print("/pose/anim switch to",anim)
currentIdiotia = anim
UpdatePoseUI()
WebStatus("Running "+ anims[currentIdiotia][0]+"...")
WebStatus("Ruuning "+ anims[currentIdiotia][0]+"...")
# /pose/live/lasernumber value
def OSClive(address, value):
def OSClive(path, tags, args, source):
print("live",address,value)
laser = int(address[11:])
#print("laser", laser, value)
print("pose live got",path, args)
laser = int(args[0])
value = int(args[1])
if value == "1" or value == 1:
idiotiaDisplay[laser] = False
liveDisplay[laser] = True
fieldsDisplay[laser] = False
if value == "1":
print("live for laser", laser)
idiotiaDisplay[value] = False
liveDisplay[value] = True
fieldsDisplay[value] = False
UpdatePoseUI()
# /pose/field/lasernumber value
def OSCfield(address, value):
def OSCfield(path, tags, args, source):
print("Pose field got", address, "with value", type(value), value)
laser = int(address[12:])
#print("laser", laser, value)
print("pose field got",path, args)
laser = int(args[0])
value = int(args[1])
if value == "1" or value == 1:
print("field",laser,"true")
idiotiaDisplay[laser] = False
liveDisplay[laser] = False
fieldsDisplay[laser] = True
if value == "1":
print("field for laser", laser)
idiotiaDisplay[value] = False
liveDisplay[value] = False
fieldsDisplay[value] = True
UpdatePoseUI()
# /pose/ljclient
def OSCljclient(value):
print("Pose bank got /pose/ljclient with value", value)
ljclient = value
lj3.LjClient(ljclient)
def OSCljclient(path, tags, args, source):
print("pose got /viewgen/ljclient with value", args[0])
lj.WebStatus("viewgen to virtual "+ str(args[0]))
ljclient = args[0]
lj.LjClient(ljclient)
# /pose/ping value
def OSCping(value):
lj3.OSCping("pose")
'''
# Starfield, idiotia
@ -515,7 +725,7 @@ def OSCrun(value):
print("Pose bank got /run with value", value)
doit = value
'''
'''
# /quit
def OSCquit():
@ -523,6 +733,7 @@ def OSCquit():
print("Stopping OSC...")
lj3.OSCstop()
sys.exit()
'''
def WebStatus(message):
lj3.SendLJ("/status",message)
@ -561,20 +772,13 @@ def UpdatePoseUI():
print('Loading Pose bank...')
WebStatus("Loading Pose bank...")
# OSC Server callbacks
print("Starting OSC server at", myIP, ":", OSCinPort, "...")
osc_startup()
osc_udp_server(myIP, OSCinPort, "InPort")
#osc_method("/pose/run*", OSCrun)
osc_method("/ping*", OSCping)
osc_method("/pose/ljclient", OSCljclient)
osc_method("/quit", OSCquit)
osc_method("/pose/idiotia/*", OSCidiotia, argscheme=OSCARG_ADDRESS + OSCARG_DATAUNPACK)
osc_method("/pose/field/*", OSCfield,argscheme=OSCARG_ADDRESS + OSCARG_DATAUNPACK)
osc_method("/pose/live/*", OSClive, argscheme=OSCARG_ADDRESS + OSCARG_DATAUNPACK)
osc_method("/pose/anim/*", OSCanim, argscheme=OSCARG_ADDRESS + OSCARG_DATAUNPACK)
oscserver.addMsgHandler("/pose/ljclient", OSCljclient)
oscserver.addMsgHandler("/pose/idiotia", OSCidiotia)
oscserver.addMsgHandler("/pose/field", OSCfield)
oscserver.addMsgHandler("/pose/live", OSClive)
oscserver.addMsgHandler("/pose/anim", OSCanim)
# Add OSC generic plugins commands : 'default", /ping, /quit, /pluginame/obj, /pluginame/var, /pluginame/adddest, /pluginame/deldest
lj3.addOSCdefaults(oscserver)
anims =[[]]*19
@ -593,21 +797,22 @@ green = lj3.rgb2int(0,255,0)
print("Updating Pose UI...")
UpdatePoseUI()
WebStatus("Running "+ anims[currentIdiotia][0]+"...")
WebStatus("Pose "+ anims[currentIdiotia][0]+".")
#WebStatus("Pose bank running.")
#print("Pose bank running")
print("Running "+ anims[currentIdiotia][0]+" on " + str(LaserNumber) +" lasers.")
print("Pose "+ anims[currentIdiotia][0]+" ready on " + str(LaserNumber) +" lasers.")
def Run():
try:
while 1:
while lj3.oscrun:
lj3.OSCframe()
# If you want an idea
# t0 = time.time()
Starfield(hori=0,verti=0)
IdiotIA()
lj3.OSCframe()
#Starfield(hori=0,verti=0)
#IdiotIA()
LivePose()
#LiveFace()
time.sleep(0.002)
#t1 = time.time()

View File

@ -76,7 +76,7 @@ BALL_MAX = 4
BALL_SIZE_X = 3
BALL_SIZE_Y = 3
LASER_ANGLE = 0
plnumber = 0
GRAVITY = 0.0001
@ -122,6 +122,7 @@ def LogoDraw(plnumber):
for xy in pl_color[0]:
xy_list.append((LOGO_OFFSET_X + xy[0], LOGO_OFFSET_Y + xy[1]))
#print xy_list
#print plnumber
lj.PolyLineOneColor(xy_list, c, plnumber, False)

View File

@ -1,322 +0,0 @@
# coding=UTF-8
'''
LJ v0.8.1
Some LJ functions useful for python 2.7 clients (was framy.py)
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
redisIP = '127.0.0.1'
r = redis.StrictRedis(host=redisIP, port=6379, db=0)
ClientNumber = 0
point_list = []
pl = [[],[],[],[]]
def SendLJ(oscaddress,oscargs=''):
oscmsg = OSCMessage()
oscmsg.setAddress(oscaddress)
oscmsg.append(oscargs)
print ("sending OSC message : ",oscmsg)
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(redisIP,client):
global ClientNumber
r = redis.StrictRedis(host=redisIP, port=6379, db=0)
ClientNumber = client
#print "client configured",ClientNumber
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 = 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)

View File

@ -14,6 +14,9 @@ import itertools
import sys
import os
import types
sys.path.append('../../../libs')
import lj
'''
is_py2 = sys.version[0] == '2'
@ -26,7 +29,7 @@ else:
import thread
import time
import random
import lj
import lj23 as lj
import entities
from controller import setup_controls
import argparse
@ -116,13 +119,15 @@ if args.laser:
else:
plnumber = 0
entities.plnumber = plnumber
# Redis Computer IP
if args.redisIP != None:
redisIP = args.redisIP
else:
redisIP = '127.0.0.1'
lj.Config(redisIP,ljclient)
lj.Config(redisIP,ljclient,"ljpong")
def StartPlaying(first_time = False):
@ -209,24 +214,26 @@ OSCRunning = True
def OSCljclient(path, tags, args, source):
print("LJ Pong got /ljpong/ljclient with value", args[0])
print("LJPong got /ljpong/ljclient with value", args[0])
lj.WebStatus("LJPong to virtual "+ str(args[0]))
ljclient = args[0]
lj.LjClient(ljclient)
def OSCpl(path, tags, args, source):
global plnumber
print("LJ Pong got /ljpong/pl with value", args[0])
lj.WebStatus("LJPong to pl "+ str(args[0]))
plnumber = args[0]
plnumber = int(args[0])
lj.LjPl(plnumber)
'''
# /ping
def OSCping(path, tags, args, source):
print("LJ Pong got /ping")
lj.SendLJ("/pong","ljpong")
lj.SendLJ("/ljpong/start",1)
'''
def OSC_frame():
# clear timed_out flag
@ -246,10 +253,10 @@ print "at", OSCIP, "port",str(OSCPort)
oscserver.handle_timeout = types.MethodType(handle_timeout, oscserver)
# OSC callbacks
lj.addOSCdefaults(oscserver)
oscserver.addMsgHandler( "/ljpong/ljclient", OSCljclient )
oscserver.addMsgHandler("/ljpong/pl", OSCpl)
oscserver.addMsgHandler("/ping", OSCping)
#oscserver.addMsgHandler("/ping", lj.OSCping)
print "Running..."

View File

@ -1,27 +1,55 @@
# coding=UTF-8
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# -*- mode: Python -*-
'''
Laserglyph
v0.1.0
Anaglyphed rotating cube (for red and green glasses)
This client uses the drawing functions (polyline) provided by LJ in lj.py
You must check in lj.py if the redis server IP is correct.
LICENCE : CC
'''
by Sam Neurohack
'''
import sys
import os
print()
ljpath = r'%s' % os.getcwd().replace('\\','/')
# import from shell
sys.path.append(ljpath +'/../libs/')
#import from LJ
sys.path.append(ljpath +'/libs/')
print (ljpath+'/../libs/')
import lj23 as lj
from OSC3 import OSCServer, OSCClient, OSCMessage
import redis
import lj3
import math
import time
import argparse
'''
from osc4py3.as_eventloop import *
from osc4py3 import oscbuildparse
#from osc4py3 import oscmethod as osm
from osc4py3.oscmethod import *
'''
OSCinPort = 8004
myIP = "192.168.2.52"
oscrun = True
# myIP = "127.0.0.1"
PL = 0
print ("")
print ("Arguments parsing if needed...")
@ -59,7 +87,7 @@ if args.myIP != None:
else:
myIP = '127.0.0.1'
print("redisIP",redisIP)
print("myIP",myIP)
if args.verbose:
debug = args.verbose
@ -67,8 +95,12 @@ else:
debug = 0
lj3.Config(redisIP,ljclient)
lj.Config(redisIP,ljclient,"glyph")
white = lj.rgb2int(255,255,255)
red = lj.rgb2int(255,0,0)
blue = lj.rgb2int(0,0,255)
green = lj.rgb2int(0,255,0)
width = 800
height = 600
@ -87,7 +119,7 @@ observer_altitude = 30000
#observer_altitude = 10000
# elevation = z coordinate
# 0.0, -2000 pop out
map_plane_altitude = 0.0
map_plane_altitude = 0.0
# Cube coordinates
# Define the vertices that compose each of the 6 faces.
@ -101,9 +133,29 @@ vertices = [
( 1.0,- 1.0, 1.0),
(- 1.0,- 1.0, 1.0)
]
faces = [(0,1,2,3),(0,4,5,1),(1,5,6,2),(2,3,7,6),(6,5,4,7),(7,3,0,4)]
#faces = [(0,1,2,3),(0,4,5,1),(1,5,6,2),(2,3,7,6),(6,5,4,7),(7,3,0,4)]
faces = [(0,1,2,3),(0,4,5,1),(1,5,6,2),(2,3,7,6),(7,3,0,4),(7,3,0,4)]
# name, intensity, active, xy, color, red, green, blue, PL , closed):
Leftcube = lj.FixedObject('Leftcube', True, 255, [], red, 255, 0, 0, PL , True)
Rightcube = lj.FixedObject('Rightcube', True, 255, [], green, 0, 255, 0, PL , True)
# 'Destination' for each PL
# name, number, active, PL , scene, laser
# PL 0
Dest0 = lj.DestObject('0', 0, True, 0 , 0, 0)
Dest1 = lj.DestObject('1', 1, True, 0 , 1, 1)
'''
viewgen3Lasers = [True,False,False,False]
# Add here, one by one, as much destination as you want for each PL.
# LJ and OSC can remotely add/delete destinations here.
lj.Dests = {
"0": {"PL": 0, "scene": 0, "laser": 0},
"1": {"PL": 0, "scene": 1, "laser": 1}
}
'''
def LeftShift(elevation):
@ -115,29 +167,36 @@ def RightShift(elevation):
diff = map_plane_altitude - elevation
return (1 - nadir) * eye_spacing * diff / (observer_altitude - elevation)
# If you want to use rgb for color :
def rgb2int(r,g,b):
return int('0x%02x%02x%02x' % (r,g,b),0)
def OSCljclient(value):
# OSC
#
print("Glyph got /glyph/ljclient with value", value)
lj3.WebStatus("Glyph to virtual "+ str(value))
ljclient = value
lj3.LjClient(ljclient)
oscserver = OSCServer( (myIP, OSCinPort) )
oscserver.timeout = 0
#oscrun = True
def OSCpl(value):
# 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
print("Glyph got /glyph/pl with value", value)
lj3.WebStatus("Glyph to pl "+ str(value))
lj3.LjPl(value)
# funny python's way to add a method to an instance of a class
import types
oscserver.handle_timeout = types.MethodType(handle_timeout, oscserver)
# OSC callbacks
# /viewgen/ljclient
def OSCljclient(path, tags, args, source):
print("Got /viewgen/ljclient with value", args[0])
lj.WebStatus("viewgen to virtual "+ str(args[0]))
ljclient = args[0]
lj.LjClient(ljclient)
# /pose/ping value
def OSCping(value):
lj3.OSCping("glyph")
'''
def Proj(x,y,z,angleX,angleY,angleZ):
rad = angleX * math.pi / 180
@ -174,18 +233,28 @@ def Run():
Left = []
Right = []
counter =0
lj3.WebStatus("LaserGlyph")
lj.WebStatus("LaserGlyph")
lj.SendLJ("/glyph/start 1")
# OSC Server callbacks
print("Starting OSC at",myIP," port",OSCinPort,"...")
print("Starting OSC server at",myIP," port",OSCinPort,"...")
'''
osc_startup()
osc_udp_server(myIP, OSCinPort, "InPort")
osc_method("/ping*", OSCping)
osc_method("/ping", lj.OSCping)
osc_method("/quit*", quit)
osc_method("/glyph/ljclient", OSCljclient)
'''
oscserver.addMsgHandler( "/glyph/ljclient", OSCljclient )
# Add OSC generic plugins commands : 'default", /ping, /quit, /pluginame/obj, /pluginame/var, /pluginame/adddest, /pluginame/deldest
lj.addOSCdefaults(oscserver)
try:
while 1:
while lj.oscrun:
lj.OSCframe()
Left = []
Right = []
@ -216,24 +285,31 @@ def Run():
# Drawing step, 2 possibilities
# Red and Green drawn by laser 0
lj3.PolyLineOneColor(Left, c = red, PL = 0, closed = True)
lj3.PolyLineOneColor(Right, c = green, PL = 0, closed = True)
lj3.DrawPL(0)
#lj.PolyLineOneColor(Left, c = red, PL = PL, closed = True)
#lj.PolyLineOneColor(Right, c = green, PL = PL, closed = True)
lj.PolyLineOneColor(Left, c = Leftcube.color , PL = Leftcube.PL, closed = Leftcube.closed)
lj.PolyLineOneColor(Right, c = Rightcube.color , PL = Rightcube.PL, closed = Rightcube.closed)
#print(len(Left))
#lj.DrawPL(PL)
#print(Dest0.name, Dest1.name)
lj.DrawDests()
'''
# Red on laser 1 and green on laser 2
lj3.PolyLineOneColor(Left, c = red, PL = 1, closed = True)
lj3.PolyLineOneColor(Right, c = green, PL = 2, closed = True)
lj3.DrawPL(1)
lj3.DrawPL(2)
lj.PolyLineOneColor(Left, c = red, PL = 1, closed = True)
lj.PolyLineOneColor(Right, c = green, PL = 2, closed = True)
lj.DrawPL(1)
lj.DrawPL(2)
'''
time.sleep(0.1)
counter += 1
if counter >360:
counter =0
if counter > 360:
counter = 0
except KeyboardInterrupt:
pass
@ -242,18 +318,7 @@ def Run():
finally:
lj3.WebStatus("Glyph Exit")
print("Stopping OSC...")
lj3.OSCstop()
pass
print ("LaserGlyph Stopped.")
white = rgb2int(255,255,255)
red = rgb2int(255,0,0)
blue = rgb2int(0,0,255)
green = rgb2int(0,255,0)
lj.ClosePlugin()
Run()

View File

@ -6,9 +6,11 @@ LICENCE : CC
'''
import redis
import lj3
import sys,time
import argparse
sys.path.append('../libs')
import lj3
from osc4py3.as_eventloop import *
from osc4py3 import oscbuildparse
@ -20,11 +22,12 @@ myIP = "127.0.0.1"
duration = 300
OSCinPort = 8006
oscrun = True
Word0 = "LASER"
Word1 = "LASER"
Word2 = "LASER"
Word3 = "LASER"
Word0 = "ONE"
Word1 = "TWO"
Word2 = "THREE"
Word3 = "FOUR"
'''
is_py2 = sys.version[0] == '2'
@ -67,7 +70,7 @@ else:
debug = 0
lj3.Config(redisIP,ljclient)
lj3.Config(redisIP,ljclient,"words")
#r = redis.StrictRedis(host=redisIP, port=6379, db=0)
@ -108,17 +111,15 @@ def OSCljclient(value):
# /ping
def OSCping():
lj3.OSCping("words")
lj3.SendLJ("words/text/0",Word0)
lj3.SendLJ("words/text/1",Word1)
# /quit dummyvalue
def quit(value):
# don't do this at home (or it'll quit blender)
global oscrun
# /quit
def OSCquit():
lj3.OSCquit("words")
oscrun = False
print("Stopped by /quit.")
lj3.ClosePlugin()
def Run():
@ -131,9 +132,9 @@ def Run():
osc_method("/words/text/1*", OSCword1)
osc_method("/words/text/2*", OSCword2)
osc_method("/words/text/3*", OSCword3)
osc_method("/ping*", OSCping)
osc_method("/words/ljclient*", OSCljclient)
osc_method("/quit", OSCquit)
osc_method("/ping", lj3.OSCping)
osc_method("/quit*", quit)
color = lj3.rgb2int(255,255,255)
lj3.WebStatus("Loading Words...")
@ -145,7 +146,7 @@ def Run():
try:
while 1:
while oscrun:
lj3.OSCframe()
@ -170,11 +171,8 @@ def Run():
finally:
lj3.WebStatus("Words Exit")
print("Stopping Words OSC...")
lj3.OSCstop()
lj3.ClosePlugin()
print ("Words Stopped.")
Run()

241
plugins/livewords3.py Normal file
View File

@ -0,0 +1,241 @@
# coding=UTF-8
'''
Live words on different lasers
LICENCE : CC
'''
import redis
import sys,time
import argparse
import os
ljpath = r'%s' % os.getcwd().replace('\\','/')
# import from shell
sys.path.append('../libs')
#import from LJ
sys.path.append(ljpath +'/libs/')
#print (ljpath+'/libs')
import lj23 as lj
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...")
myIP = "127.0.0.1"
duration = 300
OSCinPort = 8006
oscrun = True
Word0 = "BRAINFUCK"
Word1 = "D"
Word2 = "CAPTCHA"
Word3 = "D"
'''
is_py2 = sys.version[0] == '2'
if is_py2:
from Queue import Queue
else:
from queue import Queue
'''
print ("Words is checking arguments parsing if needed...")
argsparser = argparse.ArgumentParser(description="Text Cycling for LJ")
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("-c","--client",help="LJ client number (0 by default)",type=int)
argsparser.add_argument("-v","--verbose",help="Verbosity level (0 by default)",type=int)
args = argsparser.parse_args()
if args.client:
ljclient = args.client
else:
ljclient = 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'
if args.verbose:
debug = args.verbose
else:
debug = 0
lj.Config(redisIP,ljclient,"words")
#r = redis.StrictRedis(host=redisIP, port=6379, db=0)
# 'Destination' for each PL
# name, number, active, PL , scene, laser
# PL 0
Dest0 = lj.DestObject('0', 0, True, 0, 0, 0)
# PL 1
Dest1 = lj.DestObject('1', 1, True, 1, 0, 1)
# PL 2
Dest2 = lj.DestObject('2', 2, True, 2, 0, 2)
# PL 3
Dest3 = lj.DestObject('3', 3, True, 3, 0, 3)
#
# 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
import types
oscserver.handle_timeout = types.MethodType(handle_timeout, oscserver)
# 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():
oscserver.close()
def OSCword0(value):
global Word0
# Will receive message address, and message data flattened in s, x, y
print("Words 0 got /words/text/0 with value", value)
Word0 = value
def OSCword1(value):
global Word1
# Will receive message address, and message data flattened in s, x, y
print("Words 1 got /words/text/1 with value", value)
Word1 = value
def OSCword2(value):
global Word2
# Will receive message address, and message data flattened in s, x, y
print("Words 2 got /words/text/2 with value", value)
Word2 = value
def OSCword3(value):
global Word3
# Will receive message address, and message data flattened in s, x, y
print("Words 3 got /words/text/3 with value", value)
Word3 = value
def OSCljclient(value):
# Will receive message address, and message data flattened in s, x, y
print("Words got /words/ljclient with value", value)
lj.WebStatus("Words to virtual "+ str(value))
ljclient = value
lj.LjClient(ljclient)
# /quit dummyvalue
def quit(value):
# don't do this at home (or it'll quit blender)
global oscrun
oscrun = False
print("Stopped by /quit.")
lj.ClosePlugin()
def Run():
# OSC Server callbacks
print("Words starting its OSC server at", myIP, "port",OSCinPort,"...")
#oscserver.addMsgHandler( "default", lj.OSChandler )
#oscserver.addMsgHandler( "/words/ljclient", OSCljclient )
oscserver.addMsgHandler( "/words/text/0", OSCword0)
oscserver.addMsgHandler( "/words/text/1", OSCword1)
oscserver.addMsgHandler( "/words/text/2", OSCword2)
oscserver.addMsgHandler( "/words/text/3", OSCword3)
#oscserver.addMsgHandler( "/ping", lj.OSCping)
#oscserver.addMsgHandler( "/quit", lj.OSCquit)
# Add OSC generic plugins commands : 'default", /ping, /quit, /pluginame/obj, /pluginame/var, /pluginame/adddest, /pluginame/deldest
lj.addOSCdefaults(oscserver)
color = lj.rgb2int(0,255,0)
lj.WebStatus("Loading Words...")
lj.WebStatus("Words ready.")
lj.SendLJ("/words/start 1")
lj.SendLJ("words/text/0",Word0)
lj.SendLJ("words/text/1",Word1)
try:
while lj.oscrun:
OSCframe()
lj.Text(Word0, color, PL = 0, xpos = 300, ypos = 300, resize = 1, rotx =0, roty =0 , rotz=0)
#lj.DrawPL(0)
lj.Text(Word1, color, PL = 1, xpos = 300, ypos = 300, resize = 1, rotx =0, roty =0 , rotz=0)
#lj.DrawPL(1)
lj.Text(Word2, color, PL = 2, xpos = 300, ypos = 300, resize = 1, rotx =0, roty =0 , rotz=0)
#lj.DrawPL(2)
lj.Text(Word3, color, PL = 3, xpos = 300, ypos = 300, resize = 1, rotx =0, roty =0 , rotz=0)
#lj.DrawPL(3)
lj.DrawDests()
time.sleep(0.01)
except KeyboardInterrupt:
pass
# Gently stop on CTRL C
finally:
lj.ClosePlugin()
OSCstop()
Run()

View File

@ -1,645 +0,0 @@
# coding=UTF-8
'''
lj3 v0.8.1
Some LJ functions useful for python clients (was framy.py)
OSC functions commented, waiting working on OSC in python3
Config(redisIP, client number)
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.
OSCstart(): Start the OSC system.
OSCframe(): Handle incoming OSC message. Calling the right callback
OSCstop(): Properly close the OSC system
OSCping(value): Answer to LJ pings by sending /pong value
OSCquit(name): 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)
ClientNumber = 0
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)
osc_send(msg, "LJ 8002")
OSCframe()
except:
print ('Connection to LJ refused : died ?')
pass
def WebStatus(message):
SendLJ("/status", message)
# Answer to LJ pings with /pong pluginame
def OSCping(value):
SendLJ("/pong",value)
# /quit
def OSCquit(name):
WebStatus(name + " quit.")
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):
global ClientNumber, r
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)

1035
plugins/maxwell.py Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,347 +0,0 @@
# coding=UTF-8
'''
LJ v0.8.1 in python3
Some LJ functions useful for python clients (was framy.py)
OSC functions commented, waiting working on OSC in python3
Config(redisIP, client number)
PolyLineOneColor
rPolyLineOneColor
Text(word, color, PL, xpos, ypos, resize, rotx, roty, rotz) : Display a word
Send(adress,message) : 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.
LICENCE : CC
Sam Neurohack
'''
import math
import redis
# Import needed modules from osc4py3
from osc4py3.as_eventloop import *
from osc4py3 import oscbuildparse
#redisIP = '127.0.0.1'
#r = redis.StrictRedis(host=redisIP, port=6379, db=0)
ClientNumber = 0
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])
osc_send(msg, "LJ 8002")
OSCframe()
except:
print ('Connection to LJ refused : died ?')
pass
# Answer to LJ pings
def OSCping(value):
print("I got /ping with value", value)
SendLJ("/pong",value)
'''
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 Config(redisIP,client):
global ClientNumber
r = redis.StrictRedis(host=redisIP, port=6379, db=0)
ClientNumber = client
osc_udp_client(redisIP, 8002, "LJ 8002")
# If you want to use rgb for color :
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 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)

View File

@ -29,6 +29,8 @@ Remember : LJ will automatically warp geometry according to alignement data. See
'''
import redis
import sys
sys.path.append('../../libs')
import lj3
import numpy as np
import math,time
@ -48,7 +50,7 @@ from osc4py3 import oscbuildparse
from osc4py3.oscmethod import *
import json
oscrun = True
'''
is_py2 = sys.version[0] == '2'
if is_py2:
@ -103,7 +105,7 @@ if args.redisIP != None:
else:
redisIP = '127.0.0.1'
lj3.Config(redisIP,ljclient)
lj3.Config(redisIP,ljclient,"planet")
#
# Inits Laser
@ -164,6 +166,42 @@ def Proj(x,y,z,angleX,angleY,angleZ):
# All the coordinates base functions
#
#Transforming coordinates functions by Povik martin.povik@gmail.com
import math
import datetime
def cartesian_to_horizontal(x, y, z):
ele = math.degrees(math.atan2(z, math.sqrt(x * x + y * y)))
az = math.degrees(math.atan2(y, x))
return math.sqrt(x * x + y * y + z * z), ele, az
def horizontal_to_equatorial(az, ele, lat):
az, ele = math.radians(az), math.radians(ele)
lat = math.radians(lat)
cd_ct = math.cos(ele) * math.cos(az) * math.sin(lat) \
+ math.sin(ele) * math.cos(lat)
cd_st = math.cos(ele) * math.sin(az)
sd = -math.cos(ele) * math.cos(az) * math.cos(lat) + math.sin(ele) * math.sin(lat)
cd = math.sqrt(cd_ct * cd_ct + cd_st * cd_st)
return math.atan2(cd_st / cd, cd_ct / cd) * 12 / math.pi, \
math.degrees(math.atan2(sd, cd))
def timestamp_to_jd(timestamp):
return float(timestamp) / 86400 + 2440587.5
def timestamp_to_lst(timestamp, lon):
timestamp = float(timestamp)
timeofday = timestamp % 86400
jd0 = timestamp_to_jd(timestamp - timeofday)
T = (jd0 - 2451545) / 36525
s0 = 6.697374558 + 2400.05133691 * T + 0.000025862 * T**2 \
- 0.0000000017 * T**3
return (s0 + 1.0027379093 * (timeofday / 86400) * 24.0 + float(lon) / 15) % 24
def horizontal_to_equatorial2(az, ele, lat, lon, timestamp):
t, d = horizontal_to_equatorial(az, ele, lat)
return d, (timestamp_to_lst(timestamp, lon) - t) % 24
'''
To minize number of sky objects coordinates conversion : Change planetarium FOV in Ra Dec to select objects
(planets, hipparcos,..). Then get only those objects in AltAz coordinates.
@ -586,13 +624,14 @@ def NewTime(timeshift):
if DisplayAnything:
UpdateAnything()
# /quit
def OSCquit():
# /quit dummyvalue
def quit(value):
# don't do this at home (or it'll quit blender)
global oscrun
WebStatus("Planet stopping")
print("Stopping OSC...")
lj3.OSCstop()
sys.exit()
oscrun = False
print("Stopped by /quit.")
lj3.ClosePlugin()
def OSCUI(value):
# Will receive message address, and message data flattened in s, x, y
@ -615,7 +654,7 @@ try:
osc_udp_server("127.0.0.1", OSCinPort, "InPort")
osc_method("/planet/planetUI*", OSCUI)
osc_method("/ping*", lj3.OSCping)
osc_method("/quit", OSCquit)
osc_method("/quit", quit)
WebStatus("Loading Cities...")
ts = load.timescale()
@ -654,7 +693,7 @@ try:
DisplayAnything = False
print("Start displaying on",lasernumber,"lasers")
while 1:
while oscrun:
for laser in range(lasernumber):

View File

@ -1,4 +1,4 @@
#!/usr/bin/python2.7
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# -*- mode: Python -*-
@ -15,21 +15,42 @@ OSC server with :
/simu/quit
/simu/newpl new pl number to draw
/simu/newclient new client number to draw
/ping
'''
#from __future__ import print_function
import time
import math
import random
import itertools
import traceback
import sys
import os
#import thread
import redis
import pygame
import pdb
import types, ast, argparse
from OSC import OSCServer, OSCClient, OSCMessage
import types, ast, argparse, struct
import numpy as np
sys.path.append('../libs')
# import from LJ
ljpath = r'%s' % os.getcwd().replace('\\','/')
sys.path.append(ljpath +'/libs/')
#print ljpath+'/libs/'
import lj23 as lj
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
screen_size = [750,750]
pl = [[],[],[],[]]
@ -38,8 +59,11 @@ pl = [[],[],[],[]]
print ("")
print ("LJ v0.8.0 : Pygame simulator")
print ("")
import pygame
print ("Arguments parsing if needed...")
#
# Arguments parsing
#
@ -77,7 +101,7 @@ else:
redisIP = '127.0.0.1'
r = redis.StrictRedis(host=redisIP, port=6379, db=0)
lj.Config(redisIP,0,"simu")
# myIP
if args.myIP != None:
@ -101,7 +125,7 @@ print ("")
print ("Receiving on ", oscIPin, ":",str(oscPORTin))
oscserver = OSCServer( (oscIPin, oscPORTin) )
oscserver.timeout = 0
OSCRunning = True
oscrun = True
def handle_timeout(self):
self.timed_out = True
@ -109,10 +133,10 @@ def handle_timeout(self):
oscserver.handle_timeout = types.MethodType(handle_timeout, oscserver)
def sendLJ(address, args):
def SendLJ(address, args):
if debug >0:
print "Sending to LJ...", address, args
print("Sending to LJ...", address, args)
osclientlj = OSCClient()
osclientlj.connect((ljIP, ljPort))
@ -127,9 +151,13 @@ def sendLJ(address, args):
return True
except:
print 'Connection to LJ IP', ljIP,'port', ljPort, 'refused : died ?'
print('Connection to LJ IP', ljIP,'port', ljPort, 'refused : died ?')
return False
def WebStatus(message):
SendLJ("/status",message)
# RAW OSC Frame available ?
def osc_frame():
@ -142,52 +170,42 @@ def osc_frame():
# /quit
def quit(path, tags, args, source):
global oscrun
oscrun = False
pygame.quit()
print "pySimu Stopped by /quit."
sys.exit()
# /start : 0 exit
def start(path, tags, args, source):
print args, type(args)
if args[0] == 0:
pygame.quit()
print "pySimu stopped by /start 0"
sys.exit()
# Answer to LJ pings
def ping(path, tags, args, source):
# Will receive message address, and message data flattened in s, x, y
print "Simu got /ping with value", args[0]
print "Simu replied with /pong simu"
sendLJ("/pong","simu")
lj.ClosePlugin()
# /newPL pointlistnumber
def newPL(path, tags, args, source):
user = ''.join(path.split("/"))
print ""
print user,path,args
print "Simulator got a new point list number :", args[0]
print ("")
print (user,path,args)
print ("Simulator got a new point list number :", args[0])
simuPL = args[0]
# /newClient clientnumber
def newClient(path, tags, args, source):
user = ''.join(path.split("/"))
print ""
print user,path,args
print "Simulator got a new client number : ", args[0]
print ("")
print (user,path,args)
print ("Simulator got a new client number : ", args[0])
ljclient = args[0]
oscserver.addMsgHandler( "/quit", quit )
oscserver.addMsgHandler( "/ping", ping )
oscserver.addMsgHandler( "/pysimu/start", start )
oscserver.addMsgHandler( "/pysimu/newpl", newPL )
oscserver.addMsgHandler( "/pysimu/newclient", newClient )
# Redis key 'n' -> numpy array a
# array 2 dimensions is also store in redis key : h time w values
def fromRedis(n):
print ("get key", n)
encoded = r.get(n)
h, w = struct.unpack('>II',encoded[:8])
print(h,w)
a = np.frombuffer(encoded, dtype=np.int16, offset=8).reshape(h,w)
return a
#
@ -205,15 +223,26 @@ def RenderScreen(surface):
c = int(xyc[2])
if c: pygame.draw.line(surface,c,xyc_prev[:2],xyc[:2],3)
xyc_prev = xyc
#
# Startup
#
SendLJ("/simu/start",1)
WebStatus("pysimu startup...")
pygame.init()
screen = pygame.display.set_mode(screen_size)
pygame.display.set_caption("LJ Simulator")
clock = pygame.time.Clock()
update_screen = False
oscserver.addMsgHandler( "/quit", lj.OSCquit )
oscserver.addMsgHandler( "/ping", lj.OSCping )
#oscserver.addMsgHandler( "/simu/start", start )
oscserver.addMsgHandler( "/simu/newpl", newPL )
oscserver.addMsgHandler( "/simu/newclient", newClient )
print ("Simulator displays client", ljclient, "point list", str(simuPL))
WebStatus("pySimu "+ str(ljclient) + " " + str(simuPL))
#
# Main
@ -221,7 +250,7 @@ print ("Simulator displays client", ljclient, "point list", str(simuPL))
try:
while True:
while lj.oscrun:
# pending osc message ?
osc_frame()
@ -232,8 +261,15 @@ try:
break
screen.fill(0)
pl[simuPL] = ast.literal_eval(r.get("/pl/"+ str(ljclient) + "/" + str(simuPL)))
#print("/pl/"+ str(ljclient) + "/" + str(simuPL))
#print r.get("/pl/"+ str(ljclient) + "/" + str(simuPL))
if is_py2:
pl[simuPL] = ast.literal_eval(r.get("/pl/"+ str(ljclient) + "/" + str(simuPL)))
else:
pl[simuPL] = eval(r.get("/pl/"+ str(ljclient) + "/" + str(simuPL)))
#pl[simuPL] = fromRedis("/pl/"+ str(ljclient) + "/" + str(simuPL))
if update_screen:
update_screen = False
RenderScreen(screen)
@ -242,14 +278,19 @@ try:
update_screen = True
clock.tick(30)
# time.sleep(0.001)
time.sleep(0.001)
except KeyboardInterrupt:
pass
except Exception:
traceback.print_exc()
finally:
pygame.quit()
print "pySimu Stopped."
lj.ClosePlugin()

331
plugins/square.py Normal file
View File

@ -0,0 +1,331 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# -*- mode: Python -*-
'''
Square
v0.1.0
Anaglyphed rotating square (for red and green glasses)
This scene uses the drawing functions (polyline) provided by LJ in lj23.py
LICENCE : CC
by Sam Neurohack
'''
import sys
import os
print()
ljpath = r'%s' % os.getcwd().replace('\\','/')
# import from shell
sys.path.append(ljpath +'/../libs/')
#import from LJ
sys.path.append(ljpath +'/libs/')
print (ljpath+'/../libs/')
import lj23layers as lj
sys.path.append('../libs')
from OSC3 import OSCServer, OSCClient, OSCMessage
import redis
import math
import time
import argparse
OSCinPort = 8013
print ("")
print ("Arguments parsing if needed...")
argsparser = argparse.ArgumentParser(description="Square example for LJ")
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("-s","--scene",help="LJ scene number (0 by default)",type=int)
#argsparser.add_argument("-l","--laser",help="Laser number to be displayed (0 by default)",type=int)
argsparser.add_argument("-v","--verbose",help="Verbosity level (0 by default)",type=int)
argsparser.add_argument("-m","--myIP",help="Local IP (127.0.0.1 by default) ",type=str)
args = argsparser.parse_args()
if args.scene:
ljscene = args.scene
else:
ljscene = 0
'''
if args.laser:
plnumber = args.laser
else:
plnumber = 0
'''
# Redis Computer IP
if args.redisIP != None:
redisIP = args.redisIP
else:
redisIP = '127.0.0.1'
print("redisIP",redisIP)
# myIP
if args.myIP != None:
myIP = args.myIP
else:
myIP = '127.0.0.1'
print("myIP",myIP)
if args.verbose:
debug = args.verbose
else:
debug = 0
# Useful variables init.
white = lj.rgb2int(255,255,255)
red = lj.rgb2int(255,0,0)
blue = lj.rgb2int(0,0,255)
green = lj.rgb2int(0,255,0)
width = 800
height = 600
centerX = width / 2
centerY = height / 2
# 3D to 2D projection parameters
fov = 256
viewer_distance = 2.2
# Anaglyph computation parameters for right and left eyes.
# algorythm come from anaglyph geo maps
eye_spacing = 100
nadir = 0.5
observer_altitude = 30000
map_layerane_altitude = 0.0
# square coordinates : vertices that compose each of the square.
vertices = [
(- 1.0, 1.0,- 1.0),
( 1.0, 1.0,- 1.0),
( 1.0,- 1.0,- 1.0),
(- 1.0,- 1.0,- 1.0)
]
face = [0,1,2,3]
#
# LJ inits
#
layer = 0
# Setup LJ library mandatory properties for this layerugin
lj.Config(redisIP, ljscene, "square")
# Define properties for each drawn "element" : name, intensity, active, xy, color, red, green, blue, layer , closed
Leftsquare = lj.FixedObject('Leftsquare', True, 255, [], red, 255, 0, 0, layer , True)
Rightsquare = lj.FixedObject('Rightsquare', True, 255, [], green, 0, 255, 0, layer , True)
# 'Destination' for given layer : name, number, active, layer , scene, laser
Dest0 = lj.DestObject('0', 0, True, 0 , 0, 0) # Dest0 will send layer 0 points to scene 0, laser 0
'''
TRICKS:
1/ How to have another laser drawing the same thing ?
That's a destination problem : just add another destination !
Dest1 = lj.DestObject('1', 1, True, 0 , 1, 1) # Dest1 will also send layer 0 points to scene 1, laser 1
2/ Different layers to different lasers ?
Say because of too much points you want Left element drawn by scene 0, laser 0 and right element by scene 0, laser 1
First define a different object/layer for each drawn element :
Leftsquare = lj.FixedObject('Leftsquare', True, 255, [], red, 255, 0, 0, 0 , True) # Left goes to layer 0
Rightsquare = lj.FixedObject('Rightsquare', True, 255, [], green, 0, 255, 0, 1 , True) # Right goes to layer 1
Define 2 destinations :
Dest0 = lj.DestObject('0', 0, True, 0 , 0, 0) # Dest0 will send layer 0 points to scene 0, laser 0
Dest1 = lj.DestObject('1', 1, True, 1 , 0, 1) # Dest1 will send layer 1 points to scene 0, laser 1
3/ Different layers to one laser ?
You should consider adding all your points to one layer, but same as 1/ it's a destination problem,
just add another destination with the same scene/laser for each layer
Dest1 = lj.DestObject('1', 1, True, 1 , 0, 0) # Dest1 will also send layer 1 points to scene 0, laser 0
4/ I want to animate/modify anything on the fly : I'm doing a game and suddenly my hero change color.
It's a declared object problem : say Hero is a Fixed Object, you can directly change value of
Hero.name, Hero.active, Hero.intensity, Hero.xy, Hero.color, Hero.red, Hero.green, Hero.blue, Hero.layer, Hero.closed
For a character vanishing in one point you can decrease it's size : RelativeObjects has graphics computation.
PNC.name, PNC.active, PNC.intensity, PNC.xy, PNC.color, PNC.red, PNC.green, PNC.blue, PNC.layer, PNC.closed, PNC.xpos, PNC.ypos, PNC.resize, PNC.rotx, PNC.roty, PNC.rotz
Same for Dest0 if it's a destObject :
Dest0.name, Dest0.number, Dest0.active, Dest0.layer, Dest0.scene, Dest0.laser
DrawDests() will take care of all your declared drawn elements and Destinations.
'''
#
# Anaglyph computation : different X coordinate for each eye
#
def LeftShift(elevation):
diff = elevation - map_layerane_altitude
return nadir * eye_spacing * diff / (observer_altitude - elevation)
def RightShift(elevation):
diff = map_layerane_altitude - elevation
return (1 - nadir) * eye_spacing * diff / (observer_altitude - elevation)
#
# OSC
#
oscserver = OSCServer( (myIP, OSCinPort) )
oscserver.timeout = 0
# 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
import types
oscserver.handle_timeout = types.MethodType(handle_timeout, oscserver)
# OSC callbacks
# /square/ljscene
def OSCljscene(path, tags, args, source):
print("Got /square/ljscene with value", args[0])
lj.WebStatus("square to virtual "+ str(args[0]))
ljscene = args[0]
lj.Ljscene(ljscene)
def Proj(x,y,z,angleX,angleY,angleZ):
rad = angleX * math.pi / 180
cosa = math.cos(rad)
sina = math.sin(rad)
y2 = y
y = y2 * cosa - z * sina
z = y2 * sina + z * cosa
rad = angleY * math.pi / 180
cosa = math.cos(rad)
sina = math.sin(rad)
z2 = z
z = z2 * cosa - x * sina
x = z2 * sina + x * cosa
rad = angleZ * math.pi / 180
cosa = math.cos(rad)
sina = math.sin(rad)
x2 = x
x = x2 * cosa - y * sina
y = x2 * sina + y * cosa
""" Transforms this 3D point to 2D using a perspective projection. """
factor = fov / (viewer_distance + z)
x = x * factor + centerX
y = - y * factor + centerY
return (x,y)
#
# Main
#
def Run():
Left = []
Right = []
counter =0
lj.WebStatus("Square")
lj.SendLJ("/square/start 1")
# OSC Server callbacks
print("Starting OSC server at",myIP," port",OSCinPort,"...")
oscserver.addMsgHandler( "/square/ljscene", OSCljscene )
# Add OSC generic layerugins commands : 'default", /ping, /quit, /pluginame/obj, /pluginame/var, /pluginame/adddest, /pluginame/deldest
lj.addOSCdefaults(oscserver)
try:
while lj.oscrun:
lj.OSCframe()
Left = []
Right = []
x = vertices[0][0]
y = vertices[0][1]
z = vertices[0][2]
# LJ tracers will "move" the laser to this first point in black, then move to the next with second point color.
# For more accuracy in dac emulator, repeat this first point.
# Generate all points in square.
for point in face:
x = vertices[point][0]
y = vertices[point][1]
z = vertices[point][2]
Left.append(Proj(x+LeftShift(z*25),y,z,0,counter,0))
Right.append(Proj(x+RightShift(z*25),y,z,0,counter,0))
lj.PolyLineOneColor(Left, c = Leftsquare.color , layer = Leftsquare.layer, closed = Leftsquare.closed)
lj.PolyLineOneColor(Right, c = Rightsquare.color , layer = Rightsquare.layer, closed = Rightsquare.closed)
lj.DrawDests()
time.sleep(0.1)
counter += 1
if counter > 360:
counter = 0
except KeyboardInterrupt:
pass
# Gently stop on CTRL C
finally:
lj.ClosePlugin()
Run()

View File

@ -8,11 +8,13 @@ Cycling text on one LJ laser.
LICENCE : CC
'''
import sys,time
sys.path.append('../libs')
import redis
import lj3
import sys,time
import argparse
import traceback
from osc4py3.as_eventloop import *
from osc4py3 import oscbuildparse
@ -24,6 +26,8 @@ OSCinPort = 8007
duration = 300
lasertext = ["TEAMLASER","FANFAN","LOLOSTER","SAM"]
PL = 0
'''
is_py2 = sys.version[0] == '2'
if is_py2:
@ -73,9 +77,10 @@ else:
myIP = '127.0.0.1'
lj3.Config(redisIP,ljclient)
lj3.Config(redisIP,ljclient,"cycl")
#r = redis.StrictRedis(host=redisIP, port=6379, db=0)
oscrun = True
# If you want to use rgb for color :
def rgb2int(r,g,b):
@ -93,29 +98,38 @@ def OSCljclient(value):
ljclient = value
lj3.LjClient(ljclient)
def OSCpl(value):
global PL
print("Cycl got /cycl/pl with value", value)
lj3.WebStatus("Cycl to pl "+ str(value))
lj3.LjPl(value)
PL = int(value)
lj3.LjPl(PL)
# /quit dummyvalue
def quit(value):
global oscrun
lj3.ClosePlugin()
oscrun = False
'''
# /ping
def OSCping():
lj3.OSCping("cycl")
# /quit
def OSCquit():
lj3.OSCquit("cycl")
'''
print("Cycl starting its OSC server at", myIP, "port",OSCinPort,"...")
osc_startup()
osc_udp_server(myIP, OSCinPort, "InPort")
osc_method("/ping*", OSCping)
osc_method("/quit", OSCquit)
osc_method("/ping*", lj3.OSCping)
osc_method("/quit", quit)
#osc_method("/ping*", OSCping)
#osc_method("/quit", OSCquit)
osc_method("/cycl/ljclient*", OSCljclient)
osc_method("/cycl/pl*", OSCpl)
@ -130,12 +144,13 @@ def Run():
color = rgb2int(255,255,255)
try:
while 1:
while oscrun:
if timing == duration or timing == -1:
message = lasertext[step]
lj3.Text(message, color, PL = 0, xpos = 300, ypos = 300, resize = 1, rotx =0, roty =0 , rotz=0)
lj3.DrawPL(0)
#print ('PL',PL)
lj3.Text(message, color, PL = PL, xpos = 300, ypos = 300, resize = 1, rotx =0, roty =0 , rotz=0)
lj3.DrawPL(PL)
timing = 0
else:
@ -143,7 +158,11 @@ def Run():
if step >3:
step =0
timing += 1
lj3.OSCframe()
time.sleep(0.01)
except Exception:
traceback.print_exc()
except KeyboardInterrupt:
pass
@ -151,13 +170,7 @@ def Run():
finally:
WebStatus("Textcycl stop")
print("Stopping OSC...")
lj3.OSCstop()
print ("Textcycl Stopped.")
quit()
Run()

Binary file not shown.

Binary file not shown.

View File

@ -252,6 +252,7 @@
break;
case "/simul":
pl = e.data.slice(7);
//console.log(pl)
pl2 = eval(pl.replace(/[()]/g, ''));
break;
case "/plpoi":

View File

@ -1,3 +1,11 @@
main {
max-width: 38rem;
padding: 1.5rem;
margin: auto;
}
.maingrid {
display: grid;
grid-template-columns: 900px;
@ -74,7 +82,39 @@
height: 400px;
width: 400px;
grid-template-columns: 66px 66px 66px 66px 66px 66px;
grid-template-rows: 30px 67px 67px 67px 30px 30px;
grid-template-rows: 67px 67px 67px 30px 30px;
background-color: #000;
justify-items: center;
align-items: center;
border-color: #445;
border-style: groove;
border-width: 1px;
grid-gap: 1px;
transition: all .3s ease;
background-color: #151515;
}
.nozoidbuttons {
display: none;
height: 400px;
width: 400px;
grid-template-columns: 195px 195px;
grid-template-rows: 70px 40px 120px 40px 1fr;
background-color: #000;
justify-items: center;
align-items: center;
border-color: #445;
border-style: groove;
border-width: 1px;
grid-gap: 1px;
transition: all .3s ease;
background-color: #151515;
}
.destmatrix {
display: grid;
height: 250px;
width: 400px;
grid-template-columns: 76px 76px 76px 76px 76px;
grid-template-rows: 30px 30px 30px 30px 30px 1Fr;
background-color: #000;
justify-items: center;
align-items: center;
@ -146,7 +186,7 @@
.topgrid {
display: grid;
height: 80px;
grid-template-columns: 60px 75px 40px 60px 75px 60px 75px 60px 75px;
grid-template-columns: 80px 80px 80px 80px 60px 75px 60px 75px;
background-color: #000;
justify-items: center;
align-items: center;

42
webui/blocks/ai.html Normal file
View File

@ -0,0 +1,42 @@
<!-- simu right part : aiUI -->
<div id ="aiUI" style = "display: none;justify-items: center;">
<!-- with AI Interface -->
<div class="withaibox">
<div class="lasertext" style="border-color:#334;border-style: groove;border-width:1px;">With AI
</div>
<div class="withaigrid">
<!-- Velocity & Expression -->
<div><webaudio-knob id="ai/velocity" diameter="60" min="0" max="127" value="64"></webaudio-knob></div>
<div><webaudio-knob id="ai/expressivity" diameter="60" min="0" max="127" value="64"></webaudio-knob></div>
<div><webaudio-param link="ai/velocity" value="64"></webaudio-param></div>
<div><webaudio-param link="ai/expressivity" value="64"></webaudio-param></div>
<div class="lasertext">Velocity</div>
<div class="lasertext">Express.</div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Sensibility & Beauty -->
<div><webaudio-knob id="ai/sensibility" diameter="60" min="0" max="127" value="64"></webaudio-knob></div>
<div><webaudio-knob id="ai/beauty" diameter="60" min="0" max="127" value="64"></webaudio-knob></div>
<div><webaudio-param link="ai/sensibility" value="64"></webaudio-param></div>
<div><webaudio-param link="ai/beauty" value="64"></webaudio-param></div>
<div class="lasertext">Sens.</div>
<div class="lasertext">Beauty</div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- CC 1 & CC 2 -->
<div><webaudio-knob id="cc/1" diameter="60" min="1" max="127" value="64"></webaudio-knob></div>
<div><webaudio-knob id="cc/2" diameter="60" min="1" max="127" value="64"></webaudio-knob></div>
<div><webaudio-param link="cc/1" value="1"></webaudio-param></div>
<div><webaudio-param link="cc/2" value="1"></webaudio-param></div>
<div class="lasertext">CC 1</div>
<div class="lasertext">CC 2</div>
</div>
</div>
</div>
<!-- End of AI block -->

258
webui/blocks/align.html Normal file
View File

@ -0,0 +1,258 @@
<!--
Align grid block
-->
<div id="mgalign" class="mgalign">
<!-- Laser 0 -->
<div class="laserbox">
<!-- IP laser 0 -->
<div>
<form onsubmit="onSubmit(); return false;">
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="ip/0">
</form>
</div>
<div>
<!-- Align Icons -->
<webaudio-switch id="grid/0" value="0" height="25" width="21" tooltip="Switch-B" src="knobs/grid.png"></webaudio-switch>
<webaudio-switch id="mouse/0" value="0" height="25" width="21" tooltip="Switch-B" src="knobs/mouse.png"></webaudio-switch>
<!-- Blackout icon -->
<webaudio-switch id="black/0" value="0" height="25" width="21" tooltip="Switch-B" src="knobs/blackout.png"></webaudio-switch>
<!-- Swap Icons -->
<webaudio-switch id="swap/X/0" value="0" height="25" width="21" tooltip="Switch-B" src="knobs/swapx.png"></webaudio-switch>
<webaudio-switch id="swap/Y/0" value="0" height="25" width="21" tooltip="Switch-B" src="knobs/swapy.png"></webaudio-switch>
</div>
<!-- Lasergrid 0 -->
<div class="lasergrid" style="background-image: url(knobs/lasergrid0.png);">
<!-- kPPS & Points-->
<div><webaudio-param id="kpps/0" link="kpps/0" ></webaudio-param></div>
<div><webaudio-param id="points/0" link="points/0"></webaudio-param></div>
<div class="lasertext">kPPS</div>
<div class="lasertext">Points</div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Offset X & Offset Y -->
<div><webaudio-knob id="loffset/X/0" diameter="60" min="-320" max="320" value="0"></webaudio-knob></div>
<div><webaudio-knob id="loffset/Y/0" diameter="60" min="-320" max="320" value="0"></webaudio-knob></div>
<div class="lasertext">Offset X</div>
<div class="lasertext">Offset Y</div>
<div><webaudio-param link="loffset/X/0" value="0"></webaudio-param></div>
<div><webaudio-param link="loffset/Y/0" value="0"></webaudio-param></div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Scale X & Scale Y -->
<div><webaudio-knob id="scale/X/0" diameter="60" min="-10" max="10" value="0"></webaudio-knob></div>
<div><webaudio-knob id="scale/Y/0" diameter="60" min="-10" max="10" value="0"></webaudio-knob></div>
<div class="lasertext">Scale X</div>
<div class="lasertext">Scale Y</div>
<div><webaudio-param link="scale/X/0" value="0"></webaudio-param></div>
<div><webaudio-param link="scale/Y/0" value="0"></webaudio-param></div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Angle & Intensity -->
<div><webaudio-knob id="angle/0" diameter="60" min="-1" max="1" value="0"></webaudio-knob></div>
<div><webaudio-knob id="intens/0" diameter="60" min="0" max="127" value="127"></webaudio-knob></div>
<div class="lasertext">Angle</div>
<div class="lasertext">Intens.</div>
</div>
</div>
<!-- Laser 1 -->
<div class="laserbox">
<!-- IP laser 1 -->
<div>
<form onsubmit="onSubmit(); return false;">
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="ip/1">
</form>
</div>
<div>
<!-- Align Icons -->
<webaudio-switch id="grid/1" value="0" height="25" width="21" tooltip="Switch-B" src="knobs/grid.png"></webaudio-switch>
<webaudio-switch id="mouse/1" value="0" height="25" width="21" tooltip="Switch-B" src="knobs/mouse.png"></webaudio-switch>
<!-- Blackout icon -->
<webaudio-switch id="black/1" value="0" height="25" width="21" tooltip="Switch-B" src="knobs/blackout.png"></webaudio-switch>
<!-- Swap Icons -->
<webaudio-switch id="swap/X/1" value="0" height="25" width="21" tooltip="Switch-B" src="knobs/swapx.png"></webaudio-switch>
<webaudio-switch id="swap/Y/1" value="0" height="25" width="21" tooltip="Switch-B" src="knobs/swapy.png"></webaudio-switch>
</div>
<!-- Lasergrid 1 -->
<div class="lasergrid" style="background-image: url(knobs/lasergrid1.png);">
<!-- kPPS & Points-->
<div><webaudio-param id="kpps/1" link="kpps/1"></webaudio-param></div>
<div><webaudio-param id="points/1" link="points/1"></webaudio-param></div>
<div class="lasertext">kPPS</div>
<div class="lasertext">Points</div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Offset X & Offset Y -->
<div><webaudio-knob id="loffset/X/1" diameter="60" min="-20" max="20" value="0"></webaudio-knob></div>
<div><webaudio-knob id="loffset/Y/1" diameter="60" min="-20" max="20" value="0"></webaudio-knob></div>
<div class="lasertext">Offset X</div>
<div class="lasertext">Offset Y</div>
<div><webaudio-param link="loffset/X/1" value="0"></webaudio-param></div>
<div><webaudio-param link="loffset/Y/1" value="0"></webaudio-param></div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Scale X & Scale Y -->
<div><webaudio-knob id="scale/X/1" diameter="60" min="-10" max="10" value="0"></webaudio-knob></div>
<div><webaudio-knob id="scale/Y/1" diameter="60" min="-10" max="10" value="0"></webaudio-knob></div>
<div class="lasertext">Scale X</div>
<div class="lasertext">Scale Y</div>
<div><webaudio-param link="scale/X/1" value="0"></webaudio-param></div>
<div><webaudio-param link="scale/Y/1" value="0"></webaudio-param></div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Angle & Intensity -->
<div><webaudio-knob id="angle/1" diameter="60" min="-1" max="1" value="0"></webaudio-knob></div>
<div><webaudio-knob id="intens/1" diameter="60" min="0" max="127"value="127"></webaudio-knob></div>
<div class="lasertext">Angle</div>
<div class="lasertext">Intens.</div>
</div>
</div>
<!-- Laser 2 -->
<div class="laserbox">
<!-- IP laser 2 -->
<div>
<form onsubmit="onSubmit(); return false;">
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="ip/2">
</form>
</div>
<div>
<!-- Align Icons -->
<webaudio-switch id="grid/2" value="0" height="25" width="21" tooltip="Switch-B" src="knobs/grid.png"></webaudio-switch>
<webaudio-switch id="mouse/2" value="0" height="25" width="21" tooltip="Switch-B" src="knobs/mouse.png"></webaudio-switch>
<!-- Blackout icon -->
<webaudio-switch id="black/2" value="0" height="25" width="21" tooltip="Switch-B" src="knobs/blackout.png"></webaudio-switch>
<!-- Swap Icons -->
<webaudio-switch id="swap/X/2" value="0" height="25" width="21" tooltip="Switch-B" src="knobs/swapx.png"></webaudio-switch>
<webaudio-switch id="swap/Y/2" value="0" height="25" width="21" tooltip="Switch-B" src="knobs/swapy.png"></webaudio-switch>
</div>
<!-- Laser 2 grid -->
<div class="lasergrid" style="background-image: url(knobs/lasergrid2.png)">
<!-- kPPS & Points-->
<div><webaudio-param id="kpps/2" link="kpps/2"></webaudio-param></div>
<div><webaudio-param id="points/2" link="points/2"></webaudio-param></div>
<div class="lasertext">kPPS</div>
<div class="lasertext">Points</div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Offset X & Offset Y -->
<div><webaudio-knob id="loffset/X/2" diameter="60" min="-20" max="20" value="0"></webaudio-knob></div>
<div><webaudio-knob id="loffset/Y/2" diameter="60" min="-20" max="20" value="0"></webaudio-knob></div>
<div class="lasertext">Offset X</div>
<div class="lasertext">Offset Y</div>
<div><webaudio-param link="loffset/X/2" value="0"></webaudio-param></div>
<div><webaudio-param link="loffset/Y/2" value="0"></webaudio-param></div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Scale X & Scale Y -->
<div><webaudio-knob id="scale/X/2" diameter="60" min="-10" max="10" value="0"></webaudio-knob></div>
<div><webaudio-knob id="scale/Y/2" diameter="60" min="-10" max="10" value="0"></webaudio-knob></div>
<div class="lasertext">Scale X</div>
<div class="lasertext">Scale Y</div>
<div><webaudio-param link="scale/X/2" value="0"></webaudio-param></div>
<div><webaudio-param link="scale/Y/2" value="0"></webaudio-param></div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Angle & Intensity -->
<div><webaudio-knob id="angle/2" diameter="60" min="-1" max="1" value="0"></webaudio-knob></div>
<div><webaudio-knob id="intens/2" diameter="60" min="0" max="127"value="127"></webaudio-knob></div>
<div class="lasertext">Angle</div>
<div class="lasertext">Intens.</div>
</div>
</div>
<!-- Laser 3 -->
<div class="laserbox">
<!-- IP laser 3 -->
<div>
<form onsubmit="onSubmit(); return false;">
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="ip/3">
</form>
</div>
<div>
<!-- Align Icons -->
<webaudio-switch id="grid/3" value="0" height="25" width="21" tooltip="Switch-B" src="knobs/grid.png"></webaudio-switch>
<webaudio-switch id="mouse/3" value="0" height="25" width="21" tooltip="Switch-B" src="knobs/mouse.png"></webaudio-switch>
<!-- Blackout icon -->
<webaudio-switch id="black/3" value="0" height="25" width="21" tooltip="Switch-B" src="knobs/blackout.png"></webaudio-switch>
<!-- Swap Icons -->
<webaudio-switch id="swap/X/3" value="0" height="25" width="21" tooltip="Switch-B" src="knobs/swapx.png"></webaudio-switch>
<webaudio-switch id="swap/Y/3" value="0" height="25" width="21" tooltip="Switch-B" src="knobs/swapy.png"></webaudio-switch>
</div>
<!-- Laser 3 grid -->
<div class="lasergrid" style="background-image: url(knobs/lasergrid3.png)">
<!-- kPPS & Points-->
<div><webaudio-param id="kpps/3" link="kpps/3" ></webaudio-param></div>
<div><webaudio-param id="points/3" link="points/3"></webaudio-param></div>
<div class="lasertext">kPPS</div>
<div class="lasertext">Points</div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Offset X & Offset Y -->
<div><webaudio-knob id="loffset/X/3" diameter="60" min="-20" max="20" value="0"></webaudio-knob></div>
<div><webaudio-knob id="loffset/Y/3" diameter="60" min="-20" max="20" value="0"></webaudio-knob></div>
<div class="lasertext">Offset X</div>
<div class="lasertext">Offset Y</div>
<div><webaudio-param link="loffset/X/3" value="0"></webaudio-param></div>
<div><webaudio-param link="loffset/Y/3" value="0"></webaudio-param></div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Scale X & Scale Y -->
<div><webaudio-knob id="scale/X/3" diameter="60" min="-10" max="10" value="0"></webaudio-knob></div>
<div><webaudio-knob id="scale/Y/3" diameter="60" min="-10" max="10" value="0"></webaudio-knob></div>
<div class="lasertext">Scale X</div>
<div class="lasertext">Scale Y</div>
<div><webaudio-param link="scale/X/3" value="0"></webaudio-param></div>
<div><webaudio-param link="scale/Y/3" value="0"></webaudio-param></div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Angle & Intensity -->
<div><webaudio-knob id="angle/2" diameter="60" min="-1" max="1" value="0"></webaudio-knob></div>
<div><webaudio-knob id="intens/3" diameter="60" min="0" max="127" value="127"></webaudio-knob></div>
<div class="lasertext">Angle</div>
<div class="lasertext">Intens.</div>
</div>
</div>
<div>
<canvas id="aligncanvas" width="336" height="400" style="border-color: #445;border-style:groove;border-width:1px;"></canvas>
</div>
</div>
<!-- End of Align block -->

32
webui/blocks/bank0.html Normal file
View File

@ -0,0 +1,32 @@
<!-- simu right part : bank0 vjUI -->
<div id ="vjUI" class="cnvbuttons">
<!-- Bank Selection first line -->
<div><webaudio-switch id="bank0/run" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="bank0/run" value="1" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="bank0/run" value="2" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="bank0/run" value="3" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="bank0/run" value="4" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="bank0/run" value="5" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<!-- Bank Selection second line -->
<div><webaudio-switch id="noteon" value="23" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon" value="24" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon" value="25" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon" value="26" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon" value="27" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon" value="28" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<!-- Bank Selection third line -->
<div><webaudio-switch id="noteon" value="26" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon" value="27" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon" value="28" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon" value="29" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon" value="30" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
<div><webaudio-switch id="noteon" value="31" tooltip="Switch-B" height="64" width="64" src="knobs/iconvj1.png"></webaudio-switch></div>
</div>
<!-- End of bank0 block -->

257
webui/blocks/footer.html Normal file
View File

@ -0,0 +1,257 @@
<!--
Footer block display events for debug
-->
<div class="mgfooter">
<div id="showin"></div>
<div id="showout"></div>
<div id="events"</div>
</div>
</div>
<!--
web audio buttons scripts
-->
<script type="text/javascript">
var message="";
var log=[];
var knobs = document.getElementsByTagName('webaudio-knob');
for(var i = 0; i < knobs.length; i++){
knobs[i].addEventListener("input",Dump,false);
knobs[i].addEventListener("change",Dump,false);
}
var sliders = document.getElementsByTagName('webaudio-slider');
for(var i = 0; i < sliders.length; i++){
sliders[i].addEventListener("input",Dump,false);
sliders[i].addEventListener("change",Dump,false);
}
var switches = document.getElementsByTagName('webaudio-switch');
for(var i = 0; i < switches.length; i++) {
switches[i].addEventListener("change",Dump,false);
}
function Dump(e) {
var str="";
str=e.type + " : " + e.target.id + " : " + e.target.value + " ";
console.log(str);
log.unshift(str);
log.length=1;
str="";
for(var i=19;i>=0;--i) {
if(log[i])
str+=log[i]+"<br/>";
}
var evview=document.getElementById("events");
evview.innerHTML=str;
//console.log( e.type + "/" + e.target.id + "/" + e.target.value);
if (e.target.id === "align" && e.type === "change") {
showAlign();
}
if (e.target.id === "simu" && e.type === "change") {
showCanvas();
}
if (e.target.id === "live" && e.type === "change") {
showLive();
}
if (e.target.id === "nozoid" && e.type === "change") {
showNozoid();
}
if (e.target.id === "run" && e.type === "change") {
showRun();
}
if (e.target.id === "on" && e.type === "change") {
window.location.reload();
}
if (e.target.id === "nozoid/down 50" && e.type === "input") {
e.target.value = 1 ;
}
if (e.target.id === "noteon" && e.type ==="input")
console.log("only noteon change are sent not input");
else
_WS.send("/" + e.target.id + " " + e.target.value);
// for /scale : after a change (knob is released) reset knob value to 0
if (e.target.id.substring(0,5) === "scale" && e.type === "change") {
e.target.value = 0;
//console.log(e.target.id + "set to 0")
}
// for /loffset : after a change (knob is released) reset knob value to 0
if (e.target.id.substring(0,7) === "loffset" && e.type === "change") {
e.target.value = 0;
console.log(e.target.id + "set to 0")
}
// for /angle : after a change (knob is released) reset knob value to 0
if (e.target.id.substring(0,5) === "angle" && e.type === "change") {
e.target.value = 0;
//console.log(e.target.id + "set to 0")
}
}
</script>
<!--
Simulator Point lists drawing scripts
-->
<script type="text/javascript">
//
// Align canvas : store Reference To The Canvas & Set Context
//
var aligncanvas = document.getElementById("aligncanvas");
var alignctx = aligncanvas.getContext("2d");
alignctx.clearRect(0,0,400,400);
var mousePosDown = { x: 0, y: 0};
var mousePosUp = { x: 0, y: 0 };
var mouseMsgDown = '';
var mouseMsgUp = '';
function getMousePos(aligncanvas,evt)
{
var rect = aligncanvas.getBoundingClientRect();
return { x: evt.clientX - rect.left, y: evt.clientY - rect.top };
}
function MouseDown(evt)
{
mousePosDown = getMousePos(aligncanvas, evt);
mouseMsgDown = mousePosDown.x + ' ' + mousePosDown.y;
_WS.showin(mouseMsgDown);
}
function MouseUp(evt)
{
mousePosUp = getMousePos(aligncanvas, evt);
mouseMsgUp = mousePosUp.x + ' ' + mousePosUp.y;
_WS.showin(mouseMsgUp);
_WS.s.send('/mouse '+mouseMsgDown+' '+mouseMsgUp);
_WS.showin('/mouse '+mouseMsgDown+' '+mouseMsgUp);
}
aligncanvas.addEventListener("mouseup", MouseUp, false);
aligncanvas.addEventListener("mousedown", MouseDown, false);
//
// Simulator canvas : store Reference To The Canvas & Set Context
//
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var lastpoint = { x: 0, y: 0, color: 0};
ctx.clearRect(0,0,400,400);
var zoom = 0.5;
//ctx.save
// Todo : laser point will have black points to go from a polyline to another. Need to discard those black points.
function draw() {
// Clear Canvas At The Start Of Every Frame
//ctx.restore
if (pl2.length > 0)
{
// Begin a new path
// 0.7 reduces max coordinates in a more browser compatible resolution.
ctx.clearRect(0,0,400,400);
ctx.beginPath();
ctx.moveTo(pl2[0]*zoom, pl2[1]*zoom);
lastpoint.color = pl2[2];
// Draw n Lines
for (var i = 0; i < pl2.length/3; i++)
{
// New point has the same color -> add a new line to the new point
if (pl2[2+(i*3)] === lastpoint.color)
{
ctx.lineTo(pl2[i*3]*zoom, pl2[1+(i*3)]*zoom);
}
// New point has different color -> stroke with previous color
if (pl2[2+(i*3)] != lastpoint.color)
{
ctx.strokeStyle = "#"+(lastpoint.color + Math.pow(16, 6)).toString(16).slice(-6);
ctx.stroke();
ctx.closePath()
//ctx.restore
ctx.beginPath();
//ctx.clearRect(0,0,400,400);
ctx.moveTo(pl2[i*3]*zoom, pl2[1+(i*3)]*zoom);
}
// Last point -> stroke with current color
if (i === (pl2.length/3)-1 )
{
ctx.moveTo(pl2[i*3]*zoom, pl2[1+(i*3)]*zoom);
ctx.strokeStyle = "#"+((pl2[2+(i*3)]) + Math.pow(16, 6)).toString(16).slice(-6);
ctx.stroke();
ctx.closePath()
//ctx.restore
//ctx.clearRect(0,0,400,400);
}
// store point for comparison
lastpoint.x = pl2[i*3];
lastpoint.y = pl2[1+(i*3)];
lastpoint.color = pl2[2+(i*3)];
}
}
// Call Draw Function Again To Create Animation
window.requestAnimationFrame(draw);
}
// Initialize The Draw Function
draw();
</script>
</body>
<!-- non displayed items, for code reference mainly for other type of webaudio buttons
<div>
<span class="lasertext">Swap X</span>
<span class="lasertext">Swap Y</span>
</div>
<div>
<webaudio-switch id="swap/X" value="0" height="76" width="76" tooltip="Switch-B" src="knobs/switch_toggle.png"></webaudio-switch>
<webaudio-switch id="swap/Y" value="0" height="76" width="76" tooltip="Switch-B" src="knobs/switch_toggle.png"></webaudio-switch>
</div>
<div><webaudio-knob id="choice" src="knobs/Prophet5.png" diameter="80" min="0" max="10" value="0" sprites="9"></webaudio-knob></div>
<div><webaudio-knob id="choice2" src="knobs/Old11.png" diameter="80" min="0" max="10" value="0" sprites="10">></webaudio-knob></div>
<div><webaudio-knob id="laser" src="knobs/Prophetic5.png" diameter="70" min="0" max="5" value="0" sprites="5"></webaudio-knob></div>
<div>
<webaudio-slider id="slider1" width="24" height="120"></webaudio-slider>
<webaudio-slider id="slider2" width="24" height="120"></webaudio-slider>
</div>
<div>
<webaudio-switch id="laser/0" height="64" width="25" value="0" src="knobs/key0.png" type="toggle"></webaudio-switch>
<webaudio-switch id="laser/1" height="64" width="25" value="0" src="knobs/key0.png" type="toggle"></webaudio-switch>
<webaudio-switch id="laser/2" height="64" width="25" value="0" src="knobs/key0.png" type="toggle"></webaudio-switch>
<webaudio-switch id="laser/3" height="64" width="25" value="0" src="knobs/key0.png" type="toggle"></webaudio-switch>
</div>
-->
<!-- End of Footer block -->
</html>

46
webui/blocks/head.html Normal file
View File

@ -0,0 +1,46 @@
<!DOCTYPE html>
<!-- Head block -->
<!-- DO NOT EDIT index.html page. Edit the right block then python build.py -->
<!--
LJ webapp 'mg' stand for main grid elements
-->
<html>
<head>
<meta charset="utf-8">
<title>LJ</title>
<!-- Web audio buttons defaults -->
<script src="webcomponents-lite.js"></script>
<script>
WebAudioControlsOptions={
useMidi:1,
knobSrc:"knobs/simplegray.png",
knobSprites:100,
switchSrc:"knobs/switch_toggle.png",
sliderSrc:"knobs/vsliderbody.png",
sliderKnobsrc:"knobs/vsliderknob.png",
}
</script>
<script src="webaudio-controls.js"></script>
<link rel="stylesheet" href="LJgrid.css" />
<link rel="stylesheet" type="text/css" href="selector.min.css">
<script type="application/javascript" src="selector.min.js"></script>
<!-- Javascript for this webapp is a the end of this html page and in LJ.js -->
<script src="LJ.js"></script>
</head>
<body style="background-color:#222;">
<!--
MainGrid : Webpage one column, different raws displayed or hidden by menu button
-->
<div class="maingrid">
<!-- End of Header block -->

42
webui/blocks/lissa.html Normal file
View File

@ -0,0 +1,42 @@
<!-- simu right part : lissaUI block -->
<div id ="lissaUI" style = "display: none;justify-items: center;">
<!-- Lissa interface -->
<div class="lissabox">
<div class="lasertext" style="border-color:#334;border-style: groove;border-width:1px;">LISSA
</div>
<div class="lissagrid">
<!-- Select X & Select Y -->
<div><webaudio-knob id="cc/5" diameter="60" min="0" max="127" value="0"></webaudio-knob></div>
<div><webaudio-knob id="cc/6" diameter="60" min="0" max="127" value="0"></webaudio-knob></div>
<div><webaudio-param link="cc/5" value="0"></webaudio-param></div>
<div><webaudio-param link="cc/6" value="0"></webaudio-param></div>
<div class="lasertext">Select X</div>
<div class="lasertext">Select Y</div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- FOV & Dist -->
<div><webaudio-knob id="cc/21" diameter="60" min="1" max="127" value="1"></webaudio-knob></div>
<div><webaudio-knob id="cc/22" diameter="60" min="1" max="127" value="1"></webaudio-knob></div>
<div><webaudio-param link="cc/21" value="0"></webaudio-param></div>
<div><webaudio-param link="cc/22" value="0"></webaudio-param></div>
<div class="lasertext">FOV</div>
<div class="lasertext">Dist</div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Offset X & Offset Y -->
<div><webaudio-knob id="cc/1" diameter="60" min="1" max="127" value="1"></webaudio-knob></div>
<div><webaudio-knob id="cc/2" diameter="60" min="1" max="127" value="1"></webaudio-knob></div>
<div><webaudio-param link="cc/1" value="0"></webaudio-param></div>
<div><webaudio-param link="cc/2" value="0"></webaudio-param></div>
<div class="lasertext">Offset X</div>
<div class="lasertext">Offset Y</div>
</div>
</div>
</div>
<!-- End of Lissa block -->

101
webui/blocks/live.html Normal file
View File

@ -0,0 +1,101 @@
<!--
Live
-->
<div id="mglive" class="mglive">
<!-- with AI Interface -->
<div class="withaibox">
<div class="lasertext" style="border-color:#334;border-style: groove;border-width:1px;">With AI
</div>
<div class="withaigrid">
<!-- Velocity X Expression -->
<div><webaudio-knob id="ai/velocity" diameter="60" min="0" max="127" value="64"></webaudio-knob></div>
<div><webaudio-knob id="ai/expressivity" diameter="60" min="0" max="127" value="64"></webaudio-knob></div>
<div><webaudio-param link="ai/velocity" value="64"></webaudio-param></div>
<div><webaudio-param link="ai/expressivity" value="64"></webaudio-param></div>
<div class="lasertext">Velocity</div>
<div class="lasertext">Express.</div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Sensibility & Beauty -->
<div><webaudio-knob id="ai/sensibility" diameter="60" min="0" max="127" value="64"></webaudio-knob></div>
<div><webaudio-knob id="ai/beauty" diameter="60" min="0" max="127" value="64"></webaudio-knob></div>
<div><webaudio-param link="ai/sensibility" value="64"></webaudio-param></div>
<div><webaudio-param link="ai/beauty" value="64"></webaudio-param></div>
<div class="lasertext">Sens.</div>
<div class="lasertext">Beauty</div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- CC 1 & CC 2 -->
<div><webaudio-knob id="cc/1" diameter="60" min="1" max="127" value="64"></webaudio-knob></div>
<div><webaudio-knob id="cc/2" diameter="60" min="1" max="127" value="64"></webaudio-knob></div>
<div><webaudio-param link="cc/1" value="1"></webaudio-param></div>
<div><webaudio-param link="cc/2" value="1"></webaudio-param></div>
<div class="lasertext">CC 1</div>
<div class="lasertext">CC 2</div>
</div>
</div>
<!-- Lissa interface -->
<div class="lissabox">
<div class="lasertext" style="border-color:#334;border-style: groove;border-width:1px;">LISSA
</div>
<div class="lissagrid">
<!-- Select X & Select Y -->
<div><webaudio-knob id="cc/5" diameter="60" min="0" max="127" value="0"></webaudio-knob></div>
<div><webaudio-knob id="cc/6" diameter="60" min="0" max="127" value="0"></webaudio-knob></div>
<div><webaudio-param link="cc/5" value="0"></webaudio-param></div>
<div><webaudio-param link="cc/6" value="0"></webaudio-param></div>
<div class="lasertext">Select X</div>
<div class="lasertext">Select Y</div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- FOV & Dist -->
<div><webaudio-knob id="cc/21" diameter="60" min="1" max="127" value="1"></webaudio-knob></div>
<div><webaudio-knob id="cc/22" diameter="60" min="1" max="127" value="1"></webaudio-knob></div>
<div><webaudio-param link="cc/21" value="0"></webaudio-param></div>
<div><webaudio-param link="cc/22" value="0"></webaudio-param></div>
<div class="lasertext">FOV</div>
<div class="lasertext">Dist</div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Offset X & Offset Y -->
<div><webaudio-knob id="cc/1" diameter="60" min="1" max="127" value="1"></webaudio-knob></div>
<div><webaudio-knob id="cc/2" diameter="60" min="1" max="127" value="1"></webaudio-knob></div>
<div><webaudio-param link="cc/1" value="0"></webaudio-param></div>
<div><webaudio-param link="cc/2" value="0"></webaudio-param></div>
<div class="lasertext">Offset X</div>
<div class="lasertext">Offset Y</div>
</div>
</div>
<!-- 3D proj interface -->
<div class="projgrid">
<div></div>
<div class="lasertext" style="border-color:#334;border-style: groove;border-width:1px;">3D ROT</div>
<div></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div class="spacer"></div>
<div><webaudio-knob id="cc/29" diameter="60" min="0" max="127" value="0" ></webaudio-knob></div>
<div><webaudio-knob id="cc/10" diameter="60" min="0" max="127" value="0"></webaudio-knob></div>
<div><webaudio-knob id="cc/31" diameter="60" min="0" max="127" value="0"></webaudio-knob></div>
<div><webaudio-param link="cc/29" value="0"></webaudio-param></div>
<div><webaudio-param link="cc/10" value="0"></webaudio-param></div>
<div><webaudio-param link="cc/31" value="0"></webaudio-param></div>
<div class="lasertext">X</div>
<div class="lasertext">Y</div>
<div class="lasertext">Z</div>
</div>
</div>
<!-- End of Live block -->

67
webui/blocks/menu.html Normal file
View File

@ -0,0 +1,67 @@
<!--
Menu Block : buttons and Status display
-->
<div id="mgstatus" class="mgstatus">
<div>
<!-- Horizontal menu buttons -->
<webaudio-switch id="align" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/align.png"></webaudio-switch>
<webaudio-switch id="simu" value="1" height="27" width="75" tooltip="Switch-B" src="knobs/simu.png"></webaudio-switch>
<webaudio-switch id="live" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/live.png"></webaudio-switch>
<webaudio-switch id="run" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/run.png"></webaudio-switch>
<!--
<button class="button" id="showrun" onclick="showRun()">Run</button>
<button class="button" id="shownozoid" onclick="showNozoid()">Nozoid</button>
-->
</div>
<div>
<!-- Client actually drawn Selection -->
<span class="lasertext">Scene</span>
<select onclick="buttonClicked(this.value)" id="virtual" value="0">
<option value="noteon 0">0</option>
<option value="noteon 1">1</option>
<option value="noteon 2">2</option>
<option value="noteon 3">3</option>
</select>
<!-- Point List drawn in simulator -->
<span class="lasertext">PL</span>
<select onclick="buttonClicked(this.value)">
<option value="noteon 24">0</option>
<option value="noteon 25">1</option>
<option value="noteon 26">2</option>
<option value="noteon 27">3</option>
</select>
</div>
<div>
<div>
<!-- Plugins selection menu -->
<button class="info" id="showstatus">OFFLINE</button>
<select onclick="buttonClicked(this.value)" value="lj/pluginsUI">
<option value="lj/pluginsUI">Plugins</option>
<option value="planet/planetUI">Planetarium</option>
<option value="nozoid/nozoidUI">Nozoid</option>
<option value="bank0/vjUI">VJing</option>
<option value="pose/poseUI">Pose</option>
<option value="words/wordsUI">Words</option>
<option value="ai/aiUI">AI</option>
<option value="lissa/lissaUI">Lissa</option>
</select>
<!--
<span class="lasertext">Laser</span>
<select onclick="buttonClicked(this.value)">
<option value="noteon 24" selected >0</option>
<option value="noteon 25">1</option>
<option value="noteon 26">2</option>
<option value="noteon 27">3</option>
</select>
-->
</div>
</div>
</div>
<!-- End of Menu block -->

176
webui/blocks/nozoids.html Normal file
View File

@ -0,0 +1,176 @@
<!-- simu right part : NozoidsUI Block -->
<div id ="nozoidUI" class="nozoidbuttons" style = "display: none;justify-items: center;">
<!-- Nozoids UI : names and leds -->
<div>
<webaudio-knob id="nozoid/o2/led" src="knobs/leds.png" height="17" width="17" diameter="17" min="0" max="6" value="0" sprites="6"></webaudio-knob>
<webaudio-switch id="nozoid/o2" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/o2.png"></webaudio-switch>
</div>
<div>
<webaudio-knob id="nozoid/m3/led" src="knobs/leds.png" height="17" width="17" diameter="17" min="0" max="6" value="0" sprites="6"></webaudio-knob>
<webaudio-switch id="nozoid/m3" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/m3.png"></webaudio-switch>
</div>
<!-- OCS-2 UI -->
<div style="border-color: #445;border-style:groove;border-width:1px;">
<webaudio-switch id="nozoid/down/o2 25" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/slower.png"></webaudio-switch>
<webaudio-switch id="nozoid/up/o2 25" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/faster.png"></webaudio-switch>
<span class="lasertext">Sound curve for X</span>
<select onclick="buttonClicked(this.value)">
<option value="nozoid/X/o2 0">STOP</option>
<option value="nozoid/X/o2 1">VCO1</option>
<option value="nozoid/X/o2 2">VCO2</option>
<option value="nozoid/X/o2 3">LFO1</option>
<option value="nozoid/X/o2 4">LFO2</option>
<option value="nozoid/X/o2 5">LFO3</option>
<option value="nozoid/X/o2 6">CV/GEN</option>
<option value="nozoid/X/o2 7">ADSR</option>
<option value="nozoid/X/o2 8">LIGHT</option>
<option value="nozoid/X/o2 9">LINE IN</option>
<option value="nozoid/X/o2 10">MIDI</option>
<option value="nozoid/X/o2 11">CV1</option>
<option value="nozoid/X/o2 12">CV2</option>
<option value="nozoid/X/o2 13">CV3</option>
<option value="nozoid/X/o2 17">1 Out</option>
<option value="nozoid/X/o2 18">2 Out</option>
<option value="nozoid/X/o2 20">VCF</option>
<option value="nozoid/X/o2 21">MIX</option>
<option value="nozoid/X/o2 22">VCA</option>
</select>
<span class="lasertext">Sound curve for Y</span>
<select onclick="buttonClicked(this.value)">
<option value="nozoid/Y/o2 0">STOP</option>
<option value="nozoid/Y/o2 1">VCO1</option>
<option value="nozoid/Y/o2 2">VCO2</option>
<option value="nozoid/Y/o2 3">LFO1</option>
<option value="nozoid/Y/o2 4">LFO2</option>
<option value="nozoid/Y/o2 5">LFO3</option>
<option value="nozoid/Y/o2 6">CV/GEN</option>
<option value="nozoid/Y/o2 7">ADSR</option>
<option value="nozoid/Y/o2 8">LIGHT</option>
<option value="nozoid/Y/o2 9">LINE IN</option>
<option value="nozoid/Y/o2 10">MIDI</option>
<option value="nozoid/Y/o2 11">CV1</option>
<option value="nozoid/Y/o2 12">CV2</option>
<option value="nozoid/Y/o2 13">CV3</option>
<option value="nozoid/Y/o2 17">1 Out</option>
<option value="nozoid/Y/o2 18">2 Out</option>
<option value="nozoid/Y/o2 20">VCF</option>
<option value="nozoid/Y/o2 21">MIX</option>
<option value="nozoid/Y/o2 22">VCA</option>
</select>
</div>
<!-- MMO-3 UI -->
<div style="border-color: #445;border-style:groove;border-width:1px;">
<webaudio-switch id="nozoid/down/m3 25" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/slower.png"></webaudio-switch>
<webaudio-switch id="nozoid/up/m3 25" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/faster.png"></webaudio-switch>
<span class="lasertext">Sound curve for X</span>
<select onclick="buttonClicked(this.value)">
<option value="nozoid/X/m3 0">Stop</option>
<option value="nozoid/X/m3 1">OSC1</option>
<option value="nozoid/X/m3 2">OSC2</option>
<option value="nozoid/X/m3 3">OSC3</option>
<option value="nozoid/X/m3 4">LFO1</option>
<option value="nozoid/X/m3 5">LFO2</option>
<option value="nozoid/X/m3 6">LFO3</option>
<option value="nozoid/X/m3 7">ADSR</option>
<option value="nozoid/X/m3 8">CV</option>
<option value="nozoid/X/m3 9">Line IN</option>
<option value="nozoid/X/m3 10">Jstck</option>
<option value="nozoid/X/m3 11">INL</option>
<option value="nozoid/X/m3 12">INR</option>
</select>
<span class="lasertext">Sound curve for Y</span>
<select onclick="buttonClicked(this.value)">
<option value="nozoid/Y/m3 0">Stop</option>
<option value="nozoid/Y/m3 1">OSC1</option>
<option value="nozoid/Y/m3 2">OSC2</option>
<option value="nozoid/Y/m3 3">OSC3</option>
<option value="nozoid/Y/m3 4">LFO1</option>
<option value="nozoid/Y/m3 5">LFO2</option>
<option value="nozoid/Y/m3 6">LFO3</option>
<option value="nozoid/Y/m3 7">ADSR</option>
<option value="nozoid/Y/m3 8">CV</option>
<option value="nozoid/Y/m3 9">Line IN</option>
<option value="nozoid/Y/m3 10">Jstck</option>
<option value="nozoid/Y/m3 11">INL</option>
<option value="nozoid/X/m3 12">INR</option>
</select>
</div>
<!-- Curve choice -->
<div>
<span class="lasertext">CurveNumber : </span>
<select onclick="buttonClicked(this.value)">
<option value="nozoid/curve 0">0</option>
<option value="nozoid/curve 1">1</option>
<option value="nozoid/curve 2">2</option>
<option value="nozoid/curve 3">3</option>
</select>
<!-- Color choice -->
<!-- 0 black / 1 green / 2 cyan / 3 pink / 4 yellow / 5 red / 6 white (in nozoids.py) -->
<span class="lasertext">CurveColor :</span>
<select onclick="buttonClicked(this.value)">
<option value="nozoid/color 5">Red</option>
<option value="nozoid/color 1">Green</option>
<option value="nozoid/color 2">Blue</option>
<option value="nozoid/color 4">Yellow</option>
<option value="nozoid/color 3">Pink</option>
<option value="nozoid/color 6">White</option>
</select>
<!-- Laser choice -->
<span class="lasertext">DrawingLaser :</span>
<select onclick="buttonClicked(this.value)">
<option value="nozoid/laser 0">0</option>
<option value="nozoid/laser 1">1</option>
<option value="nozoid/laser 2">2</option>
<option value="nozoid/laser 3">3</option>
</select>
</div>
<!-- Automodulation X and Y choice -->
<div>
<span class="lasertext" >Automod : X</span>
<select onclick="buttonClicked(this.value)">
<option value="nozoid/auto/X/0">0</option>
<option value="nozoid/auto/X/1 Out">1 Out</option>
<option value="nozoid/auto/X/2 Out">2 Out</option>
<option value="nozoid/auto/X/3 Out">3 Out</option>
<option value="nozoid/auto/X/OutR">OutR</option>
<option value="nozoid/auto/X/OutL">OutL</option>
</select>
<span class="lasertext">Automod : Y</span>
<select onclick="buttonClicked(this.value)">
<option value="nozoid/auto/Y/0">0</option>
<option value="nozoid/auto/Y/1 Out">1 Out</option>
<option value="nozoid/auto/Y/2 Out">2 Out</option>
<option value="nozoid/auto/Y/3 Out">3 Out</option>
<option value="nozoid/auto/Y/OutR">OutR</option>
<option value="nozoid/auto/Y/OutL">OutL</option>
</select>
</div>
<div></div>
<div></div>
</div>
</div>
</div>
<!-- End of NozoidsUI block -->

View File

@ -0,0 +1,77 @@
<!-- simu right part : Planetarium Block -->
<div id ="planetUI" style = "display: none;justify-items: center;">
<!-- Stop and start switch -->
<div>
<div><webaudio-switch id="planet/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/planet.png"></webaudio-switch>
</div>
<!-- Virtual client destination -->
<div>
<span class="lasertext">Virtual</span>
<select onclick="buttonClicked(this.value)">
<option value="planet/ljclient 0" selected >0</option>
<option value="planet/ljclient 1">1</option>
<option value="planet/ljclient 2">2</option>
<option value="planet/ljclient 3">3</option>
</select>
</div>
</div>
<!-- Observer position -->
<form onsubmit="onSubmit(); return false;">
<span class="lasertext">Country (FR)</span>
<input class = "submitsmall" onchange = "onSubmit(this.id)" type="text" id="planet/country">
<span class="lasertext">City</span>
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="planet/city">
</form>
<!-- Observer time -->
<form>
<span class="lasertext">Date/Time (2012-7-12 23:00:00) </span>
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="planet/time">
</form>
<!-- Laser 0 Sky -->
<form onsubmit="onSubmit(); return false;">
<span class="lasertext">Laser 0 : Alt</span>
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="planet/alt/0">
<span class="lasertext">Az</span>
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="planet/az/0">
<span class="lasertext">Angle</span>
<input class = "submitsmall" onchange = "onSubmit(this.id)" type="text" id="planet/angle/0">
</form>
<!-- Laser 1 Sky -->
<form onsubmit="onSubmit(); return false;">
<span class="lasertext">Laser 1 : Alt</span>
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="planet/alt/1">
<span class="lasertext">Az</span>
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="planet/az/1">
<span class="lasertext">Angle</span>
<input class = "submitsmall" onchange = "onSubmit(this.id)" type="text" id="planet/angle/1">
</form>
<!-- Laser 2 Sky -->
<form onsubmit="onSubmit(); return false;">
<span class="lasertext">Laser 2 : Alt</span>
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="planet/alt/2">
<span class="lasertext">Az</span>
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="planet/az/2">
<span class="lasertext">Angle</span>
<input class = "submitsmall" onchange = "onSubmit(this.id)" type="text" id="planet/angle/2">
</form>
<!-- Laser 3 Sky -->
<form onsubmit="onSubmit(); return false;">
<span class="lasertext">Laser 3 : Alt</span>
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="planet/alt/3">
<span class="lasertext">Az</span>
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="planet/az/3">
<span class="lasertext">Angle</span>
<input class = "submitsmall" onchange = "onSubmit(this.id)" type="text" id="planet/angle/3">
</form>
</div>
<!-- End of planetarium block -->

277
webui/blocks/plugins.html Normal file
View File

@ -0,0 +1,277 @@
<!-- simu right part : plugins UI Block-->
<div id ="pluginsUI" style = "display: grid;justify-items: center;">
<!-- Plugins choice Interface -->
<div>
<webaudio-switch id="simu/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/pysimu.png"></webaudio-switch>
<webaudio-switch id="pose/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/pose.png"></webaudio-switch>
<webaudio-switch id="bank0/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/bank0.png"></webaudio-switch>
<webaudio-switch id="cycl/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/cycl.png"></webaudio-switch>
</div>
<div>
<webaudio-switch id="midigen/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/midigen.png"></webaudio-switch>
<webaudio-switch id="audiogen/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/audiogen.png"></webaudio-switch>
<webaudio-switch id="viewgen/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/viewgen.png"></webaudio-switch>
<webaudio-switch id="/artnet/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/artnet.png"></webaudio-switch>
</div>
<div>
<!-- Glyph destination LJ client Selection -->
<span class="lasertext">Scene</span>
<select onclick="buttonClicked(this.value)" id="virtual" value="0">
<option value="glyph/ljclient 0">0</option>
<option value="glyph/ljclient 1">1</option>
<option value="glyph/ljclient 2">2</option>
<option value="glyph/ljclient 3">3</option>
</select>
<!-- Cycl destination LJ client Selection -->
<span class="lasertext">Scene</span>
<select onclick="buttonClicked(this.value)" id="virtual" value="0">
<option value="cycl/ljclient 0">0</option>
<option value="cycl/ljclient 1">1</option>
<option value="cycl/ljclient 2">2</option>
<option value="cycl/ljclient 3">3</option>
</select>
</div>
<div>
<!-- Glyph Point List destination -->
<span class="lasertext">PL</span>
<select onclick="buttonClicked(this.value)">
<option value="glyph/pl 0">0</option>
<option value="glyph/pl 1">1</option>
<option value="glyph/pl 2">2</option>
<option value="glyph/pl 3">3</option>
</select>
<!-- Cycl Point List destination -->
<span class="lasertext">PL</span>
<select onclick="buttonClicked(this.value)">
<option value="cycl/pl 0">0</option>
<option value="cycl/pl 1">1</option>
<option value="cycl/pl 2">2</option>
<option value="cycl/pl 3">3</option>
</select>
</div>
<!-- LJPong & LJwars -->
<div>
<webaudio-switch id="ljpong/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/ljpong.png"></webaudio-switch>
<webaudio-switch id="ljwars/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/ljwars.png"></webaudio-switch>
<webaudio-switch id="maxw/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/maxw.png"></webaudio-switch>
<webaudio-switch id="square/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/square.png"></webaudio-switch>
</div>
<div>
<!-- LJ Pong destination LJ client Selection -->
<span class="lasertext">Scene</span>
<select onclick="buttonClicked(this.value)" id="virtual" value="0">
<option value="ljpong/ljclient 0">0</option>
<option value="ljpong/ljclient 1">1</option>
<option value="ljpong/ljclient 2">2</option>
<option value="ljpong/ljclient 3">3</option>
</select>
<!-- LJ Wars destination LJ client Selection -->
<span class="lasertext">Scene</span>
<select onclick="buttonClicked(this.value)" id="virtual" value="0">
<option value="ljwars/ljclient 0">0</option>
<option value="ljwars/ljclient 1">1</option>
<option value="ljwars/ljclient 2">2</option>
<option value="ljwars/ljclient 3">3</option>
</select>
</div>
<div>
<!-- LJ Pong Point List destination -->
<span class="lasertext">PL</span>
<select onclick="buttonClicked(this.value)">
<option value="ljpong/pl 0">0</option>
<option value="ljpong/pl 1">1</option>
<option value="ljpong/pl 2">2</option>
<option value="ljpong/pl 3">3</option>
</select>
</div>
<div class = "destmatrix">
<!-- First line Scene 0 -->
<div>
<webaudio-switch id="scene/0/start" value="1" height="27" width="75" tooltip="Switch-B" src="knobs/scene0.png"></webaudio-switch>
</div>
<!-- /pluginame/dest PL, scene, laser -->
<div>
<!-- scene 0, laser 0 -->
<select class="selector-instance" data-type="search-selector" name="third-selector" id="second" onclick="buttonClicked(this.value)">
<option value="fft/dest 1 1 0" data-sublocale="HELLO" selected>EXT</option>
<option value="viewgen/dest 0 0 0">FFT</option>
<option value="viewgen/dest 1 0 0">Lissa</option>
<option value="viewgen/dest 2 0 0">Osci</option>
<option value="glyph/dest 0 0 0">Glyph</option>
<option value="nozoid/dest 0 0 0">Nozoids</option>
<option value="pose/dest 0 0 0">IdiotIA</option>
<option value="pose/dest 1 0 0">Starfield</option>
<option value="cycl/dest 0 0 0">Cycl</option>
<option value="planet/dest 0 0 0">Planet</option>
<option value="words/dest 0 0 0">Words</option>
<option value="ljpong/dest 0 0 0">Pong</option>
<option value="ljwars/dest 0 0 0">Wars</option>
<option value="maxw/dest 0 0 0">Maxw</option>
<option value="square/dest 0 0 0">Square</option>
</select>
</div>
<div>
<!-- scene 0, laser 1 -->
<select class="selector-instance" data-type="search-selector" name="third-selector" id="second" onclick="buttonClicked(this.value)">
<option value="fft/dest 1 0 0" data-sublocale="HELLO" selected>EXT</option>
<option value="viewgen/dest 0 0 1">FFT</option>
<option value="viewgen/dest 1 0 1">Lissa</option>
<option value="viewgen/dest 2 0 1">Osci</option>
<option value="glyph/dest 0 0 1">Glyph</option>
<option value="nozoid/dest 0 0 1">Nozoids</option>
<option value="pose/dest 0 0 1">IdiotIA</option>
<option value="pose/dest 1 0 1">Starfield</option>
<option value="cycl/dest 0 0 1">Cycl</option>
<option value="planet/dest 0 0 1">Planet</option>
<option value="words/dest 0 0 1">Words</option>
<option value="ljpong/dest 0 0 1">Pong</option>
<option value="ljwars/dest 0 0 1">Wars</option>
<option value="maxw/dest 0 0 1">Maxw</option>
<option value="square/dest 0 0 1">Square</option>
</select>
</div>
<div>
<!-- scene 0, laser 2 -->
<select onclick="buttonClicked(this.value)">
<option value="ext 0 1">EXT</option>
<option value="fft/dest 0 1 0">FFT 0</option>
<option value="fft/dest 1 1 0">FFT 1</option>
<option value="fft/dest 2 1 0">FFT 2</option>
<option value="fft/dest 3 1 0">FFT 3</option>
</select>
</div>
<div>
<!-- scene 0, laser 3 -->
</div>
<!-- Second line Scene 1 -->
<div>
<webaudio-switch id="scene/1/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/scene1.png"></webaudio-switch>
</div>
<!-- /pluginame/dest PL, scene, laser -->
<div>
<!-- scene 1, laser 0 -->
<select class="selector-instance" data-type="search-selector" name="third-selector" id="second" onclick="buttonClicked(this.value)">
<option value="fft/dest 1 1 0" data-sublocale="HELLO" selected>EXT</option>
<option value="viewgen/dest 0 1 0">FFT</option>
<option value="viewgen/dest 1 1 0">Lissa</option>
<option value="viewgen/dest 2 1 0">Osci</option>
<option value="glyph/dest 0 1 0">Glyph</option>
<option value="nozoid/dest 0 1 0">Nozoids</option>
<option value="pose/dest 0 1 0">IdiotIA</option>
<option value="pose/dest 1 1 0">Starfield</option>
<option value="cycl/dest 0 1 0">Cycl</option>
<option value="planet/dest 0 1 0">Planet</option>
<option value="words/dest 0 1 0">Words</option>
<option value="ljpong/dest 0 1 0">Pong</option>
<option value="ljwars/dest 0 1 0">Wars</option>
<option value="maxw/dest 0 1 0">Maxw</option>
<option value="square/dest 0 1 0">Square</option>
</select>
</div>
<div>
<!-- scene 1 , laser 1 -->
<select class="selector-instance" data-type="search-selector" name="third-selector" id="second" onclick="buttonClicked(this.value)">
<option value="fft/dest 1 0 0" data-sublocale="HELLO" selected>EXT</option>
<option value="viewgen/dest 0 1 1">FFT</option>
<option value="viewgen/dest 1 1 1">Lissa</option>
<option value="viewgen/dest 2 1 1">Osci</option>
<option value="glyph/dest 0 1 1">Glyph</option>
<option value="nozoid/dest 0 1 1">Nozoids</option>
<option value="pose/dest 0 1 1">IdiotIA</option>
<option value="pose/dest 1 1 1">Starfield</option>
<option value="cycl/dest 0 1 1">Cycl</option>
<option value="planet/dest 0 1 1">Planet</option>
<option value="words/dest 0 1 1">Words</option>
<option value="ljpong/dest 0 1 1">Pong</option>
<option value="ljwars/dest 0 1 1">Wars</option>
<option value="maxw/dest 0 1 1">Maxw</option>
<option value="square/dest 0 1 1">Square</option>
</select>
</div>
<div>
<!-- scene 1 , laser 2 -->
</div>
<div>
<!-- scene 1 , laser 3 -->
</div>
<!-- Third line Scene 2 -->
<div>
<webaudio-switch id="scene/2/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/scene2.png"></webaudio-switch>
</div>
<div>
<!-- scene 2 , laser 0 -->
</div>
<div>
<!-- scene 2 , laser 1 -->
</div>
<div>
<!-- scene 2 , laser 2 -->
</div>
<div>
<!-- scene 2 , laser 3 -->
</div>
<!-- Fourth line Scene 3 -->
<div>
<webaudio-switch id="scene/3/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/scene3.png"></webaudio-switch>
</div>
<div>
<!-- scene 3 , laser 0 -->
</div>
<div>
<!-- scene 3 , laser 1 -->
</div>
<div>
<!-- scene 3 , laser 2 -->
</div>
<div>
<!-- scene 3 , laser 3 -->
</div>
<!-- Fifth line -->
<div><span class="lasertext">Selection</span></div>
<div>
<webaudio-switch id="laser0/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/laser0.png"></webaudio-switch>
</div>
<div>
<webaudio-switch id="laser1/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/laser1.png"></webaudio-switch>
</div>
<div>
<webaudio-switch id="laser2/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/laser2.png"></webaudio-switch>
</div>
<div>
<webaudio-switch id="laser3/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/laser3.png"></webaudio-switch>
</div>
</div>
</div>
<script>
new Selector();
</script>
<!-- End of PLuginUI block -->

69
webui/blocks/pose.html Normal file
View File

@ -0,0 +1,69 @@
<!-- simu right part : poseUI block -->
<div id ="poseUI" class="posebuttons" style = "display: none;justify-items: center;">
<!-- IdiotIA animation selection first line -->
<div><webaudio-switch id="pose/anim 0" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 1" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 2" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 3" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 4" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 5" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<!-- IdiotIA animation selection second line -->
<div><webaudio-switch id="pose/anim 6" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 7" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 8" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 9" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 10" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 11" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<!-- IdiotIA animation selection third line -->
<div><webaudio-switch id="pose/anim 12" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 13" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 14" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 15" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 16" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 17" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<!-- Pose frame player -->
<div><span class="lasertext">Frames</span></div>
<div><webaudio-switch id="pose/speed 1" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/slower.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/speed 2" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/stop.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/speed 3" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/play.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/speed 4" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/faster.png"></webaudio-switch></div>
<div></div>
<!-- IdiotIA display flag -->
<div><span class="lasertext">IdiotIA</span></div>
<div><webaudio-switch id="pose/idiotia 0" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/0.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia 1" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/1.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia 2" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/2.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia 3" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/3.png"></webaudio-switch></div>
<div></div>
<!-- Realtime pose display flag -->
<div><span class="lasertext">Live</span></div>
<div><webaudio-switch id="pose/live 0" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/0.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/live 1" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/1.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/live 2" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/2.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/live 3" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/3.png"></webaudio-switch></div>
<div></div>
<!-- Starfield display lag -->
<div><span class="lasertext">Fields</span></div>
<div><webaudio-switch id="pose/field 0" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/0.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/field 1" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/1.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/field 2" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/2.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/field 3" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/3.png"></webaudio-switch></div>
<div></div>
</div>
<!-- End of PoseUI block -->

80
webui/blocks/run.html Normal file
View File

@ -0,0 +1,80 @@
<!--
Run Block
-->
<div id="mgrun" class="mgrun">
<!-- Run Laser Client selection grid -->
<div><img src="knobs/client.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/client.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/client.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/client.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/client.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/client.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/client.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/client.png" alt=" " class="icongrid" /></div>
<div><button id ="noteon 0" onclick ="buttonClicked(this.id)" class="button:checked">0</button></div>
<div><button id ="noteon 1" onclick ="buttonClicked(this.id)" class="button">1</button></div>
<div><button id ="noteon 2" onclick ="buttonClicked(this.id)" class="button">2</button></div>
<div><button id ="noteon 3" onclick ="buttonClicked(this.id)" class="button">3</button></div>
<div><button id ="noteon 4" onclick ="buttonClicked(this.id)" class="button">4</button></div>
<div><button id ="noteon 5" onclick ="buttonClicked(this.id)" class="button">5</button></div>
<div><button id ="noteon 6" onclick ="buttonClicked(this.id)" class="button">6</button></div>
<div><button id ="noteon 7" onclick ="buttonClicked(this.id)" class="button">7</button></div>
<!-- Simulator PL selection grid -->
<div><img src="knobs/iconljay2.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/iconljay2.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/iconljay2.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/iconljay2.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/iconblack.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/iconblack.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/iconblack.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/iconblack.png" alt=" " class="icongrid" /></div>
<div><button id ="noteon 24" onclick ="buttonClicked(this.id)" class="button:checked">PL 0</button></div>
<div><button id ="noteon 25" onclick ="buttonClicked(this.id)" class="button">PL 1</button></div>
<div><button id ="noteon 26" onclick ="buttonClicked(this.id)" class="button">PL 2</button></div>
<div><button id ="noteon 27" onclick ="buttonClicked(this.id)" class="button">PL 3</button></div>
<div></div>
<div></div>
<div></div>
<div></div>
<!-- Laser selection grid -->
<div><img src="knobs/iconlaser.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/iconlaser.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/iconlaser.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/iconlaser.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/iconblack.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/iconblack.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/iconblack.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/iconblack.png" alt=" " class="icongrid" /></div>
<div><button id ="noteon 16" onclick ="buttonClicked(this.id)" class="button:checked">0</button></div>
<div><button id ="noteon 17" onclick ="buttonClicked(this.id)" class="button">1</button></div>
<div><button id ="noteon 18" onclick ="buttonClicked(this.id)" class="button">2</button></div>
<div><button id ="noteon 19" onclick ="buttonClicked(this.id)" class="button">3</button></div>
<div></div>
<div></div>
<div></div>
<div></div>
<!-- Hidden grid -->
<div><img src="knobs/iconblack.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/iconblack.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/iconblack.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/iconblack.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/iconblack.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/iconblack.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/iconblack.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/iconblack.png" alt=" " class="icongrid" /></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<!-- End of Run block -->

View File

@ -0,0 +1,14 @@
<!--
Simulator header block and interfaces
-->
<div id = "mgsimu" class="mgsimu">
<!-- Simu left part : Canvas -->
<div>
<canvas id="canvas" width="500" height="400" style="border-color: #445;border-style:groove;border-width:1px;"></canvas>
</div>
<!-- Right part interfaces -->
<div>
<!-- End of Simu Header block -->

151
webui/blocks/title.html Normal file
View File

@ -0,0 +1,151 @@
<!--
Title block and laser state
-->
<div class="mgtitle">
<!-- LJ Logo -->
<div><img src="knobs/ljaylogo.png">
</div>
<!-- ON OFF button -->
<div class="onoffgrid">
<div class="lasertextxs">/on</div>
<div><webaudio-switch id="on" height="57" width="57" value="0" src="knobs/onoff3.png" type="toggle"></webaudio-switch></div>
</div>
<!-- Lasers states grid -->
<div class="lsttgrid">
<div></div>
<div></div>
<div class="lasertextxs">S</div>
<div class="lasertextxs">C</div>
<!-- Laser 0 lstt & lack -->
<div class="lasertextxs">0</div>
<div></div>
<div><webaudio-knob id="lstt/0" src="knobs/leds.png" height="17" width="17" diameter="17" min="0" max="6" value="0" sprites="6"></webaudio-knob></div>
<div><webaudio-knob id="lack/0" src="knobs/leds.png" height="17" width="17" diameter="17" min="0" max="6" value="0" sprites="6"></webaudio-knob></div>
<!-- Laser 1 lstt & lack -->
<div class="lasertextxs">1</div>
<div></div>
<div><webaudio-knob id="lstt/1" src="knobs/leds.png" height="17" width="17" diameter="17" min="0" max="6" value="0" sprites="6"></webaudio-knob></div>
<div><webaudio-knob id="lack/1" src="knobs/leds.png" height="17" width="17" diameter="17" min="0" max="6" value="0" sprites="6"></webaudio-knob></div>
<!-- Laser 2 lstt & lack -->
<div class="lasertextxs">2</div>
<div></div>
<div><webaudio-knob id="lstt/2" src="knobs/leds.png" height="17" width="17" diameter="17" min="0" max="6" value="0" sprites="6"></webaudio-knob></div>
<div><webaudio-knob id="lack/2" src="knobs/leds.png" height="17" width="17" diameter="17" min="0" max="6" value="0" sprites="6"></webaudio-knob></div>
<!-- Laser 3 lstt & lack -->
<div class="lasertextxs">3</div>
<div></div>
<div><webaudio-knob id="lstt/3" src="knobs/leds.png" height="17" width="17" diameter="17" min="0" max="6" value="0" sprites="6"></webaudio-knob></div>
<div><webaudio-knob id="lack/3" src="knobs/leds.png" height="17" width="17" diameter="17" min="0" max="6" value="0" sprites="6"></webaudio-knob></div>
</div>
<!-- blackout button -->
<div class="blackout">
<div class="lasertextxs">Emergy Black</div>
<div><webaudio-switch id="emergency" height="64" width="64" value="0" src="knobs/blackout.png" type="toggle"></webaudio-switch></div>
</div>
<div>
<div class="topgrid">
<div>
<!-- Glyph destination LJ client Selection -->
<webaudio-switch id="glyph/start" value="0" height="27" width="80" tooltip="Switch-B" src="knobs/glyph.png"></webaudio-switch>
<select onclick="buttonClicked(this.value)" id="virtual" value="0">
<option value="glyph/ljclient 0">0</option>
<option value="glyph/ljclient 1">1</option>
<option value="glyph/ljclient 2">2</option>
<option value="glyph/ljclient 3">3</option>
</select>
<!-- Glyph Point List destination -->
<select onclick="buttonClicked(this.value)">
<option value="glyph/pl 0">0</option>
<option value="glyph/pl 1">1</option>
<option value="glyph/pl 2">2</option>
<option value="glyph/pl 3">3</option>
</select>
</div>
<div>
<!-- FFT destination LJ client Selection -->
<webaudio-switch id="fft/start" value="0" height="27" width="80" tooltip="Switch-B" src="knobs/fft.png"></webaudio-switch>
<select onclick="buttonClicked(this.value)" id="virtual" value="0">
<option value="fft/ljclient 0">0</option>
<option value="fft/ljclient 1">1</option>
<option value="fft/ljclient 2">2</option>
<option value="fft/ljclient 3">3</option>
</select>
<!-- FFT Point List destination -->
<select onclick="buttonClicked(this.value)">
<option value="fft/pl 0">0</option>
<option value="fft/pl 1">1</option>
<option value="fft/pl 2">2</option>
<option value="fft/pl 3">3</option>
</select>
</div>
<div>
<!-- Nozoids destination LJ client Selection -->
<webaudio-switch id="nozoid/start" value="0" height="27" width="80" tooltip="Switch-B" src="knobs/nozoids.png"></webaudio-switch>
<select onclick="buttonClicked(this.value)" id="virtual" value="0">
<option value="nozoid/ljclient 0">0</option>
<option value="nozoid/ljclient 1">1</option>
<option value="nozoid/ljclient 2">2</option>
<option value="nozoid/ljclient 3">3</option>
</select>
<!-- Nozoids Point List destination -->
<select onclick="buttonClicked(this.value)">
<option value="nozoid/pl 0">0</option>
<option value="nozoid/pl 1">1</option>
<option value="nozoid/pl 2">2</option>
<option value="nozoid/pl 3">3</option>
</select>
</div>
<!--
<div class="app">
<x-sign>
<div class="glitch __city" data-text="paris city">
</div>
<div class="glitch __info" data-text="paris city">
</div>
<div class="glitch __state">
<table class="t-info">
<tr>
<th class="xl-info" colspan="2" rowspan="2"></th>
<th class="sm-info" colspan="2"></th>
</tr>
<tr>
<td class="sm-info" colspan="2">http://www.teamlaser.fr</td>
</tr>
</table>
</div>
</x-sign>
</div>
-->
<!--
<div class="lasertext">Laser</div>
<div><webaudio-knob id="noteon" src="knobs/Prophetic5.png" diameter="70" min="16" max="20" value="0" sprites="5"></webaudio-knob></div>
<div><webaudio-param style="font-size:medium;" link="noteon"></webaudio-param></div>
<div class="lasertext">Set</div>
<div><webaudio-knob id="noteon" src="knobs/Prophetic5.png" diameter="70" min="8" max="12" value="4" sprites="5"></webaudio-knob></div>
<div class="lasertext">Curve</div>
<div><webaudio-knob id="noteon" src="knobs/Prophetic10.png" diameter="70" min="0" max="7" value="4" sprites="10"></webaudio-knob></div>
<div class="lasertext">Simu</div>
<div><webaudio-knob id="noteon" src="knobs/Prophetic5.png" diameter="70" min="24" max="28" value="0" sprites="5"></webaudio-knob></div>
-->
</div>
</div>
<div></div>
<div></div>
</div>
<!-- End of Title block -->

86
webui/blocks/words.html Normal file
View File

@ -0,0 +1,86 @@
<!-- simu right part : wordsUI -->
<div id ="wordsUI" style = "display: none;justify-items: center;">
<div>
<webaudio-switch id="words/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/words.png"></webaudio-switch>
<!-- Words virtual client destination -->
<span class="lasertext">Virtual</span>
<select onclick="buttonClicked(this.value)">
<option value="words/ljclient 0" selected >0</option>
<option value="words/ljclient 1">1</option>
<option value="words/ljclient 2">2</option>
<option value="words/ljclient 3">3</option>
</select>
</div>
<!-- Words 0 -->
<form onsubmit="onSubmit(); return false;">
<span class="lasertext">Laser 0</span>
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="words/text/0" value="ZERO">
<select onclick="buttonClicked(this.value)">
<!-- color selection -->
<option value="words/color/0 red" selected >Red</option>
<option value="words/color/0 green">Green</option>
<option value="words/color/0 blue">Blue</option>
<option value="words/color/0 white">White</option>
<option value="words/color/0 yellow">Yellow</option>
<option value="words/color/0 cyan">Cyan</option>
<option value="words/color/0 pink">Pink</option>
</select>
<webaudio-switch id="words/play/0" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/play.png"></webaudio-switch>
</form>
<!-- Words 1 -->
<form onsubmit="onSubmit(); return false;">
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="words/text/1" value="ONE">
<select onclick="buttonClicked(this.value)">
<!-- color selection -->
<option value="words/color/1 red" selected >Red</option>
<option value="words/color/1 green">Green</option>
<option value="words/color/1 blue">Blue</option>
<option value="words/color/1 white">White</option>
<option value="words/color/1 yellow">Yellow</option>
<option value="words/color/1 cyan">Cyan</option>
<option value="words/color/1 pink">Pink</option>
</select>
<span class="lasertext">Laser 1</span>
</form>
<!-- Words 2 -->
<form onsubmit="onSubmit(); return false;">
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="words/text/2" value="TWO">
<select onclick="buttonClicked(this.value)">
<!-- color selection -->
<option value="words/color/2/color red" selected >Red</option>
<option value="words/color/2 green">Green</option>
<option value="words/color/2 blue">Blue</option>
<option value="words/color/2 white">White</option>
<option value="words/color/2 yellow">Yellow</option>
<option value="words/color/2 cyan">Cyan</option>
<option value="words/color/2 pink">Pink</option>
</select>
<span class="lasertext">Laser 2</span>
</form>
<!-- Words 3 -->
<form onsubmit="onSubmit(); return false;">
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="words/text/3" value="THREE">
<select onclick="buttonClicked(this.value)">
<!-- color selection -->
<option value="words/color/3 red" selected >Red</option>
<option value="words/color/3 green">Green</option>
<option value="words/color/3 blue">Blue</option>
<option value="words/color/3 white">White</option>
<option value="words/color/3 yellow">Yellow</option>
<option value="words/color/3 cyan">Cyan</option>
<option value="words/color/3 pink">Pink</option>
</select>
<span class="lasertext">Laser 3</span>
</form>
</div>
<!-- End of WordsUI block -->

39
webui/build.py Normal file
View File

@ -0,0 +1,39 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# -*- mode: Python -*-
"""
Web UI index html page builder
v0.2 for LJ v0.8 +
LICENCE : CC
by Sam Neurohack
from /team/laser
"""
blocknames = [
'blocks/head.html',
'blocks/title.html',
'blocks/menu.html',
'blocks/align.html',
'blocks/live.html',
'blocks/simuheader.html',
'blocks/planetarium.html',
'blocks/lissa.html',
'blocks/ai.html',
'blocks/plugins.html',
'blocks/bank0.html',
'blocks/pose.html',
'blocks/words.html',
'blocks/nozoids.html',
'blocks/run.html',
'blocks/footer.html'
]
with open('index.html', 'w') as outfile:
for block in blocknames:
with open(block) as infile:
outfile.write(infile.read())

View File

@ -1,6 +1,7 @@
<!DOCTYPE html>
<!-- Head block -->
<!-- DO NOT EDIT index.html page. Edit the right block then python build.py -->
<!--
LJ webapp 'mg' stand for main grid elements
-->
@ -24,21 +25,27 @@
</script>
<script src="webaudio-controls.js"></script>
<link rel="stylesheet" href="LJgrid.css" />
<link rel="stylesheet" type="text/css" href="selector.min.css">
<script type="application/javascript" src="selector.min.js"></script>
<!-- Javascript for this webapp is a the end of this html page and in LJ.js -->
<script src="LJ.js"></script>
</head>
<body style="background-color:#222;">
<!--
MainGrid Webpage one column, different raws displayed or hidden by menu button
MainGrid : Webpage one column, different raws displayed or hidden by menu button
-->
<div class="maingrid">
<!-- End of Header block -->
<!--
Title and laser state
Title block and laser state
-->
<div class="mgtitle">
@ -50,7 +57,7 @@
<!-- ON OFF button -->
<div class="onoffgrid">
<div class="lasertextxs">/on</div>
<div><webaudio-switch id="on" height="52" width="41" value="0" src="knobs/bigbluetoggle.png" type="toggle"></webaudio-switch></div>
<div><webaudio-switch id="on" height="57" width="57" value="0" src="knobs/onoff3.png" type="toggle"></webaudio-switch></div>
</div>
<!-- Lasers states grid -->
@ -95,6 +102,58 @@
<div>
<div class="topgrid">
<div>
<!-- Glyph destination LJ client Selection -->
<webaudio-switch id="glyph/start" value="0" height="27" width="80" tooltip="Switch-B" src="knobs/glyph.png"></webaudio-switch>
<select onclick="buttonClicked(this.value)" id="virtual" value="0">
<option value="glyph/ljclient 0">0</option>
<option value="glyph/ljclient 1">1</option>
<option value="glyph/ljclient 2">2</option>
<option value="glyph/ljclient 3">3</option>
</select>
<!-- Glyph Point List destination -->
<select onclick="buttonClicked(this.value)">
<option value="glyph/pl 0">0</option>
<option value="glyph/pl 1">1</option>
<option value="glyph/pl 2">2</option>
<option value="glyph/pl 3">3</option>
</select>
</div>
<div>
<!-- FFT destination LJ client Selection -->
<webaudio-switch id="fft/start" value="0" height="27" width="80" tooltip="Switch-B" src="knobs/fft.png"></webaudio-switch>
<select onclick="buttonClicked(this.value)" id="virtual" value="0">
<option value="fft/ljclient 0">0</option>
<option value="fft/ljclient 1">1</option>
<option value="fft/ljclient 2">2</option>
<option value="fft/ljclient 3">3</option>
</select>
<!-- FFT Point List destination -->
<select onclick="buttonClicked(this.value)">
<option value="fft/pl 0">0</option>
<option value="fft/pl 1">1</option>
<option value="fft/pl 2">2</option>
<option value="fft/pl 3">3</option>
</select>
</div>
<div>
<!-- Nozoids destination LJ client Selection -->
<webaudio-switch id="nozoid/start" value="0" height="27" width="80" tooltip="Switch-B" src="knobs/nozoids.png"></webaudio-switch>
<select onclick="buttonClicked(this.value)" id="virtual" value="0">
<option value="nozoid/ljclient 0">0</option>
<option value="nozoid/ljclient 1">1</option>
<option value="nozoid/ljclient 2">2</option>
<option value="nozoid/ljclient 3">3</option>
</select>
<!-- Nozoids Point List destination -->
<select onclick="buttonClicked(this.value)">
<option value="nozoid/pl 0">0</option>
<option value="nozoid/pl 1">1</option>
<option value="nozoid/pl 2">2</option>
<option value="nozoid/pl 3">3</option>
</select>
</div>
<!--
<div class="app">
<x-sign>
@ -134,9 +193,10 @@
<div></div>
</div>
<!-- End of Title block -->
<!--
Menu buttons and Status display
Menu Block : buttons and Status display
-->
<div id="mgstatus" class="mgstatus">
@ -153,7 +213,7 @@
</div>
<div>
<!-- Client actually drawn Selection -->
<span class="lasertext">Virtual</span>
<span class="lasertext">Scene</span>
<select onclick="buttonClicked(this.value)" id="virtual" value="0">
<option value="noteon 0">0</option>
<option value="noteon 1">1</option>
@ -200,9 +260,10 @@
</div>
<!-- End of Menu block -->
<!--
Align
Align grid block
-->
<div id="mgalign" class="mgalign">
@ -457,7 +518,7 @@
</div>
<!-- End of Align block -->
<!--
Live
-->
@ -557,9 +618,8 @@
</div>
</div>
<!--
Simulator and interfaces
<!-- End of Live block --><!--
Simulator header block and interfaces
-->
<div id = "mgsimu" class="mgsimu">
@ -570,9 +630,10 @@
</div>
<!-- Right part interfaces -->
<div>
<!-- End of Simu Header block -->
<div>
<!-- simu right part : Planetarium -->
<!-- simu right part : Planetarium Block -->
<div id ="planetUI" style = "display: none;justify-items: center;">
<!-- Stop and start switch -->
@ -646,8 +707,8 @@
</form>
</div>
<!-- simu right part : lissaUI -->
<!-- End of planetarium block -->
<!-- simu right part : lissaUI block -->
<div id ="lissaUI" style = "display: none;justify-items: center;">
<!-- Lissa interface -->
@ -686,7 +747,8 @@
</div>
</div>
</div>
<!-- End of Lissa block -->
<!-- simu right part : aiUI -->
<div id ="aiUI" style = "display: none;justify-items: center;">
@ -727,26 +789,29 @@
</div>
</div>
<!-- End of AI block --> <!-- simu right part : plugins UI Block-->
<!-- simu right part : pluginsUI -->
<div id ="pluginsUI" style = "display: none;justify-items: center;">
<div id ="pluginsUI" style = "display: grid;justify-items: center;">
<!-- Plugins choice Interface -->
<div>
<webaudio-switch id="simu/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/pysimu.png"></webaudio-switch>
<webaudio-switch id="pose/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/pose.png"></webaudio-switch>
<webaudio-switch id="bank0/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/bank0.png"></webaudio-switch>
</div>
<div>
<webaudio-switch id="glyph/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/glyph.png"></webaudio-switch>
<webaudio-switch id="cycl/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/cycl.png"></webaudio-switch>
</div>
<div>
</div>
<div>
<webaudio-switch id="midigen/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/midigen.png"></webaudio-switch>
<webaudio-switch id="audiogen/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/audiogen.png"></webaudio-switch>
<webaudio-switch id="viewgen/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/viewgen.png"></webaudio-switch>
<webaudio-switch id="/artnet/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/artnet.png"></webaudio-switch>
</div>
<div>
<!-- Glyph destination LJ client Selection -->
<span class="lasertext">Virtual</span>
<span class="lasertext">Scene</span>
<select onclick="buttonClicked(this.value)" id="virtual" value="0">
<option value="glyph/ljclient 0">0</option>
<option value="glyph/ljclient 1">1</option>
@ -755,7 +820,7 @@
</select>
<!-- Cycl destination LJ client Selection -->
<span class="lasertext">Virtual</span>
<span class="lasertext">Scene</span>
<select onclick="buttonClicked(this.value)" id="virtual" value="0">
<option value="cycl/ljclient 0">0</option>
<option value="cycl/ljclient 1">1</option>
@ -763,8 +828,8 @@
<option value="cycl/ljclient 3">3</option>
</select>
</div>
<div>
<div>
<!-- Glyph Point List destination -->
<span class="lasertext">PL</span>
<select onclick="buttonClicked(this.value)">
@ -789,11 +854,13 @@
<div>
<webaudio-switch id="ljpong/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/ljpong.png"></webaudio-switch>
<webaudio-switch id="ljwars/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/ljwars.png"></webaudio-switch>
<webaudio-switch id="maxw/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/maxw.png"></webaudio-switch>
<webaudio-switch id="square/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/square.png"></webaudio-switch>
</div>
<div>
<!-- LJ Pong destination LJ client Selection -->
<span class="lasertext">Virtual</span>
<span class="lasertext">Scene</span>
<select onclick="buttonClicked(this.value)" id="virtual" value="0">
<option value="ljpong/ljclient 0">0</option>
<option value="ljpong/ljclient 1">1</option>
@ -802,7 +869,7 @@
</select>
<!-- LJ Wars destination LJ client Selection -->
<span class="lasertext">Virtual</span>
<span class="lasertext">Scene</span>
<select onclick="buttonClicked(this.value)" id="virtual" value="0">
<option value="ljwars/ljclient 0">0</option>
<option value="ljwars/ljclient 1">1</option>
@ -821,9 +888,184 @@
<option value="ljpong/pl 3">3</option>
</select>
</div>
<div class = "destmatrix">
<!-- First line Scene 0 -->
<div>
<webaudio-switch id="scene/0/start" value="1" height="27" width="75" tooltip="Switch-B" src="knobs/scene0.png"></webaudio-switch>
</div>
<!-- /pluginame/dest PL, scene, laser -->
<div>
<!-- scene 0, laser 0 -->
<select class="selector-instance" data-type="search-selector" name="third-selector" id="second" onclick="buttonClicked(this.value)">
<option value="fft/dest 1 1 0" data-sublocale="HELLO" selected>EXT</option>
<option value="viewgen/dest 0 0 0">FFT</option>
<option value="viewgen/dest 1 0 0">Lissa</option>
<option value="viewgen/dest 2 0 0">Osci</option>
<option value="glyph/dest 0 0 0">Glyph</option>
<option value="nozoid/dest 0 0 0">Nozoids</option>
<option value="pose/dest 0 0 0">IdiotIA</option>
<option value="pose/dest 1 0 0">Starfield</option>
<option value="cycl/dest 0 0 0">Cycl</option>
<option value="planet/dest 0 0 0">Planet</option>
<option value="words/dest 0 0 0">Words</option>
<option value="ljpong/dest 0 0 0">Pong</option>
<option value="ljwars/dest 0 0 0">Wars</option>
<option value="maxw/dest 0 0 0">Maxw</option>
<option value="square/dest 0 0 0">Square</option>
</select>
</div>
<div>
<!-- scene 0, laser 1 -->
<select class="selector-instance" data-type="search-selector" name="third-selector" id="second" onclick="buttonClicked(this.value)">
<option value="fft/dest 1 0 0" data-sublocale="HELLO" selected>EXT</option>
<option value="viewgen/dest 0 0 1">FFT</option>
<option value="viewgen/dest 1 0 1">Lissa</option>
<option value="viewgen/dest 2 0 1">Osci</option>
<option value="glyph/dest 0 0 1">Glyph</option>
<option value="nozoid/dest 0 0 1">Nozoids</option>
<option value="pose/dest 0 0 1">IdiotIA</option>
<option value="pose/dest 1 0 1">Starfield</option>
<option value="cycl/dest 0 0 1">Cycl</option>
<option value="planet/dest 0 0 1">Planet</option>
<option value="words/dest 0 0 1">Words</option>
<option value="ljpong/dest 0 0 1">Pong</option>
<option value="ljwars/dest 0 0 1">Wars</option>
<option value="maxw/dest 0 0 1">Maxw</option>
<option value="square/dest 0 0 1">Square</option>
</select>
</div>
<div>
<!-- scene 0, laser 2 -->
<select onclick="buttonClicked(this.value)">
<option value="ext 0 1">EXT</option>
<option value="fft/dest 0 1 0">FFT 0</option>
<option value="fft/dest 1 1 0">FFT 1</option>
<option value="fft/dest 2 1 0">FFT 2</option>
<option value="fft/dest 3 1 0">FFT 3</option>
</select>
</div>
<div>
<!-- scene 0, laser 3 -->
</div>
<!-- Second line Scene 1 -->
<div>
<webaudio-switch id="scene/1/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/scene1.png"></webaudio-switch>
</div>
<!-- /pluginame/dest PL, scene, laser -->
<div>
<!-- scene 1, laser 0 -->
<select class="selector-instance" data-type="search-selector" name="third-selector" id="second" onclick="buttonClicked(this.value)">
<option value="fft/dest 1 1 0" data-sublocale="HELLO" selected>EXT</option>
<option value="viewgen/dest 0 1 0">FFT</option>
<option value="viewgen/dest 1 1 0">Lissa</option>
<option value="viewgen/dest 2 1 0">Osci</option>
<option value="glyph/dest 0 1 0">Glyph</option>
<option value="nozoid/dest 0 1 0">Nozoids</option>
<option value="pose/dest 0 1 0">IdiotIA</option>
<option value="pose/dest 1 1 0">Starfield</option>
<option value="cycl/dest 0 1 0">Cycl</option>
<option value="planet/dest 0 1 0">Planet</option>
<option value="words/dest 0 1 0">Words</option>
<option value="ljpong/dest 0 1 0">Pong</option>
<option value="ljwars/dest 0 1 0">Wars</option>
<option value="maxw/dest 0 1 0">Maxw</option>
<option value="square/dest 0 1 0">Square</option>
</select>
</div>
<div>
<!-- scene 1 , laser 1 -->
<select class="selector-instance" data-type="search-selector" name="third-selector" id="second" onclick="buttonClicked(this.value)">
<option value="fft/dest 1 0 0" data-sublocale="HELLO" selected>EXT</option>
<option value="viewgen/dest 0 1 1">FFT</option>
<option value="viewgen/dest 1 1 1">Lissa</option>
<option value="viewgen/dest 2 1 1">Osci</option>
<option value="glyph/dest 0 1 1">Glyph</option>
<option value="nozoid/dest 0 1 1">Nozoids</option>
<option value="pose/dest 0 1 1">IdiotIA</option>
<option value="pose/dest 1 1 1">Starfield</option>
<option value="cycl/dest 0 1 1">Cycl</option>
<option value="planet/dest 0 1 1">Planet</option>
<option value="words/dest 0 1 1">Words</option>
<option value="ljpong/dest 0 1 1">Pong</option>
<option value="ljwars/dest 0 1 1">Wars</option>
<option value="maxw/dest 0 1 1">Maxw</option>
<option value="square/dest 0 1 1">Square</option>
</select>
</div>
<div>
<!-- scene 1 , laser 2 -->
</div>
<div>
<!-- scene 1 , laser 3 -->
</div>
<!-- Third line Scene 2 -->
<div>
<webaudio-switch id="scene/2/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/scene2.png"></webaudio-switch>
</div>
<div>
<!-- scene 2 , laser 0 -->
</div>
<div>
<!-- scene 2 , laser 1 -->
</div>
<div>
<!-- scene 2 , laser 2 -->
</div>
<div>
<!-- scene 2 , laser 3 -->
</div>
<!-- Fourth line Scene 3 -->
<div>
<webaudio-switch id="scene/3/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/scene3.png"></webaudio-switch>
</div>
<div>
<!-- scene 3 , laser 0 -->
</div>
<div>
<!-- scene 3 , laser 1 -->
</div>
<div>
<!-- scene 3 , laser 2 -->
</div>
<div>
<!-- scene 3 , laser 3 -->
</div>
<!-- Fifth line -->
<div><span class="lasertext">Selection</span></div>
<div>
<webaudio-switch id="laser0/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/laser0.png"></webaudio-switch>
</div>
<div>
<webaudio-switch id="laser1/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/laser1.png"></webaudio-switch>
</div>
<div>
<webaudio-switch id="laser2/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/laser2.png"></webaudio-switch>
</div>
<div>
<webaudio-switch id="laser3/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/laser3.png"></webaudio-switch>
</div>
</div>
</div>
<script>
new Selector();
</script>
<!-- End of PLuginUI block -->
<!-- simu right part : bank0 vjUI -->
<div id ="vjUI" class="cnvbuttons">
@ -854,65 +1096,78 @@
</div>
<!-- End of bank0 block -->
<!-- simu right part : poseUI block -->
<!-- simu right part : poseUI -->
<div id ="poseUI" class="posebuttons" style = "display: grid;justify-items: center;">
<!-- IdiotIA display flag -->
<div><span class="lasertext">IdiotIA</span></div>
<div><webaudio-switch id="pose/idiotia/0" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/0.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia/1" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/1.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia/2" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/2.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia/3" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/3.png"></webaudio-switch></div>
<div></div>
<div id ="poseUI" class="posebuttons" style = "display: none;justify-items: center;">
<!-- IdiotIA animation selection first line -->
<div><webaudio-switch id="pose/anim/0" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim/1" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim/2" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim/3" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim/4" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim/5" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 0" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 1" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 2" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 3" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 4" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 5" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<!-- IdiotIA animation selection second line -->
<div><webaudio-switch id="pose/anim/6" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim/7" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim/8" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim/9" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim/10" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim/11" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 6" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 7" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 8" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 9" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 10" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 11" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<!-- IdiotIA animation selection third line -->
<div><webaudio-switch id="pose/anim/12" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim/13" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim/14" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim/15" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim/16" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim/17" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 12" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 13" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 14" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 15" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 16" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/anim 17" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/idiotia.png"></webaudio-switch></div>
<!-- Pose frame player -->
<div><span class="lasertext">Frames</span></div>
<div><webaudio-switch id="pose/speed 1" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/slower.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/speed 2" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/stop.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/speed 3" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/play.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/speed 4" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/faster.png"></webaudio-switch></div>
<div></div>
<!-- IdiotIA display flag -->
<div><span class="lasertext">IdiotIA</span></div>
<div><webaudio-switch id="pose/idiotia 0" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/0.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia 1" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/1.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia 2" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/2.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/idiotia 3" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/3.png"></webaudio-switch></div>
<div></div>
<!-- Realtime pose display flag -->
<div><span class="lasertext">Live</span></div>
<div><webaudio-switch id="pose/live/0" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/0.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/live/1" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/1.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/live/2" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/2.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/live/3" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/3.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/live 0" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/0.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/live 1" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/1.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/live 2" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/2.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/live 3" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/3.png"></webaudio-switch></div>
<div></div>
<!-- Starfield display lag -->
<div><span class="lasertext">Fields</span></div>
<div><webaudio-switch id="pose/field/0" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/0.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/field/1" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/1.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/field/2" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/2.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/field/3" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/3.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/field 0" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/0.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/field 1" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/1.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/field 2" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/2.png"></webaudio-switch></div>
<div><webaudio-switch id="pose/field 3" value="0" tooltip="Switch-B" height="24" width="64" src="knobs/3.png"></webaudio-switch></div>
<div></div>
</div>
<!-- End of PoseUI block -->
<!-- simu right part : wordsUI -->
<!-- simu right part : wordsUI -->
<div id ="wordsUI" style = "display: none;justify-items: center;">
<div>
@ -930,7 +1185,8 @@
<!-- Words 0 -->
<form onsubmit="onSubmit(); return false;">
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="words/text/0" value=" ">
<span class="lasertext">Laser 0</span>
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="words/text/0" value="ZERO">
<select onclick="buttonClicked(this.value)">
<!-- color selection -->
<option value="words/color/0 red" selected >Red</option>
@ -941,12 +1197,12 @@
<option value="words/color/0 cyan">Cyan</option>
<option value="words/color/0 pink">Pink</option>
</select>
<span class="lasertext">Laser 0</span>
<webaudio-switch id="words/play/0" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/play.png"></webaudio-switch>
</form>
<!-- Words 1 -->
<form onsubmit="onSubmit(); return false;">
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="words/text/1" value=" ">
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="words/text/1" value="ONE">
<select onclick="buttonClicked(this.value)">
<!-- color selection -->
<option value="words/color/1 red" selected >Red</option>
@ -962,7 +1218,7 @@
<!-- Words 2 -->
<form onsubmit="onSubmit(); return false;">
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="words/text/2" value=" ">
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="words/text/2" value="TWO">
<select onclick="buttonClicked(this.value)">
<!-- color selection -->
<option value="words/color/2/color red" selected >Red</option>
@ -978,7 +1234,7 @@
<!-- Words 3 -->
<form onsubmit="onSubmit(); return false;">
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="words/text/3" value=" ">
<input class = "submit" onchange = "onSubmit(this.id)" type="text" id="words/text/3" value="THREE">
<select onclick="buttonClicked(this.value)">
<!-- color selection -->
<option value="words/color/3 red" selected >Red</option>
@ -995,36 +1251,120 @@
</div>
<!-- End of WordsUI block -->
<!-- simu right part : NozoidsUI Block -->
<!-- simu right part : NozoidUI -->
<div id ="nozoidUI" class="nozoidbuttons" style = "display: none;justify-items: center;">
<div id ="nozoidUI" style = "display: none;justify-items: center;">
<!-- Stop and start switch -->
<div>
<div><webaudio-switch id="nozoid/start" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/nozoids.png"></webaudio-switch></div>
</div>
<div>
<!-- Nozoids list and leds -->
<div>
<webaudio-knob id="nozoid/mmo3/led" src="knobs/leds.png" height="17" width="17" diameter="17" min="0" max="6" value="0" sprites="6"></webaudio-knob>
<webaudio-switch id="nozoid/mmo3" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/mmo3.png"></webaudio-switch>
<webaudio-switch id="nozoid/mmo3/down 50" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/slower.png"></webaudio-switch>
<webaudio-switch id="nozoid/mmo3/up 50" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/faster.png"></webaudio-switch>
<!-- Nozoids UI : names and leds -->
<div>
<webaudio-knob id="nozoid/o2/led" src="knobs/leds.png" height="17" width="17" diameter="17" min="0" max="6" value="0" sprites="6"></webaudio-knob>
<webaudio-switch id="nozoid/o2" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/o2.png"></webaudio-switch>
</div>
<div>
<webaudio-knob id="nozoid/m3/led" src="knobs/leds.png" height="17" width="17" diameter="17" min="0" max="6" value="0" sprites="6"></webaudio-knob>
<webaudio-switch id="nozoid/m3" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/m3.png"></webaudio-switch>
</div>
<!-- OCS-2 UI -->
<div style="border-color: #445;border-style:groove;border-width:1px;">
<div></div>
<webaudio-knob id="nozoid/ocs2/led" src="knobs/leds.png" height="17" width="17" diameter="17" min="0" max="6" value="0" sprites="6"></webaudio-knob>
<webaudio-switch id="nozoid/ocs2" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/ocs2.png"></webaudio-switch>
<webaudio-switch id="nozoid/down/o2 25" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/slower.png"></webaudio-switch>
<webaudio-switch id="nozoid/up/o2 25" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/faster.png"></webaudio-switch>
<span class="lasertext">Sound curve for X</span>
<webaudio-switch id="nozoid/ocs2/down 50" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/slower.png"></webaudio-switch>
<webaudio-switch id="nozoid/ocs2/up 50" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/faster.png"></webaudio-switch>
<select onclick="buttonClicked(this.value)">
<option value="nozoid/X/o2 0">STOP</option>
<option value="nozoid/X/o2 1">VCO1</option>
<option value="nozoid/X/o2 2">VCO2</option>
<option value="nozoid/X/o2 3">LFO1</option>
<option value="nozoid/X/o2 4">LFO2</option>
<option value="nozoid/X/o2 5">LFO3</option>
<option value="nozoid/X/o2 6">CV/GEN</option>
<option value="nozoid/X/o2 7">ADSR</option>
<option value="nozoid/X/o2 8">LIGHT</option>
<option value="nozoid/X/o2 9">LINE IN</option>
<option value="nozoid/X/o2 10">MIDI</option>
<option value="nozoid/X/o2 11">CV1</option>
<option value="nozoid/X/o2 12">CV2</option>
<option value="nozoid/X/o2 13">CV3</option>
<option value="nozoid/X/o2 17">1 Out</option>
<option value="nozoid/X/o2 18">2 Out</option>
<option value="nozoid/X/o2 20">VCF</option>
<option value="nozoid/X/o2 21">MIX</option>
<option value="nozoid/X/o2 22">VCA</option>
</select>
<span class="lasertext">Sound curve for Y</span>
<select onclick="buttonClicked(this.value)">
<option value="nozoid/Y/o2 0">STOP</option>
<option value="nozoid/Y/o2 1">VCO1</option>
<option value="nozoid/Y/o2 2">VCO2</option>
<option value="nozoid/Y/o2 3">LFO1</option>
<option value="nozoid/Y/o2 4">LFO2</option>
<option value="nozoid/Y/o2 5">LFO3</option>
<option value="nozoid/Y/o2 6">CV/GEN</option>
<option value="nozoid/Y/o2 7">ADSR</option>
<option value="nozoid/Y/o2 8">LIGHT</option>
<option value="nozoid/Y/o2 9">LINE IN</option>
<option value="nozoid/Y/o2 10">MIDI</option>
<option value="nozoid/Y/o2 11">CV1</option>
<option value="nozoid/Y/o2 12">CV2</option>
<option value="nozoid/Y/o2 13">CV3</option>
<option value="nozoid/Y/o2 17">1 Out</option>
<option value="nozoid/Y/o2 18">2 Out</option>
<option value="nozoid/Y/o2 20">VCF</option>
<option value="nozoid/Y/o2 21">MIX</option>
<option value="nozoid/Y/o2 22">VCA</option>
</select>
</div>
<!-- MMO-3 UI -->
<div style="border-color: #445;border-style:groove;border-width:1px;">
<webaudio-switch id="nozoid/down/m3 25" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/slower.png"></webaudio-switch>
<webaudio-switch id="nozoid/up/m3 25" value="0" height="27" width="75" tooltip="Switch-B" src="knobs/faster.png"></webaudio-switch>
<span class="lasertext">Sound curve for X</span>
<select onclick="buttonClicked(this.value)">
<option value="nozoid/X/m3 0">Stop</option>
<option value="nozoid/X/m3 1">OSC1</option>
<option value="nozoid/X/m3 2">OSC2</option>
<option value="nozoid/X/m3 3">OSC3</option>
<option value="nozoid/X/m3 4">LFO1</option>
<option value="nozoid/X/m3 5">LFO2</option>
<option value="nozoid/X/m3 6">LFO3</option>
<option value="nozoid/X/m3 7">ADSR</option>
<option value="nozoid/X/m3 8">CV</option>
<option value="nozoid/X/m3 9">Line IN</option>
<option value="nozoid/X/m3 10">Jstck</option>
<option value="nozoid/X/m3 11">INL</option>
<option value="nozoid/X/m3 12">INR</option>
</select>
<span class="lasertext">Sound curve for Y</span>
<select onclick="buttonClicked(this.value)">
<option value="nozoid/Y/m3 0">Stop</option>
<option value="nozoid/Y/m3 1">OSC1</option>
<option value="nozoid/Y/m3 2">OSC2</option>
<option value="nozoid/Y/m3 3">OSC3</option>
<option value="nozoid/Y/m3 4">LFO1</option>
<option value="nozoid/Y/m3 5">LFO2</option>
<option value="nozoid/Y/m3 6">LFO3</option>
<option value="nozoid/Y/m3 7">ADSR</option>
<option value="nozoid/Y/m3 8">CV</option>
<option value="nozoid/Y/m3 9">Line IN</option>
<option value="nozoid/Y/m3 10">Jstck</option>
<option value="nozoid/Y/m3 11">INL</option>
<option value="nozoid/X/m3 12">INR</option>
</select>
</div>
<!-- Curve choice -->
<div>
<span class="lasertext" >Curve</span>
<span class="lasertext">CurveNumber : </span>
<select onclick="buttonClicked(this.value)">
<option value="nozoid/curve 0">0</option>
<option value="nozoid/curve 1">1</option>
@ -1033,99 +1373,29 @@
</select>
<!-- Color choice -->
<span class="lasertext" >Color</span>
<!-- 0 black / 1 green / 2 cyan / 3 pink / 4 yellow / 5 red / 6 white (in nozoids.py) -->
<span class="lasertext">CurveColor :</span>
<select onclick="buttonClicked(this.value)">
<option value="nozoid/color 255 0 0">Red</option>
<option value="nozoid/color 0 255 0">Green</option>
<option value="nozoid/color 0 0 255">Blue</option>
<option value="nozoid/color 255 255 0">Yellow</option>
<option value="nozoid/color 0 255 255">Cyan</option>
<option value="nozoid/color 255 0 255">Magenta</option>
<option value="nozoid/color 5">Red</option>
<option value="nozoid/color 1">Green</option>
<option value="nozoid/color 2">Blue</option>
<option value="nozoid/color 4">Yellow</option>
<option value="nozoid/color 3">Pink</option>
<option value="nozoid/color 6">White</option>
</select>
</div>
<!-- X and X Curve choices -->
<div>
<span class="lasertext" >X</span>
<select onclick="buttonClicked(this.value)">
<option value="nozoid/X 0">STOP</option>
<option value="nozoid/X 1">VCO1</option>
<option value="nozoid/X 2">VCO2</option>
<option value="nozoid/X 3">LFO1</option>
<option value="nozoid/X 4">LFO2</option>
<option value="nozoid/X 5">LFO3</option>
<option value="nozoid/X 6">CV/GEN</option>
<option value="nozoid/X 7">ADSR</option>
<option value="nozoid/X 8">LIGHT</option>
<option value="nozoid/X 9">LINE IN</option>
<option value="nozoid/X 10">MIDI</option>
<option value="nozoid/X 11">CV1</option>
<option value="nozoid/X 12">CV2</option>
<option value="nozoid/X 13">CV3</option>
<option value="nozoid/X 17">1 Out</option>
<option value="nozoid/X 18">2 Out</option>
<option value="nozoid/X 20">VCF</option>
<option value="nozoid/X 21">MIX</option>
<option value="nozoid/X 22">VCA</option>
</select>
<span class="lasertext" >Curve</span>
<select onclick="buttonClicked(this.value)">
<option value="nozoid/X 0">Stop</option>
<option value="nozoid/X 1">OSC1</option>
<option value="nozoid/X 2">OSC2</option>
<option value="nozoid/X 3">OSC3</option>
<option value="nozoid/X 4">LFO1</option>
<option value="nozoid/X 5">LFO2</option>
<option value="nozoid/X 6">LFO3</option>
<option value="nozoid/X 7">ADSR</option>
<option value="nozoid/X 8">CV</option>
<option value="nozoid/X 9">Line IN</option>
<option value="nozoid/X 10">Jstck</option>
<option value="nozoid/X 11">INL</option>
<option value="nozoid/X 12">INR</option>
</select>
</div>
<!-- Laser choice -->
<!-- Y and Y Curve choices -->
<div>
<span class="lasertext" >Y</span>
<select onclick="buttonClicked(this.value)">
<option value="nozoid/Y 0">STOP</option>
<option value="nozoid/Y 1">VCO1</option>
<option value="nozoid/Y 2">VCO2</option>
<option value="nozoid/Y 3">LFO1</option>
<option value="nozoid/Y 4">LFO2</option>
<option value="nozoid/Y 5">LFO3</option>
<option value="nozoid/Y 6">CV/GEN</option>
<option value="nozoid/Y 7">ADSR</option>
<option value="nozoid/Y 8">LIGHT</option>
<option value="nozoid/Y 9">LINE IN</option>
<option value="nozoid/Y 10">MIDI</option>
<option value="nozoid/Y 11">CV1</option>
<option value="nozoid/Y 12">CV2</option>
<option value="nozoid/Y 13">CV3</option>
<option value="nozoid/Y 17">1 Out</option>
<option value="nozoid/Y 18">2 Out</option>
<option value="nozoid/Y 20">VCF</option>
<option value="nozoid/Y 21">MIX</option>
<option value="nozoid/Y 22">VCA</option>
</select>
<span class="lasertext" >Curve</span>
<select onclick="buttonClicked(this.value)">
<option value="nozoid/Y 0">Stop</option>
<option value="nozoid/Y 1">OSC1</option>
<option value="nozoid/Y 2">OSC2</option>
<option value="nozoid/Y 3">OSC3</option>
<option value="nozoid/Y 4">LFO1</option>
<option value="nozoid/Y 5">LFO2</option>
<option value="nozoid/Y 6">LFO3</option>
<option value="nozoid/Y 7">ADSR</option>
<option value="nozoid/Y 8">CV</option>
<option value="nozoid/Y 9">Line IN</option>
<option value="nozoid/Y 10">Jstck</option>
<option value="nozoid/Y 11">INL</option>
<option value="nozoid/X 12">INR</option>
</select>
<span class="lasertext">DrawingLaser :</span>
<select onclick="buttonClicked(this.value)">
<option value="nozoid/laser 0">0</option>
<option value="nozoid/laser 1">1</option>
<option value="nozoid/laser 2">2</option>
<option value="nozoid/laser 3">3</option>
</select>
</div>
@ -1140,7 +1410,7 @@
<option value="nozoid/auto/X/OutR">OutR</option>
<option value="nozoid/auto/X/OutL">OutL</option>
</select>
<span class="lasertext">Y</span>
<span class="lasertext">Automod : Y</span>
<select onclick="buttonClicked(this.value)">
<option value="nozoid/auto/Y/0">0</option>
<option value="nozoid/auto/Y/1 Out">1 Out</option>
@ -1150,19 +1420,17 @@
<option value="nozoid/auto/Y/OutL">OutL</option>
</select>
</div>
</div>
<div></div>
<div></div>
</div>
</div>
</div>
<!-- End of NozoidsUI block -->
<!--
Run
Run Block
-->
<div id="mgrun" class="mgrun">
@ -1176,14 +1444,14 @@
<div><img src="knobs/client.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/client.png" alt=" " class="icongrid" /></div>
<div><img src="knobs/client.png" alt=" " class="icongrid" /></div>
<div><button id ="noteon 0" onclick ="buttonClicked(this.id)" class="button:checked">0</button></div>
<div><button id ="noteon 1" onclick ="buttonClicked(this.id)" class="button">1</button></div>
<div><button id ="noteon 2" onclick ="buttonClicked(this.id)" class="button">2</button></div>
<div><button id ="noteon 3" onclick ="buttonClicked(this.id)" class="button">3</button></div>
<div><button id ="noteon 4" onclick ="buttonClicked(this.id)" class="button">4</button></div>
<div><button id ="noteon 5" onclick ="buttonClicked(this.id)" class="button">5</button></div>
<div><button id ="noteon 6" onclick ="buttonClicked(this.id)" class="button">6</button></div>
<div><button id ="noteon 7" onclick ="buttonClicked(this.id)" class="button">7</button></div>
<div><button id ="noteon 0" onclick ="buttonClicked(this.id)" class="button:checked">0</button></div>
<div><button id ="noteon 1" onclick ="buttonClicked(this.id)" class="button">1</button></div>
<div><button id ="noteon 2" onclick ="buttonClicked(this.id)" class="button">2</button></div>
<div><button id ="noteon 3" onclick ="buttonClicked(this.id)" class="button">3</button></div>
<div><button id ="noteon 4" onclick ="buttonClicked(this.id)" class="button">4</button></div>
<div><button id ="noteon 5" onclick ="buttonClicked(this.id)" class="button">5</button></div>
<div><button id ="noteon 6" onclick ="buttonClicked(this.id)" class="button">6</button></div>
<div><button id ="noteon 7" onclick ="buttonClicked(this.id)" class="button">7</button></div>
<!-- Simulator PL selection grid -->
<div><img src="knobs/iconljay2.png" alt=" " class="icongrid" /></div>
@ -1239,9 +1507,12 @@
<div></div>
<div></div>
</div>
<!-- End of Run block -->
<!--
Footer display events for debug
Footer block display events for debug
-->
<div class="mgfooter">
@ -1491,5 +1762,5 @@
<webaudio-switch id="laser/3" height="64" width="25" value="0" src="knobs/key0.png" type="toggle"></webaudio-switch>
</div>
-->
<!-- End of Footer block -->
</html>

BIN
webui/knobs/artnet.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
webui/knobs/audiogen.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
webui/knobs/blank.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

37
webui/knobs/close.svg Executable file
View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 31.112 31.112" style="enable-background:new 0 0 31.112 31.112;" xml:space="preserve">
<polygon points="31.112,1.414 29.698,0 15.556,14.142 1.414,0 0,1.414 14.142,15.556 0,29.698 1.414,31.112 15.556,16.97
29.698,31.112 31.112,29.698 16.97,15.556 "/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 672 B

BIN
webui/knobs/fft.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

BIN
webui/knobs/group0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
webui/knobs/group1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
webui/knobs/group2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
webui/knobs/group3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
webui/knobs/laser0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
webui/knobs/laser1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
webui/knobs/laser2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
webui/knobs/laser3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
webui/knobs/maxw.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
webui/knobs/midigen.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

BIN
webui/knobs/onoff3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
webui/knobs/play.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

BIN
webui/knobs/scene0.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

BIN
webui/knobs/scene1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Some files were not shown because too many files have changed in this diff Show More