diff --git a/README.md b/README.md index 5c9232e..bbf8966 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ LJ is in dev : versions in this repository will always be core functionnal : acc # Install # -With Linux, in LJ directory, type in a terminal window : +With Linux Buster, in LJ directory, type in a terminal window : cd server ./install.sh diff --git a/libs3/lj23layers.sync-conflict-20200803-100618-TAXKCAL.py b/libs3/lj23layers.sync-conflict-20200803-100618-TAXKCAL.py deleted file mode 100644 index fdfce35..0000000 --- a/libs3/lj23layers.sync-conflict-20200803-100618-TAXKCAL.py +++ /dev/null @@ -1,986 +0,0 @@ -#!/usr/bin/python3 -# -*- coding: utf-8 -*- -# -*- mode: Python -*- - -''' - -lj23layers v0.7.6 for LJ v0.8+ - -LJ functions (API) for python plugins/clients - -"layers" version : -- "PL" has been replaced by "layer" -- "Client" - -Each program using LJ should declare itself by call lj23layers Config : - -Config(redisIP, client number, name) - - -Basic Draw : - -- PolyLineOneColor, rPolyLineOneColor, LineTo, Line -- PolyLineRGB, rPolyLineRGB, LineRGBTo, LineRGB -- rgb2int(r,g,b) -- Drawlayer (point list number) : once you stacked all wanted elements, like 2 polylines, send them to lasers. -- DrawDests(): Draw all requested destinations for each layer . - -High level draw : - -- Text(word, integercolor, layer , xpos, ypos, resize, rotx, roty, rotz) : Display a word -- TextRGB(word, red, green, blue, ...) -- Embeded font1 - - -Laser objects (name and convenient group of parameters for one or several point lists) - -- RelativeObject -- FixedObject - -"Destinations" : Tell for given Layer a scene/Laser ("destination"). -Each Layer can have different destination (i.e to display same stuff on different laser) - - -OSC and plugins functions : - -SendLJ(adress,message) : LJ remote control. See commands.py -SendResol(address,message): Send OSC message to Resolume. -WebStatus(message) : display message on webui - -Ljscene(client): Change scene number in redis keys -Ljlayer(layer): Change layer number in redis keys = laser target. -ClosePlugin(name): Send UI closing info of given plugin - -OSCstart(): Start the OSC system. -OSCframe(): Handle incoming OSC message. Calling the right callback -OSCstop(): Properly close the OSC system -OSCping(): /ping Answer to LJ pings by sending /pong name -OSCquit(): /quit Exit calling script using name in terminal -OSCadddest(): layer , scene, laser Add a destination -OSCdeldest(): layer , scene, lasers delete a destination -OSCobj(): /name/obj objectname attribute value for automation -OSCvar(): /name/var variablename value for automation - - -Joystick management is removed. Get it back in todolist - -setup_controls(joystick) - -XboxController : getLeftHori, getLeftVert, getRightHori, getRightVert, getLeftTrigger, getRightTrigger -Ps3Controller : getLeftHori, getLeftVert, getRightHori, getRightVert, getLeftTrigger, getRightTrigger, getUp, getDown, getLeft, getRight, getFire1, getFire2(self): -MySaitekController : getLeftHori,getLeftVert, getRightHori,getRightVert, getLeftTrigger,getRightTrigger -MyThrustController : getLeftHori, getLeftVert, getRightHori, getRightVert, getLeftTrigger, getRightTrigger -CSLController : getLeftHori,getLeftVert,getRightHori, getRightVert,getLeftTrigger,getRightTrigger,getFire1,getFire2 -my USB Joystick : getUp,getDown,getLeft,getRight,etLeftTrigger, getRightTrigger,getFire1, getFire2 - - - -Class management manuals: - -https://stackoverflow.com/questions/739882/iterating-over-object-instances-of-a-given-class-in-python -https://stackoverflow.com/questions/8628123/counting-instances-of-a-class -http://effbot.org/pyfaq/how-do-i-get-a-list-of-all-instances-of-a-given-class.htm - - -LICENCE : CC -Sam Neurohack - -''' - -import math -import redis -import sys -import weakref -import struct -import numpy as np -import gstt -from multiprocessing import Process, Queue, TimeoutError - -is_py2 = sys.version[0] == '2' -if is_py2: - from OSC import OSCServer, OSCClient, OSCMessage - #print ("Importing lj23 and OSC from libs...") -else: - from OSC3 import OSCServer, OSCClient, OSCMessage - #print ("Importing lj23 and OSC3 from libs...") - - -#redisIP = '127.0.0.1' -#r = redis.StrictRedis(host=redisIP, port=6379, db=0) - -ClientNumber = 0 -name = "noname" -oscrun = True -point_list = [] -layers = [[],[],[],[],[],[],[],[],[],[]] - -fft3Groups = [-1,-1,-1,-1] - -Dests = dict() - -oscIPresol = "127.0.0.1" -oscPORTresol = 7000 - -# 3D to 2D projection parameters -fov = 256 -viewer_distance = 2.2 - - -''' - - Laser "objects" - - - set a name and convenient group of parameters for one or several point lists - - RelativeObject is for point lists around 0,0 with builtin move/rotation. - - How to init with object color, xpos,... : - osciObj = lj.RelativeObject('osciObj', True, 255, [], white, red, green,blue,0 , False, centerX , centerY , 1 , Xrot , Yrot , Zrot) - How to use in drawing functions : you're free to use 0, some or all of any laserobject attributes - - draw one or several pointlists with 'A' laserobject color and 'B' laserobject xpos ypos ? - - Change color of 'main' object and all other objects using it will change also - how to change attribute : - osciObj.resize = 2 or /pluginame/change 'OsciObj' 'resize' 2 - -''' - -class RelativeObject: - - kind = 'relative' - counter = 0 - - def __init__(self, name, active, intensity, xy, color, red, green, blue, layer , closed, xpos , ypos , resize , rotx , roty , rotz): - self.name = name - self.active = active # True/False - self.intensity = intensity - self.xy = [] # Dots list - self.color = color # RGB color in int - self.red = red - self.green = green - self.blue = blue - self.layer = layer - self.closed = closed - self.xpos = xpos - self.ypos = ypos - self.resize = resize - self.rotx = rotx - self.roty = roty - self.rotz = rotz - - RelativeObject.counter += 1 - #type(self).counter += 1 - - def __del__(self): - RelativeObject.counter -= 1 - - -# Fixed Laser object : point list in 'pygame' space (top left = 0,0 / bottom right) -class FixedObject: - - kind = 'fixed' - counter = 0 - - def __init__(self, name, intensity, active, xy, color, red, green, blue, layer , closed): - self.name = name - self.active = active # True/False - self.intensity = intensity - self.xy = [] - self.color = color - self.red = red - self.green = green - self.blue = blue - self.layer = layer - self.closed = closed - - FixedObject.counter += 1 - - def __del__(self): - FixedObject.counter -= 1 - -''' - -class IterDest(type): - def __new__ (cls, name, bases, dct): - dct['_instances'] = [] - return super().__new__(cls, name, bases, dct) - - def __call__(cls, *args, **kwargs): - instance = super().__call__(*args, **kwargs) - cls._instances.append(instance) - return instance - - def __iter__(cls): - return iter(cls._instances) - -class DestObject(): - -# class Destinations(metaclass=IterDest): - __metaclass__ = IterDest - counter = 0 - def __init__(self, name, number, active, layer , scene, laser): - self.name = name - self.number = number - self.active = active - self.layer = layer - self.scene = scene - self.laser = laser - - DestObject.counter += 1 - - def __del__(self): - DestObject.counter -= 1 -''' -class DestObject(): - -# class Destinations(metaclass=IterDest): - _instances = set() - counter = 0 - - def __init__(self, name, number, active, layer , scene, laser): - self.name = name - self.number = number - self.active = active - self.layer = layer - self.scene = scene - self.laser = laser - self._instances.add(weakref.ref(self)) - DestObject.counter += 1 - - @classmethod - def getinstances(cls): - dead = set() - for ref in cls._instances: - obj = ref() - if obj is not None: - yield obj - else: - dead.add(ref) - cls._instances -= dead - - - def __del__(self): - DestObject.counter -= 1 - - - -def Config(redIP,client,myname): - global ClientNumber, name, redisIP, r - - redisIP = redIP - r = redis.StrictRedis(host=redisIP, port=6379, db=0) - - # ClientNumber 255 are not drawing anything like artnet - ClientNumber = client - #print ("client configured",ClientNumber) - name = myname - print ("lj23layers : Plugin declare its name :",name) - #print layer - return r - - -def LjClient(client): - global ClientNumber - - ClientNumber = client - - - -def Ljlayer(somelayer): - global layer - - layer = somelayer - - -def fromRedis(n): - - encoded = r.get(n) - #print("") - #print('fromredis key',n,":",encoded) - h, w = struct.unpack('>II',encoded[:8]) - #print("fromredis array size",n,":",h,w) - a = np.frombuffer(encoded, dtype=np.int16, offset=8).reshape(h,w) - #print("fromredis array",n,":",a) - return a - -# Store Numpy array 'a' in Redis key 'n' -# Write also in redis key 'a' numpy array, its 2 dimensions size : h time w values -def toRedis(n,a): - - #print("array.shape", a.shape, len(a.shape) ) - if len(a.shape) == 1: - h = a.shape[0] - w = 1 - else: - h,w = a.shape - #print("toredis", n,"h",h,"w",w,"a",a) - shape = struct.pack('>II',h,w) - - #shape = struct.pack('>II',len(a),1) - #print("toredis",n,a) - encoded = shape + a.tobytes() - - # Store encoded data in Redis - return r.set(n,encoded) - - -# -# OSC functions -# - -# OSC clients - -def SendLJ(oscaddress,oscargs=''): - - oscmsg = OSCMessage() - oscmsg.setAddress(oscaddress) - oscmsg.append(oscargs) - - osclientlj = OSCClient() - osclientlj.connect((redisIP, 8002)) - - print("lj23layers for",name,"sending OSC message :", oscmsg, "to", redisIP, ":8002") - if gstt.debug >0: - print("lj23layers for",name,"sending OSC message :", oscmsg, "to", redisIP, ":8002") - try: - osclientlj.sendto(oscmsg, (redisIP, 8002)) - oscmsg.clearData() - except: - print ('Connection to LJ refused : died ?') - pass - #time.sleep(0.001 - - - -# Resolume OSC Arena client. -# sendresol(oscaddress, [arg1, arg2,...]) -# example : sendresol("/noteon",note) - -def SendResol(oscaddress,oscargs): - - oscmsg = OSCMessage() - oscmsg.setAddress(oscaddress) - oscmsg.append(oscargs) - - osclientresol = OSCClient() - osclientresol.connect((oscIPresol, oscPORTresol)) - - print("lj23layers sending OSC message : ", oscmsg, "to Resolume", oscIPresol, ":", oscPORTresol) - try: - osclientresol.sendto(oscmsg, (oscIPresol, oscPORTresol)) - oscmsg.clearData() - except: - print ('Connection to Resolume refused : died ?') - pass - - -def SendIntensity(laser, intensity): - r.set('/intensity/' + str(laser), str(intensity)) - r.set('/order/'+str(laser), 6) - SendLJ("/kpps/" + str(layer)+ " " + str(int(args[1]))) - - -def Sendkpps(laser, kpps): - r.set('/kpps/' + str(laser), str(kpps)) - r.set('/order/'+str(laser), 7) - - -def WebStatus(message): - SendLJ("/status", message) - - -# Closing plugin messages to LJ -def ClosePlugin(): - WebStatus(name+" Exiting") - SendLJ("/"+name+"/start",0) - - - - -# RAW OSC Frame available ? -def OSCframe(): - # clear timed_out flag - #print "oscframe" - oscserver.timed_out = False - # handle all pending requests then return - while not oscserver.timed_out: - oscserver.handle_request() - -# Answer to LJ pings with /pong value -def OSCping(path, tags, args, source): -#def OSCping(): - if gstt.debug >0: - print(name, "lj23layers got /ping from LJ -> reply /pong", name) - SendLJ("/pong",name) - -# Properly close the system. Todo -def OSCstop(): - oscserver.close() - - -# /quit -def OSCquit(path, tags, args, source): - global oscrun - - oscrun = False - print('lj23layers got /quit for',name) - #WebStatus(name + " quit.") - #SendLJ("/"+name+"/start",0) - #print("Stopping OSC...") - #OSCstop() - #sys.exit() - - -# default handler -def OSChandler(path, tags, args, source): - - oscaddress = ''.join(path.split("/")) - print("lj23layers Default OSC Handler for",name,": msg from Client :" + str(source[0]),) - print("OSC address", path) - if len(args) > 0: - print("with args", args) - - #oscIPout = str(source[0]) - #osclient.connect((oscIPout, oscPORTout)) - - -# for any laser object : /pluginame/obj objectname attribute value -# like : /pluginname/obj 'fft' 'xpos' 100 -# attributes for all lj Objects: name, xy_list, c, layer -# + for RelativeObjects : closed, xpos , ypos , resize , rotx , roty , rotz -def OSCobj(path, tags, args, source): - - obj = eval(args[0]+"."+ args[1]) - obj = args[2] - - -def OSCvar(path, tags, args, source): - - obj = eval(args[0]) - obj = args[1] - - -def addOSCdefaults(server): - global oscserver - - oscserver = server - oscserver.addMsgHandler( "default", OSChandler ) - oscserver.addMsgHandler( "/ping", OSCping) - oscserver.addMsgHandler( "/quit", OSCquit) - oscserver.addMsgHandler( "/"+ name + "/adddest", OSCadddest) - oscserver.addMsgHandler( "/"+ name + "/deldest", OSCdeldest) - oscserver.addMsgHandler( "/"+ name + "/dest", OSCdest) - oscserver.addMsgHandler( "/"+ name + "/obj", OSCobj) - oscserver.addMsgHandler( "/"+ name + "/var", OSCvar) - - - -# -# Color functions -# - -# input hexcode = '0xff00ff' -def hex2rgb(hexcode): - - hexcode = hexcode[2:] - return tuple(int(hexcode[i:i+2], 16) for i in (0, 2, 4)) - #return tuple(map(ord,hexcode[1:].decode('hex'))) - -# input rgb=(255,0,255) output '0xff00ff' -#def rgb2hex(rgb): -# return '0x%02x%02x%02x' % tuple(rgb) - -def rgb2hex(r, g, b): - return hex((r << 16) + (g << 8) + b) - - -#def rgb2int(rgb): -# return int('0x%02x%02x%02x' % tuple(rgb),0) - -def rgb2int(r,g,b): - return int('0x%02x%02x%02x' % (r,g,b),0) - -def int2rgb(intcode): - #hexcode = '0x{0:06X}'.format(intcode) - hexcode = '{0:06X}'.format(intcode) - return tuple(int(hexcode[i:i+2], 16) for i in (0, 2, 4)) - - - -# -# Drawing basic functions -# - -# Lines -def Line(xy1, xy2, c, layer ): - LineTo(xy1, 0, layer ) - LineTo(xy2, c , layer ) - -def rLine(xy1, xy2, c, layer , xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0): - rLineTo(xy1, 0, layer ) - rLineTo(xy2, c , layer ) - -def LineRGB(xy1, xy2, red,green,blue, layer ): - - LineTo(xy1, 0, layer ) - LineTo(xy2, int('0x%02x%02x%02x' % (red,green,blue),0) , layer ) - - -# Lineto -def LineTo(xy, c, layer ): - - layers[layer].append((xy + (c,))) - -def LineRGBTo(xy, red, green, blue, layer ): - - LineTo(xy, int('0x%02x%02x%02x' % (red,green,blue),0), layer ) - -def rLineTo(xy, c, layer , xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0): - - layers[layer ].append((Pointransf(xy, xpos, ypos, resize, rotx, roty, rotz) + (c,))) - - -# Polylines -def PolyLineOneColor(xy_list, c, layer , closed ): - #print "--" - #print "c",c - #print "xy_list",xy_list - #print "--" - xy0 = None - for xy in xy_list: - if xy0 is None: - xy0 = xy - #print "xy0:",xy0 - LineTo(xy0,0, layer ) - LineTo(xy0,c, layer ) - else: - #print "xy:",xy - LineTo(xy,c, layer ) - if closed: - LineTo(xy0,c, layer ) - -def PolyLineRGB(xy_list, red, green, blue, layer , closed ): - - PolyLineOneColor(xy_list, int('0x%02x%02x%02x' % (red,green,blue),0), layer , closed ) - - -# rPolylines -# Send 2D point list around 0,0 with 3D rotation resizing and reposition around xpos ypos -#def rPolyLineOneColor(self, xy_list, c, layer , closed, xpos = 0, ypos =0, resize =1, rotx =0, roty =0 , rotz=0): -def rPolyLineOneColor(xy_list, c, layer , closed, xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0): - xy0 = None - for xy in xy_list: - print(xy,xy0) - if xy0 is None: - xy0 = xy - LineTo(Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz), 0, layer ) - LineTo(Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz), c, layer ) - else: - LineTo(Pointransf(xy, xpos, ypos, resize, rotx, roty, rotz), c, layer ) - if closed: - LineTo(Pointransf(xy0, xpos, ypos, resize, rotx, roty, rotz), c, layer ) - -def rPolyLineRGB(xy_list, red, green, blue, layer , closed, xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0): - - rPolyLineOneColor(xy_list, int('0x%02x%02x%02x' % (red,green,blue),0), layer , closed, xpos = 0, ypos =0, resize =0.7, rotx =0, roty =0 , rotz=0) - - - -# Computing points coordinates for rPolyline function from 3D and around 0,0 to pygame coordinates -def Pointransf(xy, xpos = 0, ypos =0, resize =1, rotx =0, roty =0 , rotz=0): - - x = xy[0] * resize - y = xy[1] * resize - z = xy[2] * resize - - rad = math.radians(rotx) - cosaX = math.cos(rad) - sinaX = math.sin(rad) - - y2 = y - y = y2 * cosaX - z * sinaX - z = y2 * sinaX + z * cosaX - - rad = math.radians(roty) - cosaY = math.cos(rad) - sinaY = math.sin(rad) - - z2 = z - z = z2 * cosaY - x * sinaY - x = z2 * sinaY + x * cosaY - - rad = math.radians(rotz) - cosZ = math.cos(rad) - sinZ = math.sin(rad) - - x2 = x - x = x2 * cosZ - y * sinZ - y = x2 * sinZ + y * cosZ - - #print xy, (x + xpos,y+ ypos) - #return (x + xpos, y + ypos) - - #to understand why it get negative Y - """ Transforms this 3D point to 2D using a perspective projection. """ - factor = fov / (viewer_distance + z) - x = x * factor + xpos - y = y * factor + ypos - #y = - y * factor + ypos - return (x, y) - - -def Lineslayer(layer): - print("Stupido !! your code is to old : use Drawlayer() instead of LinesPL()") - Drawlayer(layer ) - - -def Draw(layer): - #print '/pl/0/'+str(layer), str(layers[layer]) - if r.set('/pl/'+str(ClientNumber)+'/'+str(layer), str(layers[layer])) == True: - #print '/pl/'+str(ClientNumber)+'/'+str(layer), str(layers[layer]) - layers[layer] = [] - return True - else: - return False - -def Resetlayer(self, layer): - layers[layer] = [] - - -# -# "Destinations" management for layers -# - - -# Add a destination for a given layer -def Addest(layer, scene, laser): - - print (name,'adding',layer,scene,laser,'?') - if Findest(layer, scene, laser) == -1: - newdest = DestsObjects.counter + 1 - Dest0 = lj.DestObject(str(newdest), newdest, True, layer , scene, laser) - print("New destination added with number", newdest) - else: - print("Destination already existed") - - -# OSC add a destination for a given layer -# /pluginame/dest layer, scene, laser -def OSCadddest(path, tags, args, source): - - Addests(int(args[0]),int(args[1]),int(args[2])) - - -# Find layer destination with its parameters in destinations dictionnary -def Findest(layer, scene, laser): - - print(name, 'searching layer,scene,laser',layer,scene,laser) - for item in DestObjects.getinstances(): - #print(item) - if item.layer == layer and item.scene == scene and item.laser == laser: - #Dests.append(item[0]) - print('found number',item.number) - return item.number - else: - print('no destination found') - return -1 - ''' - #Dests = list() - allDests = Dests.items() - for item in allDests: - print(item) - if item[1] == layer and item[2] == scene and item[3] == laser: - #Dests.append(item[0]) - return Dests[item[0]] - else: - return -1 - ''' - -# Find and remove a layer destination with its parameters in destinations dictionnary -def Deldest(layer, scene, laser): - - Destnumber = Findest(layer, scene, laser) - print(name,'deleting Destination layer, scene, laser', layer,scene, laser) - - if Destnumber != -1: - print('found DestObject', Destnumber) - delattr(DestObjects, str(Destnumber)) - print("Destination", Destnumber,"was removed") - else: - print("Destination was not found") - - -# OSC Delete a destination for a given layer -# /pluginame/deldests layer, scene, laser -def OSCdeldest(path, tags, args, source): - - Deldests(args[0], args[1], args[2]) - - -# pluginame/dest layer, scene, laser -def OSCdest(path, tags, args, source): - - # For single layer plugin : add a new destination - Addest(0, args[0], args[1]) - - # For single layer plugin : remove a destination - - # For multiple layers plugin : add or remove - - -# Replace Drawlayer if Destinations paradigm is implemented in plugin code -def DrawDests(): - - # Objects style - - #print("DrawDest") - - for destination in DestObject.getinstances(): - - #print(Dests[str(destination)]) - #print('/pl/'+str(Dests[str(destination)]["scene"])+'/'+str(Dests[str(destination)]["laser"]), ":", str(layers[Dests[str(destination)]["PL"]])) - #print(len(layers[destination.layer])) - if destination.active == True: - if r.set('/pl/'+str(destination.scene)+'/'+str(destination.laser), str(layers[destination.layer])) == True: - #print ('layer', destination.layer, '/pl/'+str(destination.scene)+'/'+str(destination.laser), str(layers[destination.layer])) - pass - else: - print('Redis key modification failed') - - # Maybe one layer can be sent to multiple destination so they are all reset *after* all sending. - for layerss in range(4): - - layers[layerss] = [] - - ''' - # Dictionnary style - - #print(Dests) - for destination in range(len(Dests)): - #print(Dests[str(destination)]) - #print('/pl/'+str(Dests[str(destination)]["scene"])+'/'+str(Dests[str(destination)]["laser"]), ":", str(layers[Dests[str(destination)]["layer"]])) - if r.set('/pl/'+str(Dests[str(destination)]["scene"])+'/'+str(Dests[str(destination)]["laser"]), str(layers[Dests[str(destination)]["layer"]])) == True: - #print '/pl/'+str(ClientNumber)+'/'+str(layer), str(layers[layer]) - pass - else: - print('Redis key modification failed') - - # Maybe one layer can be sent to multiple destination so they are all reset *after* all sending. - for destination in range(len(Dests)): - - layers[Dests[str(destination)]["layer"]] = [] - ''' -''' -scenes = 4 - -def DrawDestslayer(layer): - - for scene in range(scenes): - - if Dests[laser]["scene"] != -1: - if r.set('/pl/'+str(Dests[laser]["scene"])+'/'+str(Dests[laser]["laser"]), str(layers[Dests[laser]["laser"]])) == True: - if r.set('/pl/'+str(ClientNumber)+'/'+str(layer), str(layers[layer])) == True: - #print '/pl/'+str(ClientNumber)+'/'+str(layer), str(layers[layer]) - layers[Dests[laser]["laser"]] = [] - return True - else: - return False - -''' - -# -# High level drawing functions -# - - -# Font1 - - -ASCII_GRAPHICS = [ - -#implementé - - [(-50,30), (-30,-30), (30,-30), (10,30), (-50,30)], # 0 - [(-20,30), (0,-30), (-20,30)], # 1 - [(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], # 2 - [(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], # 3 - [(30,10), (-30,10), (0,-30), (0,30)], # 4 - [(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], # 5 - [(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], # 6 - [(-30,-30), (30,-30), (-30,30)], # 7 - [(-30,30), (-30,-30), (30,-30), (30,30), (-30,30), (-30,0), (30,0)], # 8 - [(30,0), (-30,0), (-30,-10), (0,-30), (30,-30), (30,10), (0,30), (-30,30)], # 9 - -# A implementer - [(-30,10), (30,-10), (30,10), (0,30), (-30,10), (-30,-10), (0,-30), (30,-10)], #: - [(-30,-10), (0,-30), (0,30)], [(-30,30), (30,30)], # ; - [(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], # < - [(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], # = - [(30,10), (-30,10), (0,-30), (0,30)], # > - [(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], # ? - [(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], # @ - -# Implementé 65-90 - - [(-30,30), (-30,-30), (30,-30), (30,30), (30,0), (-30,0)], # A - [(-30,30), (-30,-30), (30,-30), (30,30), (30,0), (-30,0)], # A - [(-30,30), (-30,-30), (30,-30), (30,30), (-30,30), (-30,0), (30,0)], # B - [(30,30), (-30,30), (-30,-30), (30,-30)], # C - [(-30,30), (-30,-30), (30,-30), (30,30), (-30,30)], # D - [(30,30), (-30,30), (-30,-0), (30,0), (-30,0), (-30,-30), (30,-30)], # E - [(-30,30), (-30,-0), (30,0), (-30,0), (-30,-30), (30,-30)], # F - [(0,0), (30,0), (30,30), (-30,30), (-30,-30),(30,-30)], # G - [(-30,-30), (-30,30), (-30,0), (30,0), (30,30), (30,-30)], # H - [(0,30), (0,-30)], # I - [(-30,30), (0,-30), (0,-30), (-30,-30), (30,-30)], # J - [(-30,-30), (-30,30), (-30,0), (30,-30), (-30,0), (30,30)], # K - [(30,30), (-30,30), (-30,-30)], # L - [(-30,30), (-30,-30), (0,0), (30,-30), (30,30)], # M - [(-30,30), (-30,-30), (30,30), (30,-30)], # N - [(-30,30), (-30,-30), (30,-30), (30,30), (-30,30)], # O - [(-30,0), (30,0), (30,-30), (-30,-30), (-30,30)], # P - [(30,30), (30,-30), (-30,-30), (-30,30), (30,30),(35,35)], # Q - [(-30,30), (-30,-30), (30,-30), (30,0), (-30,0), (30,30)], # R - [(30,-30), (-30,-30), (-30,0), (30,0), (30,30), (-30,30)], # S - [(0,30), (0,-30), (-30,-30), (30,-30)], # T - [(-30,-30), (-30,30), (30,30), (30,-30)], # U - [(-30,-30), (0,30), (30,-30)], # V - [(-30,-30), (-30,30), (0,0), (30,30), (30,-30)], # W - [(-30,30), (30,-30), (-30,-30), (30,30)], # X - [(0,30), (0,0), (30,-30), (0,0), (-30,-30)], # Y - [(30,30), (-30,30), (30,-30), (-30,-30)], # Z - -# A implementer - - [(-30,-10), (0,-30), (0,30)], [(-30,30), (30,30)], # [ - [(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], # \ - [(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], # ] - [(30,10), (-30,10), (0,-30), (0,30)], # ^ - [(30,-30), (-30,-30), (-30,0), (0,0), (30,10), (0,30), (-30,30)], # _ - [(30,-30), (0,-30), (-30,-10), (-30,30), (0,30), (30,10), (30,0), (-30,0)], # ` - -# Implementé 97-122 - - [(-20,20), (-20,-20), (20,-20), (20,20), (20,0), (-20,0)], # a - [(-20,20), (-20,-20), (20,-20), (20,20), (-20,20), (-20,0), (20,0)], # b - [(20,20), (-20,20), (-20,-20), (20,-20)], # c - [(-20,20), (-20,-20), (20,-20), (20,20), (-20,20)], # d - [(20,20), (-20,20), (-20,-0), (20,0), (-20,0), (-20,-20), (20,-20)], # e - [(-20,20), (-20,-0), (20,0), (-20,0), (-20,-20), (20,-20)], # f - [(0,0), (20,0), (20,20), (-20,20), (-20,-20),(20,-20)], # g - [(-20,-20), (-20,20), (-20,0), (20,0), (20,20), (20,-20)], # h - [(0,20), (0,-20)], # i - [(-20,20), (0,-20), (0,-20), (-20,-20), (20,-20)], # j - [(-20,-20), (-20,20), (-20,0), (20,-20), (-20,0), (20,20)], # k - [(20,20), (-20,20), (-20,-20)], # l - [(-20,20), (-20,-20), (0,0), (20,-20), (20,20)], # m - [(-20,20), (-20,-20), (20,20), (20,-20)], # n - [(-20,20), (-20,-20), (20,-20), (20,20), (-20,20)], # o - [(-20,0), (20,0), (20,-20), (-20,-20), (-20,20)], # p - [(20,20), (20,-20), (-20,-20), (-20,20), (20,20),(25,25)], # q - [(-20,20), (-20,-20), (20,-20), (20,0), (-20,0), (20,20)], # r - [(20,-20), (-20,-20), (-20,0), (20,0), (20,20), (-20,20)], # s - [(0,20), (0,-20), (-20,-20), (20,-20)], # t - [(-20,-20), (-20,20), (20,20), (20,-20)], # u - [(-20,-20), (0,20), (20,-20)], # v - [(-20,-20), (-20,20), (0,0), (20,20), (20,-20)], # w - [(-20,20), (20,-20)], [(-20,-20), (20,20)], # x - [(0,20), (0,0), (20,-20), (0,0), (-20,-20)], # y - [(20,20), (-20,20), (20,-20), (-20,-20)], # z - - # A implementer - [(-2,15), (2,15)], # Point a la place de { - [(-30,-10), (0,-30), (0,30)], [(-30,30), (30,30)], # | - [(-30,-10), (0,-30), (30,-10), (30,0), (-30,30), (30,30)], # } - [(-30,-30), (0,-30), (30,-10), (0,0), (30,10), (0,30), (-30,30)], # - [(30,10), (-30,10), (0,-30), (0,30)], # DEL - - # Accents 128-151 a implementer - [(30,30), (-30,30), (-30,-30), (30,-30)], # C - [(-20,-20), (-20,20), (20,20), (20,-20)], # û - [(20,20), (-20,20), (-20,-0), (20,0), (-20,0), (-20,-20), (20,-20)], # é - [(-20,20), (-20,-20), (20,-20), (20,20), (20,0), (-20,0)], # â - [(-20,20), (-20,-20), (20,-20), (20,20), (20,0), (-20,0)], # ä - [(-20,20), (-20,-20), (20,-20), (20,20), (20,0), (-20,0)], # a - [(20,20), (-20,20), (-20,-20), (20,-20)], # c - [(20,20), (-20,20), (-20,-0), (20,0), (-20,0), (-20,-20), (20,-20)], # é - [(20,20), (-20,20), (-20,-0), (20,0), (-20,0), (-20,-20), (20,-20)], # é - [(20,20), (-20,20), (-20,-0), (20,0), (-20,0), (-20,-20), (20,-20)], # é - [(0,20), (0,-20)], # i - [(0,20), (0,-20)], # i - [(0,20), (0,-20)], # i - [(-30,30), (-30,-30), (30,-30), (30,30), (30,0), (-30,0)], # A - [(-30,30), (-30,-30), (30,-30), (30,30), (30,0), (-30,0)], # A - [(30,30), (-30,30), (-30,-0), (30,0), (-30,0), (-30,-30), (30,-30)], # E - [(-20,20), (-20,-20), (20,-20), (20,20), (20,0), (-20,0)], # a - [(-20,20), (-20,-20), (20,-20), (20,20), (20,0), (-20,0)], # a - [(-20,20), (-20,-20), (20,-20), (20,20), (-20,20)], # o - [(-20,20), (-20,-20), (20,-20), (20,20), (-20,20)], # o - [(-20,20), (-20,-20), (20,-20), (20,20), (-20,20)], # o - [(-20,-20), (-20,20), (20,20), (20,-20)], # u - [(-20,-20), (-20,20), (20,20), (20,-20)] # u - -] - - -def DigitsDots(number,color): - dots =[] - for dot in ASCII_GRAPHICS[number]: - #print dot - dots.append((gstt.xy_center[0]+dot[0],gstt.xy_center[1]+dot[1],color)) - #self.point_list.append((xy + (c,))) - return dots - -def CharDots(char,color): - - dots =[] - for dot in ASCII_GRAPHICS[ord(char)-46]: - dots.append((dot[0],dot[1],color)) - return dots - -def Text(message, c, layer, xpos, ypos, resize, rotx, roty, rotz): - - dots =[] - - l = len(message) - i= 0 - #print() - # print (message) - - for ch in message: - - #print "" - # texte centre en x automatiquement selon le nombre de lettres l - x_offset = 26 * (- (0.9*l) + 3*i) - # Digits - if ord(ch)<58: - char_layer_list = ASCII_GRAPHICS[ord(ch) - 48] - - # Uppercase - elif 64 < ord(ch) < 91 : - char_layer_list = ASCII_GRAPHICS[ord(ch) - 46] - - # Lowercase - elif 96 < ord(ch) < 123 : - char_layer_list = ASCII_GRAPHICS[ord(ch) - 45] - - char_draw = [] - #dots.append((char_layer_list[0][0] + x_offset,char_layer_list[0][1],0)) - - for xy in char_layer_list: - char_draw.append((xy[0] + x_offset,xy[1],c)) - i +=1 - #print ch,char_layer_list,char_draw - rPolyLineOneColor(char_draw, c, layer , False, xpos, ypos, resize, rotx, roty, rotz) - #dots.append(char_draw) - -def TextRGB(message,c, layer, xpos, ypos, resize, rotx, roty, rotz): - - Text(message,int('0x%02x%02x%02x' % (red,green,blue),0), layer, xpos, ypos, resize, rotx, roty, rotz) - - - - - - - \ No newline at end of file diff --git a/libs3/tracer3.sync-conflict-20200728-024608-NJKFP4Q.py b/libs3/tracer3.sync-conflict-20200728-024608-NJKFP4Q.py deleted file mode 100644 index 0e06084..0000000 --- a/libs3/tracer3.sync-conflict-20200728-024608-NJKFP4Q.py +++ /dev/null @@ -1,542 +0,0 @@ -#!/usr/bin/python3 -# -*- coding: utf-8 -*- -# -*- mode: Python -*- - -''' - -Tracer -for LJ v0.8.2 - -Enhanced version (support for several lasers) of the etherdream python library from j4cDAC. -One tracer process is launched per requested laser. I/O based on redis keys. - -LICENCE : CC -Sam Neurohack, pclf - -Uses redis keys value for live inputs (Pointlists to draw,...) and outputs (DAC state, errors,..). -Most of redis keys are read and set at each main loop. -Includes live conversion in etherdream coordinates, geometric corrections,... -Etherdream IP is found in conf file for given laser number. (LJ.conf) - -Redis keys to draw things : -/order select some change to adjust. See below -/pl/lasernumber [(x,y,color),(x1,y1,color),...] A string of list of points list. -/resampler/lasernumber [(1.0,8), (0.25,3),(0.75,3),(1.0,10)] : a string for resampling rules. - the first tuple (1.0,8) is for short line < 4000 in etherdream space - (0.25,3),(0.75,3),(1.0,10) for long line > 4000 - i.e (0.25,3) means go at 25% position on the line, send 3 times this position to etherdream -/clientkey - - -Redis keys for Etherdream DAC - -- Control -/kpps see order 7 -/intensity see order 6 -/red see order 8 -/green see order 8 -/blue see order 8 - -- DAC status report -/lstt/lasernumber value etherdream last_status.playback_state (0: idle 1: prepare 2: playing) -/cap/lasernumber value number of empty points sent to fill etherdream buffer (up to 1799) -/lack/lasernumber value "a": ACK "F": Full "I": invalid. 64 or 35 for no connection. - - - -Order - - 0 : Draw Normal point list - 1 : Get the new EDH - 2 : Draw BLACK point list - 3 : Draw GRID point list - 4 : Resampler Change (longs and shorts lsteps) - 5 : Client Key change - 6 : Intensity change - 7 : kpps change - 8 : color balance change - -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 libs3 import homographyp -import numpy as np -import binascii - -black_points = [(278.0,225.0,0),(562.0,279.0,0),(401.0,375.0,0),(296.0,454.0,0),(298.0,165.0,0)] -grid_points = [(300.0,200.0,0),(500.0,200.0,65280),(500.0,400.0,65280),(300.0,400.0,65280),(300.0,200.0,65280),(300.0,200.0,0),(200.0,100.0,0),(600.0,100.0,65280),(600.0,500.0,65280),(200.0,500.0,65280),(200.0,100.0,65280)] - -r = redis.StrictRedis(host=gstt.LjayServerIP, port=6379, db=0) -# r = redis.StrictRedis(host=gstt.LjayServerIP , port=6379, db=0, password='-+F816Y+-') -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", '64': "NOCONNECTION ?" } - -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 - - - #print("Tracer", laser,":", r,g,b,"intensity", intensity, "i", i) - #print(x, type(x), int(x)) - return struct.pack(" 1: - self.status.dump(prefix) - - -class DAC(object): - """A connection to a DAC.""" - - - # "Laser point List" Point generator - # each points is yielded : Getpoints() call n times OnePoint() - - def OnePoint(self): - - while True: - - #pdb.set_trace() - for indexpoint,currentpoint in enumerate(self.pl): - #print indexpoint, currentpoint - xyc = [currentpoint[0],currentpoint[1],currentpoint[2]] - self.xyrgb = self.EtherPoint(xyc) - - delta_x, delta_y = self.xyrgb[0] - self.xyrgb_prev[0], self.xyrgb[1] - self.xyrgb_prev[1] - - #test adaptation selon longueur ligne - if math.hypot(delta_x, delta_y) < 4000: - - # For glitch art : decrease lsteps - #l_steps = [ (1.0, 8)] - l_steps = gstt.stepshortline - - else: - # For glitch art : decrease lsteps - #l_steps = [ (0.25, 3), (0.75, 3), (1.0, 10)] - l_steps = gstt.stepslongline - - for e in l_steps: - step = e[0] - - for i in range(0,e[1]): - - self.xyrgb_step = (self.xyrgb_prev[0] + step*delta_x, self.xyrgb_prev[1] + step*delta_y) + self.xyrgb[2:] - yield self.xyrgb_step - - self.xyrgb_prev = self.xyrgb - - - def GetPoints(self, n): - - d = [next(self.newstream) for i in range(n)] - #print d - return d - - - # Etherpoint all transform in one matrix, with warp !! - # xyc : x y color - def EtherPoint(self,xyc): - - c = xyc[2] - - #print("") - #print("pygame point",[(xyc[0],xyc[1],xyc[2])]) - #gstt.EDH[self.mylaser]= np.array(ast.literal_eval(r.get('/EDH/'+str(self.mylaser)))) - position = homographyp.apply(gstt.EDH[self.mylaser],np.array([(xyc[0],xyc[1])])) - - #print("etherdream point",position[0][0], position[0][1], ((c >> 16) & 0xFF) << 8, ((c >> 8) & 0xFF) << 8, (c & 0xFF) << 8) - - return (position[0][0], position[0][1], ((c >> 16) & 0xFF) << 8, ((c >> 8) & 0xFF) << 8, (c & 0xFF) << 8) - - - def read(self, l): - """Read exactly length bytes from the connection.""" - while l > len(self.buf): - self.buf += self.conn.recv(4096) - - obuf = self.buf - self.buf = obuf[l:] - return obuf[:l] - - def readresp(self, cmd): - """Read a response from the DAC.""" - - - data = self.read(22) - response = data[0] - gstt.lstt_dacanswers[self.mylaser] = response - cmdR = chr(data[1]) - status = Status(data[2:]) - - r.set('/lack/'+str(self.mylaser), response) - - if cmdR != cmd: - raise ProtocolError("expected resp for %r, got %r" - % (cmd, cmdR)) - - if response != ord('a'): - raise ProtocolError("expected ACK, got %r" - % (response, )) - - self.last_status = status - return status - - def __init__(self, mylaser, PL, port = 7765): - """Connect to the DAC over TCP.""" - socket.setdefaulttimeout(2) - - self.mylaser = mylaser - self.clientkey = r.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 - r.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(r.get(self.clientkey + str(self.mylaser)).decode('ascii')) - if r.get('/EDH/'+str(self.mylaser)) == None: - #print("Laser",self.mylaser,"NO EDH !! Computing one...") - homographyp.newEDH(self.mylaser) - else: - - gstt.EDH[self.mylaser] = np.array(ast.literal_eval(r.get('/EDH/'+str(self.mylaser)).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.newstream = self.OnePoint() - - 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 begin(self, lwm, rate): - cmd = struct.pack("