forked from protonphoton/LJ
Compare commits
24 Commits
74ba0e828b
...
f3314441d3
Author | SHA1 | Date | |
---|---|---|---|
f3314441d3 | |||
8164320694 | |||
|
5f7c61f616 | ||
|
31e4e66408 | ||
|
50b3806825 | ||
|
2f54d37856 | ||
|
1e43a5fc43 | ||
|
8e9cd509ab | ||
|
df068b8e30 | ||
|
0b7ad2d75b | ||
|
b2cc1b1ff5 | ||
18aaa1b625 | |||
e3b1b255a3 | |||
|
8fbaaa7880 | ||
|
3b0d44deb1 | ||
|
bfae3baa37 | ||
|
b7851f518d | ||
|
a89cf3d414 | ||
|
be60f25b16 | ||
|
eadc8ca19d | ||
|
aef92762b5 | ||
|
93cbcfefd5 | ||
|
a06e3ba07e | ||
|
b0c28e1510 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,5 @@
|
||||
.*sw*
|
||||
*__pycache__
|
||||
www/config.js
|
||||
|
||||
|
||||
|
55
LJ.conf
55
LJ.conf
@ -1,8 +1,8 @@
|
||||
[General]
|
||||
lasernumber = 4
|
||||
debug = 0
|
||||
lasernumber = 1
|
||||
debug = 1
|
||||
ljayserverip = 0.0.0.0
|
||||
wwwip = 192.168.2.44
|
||||
wwwip = 127.0.0.1
|
||||
nozoscip = 127.0.0.1
|
||||
bhoroscip = 127.0.0.1
|
||||
autostart = artnet
|
||||
@ -12,7 +12,7 @@ wsport = 9001
|
||||
[laser0]
|
||||
color = -1
|
||||
type = DS1000
|
||||
ip = 192.168.2.3
|
||||
ip = 127.0.0.1
|
||||
kpps = 25000
|
||||
centerx = 0
|
||||
centery = 0
|
||||
@ -21,7 +21,7 @@ zoomy = 50.0
|
||||
sizex = 32000
|
||||
sizey = 32000
|
||||
finangle = 0.0
|
||||
swapx = -1
|
||||
swapx = 1
|
||||
swapy = -1
|
||||
lsteps = [ (1.0, 8),(0.25, 3), (0.75, 3), (1.0, 10)]
|
||||
warpdest = [[-1500., 1500.],
|
||||
@ -36,8 +36,8 @@ ip = 192.168.2.5
|
||||
kpps = 25000
|
||||
centerx = 0
|
||||
centery = 0
|
||||
zoomx = 80.0
|
||||
zoomy = 80.0
|
||||
zoomx = 50.0
|
||||
zoomy = 50.0
|
||||
sizex = 32000
|
||||
sizey = 32000
|
||||
finangle = 0.0
|
||||
@ -45,9 +45,9 @@ 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.]]
|
||||
[ 1500., 1500.],
|
||||
[ 1500.,-1500.],
|
||||
[-1500.,-1500.]]
|
||||
|
||||
[laser2]
|
||||
color = -1
|
||||
@ -65,14 +65,14 @@ 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.]]
|
||||
[ 1500., 1500.],
|
||||
[ 1500.,-1500.],
|
||||
[-1500.,-1500.]]
|
||||
|
||||
[laser3]
|
||||
color = -1
|
||||
type = LUKE400
|
||||
ip = 192.168.2.4
|
||||
ip = 192.168.1.5
|
||||
kpps = 25000
|
||||
centerx = 0
|
||||
centery = 0
|
||||
@ -81,34 +81,19 @@ zoomy = 50.0
|
||||
sizex = 32000
|
||||
sizey = 32000
|
||||
finangle = 0.0
|
||||
swapx = 1
|
||||
swapy = 1
|
||||
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.]]
|
||||
[ 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}
|
||||
"custom1": {"OSC": 8014, "command": "python3 plugins/custom1.py", "display": True}
|
||||
}
|
||||
|
||||
|
114
LJ_template.conf
114
LJ_template.conf
@ -1,114 +0,0 @@
|
||||
[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
Normal file
BIN
Pd/.DS_Store
vendored
Normal file
Binary file not shown.
23
Pd/LJsender.pd
Normal file
23
Pd/LJsender.pd
Normal file
@ -0,0 +1,23 @@
|
||||
#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;
|
106
Pd/ljpd.py
Normal file
106
Pd/ljpd.py
Normal file
@ -0,0 +1,106 @@
|
||||
#!/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
147
README.md
@ -1,4 +1,4 @@
|
||||
LJ v0.8.2
|
||||
LJ v0.8.2 'fireandforget'
|
||||
|
||||
By Sam Neurohack, Loloster, Cocoa
|
||||
|
||||
@ -7,19 +7,104 @@ LICENCE : CC BY
|
||||
|
||||
![LJ](https://www.teamlaser.fr/lj/images/lj2.png)
|
||||
|
||||
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, ...
|
||||
|
||||
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.
|
||||
|
||||
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 :
|
||||
|
||||
- "Plugins" are points generators (to one or more lasers). Lot examples comes with LJ : planetarium, 3D anaglyph animations,... See plugins directory.
|
||||
- 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.
|
||||
- A "tracer" per etherdream/laser that take its given point list, correct geometry, recompute in laser controller coordinates, send it to its controller and report its status to the "manager".
|
||||
- A "manager" that talk to all tracers (which client number point lists to draw, new geometry correction,...), handle IOs (webui functions, OSC commands,...) and plugins.
|
||||
- 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 !!
|
||||
- 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.
|
||||
- A "manager" that talk to all tracers (which 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".
|
||||
- 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.
|
||||
|
||||
"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,...
|
||||
|
||||
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.
|
||||
#
|
||||
@ -41,33 +126,6 @@ Important : for best performance LJ is meant to run in a dedicated computer espe
|
||||
- Plugins list auto start, see line in LJ.conf : autostart = artnet
|
||||
- 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.
|
||||
|
||||
|
||||
|
||||
#
|
||||
@ -93,7 +151,8 @@ type all install.sh commands beginning line 4. An OS X install script soon !!
|
||||
- KVM :
|
||||
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.
|
||||
|
||||
@ -161,6 +220,8 @@ node nodeclient.js
|
||||
redis-cli -h redisserverIP monitor
|
||||
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Plugin
|
||||
#
|
||||
@ -262,7 +323,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.
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
#
|
||||
# Todo
|
||||
@ -280,6 +341,8 @@ To use this visualiser as one of LJ's lasers, in LJ.conf edit one of line ip = s
|
||||
#
|
||||
|
||||
|
||||
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.
|
||||
|
||||
Our "always working solution", as we regularly move our gear for different venues :
|
||||
@ -299,8 +362,6 @@ By default LJ uses on 127.0.0.1 (localhost) :
|
||||
- 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,...
|
||||
|
||||
#
|
||||
@ -320,7 +381,7 @@ For glitching experience you can change resampling strategy live with "resampler
|
||||
# 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 = 65535.
|
||||
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
|
||||
|
||||
#
|
||||
# Ether dream DAC
|
||||
@ -384,7 +445,9 @@ 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).
|
||||
|
||||
- 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.
|
||||
- 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.
|
||||
|
||||
"Bad points" ?
|
||||
|
||||
@ -394,7 +457,7 @@ python3 talk3.py -i etherdreamIP
|
||||
|
||||
*Don't kill your scanners : becareful with kpps setting.*
|
||||
|
||||
|
||||
The reset button copy the LJ_template.conf to LJ.conf.
|
||||
|
||||
#
|
||||
# LJ commands reference
|
||||
@ -444,8 +507,6 @@ 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
|
||||
|
||||
/regen : regen webui index html page.
|
||||
|
||||
/scim : change webui simulated laser.
|
||||
|
||||
|
||||
|
8
clitools/exports/toRedis.py
Executable file → Normal file
8
clitools/exports/toRedis.py
Executable file → Normal file
@ -8,11 +8,11 @@
|
||||
redis exporter
|
||||
v0.1.0
|
||||
|
||||
A basic exporter
|
||||
A basic exporter
|
||||
|
||||
LICENCE : CC
|
||||
|
||||
by cocoa
|
||||
by cocoa
|
||||
|
||||
|
||||
'''
|
||||
@ -21,7 +21,7 @@ import sys
|
||||
import os
|
||||
import argparse
|
||||
import redis
|
||||
import time
|
||||
import time
|
||||
|
||||
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)
|
||||
@ -47,12 +47,14 @@ try:
|
||||
line = sys.stdin.readline()
|
||||
if line == "":
|
||||
time.sleep(0.01)
|
||||
continue
|
||||
line = line.rstrip('\n')
|
||||
line=line[1:-1]
|
||||
line = line.replace("[",'(')
|
||||
line = line.replace("]",')')
|
||||
line = "[{}]".format(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
|
||||
if r.set(key,line)==True:
|
||||
debug("exports::redis set("+str(key)+") to "+line)
|
||||
|
84
clitools/exports/toUDP.py
Normal file
84
clitools/exports/toUDP.py
Normal file
@ -0,0 +1,84 @@
|
||||
#!/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
|
||||
|
@ -66,9 +66,9 @@ red = (41,24,24)
|
||||
white = (95,95,95)
|
||||
blue = (0,41,64)
|
||||
|
||||
red = (255,0,0)
|
||||
blue = (0,255,255)
|
||||
white = (255,255,255)
|
||||
red = (127,0,0)
|
||||
blue = (0,128,128)
|
||||
white = (128,128,128)
|
||||
def anaglyph( pl ):
|
||||
|
||||
debug(name,'--------------- new loop ------------------')
|
||||
@ -174,7 +174,6 @@ def anaglyph( pl ):
|
||||
debug(name,"whiteList:{}".format(out1))
|
||||
debug(name,"blueList:{}".format(out2))
|
||||
debug(name,"redList:{}".format(out3))
|
||||
return out3 + out2
|
||||
return out1 + out3 + out2
|
||||
#return out1 + out2 + out3
|
||||
|
||||
|
@ -72,7 +72,8 @@ def cycleColor( pl ):
|
||||
|
||||
debug(name,"currentColor:{}".format(currentColor))
|
||||
for i in range( 0, len(pl)):
|
||||
pl[i][2] = rgb2int( currentColor)
|
||||
if pl[i][2] != 0:
|
||||
pl[i][2] = rgb2int( currentColor)
|
||||
|
||||
# change the composant if target reached
|
||||
if value <= target and currentDirection == DOWN or value >= target and currentDirection == UP :
|
||||
|
@ -162,7 +162,7 @@ try:
|
||||
pointsList = ast.literal_eval(line)
|
||||
# Do the filter
|
||||
result = kaleidoscope( pointsList )
|
||||
print( result, flush=True )
|
||||
if len(result) : print( result, flush=True )
|
||||
looptime = time.time() - start
|
||||
# debug(name+" looptime:"+str(looptime))
|
||||
if( looptime < optimal_looptime ):
|
||||
|
188
clitools/filters/redilysis_colors.py
Executable file
188
clitools/filters/redilysis_colors.py
Executable file
@ -0,0 +1,188 @@
|
||||
#!/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
|
||||
|
2873
clitools/generators/OSC3.py
Normal file
2873
clitools/generators/OSC3.py
Normal file
File diff suppressed because it is too large
Load Diff
53
clitools/generators/blank.py
Executable file
53
clitools/generators/blank.py
Executable file
@ -0,0 +1,53 @@
|
||||
#!/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))
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
'''
|
||||
|
||||
This generator print different engle form 0 to 180 degres
|
||||
This generator print different angle form 0 to 180 degres
|
||||
|
||||
v0.1.0
|
||||
|
||||
@ -43,11 +43,13 @@ debug(name+" optimal looptime "+str(optimal_looptime))
|
||||
width = 800
|
||||
height = 800
|
||||
|
||||
white = 0xFFFF
|
||||
white = 0xFFFFFF
|
||||
blank = 0
|
||||
|
||||
radius = 70
|
||||
offset_circles = 12
|
||||
radius = 100
|
||||
offset_circles = 10
|
||||
beg_angle = 0
|
||||
end_angle = 90
|
||||
offset_angle = 10
|
||||
|
||||
angles_lines = []
|
||||
@ -58,7 +60,7 @@ def set_angles_lines():
|
||||
spacing_betwen = 2 * radius + offset_circles
|
||||
circles_per_line = math.floor((width - margin) / spacing_betwen)
|
||||
|
||||
for ang in range(0, 180 + offset_angle, offset_angle):
|
||||
for ang in range(beg_angle, end_angle + offset_angle, offset_angle):
|
||||
nb = int(ang / offset_angle)
|
||||
cx = margin + (nb % circles_per_line) * spacing_betwen
|
||||
cy = margin + int(nb / circles_per_line) * spacing_betwen
|
||||
@ -67,16 +69,18 @@ def set_angles_lines():
|
||||
py = radius * math.sin(math.radians(ang))
|
||||
|
||||
# line up
|
||||
angles_lines.append([-px + cx, py + cy, blank])
|
||||
angles_lines.append([-px + cx, py + cy, white])
|
||||
angles_lines.append([ cx, cy, white])
|
||||
angles_lines.append([ cx, 2 + 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
|
||||
angles_lines.append([-px + cx, -py + cy, blank])
|
||||
angles_lines.append([-px + cx, -py + cy, white])
|
||||
angles_lines.append([ cx, cy, white])
|
||||
angles_lines.append([ cx, -2 + 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()
|
||||
|
117
clitools/generators/drawingTests/conected_component.py
Normal file
117
clitools/generators/drawingTests/conected_component.py
Normal file
@ -0,0 +1,117 @@
|
||||
#!/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))
|
||||
|
84
clitools/generators/drawingTests/order_optimization.py
Normal file
84
clitools/generators/drawingTests/order_optimization.py
Normal file
@ -0,0 +1,84 @@
|
||||
#!/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))
|
||||
|
@ -12,7 +12,7 @@ Use it to test your filters and outputs
|
||||
|
||||
LICENCE : CC
|
||||
|
||||
by cocoa
|
||||
by cocoa
|
||||
|
||||
'''
|
||||
|
||||
@ -28,17 +28,17 @@ def debug(*args, **kwargs):
|
||||
return
|
||||
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("-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()
|
||||
args = argsparser.parse_args()
|
||||
|
||||
fps=args.fps
|
||||
verbose=args.verbose
|
||||
optimal_looptime = 1 / fps
|
||||
debug(name+" optimal looptime "+str(optimal_looptime))
|
||||
color = 65280
|
||||
color = 16777215
|
||||
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 =[]
|
||||
for i in range(00,800,int(800/120)):
|
||||
@ -71,7 +71,7 @@ mire = [
|
||||
[400,450,color],
|
||||
]
|
||||
|
||||
shape = mire
|
||||
shape = mire
|
||||
|
||||
|
||||
while True:
|
||||
@ -81,5 +81,5 @@ while True:
|
||||
if( looptime < optimal_looptime ):
|
||||
time.sleep( optimal_looptime - looptime)
|
||||
debug(name+" micro sleep:"+str( optimal_looptime - looptime))
|
||||
|
||||
|
||||
|
||||
|
126
clitools/generators/fromOSC.py
Normal file
126
clitools/generators/fromOSC.py
Normal file
@ -0,0 +1,126 @@
|
||||
#!/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()
|
||||
|
72
clitools/generators/fromRedis.py
Executable file
72
clitools/generators/fromRedis.py
Executable file
@ -0,0 +1,72 @@
|
||||
#!/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))
|
||||
|
84
clitools/generators/fromUDP.py
Normal file
84
clitools/generators/fromUDP.py
Normal file
@ -0,0 +1,84 @@
|
||||
#!/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()
|
||||
|
||||
|
||||
|
||||
|
||||
|
288
clitools/generators/redilysis_particles.py
Executable file
288
clitools/generators/redilysis_particles.py
Executable file
@ -0,0 +1,288 @@
|
||||
#!/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
|
@ -12,7 +12,7 @@ Use it to test your filters and outputs
|
||||
|
||||
LICENCE : CC
|
||||
|
||||
by cocoa
|
||||
by cocoa
|
||||
|
||||
'''
|
||||
|
||||
@ -52,7 +52,7 @@ randomize = args.randomize
|
||||
speed = args.speed
|
||||
verbose = args.verbose
|
||||
|
||||
origSpeed = speed
|
||||
origSpeed = speed
|
||||
optimal_looptime = 1 / fps
|
||||
square = [
|
||||
[-1,1],
|
||||
@ -62,14 +62,32 @@ square = [
|
||||
[-1,1]
|
||||
]
|
||||
|
||||
shape = square
|
||||
circle = [[1,0],
|
||||
[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]
|
||||
centerVector= [0,0]
|
||||
# tweak random basis
|
||||
if randomize % 2 == 1:
|
||||
randomize += 1
|
||||
debug(name,"randomize:{}".format(randomize))
|
||||
centerRand = int(math.sqrt(randomize) / 4 ) + 1
|
||||
centerRand = int(math.sqrt(randomize) / 4 ) + 1
|
||||
debug( name, "centerRand:{}".format(centerRand ) )
|
||||
class polylineGenerator( object ):
|
||||
|
||||
@ -103,10 +121,10 @@ class polylineGenerator( object ):
|
||||
min_size = 9999
|
||||
delList = []
|
||||
if randomize :
|
||||
# Change the vector
|
||||
# Change the vector
|
||||
centerVector[0] += 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:
|
||||
centerVector[0] = 0
|
||||
if currentCenter[1] + centerVector[1] >= centerY + randomize or currentCenter[1] +centerVector[1] <= centerY - randomize:
|
||||
@ -115,19 +133,19 @@ class polylineGenerator( object ):
|
||||
currentCenter[1] += centerVector[1]
|
||||
# Change speed
|
||||
speed += int( random.randrange( int(-origSpeed),origSpeed ) )
|
||||
if speed < origSpeed :
|
||||
if speed < origSpeed :
|
||||
speed = origSpeed
|
||||
elif speed > (origSpeed + randomize / 2) :
|
||||
speed = origSpeed + randomize / 2
|
||||
speed = origSpeed + randomize / 2
|
||||
#debug(name, "currentCenter:{} speed:{}".format(currentCenter,speed))
|
||||
|
||||
for i, shapeInfo in enumerate(self.polylineList):
|
||||
size = shapeInfo[0]
|
||||
# Augment speed with size
|
||||
# Augment speed with size
|
||||
"""
|
||||
size = 0 : += sqrt(speed)
|
||||
size = half max size : +=speed
|
||||
|
||||
|
||||
"""
|
||||
if size < max_size / 4:
|
||||
size += math.pow(speed, 0.1)
|
||||
@ -143,7 +161,7 @@ class polylineGenerator( object ):
|
||||
for i in delList:
|
||||
del self.polylineList[i]
|
||||
#debug(name, "polyline:",self.polylineList)
|
||||
if min_size >= interval:
|
||||
if min_size >= interval:
|
||||
debug(name, "new shape")
|
||||
self.polylineList.append([0,[currentCenter[0],currentCenter[1]]])
|
||||
|
||||
@ -172,5 +190,5 @@ while True:
|
||||
if( looptime < optimal_looptime ):
|
||||
time.sleep( optimal_looptime - looptime)
|
||||
#debug(name+" micro sleep:"+str( optimal_looptime - looptime))
|
||||
|
||||
|
||||
|
||||
|
@ -10,6 +10,16 @@ import json
|
||||
from pathlib import Path
|
||||
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:
|
||||
HL = '\033[31m'
|
||||
OKBLUE = '\033[94m'
|
||||
@ -37,12 +47,12 @@ def intkey():
|
||||
except ValueError:
|
||||
print("Error.")
|
||||
|
||||
current_id=0
|
||||
current_cmd=""
|
||||
process = None
|
||||
current_filename = ""
|
||||
currentPlayList = []
|
||||
playlistsDir = Path("./playlists")
|
||||
current_id = 0
|
||||
current_cmd = ""
|
||||
process = None
|
||||
current_filename = ""
|
||||
currentPlayList = []
|
||||
playlistsDir = Path("./playlists")
|
||||
if not playlistsDir.is_dir() : playlistsDir.mkdir()
|
||||
|
||||
def ask(q):
|
||||
@ -105,10 +115,12 @@ def action_changeCommand( inc ):
|
||||
return True
|
||||
|
||||
def action_match( k ):
|
||||
global current_id, currentPlayList
|
||||
if int(k) > (len(currentPlayList) - 1):
|
||||
print( bcolors.HL + "This key does not exist" + bcolors.ENDC )
|
||||
return False
|
||||
else :
|
||||
_ok("Changed action id to {}.".format(k))
|
||||
current_id = int(k)
|
||||
|
||||
def action_runCommand():
|
||||
@ -155,7 +167,7 @@ def action_deleteCommand():
|
||||
action_listAll()
|
||||
key = int(input())
|
||||
# Exit early
|
||||
if "x" == k:
|
||||
if "x" == key:
|
||||
return(False)
|
||||
del currentPlayList[key]
|
||||
return True
|
||||
@ -163,7 +175,7 @@ def action_deleteCommand():
|
||||
|
||||
|
||||
def action_listAll():
|
||||
global currentPlayList, current_cmd
|
||||
global currentPlayList, current_cmd, current_id
|
||||
print("\n--------------------------------------")
|
||||
for i,seq in enumerate(currentPlayList):
|
||||
pre=""
|
||||
@ -232,7 +244,7 @@ def action_loadPlaylist():
|
||||
print( bcolors.HL + "This key '{}' is not valid".format(k) + bcolors.ENDC )
|
||||
return False
|
||||
|
||||
# Load file
|
||||
# @todo replace with _loadPlaylist
|
||||
playlistFile = Path("./playlists/"+file_list[k].name)
|
||||
currentPlayList = json.loads(playlistFile.read_text())
|
||||
current_playlist_name = file_list[k].name
|
||||
@ -242,7 +254,18 @@ 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))
|
||||
|
||||
|
||||
|
||||
@ -353,13 +376,4 @@ def action_quit():
|
||||
quit = inkey()
|
||||
if quit != "n":
|
||||
_kill(process)
|
||||
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"
|
||||
}
|
||||
sys.exit(1)
|
91
clitools/runner_midi.py
Normal file → Executable file
91
clitools/runner_midi.py
Normal file → Executable file
@ -1,12 +1,87 @@
|
||||
#!/usr/bin/python3
|
||||
|
||||
import sys
|
||||
import os
|
||||
import signal
|
||||
import subprocess
|
||||
import time
|
||||
import tty,termios
|
||||
import argparse
|
||||
import re
|
||||
import json
|
||||
from pathlib import Path
|
||||
import redis
|
||||
import runner_lib as runner
|
||||
import time
|
||||
|
||||
novationRows = [
|
||||
[ 0, 1, 2, 3, 4, 5, 6, 7 ],
|
||||
[ *range(16,24)],
|
||||
[ *range(32,40)],
|
||||
[ *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)
|
||||
|
22
ethertools/watchLJ.py
Normal file
22
ethertools/watchLJ.py
Normal file
@ -0,0 +1,22 @@
|
||||
#!/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()
|
@ -70,12 +70,9 @@ def OSCframe():
|
||||
oscserver.handle_request()
|
||||
|
||||
|
||||
|
||||
|
||||
# OSC server Thread : handler, dacs reports and simulator points sender to UI.
|
||||
def osc_thread():
|
||||
|
||||
|
||||
#print("osc Thread launched")
|
||||
try:
|
||||
while True:
|
||||
@ -92,8 +89,6 @@ def osc_thread():
|
||||
print("\n")
|
||||
|
||||
|
||||
|
||||
|
||||
# Properly close the system. Todo
|
||||
def Stop():
|
||||
oscserver.close()
|
||||
|
@ -398,6 +398,16 @@ def handler(oscpath, args):
|
||||
print()
|
||||
DAChecks()
|
||||
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":
|
||||
print()
|
||||
@ -597,7 +607,7 @@ def UpdateAllwww():
|
||||
Updatepage(gstt.ljpath+"/www/LJ.js")
|
||||
Updatepage(gstt.ljpath+"/www/trckr/trckrcam1.html")
|
||||
Updatepage(gstt.ljpath+"/www/simu.html")
|
||||
Updatepage(gstt.ljpath+"/www/align.html")
|
||||
Updatepage(gstt.ljpath+"/www/settings.html")
|
||||
Updatepage(gstt.ljpath+"/www/auralls.html")
|
||||
Updatepage(gstt.ljpath+"/www/index.html")
|
||||
|
||||
|
@ -1012,8 +1012,4 @@ 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)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
93
libs3/plotOptimizer.py
Normal file
93
libs3/plotOptimizer.py
Normal file
@ -0,0 +1,93 @@
|
||||
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)
|
@ -15,7 +15,7 @@ from libs3 import gstt
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from socket import *
|
||||
|
||||
def Init(wserver):
|
||||
global WSserver
|
||||
@ -177,6 +177,14 @@ def OSCsend(name, oscaddress, oscargs =''):
|
||||
#PluginStart(name)
|
||||
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"
|
||||
|
134
libs3/tracer3.py
134
libs3/tracer3.py
@ -23,44 +23,44 @@ This tracer include an enhanced version (support for several lasers) of the ethe
|
||||
|
||||
- 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.
|
||||
the first tuple (1.0,8) is for short line < 4000 in etherdream space
|
||||
(0.25,3),(0.75,3),(1.0,10) for long line > 4000
|
||||
i.e (0.25,3) means go at 25% position on the line, send 3 times this position to etherdream
|
||||
/clientkey "/pl/SceneNumber/" What Scene to retrieve from redis
|
||||
/clientkey "/pl/SceneNumber/" What Scene to retrieve from redis
|
||||
/EDH/lasernumber
|
||||
|
||||
- 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
|
||||
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
|
||||
3 : Draw GRID point list
|
||||
4 : Resampler Change (longs and shorts lsteps)
|
||||
5 : Client Key Change = reread redis key /clientkey
|
||||
6 : Max Intensity Change = reread redis key /intensity
|
||||
7 : kpps change = reread redis key /kpps
|
||||
8 : color balance change = reread redis keys /red /green /blue
|
||||
5 : Client Key Change = reread redis key /clientkey
|
||||
6 : Max Intensity Change = reread redis key /intensity
|
||||
7 : kpps change = reread redis key /kpps
|
||||
8 : color balance change = reread redis keys /red /green /blue
|
||||
|
||||
|
||||
- Managing Etherdream DACs :
|
||||
|
||||
Discrete drawing values
|
||||
|
||||
/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,...)
|
||||
/red 0-100 % of full red, then order 8
|
||||
/green 0-100 % of full green, then order 8
|
||||
/blue 0-100 % of full blue, then order 8
|
||||
/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,...)
|
||||
/red 0-100 % of full red, then order 8
|
||||
/green 0-100 % of full green, then order 8
|
||||
/blue 0-100 % of full blue, then order 8
|
||||
|
||||
DAC status report
|
||||
|
||||
/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)
|
||||
/lack/lasernumber "a": ACK "F": Full "I": invalid. 64 or 35 for no connection.
|
||||
/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)
|
||||
/lack/lasernumber "a": ACK "F": Full "I": invalid. 64 or 35 for no connection.
|
||||
|
||||
|
||||
Geometric corrections
|
||||
@ -81,7 +81,8 @@ import pdb
|
||||
import ast
|
||||
import redis
|
||||
|
||||
from libs3 import homographyp
|
||||
from libs3 import homographyp, plotOptimizer as po
|
||||
|
||||
import numpy as np
|
||||
import binascii
|
||||
|
||||
@ -223,66 +224,39 @@ class DAC(object):
|
||||
|
||||
while True:
|
||||
|
||||
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
|
||||
self.pl = po.optimizer(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]]
|
||||
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))
|
||||
#print("rgb :", rgb)
|
||||
|
||||
#round(*self.intred/100)
|
||||
#round(*self.intgreen/100)
|
||||
#round(*self.intblue/100)
|
||||
|
||||
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
|
||||
yield self.xyrgb
|
||||
##**//# ajout de point pour un tracer adapter
|
||||
##**//delta_x, delta_y = self.xyrgb[0] - self.xyrgb_prev[0], self.xyrgb[1] - self.xyrgb_prev[1]
|
||||
##**//#test adaptation selon longueur ligne
|
||||
##**//if math.hypot(delta_x, delta_y) < 4000:
|
||||
|
||||
else:
|
||||
# For glitch art : decrease lsteps
|
||||
#l_steps = [ (0.25, 3), (0.75, 3), (1.0, 10)]
|
||||
l_steps = gstt.stepslongline
|
||||
print("big line")
|
||||
print(l_steps)
|
||||
##**// # For glitch art : decrease lsteps
|
||||
##**// #l_steps = [ (1.0, 8)]
|
||||
##**// l_steps = gstt.stepshortline
|
||||
|
||||
### print("\n\nl_step:")
|
||||
### print(l_steps)
|
||||
pAdd = 0
|
||||
### *** ###for e in l_steps:
|
||||
### *** ### step = e[0]
|
||||
##**//else:
|
||||
##**// # For glitch art : decrease lsteps
|
||||
##**// #l_steps = [ (0.25, 3), (0.75, 3), (1.0, 10)]
|
||||
##**// l_steps = gstt.stepslongline
|
||||
|
||||
### *** ### for i in range(0,e[1]):
|
||||
### *** ### pAdd +=1
|
||||
##**//for e in l_steps:
|
||||
##**// step = e[0]
|
||||
|
||||
### *** ### 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
|
||||
##**// for i in range(0,e[1]):
|
||||
|
||||
yield (self.xyrgb[0], self.xyrgb[1]) + rgb
|
||||
##**// 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_prev = self.xyrgb
|
||||
print("point added:\t" + str(pAdd))
|
||||
print("\n")
|
||||
##**//self.xyrgb_prev = self.xyrgb
|
||||
|
||||
|
||||
def GetPoints(self, n):
|
||||
@ -358,7 +332,7 @@ class DAC(object):
|
||||
|
||||
# ipconn state is -1 at startup (see gstt) and modified here
|
||||
r.set('/lack/'+str(self.mylaser), self.connstatus)
|
||||
gstt.lstt_ipconn[self.mylaser] = self.connstatus
|
||||
gstt.lstt_ipconn[self.mylaser] = self.connstatus
|
||||
|
||||
self.buf = b''
|
||||
# Upper case PL is the Point List number
|
||||
@ -372,7 +346,7 @@ class DAC(object):
|
||||
if r.get('/EDH/'+str(self.mylaser)) == None:
|
||||
#print("Laser",self.mylaser,"NO EDH !! Computing one...")
|
||||
homographyp.newEDH(self.mylaser)
|
||||
else:
|
||||
else:
|
||||
|
||||
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")
|
||||
@ -470,7 +444,23 @@ class DAC(object):
|
||||
if order == 0:
|
||||
|
||||
# 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))
|
||||
|
||||
else:
|
||||
@ -547,13 +537,13 @@ class DAC(object):
|
||||
time.sleep(0.001)
|
||||
cap += 150
|
||||
|
||||
# print("Writing %d points" % (cap, ))
|
||||
#print("Writing %d points" % (cap, ))
|
||||
#t0 = time.time()
|
||||
#if self.mylaser == 2:
|
||||
# print(points)
|
||||
# print(points)
|
||||
self.write(points)
|
||||
#t1 = time.time()
|
||||
# print("Took %f" % (t1 - t0, )
|
||||
#print("Took %f" % (t1 - t0, )
|
||||
|
||||
if not started:
|
||||
print("Tracer", self.mylaser, "starting with", gstt.kpps[self.mylaser],"kpps")
|
||||
@ -594,7 +584,7 @@ def find_dac():
|
||||
order = r.get('/order')
|
||||
neworder = order & ~(1<< self.mylaser*2)
|
||||
neworder = neworder & ~(1<< 1+ self.mylaser*2)
|
||||
r.set('/order', str(neworder))
|
||||
r.set('/order', str(neworder))
|
||||
else:
|
||||
|
||||
# Laser bit 0 = 1
|
||||
|
29
main.py
29
main.py
@ -36,35 +36,32 @@ print("")
|
||||
import redis
|
||||
import os
|
||||
ljpath = r'%s' % os.getcwd().replace('\\','/')
|
||||
|
||||
|
||||
import sys
|
||||
|
||||
#sys.path.append('libs3/')
|
||||
|
||||
from libs3 import gstt, settings
|
||||
gstt.ljpath= ljpath
|
||||
gstt.ljpath = ljpath
|
||||
|
||||
log.info("Reading " + gstt.ConfigName + " setup file...")
|
||||
settings.Read()
|
||||
|
||||
# Arguments may alter .conf file so import settings first then cli
|
||||
from libs3 import cli
|
||||
|
||||
settings.Write()
|
||||
|
||||
from multiprocessing import Process, set_start_method
|
||||
import random, ast
|
||||
|
||||
from libs3 import plugins
|
||||
|
||||
|
||||
#from libs3 import lasytracer as tracer
|
||||
from libs3 import tracer3 as tracer
|
||||
|
||||
|
||||
from libs3 import homographyp, commands, font1
|
||||
|
||||
#import subprocess
|
||||
|
||||
import os
|
||||
#import midi
|
||||
|
||||
from libs3 import OSC3
|
||||
from websocket_server import WebsocketServer
|
||||
#import socket
|
||||
@ -144,15 +141,17 @@ oscserverIPout = oscserverIP
|
||||
oscserverPORTout = 8001
|
||||
|
||||
|
||||
'''
|
||||
# Nozoid OSC Client : to send OSC message to Nozoid inport 8003
|
||||
NozoscIPout = nozoscIP
|
||||
NozoscPORTout = plugins.Port("nozoid")
|
||||
'''
|
||||
|
||||
|
||||
''''
|
||||
# Planetarium OSC Client : to send OSC message to planetarium inport 8005
|
||||
planetIPout = nozoscIP
|
||||
planetPORTout = plugins.Port("planet")
|
||||
|
||||
'''
|
||||
|
||||
import socket
|
||||
|
||||
@ -265,13 +264,15 @@ def osc_thread():
|
||||
#print("Sending simu frame from",'/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')))
|
||||
if random.randint(0,100)>95:
|
||||
plugins.sendbroadcast()
|
||||
|
||||
|
||||
except Exception as e:
|
||||
import sys, traceback
|
||||
print('\n---------------------')
|
||||
print('Exception: %s' % e)
|
||||
print('- - - - - - - - - - -')
|
||||
print('\n--------------------------')
|
||||
print('OSC Thread Exception: %s' % e)
|
||||
print('- - - - - - - - - - - - - - ')
|
||||
traceback.print_tb(sys.exc_info()[2])
|
||||
print("\n")
|
||||
|
||||
|
@ -181,7 +181,7 @@ log.infog("Aurora v0.1b")
|
||||
OSCinPort = 8090
|
||||
ljscene = 0
|
||||
|
||||
StartFXs = ["anim.Maxwell","anim.Starfield","anim.Starfield", "anim.Word"]
|
||||
StartFXs = ["anim.Starfield","anim.Starfield","anim.Starfield", "anim.Word"]
|
||||
|
||||
# Useful variables init.
|
||||
white = lj.rgb2int(255,255,255)
|
||||
@ -1125,9 +1125,9 @@ def AllFX():
|
||||
dots = eval(LAY['FX']+"(LAY)")
|
||||
if LAY['FX'] != "Zero" or lent(dots) != 0:
|
||||
#print(dots, LAY['color'])
|
||||
for cc in range(15):
|
||||
ccmidi[cc] = int(lj.fromKey("/midi/cc/1/"+str(cc)))
|
||||
#print(ccmidi)
|
||||
#for cc in range(15):
|
||||
# ccmidi[cc] = int(lj.fromKey("/midi/cc/1/"+str(cc)))
|
||||
# #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'] - (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:
|
||||
|
937
www/align.html
937
www/align.html
@ -1,937 +0,0 @@
|
||||
<!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"> </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>
|
@ -59,10 +59,10 @@
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a href="align.html">
|
||||
<a href="settings.html">
|
||||
<div class="webaudiobut">
|
||||
<div align="center" class="navled">
|
||||
Align
|
||||
Settings
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
@ -93,8 +93,8 @@
|
||||
|
||||
|
||||
<div class="webaudiobut">
|
||||
<button type="button" class="navled" style="border : #222222 1px;" onclick="onSubmit(this.id)" id="settings/restart lj" >
|
||||
rstrt LJ
|
||||
<button type="button" class="navled" style="border : #222222 1px;" onclick="onSubmit(this.id)" id="settings/reset" >
|
||||
Reset
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
@ -101,15 +101,15 @@
|
||||
|
||||
|
||||
<!--
|
||||
Align Rack
|
||||
Settings Rack
|
||||
-->
|
||||
|
||||
<a href="align.html">
|
||||
<a href="settings.html">
|
||||
<div class="content">
|
||||
<div class="TopRackGrid">
|
||||
<div>
|
||||
<h2>
|
||||
Align
|
||||
Settings
|
||||
<span class="shade"> </span>
|
||||
</h2>
|
||||
<webaudio-switch id="on" value="1" tooltip="Switch-B" height="35" width="85" src="knobs/switch1.png">
|
||||
@ -117,7 +117,7 @@
|
||||
</div>
|
||||
<div class="webaudiobut">
|
||||
<div align="center" class="busled">
|
||||
Align
|
||||
Settings
|
||||
</div>
|
||||
<div align="center" class="busled">
|
||||
|
||||
|
@ -56,10 +56,10 @@
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a href="align.html">
|
||||
<a href="settings.html">
|
||||
<div class="webaudiobut">
|
||||
<div align="center" class="navled">
|
||||
Align
|
||||
Settings
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
@ -90,8 +90,8 @@
|
||||
|
||||
|
||||
<div class="webaudiobut">
|
||||
<button type="button" class="navled" style="border : #222222 1px;" onclick="onSubmit(this.id)" id="settings/restart lj" >
|
||||
rstrt LJ
|
||||
<button type="button" class="navled" style="border : #222222 1px;" onclick="onSubmit(this.id)" id="settings/reset" >
|
||||
reset
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
@ -1,680 +0,0 @@
|
||||
<!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"> </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>
|
@ -93,10 +93,10 @@
|
||||
</div>
|
||||
</a>
|
||||
|
||||
<a href="../align.html">
|
||||
<a href="../settings.html">
|
||||
<div class="webaudiobut">
|
||||
<div align="center" class="navled">
|
||||
Align
|
||||
Settings
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
@ -127,8 +127,8 @@
|
||||
|
||||
|
||||
<div class="webaudiobut">
|
||||
<button type="button" class="navled" style="border : #222222 1px;" onclick="onSubmit(this.id)" id="settings/restart lj" >
|
||||
rstrt LJ
|
||||
<button type="button" class="navled" style="border : #222222 1px;" onclick="onSubmit(this.id)" id="settings/reset" >
|
||||
Reset
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user