#!/usr/bin/python3 import magic,os,pickle,re,subprocess basedir = '/home/pi/kiosk' remote = 'Kiosks:Kiosks/Testing' statusfile = os.path.join(basedir, 'state/statusfile') contentdir = os.path.join(basedir, 'content') slidedir = os.path.join(basedir, 'slides') tmpdir = os.path.join(basedir, 'tmp') synccommand = ['/usr/bin/rclone', 'sync', remote, contentdir] # File formats that "feh" can display directly with no processing directformats = [ 'JPEG image', 'PNG image', 'GIF image', 'Netpbm image', ] # Empty the temporary working directory def cleantmp(): try: tmpfiles = os.listdir(tmpdir) for f in tmpfiles: fpath = os.path.join(tmpdir, f) os.unlink(fpath) except: pass # Copy a file into the temporary directory def tmpcopy(filename): srcpath = os.path.join(contentdir, filename) dstpath = os.path.join(tmpdir, filename) subprocess.call(['/bin/cp', '-p', '-f', srcpath, dstpath]) # Move PNG files from temporary to slide directory # Returns a list of moved files, and cleans the temporary directory def tmpmove(moveall): tmpfiles = os.listdir(tmpdir) tmpfiles.sort() filelist = [] for f in tmpfiles: srcpath = os.path.join(tmpdir, f) if moveall or (f[-4:] == '.png'): dstpath = os.path.join(slidedir, f) subprocess.call(['/bin/mv', '-f', srcpath, dstpath]) filelist += [f] else: os.unlink(srcpath) return(filelist) # Synchronize with cloud storage subprocess.call(synccommand) # Set up to read magic numbers and guess file types ms = magic.open(magic.NONE) ms.load() # Empty temporary directory cleantmp() # Read previous file status, if it exists try: stf = open(statusfile, 'rb') filestatus = pickle.load(stf) stf.close() except: filestatus = {} # Get list of content files files = os.listdir(contentdir) files.sort() # Slide files to preserve keepcontent = {} keepslides = {} # Examine all content files for f in files: filepath = os.path.join(contentdir, f) sb = os.stat(filepath) filetype = ms.file(filepath) processfile = True if f in filestatus: # Status record exists # Check size and modification time thisstatus = filestatus[f] if (thisstatus['s'] == sb.st_size) and (thisstatus['m'] == sb.st_mtime) and (thisstatus['t'] == filetype): # exact match, do not need to process this file print('exact', f) processfile = False # mark resulting slide files to save them for i in thisstatus['f']: keepslides[i] = True else: # something has changed print('changed', f) thisstatus['s'] = sb.st_size thisstatus['m'] = sb.st_mtime thisstatus['t'] = filetype else: # new file, no status record yet, so make one print('new', f) filestatus[f] = {} filestatus[f]['s'] = sb.st_size filestatus[f]['m'] = sb.st_mtime filestatus[f]['t'] = filetype # Active file, save status record keepcontent[f] = True # if this content file needs to be made into slide file(s) if processfile: # Figure out some useful paths tmppath = os.path.join(tmpdir, f) destpath = os.path.join(slidedir, f) direct = False for d in directformats: if d in filetype: direct = True if direct: # files that can be displayed directly just need to be copied into place print('direct', filepath) tmpcopy(f) subprocess.call(['/bin/cp', '-p', '-f', filepath, destpath]) # keepslides[f] = True elif 'PDF document' in filetype: tmpcopy(f) subprocess.call(['/home/pi/kiosk/bin/file-pdf']) elif 'PostScript document' in filetype: tmpcopy(f) subprocess.call(['/home/pi/kiosk/bin/file-ps']) elif 'PowerPoint' in filetype or 'Microsoft Word' in filetype or 'Zip archive data' in filetype: tmpcopy(f) subprocess.call(['/home/pi/kiosk/bin/file-office']) elif 'ASCII text' in filetype: tmpcopy(f) subprocess.call(['/home/pi/kiosk/bin/file-text']) else: print('unknown', filepath) print(filetype) filelist = tmpmove(direct) filestatus[f]['f'] = filelist for i in filelist: keepslides[i] = True # final cleanup, delete obsolete slides # Get list of slide files files = os.listdir(slidedir) files.sort() for f in files: if f not in keepslides: os.unlink(os.path.join(slidedir, f)) print('unlink slide', f) # Delete status records for obsolete content deletekeys = [] for s in filestatus.keys(): if s not in keepcontent: deletekeys += [s] for s in deletekeys: del filestatus[s] print('delete status', s) # Write new status file stf = open(statusfile, 'wb') pickle.dump(filestatus, stf) stf.close()