gonzopi

git clone https://git.tarina.org/gonzopi
Log | Files | Refs | README | LICENSE

gonzopiserver.py (18953B)


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