execlib.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. #/usr/bin/python3
  2. import copy
  3. import __main__ as MAIN
  4. from lib.cprint import cprint
  5. from collections import OrderedDict
  6. import json
  7. try:
  8. import memcache
  9. mc = memcache.Client(['127.0.0.1:11211'], debug=0)
  10. except:
  11. mc = None
  12. def reshape_exec(data ,value=None,xfade=0,flash=0,ptfade=0,DELAY=None):
  13. f=0 #fade
  14. out = []
  15. for row in data:
  16. #cprint("reshape_exec in:",row)
  17. line = {}
  18. if type(value) is float:
  19. line["VALUE"] = value #round(value,3)
  20. else:
  21. line["VALUE"] = value
  22. if "FX" not in row:
  23. cprint("698 FX not in row...",row,color="red")
  24. row["FX"] = ""
  25. else:
  26. if type(row["FX"]) is not str:
  27. cprint("702 FX is not str...",row,color="red")
  28. row["FX"] = ""
  29. if value is not None:
  30. line["FX"] = row["FX"].split(":",1)[-1]
  31. else:
  32. line["FX"] = row["FX"]
  33. if row["FX2"]:
  34. line["FX2"] = row["FX2"]
  35. if row["FIX"]:
  36. line["FIX"] = row["FIX"]
  37. if row["ATTR"]:
  38. line["ATTR"] = row["ATTR"]
  39. if row["VALUE"] is not None:
  40. if value is None:
  41. v=row["VALUE"]
  42. if type(v) is float:
  43. line["VALUE"] = v #round(v,3)
  44. else:
  45. line["VALUE"] = v
  46. if row["ATTR"] in ["PAN","TILT"]:
  47. f = ptfade
  48. for a in ["DIM","ZOOM","FOCUS","RED","GREEN","BLUE","WHITE","AMBER","IRIS","BLADE"]:
  49. #FADE ATTRIBUTES
  50. if a in row["ATTR"]:
  51. f = xfade
  52. break
  53. if flash:
  54. xfade = 0
  55. if type( f ) is float:
  56. line["FADE"] = round(f,4)
  57. else:
  58. line["FADE"] = f
  59. out.append(line)
  60. return out
  61. def filter_fix(vcmd):
  62. FIX = {}
  63. for i in vcmd:
  64. #if i.get("ATTR","").startswith("_"):
  65. # continue
  66. ID = i.get("FIX")
  67. if ID:
  68. FIX[ID] = {"DELAY":0}
  69. return FIX
  70. def calc_align_delay(meta,_xdelay,xfade,vcmd):
  71. for i in vcmd:
  72. i["DELAY"] = round(0,3) # clean DELAY TIMING
  73. print("calc_align_delay",xfade,_xdelay)
  74. if type(xfade) not in [int,float]:
  75. return
  76. if type(_xdelay) not in [int,float]:
  77. return
  78. FIX = filter_fix(vcmd)
  79. XX = list(FIX.keys())
  80. _len = len(XX)
  81. _len_h = int(len(XX)/2)
  82. xdelay = xfade/(_len)*_xdelay
  83. # ALIGN-DELAY
  84. _xd = 0
  85. _align = meta.ALIGN.val()
  86. if _align == ">":
  87. for i in XX:
  88. FIX[i]["DELAY"] = round(_xd,3)
  89. _xd += xdelay
  90. elif _align == "<":
  91. for i in XX[::-1]:
  92. FIX[i]["DELAY"] = round(_xd,3)
  93. _xd += xdelay
  94. elif _align == "><":
  95. xdelay *= 2
  96. for i in XX[:_len_h]:
  97. _xd += xdelay
  98. FIX[i]["DELAY"] = round(_xd,3)
  99. _xd = 0
  100. for i in XX[:_len_h-1:-1]:
  101. _xd += xdelay
  102. FIX[i]["DELAY"] = round(_xd,3)
  103. elif _align == "<>":
  104. xdelay *= 2
  105. for i in XX[:_len_h-1][::-1]:
  106. _xd += xdelay
  107. FIX[i]["DELAY"] = round(_xd,3)
  108. _xd = 0
  109. for i in XX[:_len_h:-1][::-1]:
  110. _xd += xdelay
  111. FIX[i]["DELAY"] = round(_xd,3)
  112. elif _align == "rnd":
  113. _rnd = list(range(len(XX)))
  114. import random
  115. random.shuffle(_rnd)
  116. for j in _rnd:
  117. i = XX[j]
  118. FIX[i]["DELAY"] = round(_xd,3)
  119. _xd += xdelay
  120. sum_delay = 0
  121. for i in FIX:
  122. print("1-->",i,FIX[i])
  123. sum_delay += FIX[i]["DELAY"]
  124. print("###",round(sum_delay,4),round(_xd,4),round(xdelay,4),len(FIX))
  125. for i in vcmd:
  126. ID = i["FIX"]
  127. if ID in i["FIX"]:
  128. i["DELAY"] = FIX[ID]["DELAY"]
  129. #print("2-->",ID,i)
  130. import lib.showlib as showlib
  131. def EXEC_CFG_CHECKER(sdata):
  132. "repair CFG "
  133. ok = 0
  134. if "CFG" not in sdata:
  135. sdata["CFG"] = OrderedDict()
  136. ok += 1
  137. if "FADE" not in sdata["CFG"]:
  138. sdata["CFG"]["FADE"] = 4
  139. ok += 1
  140. if "HAVE-FX" not in sdata["CFG"]:
  141. sdata["CFG"]["HAVE-FX"] = 0
  142. if "HAVE-VAL" not in sdata["CFG"]:
  143. sdata["CFG"]["HAVE-VAL"] = 0
  144. if "FIX-COUNT" not in sdata["CFG"]:
  145. sdata["CFG"]["FIX-COUNT"] = 0
  146. if "DEALY" in sdata["CFG"]: # REMOVE TYPO !
  147. del sdata["CFG"]["DEALY"]
  148. if "DELAY" not in sdata["CFG"]:
  149. sdata["CFG"]["DELAY"] = 0
  150. ok += 1
  151. if "BUTTON" not in sdata["CFG"]:
  152. sdata["CFG"]["BUTTON"] = "GO"
  153. ok += 1
  154. if "HTP-MASTER" not in sdata["CFG"]:
  155. sdata["CFG"]["HTP-MASTER"] = 100 #%
  156. ok += 1
  157. if "SIZE-MASTER" not in sdata["CFG"]:
  158. sdata["CFG"]["SIZE-MASTER"] = 100 #%
  159. ok += 1
  160. if "SPEED-MASTER" not in sdata["CFG"]:
  161. sdata["CFG"]["SPEED-MASTER"] = 100 #%
  162. ok += 1
  163. if "OFFSET-MASTER" not in sdata["CFG"]:
  164. sdata["CFG"]["OFFSET-MASTER"] = 100 #%
  165. ok += 1
  166. if "HAVE-FX" not in sdata["CFG"]:
  167. sdata["CFG"]["HAVE-FX"] = 0 # yes/no
  168. ok += 1
  169. if "HAVE-VAL" not in sdata["CFG"]:
  170. sdata["CFG"]["HAVE-VAL"] = 0 # yes/no
  171. ok += 1
  172. if "FIX-COUNT" not in sdata["CFG"]:
  173. sdata["CFG"]["FIX-COUNT"] = 0 # yes/no
  174. ok += 1
  175. #try:del sdata["CFG"]["SPEED-MASTER"] #= 100 #%
  176. #except:pass
  177. return ok
  178. import time
  179. def exec_set_mc(excec_labels,exec_data):
  180. l = excec_labels
  181. d = exec_data
  182. if not mc:
  183. #cprint("MC not connected !")
  184. return
  185. index=[]
  186. for i,k in enumerate(l):
  187. nr = i
  188. data = d[k]
  189. label=l[nr]
  190. exec_set_mc_single(nr,label,data)
  191. #print("--------------exec_set_mc-------EXEC-META---------------------")
  192. def exec_set_mc_single(nr,label,data):
  193. #data = d[v]
  194. key="EXEC-"+str(nr)
  195. mc.set(key,json.dumps(data))
  196. key2="EXEC-META-"+str(nr)
  197. cfg = {'FADE': 2.0, 'DELAY': 0, 'BUTTON': 'GO', 'HTP-MASTER': 100
  198. ,'SIZE-MASTER': 100, 'SPEED-MASTER': 100, 'OFFSET-MASTER': 100, 'OUT-FADE': 10.0
  199. ,'HAVE-FX': 0, 'HAVE-VAL': 0, 'FIX-COUNT': 11
  200. }
  201. if "CFG" in data:
  202. cfg.update(data["CFG"])
  203. mc.set(key2,json.dumps({"LABEL":label,"CFG":cfg}) )
  204. class EXEC(): #Presets():
  205. def __init__(self):
  206. self.base = showlib.Base()
  207. self._last_copy = None
  208. self._last_move = None
  209. self.fx_buffer = {}
  210. def load_exec(self):
  211. filename="exec"
  212. filename="presets" # preset.sav
  213. d,l = self.base._load(filename)
  214. for i in d:
  215. sdata = d[i]
  216. ok = EXEC_CFG_CHECKER(sdata)
  217. start = time.time()
  218. self.val_exec = d
  219. self.label_exec = l
  220. exec_set_mc(self.label_exec,self.val_exec)
  221. def check_cfg(self,nr=None):
  222. #cprint("EXEC.check_cfg()",nr)#,color="red")
  223. ok = 0
  224. if nr is not None:
  225. if nr in self.val_exec:
  226. sdata = self.val_exec[nr]
  227. ok += self._check_cfg(sdata)
  228. else:
  229. cprint("nr not in data ",nr,color="red")
  230. else:
  231. for nr in self.val_exec:
  232. sdata = self.val_exec[nr]
  233. ok += self._check_cfg(sdata)
  234. return ok
  235. def _check_cfg(self,sdata):
  236. #cprint("EXEC._check_cfg()")#,color="red")
  237. ok = EXEC_CFG_CHECKER(sdata)
  238. if ok:
  239. pass#cprint("REPAIR CFG's",ok,"count:",sdata["CFG"],color="red")
  240. return ok
  241. def backup_exec(self,save_as="",new=0):
  242. filename = "exec" # new
  243. filename = "presets" # preset.sav
  244. data = self.val_exec
  245. labels = self.label_exec
  246. if new:
  247. data = [] #*512
  248. labls = [""]*512
  249. r=self.base._backup(filename,data,labels,save_as)
  250. return r
  251. def get_cfg(self,nr):
  252. #cprint("EXEC.get_cfg()",nr)
  253. self.check_cfg(nr)
  254. if nr not in self.val_exec:
  255. cprint("get_cfg",self,"error get_cfg no nr:",nr,color="red")
  256. return {}
  257. if "CFG" in self.val_exec[nr]:
  258. return self.val_exec[nr]["CFG"]
  259. def set_cfg(self,nr,sdata):
  260. cprint("EXEC.set_cfg()",nr,color="yellow")
  261. cprint(" ",sdata,color="yellow")
  262. #self.check_cfg(nr)
  263. if nr < 0:
  264. return {}
  265. if nr not in self.val_exec:
  266. cprint(" get_cfg",self,"error get_cfg no nr:",nr,color="red")
  267. return {}
  268. if "CFG" in self.val_exec[nr]:
  269. print(" ",self.val_exec[nr]["CFG"] )
  270. print(" ",sdata)
  271. # OrderedDict([('FADE', 4), ('HAVE-FX', 0), ('HAVE-VAL', 0), ('FIX-COUNT', 0), ('DELAY', 0),
  272. #('BUTTON', 'GO'), ('HTP-MASTER', 100), ('SIZE-MASTER', 100), ('SPEED-MASTER', 100), ('OFFSET-MASTER', 100)])
  273. r=EXEC_CFG_CHECKER(sdata)
  274. print(" ",sdata)
  275. self.val_exec[nr]["CFG"] = sdata
  276. if "Label" in sdata:
  277. self.label_exec[nr] = sdata["Label"]
  278. def clean(self,nr):
  279. if nr not in self.val_exec:
  280. self.val_exec[nr] = OrderedDict()
  281. #self.val_exec[nr]["VALUE"] = 0
  282. #self.val_exec[nr]["FX"] = ""
  283. sdata = self.val_exec[nr]
  284. for fix in sdata:
  285. #print("exec.clear()",nr,fix,sdata[fix])
  286. for attr in sdata[fix]:
  287. row = sdata[fix][attr]
  288. if fix == "CFG":
  289. continue
  290. if "VALUE" not in row:
  291. row["VALUE"] = None
  292. if "FX" not in row:
  293. row["FX"] = ""
  294. if "FX2" not in row:
  295. row["FX2"] = OrderedDict()
  296. elif row["FX2"]:
  297. for k in ["SIZE","SPEED","START","OFFSET"]:
  298. row["FX2"][k] = int( row["FX2"][k] )
  299. row["FX"] = ""
  300. if "FX" in row and row["FX"] and not row["FX2"]: # rebuild old FX to Dict-FX2
  301. #"off:0:0:0:16909:-:"
  302. x = row["FX"].split(":")
  303. cprint("-fx",x,len(x))
  304. #'FX2': {'TYPE': 'sinus', 'SIZE': 200, 'SPEED': 30, 'START': 0, 'OFFSET': 2805, 'BASE': '-'}}
  305. if len(x) >= 6:
  306. row["FX2"]["TYPE"] = x[0]
  307. row["FX2"]["SIZE"] = int(x[1])
  308. row["FX2"]["SPEED"] = int(x[2])
  309. row["FX2"]["START"] = int(x[3])
  310. row["FX2"]["OFFSET"] = int(x[4])
  311. row["FX2"]["BASE"] = x[5]
  312. row["FXOLD"] = row["FX"]
  313. row["FX"] = ""
  314. #cprint("exec.clear()",nr,fix,row)
  315. def get_raw_map(self,nr):
  316. self.clean(nr)
  317. #cprint("EXEC.get_raw_map",nr)
  318. sdata = self.val_exec[nr]
  319. cmd = ""
  320. out = []
  321. dmx=-1
  322. for fix in sdata:
  323. if fix == "CFG":
  324. #print("CFG",nr,sdata[fix])
  325. continue
  326. for attr in sdata[fix]:
  327. x = {}
  328. #print("RAW",attr)
  329. x["FIX"] = fix
  330. x["ATTR"] = attr
  331. x["VALUE"] = sdata[fix][attr]["VALUE"]
  332. x["FX"] = sdata[fix][attr]["FX"]
  333. x["FX2"] = sdata[fix][attr]["FX2"]
  334. #x["DMX"] = sdata[fix][attr]["NR"]
  335. out.append(x)
  336. return out
  337. def get_btn_txt(self,nr):
  338. sdata=self.val_exec[nr]
  339. BTN="go"
  340. if "CFG" in sdata:
  341. if "BUTTON" in sdata["CFG"]:
  342. BTN = sdata["CFG"]["BUTTON"]
  343. _label = self.label_exec[nr] # = label
  344. #txt=str(nr+1)+":"+str(BTN)+":"+str(len(sdata)-1)+"\n"+_label
  345. #txt=str(nr+1)+" "+str(BTN)+" "+str(len(sdata)-1)+"\n"+_label
  346. txt="{} {} {}\n{}".format(nr+1,BTN,len(sdata)-1,_label)
  347. cprint("get_btn_txt",nr,[txt])
  348. return txt
  349. def _btn_cfg(self,nr,txt=None):
  350. if nr not in self.val_exec:
  351. return ""
  352. if "CFG" not in self.val_exec[nr]:
  353. self.val_exec[nr]["CFG"] = OrderedDict()
  354. return self.val_exec[nr]["CFG"]
  355. def btn_cfg(self,nr,txt=None):
  356. if nr not in self.val_exec:
  357. return ""
  358. if "CFG" not in self.val_exec[nr]:
  359. self.val_exec[nr]["CFG"] = OrderedDict()
  360. if "BUTTON" not in self.val_exec[nr]["CFG"]:
  361. self.val_exec[nr]["CFG"]["BUTTON"] = ""
  362. if type(txt) is str:
  363. self.val_exec[nr]["CFG"]["BUTTON"] = txt
  364. if self.val_exec[nr]["CFG"]["BUTTON"] is None:
  365. self.val_exec[nr]["CFG"]["BUTTON"] = ""
  366. MAIN.master._refresh_exec(nr=nr)
  367. cprint("EEE", self.val_exec[nr]["CFG"]["BUTTON"] )
  368. return self.val_exec[nr]["CFG"]["BUTTON"]
  369. def label(self,nr,txt=None):
  370. if nr not in self.label_exec:
  371. return ""
  372. if type(txt) is str:
  373. self.label_exec[nr] = txt
  374. cprint("set label",nr,[txt])
  375. cprint("??? ?? set label",nr,[txt])
  376. return self.label_exec[nr]
  377. def clear_move(self):
  378. cprint("EXEC.clear_move()",end=" ")
  379. self.clear_copy()
  380. def clear_copy(self):
  381. cprint("EXEC.clear_copy()",end=" ")
  382. if self._last_copy is not None:
  383. cprint("=OK=",color="red")
  384. self._last_copy = None
  385. else:
  386. cprint("=NONE=",color="green")
  387. def copy(self,nr,overwrite=1):
  388. cprint("EXEC._copy",nr,"last",self._last_copy)
  389. if nr >= 0:
  390. if self._last_copy is not None:
  391. if MAIN.modes.val("COPY"):
  392. MAIN.modes.val("COPY",3)
  393. ok = self._copy(self._last_copy,nr,overwrite=overwrite)
  394. return ok #ok
  395. else:
  396. if MAIN.modes.val("COPY"):
  397. MAIN.modes.val("COPY",2)
  398. self._last_copy = nr
  399. cprint("EXEC.copy START ",color="red")
  400. return 0
  401. return 1 # on error reset move
  402. def _copy(self,nr_from,nr_to,overwrite=1):
  403. cprint("EXEC._copy",nr_from,"to",nr_to)
  404. self.check_cfg(nr_from)
  405. if type(self._last_copy) is None:
  406. cprint("EXEC._copy last nr is None",color="red")
  407. return 0
  408. cprint("------ EXEC._copy", nr_from in self.val_exec , nr_to in self.val_exec)
  409. if nr_from in self.val_exec and nr_to in self.val_exec:
  410. fdata = self.val_exec[nr_from]
  411. tdata = self.val_exec[nr_to]
  412. #cprint(fdata)
  413. flabel = self.label_exec[nr_from]
  414. tlabel = self.label_exec[nr_to]
  415. self.val_exec[nr_to] = copy.deepcopy(fdata)
  416. self.label_exec[nr_to] = flabel
  417. if not overwrite: #default
  418. cprint("overwrite",overwrite)
  419. self.val_exec[nr_from] = copy.deepcopy(tdata)
  420. self.label_exec[nr_from] = tlabel
  421. #self.label_exec[nr_from] = "MOVE"
  422. self.clear_copy()
  423. cprint("EXEC.copy OK",color="green")
  424. return 1
  425. def move(self,nr):
  426. cprint("EXEC.move",self._last_copy,"to",nr)
  427. if nr >= 0:
  428. last = self._last_copy
  429. if MAIN.modes.val("MOVE"):
  430. MAIN.modes.val("MOVE",2)
  431. ok= self.copy(nr,overwrite=0)
  432. if ok and last >= 0:
  433. if MAIN.modes.val("MOVE"):
  434. MAIN.modes.val("MOVE",3)
  435. cprint("EXEC.move OK",color="red")
  436. #self.delete(last)
  437. return ok,nr,last #ok
  438. return 0,nr,last # on error reset move
  439. def delete(self,nr):
  440. cprint("EXEC.delete",nr)
  441. ok=0
  442. if nr in self.val_exec:
  443. self.val_exec[nr] = OrderedDict()
  444. self.label_exec[nr] = "-"
  445. ok = 1
  446. self.check_cfg(nr)
  447. return ok
  448. def rec(self,nr,data,arg=""):
  449. cprint("rec",self,"rec()",len(data),arg,color="red")
  450. self.check_cfg(nr)
  451. self._check_cfg(data) #by ref
  452. odata=self.val_exec[nr]
  453. #print("odata",odata)
  454. if "CFG" in odata:
  455. if "BUTTON" in odata["CFG"]:
  456. data["CFG"]["BUTTON"] = odata["CFG"]["BUTTON"]
  457. self.val_exec[nr] = data
  458. return 1