# # Pages related to showing the media on the home server # import sys import os.path import logging import time import asyncio import subprocess import ezt from easydict import EasyDict as edict import quart import util import workqueue APP = sys.modules['__main__'].APP LOGGER = logging.getLogger(__name__) PAGINATION_SIZE = 10 # This is a disabled "..." to display in the pagination bar. NAV_OMITTED_JUMPS = edict(idx=None, name='...', status='disabled') @APP.route('/media') @APP.use_template('templates/media.ezt') async def media(): # Which page are we on? try: idx = int(quart.request.args.get('idx', 0)) except ValueError: idx = 0 ### some pseudo-random data (but stable), for now import random random.seed(0) dvds = [ ] for root_idx, root in enumerate(APP.dvdroots): for d in root.dvds.values(): ### yellow warning if directory does not have explicit LIB? dvds.append(edict(name=d.name, root_idx=root_idx, path=d.dvddir, relpath=os.path.relpath(d.dvddir, root.rootdir), libs=sorted(d.libs), streams=sorted(d.streams), offloaded=ezt.boolean(random.choice((False, True))), tssize=random.choice((None, '1M', '5G')), #d.tssize, )) dvds.sort(key=lambda o: (o.name.lower(), o.root_idx)) pages = [ ] for i in range(len(dvds) // PAGINATION_SIZE + 1): start = i * PAGINATION_SIZE end = min((i + 1) * PAGINATION_SIZE, len(dvds)) - 1 name = f'{dvds[start].name[:3].upper()}..{dvds[end].name[:3].upper()}' pages.append(edict(idx=i, name=name, status=("active" if i == idx else None), )) last_idx = len(pages) - 1 # Display (at most) 7 jumps, plus First and Last. if len(pages) > 7: if idx < 3: # Show first six jumps and "..." for seventh. del pages[6:] pages.append(NAV_OMITTED_JUMPS) elif idx >= len(pages) - 3: # Show "..." plus last six jumps. del pages[:-6] pages.insert(0, NAV_OMITTED_JUMPS) else: # Show "...", five jumps, and "..." for sevenths. del pages[idx+3:] del pages[:idx-2] pages.insert(0, NAV_OMITTED_JUMPS) pages.append(NAV_OMITTED_JUMPS) pages.insert(0, edict(idx=0, name='First', status=('disabled' if idx == 0 else None), )) pages.append(edict(idx=last_idx, name='Last', status=('disabled' if idx == last_idx else None), )) # Display subset of the DVDs. start = idx * PAGINATION_SIZE end = (idx+1) * PAGINATION_SIZE data = edict( message='message goes here', user='gstein', title='Media Management', leftnav=util.build_active_leftnav('media'), dvds=dvds[start:end], count=len(dvds), pages=pages, idx=idx, last=last_idx, ) # rip progress. status. top navbar. return data @APP.route('/copytray') async def endpoint_copytray(): # Copy the disc sitting in the tray. async def perform_copytray(): proc = await asyncio.create_subprocess_exec( APP.cfg.copytray_cmd, # no args stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, ) out, err = await proc.communicate() print('OUT:', out) print('ERR:', err) ### check proc.statuscode wtask = workqueue.WorkItem('tray', perform_copytray(), f'copying disc in tray') await APP.wq.add_io_task(wtask) # This endpoint is a "ping" to start work, with no content to return. return '', 204 @APP.route('/ripdvd//') async def endpoint_ripdvd(root_idx, name): # Rip the "main" feature of a DVD to a stream. async def perform_rip(): ### call via executor ### result = await exec await asyncio.sleep(15) key = f'{root_idx}/{name}' wtask = workqueue.WorkItem(key, perform_rip(), f'ripping {key}') await APP.wq.add_io_task(wtask) ### typically, this endpoint is called from the UI. We should set ### a flash, and redirect back to the Referrer. return f'Rip command queued for {key}.'