#! /usr/bin/python # -*- coding: utf-8 -*- """ This file is part of LibreLight. LibreLight is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. LibreLight is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with LibreLight. If not, see . (c) 2012 micha.rathfelder@gmail.com """ import random rnd_id = str(random.randint(1000,9000)) rnd_id += " Beta 22.01" try: xtitle = __file__ except: xtitle = "__file__" if "/" in xtitle: xtitle = xtitle.split("/")[-1] import sys sys.stdout.write("\x1b]2;"+str(xtitle)+" "+str(rnd_id)+"\x07") # terminal title import json import time import sys import _thread as thread import traceback import tkinter import tkinter as tk from tkinter import font import lib.chat as chat import lib.motion as motion from collections import OrderedDict show_name = "GloryCamp2021" #show_name = "JMS" #show_name = "Dimmer" CUES = OrderedDict() groups = OrderedDict() class Modes(): def __init__(self): self.modes = {} self.__cfg = {} self.__cd = None def val(self,mode,value=None): if value is not None: return self.set(mode,value) elif mode in self.modes: return self.modes[mode] def get(self,mode,value=None): return slef.val(mode,value) def __check(self,mode): if mode not in self.modes: self.modes[mode] = 0 self.__cfg[mode] = 0 def cfg(self,mode,data={}): self.__check(mode) if type(data) is dict: for k in data: v = data[k] if v not in self.__cfg: self.__cfg[k] = v return 1 elif type(data) is str: if data in self.__cfg: return self.__cfg[data] def set(self,mode,value): self.__check(mode) if mode == "CLEAR": self.modes["STORE"] = 0 self.callback("STORE") self.modes[mode] = value return value def callback(self,mode): if self.__cb is not None and mode in self.modes: value = self.modes[mode] self.__cb(mode=mode,value=value) modes = Modes() modes.modes["BLIND"] = 0 modes.modes["STORE "] = 0 modes.modes["FLASH"] = 0 modes.modes["STONY_FX"] = 0 modes.modes["SELECT"] = 0 modes.modes["ACTIVATE"] = 0 modes.modes["CFG_BTN"] = 0 modes.modes["LABEL"] = 0 POS = ["PAN","TILT","MOTION"] COLOR = ["RED","GREEN","BLUE","COLOR"] BEAM = ["GOBO","G-ROT","PRISMA","P-ROT","FOCUS","SPEED"] INT = ["DIM","SHUTTER","STROBE","FUNC"] client = chat.tcp_sender() fade = 2 #2 #0.1 #1.13 fade_on = 1 fx_prm = {"SIZE":20,"SPEED":100,"OFFSET":50,"BASE":"-","START":0} def build_cmd(dmx,val,args=[fade],flash=0,xpfx="",attr=""): cmd="" if xpfx: pfx=xpfx elif flash: pfx ="df" else: pfx ="d" if type(val) is float or type(val) is int: cmd += ",{}{}:{:0.4f}".format(pfx,dmx,val) else: cmd += ",{}{}:{}".format(pfx,dmx,val) if flash: cmd += ":0:0"#.format(val) else: for val in args: if type(val) is float or type(val) is int: cmd += ":{:0.4f}".format(val) else: cmd += ":{}".format(val) if attr: cmd += ":"+str(attr) return cmd def update_raw_dmx(data ,value=None,args=[fade],flash=0,pfx="d",fx=0): cmd = [] if flash: pfx += "f" for row in data: if fx: if value is not None: # z.b. flush off xcmd = str(value)+":"+row["FX"].split(":",1)[-1] else: xcmd = row["FX"] else: if row["VALUE"] is None: xcmd = "" else: if value is not None: if type(value) is float: xcmd = "{:0.4f}".format(value) else: xcmd = "{}".format(value) else: xcmd = "{:0.4f}".format(row["VALUE"]) for arg in args: if type(arg) is float: xcmd += ":{}".format(arg) else: xcmd += ":{:0.4f}".format(arg) #print( "pack: FIX",row["FIX"],row["ATTR"], xcmd) #xcmd += ":{}".format(row["ATTR"]) cmd.append( xcmd) return cmd def update_dmx(attr,data,value=None,args=[fade],flash=0,pfx=""): #global modes #BLIND #print("update_dmx",data) dmx = data["DMX"] dmx = (data["UNIVERS"]*512)+data["DMX"] val = None cmd="" try: if attr == "DIM" and data["ATTRIBUT"][attr]["NR"] < 0: #VDIM #print( "VDIM") for attr in data["ATTRIBUT"]: dmx = (data["UNIVERS"]*512) + data["DMX"] dmx = data["DMX"] if data["ATTRIBUT"][attr]["NR"] < 0: #virtual channels continue dmx += data["ATTRIBUT"][attr]["NR"]-1 mode = "" if "MODE" in data["ATTRIBUT"][attr]: mode = data["ATTRIBUT"][attr]["MODE"] #print(attr) val = data["ATTRIBUT"][attr]["VALUE"] if data["ATTRIBUT"][attr]["MASTER"]: val = val * (data["ATTRIBUT"]["DIM"]["VALUE"] / 255.) if val is not None: #cmd += ",d{}:{:0.4f}".format(dmx,int(val)) if value is not None: val = value if mode == "F": #FADE cmd += build_cmd(dmx,val,args=args,flash=flash,xpfx=pfx,attr=attr) else: cmd += build_cmd(dmx,val,args=[0],flash=flash,xpfx=pfx,attr=attr) #print("cmd",cmd) elif data["ATTRIBUT"][attr]["NR"] > 0: dmx += data["ATTRIBUT"][attr]["NR"]-1 val = data["ATTRIBUT"][attr]["VALUE"] mode = "" if "MODE" in data["ATTRIBUT"][attr]: mode = data["ATTRIBUT"][attr]["MODE"] if data["ATTRIBUT"][attr]["MASTER"]: #if "VDIM" in data["ATTRIBUT"]: if "DIM" in data["ATTRIBUT"] and data["ATTRIBUT"]["DIM"]["NR"] < 0: #VDIM val = val * (data["ATTRIBUT"]["DIM"]["VALUE"] / 255.) if val is not None: #cmd += ",d{}:{}".format(dmx,int(val)) if value is not None: val = value if mode == "F": #FADE cmd += build_cmd(dmx,val,args=args,flash=flash,xpfx=pfx,attr=attr) else: cmd += build_cmd(dmx,val,args=[0],flash=flash,xpfx=pfx,attr=attr) #print("cmd",cmd) if modes.val("BLIND"): cmd="" return cmd except Exception as e: print("== cb EXCEPT",e) print("Error on line {}".format(sys.exc_info()[-1].tb_lineno)) raise e class dummy_event(): def __init__(self): self.num =0 self.type = 4 #press 5 release self.set_value=-1 class Xevent(): def __init__(self,fix,elem,attr=None,data=None,mode=None): self.data=data self.attr = attr self.elem = elem self.mode = mode def encoder(self,fix,attr,data,elem,action="",xfade=None): if action == "click": if self.data["ATTRIBUT"][attr]["ACTIVE"]: self.data["ATTRIBUT"][attr]["ACTIVE"] = 0 self.elem["bg"] = "grey" else: self.data["ATTRIBUT"][attr]["ACTIVE"] = 1 self.elem["bg"] = "yellow" return 1 v2=data["ATTRIBUT"][attr]["VALUE"] change=0 increment = 4.11 if action == "+": v2+= increment v = "+{:0.4f}".format( increment ) #) #4.11" change=1 elif action == "-": v2-= increment v = "-{:0.4f}".format( increment ) #) #4.11" change=1 elif type(action) is int or type(action) is float: #v2-= increment #v = "-{:0.4f}".format( increment ) #) #4.11" v2 = action change=1 if v2 < 0: v2=0 elif v2 > 256: v2=256 if change: data["ATTRIBUT"][attr]["ACTIVE"] = 1 elem["bg"] = "yellow" #v2 = v #v = data["ATTRIBUT"][attr]["VALUE"] data["ATTRIBUT"][attr]["VALUE"] = v2 elem["text"] = "{} {:0.2f}".format(attr,v2) #worker.fade_dmx(fix,attr,data,v,v2,ft=0) if xfade: cmd=update_dmx(attr=attr,data=data) else: cmd=update_dmx(attr=attr,data=data,args=[0]) #data["ATTRIBUT"][attr]["VALUE"] = v2 if cmd and not modes.val("BLIND"): client.send(cmd) def clear(self,event=None): if modes.val("STORE"): self.data.val_commands["STORE"] = 0 modes.val("STORE",0)# = 0 self.data.elem_commands["STORE"]["bg"] = "grey" else: for fix in self.data.FIXTURES.fixtures: print( "clr",fix) data = self.data.FIXTURES.fixtures[fix] #print("elm",self.data.elem_attr[fix]) for attr in data["ATTRIBUT"]: if attr.endswith("-FINE"): continue self.data.elem_attr[fix][attr]["bg"] = "grey" data["ATTRIBUT"][attr]["ACTIVE"] = 0 #print(data["ATTRIBUT"]) print( "CB CLEAR" ) def command(self,event): if self.mode == "COMMAND": if self.attr == "CLEAR": if event.num == 1: self.clear() if self.attr.startswith("SZ:"):#SIN": #global fx_prm k = "SIZE" if event.num == 1: pass elif event.num == 2: pass elif event.num == 4: if fx_prm[k] <= 0: fx_prm[k] = 1 fx_prm[k] *=1.2 elif event.num == 5: fx_prm[k] /=1.2 #fx_prm[k] =int(fx_prm[k]) if fx_prm[k] > 4000: fx_prm[k] = 4000 if fx_prm[k] < 0: fx_prm[k] =0 self.data.elem_fx_commands[self.attr]["text"] = "SZ:{:0.0f}".format(fx_prm[k]) if self.attr.startswith("SP:"):#SIN": #global fx_prm k = "SPEED" if event.num == 1: pass elif event.num == 2: pass elif event.num == 4: if fx_prm[k] <= 0: fx_prm[k] = 1 fx_prm[k] *=1.2 elif event.num == 5: fx_prm[k] /=1.2 #fx_prm[k] =int(fx_prm[k]) if fx_prm[k] > 4000: fx_prm[k] = 4000 if fx_prm[k] < 0: fx_prm[k] =0 if fx_prm[k] < 0.1: self.data.elem_fx_commands[self.attr]["text"] = "SP:off".format(fx_prm[k]) else: self.data.elem_fx_commands[self.attr]["text"] = "SP:{:0.0f}".format(fx_prm[k]) if self.attr.startswith("ST:"):#SIN": #global fx_prm k = "START" if event.num == 1: pass elif event.num == 2: pass elif event.num == 4: if fx_prm[k] <= 0: fx_prm[k] = 1 fx_prm[k] *=1.2 elif event.num == 5: fx_prm[k] /=1.2 #fx_prm[k] =int(fx_prm[k]) if fx_prm[k] > 4000: fx_prm[k] = 4000 if fx_prm[k] < 0: fx_prm[k] =0 self.data.elem_fx_commands[self.attr]["text"] = "ST:{:0.0f}".format(fx_prm[k]) if self.attr.startswith("OF:"):#SIN": #global fx_prm k = "OFFSET" if event.num == 1: pass elif event.num == 2: pass elif event.num == 4: if fx_prm[k] <= 0: fx_prm[k] = 1 fx_prm[k] *=1.2 elif event.num == 5: fx_prm[k] /=1.2 #fx_prm[k] =int(fx_prm[k]) if fx_prm[k] > 1024: fx_prm[k] = 1024 if fx_prm[k] < 0: fx_prm[k] =0 self.data.elem_fx_commands[self.attr]["text"] = "OF:{:0.0f}".format(fx_prm[k]) if self.attr.startswith("BS:"): k = "BASE" if event.num == 1: fx_prm[k] = "0" elif event.num == 2: pass elif event.num == 4: fx_prm[k] = "+" elif event.num == 5: fx_prm[k] = "-" self.data.elem_fx_commands[self.attr]["text"] = "BS:{}".format(fx_prm[k]) if self.attr.startswith("FX:"):#SIN": if event.num == 1: cmd = "" offset = 0 offset_flag=0 start = fx_prm["START"] base = fx_prm["BASE"] for fix in self.data.FIXTURES.fixtures: data = self.data.FIXTURES.fixtures[fix] #print( "ADD FX",fix) for attr in data["ATTRIBUT"]: if attr.endswith("-FINE"): continue fx="" if "SIN" in self.attr: fx = "sinus" elif "FD" in self.attr: fx = "fade" elif "ON2" in self.attr: fx = "on2" elif "ON" in self.attr: fx = "on" elif "BUM2" in self.attr: fx = "bump2" elif "BUM" in self.attr: fx = "bump" elif "COS" in self.attr: fx = "cosinus" if fx: if fx_prm["SPEED"] < 0.1: fx = "off" else: if "DIM" in self.attr: base="" if attr == "DIM": if fx_prm["SPEED"] < 0.1: fx = "off" else: fx = "fade" elif "TILT" in self.attr: base="" if attr == "PAN": fx = "off" if attr == "TILT": if fx_prm["SPEED"] < 0.1: fx = "off" else: fx = "sinus" elif "PAN" in self.attr: base="" if attr == "PAN": if fx_prm["SPEED"] < 0.1: fx = "off" else: fx = "cosinus" if attr == "TILT": fx = "off" elif "CIR" in self.attr: base="" if attr == "PAN": if fx_prm["SPEED"] < 0.1: fx = "off" else: fx = "cosinus" if attr == "TILT": if fx_prm["SPEED"] < 0.1: fx = "off" else: fx = "sinus" if fx: fx += ":{:0.0f}:{:0.0f}:{:0.0f}:{:0.0f}:{}:".format(fx_prm["SIZE"],fx_prm["SPEED"],start,offset,base) offset_flag=1 if "FX" not in data["ATTRIBUT"][attr]: data["ATTRIBUT"][attr]["FX"] ="" print("ADD FX",fix,attr,fx,data["ATTRIBUT"][attr]["ACTIVE"]) if data["ATTRIBUT"][attr]["ACTIVE"] and fx: print("++ADD FX",fix,attr,fx) data["ATTRIBUT"][attr]["FX"] = fx #"sinus:40:100:10" cmd+=update_dmx(attr,data,pfx="fx",value=fx)#,flash=FLASH) if fx_prm["OFFSET"] > 0.5 and offset_flag: offset_flag=0 offset += fx_prm["OFFSET"] # add offset on next fixture #print("offset",offset) if cmd and not modes.val("BLIND"): client.send(cmd) elif self.attr == "FX OFF": if event.num == 1: client.send("fx0:alloff:,fxf:alloff:") self.data.elem_fx_commands[self.attr]["bg"] = "magenta" for fix in self.data.FIXTURES.fixtures: data = self.data.FIXTURES.fixtures[fix] for attr in data["ATTRIBUT"]: data["ATTRIBUT"][attr]["FX"] = "" elif self.attr == "FLASH": if event.num == 1: if modes.val("FLASH"): modes.val("FLASH",0)# = 0 self.data.elem_commands[self.attr]["bg"] = "grey" else: modes.val("FLASH",1)# = 1 self.data.elem_commands[self.attr]["bg"] = "green" elif self.attr == "BLIND": if event.num == 1: if self.data.val_commands[self.attr]: self.data.val_commands[self.attr] = 0 modes.val("BLIND",0)# = 0 self.data.elem_commands[self.attr]["bg"] = "grey" else: self.data.val_commands[self.attr] = 1 modes.val("BLIND",1)# = 1 self.data.elem_commands[self.attr]["bg"] = "red" print("BLIND",self.data.val_commands) elif self.attr == "FADE": global fade global fade_on if fade < 0.01: fade = 0.01 elif fade > 100.0: fade = 100 if event.num == 4: fade *= 1.1 elif event.num == 5: fade /= 1.1 elif event.num == 1: if fade_on: fade_on = 0 self.data.elem_commands[self.attr]["bg"] = "grey" else: fade_on = 1 self.data.elem_commands[self.attr]["bg"] = "green" elif event.num == 2: if fade > 1 and fade < 4: fade = 4 elif fade > 3 and fade < 6: fade = 6 elif fade > 5 and fade < 7: fade = 8 elif fade > 7 and fade < 9: fade = 10 elif fade > 9: fade = 0.01 elif fade < 1: fade = 1.1 self.data.elem_commands[self.attr]["text"] = "Fade{:0.2f}".format(fade) elif self.attr == "CFG-BTN": #global modes #CFG_BTN if event.num == 1: if modes.val("CFG_BTN"): modes.val("CFG_BTN",0)# = 0 self.data.elem_commands[self.attr]["bg"] = "lightgrey" else: modes.val("CFG_BTN",1)# = 1 self.data.elem_commands[self.attr]["bg"] = "red" elif self.attr == "ACTIVATE": #global modes# ACTIVATE if event.num == 1: if modes.val("ACTIVATE"): modes.val("ACTIVATE",0)# = 0 self.data.elem_commands[self.attr]["bg"] = "lightgrey" else: modes.val("ACTIVATE",1)# = 1 self.data.elem_commands[self.attr]["bg"] = "red" elif self.attr == "SELECT": #global modes# SELECT #global CFG_BTN if event.num == 1: if modes.val("SELECT"): modes.val("SELECT",0)# = 0 self.data.elem_commands[self.attr]["bg"] = "lightgrey" else: modes.val("SELECT",1)# = 1 self.data.elem_commands[self.attr]["bg"] = "red" elif self.attr == "LABEL": #global modes #LABEL #global CFG_BTN if event.num == 1: if modes.val("LABEL"): modes.val("LABEL", 0) self.data.elem_commands[self.attr]["bg"] = "lightgrey" else: modes.val("LABEL", 1) self.data.elem_commands[self.attr]["bg"] = "red" elif self.attr == "STONY_FX": if event.num == 1: if modes.val("STONY_FX"): modes.val("STONY_FX", 0) self.data.elem_fx_commands[self.attr]["bg"] = "grey" else: modes.val("STONY_FX", 1) self.data.elem_fx_commands[self.attr]["bg"] = "red" elif self.attr == "STORE": if event.num == 1: if self.data.val_commands[self.attr]: self.data.val_commands[self.attr] = 0 modes.val("STORE",0) self.data.elem_commands[self.attr]["bg"] = "lightgrey" else: self.data.val_commands[self.attr] = 1 modes.val("STORE", 1) self.data.elem_commands[self.attr]["bg"] = "red" print("BLIND",self.data.val_commands) elif self.attr == "BACKUP": self.data.PRESETS.backup_presets() self.data.FIXTURES.backup_patch() return 0 def cb(self,event): #print("cb",self,event,data) print("cb",self.attr,self.mode,event) print(["type",event.type,"num",event.num]) #print(dir(event.type)) #print(dir(event),[str(event.type)])#.keys()) try: #v = self.data["ATTRIBUT"][self.attr] #global modes #global STORE #global BLIND #global FLASH #global STONY_FX #global LABEL #global SELECT #global ACTIVATE #global CFG_BTN change = 0 if "keysym" in dir(event): if "Escape" == event.keysym: self.clear() #CLEAR return 0 if self.mode == "COMMAND": self.command(event) elif self.mode == "ROOT": if event.keysym=="Escape": pass #STORE = 0 #LABEL = 0 elif self.mode == "INPUT": print("INP",self.data.entry.get()) if event.keycode == 36: x=self.data.entry.get() client.send(x) #self.data.entry.clean() #self.data #chat.send("") elif self.mode == "INPUT2": print("INP2",self.data.entry2.get()) if event.keycode == 36: x=self.data.entry2.get() client.send(x) #self.data.entry.clean() elif self.mode == "INPUT3": print("INP3",self.data.entry3.get()) if event.keycode == 36: x=self.data.entry3.get() client.send(x) #self.data.entry.clean() #self.data #chat.send("") elif self.mode == "PRESET": nr = self.attr #int(self.attr.split(":")[1])-1 #print( "RRR", [str(event.type) , event.type] ) #print( "PRESET EVENT",event.num) if event.num == 1: if str(event.type) == '4': #4 ButtonPress #if str(event.type) == "ButtonRelease" or event.type == '5': if modes.val("STORE"): self.data.preset_store(nr) modes.val("STORE",0) elif modes.val("CFG_BTN"): import tkinter.simpledialog txt = tkinter.simpledialog.askstring("CFG-BTN","GO,FLASH,TOGGLE,SWOP\n EXE:"+str(nr)) if "CFG" not in self.data.PRESETS.val_presets[nr]: self.data.PRESETS.val_presets[nr]["CFG"] = OrderedDict() if "BUTTON" not in self.data.PRESETS.val_presets[nr]["CFG"]: self.data.PRESETS.val_presets[nr]["CFG"]["BUTTON"] = "" self.data.PRESETS.val_presets[nr]["CFG"]["BUTTON"] = txt sdata=self.data.PRESETS.val_presets[nr] BTN="go" if "CFG" in sdata:#["BUTTON"] = "GO" if "BUTTON" in sdata["CFG"]: BTN = sdata["CFG"]["BUTTON"] label = self.data.PRESETS.label_presets[nr] # = label txt=str(nr)+":"+str(BTN)+":"+str(len(sdata)-1)+"\n"+label self.data.elem_presets[nr]["text"] = txt modes.val("CFG_BTN",0)# = 0 self.data.elem_commands["CFG-BTN"]["bg"] = "grey" elif modes.val("LABEL"):#else: label = "lalaal" import tkinter.simpledialog label = tkinter.simpledialog.askstring("LABEL","Preset "+str(nr)) if label is not None: self.data.elem_presets[nr]["text"] = label self.data.PRESETS.label_presets[nr] = label sdata=self.data.PRESETS.val_presets[nr] BTN="go" if "CFG" in sdata:#["BUTTON"] = "GO" if "BUTTON" in sdata["CFG"]: BTN = sdata["CFG"]["BUTTON"] txt=str(nr)+":"+str(BTN)+":"+str(len(sdata)-1)+"\n"+label #txt = "Preset:"+str(nr)+":\n"+str(len(l))+":"+label self.data.elem_presets[nr]["text"] = txt modes.val("LABEL", 0) self.data.elem_commands["LABEL"]["bg"] = "lightgrey" elif modes.val("ACTIVATE"): self.data.preset_select(nr) self.data.preset_go(nr,xfade=0,event=event) modes.val("ACTIVATE", 0) self.data.elem_commands["ACTIVATE"]["bg"] = "lightgrey" elif modes.val("SELECT"): self.data.preset_select(nr) else: self.data.preset_go(nr,event=event) else: self.data.preset_go(nr,event=event) if event.num == 3: if not modes.val("STORE"): self.data.preset_go(nr,xfade=0,event=event) return 0 elif self.mode == "INPUT": return 0 if self.mode == "ENCODER": #if self.attr == "VDIM": # self.attr = "DIM" for fix in self.data.FIXTURES.fixtures: data = self.data.FIXTURES.fixtures[fix] for attr in data["ATTRIBUT"]: if attr.endswith("-FINE"): continue elem = self.data.elem_attr[fix][attr] if self.attr != attr: continue if event.num == 1: #self#encoder(attr=attr,data=data,elem=elem,action="click") data["ATTRIBUT"][attr]["ACTIVE"] = 1 elem["bg"] = "yellow" if "FX" in data["ATTRIBUT"][attr]:#["FX"]:# = 1 if data["ATTRIBUT"][attr]["FX"]:# = 1 elem["fg"] = "blue" else: elem["fg"] = "blue" elem["fg"] = "black" if not data["ATTRIBUT"][attr]["ACTIVE"]: continue if event.num == 4: self.encoder(fix=fix,attr=attr,data=data,elem=elem,action="+") #if attr == "DIM": # self.encoder(attr="VDIM",data=data,elem=elem,action="+") elif event.num == 5: self.encoder(fix=fix,attr=attr,data=data,elem=elem,action="-") #if attr == "DIM": # self.encoder(attr="VDIM",data=data,elem=elem,action="-") if "set_value" in dir(event) and event.set_value >=0: print("ENCODER set_value and set_fade",event) #print(dir(event)) if "set_fade" in dir(event) and event.set_fade >0: print("event.set_fade",event.set_fade) self.encoder(fix=fix,attr=attr,data=data,elem=elem,action=event.set_value,xfade=1) else: self.encoder(fix=fix,attr=attr,data=data,elem=elem,action=event.set_value) return 0 if event.num == 1: self.encoder(fix=0,attr=self.attr,data=self.data,elem=self.elem,action="click") elif event.num == 4: self.encoder(fix=0,attr=self.attr,data=self.data,elem=self.elem,action="+") elif event.num == 5: self.encoder(fix=0,attr=self.attr,data=self.data,elem=self.elem,action="-") #finally: # pass except Exception as e: print("== cb EXCEPT",e) print("Error on line {}".format(sys.exc_info()[-1].tb_lineno)) traceback.print_exc() #print(self.elem["text"],self.attr,self.data) def wheel(event,d=None): print("wheel",event,d) import copy class Element(): def __init__(self): self.__data = {} def set(self,key,val): self.__data[key] = val class Base(): def __init__(self): pass def _load(self,filename): xfname = "show/"+show_name+"/"+str(filename)+".sav" print("load",xfname) f = open(xfname,"r") lines = f.readlines() f.close() data = OrderedDict() labels = OrderedDict() for line in lines: key,label,rdata = line.split("\t",2) key = int(key) #print(xfname,"load",key,label) #print(line) jdata = json.loads(rdata,object_pairs_hook=OrderedDict) nrnull = 0 if "ATTRIBUT" in jdata: # translate old FIXTURES.fixtures start with 0 to 1 for attr in jdata["ATTRIBUT"]: if "NR" in jdata["ATTRIBUT"][attr]: nr = jdata["ATTRIBUT"][attr]["NR"] if nr == 0: nrnull = 1 break if nrnull: print("DMX NR IS NULL",attr,"CHANGE +1") for attr in jdata["ATTRIBUT"]: if "NR" in jdata["ATTRIBUT"][attr]: nr = jdata["ATTRIBUT"][attr]["NR"] if nr >= 0: jdata["ATTRIBUT"][attr]["NR"] +=1 data[key] = jdata labels[key] = label return data,labels def _backup(self,filename,data,labels): #fixture xfname = "show/"+show_name+"/"+str(filename)+".sav" print("backup",xfname) f = open(xfname,"w") for key in data: line = data[key] #print(line) label = "label" if key in labels: label = labels[key] if label == "Name-"+str(key): label = "" #print(xfname,"load",key,label,len(line)) f.write( "{}\t{}\t{}\n".format( key,label,json.dumps(line) ) ) f.close() class Event(): def __init__(self,name): self.name=name print("init",self) def event(self,event): print(self.name,event) class scroll(): def __init__(self,canvas): self.canvas=canvas def config(self,event): canvas = self.canvas canvas.configure(scrollregion=canvas.bbox("all"))#,width=400,height=200) def hex_to_rgb(hex): return tuple(int(hex[i:i+2], 16) for i in (0, 2, 4)) class cb(): def __init__(self,win): self.win = win def _callback(self,event): clobj=event.widget ## undermouse=find_withtag(master.CURRENT) undermouse=self.win.find_closest(self.win.CURRENT) print( repr(undermouse)) def callback(self,event): print(__file__,self,"callback",event) cnv = self.win item = cnv.find_closest(cnv.canvasx(event.x), cnv.canvasy(event.y))[0] tags = cnv.gettags(item) #cnv.itemconfigure(self.tag, text=tags[0]) print(tags,item) color = cnv.itemcget(item, "fill") cnv.itemconfig("all", width=1)#filla="green") cnv.itemconfig(item, width=3)#filla="green") print(color) print( hex_to_rgb(color[1:])) class GUI(Base): def __init__(self): super().__init__() self.load() self.all_attr =["DIM","PAN","TILT"] self.elem_attr = {} self.fx_commands =["STONY_FX","FX OFF","\n" ,"FX:CIR","FX:PAN","FX:TILT","FX:DIM","\n" ,"SZ:","SP:","ST:","OF:","BS:-","\n" , "FX:SIN","FX:COS","FX:BUM","FX:BUM2","FX:FD","FX:ON","FX:ON2" ] self.commands =["\n","BLIND","CLEAR","STORE","EDIT","MOVE","\n","CFG-BTN","LABEL" ,"BACKUP","SET","","","SELECT","ACTIVATE","FLASH","FADE" ] self.elem_fx_commands = {} self.val_fx_commands = {} self.elem_commands = {} self.val_commands = {} self.elem_presets = {} self.PRESETS = Presets() self.PRESETS.load_presets() self.FIXTURES = Fixtures() self.FIXTURES.load_patch() for i in range(8*8): if i not in self.PRESETS.val_presets: name = "Preset:"+str(i+1)+":\nXYZ" #self.presets[i] = [i] self.PRESETS.val_presets[i] = OrderedDict() # FIX self.PRESETS.val_presets[i]["CFG"] = OrderedDict() # CONFIG self.PRESETS.label_presets[i] = "-" def load(self,fname=""): pass def exit(self): print("__del__",self) self.PRESETS.backup_presets() print("********************************************************") self.FIXTURES.backup_patch() print("*********del",self,"***********************************************") def refresh_gui(self): for fix in self.FIXTURES.fixtures: sdata = self.FIXTURES.fixtures[fix] for attr in sdata["ATTRIBUT"]: if "FINE" in attr: continue v2 = sdata["ATTRIBUT"][attr]["VALUE"] if fix in self.elem_attr: elem = self.elem_attr[fix][attr] #print( attr,v2) elem["text"] = "{} {:0.2f}".format(attr,v2) if sdata["ATTRIBUT"][attr]["ACTIVE"]: elem["bg"] = "yellow" else: elem["bg"] = "grey" def preset_store(self,nr): print("STORE PRESET") self.val_commands["STORE"] = 0 global STORE STORE = 0 self.elem_commands["STORE"]["bg"] = "lightgrey" CFG = OrderedDict() if "CFG" in self.PRESETS.val_presets[nr]: #["CFG"] CFG = self.PRESETS.val_presets[nr]["CFG"] sdata = {} sdata["CFG"] = CFG # OrderedDict() sdata["CFG"]["FADE"] = fade sdata["CFG"]["DEALY"] = 0 #sdata["CFG"]["BUTTON"] = "GO" for fix in self.FIXTURES.fixtures: data = self.FIXTURES.fixtures[fix] for attr in data["ATTRIBUT"]: if data["ATTRIBUT"][attr]["ACTIVE"]: if fix not in sdata: sdata[fix] = {} if attr not in sdata[fix]: sdata[fix][attr] = OrderedDict() if not modes.val("STONY_FX"): sdata[fix][attr]["VALUE"] = data["ATTRIBUT"][attr]["VALUE"] #sdata[fix][attr]["FADE"] = fade else: sdata[fix][attr]["VALUE"] = None #data["ATTRIBUT"][attr]["VALUE"] if "FX" not in data["ATTRIBUT"][attr]: data["ATTRIBUT"][attr]["FX"] ="" sdata[fix][attr]["FX"] = data["ATTRIBUT"][attr]["FX"] print("sdata",len(sdata)) self.PRESETS.val_presets[nr] = sdata if len(sdata) > 1: fx_color = 0 val_color = 0 for fix in sdata: if fix == "CFG": continue #print( "$$$$",fix,sdata[fix]) for attr in sdata[fix]: if "FX" in sdata[fix][attr]: if sdata[fix][attr]["FX"]: fx_color = 1 if "VALUE" in sdata[fix][attr]: if sdata[fix][attr]["VALUE"] is not None: val_color = 1 self.elem_presets[nr]["fg"] = "black" if val_color: self.elem_presets[nr]["bg"] = "yellow" if fx_color: self.elem_presets[nr]["fg"] = "blue" else: if fx_color: self.elem_presets[nr]["bg"] = "cyan" else: self.elem_presets[nr]["fg"] = "black" self.elem_presets[nr]["bg"] = "grey" #self.elem_presets[nr].option_add("*Font", FontBold) label = "" if nr in self.PRESETS.label_presets: #print(dir(self.data)) label = self.PRESETS.label_presets[nr] BTN="go" if "CFG" in sdata:#["BUTTON"] = "GO" if "BUTTON" in sdata["CFG"]: BTN = sdata["CFG"]["BUTTON"] txt = str(nr)+":"+str(BTN)+":"+str(len(sdata)-1)+"\n"+label self.elem_presets[nr]["text"] = txt #print("GO CFG ",self.PRESETS.val_presets) def preset_select(self,nr): print("SELECT PRESET") sdata = self.PRESETS.val_presets[nr] cmd = "" for fix in sdata: if fix == "CFG": continue for attr in sdata[fix]: v2 = sdata[fix][attr]["VALUE"] v2_fx = sdata[fix][attr]["FX"] #print( self.data.elem_attr) if fix in self.elem_attr: elem = self.elem_attr[fix][attr] #self#encoder(attr=attr,data=data,elem=elem,action="click") self.FIXTURES.fixtures[fix]["ATTRIBUT"][attr]["ACTIVE"] = 1 elem["bg"] = "yellow" def preset_go(self,nr,xfade=fade,event=None): print("GO PRESET FADE",nr) rdata = self.PRESETS.get_raw_map(nr) cfg = self.PRESETS.get_cfg(nr) fcmd = self.FIXTURES.update_raw(rdata) #virtcmd = self.data.FIXTURES.get_virtual(rdata) xFLASH = 0 value=None #xfade = fade if modes.val("FLASH") or ( "BUTTON" in cfg and cfg["BUTTON"] == "SEL"): #FLASH self.preset_select(nr) return 0 elif modes.val("FLASH") or ( "BUTTON" in cfg and cfg["BUTTON"] == "FL"): #FLASH xFLASH = 1 xfade = 0 if event: if str(event.type) == "ButtonRelease" or event.type == '5' : # 4 fix vor ThinkPad / Debian 11 if xFLASH: value = "off" vvcmd = update_raw_dmx( rdata ,value,[xfade] ) fxcmd = update_raw_dmx( rdata ,value,[xfade],fx=1) cmd = [] for vcmd,d in [[vvcmd,"d"],[fxcmd,"fx"]]: if xFLASH: d+="f" for i,v in enumerate(fcmd): DMX = fcmd[i]["DMX"] if DMX and vcmd[i]: xcmd = ",{}{}:{}".format(d,DMX,vcmd[i]) cmd.append( xcmd ) if "VIRTUAL" in fcmd[i]: for a in fcmd[i]["VIRTUAL"]: DMX = fcmd[i]["VIRTUAL"][a] if DMX and vcmd[i]: xcmd = ",{}{}:{}".format(d,DMX,vcmd[i]) cmd.append( xcmd ) cmd = "".join(cmd) print("cmd",cmd) if cmd and not modes.val("BLIND"): client.send(cmd ) self.refresh_gui() def draw_dim(self,fix,data,c=0,r=0,frame=None): Font = font.Font(family='Helvetica', size=9, weight='normal') FontBold = font.Font(family='Helvetica', size=10, weight='bold') i=0 if frame is None: frame = tk.Frame(root,bg="black") frame.pack(fill=tk.X, side=tk.TOP) #b = tk.Button(frame,bg="lightblue", text="FIX:"+str(fix)+" "+data["NAME"],width=20) #b.bind("