Skip to content
Snippets Groups Projects
run 4.58 KiB
#!/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()