gonzopiserver.py (20468B)
1 #!/usr/bin/env python3 2 3 import web 4 import os 5 import socket 6 import ifaddr 7 import sys 8 import time 9 import random 10 import hashlib 11 import configparser 12 from pymediainfo import MediaInfo 13 14 # Get path of the current dir, then use it as working directory: 15 rundir = os.path.dirname(__file__) 16 if rundir != '': 17 os.chdir(rundir) 18 19 urls = ( 20 '/','intro', 21 '/c/?', 'index', 22 '/f/(.*)?', 'films', 23 '/t/(.*)?', 'tree', 24 '/p/(.*)?', 'player', 25 '/api','api' 26 ) 27 28 #--------------USB filmfolder------------------- 29 30 def usbfilmfolder(): 31 usbmount = 0 32 while True: 33 usbconnected = os.path.ismount('/media/usb'+str(usbmount)) 34 time.sleep(0.02) 35 if usbconnected == True: 36 try: 37 os.makedirs('/media/usb'+str(usbmount)+'/gonzopifilms/') 38 except: 39 pass 40 try: 41 p = subprocess.check_output('stat -f -c %T /media/usb'+str(usbmount), shell=True) 42 filesystem = p.decode() 43 print('filesystem info: ' + filesystem) 44 except: 45 print('Oh-no! dont know your filesystem') 46 filmfolder = '/media/usb'+str(usbmount)+'/gonzopifilms/' 47 return filmfolder 48 else: 49 usbmount = usbmount + 1 50 if usbmount > 20: 51 break 52 53 home = os.path.expanduser('~') 54 menuold = [] 55 vumeterold = '' 56 #configfile = home + '/.gonzopi/config.ini' 57 #configdir = os.path.dirname(configfile) 58 #config = configparser.ConfigParser() 59 #if config.read(configfile): 60 # filmfolder = config['USER']['filmfolder']+'/' 61 filmfolder = '/home/pi/gonzopifilms/' 62 real_filmfolder=filmfolder 63 64 os.system("unlink static/*") 65 #CHECK IF FILMING TO USB STORAGE 66 filmfolderusb=usbfilmfolder() 67 if filmfolderusb: 68 filmfolder=filmfolderusb 69 real_filmfolder=filmfolder 70 # Link video directory to static dir 71 os.system("ln -s -t static/ " + filmfolder) 72 filmfolder='static/gonzopifilms/' 73 else: 74 os.system("ln -s -t static/ " + filmfolder) 75 filmfolder='static/gonzopifilms/' 76 #fix filmfolder root to Videos/gonzopifilms 77 78 basedir = os.path.dirname(os.path.realpath(__file__)) 79 sys.path.append(basedir) 80 81 films = [] 82 83 #NETWORKS 84 85 networks=[] 86 adapters = ifaddr.get_adapters() 87 for adapter in adapters: 88 print("IPs of network adapter " + adapter.nice_name) 89 for ip in adapter.ips: 90 if '::' not in ip.ip[0] and '127.0.0.1' != ip.ip: 91 print(ip.ip) 92 networks.append(ip.ip) 93 network=networks[0] 94 95 app = web.application(urls, globals()) 96 render = web.template.render('templates/', base="base") 97 render2 = web.template.render('templates/', base="base2") 98 web.config.debug=False 99 os.system('rm '+basedir+'/sessions/*') 100 store = web.session.DiskStore(basedir + '/sessions/') 101 session = web.session.Session(app,store,initializer={'login': 0, 'user': '', 'backurl': '', 'bildsida': 0, 'cameras': [], 'reload': 0, 'randhash':'', 'menu':[]}) 102 103 port=55555 104 ip='0.0.0.0' 105 cameras=[] 106 recording = False 107 108 session.randhash = hashlib.md5(str(random.getrandbits(256)).encode('utf-8')).hexdigest() 109 110 ##---------------Connection---------------------------------------------- 111 112 def pingtocamera(host, port, data): 113 #print("Sending to "+host+" on port "+str(port)+" DATA:"+data) 114 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 115 s.settimeout(0.01) 116 try: 117 while True: 118 s.connect((host, port)) 119 s.send(str.encode(data)) 120 if host not in cameras and host not in networks: 121 session.cameras.append(host) 122 print("Found camera! "+host) 123 print("Sent to server..") 124 break 125 except: 126 ('did not connect') 127 s.close() 128 129 def sendtocamera(host, port, data): 130 print("Sending to "+host+" on port "+str(port)+" DATA:"+data) 131 s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 132 s.settimeout(0.1) 133 try: 134 while True: 135 s.connect((host, port)) 136 s.send(str.encode(data)) 137 print("Sent to server..") 138 break 139 except: 140 ('did not connect') 141 s.close() 142 143 144 def getfilms(filmfolder): 145 #get a list of films, in order of settings.p file last modified 146 films_sorted = [] 147 #print(filmfolder) 148 films = next(os.walk(filmfolder))[1] 149 for i in films: 150 if os.path.isfile(filmfolder + i + '/settings.p') == True: 151 lastupdate = os.path.getmtime(filmfolder + i + '/' + 'settings.p') 152 films_sorted.append((i,lastupdate)) 153 films_sorted = sorted(films_sorted, key=lambda tup: tup[1], reverse=True) 154 #print(films_sorted) 155 return films_sorted 156 157 #------------Count scenes-------- 158 159 def countscenes(filmfolder, filmname): 160 scenes = 0 161 try: 162 allfiles = os.listdir(filmfolder + filmname) 163 except: 164 allfiles = [] 165 scenes = 0 166 for a in allfiles: 167 if 'scene' in a: 168 scenes = scenes + 1 169 return scenes 170 171 #------------Count shots-------- 172 173 def countshots(filmname, filmfolder, scene): 174 shots = 0 175 try: 176 allfiles = os.listdir(filmfolder + filmname + '/scene' + str(scene).zfill(3)) 177 except: 178 allfiles = [] 179 shots = 0 180 for a in allfiles: 181 if 'shot' in a: 182 shots = shots + 1 183 return shots 184 185 #------------Count takes-------- 186 187 def counttakes(filmname, filmfolder, scene, shot): 188 takes = 0 189 try: 190 allfiles = os.listdir(filmfolder + filmname + '/scene' + str(scene).zfill(3) + '/shot' + str(shot).zfill(3)) 191 except: 192 allfiles = [] 193 return takes 194 for a in allfiles: 195 if '.mp4' in a or '.h264' in a: 196 takes = takes + 1 197 return takes 198 199 def checkpicture(thumbdir,scene,shot,take): 200 if os.path.isfile(thumbdir) == False: 201 return "/"+filmfolder+name+"/scene"+str(scene).zfill(3)+"/shot"+str(shot).zfill(3)+"/picture"+str(take).zfill(3)+".jpeg" 202 else: 203 return '' 204 205 def if_exist(dir): 206 print(basedir+dir) 207 if os.path.isfile(basedir+dir) == False: 208 print('thumb not exist') 209 return False 210 else: 211 print('thumb is') 212 return True 213 214 def countsize(filename): 215 size = 0 216 if type(filename) is str: 217 size = os.stat(filename).st_size 218 else: 219 return 0 220 return size/1024 221 222 def checkvideo(video,filmfolder,film,scene,shot,take): 223 if take==None: 224 take=1 225 #print(basedir+video) 226 p = "/"+filmfolder+film+"/scene"+str(scene).zfill(3)+"/shot"+str(shot).zfill(3)+ "/picture"+str(take).zfill(3)+".jpeg" 227 #print(p) 228 v = '' 229 if video != '': 230 try: 231 if os.stat(basedir+video).st_size == 0: 232 v = '' 233 else: 234 v='video' 235 except: 236 v = '' 237 if os.path.isfile(basedir+p) == True: 238 return p, v 239 return '', v 240 241 def has_audio_track(file_path): 242 try: 243 # Parse the media file 244 media_info = MediaInfo.parse(file_path) 245 246 # Check for audio tracks 247 for track in media_info.tracks: 248 if track.track_type == "Audio": 249 return True 250 return False 251 252 except Exception as e: 253 print(f"Error parsing {file_path}: {e}") 254 return None 255 256 class intro: 257 def GET(self): 258 return render.intro() 259 260 class index: 261 def GET(self): 262 global recording 263 films = getfilms(filmfolder) 264 renderedfilms = [] 265 unrenderedfilms = [] 266 allfilms = [] 267 for f in films: 268 if os.path.isfile(filmfolder + f[0] + '/' + f[0] + '.mp4') == True: 269 renderedfilms.append(f[0]) 270 allfilms.append(f[0]) 271 else: 272 unrenderedfilms.append(f[0]) 273 allfilms.append(f[0]) 274 i=web.input(func=None,selected=None) 275 if i.selected != None: 276 sendtocamera(ip,port,'SELECTED:'+i.selected) 277 if i.func == 'search': 278 session.cameras=[] 279 # ping ip every 10 sec while not recording to connect cameras 280 pingip=0 281 while pingip < 255 : 282 pingip+=1 283 pingtocamera(network[:-3]+str(pingip),port,'PING') 284 elif i.func == 'record': 285 sendtocamera(ip,port,'RECORD') 286 elif i.func == 'retake': 287 print('retake') 288 elif i.func == 'up': 289 sendtocamera(ip,port,'UP') 290 elif i.func == 'down': 291 sendtocamera(ip,port,'DOWN') 292 elif i.func == 'left': 293 sendtocamera(ip,port,'LEFT') 294 elif i.func == 'right': 295 sendtocamera(ip,port,'RIGHT') 296 elif i.func == 'view': 297 sendtocamera(ip,port,'VIEW') 298 elif i.func == 'middle': 299 sendtocamera(ip,port,'MIDDLE') 300 elif i.func == 'delete': 301 sendtocamera(ip,port,'DELETE') 302 elif i.func == 'picture': 303 sendtocamera(ip,port,'PICTURE') 304 session.randhash = hashlib.md5(str(random.getrandbits(256)).encode('utf-8')).hexdigest() 305 session.reload = 1 306 elif i.func == 'camera0': 307 sendtocamera(ip,port,'CAMERA:0') 308 elif i.func == 'camera1': 309 sendtocamera(ip,port,'CAMERA:1') 310 elif i.func == 'camera2': 311 sendtocamera(ip,port,'CAMERA:2') 312 elif i.func == 'camera3': 313 sendtocamera(ip,port,'CAMERA:3') 314 elif i.func == 'camera4': 315 sendtocamera(ip,port,'CAMERA:4') 316 elif i.func == 'camera5': 317 sendtocamera(ip,port,'CAMERA:5') 318 elif i.func == 'camera6': 319 sendtocamera(ip,port,'CAMERA:6') 320 elif i.func == 'camera7': 321 sendtocamera(ip,port,'CAMERA:7') 322 elif i.func == 'camera8': 323 sendtocamera(ip,port,'CAMERA:8') 324 elif i.func == 'move': 325 sendtocamera(ip,port,'move') 326 elif i.func == 'copy': 327 sendtocamera(ip,port,'copy') 328 elif i.func == 'paste': 329 sendtocamera(ip,port,'paste') 330 interface=open('/dev/shm/interface','r') 331 vumeter=open('/dev/shm/vumeter','r') 332 menu=interface.readlines() 333 vumetermessage=vumeter.readlines()[0].rstrip('\n') 334 try: 335 selected=int(menu[0]) 336 except: 337 selected=0 338 try: 339 name=menu[3].split(':')[1] 340 name=name.rstrip('\n') 341 except: 342 name='' 343 try: 344 scene=menu[4].split(':')[1].split('/')[0] 345 except: 346 scene=1 347 try: 348 shot=menu[5].split(':')[1].split('/')[0] 349 except: 350 shot=1 351 try: 352 take=menu[6].split(':')[1].split('/')[0] 353 except: 354 take=1 355 session.reload = 0 356 if i.func == 'retake': 357 print(i.func) 358 if recording == False: 359 #sendtocamera(ip,port,'RETAKE:'+shot) 360 sendtocamera(ip,port,'RETAKE') 361 recording = True 362 else: 363 sendtocamera(ip,port,'STOPRETAKE') 364 recording = False 365 if i.func != None: 366 time.sleep(1) 367 session.reload = 1 368 raise web.seeother('/c/') 369 thumb="/"+filmfolder+name+"/scene"+str(scene).zfill(3)+"/shot"+str(shot).zfill(3)+"/picture"+str(take).zfill(3)+".jpeg" 370 #print(thumb) 371 if os.path.isfile(basedir+thumb) == False: 372 print(basedir+thumb) 373 thumb='' 374 return render.index(allfilms, session.cameras, menu, selected,name,scene,shot,take,str,session.randhash,thumb,vumetermessage,i.func,filmfolder) 375 376 class films: 377 def GET(self, film): 378 shots = 0 379 takes = 0 380 gonzopifilms = getfilms(filmfolder) 381 renderedfilms = [] 382 unrenderedfilms = [] 383 allfilms = [] 384 for f in gonzopifilms: 385 if os.path.isfile(filmfolder + f[0] + '/' + f[0] + '.mp4') == True: 386 renderedfilms.append(f[0]) 387 allfilms.append(f[0]) 388 else: 389 unrenderedfilms.append(f[0]) 390 allfilms.append(f[0]) 391 i = web.input(page=None, scene=None, shot=None, take=None, film=None, randhash=None) 392 if i.scene != None: 393 shots = countshots(film, filmfolder, i.scene) 394 takes = counttakes(film, filmfolder, i.scene, i.shot) 395 if i.scene != None and i.shot != None: 396 shots = countshots(film, filmfolder, i.scene) 397 if i.randhash == None: 398 randhash = hashlib.md5(str(random.getrandbits(256)).encode('utf-8')).hexdigest() 399 scenes = countscenes(filmfolder, film) 400 return render.filmpage(allfilms, film, scenes, str, filmfolder, counttakes, countshots, shots, i.scene, takes, i.shot, i.take, checkvideo, randhash) 401 402 class tree: 403 def GET(self, film): 404 shots = 0 405 takes = 0 406 gonzopifilms = getfilms(filmfolder) 407 renderedfilms = [] 408 unrenderedfilms = [] 409 allfilms = [] 410 for f in gonzopifilms: 411 if os.path.isfile(filmfolder + f[0] + '/' + f[0] + '.mp4') == True: 412 renderedfilms.append(f[0]) 413 allfilms.append(f[0]) 414 else: 415 unrenderedfilms.append(f[0]) 416 allfilms.append(f[0]) 417 i = web.input(page=None, scene=None, shot=None, take=None, film=None, randhash=None) 418 if i.scene != None: 419 shots = countshots(film, filmfolder, i.scene) 420 takes = counttakes(film, filmfolder, i.scene, i.shot) 421 if i.scene != None and i.shot != None: 422 shots = countshots(film, filmfolder, i.scene) 423 if i.randhash == None: 424 randhash = hashlib.md5(str(random.getrandbits(256)).encode('utf-8')).hexdigest() 425 scenes = countscenes(filmfolder, film) 426 return render2.tree(allfilms, film, scenes, str, filmfolder, counttakes, countshots, countscenes, shots, i.scene, takes, i.shot, i.take, checkvideo, randhash, if_exist) 427 428 class player: 429 def GET(self, film): 430 i=web.input(scene=None,shot=None,take=None) 431 randhash = hashlib.md5(str(random.getrandbits(256)).encode('utf-8')).hexdigest() 432 return render.player(real_filmfolder,filmfolder,film,i.scene,i.shot,i.take,str,randhash,has_audio_track) 433 434 class api: 435 def GET(self): 436 global menuold, vumeterold 437 i=web.input(func=None,selected=None) 438 if i.func == 'record': 439 sendtocamera(ip,port,'RECORD') 440 elif i.func == 'retake': 441 sendtocamera(ip,port,'RETAKE') 442 elif i.func == 'up': 443 sendtocamera(ip,port,'UP') 444 elif i.func == 'down': 445 sendtocamera(ip,port,'DOWN') 446 elif i.func == 'left': 447 sendtocamera(ip,port,'LEFT') 448 elif i.func == 'right': 449 sendtocamera(ip,port,'RIGHT') 450 elif i.func == 'view': 451 sendtocamera(ip,port,'VIEW') 452 elif i.func == 'middle': 453 sendtocamera(ip,port,'MIDDLE') 454 elif i.func == 'delete': 455 sendtocamera(ip,port,'DELETE') 456 elif i.func == 'picture': 457 sendtocamera(ip,port,'PICTURE') 458 elif i.func == 'camera0': 459 sendtocamera(ip,port,'CAMERA:0') 460 elif i.func == 'camera1': 461 sendtocamera(ip,port,'CAMERA:1') 462 elif i.func == 'camera2': 463 sendtocamera(ip,port,'CAMERA:2') 464 elif i.func == 'camera3': 465 sendtocamera(ip,port,'CAMERA:3') 466 elif i.func == 'camera4': 467 sendtocamera(ip,port,'CAMERA:4') 468 elif i.func == 'camera5': 469 sendtocamera(ip,port,'CAMERA:5') 470 elif i.func == 'camera6': 471 sendtocamera(ip,port,'CAMERA:6') 472 elif i.func == 'camera7': 473 sendtocamera(ip,port,'CAMERA:7') 474 elif i.func == 'camera8': 475 sendtocamera(ip,port,'CAMERA:8') 476 elif i.func == 'move': 477 sendtocamera(ip,port,'move') 478 elif i.func == 'copy': 479 sendtocamera(ip,port,'copy') 480 elif i.func == 'paste': 481 sendtocamera(ip,port,'paste') 482 interface=open('/dev/shm/interface','r') 483 menu=interface.readlines() 484 vumeter=open('/dev/shm/vumeter','r') 485 vumetermessage=vumeter.readlines()[0].rstrip('\n') 486 if menu != menuold or vumetermessage != vumeterold: 487 menuold=menu 488 vumeterold=vumetermessage 489 #print(menu) 490 menudone='' 491 p=0 492 film=None 493 selectfilm=False 494 if menu != '': 495 scene=1 496 shot=1 497 take=1 498 for i in menu: 499 if p == 0: 500 selected=int(i)+3 501 if p > 1: 502 if selected == p: 503 #menudone=menudone+'<b> '+i.rstrip('\n')+' </b> | ' 504 menudone=menudone+'<ka style="text-decoration:none; font-size:20px;" color:fff;" href="">'+i+'</ka>' 505 else: 506 #menudone=menudone+i.rstrip('\n')+' | ' 507 menudone=menudone+'<a style="text-decoration:none; font-size:20px;" href="?selected='+str(p-3)+'"> '+i+' </a>' 508 #if p == 7: 509 # menudone=menudone+'<br>' 510 #if p == 13: 511 # menudone=menudone+'<br>' 512 #if p == 21: 513 # menudone=menudone+'<br>' 514 #if p == 30: 515 # menudone=menudone+'<br>' 516 if p == 2 and i.rstrip('\n') == 'Up and down to select and load film': 517 selectfilm=True 518 if p == 3 and selectfilm==True: 519 try: 520 film=i.split(':')[1].rstrip('\n') 521 except: 522 film=None 523 if p == 4 and selectfilm == False: 524 try: 525 film=i.split(':')[1].rstrip('\n') 526 except: 527 film=None 528 if p == 5 and film != None: 529 try: 530 scene=int(i.split(':')[1].split('/')[0]) 531 except: 532 scene=1 533 if p == 6 and film != None: 534 try: 535 shot=int(i.split(':')[1].split('/')[0]) 536 except: 537 shot=1 538 if p == 7 and film != None: 539 try: 540 take=int(i.split(':')[1].split('/')[0]) 541 except: 542 take=1 543 if p > 0 and selected == 423: 544 menudone=menudone+'<ka style="text-decoration:none; font-size:20px;" color:fff;" href="">'+i+'</ka>' 545 #if p > 2 and film == None: 546 #menudone=menudone+'<ka style="text-decoration:none; font-size:20px;" color:fff;" href="">'+i+'</ka>' 547 p = p + 1 548 thumb = '' 549 video = '' 550 if film != None: 551 if selected == 0: 552 video = '/p/'+film 553 menudone+=menudone+'video' 554 if selected == 4: 555 video = '/p/'+film 556 elif selected == 5: 557 video = '/p/'+film+'?scene=' + str(scene) 558 elif selected == 6: 559 video = '/p/'+film+'?scene='+str(scene)+'&shot='+str(shot)+'&take='+str(take) 560 elif selected == 7: 561 video = '/p/'+film+'?scene='+str(scene)+'&shot='+str(shot)+'&take='+str(take) 562 else: 563 video = '/p/'+film+'?scene='+str(scene)+'&shot='+str(shot)+'&take='+str(take) 564 thumb = '/'+filmfolder + film + "/scene" + str(scene).zfill(3) + "/shot" + str(shot).zfill(3) + "/take" + str(take).zfill(3) + ".jpeg" 565 if os.path.isfile(basedir+thumb) == True: 566 randhashimg = '?'+hashlib.md5(str(random.getrandbits(256)).encode('utf-8')).hexdigest() 567 writemenu=menudone+'<br><br>'+vumetermessage+'<br><a href="'+video+'"><img src="'+thumb+randhashimg+'"></a>' 568 #writemenu=menudone+render.player(filmfolder,film,scene,shot,take,str) 569 else: 570 writemenu=menudone+'<br><br>'+vumetermessage+'<br>' 571 f = open(basedir+'/static/menu.html', 'w') 572 f.write(writemenu) 573 f.close() 574 575 application = app.wsgifunc() 576