Compare commits
9 Commits
master
...
feat/dac_h
Author | SHA1 | Date | |
---|---|---|---|
|
bc19e77f4f | ||
|
6c73bd9fc2 | ||
|
80c76bfeb1 | ||
|
f67e7992ba | ||
|
1847c8ebef | ||
|
88998abde7 | ||
|
506616cb1b | ||
|
a9268b0d73 | ||
|
98538662b8 |
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,3 +1,5 @@
|
||||
.*swp*
|
||||
*__pycache__
|
||||
www/config.js
|
||||
.venv/
|
||||
.idea
|
||||
|
5
LJ.conf
5
LJ.conf
@ -1,15 +1,16 @@
|
||||
[General]
|
||||
lasernumber = 1
|
||||
debug = 1
|
||||
debug = 2
|
||||
ljayserverip = 0.0.0.0
|
||||
wwwip = 127.0.0.1
|
||||
nozoscip = 127.0.0.1
|
||||
bhoroscip = 127.0.0.1
|
||||
autostart = artnet
|
||||
autostart =
|
||||
wstype = ws
|
||||
wsport = 9001
|
||||
|
||||
[laser0]
|
||||
dac_family = helios
|
||||
color = -1
|
||||
type = DS1000
|
||||
ip = 127.0.0.1
|
||||
|
@ -17,7 +17,7 @@ from /team/laser
|
||||
#ConfigName = "setexample.conf"
|
||||
ConfigName = "LJ.conf"
|
||||
|
||||
debug = 0
|
||||
debug = 10
|
||||
ljpath=''
|
||||
|
||||
anims= [[],[],[],[]]
|
||||
@ -68,6 +68,7 @@ GridDisplay = [0,0,0,0]
|
||||
|
||||
# Transformation Matrix for each laser
|
||||
EDH = [[], [], [], []]
|
||||
# EDH = [[], [], [], []]
|
||||
|
||||
# Etherdreams reports
|
||||
# ipconn is initial newdac to its etherdream
|
||||
|
@ -150,13 +150,13 @@ def find_affine(points1,points2):
|
||||
H[2,2] = 1
|
||||
return H
|
||||
|
||||
def apply(H,points):
|
||||
|
||||
p = np.ones((len(points),3),'float64')
|
||||
p[:,:2] = points
|
||||
pp = np.dot(p,H.T)
|
||||
pp[:,:2]/=pp[:,2].reshape(len(p),1)
|
||||
return pp[:,:2]
|
||||
def apply(H, points):
|
||||
p = np.ones((len(points), 3), 'float64')
|
||||
p[:, :3] = points
|
||||
pp = np.dot(p, H.T)
|
||||
pp[:, :2] /= pp[:, 2].reshape(len(p), 1)
|
||||
return pp[:, :2]
|
||||
|
||||
# Align and axis swap corrections
|
||||
# Reference points
|
||||
|
BIN
libs3/libHeliosDacAPI.so
Normal file
BIN
libs3/libHeliosDacAPI.so
Normal file
Binary file not shown.
94
libs3/tracer.py
Normal file
94
libs3/tracer.py
Normal file
@ -0,0 +1,94 @@
|
||||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
'''
|
||||
|
||||
Tracer v0.8.2
|
||||
|
||||
Etherdream DACs handler on network via Redis
|
||||
|
||||
LICENCE : CC
|
||||
Sam Neurohack, pclf
|
||||
|
||||
One tracer process is launched per requested laser by LJ. Lasers parameters in LJ.conf.
|
||||
Live I/O based on redis keys : inputs (Pointlists to draw,...) and outputs (DAC state, errors,..).
|
||||
Keys are mostly read and set at each main loop.
|
||||
|
||||
* Redis keys reference *
|
||||
|
||||
- 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
|
||||
/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
|
||||
/EDH/lasernumber
|
||||
|
||||
- Tracer control :
|
||||
|
||||
/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
|
||||
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
|
||||
|
||||
|
||||
- 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
|
||||
|
||||
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.
|
||||
|
||||
|
||||
Geometric corrections
|
||||
|
||||
Doctodo
|
||||
|
||||
|
||||
'''
|
||||
import socket
|
||||
import time
|
||||
import struct
|
||||
# from gstt import debug
|
||||
from libs3 import gstt, log
|
||||
import math
|
||||
from itertools import cycle
|
||||
# from globalVars import *
|
||||
import pdb
|
||||
import ast
|
||||
import redis
|
||||
from .tracer_etherdream import TracerEtherdream
|
||||
from .tracer_helios import TracerHelios
|
||||
|
||||
from libs3 import homographyp
|
||||
import numpy as np
|
||||
import binascii
|
||||
|
||||
r = redis.StrictRedis(host=gstt.LjayServerIP, port=6379, db=0)
|
||||
|
||||
|
||||
def DAC(mylaser, point_list_number, dac_family="etherdream"):
|
||||
print(f"# Starting DAC #{mylaser} PL#:{point_list_number} Family:'{dac_family}'")
|
||||
if dac_family == "etherdream":
|
||||
return TracerEtherdream(mylaser, point_list_number, redis=r, port=7765)
|
||||
if dac_family == "helios":
|
||||
return TracerHelios(mylaser, point_list_number, redis=r)
|
334
libs3/tracer_common.py
Normal file
334
libs3/tracer_common.py
Normal file
@ -0,0 +1,334 @@
|
||||
import ast
|
||||
import math
|
||||
import struct
|
||||
import sys
|
||||
import time
|
||||
|
||||
import numpy as np
|
||||
import redis
|
||||
|
||||
from libs3 import gstt, log
|
||||
|
||||
|
||||
def pack_point(laser, intensity, x, y, r, g, b, i=-1, u1=0, u2=0, flags=0):
|
||||
"""Pack some color values into a struct dac_point."""
|
||||
|
||||
# print("Tracer", laser,":", r,g,b,"intensity", intensity, "i", i)
|
||||
|
||||
if r > intensity:
|
||||
r = intensity
|
||||
if g > intensity:
|
||||
g = intensity
|
||||
if b > intensity:
|
||||
b = intensity
|
||||
|
||||
if max(r, g, b) == 0:
|
||||
i = 0
|
||||
else:
|
||||
i = intensity
|
||||
|
||||
x = int(x)
|
||||
y = int(y)
|
||||
# print("Tracer ", laser, ": packing", x, y, r, g, b, "intensity", intensity, "i", i)
|
||||
|
||||
if x < -32767:
|
||||
if gstt.debug > 1:
|
||||
log.err("Tracer " + str(laser) + " : x coordinates " + str(x) + " was below -32767")
|
||||
x = -32000
|
||||
|
||||
if x > 32767:
|
||||
if gstt.debug > 1:
|
||||
log.err("Tracer " + str(laser) + " : x coordinates " + str(x) + " was bigger than 32767")
|
||||
x = 32000
|
||||
|
||||
if y < -32767:
|
||||
|
||||
if gstt.debug > 1:
|
||||
log.err("Tracer " + str(laser) + " : y coordinates " + str(y) + " was below -32767")
|
||||
y = -32000
|
||||
|
||||
if y > 32767:
|
||||
|
||||
if gstt.debug > 1:
|
||||
log.err("Tracer " + str(laser) + " : y coordinates " + str(y) + " was bigger than 32767")
|
||||
y = 32000
|
||||
|
||||
return struct.pack("<HhhHHHHHH", flags, x, y, r, g, b, i, u1, u2)
|
||||
|
||||
|
||||
class ProtocolError(Exception):
|
||||
"""Exception used when a protocol error is detected."""
|
||||
pass
|
||||
|
||||
|
||||
class Status(object):
|
||||
"""Represents a status response from the DAC."""
|
||||
|
||||
def __init__(self, data):
|
||||
"""Initialize from a chunk of data."""
|
||||
self.protocol_version, self.le_state, self.playback_state, \
|
||||
self.source, self.le_flags, self.playback_flags, \
|
||||
self.source_flags, self.fullness, self.point_rate, \
|
||||
self.point_count = \
|
||||
struct.unpack("<BBBBHHHHII", data)
|
||||
|
||||
def dump(self, prefix=" - "):
|
||||
"""Dump to a string."""
|
||||
lines = [
|
||||
""
|
||||
"Host ",
|
||||
"Light engine: state %d, flags 0x%x" %
|
||||
(self.le_state, self.le_flags),
|
||||
"Playback: state %d, flags 0x%x" %
|
||||
(self.playback_state, self.playback_flags),
|
||||
"Buffer: %d points" %
|
||||
(self.fullness,),
|
||||
"Playback: %d kpps, %d points played" %
|
||||
(self.point_rate, self.point_count),
|
||||
"Source: %d, flags 0x%x" %
|
||||
(self.source, self.source_flags)
|
||||
]
|
||||
|
||||
if gstt.debug == 2:
|
||||
print()
|
||||
for l in lines:
|
||||
print(prefix + l)
|
||||
|
||||
|
||||
def OnePointIterator(ref):
|
||||
while True:
|
||||
for indexpoint, currentpoint in enumerate(ref.pl):
|
||||
|
||||
# We modify the point geometry according to warp settings
|
||||
# print indexpoint, currentpoint
|
||||
# xyc = [currentpoint[0], currentpoint[1], currentpoint[2]]
|
||||
# ref.xyrgb = ref.get_warped_point(xyc)
|
||||
x, y = ref.get_warped_point(currentpoint[0], currentpoint[1])
|
||||
r, g, b = ref.int_to_rgb(currentpoint[2])
|
||||
|
||||
# We modify the point color based on channel specific r,g,b intensity settings
|
||||
rgb = (round(r * ref.intred / 100), round(g * ref.intgreen / 100),
|
||||
round(b * ref.intblue / 100))
|
||||
|
||||
# We compute the delta with previous position
|
||||
delta_x, delta_y = x - ref.prev_x, y - ref.prev_y
|
||||
|
||||
# We compute the distance from previous postion
|
||||
if math.hypot(delta_x, delta_y) < 4000:
|
||||
# For glitch art : decrease lsteps
|
||||
# l_steps = [ (1.0, 8)]
|
||||
l_steps = gstt.stepshortline
|
||||
else:
|
||||
# For glitch art : decrease lsteps
|
||||
# l_steps = [ (0.25, 3), (0.75, 3), (1.0, 10)]
|
||||
l_steps = gstt.stepslongline
|
||||
|
||||
# We add intermediate points based on settings
|
||||
for e in l_steps:
|
||||
step = e[0]
|
||||
|
||||
for i in range(0, e[1]):
|
||||
ref.xyrgb_step = (ref.prev_x + step * delta_x,
|
||||
ref.prev_y + step * delta_y) + rgb # + ref.xyrgb_prev[2:]# + rgb
|
||||
# print(ref.xyrgb_step)
|
||||
yield ref.xyrgb_step
|
||||
|
||||
ref.prev_x, ref.prev_y = x, y
|
||||
ref.xyrgb_prev = [x, y]
|
||||
|
||||
|
||||
class Tracer(object):
|
||||
"""A connection to a DAC."""
|
||||
laser_id: int
|
||||
redis: object
|
||||
point_list_number: list
|
||||
pl: list
|
||||
client_key: str # /pl/<laser_id> by default
|
||||
prev_x = 0
|
||||
prev_y = 0
|
||||
|
||||
black_points = [(278.0, 225.0, 0), (562.0, 279.0, 0), (401.0, 375.0, 0), (296.0, 454.0, 0), (298.0, 165.0, 0)]
|
||||
grid_points = [(300.0, 200.0, 0), (500.0, 200.0, 65280), (500.0, 400.0, 65280), (300.0, 400.0, 65280),
|
||||
(300.0, 200.0, 65280), (300.0, 200.0, 0), (200.0, 100.0, 0), (600.0, 100.0, 65280),
|
||||
(600.0, 500.0, 65280), (200.0, 500.0, 65280), (200.0, 100.0, 65280)]
|
||||
ackstate = {'61': 'ACK', '46': 'FULL', '49': "INVALID", '21': 'STOP', '64': "NO CONNECTION ?",
|
||||
'35': "NO CONNECTION ?",
|
||||
'97': 'ACK', '70': 'FULL', '73': "INVALID", '33': 'STOP', '100': "NOCONNECTION", '48': "NOCONNECTION",
|
||||
'a': 'ACK', 'F': 'FULL', 'I': "INVALID", '!': 'STOP', 'd': "NO CONNECTION ?", '0': "NO CONNECTION ?"}
|
||||
lstate = {'0': 'IDLE', '1': 'PREPARE', '2': "PLAYING", '3': 'STOP', '64': "NOCONNECTION ?"}
|
||||
|
||||
"""
|
||||
status : the general status of the DAC, is it working or not?
|
||||
ack_status : DAC specific, sent continuously by the DAC to track activity
|
||||
"""
|
||||
|
||||
def int_to_rgb(self, c):
|
||||
return ((c >> 16) & 0xFF) << 8, ((c >> 8) & 0xFF) << 8, (c & 0xFF) << 8
|
||||
|
||||
def get_status(self):
|
||||
raise Exception("Please override the method")
|
||||
|
||||
def set_status(self, status: int):
|
||||
raise Exception("Please override the method")
|
||||
|
||||
def get_warped_point(self, x, y):
|
||||
"""
|
||||
A DAC specific point model, ex EtherPoint or HeliosPoint
|
||||
:param xyc: x,y,color
|
||||
:return:
|
||||
"""
|
||||
raise Exception("Please override the method")
|
||||
|
||||
# def get_ack_status(self):
|
||||
# raise Exception("Please override the method")
|
||||
#
|
||||
# def set_ack_status(self, ack_status: int):
|
||||
# raise Exception("Please override the method")
|
||||
|
||||
def prepare(self):
|
||||
raise Exception("Please override the method")
|
||||
|
||||
def begin(self, n, kpps):
|
||||
raise Exception("Please override the method")
|
||||
|
||||
def before_loop(self):
|
||||
"""
|
||||
Hook for DAC specific actions on each loop
|
||||
:return:
|
||||
"""
|
||||
raise Exception("Please override the method")
|
||||
|
||||
def get_points_capacity(self):
|
||||
"""
|
||||
How much points can we send next to the DAC
|
||||
:return: int
|
||||
"""
|
||||
raise Exception("Please override the method")
|
||||
|
||||
def convert_color(self, c):
|
||||
"""
|
||||
DAC specific color conversion
|
||||
:param c:
|
||||
:return:
|
||||
"""
|
||||
raise Exception("Please override the method")
|
||||
|
||||
def write(self, points):
|
||||
"""
|
||||
Actual sending to the DAC
|
||||
:param points: a list of points "corrected" with geometry, color, intensity settings
|
||||
:return:
|
||||
"""
|
||||
raise Exception("Please override the method")
|
||||
|
||||
def play_stream(self):
|
||||
"""
|
||||
Main loop common for every dac driver
|
||||
:return:
|
||||
"""
|
||||
self.before_loop()
|
||||
|
||||
started = 0
|
||||
|
||||
while True:
|
||||
|
||||
self.redis.set('/lstate/' + str(self.laser_id), self.get_status())
|
||||
|
||||
# print("laser", self.laser_id, "Pb : ",self.last_status.playback_state)
|
||||
|
||||
order = int(self.redis.get('/order/' + str(self.laser_id)).decode('ascii'))
|
||||
# print("tracer", str(self.laser_id),"order", order, type(order)
|
||||
|
||||
if order == 0:
|
||||
""" 0 : The actual points sending to laser """
|
||||
# USER point list /
|
||||
# @todo si la clef est vide utiliser les points noirs ? -> syntax error -> black points.
|
||||
try:
|
||||
self.pl = ast.literal_eval(self.redis.get(self.clientkey + str(self.laser_id)).decode('ascii'))
|
||||
# print(self.clientkey + str(self.laser_id))
|
||||
# print(self.pl)
|
||||
|
||||
except SyntaxError:
|
||||
print("BAD POINTLIST on Tracer : laser", self.laser_id, " order 0 : pl : ", self.pl)
|
||||
self.pl = self.black_points
|
||||
|
||||
# print("Tracer : laser", self.laser_id, " order 0 : pl : ",len(self.pl))
|
||||
|
||||
else:
|
||||
|
||||
if order == 1:
|
||||
""" 1 : Get the new EDH / The zoom || trapezoidal / homography settings for the laser """
|
||||
print("Tracer", self.laser_id, "new EDH ORDER in redis")
|
||||
gstt.EDH[self.laser_id] = np.array(
|
||||
ast.literal_eval(self.redis.get('/EDH/' + str(self.laser_id)).decode('ascii')))
|
||||
# Back to user point list
|
||||
self.redis.set('/order/' + str(self.laser_id), 0)
|
||||
|
||||
#
|
||||
if order == 2:
|
||||
""" 2 : Send a BLACK point list """
|
||||
print("Tracer", self.laser_id, "BLACK ORDER in redis")
|
||||
self.pl = self.black_points
|
||||
|
||||
if order == 3:
|
||||
""" 3: Send a GRID point list"""
|
||||
print("Tracer", self.laser_id, "GRID ORDER in redis")
|
||||
self.pl = self.grid_points
|
||||
|
||||
if order == 4:
|
||||
""" 4: Resampler Change, modify the automatic intermediary points settings """
|
||||
self.resampler = ast.literal_eval(
|
||||
self.redis.get('/resampler/' + str(self.laser_id)).decode('ascii'))
|
||||
print("Tracer", self.laser_id, " : resetting lsteps for", self.resampler)
|
||||
gstt.stepshortline = self.resampler[0]
|
||||
gstt.stepslongline[0] = self.resampler[1]
|
||||
gstt.stepslongline[1] = self.resampler[2]
|
||||
gstt.stepslongline[2] = self.resampler[3]
|
||||
# Back to user point list order
|
||||
self.redis.set('/order/' + str(self.laser_id), 0)
|
||||
|
||||
if order == 5:
|
||||
""" 5: Client Key change, change the address to read points from in redis ex: /pl/0 => /pl/3"""
|
||||
print("Tracer", self.laser_id, "new clientkey")
|
||||
self.clientkey = self.redis.get('/clientkey')
|
||||
# Back to user point list order
|
||||
self.redis.set('/order/' + str(self.laser_id), 0)
|
||||
|
||||
if order == 6:
|
||||
""" 6: change intensity """
|
||||
# @todo check for helios vs etherdream
|
||||
self.intensity = int(self.redis.get('/intensity/' + str(self.laser_id)).decode('ascii')) << 8
|
||||
print("Tracer", self.laser_id, "new Intensity", self.intensity)
|
||||
gstt.intensity[self.laser_id] = self.intensity
|
||||
self.redis.set('/order/' + str(self.laser_id), "0")
|
||||
|
||||
if order == 7:
|
||||
""" 7: kpps change"""
|
||||
gstt.kpps[self.laser_id] = int(self.redis.get('/kpps/' + str(self.laser_id)).decode('ascii'))
|
||||
print("Tracer", self.laser_id, "new kpps", gstt.kpps[self.laser_id])
|
||||
self.update(0, gstt.kpps[self.laser_id])
|
||||
self.redis.set('/order/' + str(self.laser_id), "0")
|
||||
|
||||
if order == 8:
|
||||
""" 8: color balance change"""
|
||||
self.intred = int(self.redis.get('/red/' + str(self.laser_id)).decode('ascii'))
|
||||
self.intgreen = int(self.redis.get('/green/' + str(self.laser_id)).decode('ascii'))
|
||||
self.intblue = int(self.redis.get('/blue/' + str(self.laser_id)).decode('ascii'))
|
||||
print("Tracer", self.laser_id, "new color balance", self.intred, "% ", self.intgreen, "% ",
|
||||
self.intblue, "% ")
|
||||
self.redis.set('/order/' + str(self.laser_id), "0")
|
||||
|
||||
# if getattr(self, "last_status") :
|
||||
# self.redis.set('/lstt/' + str(self.laser_id), self.last_status.playback_state)
|
||||
# pdb.set_trace()
|
||||
# How much room?
|
||||
capacity = self.get_points_capacity()
|
||||
iterator = iter(OnePointIterator(self))
|
||||
|
||||
self.redis.set('/cap/' + str(self.laser_id), capacity)
|
||||
points = [next(iterator) for i in range(capacity)]
|
||||
self.write(points)
|
||||
if not started:
|
||||
print("Tracer", self.laser_id, "starting with", gstt.kpps[self.laser_id], "kpps")
|
||||
self.begin(0, gstt.kpps[self.laser_id])
|
||||
started = 1
|
400
libs3/tracer_etherdream.py
Normal file
400
libs3/tracer_etherdream.py
Normal file
@ -0,0 +1,400 @@
|
||||
#!/usr/bin/python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# -*- mode: Python -*-
|
||||
|
||||
'''
|
||||
|
||||
Tracer v0.8.2
|
||||
|
||||
Etherdream DACs handler on network via Redis
|
||||
|
||||
LICENCE : CC
|
||||
Sam Neurohack, pclf
|
||||
|
||||
Includes live conversion in etherdream coordinates, geometric corrections, color balance change, intensity limitation, grid display,...
|
||||
|
||||
One tracer process is launched per requested laser by LJ. Lasers parameters in LJ.conf.
|
||||
Live I/O based on redis keys : inputs (Pointlists to draw,...) and outputs (DAC state, errors,..).
|
||||
Keys are mostly read and set at each main loop.
|
||||
This tracer include an enhanced version (support for several lasers) of the etherdream python library from j4cDAC.
|
||||
|
||||
|
||||
* Redis keys reference *
|
||||
|
||||
- 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
|
||||
/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
|
||||
/EDH/lasernumber
|
||||
|
||||
- Tracer control :
|
||||
|
||||
/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
|
||||
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
|
||||
|
||||
|
||||
- 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
|
||||
|
||||
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.
|
||||
|
||||
|
||||
Geometric corrections
|
||||
|
||||
Doctodo
|
||||
|
||||
|
||||
'''
|
||||
|
||||
import socket
|
||||
import time
|
||||
import struct
|
||||
# from gstt import debug
|
||||
from libs3 import gstt, log
|
||||
import math
|
||||
import ast
|
||||
|
||||
from libs3 import homographyp
|
||||
import numpy as np
|
||||
from .tracer_common import *
|
||||
|
||||
# @todo this needs normallization
|
||||
ackstate = {'61': 'ACK', '46': 'FULL', '49': "INVALID", '21': 'STOP', '64': "NO CONNECTION ?",
|
||||
'35': "NO CONNECTION ?",
|
||||
'97': 'ACK', '70': 'FULL', '73': "INVALID", '33': 'STOP', '100': "NOCONNECTION", '48': "NOCONNECTION",
|
||||
'a': 'ACK', 'F': 'FULL', 'I': "INVALID", '!': 'STOP', 'd': "NO CONNECTION ?", '0': "NO CONNECTION ?"}
|
||||
black_points = [(278.0, 225.0, 0), (562.0, 279.0, 0), (401.0, 375.0, 0), (296.0, 454.0, 0), (298.0, 165.0, 0)]
|
||||
grid_points = [(300.0, 200.0, 0), (500.0, 200.0, 65280), (500.0, 400.0, 65280), (300.0, 400.0, 65280),
|
||||
(300.0, 200.0, 65280), (300.0, 200.0, 0), (200.0, 100.0, 0), (600.0, 100.0, 65280),
|
||||
(600.0, 500.0, 65280), (200.0, 500.0, 65280), (200.0, 100.0, 65280)]
|
||||
|
||||
|
||||
class TracerEtherdream(Tracer):
|
||||
"""A connection to a DAC."""
|
||||
|
||||
# "Laser point List" Point generator
|
||||
# each points is yielded : Getpoints() call n times OnePoint()
|
||||
|
||||
def __init__(self, mylaser, PL, redis, port=7765):
|
||||
"""Connect to the DAC over TCP."""
|
||||
socket.setdefaulttimeout(2)
|
||||
self.redis = redis
|
||||
self.mylaser = mylaser
|
||||
self.clientkey = self.redis.get("/clientkey").decode('ascii')
|
||||
|
||||
# log.info("Tracer "+str(self.mylaser)+" connecting to "+ gstt.lasersIPS[mylaser])
|
||||
# print("DAC", self.mylaser, "Handler process, connecting to", gstt.lasersIPS[mylaser] )
|
||||
self.conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
self.connstatus = self.conn.connect_ex((gstt.lasersIPS[mylaser], port))
|
||||
if self.connstatus == 35 or self.connstatus == 64:
|
||||
log.err(
|
||||
"Tracer " + str(self.mylaser) + " (" + gstt.lasersIPS[mylaser] + "): " + ackstate[str(self.connstatus)])
|
||||
else:
|
||||
print(
|
||||
"Tracer " + str(self.mylaser) + " (" + gstt.lasersIPS[mylaser] + "): " + ackstate[str(self.connstatus)])
|
||||
|
||||
# ipconn state is -1 at startup (see gstt) and modified here
|
||||
self.redis.set('/lack/' + str(self.mylaser), self.connstatus)
|
||||
gstt.lstt_ipconn[self.mylaser] = self.connstatus
|
||||
|
||||
self.buf = b''
|
||||
# Upper case PL is the Point List number
|
||||
self.PL = PL
|
||||
|
||||
# Lower case pl is the actual point list coordinates
|
||||
|
||||
# pdb.set_trace()
|
||||
self.pl = ast.literal_eval(self.redis.get(self.clientkey + str(self.mylaser)).decode('ascii'))
|
||||
if self.redis.get('/EDH/' + str(self.mylaser)) == None:
|
||||
# print("Laser",self.mylaser,"NO EDH !! Computing one...")
|
||||
homographyp.newEDH(self.mylaser)
|
||||
else:
|
||||
|
||||
gstt.EDH[self.mylaser] = np.array(ast.literal_eval(self.redis.get('/EDH/' + str(self.mylaser)).decode('ascii')))
|
||||
# print("Laser",self.mylaser,"found its EDH in redis")
|
||||
# print gstt.EDH[self.mylaser]
|
||||
|
||||
self.xyrgb = self.xyrgb_prev = (0, 0, 0, 0, 0)
|
||||
self.intensity = 65280
|
||||
self.intred = 100
|
||||
self.intgreen = 100
|
||||
self.intblue = 100
|
||||
self.newstream = self.OnePoint()
|
||||
self.prev_x = 0
|
||||
self.prev_y = 0
|
||||
|
||||
if gstt.debug > 0:
|
||||
print("Tracer", self.mylaser, "init asked for ckey", self.clientkey + str(self.mylaser))
|
||||
if self.connstatus != 0:
|
||||
# print(""
|
||||
log.err("Connection ERROR " + str(self.connstatus) + " with laser " + str(mylaser) + " : " + str(
|
||||
gstt.lasersIPS[mylaser]))
|
||||
# print("first 10 points in PL",self.PL, self.GetPoints(10)
|
||||
else:
|
||||
print("Connection status for DAC " + str(self.mylaser) + " : " + str(self.connstatus))
|
||||
|
||||
# Reference points
|
||||
# Read the "hello" message
|
||||
first_status = self.readresp("?")
|
||||
first_status.dump()
|
||||
position = []
|
||||
|
||||
def before_loop(self):
|
||||
|
||||
# print("laser", self.laser_id, "Pb : ",self.last_status.playback_state)
|
||||
# error if DAC is already playing state (from other source)
|
||||
if self.last_status.playback_state == 2:
|
||||
raise Exception("already playing?!")
|
||||
|
||||
# if idle go to prepare state
|
||||
elif self.last_status.playback_state == 0:
|
||||
self.prepare()
|
||||
|
||||
def get_points_capacity(self):
|
||||
cap = 1799 - self.last_status.fullness
|
||||
if cap < 100:
|
||||
time.sleep(0.001)
|
||||
cap += 150
|
||||
return
|
||||
|
||||
def read(self, l):
|
||||
"""Read exactly length bytes from the connection."""
|
||||
while l > len(self.buf):
|
||||
self.buf += self.conn.recv(4096)
|
||||
|
||||
obuf = self.buf
|
||||
self.buf = obuf[l:]
|
||||
return obuf[:l]
|
||||
|
||||
def readresp(self, cmd):
|
||||
"""Read a response from the DAC."""
|
||||
|
||||
data = self.read(22)
|
||||
response = data[0]
|
||||
gstt.lstt_dacanswers[self.mylaser] = response
|
||||
cmdR = chr(data[1])
|
||||
status = Status(data[2:])
|
||||
|
||||
self.redis.set('/lack/' + str(self.mylaser), response)
|
||||
|
||||
if cmdR != cmd:
|
||||
raise ProtocolError("expected resp for %r, got %r"
|
||||
% (cmd, cmdR))
|
||||
|
||||
if response != ord('a'):
|
||||
raise ProtocolError("expected ACK, got %r"
|
||||
% (response,))
|
||||
|
||||
self.last_status = status
|
||||
return status
|
||||
|
||||
def begin(self, lwm, rate):
|
||||
cmd = struct.pack("<cHI", b'b', lwm, rate)
|
||||
print("Tracer", str(self.mylaser), "begin with PL : ", str(self.PL))
|
||||
self.conn.sendall(cmd)
|
||||
return self.readresp("b")
|
||||
|
||||
def update(self, lwm, rate):
|
||||
print(("update", lwm, rate))
|
||||
cmd = struct.pack("<cHI", b'u', lwm, rate)
|
||||
self.conn.sendall(cmd)
|
||||
return self.readresp("u")
|
||||
|
||||
def encode_point(self, point):
|
||||
return pack_point(self.mylaser, self.intensity, *point)
|
||||
|
||||
def get_capacity(self):
|
||||
""" How much points can we send next / are free in etherdream's buffer?"""
|
||||
cap = 1799 - self.last_status.fullness
|
||||
return cap
|
||||
|
||||
def write(self, points):
|
||||
epoints = list(map(self.encode_point, points))
|
||||
cmd = struct.pack("<cH", b'd', len(epoints))
|
||||
self.conn.sendall(cmd + b''.join(epoints))
|
||||
return self.readresp('d')
|
||||
|
||||
def get_warped_point(self, x, y ):
|
||||
# Etherpoint all transform in one matrix, with warp !!
|
||||
# xy : x y
|
||||
|
||||
# gstt.EDH[self.mylaser]= np.array(ast.literal_eval(self.redis.get('/EDH/'+str(self.mylaser))))
|
||||
position = homographyp.apply(gstt.EDH[self.laser_id], np.array([(x, y)]))
|
||||
|
||||
# print("etherdream point",position[0][0], position[0][1], ((c >> 16) & 0xFF) << 8, ((c >> 8) & 0xFF) << 8, (c & 0xFF) << 8)
|
||||
|
||||
return position[0][0], position[0][1]
|
||||
|
||||
def prepare(self):
|
||||
self.conn.sendall(b'p')
|
||||
return self.readresp('p')
|
||||
|
||||
def stop(self):
|
||||
self.conn.sendall('s')
|
||||
return self.readresp('s')
|
||||
|
||||
def estop(self):
|
||||
self.conn.sendall("\xFF")
|
||||
return self.readresp("\xFF")
|
||||
|
||||
def clear_estop(self):
|
||||
self.conn.sendall("c")
|
||||
return self.readresp("c")
|
||||
|
||||
def ping(self):
|
||||
self.conn.sendall('?')
|
||||
return self.readresp('?')
|
||||
|
||||
def play_stream(self):
|
||||
|
||||
# print("laser", self.mylaser, "Pb : ",self.last_status.playback_state)
|
||||
|
||||
# error if etherdream is already playing state (from other source)
|
||||
if self.last_status.playback_state == 2:
|
||||
raise Exception("already playing?!")
|
||||
|
||||
# if idle go to prepare state
|
||||
elif self.last_status.playback_state == 0:
|
||||
self.prepare()
|
||||
|
||||
started = 0
|
||||
|
||||
while True:
|
||||
|
||||
# print("laser", self.mylaser, "Pb : ",self.last_status.playback_state)
|
||||
|
||||
order = int(self.redis.get('/order/' + str(self.mylaser)).decode('ascii'))
|
||||
# print("tracer", str(self.mylaser),"order", order, type(order)
|
||||
|
||||
if order == 0:
|
||||
|
||||
# USER point list
|
||||
|
||||
# self.pl = ast.literal_eval(self.redis.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 = self.redis.get(self.clientkey+str(self.mylaser))
|
||||
# self.pl = ast.literal_eval(newpl.decode('ascii'))
|
||||
self.pl = ast.literal_eval(self.redis.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:
|
||||
|
||||
# Get the new EDH
|
||||
if order == 1:
|
||||
print("Tracer", self.mylaser, "new EDH ORDER in redis")
|
||||
gstt.EDH[self.mylaser] = np.array(
|
||||
ast.literal_eval(self.redis.get('/EDH/' + str(self.mylaser)).decode('ascii')))
|
||||
# Back to user point list
|
||||
self.redis.set('/order/' + str(self.mylaser), 0)
|
||||
|
||||
# BLACK point list
|
||||
if order == 2:
|
||||
print("Tracer", self.mylaser, "BLACK ORDER in redis")
|
||||
self.pl = black_points
|
||||
|
||||
# GRID point list
|
||||
if order == 3:
|
||||
print("Tracer", self.mylaser, "GRID ORDER in redis")
|
||||
self.pl = grid_points
|
||||
|
||||
# Resampler Change
|
||||
if order == 4:
|
||||
self.resampler = ast.literal_eval(self.redis.get('/resampler/' + str(self.mylaser)).decode('ascii'))
|
||||
print("Tracer", self.mylaser, " : resetting lsteps for", self.resampler)
|
||||
gstt.stepshortline = self.resampler[0]
|
||||
gstt.stepslongline[0] = self.resampler[1]
|
||||
gstt.stepslongline[1] = self.resampler[2]
|
||||
gstt.stepslongline[2] = self.resampler[3]
|
||||
# Back to user point list order
|
||||
self.redis.set('/order/' + str(self.mylaser), 0)
|
||||
|
||||
# Client Key change
|
||||
if order == 5:
|
||||
print("Tracer", self.mylaser, "new clientkey")
|
||||
self.clientkey = self.redis.get('/clientkey')
|
||||
# Back to user point list order
|
||||
self.redis.set('/order/' + str(self.mylaser), 0)
|
||||
|
||||
# Intensity change
|
||||
if order == 6:
|
||||
self.intensity = int(self.redis.get('/intensity/' + str(self.mylaser)).decode('ascii')) << 8
|
||||
print("Tracer", self.mylaser, "new Intensity", self.intensity)
|
||||
gstt.intensity[self.mylaser] = self.intensity
|
||||
self.redis.set('/order/' + str(self.mylaser), "0")
|
||||
|
||||
# kpps change
|
||||
if order == 7:
|
||||
gstt.kpps[self.mylaser] = int(self.redis.get('/kpps/' + str(self.mylaser)).decode('ascii'))
|
||||
print("Tracer", self.mylaser, "new kpps", gstt.kpps[self.mylaser])
|
||||
self.update(0, gstt.kpps[self.mylaser])
|
||||
self.redis.set('/order/' + str(self.mylaser), "0")
|
||||
|
||||
# color balance change
|
||||
if order == 8:
|
||||
self.intred = int(self.redis.get('/red/' + str(self.mylaser)).decode('ascii'))
|
||||
self.intgreen = int(self.redis.get('/green/' + str(self.mylaser)).decode('ascii'))
|
||||
self.intblue = int(self.redis.get('/blue/' + str(self.mylaser)).decode('ascii'))
|
||||
print("Tracer", self.mylaser, "new color balance", self.intred, "% ", self.intgreen, "% ",
|
||||
self.intblue, "% ")
|
||||
self.redis.set('/order/' + str(self.mylaser), "0")
|
||||
|
||||
self.redis.set('/lstt/' + str(self.mylaser), self.last_status.playback_state)
|
||||
# pdb.set_trace()
|
||||
# How much room?
|
||||
|
||||
cap = 1799 - self.last_status.fullness
|
||||
points = self.GetPoints(cap)
|
||||
|
||||
self.redis.set('/cap/' + str(self.mylaser), cap)
|
||||
|
||||
if cap < 100:
|
||||
time.sleep(0.001)
|
||||
cap += 150
|
||||
|
||||
# print("Writing %d points" % (cap, ))
|
||||
# t0 = time.time()
|
||||
# if self.mylaser == 2:
|
||||
# print(points)
|
||||
self.write(points)
|
||||
# t1 = time.time()
|
||||
# print("Took %f" % (t1 - t0, )
|
||||
|
||||
if not started:
|
||||
print("Tracer", self.mylaser, "starting with", gstt.kpps[self.mylaser], "kpps")
|
||||
self.begin(0, gstt.kpps[self.mylaser])
|
||||
started = 1
|
121
libs3/tracer_helios.py
Normal file
121
libs3/tracer_helios.py
Normal file
@ -0,0 +1,121 @@
|
||||
import ctypes
|
||||
import math
|
||||
import random
|
||||
|
||||
from libs3 import gstt
|
||||
from libs3 import homographyp
|
||||
from .tracer_common import Tracer, OnePointIterator, ProtocolError, Status
|
||||
import numpy as np
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
# Define point structure
|
||||
class HeliosPoint(ctypes.Structure):
|
||||
# _pack_=1
|
||||
_fields_ = [('x', ctypes.c_uint16),
|
||||
('y', ctypes.c_uint16),
|
||||
('r', ctypes.c_uint8),
|
||||
('g', ctypes.c_uint8),
|
||||
('b', ctypes.c_uint8),
|
||||
('i', ctypes.c_uint8)]
|
||||
|
||||
|
||||
# Load and initialize library
|
||||
so_path = Path(__file__).absolute().parent.joinpath("libHeliosDacAPI.so")
|
||||
HeliosLib = ctypes.cdll.LoadLibrary(so_path)
|
||||
numDevices = HeliosLib.OpenDevices()
|
||||
print("Found ", numDevices, "Helios DACs")
|
||||
|
||||
|
||||
|
||||
|
||||
class TracerHelios(Tracer):
|
||||
"""A connection to a DAC."""
|
||||
|
||||
def __init__(self, laser_id, PL, redis):
|
||||
self.redis = redis
|
||||
self.laser_id = laser_id
|
||||
self.PL = PL
|
||||
self.pl = [[0, 0, 0]]
|
||||
self.clientkey = self.redis.get("/clientkey").decode('ascii')
|
||||
self.xyrgb = self.xyrgb_prev = (0, 0, 0, 0, 0)
|
||||
self.intensity = 65280
|
||||
self.intred = 100
|
||||
self.intgreen = 100
|
||||
self.intblue = 100
|
||||
self.prev_x = 0
|
||||
self.prev_y = 0
|
||||
|
||||
self.min_res = 0
|
||||
self.max_res = 4095
|
||||
|
||||
# self.newstream = OnePointIterator()
|
||||
|
||||
# "Laser point List" Point generator
|
||||
# each points is yielded : Getpoints() call n times OnePoint()
|
||||
pass
|
||||
|
||||
def clip(self, number):
|
||||
return int( self.min_res if number < self.min_res else self.max_res if number > self.max_res else number)
|
||||
|
||||
|
||||
def get_points_capacity(self):
|
||||
return 1000
|
||||
|
||||
# def GetPoints(self, capacity):
|
||||
# a = [2,3]
|
||||
# return a
|
||||
|
||||
def prepare(self):
|
||||
return True
|
||||
|
||||
def begin(self, n, kpps):
|
||||
return True
|
||||
|
||||
def get_status(self):
|
||||
""" Return 0 if not ready (playing), 1 if ready to receive new frame,-1 if communication failed """
|
||||
# va chercher dans le helios et renvoie la normalisée
|
||||
status = HeliosLib.GetStatus(0)
|
||||
if status == 0:
|
||||
return self.lstate["2"] # playing
|
||||
if status == 1:
|
||||
return self.lstate["0"] # ready
|
||||
if status == -1:
|
||||
return self.lstate["64"] # no connection
|
||||
|
||||
def set_status(self, status: int):
|
||||
return
|
||||
|
||||
def before_loop(self):
|
||||
return True
|
||||
|
||||
def write(self, points):
|
||||
frame_type = HeliosPoint * self.get_points_capacity()
|
||||
frame = frame_type()
|
||||
helios_id = 0
|
||||
points = [point for point in points]
|
||||
for i, point in enumerate(points):
|
||||
x, y, r, g, b = point
|
||||
x *= 10
|
||||
y *= 10
|
||||
x = 0 if math.isnan(x) else self.clip(x)
|
||||
y = 0 if math.isnan(y) else self.clip(y)
|
||||
frame[i] = HeliosPoint(int(x), int(y), int(r), int(g), int(b), 255)
|
||||
statusAttempts = 0
|
||||
# Make 512 attempts for DAC status to be ready. After that, just give up and try to write the frame anyway
|
||||
while (statusAttempts < 512 and HeliosLib.GetStatus(helios_id) != 1):
|
||||
statusAttempts += 1
|
||||
f = ctypes.pointer(frame)
|
||||
# int HeliosDac::WriteFrame(unsigned int devNum, unsigned int pps, std::uint8_t flags, HeliosPoint* points, unsigned int numOfPoints)
|
||||
# ret_helios = HeliosLib.WriteFrame(0, 3000, 0, f, len(frame))
|
||||
# # @todo : detect errors
|
||||
# if ret_helios != 1:
|
||||
# print(f"ERR ]Helios DAC #{self.laser_id} returned error {ret_helios}")
|
||||
|
||||
def get_warped_point(self, x, y):
|
||||
# transform in one matrix, with warp !!
|
||||
# Etherpoint all transform in one matrix, with warp !!
|
||||
np_arr = np.array([(x, y, 0)])
|
||||
laser_edh = gstt.EDH[self.laser_id]
|
||||
position = homographyp.apply(laser_edh, np_arr)
|
||||
return position[0][0], position[0][1]
|
251
main.py
251
main.py
@ -22,9 +22,11 @@ All used ports:
|
||||
Plugins OSC Ports (see LJ.conf)
|
||||
|
||||
'''
|
||||
#import pdb
|
||||
# import pdb
|
||||
import traceback
|
||||
|
||||
from libs3 import log
|
||||
|
||||
print("")
|
||||
print("")
|
||||
log.infog("LJ Laser Server")
|
||||
@ -35,11 +37,13 @@ print("")
|
||||
|
||||
import redis
|
||||
import os
|
||||
ljpath = r'%s' % os.getcwd().replace('\\','/')
|
||||
|
||||
ljpath = r'%s' % os.getcwd().replace('\\', '/')
|
||||
import sys
|
||||
|
||||
#sys.path.append('libs3/')
|
||||
# sys.path.append('libs3/')
|
||||
from libs3 import gstt, settings
|
||||
config = settings.config
|
||||
gstt.ljpath = ljpath
|
||||
|
||||
log.info("Reading " + gstt.ConfigName + " setup file...")
|
||||
@ -47,43 +51,39 @@ 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 lasytracer as tracer
|
||||
from libs3 import tracer
|
||||
|
||||
from libs3 import homographyp, commands, font1
|
||||
#import subprocess
|
||||
# import subprocess
|
||||
import os
|
||||
#import midi
|
||||
# import midi
|
||||
from libs3 import OSC3
|
||||
from websocket_server import WebsocketServer
|
||||
#import socket
|
||||
# import socket
|
||||
import types, _thread, time
|
||||
|
||||
|
||||
|
||||
r = redis.StrictRedis(host=gstt.LjayServerIP , port=6379, db=0)
|
||||
r = redis.StrictRedis(host=gstt.LjayServerIP, port=6379, db=0)
|
||||
# r = redis.StrictRedis(host=gstt.LjayServerIP , port=6379, db=0, password='-+F816Y+-')
|
||||
args =[0,0]
|
||||
args = [0, 0]
|
||||
|
||||
|
||||
def dac_process(number, pl):
|
||||
|
||||
def dac_process(number, pl, dac_family):
|
||||
import sys
|
||||
from libs3 import gstt
|
||||
|
||||
print("Starting dac process", number)
|
||||
try:
|
||||
d = tracer.DAC(number, pl, dac_family=dac_family)
|
||||
|
||||
while True:
|
||||
try:
|
||||
d = tracer.DAC(number,pl)
|
||||
d.play_stream()
|
||||
|
||||
except Exception as e:
|
||||
@ -92,6 +92,7 @@ def dac_process(number, pl):
|
||||
import traceback
|
||||
|
||||
if gstt.debug > 0:
|
||||
# if True:
|
||||
log.err('\n---------------------')
|
||||
log.err('Exception: %s' % e)
|
||||
log.err('- - - - - - - - - - -')
|
||||
@ -103,12 +104,11 @@ def dac_process(number, pl):
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
|
||||
#
|
||||
# Servers init variables
|
||||
#
|
||||
|
||||
print("Start Scene number :",gstt.SceneNumber)
|
||||
print("Start Scene number :", gstt.SceneNumber)
|
||||
|
||||
print("WebUI connect to :", gstt.wwwIP)
|
||||
|
||||
@ -121,16 +121,16 @@ print("OSCserver IP :", oscserverIP)
|
||||
nozoscIP = gstt.nozoscip
|
||||
print("Nozosc IP :", nozoscIP)
|
||||
|
||||
# gstt.debug = 1
|
||||
debug = gstt.debug
|
||||
print("Debug :", debug)
|
||||
|
||||
|
||||
# Websocket listening port
|
||||
wsPORT = 9001
|
||||
|
||||
# oscserver
|
||||
# OSC Server : accept OSC message on port 8002
|
||||
#oscIPin = "192.168.1.10"s
|
||||
# oscIPin = "192.168.1.10"s
|
||||
oscserverIPin = serverIP
|
||||
|
||||
print("oscserverIPin", oscserverIPin)
|
||||
@ -140,7 +140,6 @@ oscserverPORTin = 8002
|
||||
oscserverIPout = oscserverIP
|
||||
oscserverPORTout = 8001
|
||||
|
||||
|
||||
'''
|
||||
# Nozoid OSC Client : to send OSC message to Nozoid inport 8003
|
||||
NozoscIPout = nozoscIP
|
||||
@ -155,15 +154,15 @@ planetPORTout = plugins.Port("planet")
|
||||
|
||||
import socket
|
||||
|
||||
#retry = 1
|
||||
#delay = 1
|
||||
# retry = 1
|
||||
# delay = 1
|
||||
|
||||
|
||||
#
|
||||
# OSC
|
||||
#
|
||||
|
||||
oscserver = OSC3.OSCServer( (oscserverIPin, oscserverPORTin) )
|
||||
oscserver = OSC3.OSCServer((oscserverIPin, oscserverPORTin))
|
||||
oscserver.timeout = 0
|
||||
OSCRunning = True
|
||||
|
||||
@ -171,60 +170,58 @@ OSCRunning = True
|
||||
def handle_timeout(self):
|
||||
self.timed_out = True
|
||||
|
||||
|
||||
oscserver.handle_timeout = types.MethodType(handle_timeout, oscserver)
|
||||
|
||||
|
||||
# OSC default path handler : send incoming OSC message to UI via websocket 9001
|
||||
def handler(path, tags, args, source):
|
||||
|
||||
oscpath = path.split("/")
|
||||
if gstt.debug > 0:
|
||||
print("")
|
||||
print("OSC handler in main said : path", path," oscpath ", oscpath," args", args)
|
||||
print("OSC handler in main said : path", path, " oscpath ", oscpath, " args", args)
|
||||
|
||||
if oscpath[1] != "pong":
|
||||
sendWSall(path + " " + str(args[0]))
|
||||
commands.handler(oscpath,args)
|
||||
commands.handler(oscpath, args)
|
||||
|
||||
|
||||
# RAW OSC Frame available ?
|
||||
def osc_frame():
|
||||
#print 'oscframe'
|
||||
# print 'oscframe'
|
||||
# clear timed_out flag
|
||||
oscserver.timed_out = False
|
||||
# handle all pending requests then return
|
||||
while not oscserver.timed_out:
|
||||
oscserver.handle_request()
|
||||
|
||||
def PingAll():
|
||||
|
||||
def PingAll():
|
||||
if gstt.debug > 0:
|
||||
print("Pinging all plugins...")
|
||||
|
||||
for plugin in list(gstt.plugins.keys()):
|
||||
if gstt.debug > 0:
|
||||
print("pinging", plugin)
|
||||
#sendWSall("/"+ plugin + "/start 0")
|
||||
# sendWSall("/"+ plugin + "/start 0")
|
||||
plugins.Ping(plugin)
|
||||
|
||||
|
||||
|
||||
# OSC server Thread : handler, dacs reports and simulator points sender to UI.
|
||||
def osc_thread():
|
||||
|
||||
#while True:
|
||||
# while True:
|
||||
try:
|
||||
while True:
|
||||
|
||||
time.sleep(0.1)
|
||||
osc_frame()
|
||||
for laserid in range(0,gstt.LaserNumber): # Laser not used -> led is not lit
|
||||
for laserid in range(0, gstt.LaserNumber): # Laser not used -> led is not lit
|
||||
|
||||
lstate = {'0': 'IDLE', '1': 'PREPARE', '2': "PLAYING", '64': "NOCONNECTION ?" }
|
||||
lstt = r.get('/lstt/'+ str(laserid)).decode('ascii')
|
||||
#print ("laserid", laserid,"lstt",lstt, type(lstt))
|
||||
if gstt.debug >1:
|
||||
print("DAC", laserid, "is in (lstt) :", lstt , lstate[str(lstt)])
|
||||
lstate = {'0': 'IDLE', '1': 'PREPARE', '2': "PLAYING", '64': "NOCONNECTION ?"}
|
||||
lstt = r.get('/lstt/' + str(laserid)).decode('ascii')
|
||||
# print ("laserid", laserid,"lstt",lstt, type(lstt))
|
||||
if gstt.debug > 1:
|
||||
print("DAC", laserid, "is in (lstt) :", lstt, lstate[str(lstt)])
|
||||
if lstt == "0": # Dac IDLE state(0) -> led is blue (3)
|
||||
sendWSall("/lstt/" + str(laserid) + " 3")
|
||||
|
||||
@ -234,37 +231,40 @@ def osc_thread():
|
||||
if lstt == "2": # Dac PLAYING (2) -> led is green (1)
|
||||
sendWSall("/lstt/" + str(laserid) + " 1")
|
||||
|
||||
ackstate = {'61': 'ACK', '46': 'FULL', '49': "INVALID", '21': 'STOP', '64': "NOCONNECTION ?",
|
||||
'35': "NOCONNECTION ?", '97': 'ACK', '70': 'FULL', '73': "INVALID", '33': 'STOP',
|
||||
'100': "NOCONNECTION", '48': "NOCONNECTION", 'a': 'ACK', 'F': 'FULL', 'I': "INVALID",
|
||||
'!': 'STOP', 'd': "NOCONNECTION", '0': "NOCONNECTION"}
|
||||
lack = r.get('/lack/' + str(laserid)).decode('ascii')
|
||||
|
||||
ackstate = {'61': 'ACK', '46': 'FULL', '49': "INVALID", '21': 'STOP', '64': "NOCONNECTION ?", '35': "NOCONNECTION ?" , '97': 'ACK', '70': 'FULL', '73': "INVALID", '33': 'STOP', '100': "NOCONNECTION", '48': "NOCONNECTION", 'a': 'ACK', 'F': 'FULL', 'I': "INVALID", '!': 'STOP', 'd': "NOCONNECTION", '0': "NOCONNECTION"}
|
||||
lack= r.get('/lack/'+str(laserid)).decode('ascii')
|
||||
|
||||
if gstt.debug >1:
|
||||
if gstt.debug > 1:
|
||||
print("DAC", laserid, "answered (lack):", lack, chr(int(lack)), ackstate[str(lack)])
|
||||
|
||||
if chr(int(lack)) == 'a': # Dac sent ACK ("a") -> led is green (1)
|
||||
sendWSall("/lack/" + str(laserid) +" 1")
|
||||
sendWSall("/lack/" + str(laserid) + " 1")
|
||||
|
||||
if chr(int(lack)) == 'F': # Dac sent FULL ("F") -> led is orange (5)
|
||||
sendWSall("/lack/" + str(laserid) +" 5")
|
||||
sendWSall("/lack/" + str(laserid) + " 5")
|
||||
|
||||
if chr(int(lack)) == 'I': # Dac sent INVALID ("I") -> led is yellow (4)
|
||||
sendWSall("/lack/" + str(laserid)+" 4")
|
||||
#print lack
|
||||
sendWSall("/lack/" + str(laserid) + " 4")
|
||||
# print lack
|
||||
|
||||
if lack == "64" or lack =="35": # no connection to dac -> leds are red (6)
|
||||
if lack == "64" or lack == "35": # no connection to dac -> leds are red (6)
|
||||
sendWSall("/lack/" + str(laserid) + " 6")
|
||||
sendWSall("/lstt/" + str(laserid) + " 6")
|
||||
#sendWSall("/lstt/" + str(laserid) + " 0")
|
||||
# sendWSall("/lstt/" + str(laserid) + " 0")
|
||||
sendWSall("/points/" + str(laserid) + " 6")
|
||||
|
||||
else:
|
||||
# last number of points sent to etherdream buffer
|
||||
sendWSall("/points/" + str(laserid) + " " + str(r.get('/cap/'+str(laserid)).decode('ascii')))
|
||||
sendWSall("/points/" + str(laserid) + " " + str(r.get('/cap/' + str(laserid)).decode('ascii')))
|
||||
|
||||
#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:
|
||||
# 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()
|
||||
|
||||
|
||||
@ -276,39 +276,40 @@ def osc_thread():
|
||||
traceback.print_tb(sys.exc_info()[2])
|
||||
print("\n")
|
||||
|
||||
|
||||
#
|
||||
# Websocket part
|
||||
#
|
||||
|
||||
# Called for every WS client connecting (after handshake)
|
||||
def new_client(client, wserver):
|
||||
|
||||
print("New WS client connected and was given id %d" % client['id'])
|
||||
sendWSall("/status Hello " + str(client['id']))
|
||||
|
||||
for laserid in range(0,gstt.LaserNumber):
|
||||
for laserid in range(0, gstt.LaserNumber):
|
||||
|
||||
sendWSall("/ip/" + str(laserid) + " " + str(gstt.lasersIPS[laserid]))
|
||||
sendWSall("/kpps/" + str(laserid)+ " " + str(gstt.kpps[laserid]))
|
||||
#sendWSall("/laser"+str(laserid)+"/start 1")
|
||||
sendWSall("/laser "+str(laserid))
|
||||
#print("/laser "+str(laserid))
|
||||
sendWSall("/kpps/" + str(laserid) + " " + str(gstt.kpps[laserid]))
|
||||
# sendWSall("/laser"+str(laserid)+"/start 1")
|
||||
sendWSall("/laser " + str(laserid))
|
||||
# print("/laser "+str(laserid))
|
||||
sendWSall("/lack/" + str(laserid) + " 6")
|
||||
#print("/lack/" + str(laserid) + " 6")
|
||||
# print("/lack/" + str(laserid) + " 6")
|
||||
sendWSall("/lstt/" + str(laserid) + " 6")
|
||||
#print("/lstt/" + str(laserid) + " 6")
|
||||
# print("/lstt/" + str(laserid) + " 6")
|
||||
sendWSall("/points/" + str(laserid) + " 0")
|
||||
#print("/points/" + str(laserid) + " 0")
|
||||
# print("/points/" + str(laserid) + " 0")
|
||||
|
||||
if gstt.swapX[laserid] == 1:
|
||||
sendWSall("/swap/X/" + str(laserid)+ " 1")
|
||||
sendWSall("/swap/X/" + str(laserid) + " 1")
|
||||
else:
|
||||
sendWSall("/swap/X/" + str(laserid)+ " 0")
|
||||
sendWSall("/swap/X/" + str(laserid) + " 0")
|
||||
|
||||
if gstt.swapY[laserid] == 1:
|
||||
sendWSall("/swap/Y/" + str(laserid)+ " 1")
|
||||
sendWSall("/swap/Y/" + str(laserid) + " 1")
|
||||
else:
|
||||
sendWSall("/swap/Y/" + str(laserid)+ " 0")
|
||||
sendWSall("/swap/Y/" + str(laserid) + " 0")
|
||||
|
||||
|
||||
# Called for every WS client disconnecting
|
||||
def client_left(client, wserver):
|
||||
@ -317,16 +318,15 @@ def client_left(client, wserver):
|
||||
|
||||
# Called for each WS received message.
|
||||
def message_received(client, wserver, message):
|
||||
|
||||
#if len(message) > 200:
|
||||
# if len(message) > 200:
|
||||
# message = message[:200]+'..'
|
||||
|
||||
#if gstt.debug >0:
|
||||
# if gstt.debug >0:
|
||||
# print ("")
|
||||
# print("WS Client(%d) said: %s" % (client['id'], message))
|
||||
|
||||
oscpath = message.split(" ")
|
||||
#print "WS Client", client['id'], "said :", message, "splitted in an oscpath :", oscpath
|
||||
# print "WS Client", client['id'], "said :", message, "splitted in an oscpath :", oscpath
|
||||
if gstt.debug > 0:
|
||||
print("WS Client", client['id'], "said :", message, "splitted in an oscpath :", oscpath)
|
||||
|
||||
@ -340,30 +340,28 @@ def message_received(client, wserver, message):
|
||||
if oscpath[0].find(plugin) != -1:
|
||||
|
||||
message4plugin = True
|
||||
#print(oscpath)
|
||||
# print(oscpath)
|
||||
if plugins.Send(plugin, oscpath):
|
||||
print("plugins sent incoming WS correctly to", plugin)
|
||||
else:
|
||||
print("plugins detected", plugin, "offline.")
|
||||
|
||||
|
||||
# WS received message is an LJ command
|
||||
|
||||
if message4plugin == False:
|
||||
|
||||
if len(oscpath) == 1:
|
||||
args[0] = "noargs"
|
||||
#print "noargs command"
|
||||
# print "noargs command"
|
||||
|
||||
elif len(oscpath) > 1:
|
||||
args[0] = str(oscpath[1])
|
||||
#print "arg",oscpath[1]
|
||||
|
||||
commands.handler(oscpath[0].split("/"),args)
|
||||
# print "arg",oscpath[1]
|
||||
|
||||
commands.handler(oscpath[0].split("/"), args)
|
||||
|
||||
# if needed a loop back : WS Client -> server -> WS Client
|
||||
#sendWSall("ws"+message)
|
||||
# sendWSall("ws"+message)
|
||||
|
||||
|
||||
def handle_timeout(self):
|
||||
@ -371,10 +369,11 @@ def handle_timeout(self):
|
||||
|
||||
|
||||
def sendWSall(message):
|
||||
#if gstt.debug >0:
|
||||
#print("WS sending %s" % (message))
|
||||
# if gstt.debug >0:
|
||||
# print("WS sending %s" % (message))
|
||||
wserver.send_message_to_all(message)
|
||||
|
||||
|
||||
'''
|
||||
print ""
|
||||
print "Midi Configuration"
|
||||
@ -382,9 +381,10 @@ midi.InConfig()
|
||||
midi.OutConfig()
|
||||
'''
|
||||
|
||||
|
||||
def fff(name):
|
||||
print()
|
||||
print('HELLO', name ) #indent
|
||||
print('HELLO', name) # indent
|
||||
print()
|
||||
|
||||
|
||||
@ -395,26 +395,24 @@ def fff(name):
|
||||
print("")
|
||||
log.info("Creating startup point lists...")
|
||||
|
||||
if r.set("/clientkey", "/pl/" + str(gstt.SceneNumber) + "/") == True:
|
||||
print("sent clientkey : /pl/" + str(gstt.SceneNumber) + "/")
|
||||
|
||||
if r.set("/clientkey","/pl/"+str(gstt.SceneNumber)+"/")==True:
|
||||
print("sent clientkey : /pl/"+str(gstt.SceneNumber)+"/")
|
||||
|
||||
#pdb.set_trace()
|
||||
for sceneid in range(0,gstt.MaxScenes+1):
|
||||
print("Scene "+ str(sceneid))
|
||||
#digit_points = font1.DigitsDots(sceneid,65280)
|
||||
# pdb.set_trace()
|
||||
for sceneid in range(0, gstt.MaxScenes + 1):
|
||||
print("Scene " + str(sceneid))
|
||||
# digit_points = font1.DigitsDots(sceneid,65280)
|
||||
|
||||
# Order all lasers to show its number at startup -> tell all 4 laser process to USER PLs
|
||||
for laserid in range(0,gstt.LaserNumber):
|
||||
for laserid in range(0, gstt.LaserNumber):
|
||||
|
||||
digit_points = font1.DigitsDots(laserid,65280)
|
||||
if r.set('/pl/'+str(sceneid)+'/'+str(laserid), str(digit_points)) == True:
|
||||
digit_points = font1.DigitsDots(laserid, 65280)
|
||||
if r.set('/pl/' + str(sceneid) + '/' + str(laserid), str(digit_points)) == True:
|
||||
pass
|
||||
#print( ast.literal_eval(r.get('/pl/'+str(sceneid)+'/'+str(laserid)).decode('ascii')))
|
||||
#print("/pl/"+str(sceneid)+"/"+str(laserid)+" "+str(ast.literal_eval(r.get('/pl/'+str(sceneid)+'/'+str(laserid)).decode('ascii'))))
|
||||
|
||||
r.set('/order/'+str(laserid), 0)
|
||||
# print( ast.literal_eval(r.get('/pl/'+str(sceneid)+'/'+str(laserid)).decode('ascii')))
|
||||
# print("/pl/"+str(sceneid)+"/"+str(laserid)+" "+str(ast.literal_eval(r.get('/pl/'+str(sceneid)+'/'+str(laserid)).decode('ascii'))))
|
||||
|
||||
r.set('/order/' + str(laserid), 0)
|
||||
|
||||
#
|
||||
# Starts one DAC process per requested Laser
|
||||
@ -434,33 +432,35 @@ if __name__ == '__main__':
|
||||
else:
|
||||
log.infog("Resquested DACs mode")
|
||||
|
||||
lasernumber = gstt.LaserNumber -1
|
||||
lasernumber = gstt.LaserNumber - 1
|
||||
print("LaserNumber = ", gstt.LaserNumber)
|
||||
|
||||
log.info("Starting " + str(gstt.LaserNumber) + " DACs process...")
|
||||
|
||||
log.info("Starting "+str(gstt.LaserNumber) + " DACs process...")
|
||||
|
||||
# Launch one process (a tracer3 instance) by etherdream
|
||||
dac_worker0= Process(target=dac_process, args=(0,0,))
|
||||
# Launch one process (a tracer3 instance) for etherdream / helios
|
||||
dac_family = None
|
||||
if config["laser0"].get("dac_family"):
|
||||
dac_family = config["laser0"]["dac_family"]
|
||||
dac_worker0 = Process(target=dac_process, args=(0, 0, dac_family))
|
||||
dac_worker0.start()
|
||||
commands.worker0 = dac_worker0
|
||||
print("Tracer 0 : name", dac_worker0.name , "pid", dac_worker0.pid )
|
||||
print("Tracer 0 : name", dac_worker0.name, "pid", dac_worker0.pid)
|
||||
|
||||
if lasernumber >0:
|
||||
dac_worker1= Process(target=dac_process, args=(1,0,))
|
||||
if lasernumber > 0:
|
||||
dac_worker1 = Process(target=dac_process, args=(1, 0,))
|
||||
commands.worker1 = dac_worker1
|
||||
print("Tracer 1 : name", dac_worker1.name , "pid", dac_worker1.pid )
|
||||
print("Tracer 1 : name", dac_worker1.name, "pid", dac_worker1.pid)
|
||||
dac_worker1.start()
|
||||
|
||||
if lasernumber >1:
|
||||
dac_worker2= Process(target=dac_process, args=(2,0,))
|
||||
if lasernumber > 1:
|
||||
dac_worker2 = Process(target=dac_process, args=(2, 0,))
|
||||
dac_worker2.start()
|
||||
commands.worker2 = dac_worker2
|
||||
print("Tracer 2 : name", dac_worker2.name , "pid", dac_worker2.pid )
|
||||
print("Tracer 2 : name", dac_worker2.name, "pid", dac_worker2.pid)
|
||||
|
||||
if lasernumber >2:
|
||||
dac_worker3= Process(target=dac_process, args=(3,0,))
|
||||
print("Tracer 3 : name", dac_worker3.name , "pid", dac_worker3.pid )
|
||||
if lasernumber > 2:
|
||||
dac_worker3 = Process(target=dac_process, args=(3, 0,))
|
||||
print("Tracer 3 : name", dac_worker3.name, "pid", dac_worker3.pid)
|
||||
commands.worker3 = dac_worker3
|
||||
dac_worker3.start()
|
||||
print("")
|
||||
@ -472,29 +472,29 @@ if __name__ == '__main__':
|
||||
try:
|
||||
|
||||
# Websocket startup
|
||||
wserver = WebsocketServer(wsPORT,host=serverIP)
|
||||
wserver = WebsocketServer(wsPORT, host=serverIP)
|
||||
plugins.Init(wserver)
|
||||
|
||||
log.info("Starting servers...")
|
||||
# Launch OSC thread listening to oscserver
|
||||
print("Launching OSC server...")
|
||||
print("at", oscserverIPin, "port",str(oscserverPORTin))
|
||||
oscserver.addMsgHandler( "/noteon", commands.NoteOn)
|
||||
oscserver.addMsgHandler( "/scim", commands.Scim)
|
||||
oscserver.addMsgHandler( "/line1", commands.Line1)
|
||||
oscserver.addMsgHandler( "/forwardui", commands.ForwardUI)
|
||||
# Default OSC handler for all OSC incoming message
|
||||
oscserver.addMsgHandler("default", handler)
|
||||
_thread.start_new_thread(osc_thread, ())
|
||||
# print("Launching OSC server...")
|
||||
# print("at", oscserverIPin, "port", str(oscserverPORTin))
|
||||
# oscserver.addMsgHandler("/noteon", commands.NoteOn)
|
||||
# oscserver.addMsgHandler("/scim", commands.Scim)
|
||||
# oscserver.addMsgHandler("/line1", commands.Line1)
|
||||
# oscserver.addMsgHandler("/forwardui", commands.ForwardUI)
|
||||
# # Default OSC handler for all OSC incoming message
|
||||
# oscserver.addMsgHandler("default", handler)
|
||||
# _thread.start_new_thread(osc_thread, ())
|
||||
|
||||
print("Launching webUI Websocket server...")
|
||||
print("at", serverIP, "port",wsPORT)
|
||||
print("at", serverIP, "port", wsPORT)
|
||||
wserver.set_fn_new_client(new_client)
|
||||
wserver.set_fn_client_left(client_left)
|
||||
wserver.set_fn_message_received(message_received)
|
||||
print("")
|
||||
log.info("Resetting all Homographies...")
|
||||
for laserid in range(0,gstt.LaserNumber):
|
||||
for laserid in range(0, gstt.LaserNumber):
|
||||
homographyp.newEDH(laserid)
|
||||
|
||||
# plugins autostart
|
||||
@ -530,6 +530,3 @@ if __name__ == '__main__':
|
||||
|
||||
random_points = [(300.0+random.randint(-100, 100), 200.0+random.randint(-100, 100), 0), (500.0+random.randint(-100, 100), 200.0+random.randint(-100, 100), 65280), (500.0+random.randint(-100, 100), 400.0+random.randint(-100, 100), 65280), (300.0+random.randint(-100, 100), 400.0+random.randint(-100, 100), 65280), (300.0+random.randint(-100, 100), 200.0+random.randint(-100, 100), 65280)]
|
||||
'''
|
||||
|
||||
|
||||
|
||||
|
@ -1,48 +1,39 @@
|
||||
#!/bin/bash
|
||||
sudo apt upgrade
|
||||
sudo apt install python3-pip
|
||||
sudo apt install redis-server
|
||||
# for dedicated computer after fresh linux install. todo : ask if needed.
|
||||
#sudo apt install git
|
||||
#sudo apt install syncthing
|
||||
#sudo apt install htop
|
||||
#sudo apt install screen
|
||||
#sudo apt install tmux
|
||||
#sudo apt install nginx
|
||||
#sudo apt install supervisor
|
||||
#sudo apt install ssh
|
||||
# todo one day : modify correct path in syncthing.conf
|
||||
#sudo cp syncthing.conf to /etc/supervisor/conf.d/
|
||||
pip3 install scipy
|
||||
pip3 install numpy
|
||||
#pip install pygame==1.9.2
|
||||
#pip3 install pygame==1.9.2
|
||||
pip3 install redis
|
||||
pip3 install pysimpledmx
|
||||
pip3 install DMXEnttecPro
|
||||
sudo apt install libasound2-dev
|
||||
sudo apt install libjack-dev
|
||||
pip3 install python-rtmidi
|
||||
pip3 install mido
|
||||
git clone https://github.com/ptone/pyosc --depth 1 /tmp/pyosc && cd /tmp/pyosc && sudo ./setup.py install
|
||||
pip3 install tk
|
||||
cd ../
|
||||
python3 configure.py
|
||||
# todo : ask for computer ip and run updateUI.py
|
||||
cd /tmp
|
||||
sudo apt install portaudio19-dev
|
||||
sudo apt install cmake
|
||||
git clone https://github.com/Ableton/link.git
|
||||
cd link
|
||||
git submodule update --init --recursive
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
cmake --build .
|
||||
cd /tmp/
|
||||
git clone --recursive https://github.com/gonzaloflirt/link-python.git
|
||||
cd link-python
|
||||
mkdir build
|
||||
cd build
|
||||
cmake ..
|
||||
cmake --build .
|
||||
|
||||
# Check if root
|
||||
[[ 0 -ne $UID ]] && { echo "Must run as root. Exiting."; exit; }
|
||||
|
||||
# Require a user for exploitation
|
||||
DEFAULT=$(getent passwd 1000|cut -d: -f1)
|
||||
read -e -i "$DEFAULT" -p "Please provide the system user who will own the project: " USER
|
||||
|
||||
getent passwd "$USER" &>/dev/null || { echo "Sorry, but '$USER' does not exist on this system. Exiting."; exit 2; }
|
||||
|
||||
# Propose some packages
|
||||
echo -e "\nThe following packages are not mandatory, add them as needed.\n"
|
||||
declare -a ADD_PACK
|
||||
POS_PACK=( htop nginx screen ssh ssl-cert supervisor syncthing tmux )
|
||||
POS_PACK_LEN=${#POS_PACK[@]}
|
||||
for i in ${!POS_PACK[@]} ; do
|
||||
pack=${POS_PACK[i]}
|
||||
read -e -n 1 -p "$((i+1))/${POS_PACK_LEN} Add package ${pack} ? [Y/n]: "
|
||||
REPLY=${REPLY:-Y}
|
||||
[[ "Y" == ${REPLY^^} ]] && ADD_PACK+=(${pack})
|
||||
done
|
||||
|
||||
# Propose the install
|
||||
PACK_LIST=$( echo "cmake git libasound2-dev libjack-dev libsdl1.2-dev network-manager portaudio19-dev python3-dev python3-pip python3-rtmidi redis-server ${ADD_PACK[@]}" | sort )
|
||||
echo -e "\nYou are goind to install:\n$( for pack in ${PACK_LIST[@]}; do echo ' * '$pack; done; )\n"
|
||||
read -e -n1 -p "OK? [Y/n]: "
|
||||
REPLY=${REPLY:-Y}
|
||||
[[ "N" == ${REPLY^^} ]] && exit
|
||||
|
||||
# Run the install
|
||||
apt install -y --no-install-recommends $PACK_LIST
|
||||
pip3 install setuptools
|
||||
pip3 install DMXEnttecPro mido numpy pysimpledmx redis scipy
|
||||
git clone https://github.com/ptone/pyosc --depth 1 /tmp/pyosc && cd /tmp/pyosc && ./setup.py install
|
||||
cd /tmp && git clone https://github.com/Ableton/link.git && cd link && git submodule update --init --recursive && mkdir build && cd build && cmake .. && cmake --build .
|
||||
cd /tmp/ && git clone --recursive https://github.com/gonzaloflirt/link-python.git && cd link-python && mkdir build && cd build && cmake .. && cmake --build .
|
||||
cd /opt/ && git clone https://git.interhacker.space/teamlaser/LJ
|
||||
chown -R $USER /opt/LJ
|
||||
|
Loading…
Reference in New Issue
Block a user