Compare commits

..

1 Commits

Author SHA1 Message Date
74ba0e828b [feat in progress]: drawing improvment
I understand the previous way to add Point.
I have read the paper who describe the way to add point.
I'm doing the the visual witch are used in the paper to test the
optimisation.
2020-12-06 12:45:25 +01:00
41 changed files with 1991 additions and 4634 deletions

2
.gitignore vendored
View File

@ -1,5 +1,3 @@
.*sw* .*sw*
*__pycache__ *__pycache__
www/config.js www/config.js

55
LJ.conf
View File

@ -1,8 +1,8 @@
[General] [General]
lasernumber = 1 lasernumber = 4
debug = 1 debug = 0
ljayserverip = 0.0.0.0 ljayserverip = 0.0.0.0
wwwip = 127.0.0.1 wwwip = 192.168.2.44
nozoscip = 127.0.0.1 nozoscip = 127.0.0.1
bhoroscip = 127.0.0.1 bhoroscip = 127.0.0.1
autostart = artnet autostart = artnet
@ -12,7 +12,7 @@ wsport = 9001
[laser0] [laser0]
color = -1 color = -1
type = DS1000 type = DS1000
ip = 127.0.0.1 ip = 192.168.2.3
kpps = 25000 kpps = 25000
centerx = 0 centerx = 0
centery = 0 centery = 0
@ -21,7 +21,7 @@ zoomy = 50.0
sizex = 32000 sizex = 32000
sizey = 32000 sizey = 32000
finangle = 0.0 finangle = 0.0
swapx = 1 swapx = -1
swapy = -1 swapy = -1
lsteps = [ (1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)] lsteps = [ (1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)]
warpdest = [[-1500., 1500.], warpdest = [[-1500., 1500.],
@ -36,8 +36,8 @@ ip = 192.168.2.5
kpps = 25000 kpps = 25000
centerx = 0 centerx = 0
centery = 0 centery = 0
zoomx = 50.0 zoomx = 80.0
zoomy = 50.0 zoomy = 80.0
sizex = 32000 sizex = 32000
sizey = 32000 sizey = 32000
finangle = 0.0 finangle = 0.0
@ -45,9 +45,9 @@ swapx = -1
swapy = -1 swapy = -1
lsteps = [ (1.0, 2),(0.25, 1), (0.75, 1), (1.0, 5)] lsteps = [ (1.0, 2),(0.25, 1), (0.75, 1), (1.0, 5)]
warpdest = [[-1500., 1500.], warpdest = [[-1500., 1500.],
[ 1500., 1500.], [ 1500., 1500.],
[ 1500.,-1500.], [ 1500.,-1500.],
[-1500.,-1500.]] [-1500.,-1500.]]
[laser2] [laser2]
color = -1 color = -1
@ -65,14 +65,14 @@ swapx = -1
swapy = -1 swapy = -1
lsteps = [(1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)] lsteps = [(1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)]
warpdest = [[-1500., 1500.], warpdest = [[-1500., 1500.],
[ 1500., 1500.], [ 1500., 1500.],
[ 1500.,-1500.], [ 1500.,-1500.],
[-1500.,-1500.]] [-1500.,-1500.]]
[laser3] [laser3]
color = -1 color = -1
type = LUKE400 type = LUKE400
ip = 192.168.1.5 ip = 192.168.2.4
kpps = 25000 kpps = 25000
centerx = 0 centerx = 0
centery = 0 centery = 0
@ -81,19 +81,34 @@ zoomy = 50.0
sizex = 32000 sizex = 32000
sizey = 32000 sizey = 32000
finangle = 0.0 finangle = 0.0
swapx = -1 swapx = 1
swapy = -1 swapy = 1
lsteps = [(1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)] lsteps = [(1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)]
warpdest = [[-1500., 1500.], warpdest = [[-1500., 1500.],
[ 1500., 1500.], [ 1500., 1500.],
[ 1500.,-1500.], [ 1500.,-1500.],
[-1500.,-1500.]] [-1500.,-1500.]]
[plugins] [plugins]
plugins = { plugins = {
"aurora": {"OSC": 8090, "command": "python3 plugins/aurora/aurora.py", "display": True}, "aurora": {"OSC": 8090, "command": "python3 plugins/aurora/aurora.py", "display": True},
"nozoid": {"OSC": 8003, "command": "python3 plugins/audio/nozoids3.py", "display": True},
"glyph": {"OSC": 8004, "command": "python3 plugins/laserglyph.py", "display": True},
"planet": {"OSC": 8005, "command": "python3 plugins/planetarium/main.py", "display": True},
"words": {"OSC": 8006, "command": "python3 plugins/livewords3.py", "display": True},
"cycl": {"OSC": 8007, "command": "python3 plugins/textcycl.py", "display": True},
"simu": {"OSC": 8008, "command": "python plugins/pysimu.py", "display": False},
"artnet": {"OSC": 8009, "command": "python3 libs3/artnet.py", "display": False}, "artnet": {"OSC": 8009, "command": "python3 libs3/artnet.py", "display": False},
"trckr": {"OSC": 8017, "command": "python3 plugins/trckr.py", "display": False},
"maxw": {"OSC": 8012, "command": "python3 plugins/maxwell.py", "display": True},
"square": {"OSC": 8013, "command": "python3 plugins/square.py", "display": True}, "square": {"OSC": 8013, "command": "python3 plugins/square.py", "display": True},
"custom1": {"OSC": 8014, "command": "python3 plugins/custom1.py", "display": True} "custom1": {"OSC": 8014, "command": "python3 plugins/custom1.py", "display": True},
"mitraille": {"OSC": 8015, "command": "python3 plugins/audio/mitraille.py", "display": True},
"livecode": {"OSC": 8016, "command": "python3 plugins/livecoding.py", "display": True},
"ljpong": {"OSC": 8020, "command": "python plugins/games/ljpong/main.py", "display": True},
"ljwars": {"OSC": 8021, "command": "python plugins/games/ljsw/main.py", "display": True},
"audiogen": {"OSC": 8030, "command": "python3 plugins/audio/audiogen.py", "display": False},
"midigen": {"OSC": 8031, "command": "python3 plugins/audio/midigen.py", "display": False},
"viewgen": {"OSC": 8032, "command": "python3 plugins/audio/viewgen.py", "display": True}
} }

114
LJ_template.conf Normal file
View File

@ -0,0 +1,114 @@
[General]
lasernumber = 1
debug = 0
ljayserverip = 0.0.0.0
wwwip = 192.168.2.43
nozoscip = 127.0.0.1
bhoroscip = 127.0.0.1
autostart = artnet
wstype = ws
wsport = 9001
[laser0]
color = -1
type = DS1000
ip = 192.168.2.3
kpps = 25000
centerx = 0
centery = 0
zoomx = 50.0
zoomy = 50.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.]]
[laser1]
color = -1
type = LOCAL
ip = 192.168.2.5
kpps = 25000
centerx = 0
centery = 0
zoomx = 50.0
zoomy = 50.0
sizex = 32000
sizey = 32000
finangle = 0.0
swapx = -1
swapy = -1
lsteps = [ (1.0, 2),(0.25, 1), (0.75, 1), (1.0, 5)]
warpdest = [[-1500., 1500.],
[ 1500., 1500.],
[ 1500.,-1500.],
[-1500.,-1500.]]
[laser2]
color = -1
type = LUKE400
ip = 192.168.2.6
kpps = 25000
centerx = 0
centery = 0
zoomx = 50.0
zoomy = 50.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.]]
[laser3]
color = -1
type = LUKE400
ip = 192.168.1.5
kpps = 25000
centerx = 0
centery = 0
zoomx = 50.0
zoomy = 50.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 = {
"aurora": {"OSC": 8090, "command": "python3 plugins/aurora/aurora.py", "display": True},
"nozoid": {"OSC": 8003, "command": "python3 plugins/audio/nozoids3.py", "display": True},
"glyph": {"OSC": 8004, "command": "python3 plugins/laserglyph.py", "display": True},
"planet": {"OSC": 8005, "command": "python3 plugins/planetarium/main.py", "display": True},
"words": {"OSC": 8006, "command": "python3 plugins/livewords3.py", "display": True},
"cycl": {"OSC": 8007, "command": "python3 plugins/textcycl.py", "display": True},
"simu": {"OSC": 8008, "command": "python plugins/pysimu.py", "display": False},
"artnet": {"OSC": 8009, "command": "python3 libs3/artnet.py", "display": False},
"trckr": {"OSC": 8017, "command": "python3 plugins/trckr.py", "display": False},
"maxw": {"OSC": 8012, "command": "python3 plugins/maxwell.py", "display": True},
"square": {"OSC": 8013, "command": "python3 plugins/square.py", "display": True},
"custom1": {"OSC": 8014, "command": "python3 plugins/custom1.py", "display": True},
"mitraille": {"OSC": 8015, "command": "python3 plugins/audio/mitraille.py", "display": True},
"livecode": {"OSC": 8016, "command": "python3 plugins/livecoding.py", "display": True},
"ljpong": {"OSC": 8020, "command": "python plugins/games/ljpong/main.py", "display": True},
"ljwars": {"OSC": 8021, "command": "python plugins/games/ljsw/main.py", "display": True},
"audiogen": {"OSC": 8030, "command": "python3 plugins/audio/audiogen.py", "display": False},
"midigen": {"OSC": 8031, "command": "python3 plugins/audio/midigen.py", "display": False},
"viewgen": {"OSC": 8032, "command": "python3 plugins/audio/viewgen.py", "display": True}
}

BIN
Pd/.DS_Store vendored

Binary file not shown.

View File

@ -1,23 +0,0 @@
#N canvas 468 143 709 527 10;
#X msg 60 237 disconnect;
#X floatatom 27 294 0 0 0 0 - - -;
#X text 22 315 Outlet is nonzero if connection is open \, zero otherwise.
;
#X msg 37 60 send mytext trololo;
#X obj 28 267 netsend 1;
#X msg 51 125 send /pl/0/0 (150 2300 65280) (170 170 65280) (230 170
65280) (210 230 65280) (150 230 65280);
#X text 258 29 LJ Sender;
#X msg 46 84 send /pl/0/0 150 2300 65280 170 170 65280 230 170 65280
210 230 65280 150 230 65280;
#X msg 26 39 connect 127.0.0.1 8083;
#X msg 58 165 send /pl/0/0 [(150.0:230.0:65280) (170.0:170.0:65280)
(230.0:170.0:65280) (210.0:230.0:65280) (150.0:230.0:65280)];
#X text 444 174 <- le mieux;
#X connect 0 0 4 0;
#X connect 3 0 4 0;
#X connect 4 0 1 0;
#X connect 5 0 4 0;
#X connect 7 0 4 0;
#X connect 8 0 4 0;
#X connect 9 0 4 0;

View File

@ -1,106 +0,0 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# -*- mode: Python -*-
'''
LJPD
Udp server to redis
v0.1b
'''
import traceback, time
import argparse
import socket
import _thread
import redis
print()
print ("LJPD")
print ("Arguments parsing if needed...")
argsparser = argparse.ArgumentParser(description="dumpUDP v0.1b help mode")
argsparser.add_argument("-i","--IP",help="IP to bind to (0.0.0.0 by default)", type=str)
argsparser.add_argument("-p","--port",help="UDP port to bind to (9000 by default)", type=str)
argsparser.add_argument("-l","--lj",help="LJ IP address (127.0.0.1 by default)", type=str)
args = argsparser.parse_args()
# LJ server IP name
if args.IP:
ljIP = lj.IP
else:
ljIP = "127.0.0.1"
# Server
if args.IP:
serverIP = args.IP
else:
serverIP = "0.0.0.0"
# ORCA destination device
if args.port:
UDPORT = int(args.port)
else:
UDPORT = 8083
print("Connecting to Redis...")
r = redis.StrictRedis(host= ljIP, port=6379, db=0)
def GetTime():
return time.strftime("%a, %d %b %Y %H:%M:%S", time.localtime())
def udp_thread():
while True:
payload, client_address = sock.recvfrom(1024)
udpath = payload.decode('utf_8')
print(GetTime(),"From", str(client_address),"got", udpath )
#r.set('/pl/0/0', "/pl/"+str(clientnumber)+"/")
#print(udpath[0:1], " ",udpath[1:2], " ",udpath[2:3], " ",udpath[3:4], " " )
# Reply to client
bytesToSend = str.encode("ACK :"+str(payload))
serverAddressPort = (client_address, UDPORT)
bufferSize = 1024
#sock.sendto(bytesToSend, serverAddressPort)
sock.sendto(bytesToSend, client_address)
time.sleep(0.005)
def Start(serverIP, UDPORT):
global sock
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server = ( serverIP,UDPORT)
sock.bind(server)
_thread.start_new_thread(udp_thread, ())
# Launch server in another thread.
print("Launching UDP Server", serverIP,':', UDPORT)
Start(serverIP, UDPORT)
# Do something else
try:
while True:
time.sleep(0.005)
except Exception:
traceback.print_exc()
finally:
print("")
print("ljpd stopped.")

147
README.md
View File

@ -1,4 +1,4 @@
LJ v0.8.2 'fireandforget' LJ v0.8.2
By Sam Neurohack, Loloster, Cocoa By Sam Neurohack, Loloster, Cocoa
@ -7,104 +7,19 @@ LICENCE : CC BY
![LJ](https://www.teamlaser.fr/lj/images/lj2.png) ![LJ](https://www.teamlaser.fr/lj/images/lj2.png)
LJ is like a video projector where you fire images and forget. Lasers are dangerous : you can really fire real world objects. That's why you really shouldn't forget your lasers and go drink a beer. A software laser framework with GUI, for up to 4 lasers live actions with ethedreams DACs. Think creative like Laser "battles", planetarium, sharing available lasers in demoparties for competition, ...
As content creator, it's damn easy to send frames : LJ do the heavy lifting for up to 4 lasers live actions. Think creative like games, Laser "battles", planetarium, sharing available lasers in demoparties for competition,...
LJ has 5 main components : LJ has 5 main components :
- Frame *generators* to one or more lasers. Generators can be program "plugins" managed by LJ or you can feed the "connectors" directly. Remember with laser : *one frame = one polyline*, like in LOGO. - "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 "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 point lists to draw, new geometry correction,...), handle IOs (webui functions, OSC commands,...) and plugins. - 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. *Yes, there is a builtin simulator* so you can create without actual lasers. This UI can be used in a tablet, computer, whatever. You can open www directory and load html files. To not mess with user computer, it's "bring your own webserver". - A web GUI in html, css, and vanilla js. This UI can be used in a tablet, computer, whatever. LJ does not come with an html server but absolutely can . This GUI has a (currently slow) simulator, but one can also use an etherdream/laser emulator (see nannou simulator below) to work without physical lasers !!
- Frame *connectors* for pointlists, if you don't want to talk directly to the network available database (redis). Each "tracer" is instructed to get one of the avalaible pointlist in redis. - A network available database (redis). "Plugins" can send directly their pointlists to redis. Each "tracer" is instructed to get one of the avalaible pointlist in redis.
"Frames connectors" are :
- OSC (port 8002)
- Websocket (port 9001)
- Redis keys (one key per laser)
All derivatives you can think of like :
- Clitools is very powerfull : tunnel -> kaleidoscop -> color cycler -> redis connector.
- PureData (wip via UDP)
- Netlogo (text outputs are piped to clitools)
- ...
#
# Scenes and pointlists.
#
![Scenes](https://www.teamlaser.fr/lj/images/scenes.png)
LJ accept up to 4 groups = virtual "scenes" of 4 "pointlists" each (= one pointlist per laser), so up to 16 pointlists can be sent to redis at anytime from anywhere in the network. The idea behind this is to easily share actual lasers. Imagine in demo party :
Erica needs 4 lasers, that's the 4 pointlists of "scene" 0.
Paula and Jennifer use only 2 lasers each, so they can share "scene" 1.
And so on..
To change current scene used by lasers/tracers use the command : /scene/scenenumber/start 1
#
# How talk to frames connectors
#
One "frame" must be formated like /pl/scenenumber/lasernumber pointlist.
Example :
/pl/0/0 "[(150.0, 230.0, 65280), (170.0, 170.0, 65280), (230.0, 170.0, 65280), (210.0, 230.0, 65280), (150.0, 230.0, 65280)]"
Use the same syntax if you send your pointlist directly in redis : "/pl/0/0" is the key and keyvalue is "[(150.0,..."
Every point must be : (x,y,color). Color is the hex color #FFFFFF in decimal.
You can't specify an output framerate. It depends on your pointlist and laser mirrors scanners :
- if you draw a simple + single object like a oneline you'll get thousands fps.
- Longer pointlists are longer to draw by laser mirrors.
Inside "clitools" every point is [x,y,color]
See command reference for extensive documentation, but /pl is the only one you need to draw something. The webUI is here to masquerade all these commands.
#
# Requirements
#
Computer :
- 4 threads+ processor
- RAM 4 Go
- Gigabit *ethernet*
Laser(s) :
- ILDA capable
- DAC : Etherdream
Web User Interface :
- any computer, phone, tablet,...
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 and use a dedicated computer to run seperately main program from plugins, youtube,...
Important : for best performance LJ is meant to run in a dedicated computer especially with multiple lasers and highly multitasked load : if you watch video, use live webcam face recognition, webui simulator,... and run LJ on the same computer, well you need a bunch of cores. If you don't, spread the load : you can use webui on a tablet, the livecam on a phone, run pointlists generators on another computer,... Important : for best performance LJ is meant to run in a dedicated computer especially with multiple lasers and highly multitasked load : if you watch video, use live webcam face recognition, webui simulator,... and run LJ on the same computer, well you need a bunch of cores. If you don't, spread the load : you can use webui on a tablet, the livecam on a phone, run pointlists generators on another computer,...
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 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.
LJ is tested with Firefox, supports Linux and OS X. Windows is unkown but welcome, if someone want to jump in.
# #
# Features among many others. # Features among many others.
# #
@ -126,6 +41,33 @@ LJ is tested with Firefox, supports Linux and OS X. Windows is unkown but welcom
- Plugins list auto start, see line in LJ.conf : autostart = artnet - Plugins list auto start, see line in LJ.conf : autostart = artnet
- user.py plugin code example - user.py plugin code example
#
# Scenes and pointlists.
#
![Scenes](https://www.teamlaser.fr/lj/images/scenes.png)
LJ accept up to 4 groups = virtual "scenes" of 4 "pointlists" each (= one pointlist per laser), so up to 16 pointlists can be sent to redis at anytime from anywhere in the network. The idea behind this is to easily share actual lasers. Imagine in demo party :
Erica needs 4 lasers, that's the 4 pointlists of "scene" 0.
Paula and Jennifer use only 2 lasers each, so they can share "scene" 1.
And so on..
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 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.
To change current scene used by lasers/tracers use the command : /scene/scenenumber/start 1
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 and use a dedicated computer to run seperately main program from plugins, youtube,...
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.
# #
@ -151,8 +93,7 @@ type all install.sh commands beginning line 4. An OS X install script soon !!
- KVM : - KVM :
an ISO is available here : https://www.tmplab.org/wp-content/lazer-iso.zip an ISO is available here : https://www.tmplab.org/wp-content/lazer-iso.zip
- Postinstall for all :
## Postinstall for all :
You probably want redis bound to all network interfaces : comment the bind line in /etc/redis/redis.conf and restart it. You probably want redis bound to all network interfaces : comment the bind line in /etc/redis/redis.conf and restart it.
@ -220,8 +161,6 @@ node nodeclient.js
redis-cli -h redisserverIP monitor redis-cli -h redisserverIP monitor
# #
# Plugin # Plugin
# #
@ -323,7 +262,7 @@ DrawDests() will take care of all your declared drawn elements/"objects" and Des
2 compiled nannou visualisers are included, one for Linux, one for macOS. It's pretty old version but much more compatible with "old" processors/computer. 2 compiled nannou visualisers are included, one for Linux, one for macOS. It's pretty old version but much more compatible with "old" processors/computer.
To use this visualiser as one of LJ's lasers, use configure.py to set one laser to the IP of the computer running the visualiser. Relaunch LJ. One visualiser per computer. To use this visualiser as one of LJ's lasers, in LJ.conf edit one of line ip = someipaddress with the IP of the computer running the visualiser. Relaunch LJ. One visualiser per computer.
# #
# Todo # Todo
@ -341,8 +280,6 @@ To use this visualiser as one of LJ's lasers, use configure.py to set one laser
# #
You need to update LJ to your network/etherdreams IPs. Be sure to check command arguments : python3 configure.py
LJ is network based and this is *critical and flickering reason #1* if not managed properly, especially if you have several lasers. LJ is network based and this is *critical and flickering reason #1* if not managed properly, especially if you have several lasers.
Our "always working solution", as we regularly move our gear for different venues : Our "always working solution", as we regularly move our gear for different venues :
@ -362,6 +299,8 @@ By default LJ uses on 127.0.0.1 (localhost) :
- Some OSC clients defined in LJ.conf to forward commands to defined plugins. - Some OSC clients defined in LJ.conf to forward commands to defined plugins.
You need to update LJ.conf to your network/etherdreams IPs and be sure to check command arguments : python3 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 idea 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,...
# #
@ -381,7 +320,7 @@ For glitching experience you can change resampling strategy live with "resampler
# Colors # Colors
# #
LJ is compatible with TLL and analog modulation. Each point color is an int value, wich is simply the hex color in decimal. Example : white = #fffff = 16777215 LJ is compatible with TLL and analog modulation. Each point color is an int value, wich is simply the hex color in decimal. Example : white = #fffff = 65535.
# #
# Ether dream DAC # Ether dream DAC
@ -445,9 +384,7 @@ python3 talk3.py -i etherdreamIP
- Switch to simu page. If you don't see anything : check redis server or your points in redis doesn't respect pointlist formatting (see command reference). - Switch to simu page. If you don't see anything : check redis server or your points in redis doesn't respect pointlist formatting (see command reference).
- Check Leds : for each IRL lasers the two sets of must be green at startup and laser should display their number or the pointlist you want. - If talk3 works but you don't see your points : click on the Grid icon in Align page. This will override your pointlist and display squares. If Grid works : recomputed points by tracers are "bad" with given values in LJ.conf.
- If talk3 works but you don't see your points : click on the Grid icon in Align page. This will override your pointlist and display squares. If Grid works : recomputed points by tracers are "bad" with given values in LJ.conf.
"Bad points" ? "Bad points" ?
@ -457,7 +394,7 @@ python3 talk3.py -i etherdreamIP
*Don't kill your scanners : becareful with kpps setting.* *Don't kill your scanners : becareful with kpps setting.*
The reset button copy the LJ_template.conf to LJ.conf.
# #
# LJ commands reference # LJ commands reference
@ -507,6 +444,8 @@ lsteps is a string like "[ (1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)]"
/scene/scenenumber/start 0 or 1 : tell all tracers to use given scene /scene/scenenumber/start 0 or 1 : tell all tracers to use given scene
/regen : regen webui index html page.
/scim : change webui simulated laser. /scim : change webui simulated laser.

8
clitools/exports/toRedis.py Normal file → Executable file
View File

@ -8,11 +8,11 @@
redis exporter redis exporter
v0.1.0 v0.1.0
A basic exporter A basic exporter
LICENCE : CC LICENCE : CC
by cocoa by cocoa
''' '''
@ -21,7 +21,7 @@ import sys
import os import os
import argparse import argparse
import redis import redis
import time import time
argsparser = argparse.ArgumentParser(description="Redis exporter LJ") argsparser = argparse.ArgumentParser(description="Redis exporter LJ")
argsparser.add_argument("-i","--ip",help="IP address of the Redis server ",default="127.0.0.1",type=str) argsparser.add_argument("-i","--ip",help="IP address of the Redis server ",default="127.0.0.1",type=str)
@ -47,14 +47,12 @@ try:
line = sys.stdin.readline() line = sys.stdin.readline()
if line == "": if line == "":
time.sleep(0.01) time.sleep(0.01)
continue
line = line.rstrip('\n') line = line.rstrip('\n')
line=line[1:-1] line=line[1:-1]
line = line.replace("[",'(') line = line.replace("[",'(')
line = line.replace("]",')') line = line.replace("]",')')
line = "[{}]".format(line) line = "[{}]".format(line)
if line == "[]": if line == "[]":
line="[(400.0,400.0,0),(400.0,400.0,0),(400.0,400.0,0),(400.0,400.0,0)]"
continue continue
if r.set(key,line)==True: if r.set(key,line)==True:
debug("exports::redis set("+str(key)+") to "+line) debug("exports::redis set("+str(key)+") to "+line)

View File

@ -1,84 +0,0 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# -*- mode: Python -*-
'''
toUDP
v0.1.0
A basic exporter
LICENCE : CC
by cocoa
'''
from __future__ import print_function
import sys
import os
import argparse
import time
import socket
import ast
argsparser = argparse.ArgumentParser(description="toUDP v0.1b help mode")
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
argsparser.add_argument("-i","--ip",help="IP to bind to (0.0.0.0 by default)",default="0.0.0.0",type=str)
argsparser.add_argument("-p","--port",help="UDP port to bind to (9000 by default)",default="9003",type=str)
args = argsparser.parse_args()
verbose = args.verbose
ip = args.ip
port = int(args.port)
verbose = args.verbose
name = "exports::toUDP"
def debug(*args, **kwargs):
if( verbose == False ):
return
print(*args, file=sys.stderr, **kwargs)
def ClientStart(ip, port):
global sockclient
sockclient = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
def ClientSend(msgFromClient):
bytesToSend = str.encode(str(msgFromClient))
serverAddressPort = (ip, port)
bufferSize = 1024
# Send to server using created UDP socket
sockclient.sendto(bytesToSend, serverAddressPort)
'''
# If reply :
msgFromServer = sockclient.recvfrom(bufferSize)
msg = "Message from Server {}".format(msgFromServer[0])
print(msg)
'''
try:
ClientStart(ip, port)
while True:
line = sys.stdin.readline()
if line == "":
time.sleep(0.01)
line = line.rstrip('\n')
#pointsList = ast.literal_eval(line)
debug(name,": "+line)
ClientSend(line)
except EOFError:
debug("break")# no more information

View File

@ -66,9 +66,9 @@ red = (41,24,24)
white = (95,95,95) white = (95,95,95)
blue = (0,41,64) blue = (0,41,64)
red = (127,0,0) red = (255,0,0)
blue = (0,128,128) blue = (0,255,255)
white = (128,128,128) white = (255,255,255)
def anaglyph( pl ): def anaglyph( pl ):
debug(name,'--------------- new loop ------------------') debug(name,'--------------- new loop ------------------')
@ -174,6 +174,7 @@ def anaglyph( pl ):
debug(name,"whiteList:{}".format(out1)) debug(name,"whiteList:{}".format(out1))
debug(name,"blueList:{}".format(out2)) debug(name,"blueList:{}".format(out2))
debug(name,"redList:{}".format(out3)) debug(name,"redList:{}".format(out3))
return out3 + out2
return out1 + out3 + out2 return out1 + out3 + out2
#return out1 + out2 + out3 #return out1 + out2 + out3

View File

@ -72,8 +72,7 @@ def cycleColor( pl ):
debug(name,"currentColor:{}".format(currentColor)) debug(name,"currentColor:{}".format(currentColor))
for i in range( 0, len(pl)): for i in range( 0, len(pl)):
if pl[i][2] != 0: pl[i][2] = rgb2int( currentColor)
pl[i][2] = rgb2int( currentColor)
# change the composant if target reached # change the composant if target reached
if value <= target and currentDirection == DOWN or value >= target and currentDirection == UP : if value <= target and currentDirection == DOWN or value >= target and currentDirection == UP :

View File

@ -162,7 +162,7 @@ try:
pointsList = ast.literal_eval(line) pointsList = ast.literal_eval(line)
# Do the filter # Do the filter
result = kaleidoscope( pointsList ) result = kaleidoscope( pointsList )
if len(result) : print( result, flush=True ) print( result, flush=True )
looptime = time.time() - start looptime = time.time() - start
# debug(name+" looptime:"+str(looptime)) # debug(name+" looptime:"+str(looptime))
if( looptime < optimal_looptime ): if( looptime < optimal_looptime ):

View File

@ -1,188 +0,0 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# -*- mode: Python -*-
'''
redilysis colors
v0.1.0
A complex effect that depends on redis keys for audio analysis
see https://git.interhacker.space/teamlase/redilysis for more informations
about the redilysis project
LICENCE : CC
by cocoa
'''
from __future__ import print_function
import argparse
import ast
import os
import math
import random
import redis
import sys
import time
name = "filters::redilysis_colors"
def debug(*args, **kwargs):
if( verbose == False ):
return
print(*args, file=sys.stderr, **kwargs)
def msNow():
return time.time()
# The list of available modes => redis keys each requires to run
oModeList = {
}
def rgb2int(rgb):
return int('0x%02x%02x%02x' % tuple(rgb),0)
def int2rgb(intcode):
#hexcode = hex(intcode)[2:]
hexcode = '{0:06X}'.format(intcode)
return tuple(int(hexcode[i:i+2], 16) for i in (0, 2, 4))
#return tuple(map(ord,hexcode[1:].decode('hex')))
CHAOS = 1
REDIS_FREQ = 100
# General Args
argsparser = argparse.ArgumentParser(description="Redilysis filter")
argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int)
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose")
# Redis Args
argsparser.add_argument("-i","--ip",help="IP address of the Redis server ",default="127.0.0.1",type=str)
argsparser.add_argument("-p","--port",help="Port of the Redis server ",default="6379",type=str)
argsparser.add_argument("-s","--redis-freq",help="Query Redis every x (in milliseconds). Default:{}".format(REDIS_FREQ),default=REDIS_FREQ,type=int)
# Modes And Common Modes Parameters
#argsparser.add_argument("-m","--modelist",required=False,help="Comma separated list of modes to use from: {}".format("i, ".join(oModeList.keys())),type=str)
argsparser.add_argument("-c","--chaos",help="How much disorder to bring. High value = More chaos. Default {}".format(CHAOS), default=CHAOS, type=float)
args = argsparser.parse_args()
fps = args.fps
ip = args.ip
port = args.port
redisFreq = args.redis_freq / 1000
verbose = args.verbose
chaos = float(args.chaos)
optimal_looptime = 1 / fps
max_width = 800
max_height = 800
redisKeys = ["rms","spectrum_10","spectrum_120"]
debug(name,"Redis Keys:{}".format(redisKeys))
redisData = {}
redisLastHit = msNow() - 99999
r = redis.Redis(
host=ip,
port=port)
def refreshRedis():
global redisData
for key in redisKeys:
try:
redisData[key] = ast.literal_eval(r.get(key).decode('ascii'))
except :
debug("Error when reading redis key '{}".format(key))
def gauss(x, mu, sigma):
return( math.exp(-math.pow((x-mu),2)/(2*math.pow(sigma,2))/math.sqrt(2*math.pi*math.pow(sigma,2))))
spect10Correct = [
6.0,
1.5,
1.0,
1.0,
1.0,
1.0,
1.0,
0.8,
0.6,
0.5,
]
def default( pl ):
global redisData
spect = redisData["spectrum_10"]
debug(name, "spect:{}".format(spect))
new_list = []
# We want to color points that are on left and right when high is strong
# i.e. the farther the distance from spectrum, the higher notes have influence
# power = 0-1
# x = 800 spec[2]= 6.0 spec[7]=0.0 power=0.0
# x = 0 spec[2]= 6.0 spec[7]=0.0 power=0.0
# x = 0 spec[2]= 1.0 spec[7]=0.5 power=1.0
# dist 0 = 1
# 400 - 400 : maxW/2 -x
# 399 = -1 : x - 400
# 401 = 1
# x = 400 spec[2]= 6.0 spec[7]=0.0 power=1.0
# x = 400 spec[2]= 1.0 spec[7]=0.5 power=0.0
for i, point in enumerate(pl):
ocolor = pl[i][2]
if ocolor == 0 :
new_list.append(point)
continue
colorTuple = int2rgb(ocolor)
x = point[0]
dist = abs(x - max_width/2)
key = int(2* dist / max_width * 7)
try:
power = spect[key] / spect10Correct[key] * chaos
except:
pass
color = []
for i in colorTuple:
new_color = int(i * power)
if new_color > 255 :
new_color = 255
if new_color < 0 :
new_color = 0
color.append( new_color )
color = rgb2int(tuple(color))
point[2] = color
new_list.append(point)
#debug(name,"x:{}\t dist:{}\t key:{}\t power:{}\t ocolor:{}\t color:{}".format(point[0], dist, key,power, ocolor, pl[i][2]))
debug( name,"rms_noise output:{}".format(new_list))
return new_list
try:
while True:
refreshRedis()
start = time.time()
line = sys.stdin.readline()
if line == "":
time.sleep(0.01)
line = line.rstrip('\n')
pointsList = ast.literal_eval(line)
# Do the filter
pointsList = default(pointsList)
print( pointsList, flush=True )
looptime = time.time() - start
# debug(name+" looptime:"+str(looptime))
if( looptime < optimal_looptime ):
time.sleep( optimal_looptime - looptime)
# debug(name+" micro sleep:"+str( optimal_looptime - looptime))
except EOFError:
debug(name+" break")# no more information

File diff suppressed because it is too large Load Diff

View File

@ -1,53 +0,0 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# -*- mode: Python -*-
'''
Send only black points
v0.1.0
Use it to test your filters and outputs
LICENCE : CC
by cocoa
'''
from __future__ import print_function
import time
import argparse
import sys
name="generator::dummy"
def debug(*args, **kwargs):
if( verbose == False ):
return
print(*args, file=sys.stderr, **kwargs)
argsparser = argparse.ArgumentParser(description="dummy generator")
argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int)
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
args = argsparser.parse_args()
fps=args.fps
verbose=args.verbose
optimal_looptime = 1 / fps
debug(name+" optimal looptime "+str(optimal_looptime))
shape = [[400,400,0],[400,400,64],[400,400,0]]
while True:
start = time.time()
print(shape, flush=True);
looptime = time.time() - start
if( looptime < optimal_looptime ):
time.sleep( optimal_looptime - looptime)
debug(name+" micro sleep:"+str( optimal_looptime - looptime))

View File

@ -5,7 +5,7 @@
''' '''
This generator print different angle form 0 to 180 degres This generator print different engle form 0 to 180 degres
v0.1.0 v0.1.0
@ -43,13 +43,11 @@ debug(name+" optimal looptime "+str(optimal_looptime))
width = 800 width = 800
height = 800 height = 800
white = 0xFFFFFF white = 0xFFFF
blank = 0 blank = 0
radius = 100 radius = 70
offset_circles = 10 offset_circles = 12
beg_angle = 0
end_angle = 90
offset_angle = 10 offset_angle = 10
angles_lines = [] angles_lines = []
@ -60,7 +58,7 @@ def set_angles_lines():
spacing_betwen = 2 * radius + offset_circles spacing_betwen = 2 * radius + offset_circles
circles_per_line = math.floor((width - margin) / spacing_betwen) circles_per_line = math.floor((width - margin) / spacing_betwen)
for ang in range(beg_angle, end_angle + offset_angle, offset_angle): for ang in range(0, 180 + offset_angle, offset_angle):
nb = int(ang / offset_angle) nb = int(ang / offset_angle)
cx = margin + (nb % circles_per_line) * spacing_betwen cx = margin + (nb % circles_per_line) * spacing_betwen
cy = margin + int(nb / circles_per_line) * spacing_betwen cy = margin + int(nb / circles_per_line) * spacing_betwen
@ -69,18 +67,16 @@ def set_angles_lines():
py = radius * math.sin(math.radians(ang)) py = radius * math.sin(math.radians(ang))
# line up # line up
angles_lines.append([-px + cx, py + cy, blank])
angles_lines.append([-px + cx, py + cy, white]) angles_lines.append([-px + cx, py + cy, white])
angles_lines.append([ cx, 2 + cy, white]) angles_lines.append([ cx, cy, white])
angles_lines.append([ px + cx, py + cy, white]) angles_lines.append([ px + cx, py + cy, white])
#angles_lines.append([ px + cx, py + cy, blank]) angles_lines.append([ px + cx, py + cy, blank])
# line down # line down
angles_lines.append([-px + cx, -py + cy, blank])
angles_lines.append([-px + cx, -py + cy, white]) angles_lines.append([-px + cx, -py + cy, white])
angles_lines.append([ cx, -2 + cy, white]) angles_lines.append([ cx, cy, white])
angles_lines.append([ px + cx, -py + cy, white]) angles_lines.append([ px + cx, -py + cy, white])
#angles_lines.append([ px + cx, -py + cy, blank]) angles_lines.append([ px + cx, -py + cy, blank])
set_angles_lines() set_angles_lines()

View File

@ -1,117 +0,0 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# -*- mode: Python -*-
'''
This generator print a shape with 3 discinected component, 2 non eulerian and one eulerian.
v0.1.0
LICENCE : CC
by lapin (aka nipal)
'''
from __future__ import print_function
import time
import argparse
import sys
import math
name="generator::endingPoint"
def debug(*args, **kwargs):
if( verbose == False ):
return
print(*args, file=sys.stderr, **kwargs)
def debug2(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
argsparser = argparse.ArgumentParser(description="dummy generator")
argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int)
argsparser.add_argument("-s","--speed",help="point per frame progress",default=3,type=int)
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
args = argsparser.parse_args()
fps=args.fps
verbose=args.verbose
optimal_looptime = 1 / fps
debug(name+" optimal looptime "+str(optimal_looptime))
width = 800
height = 800
white = 0xFFFFFF
blank = 0
def shape_scale(shape, scale_factor):
new_shape = []
for p in shape:
new_shape.append([p[0] * scale_factor, p[1] * scale_factor, p[2]])
return new_shape
def shape_incr(shape, x, y):
new_shape = []
for p in shape:
new_shape.append([p[0] + x, p[1] + y, p[2]])
return new_shape
comp_a = []
comp_b = []
comp_c = []
comp_b.append([ 0, 3, blank])
comp_b.append([ 0, 4, white])
comp_b.append([ 0, 0, white])
comp_b.append([ 3, 0, white])
comp_b.append([ 3, 6, white])
comp_b.append([ 3, 6, white])
comp_b.append([ 3, 0, white])
comp_b.append([ 3, 0, blank])
comp_b.append([ 3, 0, white])
comp_b.append([ 5, 4, white])
comp_b.append([ 5, 4, blank])
comp_a.append([ 5, 17, blank])
comp_a.append([ 5, 17, white])
comp_a.append([ 0, 5, white])
comp_a.append([12, 0, white])
comp_a.append([17, 12, white])
comp_a.append([ 5, 17, white])
comp_a.append([ 5, 17, blank])
comp_c.append([-3, 5, blank])
comp_c.append([-3, 5, white])
comp_c.append([ 0, 4, white])
comp_c.append([ 0, 0, white])
comp_c.append([ 4, 0, white])
comp_c.append([ 4, 4, white])
comp_c.append([ 7, 5, white])
comp_c.append([ 7, 5, blank])
comp_a = shape_scale(comp_a, 11)
comp_a = shape_incr(comp_a, 300, 75)
comp_b = shape_scale(comp_b, 45)
comp_b = shape_incr(comp_b, 0, 300)
comp_c = shape_scale(comp_c, 30)
comp_c = shape_incr(comp_c, 600, 300)
shape = comp_a + comp_b + comp_c
while True:
start = time.time()
print(shape, flush=True);
looptime = time.time() - start
if( looptime < optimal_looptime ):
time.sleep( optimal_looptime - looptime)
debug(name+" micro sleep:"+str( optimal_looptime - looptime))

View File

@ -1,84 +0,0 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# -*- mode: Python -*-
'''
This generator print a shape with best angle representation when the path is redraw
v0.1.0
LICENCE : CC
by lapin (aka nipal)
'''
from __future__ import print_function
import time
import argparse
import sys
import math
name="generator::endingPoint"
def debug(*args, **kwargs):
if( verbose == False ):
return
print(*args, file=sys.stderr, **kwargs)
def debug2(*args, **kwargs):
print(*args, file=sys.stderr, **kwargs)
argsparser = argparse.ArgumentParser(description="dummy generator")
argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int)
argsparser.add_argument("-s","--speed",help="point per frame progress",default=3,type=int)
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
args = argsparser.parse_args()
fps=args.fps
verbose=args.verbose
optimal_looptime = 1 / fps
debug(name+" optimal looptime "+str(optimal_looptime))
width = 800
height = 800
white = 0xFFFFFF
blank = 0
point_offset = 250
point_width = 4
point_list = [
[8,7,6,10,7,3,6,2,7,11,6,9],
[5,6,1,],
[4,7,12,],
]
shape = []
# on ajoute des lilste de point
for l in point_list:
x = point_offset * ((l[0] - 1) % (point_width))
y = point_offset * int((l[0] - 1) / (point_width))
shape.append([x, y, blank])
debug2("=====")
debug2(f"id: {l[0]}\tx: {x}\ty: {y}\t\tpoint_width: {point_width}\t\n")
for p in l:
x = point_offset * ((p - 1) % (point_width))
y = point_offset * int((p - 1) / (point_width))
shape.append([x, y, white])
debug2(f"id: {p}\tx: {x}\ty: {y}\t\tpoint_width: {point_width}\t\n")
while True:
start = time.time()
print(shape, flush=True);
looptime = time.time() - start
if( looptime < optimal_looptime ):
time.sleep( optimal_looptime - looptime)
debug(name+" micro sleep:"+str( optimal_looptime - looptime))

View File

@ -12,7 +12,7 @@ Use it to test your filters and outputs
LICENCE : CC LICENCE : CC
by cocoa by cocoa
''' '''
@ -28,17 +28,17 @@ def debug(*args, **kwargs):
return return
print(*args, file=sys.stderr, **kwargs) print(*args, file=sys.stderr, **kwargs)
argsparser = argparse.ArgumentParser(description="dummy generator")
argsparser = argparse.ArgumentParser(description="Dummy generator")
argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int) argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int)
argsparser.add_argument("-s","--speed",help="point per frame progress",default=3,type=int)
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output") argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
args = argsparser.parse_args() args = argsparser.parse_args()
fps=args.fps fps=args.fps
verbose=args.verbose verbose=args.verbose
optimal_looptime = 1 / fps optimal_looptime = 1 / fps
debug(name+" optimal looptime "+str(optimal_looptime)) debug(name+" optimal looptime "+str(optimal_looptime))
color = 16777215 color = 65280
square = [[100.0, 100.0, color], [100.0, 500.0, color], [500.0, 500.0, color], [500.0, 100.0, color], [100.0, 100.0, color]] square = [[100.0, 100.0, color], [100.0, 500.0, color], [500.0, 500.0, color], [500.0, 100.0, color], [100.0, 100.0, color]]
line =[] line =[]
for i in range(00,800,int(800/120)): for i in range(00,800,int(800/120)):
@ -71,7 +71,7 @@ mire = [
[400,450,color], [400,450,color],
] ]
shape = mire shape = mire
while True: while True:
@ -81,5 +81,5 @@ while True:
if( looptime < optimal_looptime ): if( looptime < optimal_looptime ):
time.sleep( optimal_looptime - looptime) time.sleep( optimal_looptime - looptime)
debug(name+" micro sleep:"+str( optimal_looptime - looptime)) debug(name+" micro sleep:"+str( optimal_looptime - looptime))

View File

@ -1,126 +0,0 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# -*- mode: Python -*-
'''
Forward /pl pointlist to cli
input OSC in END points format : (x,y,color)
output CLI in CLI points format : [x,y,color]
/pl "[(150.0, 230.0, 255), (170.0, 170.0, 255), (230.0, 170.0, 255), (210.0, 230.0, 255), (150.0, 230.0, 255)]"
v0.1.0
LICENCE : CC
by Cocoa, Sam Neurohack
'''
from __future__ import print_function
from OSC3 import OSCServer, OSCClient, OSCMessage
import sys
from time import sleep
import argparse
import ast
argsparser = argparse.ArgumentParser(description="fromOSC generator")
argsparser.add_argument("-i","--ip",help="IP to bind to (0.0.0.0 by default)",default="0.0.0.0",type=str)
argsparser.add_argument("-p","--port",help="OSC port to bind to (9002 by default)",default=9002,type=str)
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
args = argsparser.parse_args()
verbose = args.verbose
ip = args.ip
port = int(args.port)
def debug(*args, **kwargs):
if( verbose == False ):
return
print(*args, file=sys.stderr, **kwargs)
oscserver = OSCServer( (ip, port) )
oscserver.timeout = 0
run = 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 OSC_frame():
# clear timed_out flag
oscserver.timed_out = False
# handle all pending requests then return
while not oscserver.timed_out:
oscserver.handle_request()
# default handler
def OSChandler(oscpath, tags, args, source):
oscaddress = ''.join(oscpath.split("/"))
debug("fromOSC Default OSC Handler got oscpath", oscpath, "from" + str(source[0]), ":", args)
#print("OSC address", path)
#print("find.. /bhoreal ?", path.find('/bhoreal'))
if oscpath == "/pl" and len(args)==1:
debug("correct OSC type :'/pl")
if validate(args[0]) == True:
debug("new pl : ", args[0])
line = args[0].replace("(",'[')
line = line.replace(")",']')
line = "[{}]".format(line)
print(line, flush=True);
else:
debug("Bad pointlist -> msg trapped.")
else:
debug("BAD OSC Message : " + oscpath +" " +args[0])
oscserver.addMsgHandler( "default", OSChandler )
def validate(pointlist):
state = True
if len(pointlist)<9:
debug("Not enough characters :", pointlist)
state = False
if pointlist.find("(") == -1:
debug("Bad format : use () not [] for points", pointlist)
state = False
try:
pl = bytes(pointlist, 'ascii')
check = ast.literal_eval(pl.decode('ascii'))
except:
debug("BAD POINTLIST :", pointlist)
state = False
return state
# simulate a "game engine"
while run:
# do the game stuff:
sleep(0.01)
# call user script
OSC_frame()
oscserver.close()

View File

@ -1,72 +0,0 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# -*- mode: Python -*-
'''
This generator reads a frame from redis
v0.1.0
Use it to create feedback loops by writing to the same frame
or to copy the frame from someone else
LICENCE : CC
by cocoa
'''
from __future__ import print_function
import ast
import argparse
import json
import redis
import sys
import time
name="generator::fromRedis"
def debug(*args, **kwargs):
if( verbose == False ):
return
print(*args, file=sys.stderr, **kwargs)
argsparser = argparse.ArgumentParser(description="Dummy generator")
argsparser.add_argument("-k","--key",required=True,help="Redis key to look after",default=30,type=str)
argsparser.add_argument("-i","--ip",help="IP address of the Redis server ",default="127.0.0.1",type=str)
argsparser.add_argument("-p","--port",help="Port of the Redis server ",default="6379",type=str)
argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int)
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
args = argsparser.parse_args()
fps = args.fps
verbose = args.verbose
key = args.key
ip = args.ip
port = args.port
optimal_looptime = 1 / fps
debug(name+" optimal looptime "+str(optimal_looptime))
r = redis.Redis(
host=ip,
port=port)
while True:
start = time.time()
# Read from Redis
line = r.get(key)
# Decode as list of tuples
pointsList = ast.literal_eval(line.decode('ascii'))
# convert to list of lists
pointsList = [list(elem) for elem in pointsList]
# Convert to JSON string
line = json.dumps( pointsList )
debug(name,"Key:{} line:{}".format(key,line))
print(line, flush=True);
looptime = time.time() - start
if( looptime < optimal_looptime ):
time.sleep( optimal_looptime - looptime)
debug(name+" micro sleep:"+str( optimal_looptime - looptime))

View File

@ -1,84 +0,0 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# -*- mode: Python -*-
'''
fromUDP
Udp server to cli
v0.1b
'''
from __future__ import print_function
import traceback, time
import argparse
import socket
import _thread
import sys
name="generator::fromUDP"
def debug(*args, **kwargs):
if( verbose == False ):
return
print(*args, file=sys.stderr, **kwargs)
argsparser = argparse.ArgumentParser(description="fromUDP v0.1b help mode")
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
argsparser.add_argument("-i","--ip",help="IP to bind to (0.0.0.0 by default)",default="0.0.0.0",type=str)
argsparser.add_argument("-p","--port",help="UDP port to bind to (9000 by default)",default=9000,type=str)
args = argsparser.parse_args()
verbose = args.verbose
ip = args.ip
port = int(args.port)
verbose = args.verbose
def udp_thread():
while True:
payload, client_address = sock.recvfrom(1024)
udpath = payload.decode('utf_8')
debug(udpath[0:])
print(udpath[0:], flush=True);
'''
# Reply to client
bytesToSend = str.encode("ACK :"+str(payload))
serverAddressPort = (client_address, port)
bufferSize = 1024
#sock.sendto(bytesToSend, serverAddressPort)
sock.sendto(bytesToSend, client_address)
'''
def StartUDP(serverIP, UDPORT):
global sock
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
server = ( serverIP,UDPORT)
sock.bind(server)
_thread.start_new_thread(udp_thread, ())
StartUDP(ip, port)
# Do something else
try:
while True:
time.sleep(0.005)
except Exception:
traceback.print_exc()

View File

@ -1,288 +0,0 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# -*- mode: Python -*-
'''
v0.1.0
LICENCE : CC
by cocoa
'''
from __future__ import print_function
import math
import random
import sys
import os
import time
import redis
import ast
import argparse
MAX_PARTICLES = 50
MAX_TIME = 500
argsparser = argparse.ArgumentParser(description="Dummy generator")
argsparser.add_argument("-f","--fps",help="Frame Per Second",default=30,type=int)
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose output")
# Redis Args
argsparser.add_argument("-i","--ip",help="IP address of the Redis server ",default="127.0.0.1",type=str)
argsparser.add_argument("-p","--port",help="Port of the Redis server ",default="6379",type=str)
#
argsparser.add_argument("-M","--max-particles",help="Max Particles. Default:{}".format(MAX_PARTICLES),default=MAX_PARTICLES,type=int)
argsparser.add_argument("-m","--max-time",help="Max Particles. Default:{}".format(MAX_TIME),default=MAX_TIME,type=int)
args = argsparser.parse_args()
verbose = args.verbose
ip = args.ip
port = args.port
max_particles = args.max_particles
max_time = args.max_time
def debug(*args, **kwargs):
if( verbose == False ):
return
print(*args, file=sys.stderr, **kwargs)
def rgb2int(rgb):
#debug(name,"::rgb2int rbg:{}".format(rgb))
return int('0x%02x%02x%02x' % tuple(rgb),0)
def spectrum_120( ):
return ast.literal_eval(redisData["spectrum_10"])
def rgb2int(rgb):
#debug(name,"::rgb2int rbg:{}".format(rgb))
return int('0x%02x%02x%02x' % tuple(rgb),0)
def msNow():
return time.time()
def refreshRedis():
global redisData
for key in redisKeys:
redisData[key] = ast.literal_eval(r.get(key).decode('ascii'))
name="generator::redilisys_particles"
class UnpreparedParticle(Exception):
pass
class Particle(object):
def __init__(self, x, y, m):
self.x = x
self.y = y
self.m = m
self.dx = 0
self.dy = 0
self.connectedTo = []
self.decay = random.randint(10,max_time)
self.color = (random.randint(128,256) - int(12.8 * self.m),
random.randint(128,256) - int(12.8 * self.m),
random.randint(128,256) - int(12.8 * self.m))
self.color = (255,255,255)
#debug( self.color )
def interact(self, bodies):
self.connectedTo = []
spec = redisData["spectrum_10"]
power = int(sum(spec[4:6]))
for other in bodies:
if other is self:
continue
dx = other.x - self.x
dy = other.y - self.y
dist = math.sqrt(dx*dx + dy*dy)
if dist == 0:
dist = 1
if dist < 100 and random.randint(0,power) > 0.5 :
self.connectedTo.append(other)
self.decay += 2
factor = other.m / dist**2
high_power = sum(spec[8:9]) if sum(spec[8:9]) != 0 else 0.01
self.dx += (dx * factor * self.m)
self.dy += (dy * factor * self.m)
#print "factor %f" % (factor,)
def move(self):
spec = redisData["spectrum_10"]
x_friction = (2.2-(1+spec[7]/2))
y_friction = (2.2-(1+spec[7]/2))
#x_friction = 1.02
#y_friction = 1.04
self.dx /= x_friction if x_friction != 0 else 0.01
self.dy /= y_friction if y_friction != 0 else 0.01
self.x += self.dx
self.y += self.dy
if self.x > max_width:
self.dx = - self.dx /8
self.x = max_width
if self.x < 1:
self.dx = - self.dx /8
self.x = 1
if self.y > max_height:
self.dy = - self.dy /4
self.y = max_height
if self.y < 1:
self.dy = - self.dy /4
self.y = 1
#print "(%.2f,%.2f) -> (%.2f,%.2f)" % (ox, oy, self.x, self.y)
def attractor(self,attractor):
spec = redisData["spectrum_10"]
power = sum(spec[0:4])/3
# If we're going in the direction of center, reverse
next_x = self.x + self.dx
next_y = self.y + self.dy
next_dx = attractor["x"] - self.x
next_dy = attractor["y"] - self.y
next_dist = math.sqrt(next_dx*next_dx + next_dy*next_dy)
dx = attractor["x"] - self.x
dy = attractor["y"] - self.y
dist = math.sqrt(dx*dx + dy*dy)
if dist == 0:
dist = 1
factor = power/ dist**2
x_acceleration = (dx * factor * power * power)
y_acceleration = (dx * factor * power * power)
if next_dist > dist:
self.dx -= x_acceleration * power
self.dy -= y_acceleration * power
else:
self.dx += x_acceleration
self.dy += y_acceleration
class Attractor(Particle):
def move(self):
pass
class ParticleViewer(object):
def __init__(self, particles, size=(800,800)):
(self.width, self.height) = size
self.size = size
self.particles = particles
self.xoff = 0
self.yoff = 0
self.scalefactor = 1
def redraw(self):
pl = []
drawnVectors = []
for p in self.particles:
x = int(self.scalefactor * p.x) - self.xoff
y = int(self.scalefactor * p.y) - self.yoff
if x > max_width:
x = max_width
if x < 1:
x = 1
if y > max_height:
y = max_height
if y < 1:
y = 1
color = rgb2int(p.color)
pl.append([x+1,y+1,0])
pl.append([x+1,y+1,color])
pl.append([x,y,color])
for other in p.connectedTo:
if [other,self] in drawnVectors:
continue
drawnVectors.append([other,self])
pl.append([x,y,0])
pl.append([x,y,color])
pl.append([other.x,other.y,color])
print(pl,flush = True)
def decayParticles(self):
for i,p in enumerate(self.particles):
# Handle positional decay
if p.decay == 0:
del self.particles[i]
continue
p.decay = p.decay - 1
# Handle color decay
n = int(255 * (p.decay / max_time ))
p.color = (n,n,n)
def emitParticles(self):
spec = redisData["spectrum_10"]
power = sum(spec[6:])
if len(self.particles ) > math.sqrt(max_particles):
if len(self.particles) > max_particles:
return
if random.random() > power:
return
# x is either left or right
d = 600
rx = 100 if random.randint(0,1) else 700
#rx = random.randint(1,max_width)
ry = random.randint(1,max_height)
spec = redisData["spectrum_10"]
m = random.randint(1,1+int(10*spec[7]))
particles.append(Particle(rx, ry, m))
def tick(self):
self.decayParticles()
self.emitParticles()
for p in self.particles:
p.interact(self.particles)
p.attractor({
"x":max_width/2,
"y":max_height/2
})
for p in particles:
p.move()
self.redraw()
def scale(self, factor):
self.scalefactor += factor
max_width = 800
max_height = 800
redisKeys = ["spectrum_120","spectrum_10"]
redisData = {}
redisLastHit = msNow() - 99999
r = redis.Redis(
host=ip,
port=port)
white = 16777215
refreshRedis()
if __name__ == "__main__":
particles = []
# particles.append(Attractor(320, 200, 10))
# particles.append(Attractor(100, 100, 10))
win = ParticleViewer(particles)
try:
while True:
win.tick()
refreshRedis()
time.sleep(.03)
except KeyboardInterrupt:
pass

View File

@ -12,7 +12,7 @@ Use it to test your filters and outputs
LICENCE : CC LICENCE : CC
by cocoa by cocoa
''' '''
@ -52,7 +52,7 @@ randomize = args.randomize
speed = args.speed speed = args.speed
verbose = args.verbose verbose = args.verbose
origSpeed = speed origSpeed = speed
optimal_looptime = 1 / fps optimal_looptime = 1 / fps
square = [ square = [
[-1,1], [-1,1],
@ -62,32 +62,14 @@ square = [
[-1,1] [-1,1]
] ]
circle = [[1,0], shape = square
[0.9238795325112867,0.3826834323650898],
[0.7071067811865476,0.7071067811865475],
[0.38268343236508984,0.9238795325112867],
[0,1.0],
[-0.3826834323650897,0.9238795325112867],
[-0.7071067811865475,0.7071067811865476],
[-0.9238795325112867,0.3826834323650899],
[-1.0,0],
[-0.9238795325112868,-0.38268343236508967],
[-0.7071067811865477,-0.7071067811865475],
[-0.38268343236509034,-0.9238795325112865],
[0,-1.0],
[0.38268343236509,-0.9238795325112866],
[0.707106781186548,-0.707106781186547],
[0.9238795325112872,-0.3826834323650887],
[1,0]]
shape = circle
currentCenter = [centerX, centerY] currentCenter = [centerX, centerY]
centerVector= [0,0] centerVector= [0,0]
# tweak random basis # tweak random basis
if randomize % 2 == 1: if randomize % 2 == 1:
randomize += 1 randomize += 1
debug(name,"randomize:{}".format(randomize)) debug(name,"randomize:{}".format(randomize))
centerRand = int(math.sqrt(randomize) / 4 ) + 1 centerRand = int(math.sqrt(randomize) / 4 ) + 1
debug( name, "centerRand:{}".format(centerRand ) ) debug( name, "centerRand:{}".format(centerRand ) )
class polylineGenerator( object ): class polylineGenerator( object ):
@ -121,10 +103,10 @@ class polylineGenerator( object ):
min_size = 9999 min_size = 9999
delList = [] delList = []
if randomize : if randomize :
# Change the vector # Change the vector
centerVector[0] += random.randrange( -centerRand,centerRand ) centerVector[0] += random.randrange( -centerRand,centerRand )
centerVector[1] += random.randrange( -centerRand,centerRand ) centerVector[1] += random.randrange( -centerRand,centerRand )
# Modify the vector if it is over the limit # Modify the vector if it is over the limit
if currentCenter[0] + centerVector[0] >= centerX + randomize or currentCenter[0] + centerVector[0] <= centerX - randomize: if currentCenter[0] + centerVector[0] >= centerX + randomize or currentCenter[0] + centerVector[0] <= centerX - randomize:
centerVector[0] = 0 centerVector[0] = 0
if currentCenter[1] + centerVector[1] >= centerY + randomize or currentCenter[1] +centerVector[1] <= centerY - randomize: if currentCenter[1] + centerVector[1] >= centerY + randomize or currentCenter[1] +centerVector[1] <= centerY - randomize:
@ -133,19 +115,19 @@ class polylineGenerator( object ):
currentCenter[1] += centerVector[1] currentCenter[1] += centerVector[1]
# Change speed # Change speed
speed += int( random.randrange( int(-origSpeed),origSpeed ) ) speed += int( random.randrange( int(-origSpeed),origSpeed ) )
if speed < origSpeed : if speed < origSpeed :
speed = origSpeed speed = origSpeed
elif speed > (origSpeed + randomize / 2) : elif speed > (origSpeed + randomize / 2) :
speed = origSpeed + randomize / 2 speed = origSpeed + randomize / 2
#debug(name, "currentCenter:{} speed:{}".format(currentCenter,speed)) #debug(name, "currentCenter:{} speed:{}".format(currentCenter,speed))
for i, shapeInfo in enumerate(self.polylineList): for i, shapeInfo in enumerate(self.polylineList):
size = shapeInfo[0] size = shapeInfo[0]
# Augment speed with size # Augment speed with size
""" """
size = 0 : += sqrt(speed) size = 0 : += sqrt(speed)
size = half max size : +=speed size = half max size : +=speed
""" """
if size < max_size / 4: if size < max_size / 4:
size += math.pow(speed, 0.1) size += math.pow(speed, 0.1)
@ -161,7 +143,7 @@ class polylineGenerator( object ):
for i in delList: for i in delList:
del self.polylineList[i] del self.polylineList[i]
#debug(name, "polyline:",self.polylineList) #debug(name, "polyline:",self.polylineList)
if min_size >= interval: if min_size >= interval:
debug(name, "new shape") debug(name, "new shape")
self.polylineList.append([0,[currentCenter[0],currentCenter[1]]]) self.polylineList.append([0,[currentCenter[0],currentCenter[1]]])
@ -190,5 +172,5 @@ while True:
if( looptime < optimal_looptime ): if( looptime < optimal_looptime ):
time.sleep( optimal_looptime - looptime) time.sleep( optimal_looptime - looptime)
#debug(name+" micro sleep:"+str( optimal_looptime - looptime)) #debug(name+" micro sleep:"+str( optimal_looptime - looptime))

View File

@ -10,16 +10,6 @@ import json
from pathlib import Path from pathlib import Path
import redis import redis
environ = {
# "REDIS_IP" : "127.0.0.1",
"REDIS_IP" : "192.168.2.44",
"REDIS_PORT" : "6379",
"REDIS_KEY" : "/pl/0/0",
"REDIS_SCENE" : "0",
"REDIS_LASER" : "0"
}
class bcolors: class bcolors:
HL = '\033[31m' HL = '\033[31m'
OKBLUE = '\033[94m' OKBLUE = '\033[94m'
@ -47,12 +37,12 @@ def intkey():
except ValueError: except ValueError:
print("Error.") print("Error.")
current_id = 0 current_id=0
current_cmd = "" current_cmd=""
process = None process = None
current_filename = "" current_filename = ""
currentPlayList = [] currentPlayList = []
playlistsDir = Path("./playlists") playlistsDir = Path("./playlists")
if not playlistsDir.is_dir() : playlistsDir.mkdir() if not playlistsDir.is_dir() : playlistsDir.mkdir()
def ask(q): def ask(q):
@ -115,12 +105,10 @@ def action_changeCommand( inc ):
return True return True
def action_match( k ): def action_match( k ):
global current_id, currentPlayList
if int(k) > (len(currentPlayList) - 1): if int(k) > (len(currentPlayList) - 1):
print( bcolors.HL + "This key does not exist" + bcolors.ENDC ) print( bcolors.HL + "This key does not exist" + bcolors.ENDC )
return False return False
else : else :
_ok("Changed action id to {}.".format(k))
current_id = int(k) current_id = int(k)
def action_runCommand(): def action_runCommand():
@ -167,7 +155,7 @@ def action_deleteCommand():
action_listAll() action_listAll()
key = int(input()) key = int(input())
# Exit early # Exit early
if "x" == key: if "x" == k:
return(False) return(False)
del currentPlayList[key] del currentPlayList[key]
return True return True
@ -175,7 +163,7 @@ def action_deleteCommand():
def action_listAll(): def action_listAll():
global currentPlayList, current_cmd, current_id global currentPlayList, current_cmd
print("\n--------------------------------------") print("\n--------------------------------------")
for i,seq in enumerate(currentPlayList): for i,seq in enumerate(currentPlayList):
pre="" pre=""
@ -244,7 +232,7 @@ def action_loadPlaylist():
print( bcolors.HL + "This key '{}' is not valid".format(k) + bcolors.ENDC ) print( bcolors.HL + "This key '{}' is not valid".format(k) + bcolors.ENDC )
return False return False
# @todo replace with _loadPlaylist # Load file
playlistFile = Path("./playlists/"+file_list[k].name) playlistFile = Path("./playlists/"+file_list[k].name)
currentPlayList = json.loads(playlistFile.read_text()) currentPlayList = json.loads(playlistFile.read_text())
current_playlist_name = file_list[k].name current_playlist_name = file_list[k].name
@ -254,18 +242,7 @@ def action_loadPlaylist():
def _loadPlaylist( filename ):
global currentPlayList, current_playlist_name, current_id
try:
playlistFile = Path(filename)
currentPlayList = json.loads(playlistFile.read_text())
current_playlist_name = filename
current_id = 0
_ok("Playlist loaded: {}\n".format(current_playlist_name))
return True
except Exception as e:
_err("_loadPlaylist error when loading '{}':{}".format(filename,e))
@ -376,4 +353,13 @@ def action_quit():
quit = inkey() quit = inkey()
if quit != "n": if quit != "n":
_kill(process) _kill(process)
sys.exit(1) sys.exit(1)
environ = {
# "REDIS_IP" : "127.0.0.1",
"REDIS_IP" : "192.168.2.44",
"REDIS_PORT" : "6379",
"REDIS_KEY" : "/pl/0/0",
"REDIS_SCENE" : "0",
"REDIS_LASER" : "0"
}

93
clitools/runner_midi.py Executable file → Normal file
View File

@ -1,87 +1,12 @@
#!/usr/bin/python3 #!/usr/bin/python3
import argparse import sys
import re import os
import redis import signal
import runner_lib as runner import subprocess
import time import time
import tty,termios
novationRows = [ import re
[ 0, 1, 2, 3, 4, 5, 6, 7 ], import json
[ *range(16,24)], from pathlib import Path
[ *range(32,40)], import runner_lib as runner
[ *range(48,56)]
]
argsparser = argparse.ArgumentParser(description="Playlist midi")
argsparser.add_argument("playlist",help="JSON playlist file ",type=str)
argsparser.add_argument("-i","--ip",help="IP address of the Redis server ",default="127.0.0.1",type=str)
argsparser.add_argument("-r","--row",help="Row of Novation pad. Default:1 ",default=1,type=str)
argsparser.add_argument("-k","--key",help="Redis key to update",default="0",type=str)
argsparser.add_argument("-l","--laser",help="Laser number. Default:0 ",default=0,type=int)
argsparser.add_argument("-p","--port",help="Port of the Redis server ",default="6379",type=str)
argsparser.add_argument("-s","--scene",help="Laser scene. Default:0 ",default=0,type=int)
argsparser.add_argument("-v","--verbose",action="store_true",help="Verbose")
args = argsparser.parse_args()
ip = args.ip
port = args.port
key = args.key
verbose=args.verbose
laser = args.laser
scene = args.scene
playlist = args.playlist
row = args.row - 1
rowKeys = novationRows[row]
# Subscriber
r = redis.StrictRedis(host=ip, port=port, db=0)
p = r.pubsub()
p.subscribe('/midi/last_event')
runner._killBill()
# Set Laser and scene
runner._setKey( laser = laser, scene = scene)
# Load playlist
runner._loadPlaylist( playlist )
print("Loaded playlist : {}".format(runner.currentPlayList))
runner.action_info()
runner.current_id = -1
while True:
runner._killBill()
message = p.get_message()
if message:
#runner._ok ("Subscriber: %s" % message['data'])
# b'/midi/noteon/0/19/127'
match = re.match(".*/([0-9]+)/[0-9]+",str(message['data']))
if not match:
continue
key = int(match.group(1))
# Check if the event is for us
if key not in rowKeys:
print("key {} not in {} ".format(key,rowKeys))
continue
try:
command_id = rowKeys.index(key)
cmd = runner.currentPlayList[command_id]
if command_id != runner.current_id :
runner._ok("Launching command #{}\n Previous was {}\n Cmd:{}".format(command_id,runner.current_id,cmd))
runner.action_match(command_id)
runner.action_runCommand()
else :
runner._err("Not running {} : already running.".format(command_id))
except Exception as e :
print("Woops.",e)

View File

@ -1,22 +0,0 @@
#!/usr/bin/python3
# -*- coding: utf-8 -*-
# -*- mode: Python -*-
# or tcpdump -i eth1 port 54545 -XX
import socket
def find_LJ():
"""Listen for broadcast packets."""
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(("0.0.0.0", 54545))
while True:
data, addr = s.recvfrom(1024)
print(" %s " % (data, ))
print("Packet from %s: " % (addr, ))
find_LJ()

View File

@ -70,9 +70,12 @@ def OSCframe():
oscserver.handle_request() oscserver.handle_request()
# OSC server Thread : handler, dacs reports and simulator points sender to UI. # OSC server Thread : handler, dacs reports and simulator points sender to UI.
def osc_thread(): def osc_thread():
#print("osc Thread launched") #print("osc Thread launched")
try: try:
while True: while True:
@ -89,6 +92,8 @@ def osc_thread():
print("\n") print("\n")
# Properly close the system. Todo # Properly close the system. Todo
def Stop(): def Stop():
oscserver.close() oscserver.close()

View File

@ -398,16 +398,6 @@ def handler(oscpath, args):
print() print()
DAChecks() DAChecks()
print("Done.") print("Done.")
if oscpath[2] == "reset":
import shutil
print()
shutil.copyfile(gstt.ljpath+'/templates/LJ_template.conf', gstt.ljpath+'/LJ.conf')
print("templates/LJ_template.conf copied to LJ.conf.")
print("** RESTART LJ **")
#LJautokill()
if oscpath[2] == "restart": if oscpath[2] == "restart":
print() print()
@ -607,7 +597,7 @@ def UpdateAllwww():
Updatepage(gstt.ljpath+"/www/LJ.js") Updatepage(gstt.ljpath+"/www/LJ.js")
Updatepage(gstt.ljpath+"/www/trckr/trckrcam1.html") Updatepage(gstt.ljpath+"/www/trckr/trckrcam1.html")
Updatepage(gstt.ljpath+"/www/simu.html") Updatepage(gstt.ljpath+"/www/simu.html")
Updatepage(gstt.ljpath+"/www/settings.html") Updatepage(gstt.ljpath+"/www/align.html")
Updatepage(gstt.ljpath+"/www/auralls.html") Updatepage(gstt.ljpath+"/www/auralls.html")
Updatepage(gstt.ljpath+"/www/index.html") Updatepage(gstt.ljpath+"/www/index.html")

View File

@ -1012,4 +1012,8 @@ def TextRGB(message, zpos, c, layer, xpos, ypos, resize, rotx, roty, rotz):
Text(message, zpos, int('0x%02x%02x%02x' % (red,green,blue),0), layer, xpos, ypos, resize, rotx, roty, rotz) Text(message, zpos, int('0x%02x%02x%02x' % (red,green,blue),0), layer, xpos, ypos, resize, rotx, roty, rotz)

View File

@ -1,93 +0,0 @@
class Node:
def __init__(self, sid, color):
self.sid = sid
self.connected = []
self.used = False
self.color = color
self.is_free = None # may be an other value to initialise
def add_nodes(self, neighbord):
not_the_same = neighbord != self.sid
not_allrady_inside = neighbord not in self.connected
if neighbord != self.sid and neighbord not in self.connected:
self.connected.append(neighbord)
# print the content of the objet to debug with print()
def __repr__(self):
is_free = " \t###" if self.is_free else " \t___"
return is_free + str(self.connected) + "\n"
#class Graph:
# nodes = {} # dict of all nodes
#
# def __init__(selt):
# pass
def list_to_nodes(pl):
all_nodes = {} # it will contain all nodes
sid_prev = None
for p in pl:
sid = str([int(p[0]), int(p[1])])
is_colored = p[2] != 0
if is_colored:
if sid not in all_nodes:
all_nodes[sid] = Node(sid, p[2])
if sid_prev != None:
all_nodes[sid].add_nodes(sid_prev)
all_nodes[sid_prev].add_nodes(sid)
sid_prev = sid if is_colored else None
return all_nodes
# recursiv function witch get all connected node for one component and tag them as used
def get_one_comp(id_elem, nodes):
comp = []
comp.append(id_elem)
nodes[id_elem].used = True
for id_near in nodes[id_elem].connected:
if nodes[id_near].used == False:
comp += get_one_comp(id_near, nodes)
return comp
def get_comps(nodes):
comps = [] #all component
iter_nodes = iter(nodes)
nb_elem = len(nodes)
for id_nodes in iter_nodes:
if nodes[id_nodes].used == False:
comps.append(get_one_comp(id_nodes, nodes))
return comps
# if ther is a class for the component it would be a good idea to set en atribute about eulerian graph or non eulerian graph
def set_free_vertices(components, nodes):
for comp in components:
all_even_neighbord = True
for id_node in comp:
if len(nodes[id_node].connected) % 2 == 0: # test if even neighbord
nodes[id_node].is_free = False
else:
nodes[id_node].is_free = True
all_even_neighbord = False
if all_even_neighbord:
for id_node in comp:
nodes[id_node].is_free = True
def optimizer(pl):
all_nodes = {} # it will contain all nodes
components = [] # list of connected node as a graph
# construct dict of connected all_nodes
all_nodes = list_to_nodes(pl)
components = get_comps(all_nodes)
set_free_vertices(components, all_nodes)
print("\n\nall_nodes:\n", all_nodes)
print("\n\nconnected_components:\n", components)
return pl
if __name__ == '__main__':
pl = [(355, 262, 0), (355, 262, 16777215), (300, 130, 16777215), (432, 75, 16777215), (487, 207, 16777215), (355, 262, 16777215), (355, 262, 0), (0, 435, 0), (0, 480, 16777215), (0, 300, 16777215), (135, 300, 16777215), (135, 570, 16777215), (135, 570, 16777215), (135, 300, 16777215), (135, 300, 0), (135, 300, 16777215), (225, 480, 16777215), (225, 480, 0), (510, 450, 0), (510, 450, 16777215), (600, 420, 16777215), (600, 300, 16777215), (720, 300, 16777215), (720, 420, 16777215), (810, 450, 16777215), (810, 450, 0)]
optimizer(pl)

View File

@ -15,7 +15,7 @@ from libs3 import gstt
import os import os
import subprocess import subprocess
import sys import sys
from socket import *
def Init(wserver): def Init(wserver):
global WSserver global WSserver
@ -177,14 +177,6 @@ def OSCsend(name, oscaddress, oscargs =''):
#PluginStart(name) #PluginStart(name)
return False return False
def sendbroadcast():
if gstt.debug > 0:
print("Sending broadcast")
cs = socket(AF_INET, SOCK_DGRAM)
cs.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
cs.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
cs.sendto("LJ 0.8".encode(), ("255.255.255.255", 54545))
# for each plugin will automatically add /pluginame before oscpath to send like /aurora/scim 1, if oscpath = "/scim 1" # for each plugin will automatically add /pluginame before oscpath to send like /aurora/scim 1, if oscpath = "/scim 1"

View File

@ -23,44 +23,44 @@ This tracer include an enhanced version (support for several lasers) of the ethe
- Drawing things : - Drawing things :
/pl/Scene/lasernumber [(x,y,color),(x1,y1,color),...] The live list of drawn pygame points. Tracer continously ask redis for key /clientkey+lasernumber /pl/Scene/lasernumber [(x,y,color),(x1,y1,color),...] The live list of drawn pygame points. Tracer continously ask redis for key /clientkey+lasernumber
/resampler/lasernumber [(1.0,8), (0.25,3),(0.75,3),(1.0,10)] : a string for resampling rules. /resampler/lasernumber [(1.0,8), (0.25,3),(0.75,3),(1.0,10)] : a string for resampling rules.
the first tuple (1.0,8) is for short line < 4000 in etherdream space the first tuple (1.0,8) is for short line < 4000 in etherdream space
(0.25,3),(0.75,3),(1.0,10) for long line > 4000 (0.25,3),(0.75,3),(1.0,10) for long line > 4000
i.e (0.25,3) means go at 25% position on the line, send 3 times this position to etherdream i.e (0.25,3) means go at 25% position on the line, send 3 times this position to etherdream
/clientkey "/pl/SceneNumber/" What Scene to retrieve from redis /clientkey "/pl/SceneNumber/" What Scene to retrieve from redis
/EDH/lasernumber /EDH/lasernumber
- Tracer control : - Tracer control :
/order 0-8 Set redis key with new value then issue the order number /order 0-8 Set redis key with new value then issue the order number
0 : Draw Normal point list 0 : Draw Normal point list
1 : Get the new EDH = reread redis key /EDH/lasernumber 1 : Get the new EDH = reread redis key /EDH/lasernumber
2 : Draw BLACK point list 2 : Draw BLACK point list
3 : Draw GRID point list 3 : Draw GRID point list
4 : Resampler Change (longs and shorts lsteps) 4 : Resampler Change (longs and shorts lsteps)
5 : Client Key Change = reread redis key /clientkey 5 : Client Key Change = reread redis key /clientkey
6 : Max Intensity Change = reread redis key /intensity 6 : Max Intensity Change = reread redis key /intensity
7 : kpps change = reread redis key /kpps 7 : kpps change = reread redis key /kpps
8 : color balance change = reread redis keys /red /green /blue 8 : color balance change = reread redis keys /red /green /blue
- Managing Etherdream DACs : - Managing Etherdream DACs :
Discrete drawing values Discrete drawing values
/kpps 0- DAC output speed to laser, then order 7. Depends of actual angle /kpps 0- DAC output speed to laser, then order 7. Depends of actual angle
/intensity 0-255 Laser output power, then order 6 (for alignement,...) /intensity 0-255 Laser output power, then order 6 (for alignement,...)
/red 0-100 % of full red, then order 8 /red 0-100 % of full red, then order 8
/green 0-100 % of full green, then order 8 /green 0-100 % of full green, then order 8
/blue 0-100 % of full blue, then order 8 /blue 0-100 % of full blue, then order 8
DAC status report DAC status report
/lstt/lasernumber etherdream last_status.playback_state (0: idle 1: prepare 2: playing) /lstt/lasernumber etherdream last_status.playback_state (0: idle 1: prepare 2: playing)
/cap/lasernumber number of empty points sent to fill etherdream buffer (up to 1799) /cap/lasernumber number of empty points sent to fill etherdream buffer (up to 1799)
/lack/lasernumber "a": ACK "F": Full "I": invalid. 64 or 35 for no connection. /lack/lasernumber "a": ACK "F": Full "I": invalid. 64 or 35 for no connection.
Geometric corrections Geometric corrections
@ -81,8 +81,7 @@ import pdb
import ast import ast
import redis import redis
from libs3 import homographyp, plotOptimizer as po from libs3 import homographyp
import numpy as np import numpy as np
import binascii import binascii
@ -224,39 +223,66 @@ class DAC(object):
while True: while True:
self.pl = po.optimizer(self.pl) print("\n\n\n\t\t^^^^")
### here self.pl has all the point in one frame
#pdb.set_trace()
### print(self.pl)
### <<<< On peut introduire ici l'autre optimisation
for indexpoint,currentpoint in enumerate(self.pl): for indexpoint,currentpoint in enumerate(self.pl):
print(indexpoint, currentpoint)
# transformations des point au format adapter au etherdream
xyc = [currentpoint[0],currentpoint[1],currentpoint[2]] xyc = [currentpoint[0],currentpoint[1],currentpoint[2]]
self.xyrgb = self.EtherPoint(xyc) self.xyrgb = self.EtherPoint(xyc)
### ### print("1-\nxyrgb[2:]")
### ### print(self.xyrgb[2:])
### print("VVxyrgb")
### print(self.xyrgb)
### print("\n")
rgb = (round(self.xyrgb[2:][0] *self.intred/100), round(self.xyrgb[2:][1] *self.intgreen/100), round(self.xyrgb[2:][2] *self.intblue/100)) rgb = (round(self.xyrgb[2:][0] *self.intred/100), round(self.xyrgb[2:][1] *self.intgreen/100), round(self.xyrgb[2:][2] *self.intblue/100))
#print("rgb :", rgb)
yield self.xyrgb #round(*self.intred/100)
##**//# ajout de point pour un tracer adapter #round(*self.intgreen/100)
##**//delta_x, delta_y = self.xyrgb[0] - self.xyrgb_prev[0], self.xyrgb[1] - self.xyrgb_prev[1] #round(*self.intblue/100)
##**//#test adaptation selon longueur ligne
##**//if math.hypot(delta_x, delta_y) < 4000: delta_x, delta_y = self.xyrgb[0] - self.xyrgb_prev[0], self.xyrgb[1] - self.xyrgb_prev[1]
#test adaptation selon longueur ligne
print("delta_x: "+str(delta_x) + "\t\tdelta_y: "+str(delta_y))
print("norme delta:\t" + str(math.hypot(delta_x, delta_y)))
if math.hypot(delta_x, delta_y) < 4000:
# For glitch art : decrease lsteps
#l_steps = [ (1.0, 8)]
print("little line")
l_steps = gstt.stepshortline
##**// # For glitch art : decrease lsteps else:
##**// #l_steps = [ (1.0, 8)] # For glitch art : decrease lsteps
##**// l_steps = gstt.stepshortline #l_steps = [ (0.25, 3), (0.75, 3), (1.0, 10)]
l_steps = gstt.stepslongline
print("big line")
print(l_steps)
##**//else: ### print("\n\nl_step:")
##**// # For glitch art : decrease lsteps ### print(l_steps)
##**// #l_steps = [ (0.25, 3), (0.75, 3), (1.0, 10)] pAdd = 0
##**// l_steps = gstt.stepslongline ### *** ###for e in l_steps:
### *** ### step = e[0]
##**//for e in l_steps: ### *** ### for i in range(0,e[1]):
##**// step = e[0] ### *** ### pAdd +=1
##**// for i in range(0,e[1]): ### *** ### self.xyrgb_step = (self.xyrgb_prev[0] + step*delta_x, self.xyrgb_prev[1] + step*delta_y) + rgb # + self.xyrgb_prev[2:]# + rgb
### *** ### #print(self.xyrgb_step)
### *** ### yield self.xyrgb_step
##**// self.xyrgb_step = (self.xyrgb_prev[0] + step*delta_x, self.xyrgb_prev[1] + step*delta_y) + rgb # + self.xyrgb_prev[2:]# + rgb yield (self.xyrgb[0], self.xyrgb[1]) + rgb
##**// #print(self.xyrgb_step)
##**// yield self.xyrgb_step
##**//self.xyrgb_prev = self.xyrgb self.xyrgb_prev = self.xyrgb
print("point added:\t" + str(pAdd))
print("\n")
def GetPoints(self, n): def GetPoints(self, n):
@ -332,7 +358,7 @@ class DAC(object):
# ipconn state is -1 at startup (see gstt) and modified here # ipconn state is -1 at startup (see gstt) and modified here
r.set('/lack/'+str(self.mylaser), self.connstatus) r.set('/lack/'+str(self.mylaser), self.connstatus)
gstt.lstt_ipconn[self.mylaser] = self.connstatus gstt.lstt_ipconn[self.mylaser] = self.connstatus
self.buf = b'' self.buf = b''
# Upper case PL is the Point List number # Upper case PL is the Point List number
@ -346,7 +372,7 @@ class DAC(object):
if r.get('/EDH/'+str(self.mylaser)) == None: if r.get('/EDH/'+str(self.mylaser)) == None:
#print("Laser",self.mylaser,"NO EDH !! Computing one...") #print("Laser",self.mylaser,"NO EDH !! Computing one...")
homographyp.newEDH(self.mylaser) homographyp.newEDH(self.mylaser)
else: else:
gstt.EDH[self.mylaser] = np.array(ast.literal_eval(r.get('/EDH/'+str(self.mylaser)).decode('ascii'))) gstt.EDH[self.mylaser] = np.array(ast.literal_eval(r.get('/EDH/'+str(self.mylaser)).decode('ascii')))
#print("Laser",self.mylaser,"found its EDH in redis") #print("Laser",self.mylaser,"found its EDH in redis")
@ -444,23 +470,7 @@ class DAC(object):
if order == 0: if order == 0:
# USER point list # USER point list
self.pl = ast.literal_eval(r.get(self.clientkey+str(self.mylaser)).decode('ascii'))
#self.pl = ast.literal_eval(r.get(self.clientkey+str(self.mylaser)).decode('ascii'))
#print("Tracer : laser", self.mylaser, " order 0 : pl : ",len(self.pl))
# si la clef est vide utiliser les points noirs ? -> syntax error -> black points.
try:
#newpl = ""
#newpl = r.get(self.clientkey+str(self.mylaser))
#self.pl = ast.literal_eval(newpl.decode('ascii'))
self.pl = ast.literal_eval(r.get(self.clientkey+str(self.mylaser)).decode('ascii'))
except SyntaxError:
print("BAD POINTLIST on Tracer : laser", self.mylaser, " order 0 : pl : ", self.pl)
self.pl = black_points
#print("Tracer : laser", self.mylaser, " order 0 : pl : ",len(self.pl)) #print("Tracer : laser", self.mylaser, " order 0 : pl : ",len(self.pl))
else: else:
@ -537,13 +547,13 @@ class DAC(object):
time.sleep(0.001) time.sleep(0.001)
cap += 150 cap += 150
#print("Writing %d points" % (cap, )) # print("Writing %d points" % (cap, ))
#t0 = time.time() #t0 = time.time()
#if self.mylaser == 2: #if self.mylaser == 2:
# print(points) # print(points)
self.write(points) self.write(points)
#t1 = time.time() #t1 = time.time()
#print("Took %f" % (t1 - t0, ) # print("Took %f" % (t1 - t0, )
if not started: if not started:
print("Tracer", self.mylaser, "starting with", gstt.kpps[self.mylaser],"kpps") print("Tracer", self.mylaser, "starting with", gstt.kpps[self.mylaser],"kpps")
@ -584,7 +594,7 @@ def find_dac():
order = r.get('/order') order = r.get('/order')
neworder = order & ~(1<< self.mylaser*2) neworder = order & ~(1<< self.mylaser*2)
neworder = neworder & ~(1<< 1+ self.mylaser*2) neworder = neworder & ~(1<< 1+ self.mylaser*2)
r.set('/order', str(neworder)) r.set('/order', str(neworder))
else: else:
# Laser bit 0 = 1 # Laser bit 0 = 1

29
main.py
View File

@ -36,32 +36,35 @@ print("")
import redis import redis
import os import os
ljpath = r'%s' % os.getcwd().replace('\\','/') ljpath = r'%s' % os.getcwd().replace('\\','/')
import sys import sys
#sys.path.append('libs3/') #sys.path.append('libs3/')
from libs3 import gstt, settings from libs3 import gstt, settings
gstt.ljpath = ljpath gstt.ljpath= ljpath
log.info("Reading " + gstt.ConfigName + " setup file...") log.info("Reading " + gstt.ConfigName + " setup file...")
settings.Read() settings.Read()
# Arguments may alter .conf file so import settings first then cli # Arguments may alter .conf file so import settings first then cli
from libs3 import cli from libs3 import cli
settings.Write() settings.Write()
from multiprocessing import Process, set_start_method from multiprocessing import Process, set_start_method
import random, ast import random, ast
from libs3 import plugins from libs3 import plugins
#from libs3 import lasytracer as tracer
from libs3 import tracer3 as tracer from libs3 import tracer3 as tracer
from libs3 import homographyp, commands, font1 from libs3 import homographyp, commands, font1
#import subprocess #import subprocess
import os import os
#import midi #import midi
from libs3 import OSC3 from libs3 import OSC3
from websocket_server import WebsocketServer from websocket_server import WebsocketServer
#import socket #import socket
@ -141,17 +144,15 @@ oscserverIPout = oscserverIP
oscserverPORTout = 8001 oscserverPORTout = 8001
'''
# Nozoid OSC Client : to send OSC message to Nozoid inport 8003 # Nozoid OSC Client : to send OSC message to Nozoid inport 8003
NozoscIPout = nozoscIP NozoscIPout = nozoscIP
NozoscPORTout = plugins.Port("nozoid") NozoscPORTout = plugins.Port("nozoid")
'''
''''
# Planetarium OSC Client : to send OSC message to planetarium inport 8005 # Planetarium OSC Client : to send OSC message to planetarium inport 8005
planetIPout = nozoscIP planetIPout = nozoscIP
planetPORTout = plugins.Port("planet") planetPORTout = plugins.Port("planet")
'''
import socket import socket
@ -264,15 +265,13 @@ def osc_thread():
#print("Sending simu frame from",'/pl/'+str(gstt.SceneNumber)+'/'+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))) #print(r.get('/pl/'+str(gstt.SceneNumber)+'/'+str(gstt.Laser)))
sendWSall("/simul" +" "+ str(r.get('/pl/'+str(gstt.SceneNumber)+'/'+str(gstt.Laser)).decode('ascii'))) sendWSall("/simul" +" "+ str(r.get('/pl/'+str(gstt.SceneNumber)+'/'+str(gstt.Laser)).decode('ascii')))
if random.randint(0,100)>95:
plugins.sendbroadcast()
except Exception as e: except Exception as e:
import sys, traceback import sys, traceback
print('\n--------------------------') print('\n---------------------')
print('OSC Thread Exception: %s' % e) print('Exception: %s' % e)
print('- - - - - - - - - - - - - - ') print('- - - - - - - - - - -')
traceback.print_tb(sys.exc_info()[2]) traceback.print_tb(sys.exc_info()[2])
print("\n") print("\n")

View File

@ -181,7 +181,7 @@ log.infog("Aurora v0.1b")
OSCinPort = 8090 OSCinPort = 8090
ljscene = 0 ljscene = 0
StartFXs = ["anim.Starfield","anim.Starfield","anim.Starfield", "anim.Word"] StartFXs = ["anim.Maxwell","anim.Starfield","anim.Starfield", "anim.Word"]
# Useful variables init. # Useful variables init.
white = lj.rgb2int(255,255,255) white = lj.rgb2int(255,255,255)
@ -1125,9 +1125,9 @@ def AllFX():
dots = eval(LAY['FX']+"(LAY)") dots = eval(LAY['FX']+"(LAY)")
if LAY['FX'] != "Zero" or lent(dots) != 0: if LAY['FX'] != "Zero" or lent(dots) != 0:
#print(dots, LAY['color']) #print(dots, LAY['color'])
#for cc in range(15): for cc in range(15):
# ccmidi[cc] = int(lj.fromKey("/midi/cc/1/"+str(cc))) ccmidi[cc] = int(lj.fromKey("/midi/cc/1/"+str(cc)))
# #print(ccmidi) #print(ccmidi)
lj.rPolyLineOneColor(dots, c = LAY['color'], layer = l, closed = LAY['closed'], xpos = LAY['Xcoord'] + LAY['stepvals'][LAY['step']] - (LAY['lineSize']/2), ypos = Layer[l]['Ycoord'], resize = LAY['scale'] * audioR, rotx = LAY['Xrotdirec'], roty = LAY['Yrotdirec'], rotz = LAY['Zrotdirec']) lj.rPolyLineOneColor(dots, c = LAY['color'], layer = l, closed = LAY['closed'], xpos = LAY['Xcoord'] + LAY['stepvals'][LAY['step']] - (LAY['lineSize']/2), ypos = Layer[l]['Ycoord'], resize = LAY['scale'] * audioR, rotx = LAY['Xrotdirec'], roty = LAY['Yrotdirec'], rotz = LAY['Zrotdirec'])
#lj.rPolyLineOneColor(dots, c = LAY['color'], layer = l, closed = LAY['closed'], xpos = LAY['Xcoord'] - (ccmidi[0]-64)*4 - (LAY['lineSize']/2), ypos = Layer[l]['Ycoord'] + (ccmidi[1]-64)*4, resize = LAY['scale'] * audioR * (ccmidi[2])/50, rotx = LAY['Xrotdirec']+(ccmidi[3]*3), roty = LAY['Yrotdirec']+(ccmidi[3]*3), rotz = LAY['Zrotdirec']+(ccmidi[3]*3)) #lj.rPolyLineOneColor(dots, c = LAY['color'], layer = l, closed = LAY['closed'], xpos = LAY['Xcoord'] - (ccmidi[0]-64)*4 - (LAY['lineSize']/2), ypos = Layer[l]['Ycoord'] + (ccmidi[1]-64)*4, resize = LAY['scale'] * audioR * (ccmidi[2])/50, rotx = LAY['Xrotdirec']+(ccmidi[3]*3), roty = LAY['Yrotdirec']+(ccmidi[3]*3), rotz = LAY['Zrotdirec']+(ccmidi[3]*3))
else: else:

937
www/align.html Normal file
View File

@ -0,0 +1,937 @@
<!DOCTYPE html>
<html>
<head>
<title>Align Rack</title>
<meta charset="utf-8" />
<meta name="apple-mobile-web-app-title" content="Align">
<meta name="apple-mobile-web-app-capable" content="yes">
<link rel="apple-touch-startup-image" href="/launch.png">
<link rel="apple-touch-icon" href="touch-icon-iphone.png">
<link rel="apple-touch-icon" sizes="152x152" href="touch-icon-ipad.png">
<link rel="apple-touch-icon" sizes="180x180" href="touch-icon-iphone-retina.png">
<link rel="apple-touch-icon" sizes="167x167" href="touch-icon-ipad-retina.png">
<!-- Page specific styles -->
<style>
</style>
<!-- Web audio buttons defaults -->
<script type="application/javascript" src="webcomponents-lite.js"></script>
<script type="application/javascript" src="config.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>
<link rel="stylesheet" href="css/common.css" />
</head>
<body style="background-color:#222;">
<div class="Rackcontent">
<!--
Navigation Rack
-->
<div class="content">
<div class="buttons-7container">
<a href="index.html">
<div class="webaudiobut">
<div align="center" class="navled">
Index
</div>
</div>
</a>
<a href="align.html">
<div class="webaudiobut">
<div align="center" class="navled">
Align
</div>
</div>
</a>
<a href="auralls.html">
<div class="webaudiobut">
<div align="center" class="navled">
Aurora
</div>
</div>
</a>
<a href="trckr/trckrcam1.html">
<div class="webaudiobut">
<div align="center" class="navled">
Lasercam
</div>
</div>
</a>
<a href="simu.html">
<div class="webaudiobut">
<div align="center" class="navled">
Simu
</div>
</div>
</a>
<div class="webaudiobut">
<button type="button" class="navled" style="border : #222222 1px;" onclick="onSubmit(this.id)" id="settings/restart lj" >
restrt LJ
</button>
</div>
<div class="webaudiobut">
<button type="button" class="navled" style="border : #222222 1px;" onclick="onSubmit(this.id)" id="settings/restart aurora" >
restrt AU
</button>
</div>
</div>
</div>
<!--
Display Rack
-->
<div class="content">
<div class="TopRackGrid">
<div>
<h2>
/TL Align
<span class="shade">&nbsp;</span>
</h2>
<webaudio-switch id="on" value="1" tooltip="Switch-B" height="35" width="85" src="knobs/switch1.png">
</webaudio-switch>
</div>
<div class="webaudiobut">
<div align="center" id="line1" class="busled">
Align Rack
</div>
<div align="center" id="status" class="busled">
/team/laser
</div>
</div>
<div class="etherled" style="margin-left: 30px;margin-top: 1px;">
Stt
<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>
<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>
<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>
<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 class="etherled" style="margin-left: 30px;margin-top: 1px;">
Ack
<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>
<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>
<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>
<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>
</div>
<!--
Scene choice Rack
-->
<div class="content">
<div class="Settingrid">
<div>
<h2>Scene</h2>
</div>
<div class="webaudiobut" align="center" style="width: 83px;">
<button type="button" class="navled" style="border: 1px solid #002020; text-align: middle;" onclick="onSubmit(this.id)" id="scene/0/start 1" >
0
</button>
</div>
<div>
</div>
<div class="webaudiobut" align="center" style="width: 83px;">
<button type="button" class="navled" style="border: 1px solid #002020; text-align: middle;" onclick="onSubmit(this.id)" id="scene/1/start 1" >
1
</button>
</div>
<div>
</div>
<div class="webaudiobut" align="center" style="width: 83px;">
<button type="button" class="navled" style="border: 1px solid #002020; text-align: middle;" onclick="onSubmit(this.id)" id="scene/2/start 1" >
2
</button>
</div>
<div>
</div>
<div class="webaudiobut" align="center" style="width: 83px;">
<button type="button" class="navled" style="border: 1px solid #002020; text-align: middle;" onclick="onSubmit(this.id)" id="scene/3/start 1" >
3
</button>
</div>
<div></div>
<div></div>
<div></div>
<div> </div>
<div></div>
</div>
</div>
<!--
Settings Rack
<div class="content">
<div class="Settingrid">
<div>
<h2>Settings</h2>
</div>
<div class="webaudiobut">
<div align="center" class="navled" style="border: 1px solid #222;">
Lasers
</div>
</div>
<div>
<form onsubmit="onSubmit(); return false;">
<select name="settings/lasers" class = "submitalign" onchange = "onSubmit(this.id)" type="text" id="settings/lasers">
<option value="1" selected>1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
</form>
</div>
<div class="webaudiobut" align="center" style="width: 83px;">
<button type="button" class="navled" style="border: 1px solid #002020; text-align: middle;" onclick="onSubmit(this.id)" id="settings/rescan" >
Rescan
</button>
</div>
<div>
<form onsubmit="onSubmit(); return false;">
<select name="settings/debug" class = "submitalign" onchange = "onSubmit(this.id)" type="text" id="settings/debug">
<option value="0" selected>0</option>
<option value="1">1</option>
<option value="2">2</option>
</select>
</form>
</div>
<div class="webaudiobut">
<div align="center" class="navled" style="border: 1px solid #222;">
Debug
</div>
</div>
<div>
<form onsubmit="onSubmit(); return false;">
<input class = "submite" onchange = "onSubmit(this.id)" type="text" id="settings/IP">
</form>
</div>
<div class="webaudiobut" align="center" style="width: 73px;">
<button type="button" class="navled" style="border: 1px solid #002020;" onclick="onSubmit(this.id)" id="settings/regen" >
Regen
</button>
</div>
<div></div>
<div></div>
<div></div>
<div> </div>
<div></div>
</div>
</div>
-->
<!--
Align Rack
-->
<div class="content" style="height: 500px">
<div class="TextGrid">
<div class="mgalign" style="margin-left:0px;">
<!--
Laser 0
-->
<div class="laserbox" align="center">
<!-- IP laser 0 -->
<div>
<form onsubmit="onSubmit(); return false;">
<input class = "submite" onchange = "onSubmit(this.id)" type="text" id="ip/0">
</form>
</div>
<!-- Laser type
<div class="spacer" style="height: 10px;"></div>
<div >
<form onsubmit="onSubmit(); return false;">
<select name="lasertype" class = "submite" onchange = "onSubmit(this.id)" type="text" id="lasertype/0">
<option value="DS1000" selected>DS1000</option>
<option value="Luke400">Luke400</option>
<option value="Spectra">Spectra</option>
<option value="Fire500">Fire500</option>
</select>
</form>
</div>
-->
<div class="spacer" style="height: 8px;"></div>
<div>
<!-- Align Icons -->
<webaudio-switch id="grid/0" value="0" height="25" width="25" tooltip="Switch-B" src="knobs/grid.png"></webaudio-switch>
<webaudio-switch id="mouse/0" value="0" height="25" width="25" tooltip="Switch-B" src="knobs/mouse.png"></webaudio-switch>
<!-- Blackout icon -->
<webaudio-switch id="black/0" value="0" height="25" width="25" tooltip="Switch-B" src="knobs/blackout.png"></webaudio-switch>
<!-- Swap Icons -->
<webaudio-switch id="swap/X/0" value="0" height="25" width="25" tooltip="Switch-B" src="knobs/swapx.png"></webaudio-switch>
<webaudio-switch id="swap/Y/0" value="0" height="25" width="25" tooltip="Switch-B" src="knobs/swapy.png"></webaudio-switch>
</div>
<div class="spacer" style="height: 6px;"></div>
<!-- kpps knob -->
<div><webaudio-knob id="kpps/0" diameter="60" min="100" max="40000" value="25000"></webaudio-knob></div>
<!-- Lasergrid 0 -->
<div class="lasergrid" style="background-image: url(knobs/lasergrid0.png);">
<!-- kPPS & Points-->
<div></div>
<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></div>
<div class="lasertext">kPPS</div>
<div class="lasertext">Buffer</div>
<div></div>
<div class="spacer" style="height: 5px;"></div>
<div class="spacer" style="height: 5px;"></div>
<!-- Angle, Offset X, Offset Y -->
<div><webaudio-knob id="angle/0" diameter="60" min="0" max="360" value="0"></webaudio-knob></div>
<div><webaudio-knob id="loffset/X/0" diameter="60" min="-27000" max="27000" value="0"></webaudio-knob></div>
<div><webaudio-knob id="loffset/Y/0" diameter="60" min="-27000" max="27000" value="0"></webaudio-knob></div>
<div class="lasertext">Angle</div>
<div class="lasertext">Offset X</div>
<div class="lasertext">Offset Y</div>
<div><webaudio-param link="angle/0" value="0"></webaudio-param></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" style="height: 5px;"></div>
<div class="spacer" style="height: 5px;"></div>
<div class="spacer" style="height: 5px;"></div>
<!-- Max global intensity, Scale X, Scale Y -->
<div><webaudio-knob id="intens/0" diameter="60" min="0" max="255" value="255"></webaudio-knob></div>
<div><webaudio-knob id="scale/X/0" diameter="60" min="0" max="200" value="50"></webaudio-knob></div>
<div><webaudio-knob id="scale/Y/0" diameter="60" min="0" max="200" value="50"></webaudio-knob></div>
<div class="lasertext"style="color: #ddd;">Intens</div>
<div class="lasertext">Scale X</div>
<div class="lasertext">Scale X</div>
<div><webaudio-param link="intens/0" value="255"></webaudio-param></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>
<div class="spacer"></div>
<!-- Red green blue % Intensity for color balancing -->
<div><webaudio-knob id="red/0" diameter="60" min="0" max="100" value="100"></webaudio-knob></div>
<div><webaudio-knob id="green/0" diameter="60" min="0" max="100" value="100"></webaudio-knob></div>
<div><webaudio-knob id="blue/0" diameter="60" min="0" max="100" value="100"></webaudio-knob></div>
<div class="lasertext" style="color: #cbb;">Red</div>
<div class="lasertext" style="color: #bcb;">Green</div>
<div class="lasertext" style="color: #bbc;">Blue</div>
</div>
</div>
<!--
Laser 1
-->
<div class="laserbox" align="center">
<!-- IP laser 1 -->
<div>
<form onsubmit="onSubmit(); return false;">
<input class = "submite" onchange = "onSubmit(this.id)" type="text" id="ip/1">
</form>
</div>
<div class="spacer" style="height: 8px;"></div>
<div >
<!-- Align Icons -->
<webaudio-switch id="grid/1" value="0" height="25" width="25" tooltip="Switch-B" src="knobs/grid.png"></webaudio-switch>
<webaudio-switch id="mouse/1" value="0" height="25" width="25" tooltip="Switch-B" src="knobs/mouse.png"></webaudio-switch>
<!-- Blackout icon -->
<webaudio-switch id="black/1" value="0" height="25" width="25" tooltip="Switch-B" src="knobs/blackout.png"></webaudio-switch>
<!-- Swap Icons -->
<webaudio-switch id="swap/X/1" value="0" height="25" width="25" tooltip="Switch-B" src="knobs/swapx.png"></webaudio-switch>
<webaudio-switch id="swap/Y/1" value="0" height="25" width="25" tooltip="Switch-B" src="knobs/swapy.png"></webaudio-switch>
</div>
<div class="spacer" style="height: 6px;"></div>
<!-- kpps knob -->
<div><webaudio-knob id="kpps/1" diameter="60" min="100" max="40000" value="25000"></webaudio-knob></div>
<!-- Lasergrid 1 -->
<div class="lasergrid" style="background-image: url(knobs/lasergrid1.png);">
<!-- kPPS & Points-->
<div></div>
<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></div>
<div class="lasertext">kPPS</div>
<div class="lasertext">Buffer</div>
<div></div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Angle, Offset X, Offset Y -->
<div><webaudio-knob id="angle/1" diameter="60" min="0" max="360"value="0"></webaudio-knob></div>
<div><webaudio-knob id="loffset/X/1" diameter="60" min="-27000" max="27000" value="0"></webaudio-knob></div>
<div><webaudio-knob id="loffset/Y/1" diameter="60" min="-27000" max="27000" value="0"></webaudio-knob></div>
<div class="lasertext">Angle</div>
<div class="lasertext">Offset X</div>
<div class="lasertext">Offset Y</div>
<div><webaudio-param link="angle/1" value="0"></webaudio-param></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" style="height: 5px;"></div>
<div class="spacer" style="height: 5px;"></div>
<div class="spacer" style="height: 5px;"></div>
<!-- Max global intensity, Scale X, Scale Y -->
<div><webaudio-knob id="intens/1" diameter="60" min="0" max="255" value="255"></webaudio-knob></div>
<div><webaudio-knob id="scale/X/1" diameter="60" min="0" max="200" value="50"></webaudio-knob></div>
<div><webaudio-knob id="scale/Y/1" diameter="60" min="0" max="200" value="50"></webaudio-knob></div>
<div class="lasertext"style="color: #ddd;">Intens</div>
<div class="lasertext">Scale X</div>
<div class="lasertext">Scale X</div>
<div><webaudio-param link="intens/1" value="255"></webaudio-param></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>
<div class="spacer"></div>
<!-- Red green blue % Intensity for color balancing -->
<div><webaudio-knob id="red/1" diameter="60" min="0" max="100" value="100"></webaudio-knob></div>
<div><webaudio-knob id="green/1" diameter="60" min="0" max="100" value="100"></webaudio-knob></div>
<div><webaudio-knob id="blue/1" diameter="60" min="0" max="100" value="100"></webaudio-knob></div>
<div class="lasertext" style="color: #cbb;">Red</div>
<div class="lasertext" style="color: #bcb;">Green</div>
<div class="lasertext" style="color: #bbc;">Blue</div>
</div>
</div>
<!--
Laser 2
-->
<div class="laserbox" align="center">
<!-- IP laser 2 -->
<div>
<form onsubmit="onSubmit(); return false;">
<input class = "submite" onchange = "onSubmit(this.id)" type="text" id="ip/2">
</form>
</div>
<div class="spacer" style="height: 8px;"></div>
<div>
<!-- Align Icons -->
<webaudio-switch id="grid/2" value="0" height="25" width="25" tooltip="Switch-B" src="knobs/grid.png"></webaudio-switch>
<webaudio-switch id="mouse/2" value="0" height="25" width="25" tooltip="Switch-B" src="knobs/mouse.png"></webaudio-switch>
<!-- Blackout icon -->
<webaudio-switch id="black/2" value="0" height="25" width="25" tooltip="Switch-B" src="knobs/blackout.png"></webaudio-switch>
<!-- Swap Icons -->
<webaudio-switch id="swap/X/2" value="0" height="25" width="25" tooltip="Switch-B" src="knobs/swapx.png"></webaudio-switch>
<webaudio-switch id="swap/Y/2" value="0" height="25" width="25" tooltip="Switch-B" src="knobs/swapy.png"></webaudio-switch>
</div>
<div class="spacer" style="height: 6px;"></div>
<!-- kpps knob -->
<div><webaudio-knob id="kpps/2" diameter="60" min="100" max="40000" value="25000"></webaudio-knob></div>
<!-- Laser 2 grid -->
<div class="lasergrid" style="background-image: url(knobs/lasergrid2.png)">
<!-- kPPS & Points-->
<div></div>
<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></div>
<div class="lasertext">kPPS</div>
<div class="lasertext">Buffer</div>
<div></div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Angle, Offset X, Offset Y -->
<div><webaudio-knob id="angle/2" diameter="60" min="0" max="360" value="0"></webaudio-knob></div>
<div><webaudio-knob id="loffset/X/2" diameter="60" min="-27000" max="27000" value="0"></webaudio-knob></div>
<div><webaudio-knob id="loffset/Y/2" diameter="60" min="-27000" max="27000" value="0"></webaudio-knob></div>
<div class="lasertext">Angle</div>
<div class="lasertext">Offset X</div>
<div class="lasertext">Offset Y</div>
<div><webaudio-param link="angle/2" value="0"></webaudio-param></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" style="height: 5px;"></div>
<div class="spacer" style="height: 5px;"></div>
<div class="spacer" style="height: 5px;"></div>
<!-- Max global intensity, Scale X, Scale Y -->
<div><webaudio-knob id="intens/2" diameter="60" min="0" max="255" value="255"></webaudio-knob></div>
<div><webaudio-knob id="scale/X/2" diameter="60" min="0" max="200" value="50"></webaudio-knob></div>
<div><webaudio-knob id="scale/Y/2" diameter="60" min="0" max="200" value="50"></webaudio-knob></div>
<div class="lasertext"style="color: #ddd;">Intens</div>
<div class="lasertext">Scale X</div>
<div class="lasertext">Scale X</div>
<div><webaudio-param link="intens/2" value="255"></webaudio-param></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>
<div class="spacer"></div>
<!-- Red green blue % Intensity for color balancing -->
<div><webaudio-knob id="red/2" diameter="60" min="0" max="100" value="100"></webaudio-knob></div>
<div><webaudio-knob id="green/2" diameter="60" min="0" max="100" value="100"></webaudio-knob></div>
<div><webaudio-knob id="blue/2" diameter="60" min="0" max="100" value="100"></webaudio-knob></div>
<div class="lasertext" style="color: #cbb;">Red</div>
<div class="lasertext" style="color: #bcb;">Green</div>
<div class="lasertext" style="color: #bbc;">Blue</div>
</div>
</div>
<!--
Laser 3
-->
<div class="laserbox" align="center">
<!-- IP laser 3 -->
<div>
<form onsubmit="onSubmit(); return false;">
<input class = "submite" onchange = "onSubmit(this.id)" type="text" id="ip/3">
</form>
</div>
<div class="spacer" style="height: 8px;"></div>
<div>
<!-- Align Icons -->
<webaudio-switch id="grid/3" value="0" height="25" width="25" tooltip="Switch-B" src="knobs/grid.png"></webaudio-switch>
<webaudio-switch id="mouse/3" value="0" height="25" width="25" tooltip="Switch-B" src="knobs/mouse.png"></webaudio-switch>
<!-- Blackout icon -->
<webaudio-switch id="black/3" value="0" height="25" width="25" tooltip="Switch-B" src="knobs/blackout.png"></webaudio-switch>
<!-- Swap Icons -->
<webaudio-switch id="swap/X/3" value="0" height="25" width="25" tooltip="Switch-B" src="knobs/swapx.png"></webaudio-switch>
<webaudio-switch id="swap/Y/3" value="0" height="25" width="25" tooltip="Switch-B" src="knobs/swapy.png"></webaudio-switch>
</div>
<div class="spacer" style="height: 6px;"></div>
<!-- kpps knob -->
<div><webaudio-knob id="kpps/3" diameter="60" min="100" max="40000" value="25000"></webaudio-knob></div>
<!-- Laser 3 grid -->
<div class="lasergrid" style="background-image: url(knobs/lasergrid3.png)">
<!-- kPPS & Points-->
<div></div>
<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></div>
<div class="lasertext">kPPS</div>
<div class="lasertext">Buffer</div>
<div></div>
<div class="spacer"></div>
<div class="spacer"></div>
<!-- Angle, Offset X, Offset Y -->
<div><webaudio-knob id="angle/3" diameter="60" min="0" max="360" value="0"></webaudio-knob></div>
<div><webaudio-knob id="loffset/X/3" diameter="60" min="-27000" max="27000" value="0"></webaudio-knob></div>
<div><webaudio-knob id="loffset/Y/3" diameter="60" min="-27000" max="27000" value="0"></webaudio-knob></div>
<div class="lasertext">Angle</div>
<div class="lasertext">Offset X</div>
<div class="lasertext">Offset Y</div>
<div><webaudio-param link="angle/3" value="0"></webaudio-param></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" style="height: 5px;"></div>
<div class="spacer" style="height: 5px;"></div>
<div class="spacer" style="height: 5px;"></div>
<!-- Max global intensity, Scale X, Scale Y -->
<div><webaudio-knob id="intens/3" diameter="60" min="0" max="255" value="255"></webaudio-knob></div>
<div><webaudio-knob id="scale/X/3" diameter="60" min="0" max="200" value="50"></webaudio-knob></div>
<div><webaudio-knob id="scale/Y/3" diameter="60" min="0" max="200" value="50"></webaudio-knob></div>
<div class="lasertext"style="color: #ddd;">Intens</div>
<div class="lasertext">Scale X</div>
<div class="lasertext">Scale X</div>
<div><webaudio-param link="intens/3" value="255"></webaudio-param></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>
<div class="spacer"></div>
<!-- Red green blue % Intensity for color balancing -->
<div><webaudio-knob id="red/3" diameter="60" min="0" max="100" value="100"></webaudio-knob></div>
<div><webaudio-knob id="green/3" diameter="60" min="0" max="100" value="100"></webaudio-knob></div>
<div><webaudio-knob id="blue/3" diameter="60" min="0" max="100" value="100"></webaudio-knob></div>
<div class="lasertext" style="color: #cbb;">Red</div>
<div class="lasertext" style="color: #bcb;">Green</div>
<div class="lasertext" style="color: #bbc;">Blue</div>
</div>
</div>
</div>
</div>
</div>
<!--
Encoders Line
# /aurora/radius layernumber radius [0-1]
# /aurora/rotdirec layer axe direc
# /aurora/linesize layer value
# /aurora/rotdirec layer axe direc
# /aurora/rotspeed layernumber axe speed
# /aurora/transpeed layernumber axe transpeed
# /aurora/transamt layernumber axe maxposition
-->
<!--
JS
-->
<!-- LJ style WS : A nettoyer ! -->
<script type="text/javascript">
var LJ = websocket_uri
var _WS = {
uri: LJ,
ws: null,
init : function (e) {
_WS.s = new WebSocket(_WS.uri);
_WS.s.onopen = function (e) { _WS.onOpen(e); };
_WS.s.onclose = function (e) { _WS.onClose(e); };
_WS.s.onmessage = function (e) { _WS.onMessage(e); };
_WS.s.onerror = function (e) { _WS.onError(e); };
},
onOpen: function () {
_WS.showstatus("Connected to "+LJ);
document.getElementById("on").value = 1;
},
onClose: function () {
_WS.showline1('<span style="color: red;">LJ DISCONNECTED</span> ');
document.getElementById("on").value = 0;
document.getElementById("lstt/0").value = 0;
document.getElementById("lstt/1").value = 0;
document.getElementById("lstt/2").value = 0;
document.getElementById("lstt/3").value = 0;
document.getElementById("lack/0").value = 0;
document.getElementById("lack/1").value = 0;
document.getElementById("lack/2").value = 0;
document.getElementById("lack/3").value = 0;
},
onMessage: function (e) {
var res = e.data.split(" ");
//console.log(e.data)
//console.log(res[0].substring(0,6))
//console.log(res)
//console.log(res[0].slice(1))
var divtext = document.getElementById('status');
var divtextp = document.getElementById('players');
switch (res[0].substring(0,6)) {
case "/statu":
_WS.showline1("connected to "+LJ);
if (res[2]==="Disconnected"){
_WS.showstatus(res[1]+" "+'<span style="color: red;">'+ res[2]+'</span> ');
}
else{
_WS.showstatus(res[1]+" "+res[2]);
}
break;
case "/redst":
//console.log("red"+res[1]+" "+res[2]);
_WS.showstatus('<span style="color: red;">'+res[1]+" "+ res[2]+'</span> ');
break;
case "/line1":
//divtext.innerHTML="connected to "+LJ;
divtext1.innerHTML=res[1]+" "+res[2];
break;
case "/redline1":
//divtext.innerHTML="connected to "+LJ;
divtext1.innerHTML='<span style="color: red;">'+ res[1]+" "+res[2]+'</span>';
break;
case "/lack/":
console.log("/lack "+res[1])
document.getElementById(res[0].slice(1)).value = res[1];
break;
case "/lstt/":
console.log("/lstt "+res[1])
document.getElementById(res[0].slice(1)).value = res[1];
break;
default:
//console.log("test "+res[0].slice(1)+" "+res[1]);
document.getElementById(res[0].slice(1)).value = res[1];
//_WS.showstatus(e.data);
break
}
},
onError: function (e) {
_WS.showstatus('<span style="color: red;">ERROR:</span> ' + e.data);
},
showin: function (message) {
var divtext = document.getElementById('status');
divtext.innerHTML="";
divtext.innerHTML= message.toString();
},
showout: function (message) {
var divtext = document.getElementById('status');
divtext.innerHTML="";
divtext.innerHTML= message.toString();
},
showstatus: function (message) {
var divtext = document.getElementById('status');
divtext.innerHTML="";
divtext.innerHTML= message.toString();
},
showline1: function (message) {
var divtext = document.getElementById('line1');
divtext.innerHTML="";
divtext.innerHTML= message.toString();
},
send: function (message) {
if (!message.length) {
alert('Empty message not allowed !');
} else {
_WS.showstatus(message);
_WS.s.send(message);
}
},
close: function () {
_WS.showstatus('GOODBYE !');
_WS.s.close();
}
};
window.addEventListener('load', _WS.init, false);
//
// Forms submits
//
function onSubmit(clicked_id) {
var input = document.getElementById(clicked_id);
console.log("/" + clicked_id + " " + input.value);
_WS.send("/" + clicked_id + " " + input.value);
}
</script>
<!--
web audio encoders 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 newlaser(id) {
console.log("newlaser")
nolaser();
nofx();
laserid = "noteon "+(24-id);
console.log("laserid "+laserid);
var x = document.getElementById(laserid);
x.value = 1 ;
console.log("laser "+id);
}
function nofx0() {
console.log("nofx0")
var x = document.getElementById("aurora/fx/0 ScanH");
x.value = 0 ;
var x = document.getElementById("aurora/fx/0 ScanV");
x.value = 0 ;
var x = document.getElementById("aurora/fx/0 Wave");
x.value = 0 ;
var x = document.getElementById("aurora/fx/0 Circle");
x.value = 0 ;
var x = document.getElementById("aurora/fx/0 Starfield");
x.value = 0 ;
var x = document.getElementById("aurora/fx/0 Word");
x.value = 0 ;
var x = document.getElementById("aurora/fx/0 Trckr");
x.value = 0 ;
}
function nocolor0() {
console.log("nocolor0")
var x = document.getElementById("aurora/color/0 red");
x.value = 0 ;
var x = document.getElementById("aurora/color/0 yellow");
x.value = 0 ;
var x = document.getElementById("aurora/color/0 green");
x.value = 0 ;
var x = document.getElementById("aurora/color/0 blue");
x.value = 0 ;
var x = document.getElementById("aurora/color/0 cyan");
x.value = 0 ;
var x = document.getElementById("aurora/color/0 white");
x.value = 0 ;
}
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/>";
}
_WS.send("/" + e.target.id + " " + e.target.value);
var res = e.target.id.split(" ");
// on off
if (e.target.id === "on" && e.type === "change") {
window.location.reload();
}
// Go to index
if (e.target.id === "index" && e.type === "change") {
window.location.assign("index.html");
}
// Fx
if (res[0].substring(7,9) === "fx" && e.type === "change") {
var layer = res[0].substring(10,12);
nofx0();
var x = document.getElementById(e.target.id);
x.value = 1 ;
_WS.showstatus(e.target.id);
}
// Colors
if (res[0].substring(7,9) === "co" && e.type === "change") {
var layer = res[0].substring(13,14);
console.log(layer)
nocolor0();
var x = document.getElementById(e.target.id);
x.value = 1 ;
_WS.showstatus(e.target.id);
}
}
</script>
</body>
</html>

View File

@ -59,10 +59,10 @@
</div> </div>
</a> </a>
<a href="settings.html"> <a href="align.html">
<div class="webaudiobut"> <div class="webaudiobut">
<div align="center" class="navled"> <div align="center" class="navled">
Settings Align
</div> </div>
</div> </div>
</a> </a>
@ -93,8 +93,8 @@
<div class="webaudiobut"> <div class="webaudiobut">
<button type="button" class="navled" style="border : #222222 1px;" onclick="onSubmit(this.id)" id="settings/reset" > <button type="button" class="navled" style="border : #222222 1px;" onclick="onSubmit(this.id)" id="settings/restart lj" >
Reset rstrt LJ
</button> </button>
</div> </div>

View File

@ -101,15 +101,15 @@
<!-- <!--
Settings Rack Align Rack
--> -->
<a href="settings.html"> <a href="align.html">
<div class="content"> <div class="content">
<div class="TopRackGrid"> <div class="TopRackGrid">
<div> <div>
<h2> <h2>
Settings Align
<span class="shade">&nbsp;</span> <span class="shade">&nbsp;</span>
</h2> </h2>
<webaudio-switch id="on" value="1" tooltip="Switch-B" height="35" width="85" src="knobs/switch1.png"> <webaudio-switch id="on" value="1" tooltip="Switch-B" height="35" width="85" src="knobs/switch1.png">
@ -117,7 +117,7 @@
</div> </div>
<div class="webaudiobut"> <div class="webaudiobut">
<div align="center" class="busled"> <div align="center" class="busled">
Settings Align
</div> </div>
<div align="center" class="busled"> <div align="center" class="busled">
&nbsp; &nbsp;

View File

@ -56,10 +56,10 @@
</div> </div>
</a> </a>
<a href="settings.html"> <a href="align.html">
<div class="webaudiobut"> <div class="webaudiobut">
<div align="center" class="navled"> <div align="center" class="navled">
Settings Align
</div> </div>
</div> </div>
</a> </a>
@ -90,8 +90,8 @@
<div class="webaudiobut"> <div class="webaudiobut">
<button type="button" class="navled" style="border : #222222 1px;" onclick="onSubmit(this.id)" id="settings/reset" > <button type="button" class="navled" style="border : #222222 1px;" onclick="onSubmit(this.id)" id="settings/restart lj" >
reset rstrt LJ
</button> </button>
</div> </div>

680
www/trckr/trckr.html Normal file
View File

@ -0,0 +1,680 @@
<!doctype html>
<html lang="en">
<head>
<title>LASERCam 1</title>
<meta charset="utf-8">
<link href="./styles/bootstrap.min.css" rel="stylesheet" type="text/css">
<meta name="apple-mobile-web-app-title" content="Tracker">
<meta name="apple-mobile-web-app-capable" content="yes">
<link rel="apple-touch-startup-image" href="../launch.png">
<link rel="apple-touch-icon" href="../touch-icon-iphone.png">
<link rel="apple-touch-icon" sizes="152x152" href="../touch-icon-ipad.png">
<link rel="apple-touch-icon" sizes="180x180" href="../touch-icon-iphone-retina.png">
<link rel="apple-touch-icon" sizes="167x167" href="../touch-icon-ipad-retina.png">
<script type="application/javascript" src="../config.js"></script>
<style>
</style>
<script>
// getUserMedia only works over https in Chrome 47+, so we redirect to https. Also notify user if running from file.
if (window.location.protocol == "file:") {
alert("You seem to be running this example directly from a file. Note that these examples only work when served from a server or localhost due to canvas cross-domain restrictions.");
} else if (window.location.hostname !== "localhost" && window.location.protocol !== "https:"){
window.location.protocol = "http";
//window.location.protocol = "https";
}
</script>
<!--
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-32642923-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
-->
<!-- Web audio buttons defaults -->
<script type="application/javascript" 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>
<link rel="stylesheet" href="../css/common.css" />
</head>
<body style="background-color:#222;">
<script src="./js/libs/utils.js"></script>
<script src="../build/clmtrackr.js"></script>
<script src="./js/libs/Stats.js"></script>
<!--
Top Rack
<div align="center">
<a href="index.html"><img height="25" width="21" src="../knobs/indexs.png"></a>
</div>
-->
<div class="Rackcontent">
<!--
Navigation Rack
-->
<div class="content">
<div class="buttons-7container">
<a href="../index.html">
<div class="webaudiobut">
<div align="center" class="navled">
Index
</div>
</div>
</a>
<a href="../align.html">
<div class="webaudiobut">
<div align="center" class="navled">
Align
</div>
</div>
</a>
<a href="../auralls.html">
<div class="webaudiobut">
<div align="center" class="navled">
Aurora
</div>
</div>
</a>
<a href="trckrcam1.html">
<div class="webaudiobut">
<div align="center" class="navled">
Lasercam
</div>
</div>
</a>
<a href="../simu.html">
<div class="webaudiobut">
<div align="center" class="navled">
Simu
</div>
</div>
</a>
<div class="webaudiobut">
<button type="button" class="navled" style="border : #222222 1px;" onclick="onSubmit(this.id)" id="settings/restart lj" >
rstrt LJ
</button>
</div>
<div class="webaudiobut">
<button type="button" class="navled" style="border : #222222 1px;" onclick="onSubmit(this.id)" id="settings/restart aurora" >
rstrt AU
</button>
</div>
</div>
</div>
<!--
Lasers & colors Rack
-->
<div class="content">
<div class="TopRackGrid">
<div>
<h2>
/TL RGY 1
<span class="shade">&nbsp;</span>
</h2>
<webaudio-switch id="on" value="1" tooltip="Switch-B" height="35" width="85" src="../knobs/switch1.png">
</webaudio-switch>
</div>
<div style="border : #242424 1px solid;background: #000;">
<div align="center" id="line1" class="busled">
LASERcam 1 : Allow to use your webcam + start
</div>
<div align="center" id="status" class="busled">
/team/laser
</div>
</div>
<div></div>
<div>
<div style="margin-top : 30px;">
</div>
<div>
</div>
</div>
</div>
</div>
<!--
Colors Rack
-->
<div class="content">
<div class="Rackgrid">
<div>
<h2>
Colors
</h2>
</div>
<div class="webaudiobut"><webaudio-switch id="noteon 24" value="1" tooltip="Switch-B" height="64" width="64" src="../knobs/big0.png"></webaudio-switch></div>
<div class="webaudiobut"><webaudio-switch id="noteon 25" value="0" tooltip="Switch-B" height="64" width="64" src=" ../knobs/big1.png"></webaudio-switch></div>
<div class="webaudiobut"><webaudio-switch id="noteon 26" value="0" tooltip="Switch-B" height="64" width="64" src="../knobs/big2.png"></webaudio-switch></div>
<div class="webaudiobut"><webaudio-switch id="noteon 27" value="0" tooltip="Switch-B" height="64" width="64" src="../knobs/big3.png"></webaudio-switch></div>
<div></div>
<div class="webaudiobut"><webaudio-switch id="trckr/color/0 red" value="1" tooltip="Switch-B" height="64" width="64" src="knobs/red.png"></webaudio-switch></div>
<div class="webaudiobut"><webaudio-switch id="trckr/color/0 yellow" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/yellow.png"></webaudio-switch></div>
<div class="webaudiobut"><webaudio-switch id="trckr/color/0 green" value="0" tooltip="Switch-B" height="64" width="64" src="knobs/green.png"></webaudio-switch></div>
<div></div>
</div>
</div>
<!--
Webcam Rack
-->
<div class="content" style="background-image: linear-gradient(174deg, #111,#030303);">
<video id="videoel" class="webaudiobut" width="400" height="300" preload="auto" loop playsinline autoplay>
</video>
<canvas id="overlay" width="400" height="300"></canvas>
<input class="btn" type="button" value="wait" style="margin-left: 150px;" disabled="disabled" onclick="startVideo()" id="startbutton"></input>
</div>
<!--
Big Display Rack
-->
<div class="content">
<div id="text" class="busled" style="font-size:1.5em;border : #242424 1px solid;background: #000;-webkit-box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72);-moz-box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72);box-shadow: 4px 6px 10px -1px rgba(0,0,0,0.72);">
<div id="gum" class="gum">
<p>To try it out:
<ol>
<li>Allow the page to use your webcamera</li>
<li>Make sure that your face is clearly visible in the video, and click start</li>
<li>See the model fitted to your face</li>
<ol>
</p>
</div>
<div id="nogum" class="nogum">
</div>
</div>
</div>
</div>
<!--
JS
-->
<script>
var vid = document.getElementById('videoel');
var vid_width = vid.width;
var vid_height = vid.height;
var overlay = document.getElementById('overlay');
var overlayCC = overlay.getContext('2d');
/*********** Setup of video/webcam and checking for webGL support *********/
function enablestart() {
var startbutton = document.getElementById('startbutton');
startbutton.value = "start";
startbutton.disabled = null;
}
var insertAltVideo = function(video) {
// insert alternate video if getUserMedia not available
if (supports_video()) {
if (supports_webm_video()) {
video.src = "./media/cap12_edit.webm";
} else if (supports_h264_baseline_video()) {
video.src = "./media/cap12_edit.mp4";
} else {
return false;
}
return true;
} else return false;
}
function adjustVideoProportions() {
// resize overlay and video if proportions of video are not 4:3
// keep same height, just change width
var proportion = vid.videoWidth/vid.videoHeight;
vid_width = Math.round(vid_height * proportion);
vid.width = vid_width;
overlay.width = vid_width;
}
function gumSuccess( stream ) {
// add camera stream if getUserMedia succeeded
if ("srcObject" in vid) {
vid.srcObject = stream;
} else {
vid.src = (window.URL && window.URL.createObjectURL(stream));
}
vid.onloadedmetadata = function() {
adjustVideoProportions();
vid.play();
}
vid.onresize = function() {
adjustVideoProportions();
if (trackingStarted) {
ctrack.stop();
ctrack.reset();
ctrack.start(vid);
}
}
}
function gumFail() {
// fall back to video if getUserMedia failed
insertAltVideo(vid);
document.getElementById('gum').className = "hide";
document.getElementById('nogum').className = "nohide";
}
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
window.URL = window.URL || window.webkitURL || window.msURL || window.mozURL;
// set up video
if (navigator.mediaDevices) {
navigator.mediaDevices.getUserMedia({video : true}).then(gumSuccess).catch(gumFail);
} else if (navigator.getUserMedia) {
navigator.getUserMedia({video : true}, gumSuccess, gumFail);
} else {
insertAltVideo(vid);
document.getElementById('gum').className = "hide";
document.getElementById('nogum').className = "nohide";
alert("Your browser does not seem to support getUserMedia, using a fallback video instead.");
}
vid.addEventListener('canplay', enablestart, false);
/*********** Code for face tracking *********/
var ctrack = new clm.tracker();
ctrack.init();
var trackingStarted = false;
var counter = 0;
var layer = 0;
function startVideo() {
// start video
vid.play();
// start tracking
ctrack.start(vid);
trackingStarted = true;
// start loop to draw face
drawLoop();
}
function drawLoop() {
requestAnimFrame(drawLoop);
overlayCC.clearRect(0, 0, vid_width, vid_height);
//psrElement.innerHTML = "score :" + ctrack.getScore().toFixed(4);
var positions = ctrack.getCurrentPosition();
// do something with the positions ...
// print the positions
var positionString = "";
var positionFace = 'trckr/frame '+layer+" "+counter+" ";
if (positions) {
ctrack.draw(overlay);
for (var p = 0;p < 71;p++) {
positionString += "featurepoint "+p+" : ["+positions[p][0].toFixed(2)+","+positions[p][1].toFixed(2)+"]<br/>";
positionFace += positions[p][0].toFixed(2)+" "+positions[p][1].toFixed(2)+" ";
}
//document.getElementById('positions').innerHTML = positionString;
_WS.s.send(positionFace);
counter +=1;
}
}
/*********** Code for stats **********/
stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
document.getElementById('container').appendChild( stats.domElement );
// update stats on every iteration
document.addEventListener('clmtrackrIteration', function(event) {
stats.update();
}, false);
</script>
<!-- LJ style WS : A nettoyer ! -->
<script type="text/javascript">
var LJ = 'ws://192.168.2.43:9001/'
var _WS = {
uri: LJ,
ws: null,
init : function (e) {
_WS.s = new WebSocket(_WS.uri);
_WS.s.onopen = function (e) { _WS.onOpen(e); };
_WS.s.onclose = function (e) { _WS.onClose(e); };
_WS.s.onmessage = function (e) { _WS.onMessage(e); };
_WS.s.onerror = function (e) { _WS.onError(e); };
},
onOpen: function () {
_WS.showstatus("Connected to "+LJ);
document.getElementById("on").value = 1;
},
onClose: function () {
_WS.showline1('<span style="color: red;">LJ DISCONNECTED</span> ');
},
onMessage: function (e) {
var res = e.data.split(" ");
//console.log(e.data)
//console.log(res[0].substring(0,6))
//console.log(res)
//console.log(res[0].slice(1))
var divtext = document.getElementById('status');
var divtextp = document.getElementById('players');
switch (res[0].substring(0,6)) {
case "/statu":
if (res[2]==="Disconnected"){
_WS.showstatus(res[1]+" "+'<span style="color: red;">'+ res[2]+'</span> ');
}
else{
_WS.showstatus(res[1]+" "+res[2]);
}
break;
case "/redst":
//console.log("red"+res[1]+" "+res[2]);
_WS.showstatus('<span style="color: red;">'+res[1]+" "+ res[2]+'</span> ');
break;
case "/line1":
//divtext.innerHTML="connected to "+LJ;
divtext1.innerHTML=res[1]+" "+res[2];
break;
case "/redline1":
//divtext.innerHTML="connected to "+LJ;
divtext1.innerHTML='<span style="color: red;">'+ res[1]+" "+res[2]+'</span>';
break;
case "/laser":
console.log("/laser "+res[1])
newlaser(res[1])
break;
case "/lack/":
console.log("/lack "+res[1])
document.getElementById(res[0].slice(1)).value = res[1];
break;
case "/lstt/":
console.log("/lstt "+res[1])
document.getElementById(res[0].slice(1)).value = res[1];
break;
default:
//console.log("test "+res[0].slice(1)+" "+res[1]);
document.getElementById(res[0].slice(1)).value = res[1];
//_WS.showstatus(e.data);
}
},
showline1: function (message) {
var divtext = document.getElementById('line1');
divtext.innerHTML="";
divtext.innerHTML= message.toString();
},
onError: function (e) {
_WS.showstatus('<span style="color: red;">ERROR:</span> ' + e.data);
},
showin: function (message) {
var divtext = document.getElementById('status');
divtext.innerHTML="";
divtext.innerHTML= message.toString();
},
showout: function (message) {
var divtext = document.getElementById('status');
divtext.innerHTML="";
divtext.innerHTML= message.toString();
},
showstatus: function (message) {
var divtext = document.getElementById('status');
divtext.innerHTML="";
divtext.innerHTML= message.toString();
},
send: function (message) {
if (!message.length) {
alert('Empty message not allowed !');
} else {
_WS.showstatus(message);
_WS.s.send(message);
}
},
close: function () {
_WS.showstatus('GOODBYE !');
_WS.s.close();
}
};
window.addEventListener('load', _WS.init, false);
//
// Forms submits
//
function onSubmit(clicked_id) {
var input = document.getElementById(clicked_id);
console.log("/" + clicked_id + " " + input.value);
_WS.send("/" + clicked_id + " " + input.value);
}
</script>
<!--
web audio encoders 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 newlaser(id) {
console.log("newlaser " +id)
var laserid = 24+ parseInt(id,10);
laser = "noteon "+laserid;
console.log("laser "+laser);
nolaser();
nofx();
var x = document.getElementById(laser);
x.value = 1 ;
}
function nolaser() {
//console.log("nolaser")
var x = document.getElementById("noteon 24");
x.value = 0 ;
var x = document.getElementById("noteon 25");
x.value = 0 ;
var x = document.getElementById("noteon 26");
x.value = 0 ;
var x = document.getElementById("noteon 27");
x.value = 0 ;
}
// RGB Colors
function nocolor() {
//console.log("nocolor0")
var x = document.getElementById("trckr/color/ red");
x.value = 0 ;
var x = document.getElementById("trckr/color/ yellow");
x.value = 0 ;
var x = document.getElementById("trckr/color/ green");
x.value = 0 ;
var x = document.getElementById("trckr/color/ blue");
x.value = 0 ;
var x = document.getElementById("trckr/color/ cyan");
x.value = 0 ;
var x = document.getElementById("trckr/color/ white");
x.value = 0 ;
}
// RGY Colors
//function nocolor() {
//var x = document.getElementById("trckr/color/ red");
// x.value = 0 ;
//var x = document.getElementById("trckr/color/ yellow");
// x.value = 0 ;
//var x = document.getElementById("trckr/color/ green");
// x.value = 0 ;
//}
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/>";
}
_WS.send("/" + e.target.id + " " + e.target.value);
var res = e.target.id.split(" ");
// on off
if (e.target.id === "on" && e.type === "change") {
window.location.reload();
}
// Go to index
if (e.target.id === "index" && e.type === "change") {
window.location.assign("../index.html");
}
// Fx
if (res[0].substring(7,9) === "fx" && e.type === "change") {
var layer = res[0].substring(10,12);
nofx0();
var x = document.getElementById(e.target.id);
x.value = 1 ;
_WS.showstatus(e.target.id);
}
// Colors
if (res[0].substring(7,9) === "co" && e.type === "change") {
nocolor();
_WS.send("/"+res[0]+laser+ " "+ res[1]+ " " + e.target.value);
var x = document.getElementById(e.target.id);
x.value = 1 ;
//_WS.showstatus("Laser "+laser+ " "+ res[1]);
console.log("colors sending "+res[0]+laser+ " "+ res[1]+ " " + e.target.value);
}
// Lasers
if (res[0] === "noteon" && e.type === "change") {
//console.log(e.target.id);
//console.log(res);
//console.log(res[1] - 24)
newlaser(res[1] - 24);
_WS.send("/" + e.target.id + " " + e.target.value);
//nolaser();
//nofx();
//_WS.send("/" + e.target.id + " " + e.target.value);
//var x = document.getElementById(e.target.id);
//x.value = 1 ;
//laser = res[1] - 24;
//console.log("laser "+laser);
}
</script>
</body>
</html>

View File

@ -93,10 +93,10 @@
</div> </div>
</a> </a>
<a href="../settings.html"> <a href="../align.html">
<div class="webaudiobut"> <div class="webaudiobut">
<div align="center" class="navled"> <div align="center" class="navled">
Settings Align
</div> </div>
</div> </div>
</a> </a>
@ -127,8 +127,8 @@
<div class="webaudiobut"> <div class="webaudiobut">
<button type="button" class="navled" style="border : #222222 1px;" onclick="onSubmit(this.id)" id="settings/reset" > <button type="button" class="navled" style="border : #222222 1px;" onclick="onSubmit(this.id)" id="settings/restart lj" >
Reset rstrt LJ
</button> </button>
</div> </div>