vpu_live.py 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086
  1. import math
  2. import random
  3. import time
  4. import os
  5. from optparse import OptionParser
  6. ...
  7. parser = OptionParser()
  8. parser.add_option("-m", "--mode", dest="mode",
  9. help="pixel mode pix,x,y --mode 40,10,8") #, metavar="FILE")
  10. parser.add_option("-X", "--XX", dest="XX", #default=1,
  11. help="x-split") #, metavar="FILE")
  12. parser.add_option("-x", "--xx", dest="xsplit", #default=1,
  13. help="x-split") #, metavar="FILE")
  14. parser.add_option("-y", "--yy", dest="ysplit",#default=1,
  15. help="y-split") #, metavar="FILE")
  16. parser.add_option("", "--start-univ", dest="start_univ",#default=1,
  17. help="set start-univers default=2") #, metavar="FILE")
  18. parser.add_option("", "--gobo-ch", dest="gobo_ch",#default=1,
  19. help="gobo ch univ on 1") #, metavar="FILE")
  20. #os.environ['SDL_VIDEO_WINDOW_POS'] = '%i,%i' % (200,164)
  21. parser.add_option("", "--win-pos", dest="win_pos",default="200,164",
  22. help="SDL_VIDEO_WINDOW_POS --win-pos=200,164") #, metavar="FILE")
  23. parser.add_option("", "--pixel-mapping", dest="pixel_mapping",default=0,
  24. help="pixel_mapping file/on --pixel-mapping=_x") #, metavar="FILE")
  25. parser.add_option("", "--countdown", dest="countdown",#default=1,
  26. help="enable countdown") #, metavar="FILE")
  27. #parser.add_option("-f", "--file", dest="filename",
  28. # help="write report to FILE", metavar="FILE")
  29. #parser.add_option("-q", "--quiet",
  30. # action="store_false", dest="verbose", default=True,
  31. # help="don't print status messages to stdout")
  32. (options, args) = parser.parse_args()
  33. START = time.time()
  34. # ===== ARTNET DMX =========
  35. import memcache
  36. mc = memcache.Client(['127.0.0.1:11211'], debug=0)
  37. def read_index():
  38. ips=mc.get("index")#cmd)
  39. if ips is None:
  40. ips = {}
  41. #for k,v in ips.items():
  42. # print(k,v)
  43. return ips
  44. def select_ip(ips, univ=2): # artnet univ
  45. _univ = ":{}".format(univ)
  46. for ip in ips: #high priority
  47. if "2.0.0" in ip and _univ in ip:
  48. return ip
  49. for ip in ips:
  50. if "ltp-out" in ip and _univ in ip:
  51. return ip
  52. FUNC = 0
  53. def read_dmx(ip):
  54. global frame
  55. r = ""
  56. if ip:
  57. #t = int(math.sin(time.time() - s)*10)
  58. r = mc.get(ip) #"2.0.0.13:2")
  59. frame += 1
  60. rr = [0]*512
  61. for i,v in enumerate(r):
  62. try: #cleanup ltp-out to int
  63. v = int(v)
  64. rr[i] = v
  65. except:pass
  66. r = rr
  67. if not r:
  68. c = 0
  69. #time.sleep(0.1)
  70. r = [0] *512
  71. for i in range(12*8+1):
  72. dmx = i*4
  73. #print(dmx)
  74. r[dmx:dmx+4] = [255,10,10,40]
  75. return r
  76. # ===== ARTNET DMX =========
  77. p = 16
  78. block = [p,p]
  79. _x = 8
  80. _y = 8
  81. #HD = "0"
  82. if options.mode:
  83. try:
  84. HD = options.mode
  85. p,_x,_y = HD.split(",")
  86. _x = int(_x)
  87. _y = int(_y)
  88. p = int(p)
  89. block = [p,p]
  90. except Exception as e:
  91. print( "Exc",options.mode,e)
  92. HD_x = 2
  93. HD_y = 2
  94. print( [options.xsplit])
  95. print( [options.ysplit])
  96. try:
  97. if options.xsplit:
  98. HD_x = int(options.xsplit)
  99. if options.ysplit:
  100. HD_y = int(options.ysplit)
  101. except Exception as e:
  102. print( "Exc",options.mode,e)
  103. print("HD",HD_x,HD_y)
  104. print("xy",_x,_y)
  105. print("++++++++++++++++++", p,_x,_y)
  106. _x2 = _x
  107. try:
  108. if options.XX:
  109. pass#_x2 = int(options.XX)
  110. except Exception as e:
  111. print( "Exc",options.mode,e)
  112. print("_x2 , -X",_x2)
  113. # ===== GUI =========
  114. import pygame
  115. import pygame.gfxdraw
  116. import pygame.font
  117. os.environ['SDL_VIDEO_WINDOW_POS'] = '%i,%i' % (200,164)
  118. if options.win_pos:
  119. if "," in options.win_pos:
  120. win_pos = options.win_pos.split(",")
  121. try:
  122. WIN_POS = '%i,%i' % (int(win_pos[0]),int(win_pos[1]) )
  123. os.environ['SDL_VIDEO_WINDOW_POS'] = WIN_POS
  124. except Excetpion as e:
  125. print("win_pos",win_pos,e)
  126. os.environ['SDL_VIDEO_CENTERED'] = '0'
  127. pg = pygame
  128. pygame.init()
  129. pygame.mixer.quit()
  130. f = pygame.font.get_fonts()
  131. for i in f:
  132. if "mono" in i.lower():
  133. print(i)
  134. font = pygame.font.SysFont("freemonobold",22)
  135. font10 = pygame.font.SysFont("freemonobold",10)
  136. font12 = pygame.font.SysFont("freemonobold",12)
  137. font15 = pygame.font.SysFont("freemonobold",15)
  138. font40 = pygame.font.SysFont("freemonobold",40)
  139. font80 = pygame.font.SysFont("freemonobold",70)
  140. #font = pygame.font.SysFont(None,30)
  141. fr = font.render("hallo" ,1, (200,0,255))
  142. PIXEL_MAPPING = 0
  143. grid_file = "/tmp/vpu_grid_hd.csv"
  144. pm_wy = 0
  145. if options.pixel_mapping:
  146. PIXEL_MAPPING = 1
  147. path = options.pixel_mapping
  148. path = path.replace("/","-")
  149. path = path.replace(".","-")
  150. path = path.replace("\"","-")
  151. path = path.replace("'","-")
  152. grid_file = "/home/user/LibreLight/vpu_grid_hd{}.csv".format(path)
  153. #_x = 8
  154. #_y = 8
  155. print(" ",[options.pixel_mapping],"grid_file",grid_file)
  156. #grid_file = "/home/user/LibreLight/vpu_grid_hd.csv"
  157. main_size=(600,500)
  158. try:
  159. if _x < 8 and PIXEL_MAPPING > 1:
  160. wx = 60+block[0] * 8
  161. else:
  162. wx = 60+block[0] * _x
  163. wy = 80+block[1] * _y
  164. main_size=(wx,wy)
  165. if PIXEL_MAPPING >= 1:
  166. pm_wy = 120+block[0] * 8
  167. main_size=(wx,wy+pm_wy)
  168. except Exception as e:
  169. print("Exception:",e)
  170. #main_size=(280,200)
  171. main_size = (main_size[0],main_size[1])
  172. window = pygame.display.set_mode(main_size,pg.RESIZABLE)#,32)#,pygame.FULLSCREEN) #x left->right ,y top-> bottom
  173. pg.display.set_caption('LibreLight VPU-SCREEN')
  174. class Fix():
  175. def __init__(self,_id,pos,block=[16,16],univ=0,dmx=0,ch=4):
  176. #print("Fix",_id)
  177. self._id = _id
  178. self.dmx = (_id-1) * ch +1 #dmx
  179. self.univ = univ
  180. self.ch = ch
  181. self.pos = pos
  182. self.rgb = [0,0,0]
  183. self.block = block #[10,10]
  184. self.x = pos[0]
  185. self.y = pos[1]
  186. self.strobo = time.time()
  187. self.bmp = 250
  188. self.sub_fix = []
  189. sub_block =[block[0]/HD_x,block[1]/HD_y]
  190. if _id <= 0: #exit
  191. return
  192. spalte = (_id-1)%_y +1
  193. zeile = int((_id-1)/_x2) #+1
  194. #zeile = zeile*_x*HD_x*HD_y
  195. add_row = _x*HD_x*HD_y
  196. #zeile 1
  197. sid = (_id-1)*2 + zeile*HD_x*_x2
  198. #for i in range(1,HD_x):
  199. sid = sid+1
  200. #sid = zeile
  201. sub_pos= [pos[0]*block[0],pos[1]*block[1]]
  202. sub_fix = SubFix(sid,sub_pos,sub_block,univ,dmx,ch)
  203. self.sub_fix.append(sub_fix)
  204. sid = sid+1
  205. #sid = zeile
  206. sub_pos= [pos[0]*block[0]+block[0]/2,pos[1]*block[1]]
  207. sub_fix = SubFix(sid,sub_pos,sub_block,univ,dmx,ch)
  208. self.sub_fix.append(sub_fix)
  209. #zeile 2
  210. sid = (_id-1)*2+1 + _x2*HD_x + zeile*HD_x*_x2 # int(add_row)
  211. #sid = sid+1
  212. #sid = HD_x
  213. sub_pos= [pos[0]*block[0],pos[1]*block[1]+block[1]/2]
  214. sub_fix = SubFix(sid,sub_pos,sub_block,univ,dmx,ch)
  215. self.sub_fix.append(sub_fix)
  216. #sid = sid+1
  217. sid = sid+1
  218. sub_pos= [pos[0]*block[0]+block[0]/2,pos[1]*block[1]+block[1]/2]
  219. sub_fix = SubFix(sid,sub_pos,sub_block,univ,dmx,ch)
  220. self.sub_fix.append(sub_fix)
  221. def calc(self,data):
  222. _rgb = [0,255,0]
  223. return _rgb
  224. def sub_calc(self,data):
  225. _rgb = [0,255,0]
  226. for sub_fix in self.sub_fix:
  227. sub_fix.block = self.block[:]
  228. _rgb = sub_fix.calc(data)
  229. return _rgb
  230. def POS(self,x=0,y=0,a=0,b=0):
  231. A = (self.pos[0])*self.block[0]
  232. B = (self.pos[1])*self.block[1]
  233. C = self.block[0]-a
  234. D = self.block[1]-b
  235. return [x+A,y+B,C,D]
  236. def subPOS(self,x=0,y=0,a=0,b=0):
  237. __out = []
  238. for sub_fix in self.sub_fix:
  239. __out.append( sub_fix.POS(x,y,a,b) )
  240. return __out
  241. class SubFix():
  242. def __init__(self,_id,pos,block=[16,16],univ=0,dmx=0,ch=4):
  243. #print("Fix",_id)
  244. self._id = _id
  245. self.dmx = (_id-1) * ch +1 #dmx
  246. self.univ = univ
  247. self.ch = ch
  248. self.pos = pos
  249. self.rgb = [0,0,40]
  250. self.block = block #[10,10]
  251. self.x = pos[0]
  252. self.y = pos[1]
  253. self.strobo = time.time()
  254. self.bmp = 250
  255. def calc(self,data):
  256. #return [130,30,20]
  257. dmx_sub = [30]*10
  258. #print(dmx_sub)
  259. dmx = self.dmx -1
  260. _dmx_sub = []
  261. if self.dmx >= 0:
  262. dmx = rDMX(self.univ,self.dmx)-1
  263. if dmx+self.ch < len(data):
  264. _dmx_sub = data[dmx:dmx+self.ch]
  265. if _dmx_sub:
  266. dmx_sub = _dmx_sub
  267. #print(dmx_sub)
  268. dim = dmx_sub[0]/255
  269. #print("dmx",dmx,dmx_sub)
  270. r = dmx_sub[1]*dim
  271. g = dmx_sub[2]*dim
  272. b = dmx_sub[3]*dim
  273. r = int(r)
  274. g = int(g)
  275. b = int(b)
  276. self.rgb = [r,g,b]
  277. return self.rgb
  278. def POS(self,x=0,y=0,a=0,b=0):
  279. A = (self.pos[0]) #+self.block[0]
  280. B = (self.pos[1]) #+self.block[1]
  281. C = self.block[0]-a
  282. D = self.block[1]-b
  283. if NR:
  284. C-=1
  285. D-=1
  286. return [int(x+A),int(y+B),int(C),int(D)]
  287. class POINTER():
  288. def __init__(self):
  289. self.pos = [0,0,0,0]
  290. self.on = 0
  291. self.rgb = [0,100,10]
  292. self._x = 0
  293. self._y = 0
  294. self.x = 0
  295. self.y = 0
  296. self.fix = Fix(0 ,[999,999],[16,16],0,0,0)
  297. def row_move(self,x,y):
  298. self._x = x
  299. self._y = y
  300. def move(self,pos):
  301. self.pos = pos
  302. self.on = 1
  303. def cross(self,x,y):
  304. self.x = x
  305. self.y = y
  306. def draw(self,x,y):
  307. pos = self.pos[:]
  308. #print("draw",x,y,pos)
  309. pos[0] += x
  310. pos[1] += y
  311. fix_x= self.fix.x
  312. fix_y= self.fix.y +y
  313. #print("draw",x,y,pos)
  314. if self.on:
  315. pygame.draw.rect(window,self.rgb,pos)
  316. #pygame.draw.line(window,self.rgb, (pos[0],pos[1]) , (pos[0]+100,pos[1]) )
  317. # mouse grid posision
  318. fr = font15.render("{}/{}".format(fix_x+1,fix_y) ,1, (200,200,200))
  319. _nr = fix_y * _x + fix_x +1
  320. #fr = font15.render("{:02} {}/{}".format(_nr, fix_x+1,fix_y+1 ) ,1, (200,200,200))
  321. fr = font15.render("{:02}".format(_nr ) ,1, (200,200,200))
  322. window.blit(fr,(pos[0]+2,pos[1]+2 ))
  323. window.blit(fr,(130,1))
  324. # fix pos
  325. txt=str(pos) #"[0, 0, 0, 0]"
  326. fr = font15.render(txt ,1, (200,200,200))
  327. #window.blit(fr,(pos[0]+2,pos[1]+2 ))
  328. window.blit(fr,(10,1))
  329. # univers
  330. #fr = font15.render("{:02}:{:03}".format(fix.univ,fix.dmx) ,1, (200,200,200))
  331. #window.blit(fr,(300,10))
  332. # pointer
  333. fr = font15.render("X:{:03}".format(self._x) ,1, (200,200,200))
  334. window.blit(fr,(10,30))
  335. fr = font15.render("Y:{:03}".format(self._y) ,1, (200,200,200))
  336. window.blit(fr,(10,40))
  337. # crosshair
  338. self.rgb = [0,0,200]
  339. pygame.draw.line(window,self.rgb, (self.x-p,self.y) , (self.x-2,self.y),4 )
  340. pygame.draw.line(window,self.rgb, (self.x,self.y-p) , (self.x,self.y-2),4 )
  341. self.rgb = [0,200,0]
  342. pygame.draw.line(window,self.rgb, (self.x+2,self.y) , (self.x+p,self.y),4 )
  343. pygame.draw.line(window,self.rgb, (self.x,self.y+2) , (self.x,self.y+p),4 )
  344. self.rgb = [200,0,0]
  345. pointer = POINTER()
  346. NR = 0
  347. running = True
  348. def event():
  349. global NR,running
  350. for event in pygame.event.get():
  351. #print(event.dict)
  352. _button = None
  353. if "button" in event.dict:
  354. _button = event.dict["button"]
  355. _state = None
  356. if "state" in event.dict:
  357. _state = event.state
  358. _key = None
  359. if "key" in event.dict:
  360. _key = event.key
  361. _pos = None
  362. if "pos" in event.dict:
  363. _pos = event.pos
  364. _type = None
  365. if "type" in event.dict:
  366. _type = event.type
  367. _type = event.type
  368. _mod = None
  369. if "mod" in event.dict:
  370. _mod = event.mod
  371. if 0:
  372. print( " ")
  373. print( "{:.02f}".format( time.time() - START ))
  374. print("button -",_button,end="\t| ")
  375. #print("state -",_state)
  376. print("pos -",_pos)
  377. print("type -",_type, end="\t| ")
  378. print("key -",_key)
  379. print("mod -",_mod)
  380. try:
  381. if _type == 5:
  382. if _button == 1:
  383. NR += 1
  384. if NR > 1:
  385. NR = 0
  386. if _button == 3:
  387. NR -= 1
  388. if NR < 0:
  389. NR = 1
  390. if _pos:
  391. posA = _pos
  392. fix = find_pix(_pos[0]-40,_pos[1]-60+pm_wy)
  393. if fix:
  394. pos = fix.POS(40,60+pm_wy)
  395. rgb = [0,0,0]
  396. pointer.move(pos)
  397. pointer.fix = fix
  398. else:
  399. pointer.on = 0
  400. pointer.row_move(_pos[0],_pos[1])
  401. pointer.cross(_pos[0],_pos[1])
  402. if event.type == pygame.VIDEORESIZE:
  403. window = pygame.display.set_mode((event.w, event.h), pygame.RESIZABLE)
  404. except Exception as e:
  405. print(e)
  406. if event.type==pygame.QUIT:
  407. running=False
  408. fps = 0
  409. frame = 0
  410. frame_t = time.time()
  411. IP = "yyy"
  412. def draw_overlay():
  413. global fps
  414. fr = font.render("FPS:{}".format(fps) ,1, (200,0,255))
  415. window.blit(fr,(10,10))
  416. fr = font.render("ip:{}".format(IP) ,1, (200,0,255))
  417. window.blit(fr,(80,10))
  418. def calc_fps():
  419. global fps,frame,frame_t
  420. t = time.time()
  421. if frame_t+1 < t:
  422. fps = frame #frame_t- t #frame
  423. frame = 1
  424. frame_t = time.time()
  425. # ===== GUI =========
  426. #def draw_circle(surface, x, y, radius, color):
  427. def draw_circle(surface,color, pos, radius):
  428. x,y=pos
  429. pygame.gfxdraw.aacircle(surface, int(x), int(y), radius-1, color)
  430. pygame.gfxdraw.filled_circle(surface, int(x), int(y), radius-1, color)
  431. def rDMX(univ,dmx):
  432. return univ*512+dmx
  433. def generate_grid(mapping=0):
  434. _log = []
  435. #if PIXEL_MAPPING:
  436. # log = open(grid_file,"w")
  437. head = "i,univ,dmx,x,y,ch\n"
  438. head = "i,univ,dmx,ch\n"
  439. head = "univ,dmx,x,y,ch\n"
  440. head = "nr,id,info\n"
  441. print("csv:",head)
  442. #if PIXEL_MAPPING:
  443. # log.write(head)
  444. _log.append(head)
  445. dmx = 1-1
  446. ch = 4
  447. y=0
  448. x=0
  449. #for i in range((_y)*(_x)):
  450. for i in range((8)*(8)):
  451. #if x > _x and i%_x == 0:
  452. if x > 8 and i%8 == 0:
  453. print("--> -->")
  454. x=0
  455. y+=1
  456. _univ = int(dmx/512)
  457. _dmx = dmx - (_univ)*512
  458. pos=[x,y]
  459. line="{},{},{},{},{},{}\n".format(i+1,_univ,_dmx+1,pos[0],pos[1],ch)
  460. line="{},{},{},{},{}\n".format(_univ,_dmx+1,x,y,ch)
  461. line="{},{},x\n".format(i+1,i+1)
  462. #print("wcsv:",[line])
  463. #if PIXEL_MAPPING:
  464. # log.write(line)
  465. _log.append(line)
  466. dmx += ch
  467. x+=1
  468. if mapping and PIXEL_MAPPING:
  469. print("CREATE NEW PIXELMAP FILE !!",grid_file)
  470. log = open(grid_file,"w")
  471. log.writelines(_log)
  472. log.close()
  473. return _log[:] #GRID
  474. def init_grid(mapping=0,_x=4,_y=4):
  475. if mapping and PIXEL_MAPPING:
  476. try:
  477. log = open(grid_file,"r")
  478. except:
  479. generate_grid(mapping=mapping)
  480. log = open(grid_file,"r")
  481. lines = log.readlines()
  482. else:
  483. lines = generate_grid()
  484. GRID = []
  485. y=0
  486. x=0
  487. print("CSV header",[lines[0]],[PIXEL_MAPPING])
  488. for i,line in enumerate(lines[1:]): #exclude first line
  489. #print("rcsv",[line])
  490. line = line.strip()
  491. line = line.split(",") # csv
  492. if i >= _x and i%_x == 0:
  493. x=0
  494. y+=1
  495. if y >= _y:
  496. break
  497. #i = int(line[0])
  498. _id = int(line[1])
  499. #univ = int(line[0])
  500. #dmx = int(line[1])
  501. #x = int(line[3])
  502. #y = int(line[4])
  503. #ch = int(line[4])
  504. pos = [x,y]
  505. f = Fix(_id,pos,block) #pos,univ,dmx,ch)
  506. #f.x = x
  507. #f.y = y
  508. #f.block = block
  509. GRID.append(f)
  510. x+=1
  511. #print("y, _y",y,_y)
  512. return GRID
  513. def find_pix(x,y):
  514. global GRID
  515. for fix in GRID:
  516. X = 0
  517. Y = 0
  518. pos = fix.POS()
  519. #pos = fix.POS()
  520. #pos = fix.POS(40,60-pm_wy)
  521. #pos = fix.POS(x,y+pm_wy)#40,60)
  522. if x > pos[0] and x < pos[0]+pos[2]:
  523. X = 1
  524. if y > pos[1] and y < pos[1]+pos[3]:
  525. Y = 1
  526. if X and Y:
  527. #print(pos,x,y)
  528. #print("find",X,Y)
  529. return fix
  530. GRID = []
  531. _GRID = []
  532. _GRID = init_grid(_x=8,_y=8,mapping=1) #init_gird()
  533. NR = 0
  534. START_UNIV=2
  535. if options.start_univ:
  536. try:
  537. START_UNIV=int(options.start_univ)
  538. except Exception as e:
  539. print("Exception START UNIV",e)
  540. gobo_ch=1
  541. if options.gobo_ch:
  542. try:
  543. gobo_ch=int(options.gobo_ch)
  544. except Exception as e:
  545. print("Exception gobo_ch",e)
  546. if gobo_ch <= 0:
  547. gobo_ch = 1
  548. def draw_box(pos1,pos2,color=[128,128,128],text=1):
  549. color = [200,0,0,127]
  550. if text:
  551. fr = font15.render("A" ,1, (200,200,200))
  552. window.blit(fr,pos1)
  553. fr = font15.render("B" ,1, (200,200,200))
  554. window.blit(fr,[pos2[0]-10,pos2[1]-10])
  555. # h unten
  556. _pos1 = [pos1[0],pos2[1]]
  557. _pos2 = [pos2[0],pos2[1]]
  558. pygame.draw.aaline(window,color,_pos1,_pos2,1)
  559. color = [255,255,0,127]
  560. # h rechts
  561. _pos1 = [pos2[0],pos1[1]]
  562. _pos2 = [pos2[0],pos2[1]]
  563. pygame.draw.aaline(window,color,_pos1,_pos2,1)
  564. color = [0,200,0,127]
  565. # h links
  566. _pos1 = [pos1[0],pos1[1]]
  567. _pos2 = [pos1[0],pos2[1]]
  568. pygame.draw.aaline(window,color,_pos1,_pos2,1)
  569. color = [0,0,200,127]
  570. # h oben
  571. _pos1 = [pos1[0],pos1[1]]
  572. _pos2 = [pos2[0],pos1[1]]
  573. pygame.draw.aaline(window,color,_pos1,_pos2,1)
  574. def grab(x=55,y=55,w=60,h=60):
  575. # usage
  576. # sub = grab()
  577. # window.blit(sub, (500,10))
  578. crop = None
  579. rect = pygame.Rect(x, y, w, h)
  580. try:
  581. sub = window.subsurface(rect)
  582. #pixArray = pygame.PixelArray(screen)
  583. crop = pygame.Surface((w,h))
  584. crop.blit(sub, (0,0))
  585. except ValueError as e:
  586. pass#print("exception",e,"line715")
  587. #except Exception as e:
  588. # print("exception",e,"line715")
  589. #print(rect)
  590. return crop
  591. def reshape(x,y):
  592. if PIXEL_MAPPING <= 0:
  593. return None
  594. global GRID
  595. global _GRID
  596. i = 0
  597. counter = 0
  598. z=0
  599. x_min = 99999
  600. x_max = 0
  601. y_min = 99999
  602. y_max = 0
  603. fr = font.render("OUTPUT MAP".format(t1.get()) ,1, (255,255,255))
  604. fr_r = fr.get_rect(center=(x+int(wx/2),y+pm_wy-5))
  605. #window.blit(fr,(x+int(wx/2),y+pm_wy))
  606. window.blit(fr,fr_r)
  607. fr = font.render("↑ ↑ ↑".format(t1.get()) ,1, (255,255,255))
  608. fr_r = fr.get_rect(center=(x+int(wx/2),y+pm_wy+15))
  609. #window.blit(fr,(x+int(wx/2),y+pm_wy))
  610. window.blit(fr,fr_r)
  611. fr = font.render("INPUT".format(t1.get()) ,1, (255,255,255))
  612. fr_r = fr.get_rect(center=(x+int(wx/2),y+pm_wy+35))
  613. #window.blit(fr,(x+int(wx/2),y+pm_wy))
  614. window.blit(fr,fr_r)
  615. j = 0
  616. for fix in _GRID:
  617. if j >= 8*8: # max output size
  618. break
  619. #if j >= _x*_y: # max input size
  620. # break
  621. j+=1
  622. ii = i
  623. #z= i # helping border offset
  624. pos = fix.POS(40,60)
  625. rgb = fix.rgb
  626. # green
  627. pygame.draw.rect(window,[0,40,0],pos)
  628. xposs = [] #None #pos[:]
  629. for fix2 in GRID:
  630. if fix._id == fix2._id:
  631. xposs.append( fix2.POS(40,60) )
  632. for xpos in xposs:
  633. sub = grab(xpos[0],xpos[1]+pm_wy,xpos[2],xpos[3])
  634. if sub:
  635. if 1:#j <= _x*_y: # max input size
  636. window.blit(sub, (x+pos[0]+z,y+pos[1]+z))
  637. else:
  638. # red
  639. pygame.draw.rect(window,[40,0,0],pos) #[x+pos[0]+2+z,y+pos[1]+2+z-pm_wy,12,9])
  640. if xpos[0] < x_min:
  641. x_min = xpos[0]
  642. if xpos[0] > x_max:
  643. x_max += xpos[2]
  644. if xpos[1] < y_min:
  645. y_min = xpos[1]
  646. if xpos[1] > x_max:
  647. y_max += xpos[3]
  648. # DRAW FIX NUMBER on TOP
  649. #apos = pos
  650. #argb = rgb
  651. apos = fix.POS(40,60+pm_wy)
  652. argb = fix.rgb
  653. # overwrite number overlay
  654. if NR:
  655. #pygame.draw.rect(window,[30,40,0],apos)
  656. pygame.draw.rect(window,[200,0,0],[x+apos[0]+2+z,y+apos[1]+2+z-pm_wy,12,9])
  657. if NR:# == 2:
  658. if fix._id != i+1:
  659. fr = font15.render("{:02}".format(fix._id) ,1, (255,255,0))
  660. window.blit(fr,(x+apos[0]+2+z,y+apos[1]+2+z-pm_wy))
  661. #print(fix._id,xposs,pos)
  662. else:
  663. fr = font15.render("{:02}".format(fix._id) ,1, (100,100,255))
  664. window.blit(fr,(x+apos[0]+2+z,y+apos[1]+2+z-pm_wy))
  665. i += 1
  666. #print("--#")
  667. # frame box
  668. #pygame.draw.box(window,[100,0,0],[x+x_min,y+x_min,x_max+x_min,y_min+y_max])
  669. pos1= [x+x_min,y+x_min]
  670. pos2= [x_max+x_min,y_min+y_max]
  671. #draw_box(pos1,pos2,text=0)
  672. class Timer():
  673. def __init__(self,start=120):
  674. self.start = start
  675. self.timer = self.start
  676. self.timer_t = time.time()
  677. def reset(self):
  678. self.timer = self.start
  679. def get(self):
  680. self.timer -= time.time()-self.timer_t
  681. self.timer_t = time.time()
  682. if self.timer <= 0:
  683. self.reset()
  684. return self.timer
  685. def reload_grid():
  686. global GRID
  687. global _GRID
  688. try:
  689. GRID = init_grid(_x=_x,_y=_y) #init_gird()
  690. _GRID = init_grid(_x=8,_y=8,mapping=1) #init_gird()
  691. except Exception as e:
  692. print("Except: grid re init",e)
  693. t1 = Timer(143)
  694. time.sleep(0.33)
  695. t2 = Timer(11)
  696. count_tilt = 0
  697. def main():
  698. global IP
  699. global GRID
  700. global _GRID
  701. global FUNC
  702. global count_tilt
  703. counter = time.time()
  704. GRID = init_grid(_x=_x,_y=_y) #init_gird()
  705. #GRID = init_grid(_x=8,_y=8) #init_gird()
  706. print("GRID LEN:",len(GRID))
  707. s=time.time()
  708. print("run")
  709. r = ""
  710. IP = "xx"
  711. while running:
  712. #reload_grid()
  713. pygame.display.flip()
  714. event()
  715. window.fill((10,0,20))
  716. calc_fps()
  717. draw_overlay()
  718. ips = read_index()
  719. # ----
  720. ip = select_ip(ips,univ=1) # univ 1 gobo
  721. dataA = read_dmx(ip)
  722. # ----
  723. ip = select_ip(ips,univ=START_UNIV)
  724. IP = ip
  725. data = read_dmx(ip)
  726. ip = select_ip(ips,univ=START_UNIV+1)
  727. data3 = read_dmx(ip)
  728. data.extend(data3)
  729. ip = select_ip(ips,univ=START_UNIV+2)
  730. data3 = read_dmx(ip)
  731. data.extend(data3)
  732. ip = select_ip(ips,univ=START_UNIV+4)
  733. data3 = read_dmx(ip)
  734. data.extend(data3)
  735. #ip = select_ip(ips,univ=START_UNIV+5)
  736. #data3 = read_dmx(ip)
  737. #data.extend(data3)
  738. # GRID loop
  739. try:
  740. ddd = 1023 #univ 3 512
  741. #FUNC = data[ddd]
  742. FUNC2 = dataA[gobo_ch-1]
  743. FUNC = FUNC2
  744. #print("FUNC", FUNC )#:ddd+512])
  745. #FUNC = 15
  746. except Exception as e:
  747. print("EXC FUNC",e)
  748. i = 0
  749. dmx = 1
  750. h = 1
  751. v = 1
  752. for fix in GRID:
  753. pos = fix.POS(40,60+pm_wy)
  754. rgb = fix.rgb
  755. if 1:
  756. # draw row/col grid number
  757. if fix.pos[0] == 0:
  758. fr = font12.render("{}".format(fix.pos[1]+1) ,1, (200,200,200))
  759. window.blit(fr,(10,pos[1]+3 ))
  760. if fix.pos[1] == 0:
  761. fr = font12.render("{}".format(fix.pos[0]+1) ,1, (200,200,200))
  762. window.blit(fr,(pos[0]+2,35 ))
  763. pygame.draw.rect(window,rgb,pos)
  764. # DRAW SUB-FIXTURE
  765. j = 0
  766. for subfix in fix.sub_fix:#calc(data):
  767. subfix.calc(data)
  768. #fix = subfix
  769. spos = subfix.POS(40,60+pm_wy)
  770. srgb = subfix.rgb
  771. #print(fix.dmx,rgb,pos)
  772. #pygame.draw.circle(window,rgb,(pos[0]+int(pos[2]/2),pos[1]+int(pos[3]/2)),int(pos[3]/2))
  773. #FUNC = 0
  774. if FUNC > 10 and FUNC <= 20: # big dot
  775. draw_circle(window,srgb,(spos[0]+int(spos[2]/2),spos[1]+int(spos[3]/2)),int(spos[3]/2))
  776. elif FUNC > 20 and FUNC <= 30:#small dot
  777. draw_circle(window,srgb,(spos[0]+int(spos[2]/2),spos[1]+int(spos[3]/2)),int(spos[3]/3.5))
  778. elif FUNC > 30 and FUNC <= 40:#donut
  779. draw_circle(window,srgb,(spos[0]+int(spos[2]/2),spos[1]+int(spos[3]/2)),int(spos[3]/2))
  780. draw_circle(window,[0,0,0],(spos[0]+int(spos[2]/2),spos[1]+int(spos[3]/2)),int(spos[3]/3.5))
  781. elif FUNC > 40 and FUNC <= 50: # rec with hole
  782. pygame.draw.rect(window,srgb,spos)
  783. draw_circle(window,[0,0,0],(spos[0]+int(spos[2]/2),spos[1]+int(spos[3]/2)),int(spos[3]/3.5))
  784. elif FUNC > 50 and FUNC <= 60: # rec with big hole
  785. pygame.draw.rect(window,srgb,spos)
  786. draw_circle(window,[0,0,0],(spos[0]+int(spos[2]/2),spos[1]+int(spos[3]/2)),int(spos[3]/2))
  787. elif FUNC > 60 and FUNC <= 70: # rec with donat
  788. pygame.draw.rect(window,srgb,spos)
  789. draw_circle(window,[0,0,0],(spos[0]+int(spos[2]/2),spos[1]+int(spos[3]/2)),int(spos[3]/2))
  790. draw_circle(window,srgb,(spos[0]+int(spos[2]/2),spos[1]+int(spos[3]/2)),int(spos[3]/3.5))
  791. elif FUNC > 70 and FUNC <= 80: # rec boarder
  792. pygame.draw.rect(window,srgb,[spos[0]+1,spos[1]+1,spos[2]-2,spos[3]-2])
  793. elif FUNC > 80 and FUNC <= 90: # rec big boarder
  794. pygame.draw.rect(window,srgb,[spos[0]+2,spos[1]+2,spos[2]-4,spos[3]-4])
  795. elif FUNC > 90 and FUNC <= 100: # rec thin line
  796. pygame.draw.rect(window,srgb,spos)
  797. pygame.draw.rect(window,[0,0,0],[spos[0]+1,spos[1]+1,spos[2]-2,spos[3]-2])
  798. elif FUNC > 100 and FUNC <= 110: # rec big line
  799. pygame.draw.rect(window,srgb,spos)
  800. pygame.draw.rect(window,[0,0,0],[spos[0]+2,spos[1]+2,spos[2]-4,spos[3]-4])
  801. elif FUNC > 110 and FUNC <= 120: # rec with dot
  802. pygame.draw.rect(window,srgb,spos)
  803. pygame.draw.rect(window,[0,0,0],[spos[0]+1,spos[1]+1,spos[2]-2,spos[3]-2])
  804. draw_circle(window,srgb,(spos[0]+int(spos[2]/2),spos[1]+int(spos[3]/2)),int(spos[3]/3.5))
  805. elif FUNC > 120 and FUNC <= 130: # rec inline
  806. pygame.draw.rect(window,srgb,[spos[0]+2,spos[1]+2,spos[2]-4,spos[3]-4])
  807. pygame.draw.rect(window,[0,0,0],[spos[0]+3,spos[1]+3,spos[2]-6,spos[3]-6])
  808. elif FUNC > 130 and FUNC <= 140: # 3 dot (heart)
  809. draw_circle(window,srgb,(spos[0]+int(spos[2]/2)+2,spos[1]+int(spos[3]/2)),int(spos[3]/3.5))
  810. draw_circle(window,srgb,(spos[0]+int(spos[2]/2)-2,spos[1]+int(spos[3]/2)),int(spos[3]/3.5))
  811. draw_circle(window,srgb,(spos[0]+int(spos[2]/2),spos[1]+int(spos[3]/2)+2),int(spos[3]/3.5))
  812. else:
  813. pygame.draw.rect(window,srgb,spos)
  814. # draw row/col grid number
  815. if subfix.pos[0] == 0:
  816. fr = font12.render("{}".format(v ) ,1, (200,200,200))
  817. window.blit(fr,(25,spos[1] ))
  818. v += 1
  819. if subfix.pos[1] == 0:
  820. fr = font12.render("{}".format(1) ,1, (200,200,200))
  821. fr = font12.render("{}".format(h ) ,1, (200,200,200))
  822. h+=1
  823. window.blit(fr,(spos[0],50 ))
  824. if p >= 40:
  825. if NR:
  826. #fr = font15.render("{:02}".format(j+1) ,1, (0,200,255))
  827. fr = font15.render("{:02}".format(subfix._id) ,1, (250,200,5))
  828. window.blit(fr,(spos[0]+2,spos[1]+10))
  829. j += 1
  830. i += 1
  831. # DRAW FIX NUMBER on TOP
  832. i=0
  833. y=0
  834. for fix in GRID:
  835. pos = fix.POS(40,60+pm_wy)
  836. rgb = fix.rgb
  837. if NR:
  838. pygame.draw.rect(window,[0,0,0],[pos[0]+2,pos[1]+2,12,9])
  839. if fix._id%_x-1 == 0: # line break border
  840. pygame.draw.line(window,[255,255,0],(pos[0],pos[1]+4),(pos[0],pos[1]+pos[3]-4),1)
  841. pygame.draw.line(window,[255,255,0],(pos[0],pos[1]+int(pos[3]/2)),(pos[0]+int(pos[2]/2),int(pos[1]+pos[3]/2)),1)
  842. if fix._id%_x == 0: # line break border
  843. pygame.draw.line(window,[255,255,255],(pos[0]+pos[2]-1,pos[1]+4),(pos[0]+pos[2]-1,pos[1]+pos[3]-4),1)
  844. pygame.draw.line(window,[255,255,255],(pos[0]+pos[2]-1,int(pos[1]+pos[3]/2)),(pos[0]+int(pos[2]/2-1),int(pos[1]+pos[3]/2)),1)
  845. if counter +5 < time.time():
  846. counter = time.time()
  847. reload_grid()
  848. if fix._id != i+1:
  849. fr = font15.render("{:02}".format(fix._id) ,1, (255,255,0))
  850. else:
  851. fr = font15.render("{:02}".format(fix._id) ,1, (100,100,255))
  852. window.blit(fr,(pos[0]+2,pos[1]+2))
  853. i += 1
  854. pointer.draw(0,pm_wy) #wy
  855. if options.countdown:
  856. #fr = font80.render("{:0.2f}".format(t1.get()) ,1, (25,20,205))
  857. fr = font80.render("{:0}".format(int(t1.get())) ,1, (25,20,205))
  858. window.blit(fr,(80+count_tilt,int(60+pm_wy+math.sin(count_tilt/100*3.1)*20)))
  859. count_tilt += 1
  860. if count_tilt > 40:
  861. count_tilt = 0
  862. #fr = font80.render("{:05}".format(int((time.time()-START)*100)) ,1, (25,20,205))
  863. #fr = font80.render("{:0.2f}".format(t2.get()) ,1, (25,200,5))
  864. fr = font80.render("{:0}".format(int(t2.get())) ,1, (25,200,5))
  865. window.blit(fr,(80,60+pm_wy))
  866. if PIXEL_MAPPING >= 1:
  867. reshape(0,0) #start pos
  868. else:
  869. reshape(spos[0]+spos[2]+20,10) #start pos
  870. pygame.display.flip()
  871. pg.time.wait(60)
  872. if __name__ == "__main__":
  873. main()