Browse Source

improfe FX3, cleanup and refactor DONE! WORKS!

micha 1 day ago
parent
commit
0fcc2ea948
8 changed files with 331 additions and 205 deletions
  1. 4 2
      _LibreLightDesk.py
  2. 1 2
      _console.py
  3. 5 4
      lib/fxlib.py
  4. 30 7
      lib/jsbc.py
  5. 95 0
      lib/mc_api.py
  6. 2 1
      lib/zchat.py
  7. 70 0
      test/FX3_test.py
  8. 124 189
      tkgui/FX3.py

+ 4 - 2
_LibreLightDesk.py

@@ -551,9 +551,11 @@ def jclient_send(data):
     t_start = time.time()
     jtxt = data
     jdatas = []
+    print("jclient_send.type(data)",type(data))
     for jdata in data:
+        #print("xxffrr",jdata)
         if type(jdata) not in [dict,OrderedDict]:
-            cprint("jclient_send, error jdata not dict like ",[jdata],color="red")
+            cprint("jclient_send, error jdata not dict like ",[jdata,type(jdata)],color="red")
             continue
 
         if "CMD" in jdata:
@@ -567,7 +569,7 @@ def jclient_send(data):
         elif "DMX" in jdata:
 
             try:
-                print(jdata)
+                #print(jdata)
                 jdata["DMX"] = int(jdata["DMX"])
                 dmx = jdata["DMX"]
 

+ 1 - 2
_console.py

@@ -1126,6 +1126,7 @@ def _parse_cmds(cmds,clock=0):
     return out
 
 def _parse_cmd(out,cmd,clock=0):
+    #print("_parse_cmd",out,cmd)
     master_fx = MASTER_FX()
     Admx = DMXCH() #dummy
     x=cmd
@@ -1336,10 +1337,8 @@ def JCB(data,sock=None): #json client input
 
     e  = time.time()
     ct = int(e*100)/100
-    print()
     msg = "{} JCB START: {:0.02f} sizeof:{}"
     msg = msg.format(ct,e-s,sys.getsizeof(data) ) 
-    print(msg)
 
     jdatas = parse_json(data)
 

+ 5 - 4
lib/fxlib.py

@@ -50,7 +50,7 @@ def process_wings(xfixtures,fx_prm):
         wing_buffer = _wing_buffer
     return wing_buffer
 
-def process_effect(wing_buffer,fx_prm,fx_prm_move,modes,jclient_send,master,FIXTURES,fx_name=""):
+def _process_effect(wing_buffer,fx_prm,fx_prm_move,FIXTURES,fx_name=""):
     jdatas = []
     offset = 0
     offset_move = 0
@@ -169,7 +169,7 @@ def process_effect(wing_buffer,fx_prm,fx_prm_move,modes,jclient_send,master,FIXT
                             else:
                                 fx = "sinus"
 
-                    elif ":RED" in f_name:
+                    elif ":RED" in fx_name:
                         fxon  = "on" 
                         fxoff = "static" #"off" 
                         MODE = fx_modes[fx_prm["MODE"]]
@@ -293,11 +293,12 @@ def process_effect(wing_buffer,fx_prm,fx_prm_move,modes,jclient_send,master,FIXT
                 else:
                     offset += aoffset 
                 offset = round(offset,2)
+    return jdatas
 
-    #exit()
+def process_effect(wing_buffer,fx_prm,fx_prm_move,modes,jclient_send,master,FIXTURES,fx_name=""):
+    jdatas = _process_effect(wing_buffer,fx_prm,fx_prm_move,FIXTURES,fx_name=fx_name)
     if jdatas and not modes.val("BLIND"):
         jclient_send(jdatas)
     master._refresh_fix()
-
     return jdatas
 

+ 30 - 7
lib/jsbc.py

@@ -4,6 +4,7 @@ import time
 import traceback
 import json
 import _thread as thread
+from collections import OrderedDict
 
 import __main__ as MAIN
 from lib.cprint import *
@@ -13,17 +14,16 @@ import lib.fixlib as fixlib
 GLOBAL_old_exec_nr = -1
 def JSCB(x,sock=None):
     global GLOBAL_old_exec_nr 
-    print()
+    print("JSCB ...",x)
     # REMOTE KEY EVENT's
     i = ""
     msg = ""
     msgs = []
+    FX3 = []
     try:
-        #print("JSCB",sock)
         for i in x:
-            #print("i",[i])
             msgs = json.loads(i)
-            #print(" JSCB",msgs) #,sock)
+
             if type(msgs) is not list:
                 continue
             
@@ -58,9 +58,16 @@ def JSCB(x,sock=None):
                     fixlib.encoder(MAIN.FIXTURES.fixtures,str(fix_nr),attr,xval=val,xfade=0,xdelay=0)#,blind=0)
                     OK = 1
                 elif "FX3" == msg["event"]:
-                    msg["VALUEx"] = "DOOM"
                     cprint("FX3 OK",color="yellow")
-                    MAIN.jclient_send([msg]) #ajdata)
+                    i=0
+                    msg2 ={}
+                    for v in ['MODE', 'WING', 'VALUE', 'FIX', 'DMX', 'ATTR', 'FX2']:
+                        print("*'*'",v)
+                        if v in msg:
+                            msg2[v] = msg[v]
+                            i+=1
+                    msg = msg2
+                    FX3.append(msg2)
                     OK = 1
                 elif "CLEAR" == msg["event"]:
                     fixlib.clear(MAIN.FIXTURES.fixtures)
@@ -77,7 +84,9 @@ def JSCB(x,sock=None):
                     MAIN.modes.val(msg["event"],1)
                     OK = 1
                 elif "FX-OFF" == msg["event"]:
-                    MAIN.CONSOLE.fx_off("all") 
+                    MAIN.FIXTURES.fx_off("all")
+                    MAIN.CONSOLE.fx_off("all")
+                    MAIN.CONSOLE.flash_off("all")
                     OK = 1
                 elif "SAVE\nSHOW" == msg["event"]:
                     MAIN.save_show()
@@ -194,6 +203,20 @@ def JSCB(x,sock=None):
                 else:
                     cprint(" jsbc.remote-key:",msg ,color="red")
                     print()
+            if FX3:
+                MAIN.jclient_send(FX3)
+                for i in FX3:
+                    if "FIX" in i and "ATTR" in i:
+                        fix = i["FIX"]
+                        attr = i["ATTR"]
+                        if attr.startswith("_"):
+                            continue
+                        if fix in MAIN.FIXTURES.fixtures:
+                            if attr in MAIN.FIXTURES.fixtures[fix]["ATTRIBUT"]:
+                                # insert FX3 into fixture.attr.FX2
+                                MAIN.FIXTURES.fixtures[fix]["ATTRIBUT"][attr]["FX2"] = OrderedDict(i["FX2"])
+                FX3 = []
+
     except Exception as e:
         cprint("exception JSCB:",e,color="red")
         cprint("- i:",i,color="red")

+ 95 - 0
lib/mc_api.py

@@ -0,0 +1,95 @@
+#!/usr/bin/python3
+
+import json
+import memcache
+try:
+    mc = memcache.Client(['127.0.0.1:11211'], debug=0)
+except:
+    mc = None
+
+def get_programmer():
+    if mc is None:
+        return
+
+    DATA=mc.get("fix")#cmd)
+    out=[]
+    for k,v in DATA.items():
+        ok=0
+        for kk,vv in v["ATTRIBUT"].items():
+            if kk.startswith("_"):
+                continue
+            if vv["ACTIVE"]:
+                tmp={"ID":k,"NAME":v["NAME"],"ATTR":kk,"NR":vv["NR"]} #,"FX3":vv["FX2"]}
+                out.append(tmp)
+                ok=1
+        #if ok:
+        #    print()
+    return out
+
+def get_patch():
+    if mc is None:
+        return
+    index=mc.get("PATCH-INDEX") #index")#cmd)
+    index=json.loads(index)
+    out = []
+    for v in index:
+        patch=mc.get("PATCH-"+str(v)) #index")#cmd)
+        patch=json.loads(patch)
+        u =  patch["UNIVERS"] #* 512
+        d =  patch["DMX"]
+        attr = {}
+        for a in patch["ATTRIBUT"]:
+            nr =patch["ATTRIBUT"][a]["NR"] 
+            if nr <= 0:
+                continue
+            if a == "END":
+                continue
+            if a.startswith("_"):
+                continue
+            nr = nr + d + u*512
+            attr[a] = nr-1
+        tmp = {"FIX":v,"UNI":u,"DMX":d,"NR":nr,"ATTR":attr}
+        out.append(tmp )
+    
+    return out
+
+
+
+def patch_order_by_fix(patch):
+    out={}
+    for p in patch:
+        ID = p["FIX"]
+        out[ID] = p
+        #print("patch_order",[ID,p])
+    return out
+
+def get_exec_meta(nr):
+    data = {}
+    try:
+        data = mc.get("EXEC-META-"+str(nr)) 
+        data = json.loads(data)
+    except Exception as e:
+        print("  ER1R mc...",e)
+    return data 
+
+modes = {}
+def modes_refresh():
+    global modes
+    try:
+        data = mc.get("MODES")
+        data = json.loads(data)
+        modes = data
+    except Exception as e:
+        print("  ER7R mc...",e)
+        #time.sleep(3)
+    return modes
+
+def modes_refresh_loop():
+    time.sleep(3)
+    while 1:
+        modes_refresh()
+        time.sleep(0.1)
+
+
+
+

+ 2 - 1
lib/zchat.py

@@ -62,7 +62,7 @@ def _send(sock,msg):
         r=sock.send(_msg)
         return r
     except Exception as e:
-        print("excep _send",e)
+        print("ERR zchat._send",e)
 
 
 def _recv(sock):
@@ -293,6 +293,7 @@ class Client():
 
     def send(self,msg):
         r=_send(self.xs,msg)
+        print("send",r)
         if not r:
             self.connect()
 

+ 70 - 0
test/FX3_test.py

@@ -0,0 +1,70 @@
+import json
+import lib.zchat as chat
+import time
+import lib.fxlib
+
+cmd_client = chat.Client(port=30003)
+time.sleep(1)
+print("TEST")
+
+msg=json.dumps([{"event":"FX-OFF","VALUE":255,"DATA":{}}]).encode("utf-8")
+cmd_client.send(msg) # diable LABEL mode
+time.sleep(0.1)
+
+msg = [{'event': 'CLEAR', 'TYPE': 'ENCODERS', 'FIX': '', 'VAL': 'click', 'ATTR': ""}]
+msg=json.dumps(msg).encode("utf-8")
+print(msg)
+cmd_client.send(msg)
+time.sleep(0.5)
+
+for i in range(1,10):
+    for attr in ["RED","BLUE","GREEN","PAN","TILT","DIM"]:
+        msg = [{'event': 'FIXTURES', 'TYPE': 'ENCODERS', 'FIX': str(3000+i), 'VAL': 'click', 'ATTR': attr}]
+        msg=json.dumps(msg).encode("utf-8")
+        print(msg)
+        cmd_client.send(msg)
+        time.sleep(.01)
+
+
+time.sleep(1)
+msg_x = {'event' :"FX3", 'TYPE': 'ENCODERS', 'MODE': 'FX', 'WING': 2, 'VALUE': None, 'FIX': '3009', 'DMX': 248, 'DMX-FINE': -199, 'ATTR': 'BLUE', 'FX2': {'TYPE': 'sinus', 'SIZE': 255, 'SPEED': 10, 'WIDTH': 25, 'START': 0, 'OFFSET': 200.0, 'INVERT': 1, 'BASE': '-'}}
+
+msg_x = {'event':'FX3','MODE': 'FX', 'WING': 2, 'VALUE': None, 'FIX': '3009', 'DMX': 248, 'DMX-FINE': -199, 'ATTR': 'BLUE', 'FX2': {'TYPE': 'cosinus', 'SIZE': 255, 'SPEED': 10, 'WIDTH': 25, 'START': 0, 'OFFSET': 200.0, 'INVERT': 1, 'BASE': '-'}}
+msg = [msg_x]
+msg=json.dumps(msg).encode("utf-8")
+print("msg send",msg)
+cmd_client.send(msg)
+
+exit()
+while 1:
+    msg = input()
+    #msg=[msg]
+    #msg=json.dumps(msg).encode("utf-8")
+    msg=msg.encode("utf-8")
+    print("msg send",msg)
+    cmd_client.send(msg)
+
+
+#wing_buffer = list(range(3002,3009+1))
+#jdatas = _process_effect(wing_buffer,fx_prm,fx_prm_move,FIXTURES,fx_name=fx_name)
+
+exit()
+
+time.sleep(1)
+
+msg = msg_x
+i=11
+msg = [{'event': 'FIXTURES', 'TYPE': 'ENCODERS', 'FIX': str(3000+i), 'VAL': 'click', 'ATTR': attr}]
+msg = {'event': 'FX3', 'TYPE': 'ENCODERS', 'FIX': '3009', 'VAL': 'click', 'ATTR': 'DIM', 'FX2': {'TYPE': 'sinus', 'SIZE': 255, 'SPEED': 20, 'WIDTH': 25, 'START': 0, 'OFFSET': 200.0, 'INVERT': 1, 'BASE': '-'}}
+#msg = msg_x
+msg=[msg]
+msg=json.dumps(msg).encode("utf-8")
+print("msg send",msg)
+cmd_client.send(msg)
+
+
+
+
+
+input()
+input()

+ 124 - 189
tkgui/FX3.py

@@ -37,6 +37,10 @@ import lib.tkevent as tkevent
 import tool.movewin as movewin
 movewin.check_is_started("FX3","/opt/LibreLight/Xdesk/tkgui/FX3.py")
 
+class rEvent():
+    def __init__(self):
+        self.num = 1
+        self.type = "rEvent <EventType.ButtonPress: '4'>"
 
 console = chat.Client() #port=50001)
 def jsend(jdatas):
@@ -137,20 +141,14 @@ def reshape_grid_to_jdata(grid_data1):
     for i in grid_data1: 
         attr = i["ATTR"].strip()
         if attr:
+            #grid_data2[attr] = {"event":"FX3","MODE":"FX2","DMX":-11,"DMX-FINE":-99,"FIX":"","ATTR":"","VALUE":None,"FX2":i} 
             grid_data2[attr] = {"event":"FX3","MODE":"FX","DMX":-11,"DMX-FINE":-99,"FIX":"","ATTR":"","VALUE":None,"FX2":i} 
     return grid_data2
 
-def patch_order_by_fix(patch):
-    out={}
-    for p in patch:
-        ID = p["FIX"]
-        out[ID] = p
-        #print("patch_order",[ID,p])
-    return out
 
 def update_dmx_adresses(grid_data2): 
-    patch = get_patch() 
-    patch = patch_order_by_fix(patch)
+    patch = mc_api.get_patch() 
+    patch = mc_api.patch_order_by_fix(patch)
     out=[]
     for i in grid_data2:
         ID = i["FIX"]
@@ -171,10 +169,10 @@ def update_dmx_adresses(grid_data2):
     return grid_data2
 
 def extract_fixture_list(grid_data3):
-    print()
+    #print()
     out = {}
     for k,v in enumerate(grid_data3):
-        print("calc_off",k,v)
+        #print("calc_off",k,v)
         if v["FIX"] not in out:
             out[v["FIX"]] = 0
         else:
@@ -183,7 +181,7 @@ def extract_fixture_list(grid_data3):
 
 def correct_base(grid_data3):
     for k,v in enumerate(grid_data3):
-        print("BASE:",[k,v])
+        #print("BASE:",[k,v])
         if type(v["FX2"]["BASE"]) not in [int,float]:
             continue
 
@@ -199,7 +197,7 @@ def calculate_offset(grid_data3):
     offset = {}
     offset_len = len(fix)-1
 
-    print()
+    #print()
     for i,f in enumerate(fix):
 
         for k,v in enumerate(grid_data3):
@@ -214,7 +212,7 @@ def calculate_offset(grid_data3):
 
             nof = round( offset[attr]*i,2 ) # ID
             v["FX2"]["OFFSET"] = nof
-            print("x_offset: ",k,v["FIX"],v["ATTR"],offset,nof)
+            #print("x_offset: ",k,v["FIX"],v["ATTR"],offset,nof)
 
 def merge_grid_and_programmer(programmer,grid_data2):
     out=[]
@@ -222,10 +220,12 @@ def merge_grid_and_programmer(programmer,grid_data2):
     for k,v in enumerate(programmer):
         attr = v["ATTR"]
         ID = v["ID"]
-        print("v",v)
+        #print("merge_grid..",v)
         if attr in grid_data2:
             tmp = copy.deepcopy(grid_data2[attr])
-            print(" ",tmp)
+            if "GRP" in tmp["FX2"]:
+                del tmp["FX2"]["GRP"]
+            #print(" tmp",tmp)
             _offset = tmp["FX2"]["OFFSET"]
             tmp["ATTR"] = attr
             tmp["FIX"] = ID
@@ -233,7 +233,7 @@ def merge_grid_and_programmer(programmer,grid_data2):
     return out
 
 def log(x,name="log",color="yellow"):
-    print()
+    #print()
     if type(x) in [dict]: #,OrderedDict]:
         for k,v in x.items():
             cprint(name,[k,v],color=color)
@@ -252,27 +252,28 @@ class tk_event_fx():
         self.mode = mode
         self.ATTR_GRP = ""
 
-    def command_fx3(self,event,mode=""):
+    def command_fx3(self,event=None,mode=""):
         prm = []
         ct  = ""
-        print(" --", self.attr)
+        #print(" --", self.attr)
         fx3_grid = MAIN.meta.fx3_grid # OptionBuffer()
         if self.attr == "START":
             grid_data1 = get_fx3_grid()
             grid_data2 = reshape_grid_to_jdata(grid_data1)
-            programmer=get_programmer()
+            programmer = mc_api.get_programmer()
             grid_data3 = merge_grid_and_programmer(programmer,grid_data2)
 
             calculate_offset(grid_data3)
             correct_base(grid_data3)
             update_dmx_adresses(grid_data3)
 
-            msg=json.dumps(grid_data3).encode("utf-8")
-            cprint("SEND FX3:",color="green")
+            grid_data4 = []
             for i in grid_data3:
                 cprint(" ", i,color="green")
-            #cmd_client.send(msg)
-            jsend(msg)
+                grid_data4.append(i)
+            msg=json.dumps(grid_data4).encode("utf-8")
+            cprint("SEND FX3:",color="green")
+            cmd_client.send(msg)
 
         if self.attr not in fx3_grid:
             fx_data = {}
@@ -294,7 +295,7 @@ class tk_event_fx():
                     if "ATTR" in v and v["ATTR"] != " ":
                         print("HH",k,v)
 
-            print()
+            #print()
             return
         fx_func = MAIN.meta.OptionBuffer()
         if self.attr.startswith("ATTR:"):
@@ -327,7 +328,7 @@ class tk_event_fx():
         return
 
 
-    def command(self,event,mode=""):       
+    def command(self,event=None,mode=""):       
         cprint("tkevent.tk_event_fx.command")
         cprint(" ",self.mode)
         prm = None
@@ -635,7 +636,7 @@ def refresh_fx3_elem(_filter=""):
             v2 = MAIN.meta.fx3_grid[comm].val()
             v1 = b["text"]
             if str(v2) != str(v1):
-                print(" change")
+                #print(" change")
                 b["text"] = str(v2)
 
 def refresh_fx3_loop():
@@ -643,6 +644,55 @@ def refresh_fx3_loop():
         refresh_fx3_elem()
         time.sleep(2)
 
+def _XXX(xcb,xcomm,xb):
+    def XXX(event=None,**data):
+        print("BTN:",xb["text"],xcomm)
+        print("xXx "*22)
+        print("XXX",event,data)
+        if xcomm == "CIRCLE":
+            motion("circle")
+        elif xcomm == "PAN":
+            motion("pan")
+        elif xcomm == "TILT":
+            motion("tilt")
+        elif xcomm == "FLAY":
+            motion("flay")
+        elif xcomm == "STREET":
+            motion("street")
+        elif xcomm == "DIM":
+            dim(code="dim")
+        elif xcomm == "RED":
+            rgb("red")
+        elif xcomm == "GREEN":
+            rgb("green")
+        elif xcomm == "BLUE":
+            rgb("blue")
+        elif xcomm == "CYAN":
+            rgb("cyan")
+        elif xcomm == "MAGENTA":
+            rgb("magenta")
+        elif xcomm == "YELLOW":
+            rgb("yellow")
+        elif xcomm == "MINI":
+            size(25)
+        elif xcomm == "SMALL":
+            size(50)
+        elif xcomm == "NORMAL":
+            size(100)
+        elif xcomm == "BIG":
+            size(255)
+        elif xcomm == "SLOW":
+            speed(5)
+        elif xcomm == "MID":
+            speed(25)
+        elif xcomm == "FAST":
+            speed(80)
+        elif xcomm == "TURBO":
+            speed(160)
+
+        xcb(event) #,data)
+    return XXX
+
 def _draw_fx3(frame,c,r,gui,mode="FX"):
     ct  = MAIN.meta.fx3 #moves
     prm = MAIN.meta.fx3_prm
@@ -666,54 +716,6 @@ def _draw_fx3(frame,c,r,gui,mode="FX"):
         ct.elem[comm] = b
         ct.val[comm] = 0
 
-        def _XXX(xcb,xcomm,xb):
-            def XXX(event=None,**data):
-                print("BTN:",xb["text"],xcomm)
-                print("xXx "*22)
-                print("XXX",event,data)
-                if xcomm == "CIRCLE":
-                    motion("circle")
-                elif xcomm == "PAN":
-                    motion("pan")
-                elif xcomm == "TILT":
-                    motion("tilt")
-                elif xcomm == "FLAY":
-                    motion("flay")
-                elif xcomm == "STREET":
-                    motion("street")
-                elif xcomm == "DIM":
-                    dim(code="dim")
-                elif xcomm == "RED":
-                    rgb("red")
-                elif xcomm == "GREEN":
-                    rgb("green")
-                elif xcomm == "BLUE":
-                    rgb("blue")
-                elif xcomm == "CYAN":
-                    rgb("cyan")
-                elif xcomm == "MAGENTA":
-                    rgb("magenta")
-                elif xcomm == "YELLOW":
-                    rgb("yellow")
-                elif xcomm == "MINI":
-                    size(25)
-                elif xcomm == "SMALL":
-                    size(50)
-                elif xcomm == "NORMAL":
-                    size(100)
-                elif xcomm == "BIG":
-                    size(255)
-                elif xcomm == "SLOW":
-                    speed(5)
-                elif xcomm == "MID":
-                    speed(25)
-                elif xcomm == "FAST":
-                    speed(80)
-                elif xcomm == "TURBO":
-                    speed(160)
-
-                xcb(event) #,data)
-            return XXX
 
         _cb = tk_event_fx(fix=0,elem=b,attr=comm,data=gui,mode=mode).cb
         _comm = comm
@@ -848,11 +850,6 @@ root = None
 
 cmd_client = chat.Client(port=30003)
 
-try:
-    import memcache
-    mc = memcache.Client(['127.0.0.1:11211'], debug=0)
-except:
-    mc = None
 
 class GUI(): # DUMMY
     def __init__(self):
@@ -863,58 +860,6 @@ class GUI(): # DUMMY
         for i in range(512):
             self.METAS.append({})
 
-    def _load_meta(self,nr):
-        data = {}
-        try:
-            data = mc.get("EXEC-META-"+str(nr)) 
-            data = json.loads(data)
-        except Exception as e:
-            print("  ER1R mc...",e)
-        return data 
-
-    def _refresh_meta_data(self,*arg,**args):
-        start = time.time()
-
-        METAS = []
-        for i in range(512):
-            nr = i #+1
-            METAS.append( self._load_meta(nr) )
-
-        self.METAS = METAS
-
-        for nr,b in enumerate( self.elem_exec): #[nr]
-            self._refresh_data_single(nr,b,METAS)
-
-        print(__file__.split("/")[-1], "_refresh_meta_data:",int((time.time()-start)*10)/10 )
-
-    def refresh_meta_loop(self):
-        time.sleep(3)
-        while 1:
-            try:
-                self._refresh_meta_data()
-                time.sleep(3)
-            except Exception as e:
-                print("  ER5R refr_loop()...",e)
-                time.sleep(3)
-            time.sleep(0.1)
-
-    def _refresh_data_single(self,nr,b,METAS=None):
-        start = time.time()
-        no_meta = 0
-
-        if not METAS:
-            no_meta = 1
-            try:
-                data = mc.get("EXEC-META-"+str(nr)) #,json.dumps(index))
-                data = json.loads(data)
-                self.METAS[nr] = data #.append(data)
-                #print(time.time())
-                print("     _REFRESH_EXEC_sinusGLE",nr,b,data["LABEL"])
-            except Exception as e:
-                print("  ER1R mc...",e)
-
-            METAS = self.METAS
-
 
 gui  = GUI()
  
@@ -980,59 +925,7 @@ def focus_out(event=None):
 root.bind("<FocusIn>", focus_in)
 root.bind("<FocusOut>", focus_out)
 
-import memcache
-try:
-    mc = memcache.Client(['127.0.0.1:11211'], debug=0)
-except:
-    mc = None
-
-def get_programmer():
-    if mc is None:
-        return
-
-    DATA=mc.get("fix")#cmd)
-    out=[]
-    for k,v in DATA.items():
-        ok=0
-        for kk,vv in v["ATTRIBUT"].items():
-            if kk.startswith("_"):
-                continue
-            if vv["ACTIVE"]:
-                tmp={"ID":k,"NAME":v["NAME"],"ATTR":kk,"NR":vv["NR"]} #,"FX3":vv["FX2"]}
-                out.append(tmp)
-                ok=1
-        if ok:
-            print()
-    return out
-
-def get_patch():
-    if mc is None:
-        return
-    index=mc.get("PATCH-INDEX") #index")#cmd)
-    index=json.loads(index)
-    out = []
-    for v in index:
-        patch=mc.get("PATCH-"+str(v)) #index")#cmd)
-        patch=json.loads(patch)
-        u =  patch["UNIVERS"] #* 512
-        d =  patch["DMX"]
-        attr = {}
-        for a in patch["ATTRIBUT"]:
-            nr =patch["ATTRIBUT"][a]["NR"] 
-            if nr <= 0:
-                continue
-            if a == "END":
-                continue
-            if a.startswith("_"):
-                continue
-            nr = nr + d + u*512
-            attr[a] = nr-1
-        tmp = {"FIX":v,"UNI":u,"DMX":d,"NR":nr,"ATTR":attr}
-        out.append(tmp )
-    
-    return out
-
-
+import lib.mc_api as mc_api
 
 modes = {}
 def modes_refresh_loop():
@@ -1040,9 +933,8 @@ def modes_refresh_loop():
     while 1:
         try:
             global root,title,modes
-            data = mc.get("MODES")
+            data = mc_api.modes_refresh()
             title2 = title +"  "+str(data)
-            data = json.loads(data)
             modes = data
 
             if root:
@@ -1075,12 +967,55 @@ def modes_refresh_loop():
 
               
         except Exception as e:
-            print("  ER7R mc...",e)
+            print("  ER44 mode_refr ...",e)
             time.sleep(3)
         time.sleep(0.1)
 
-thread.start_new_thread(gui.refresh_meta_loop,())
+#thread.start_new_thread(gui.refresh_meta_loop,())
 thread.start_new_thread(modes_refresh_loop,())
 thread.start_new_thread(refresh_fx3_loop,())
 
+if "--test" in sys.argv:
+    def test():
+        time.sleep(1)
+        print("TEST...")
+        time.sleep(1)
+        print("TEST...")
+        event = rEvent()
+
+        msg = [{'event': 'CLEAR', 'TYPE': 'ENCODERS', 'FIX': '', 'VAL': 'click', 'ATTR': ""}]
+        msg=json.dumps(msg).encode("utf-8")
+        cmd_client.send(msg)
+        time.sleep(1)
+
+        for i in range(1,10):
+            for attr in ["RED","BLUE","GREEN","PAN","TILT","DIM"]:
+                msg = [{'event': 'FIXTURES', 'TYPE': 'ENCODERS', 'FIX': str(3000+i), 'VAL': 'click', 'ATTR': attr}]
+                msg=json.dumps(msg).encode("utf-8")
+                cmd_client.send(msg)
+
+
+        mode = "FX-MAIN"
+        attr="FX OFF"
+        cb0 =  tk_event_fx(fix=0,elem=None,attr=attr,data=gui,mode=mode).cb
+        cb0(event)
+
+        mode = "FX-3"
+        attr="CIRCLE"
+        attr="RED"
+        _cb =  tk_event_fx(fix=0,elem=None,attr=attr,data=gui,mode=mode).cb
+        b = tk.Button(root,bg="lightgrey", text=str(attr),width=6,height=1) # dummy button
+        cb1 = _XXX(_cb,attr,b)
+        time.sleep(1)
+        cb1(event)
+
+        attr="START"
+        cb1 =  tk_event_fx(fix=0,elem=None,attr=attr,data=gui,mode=mode).cb
+        time.sleep(1)
+        cb1(event)
+
+
+
+    thread.start_new_thread(test,())
+
 root.mainloop()