media-sucker/src/reader.py

117 lines
3.0 KiB
Python
Raw Normal View History

2022-02-26 08:05:20 -07:00
#! /usr/bin/python3
import os
import subprocess
import time
import re
import fcntl
2022-08-21 15:58:11 -06:00
import json
2022-08-20 16:42:53 -06:00
import logging
2022-08-25 10:17:25 -06:00
import slugify
2022-08-21 15:58:11 -06:00
import dvd
2022-08-23 22:06:44 -06:00
import cd
2022-08-25 10:17:25 -06:00
import worker
2022-02-26 08:05:20 -07:00
CDROM_DRIVE_STATUS = 0x5326
CDS_NO_INFO = 0
CDS_NO_DISC = 1
CDS_TRAY_OPEN = 2
2022-08-20 16:42:53 -06:00
CDS_DRIVE_NOT_READ = 3
2022-02-26 08:05:20 -07:00
CDS_DISC_OK = 4
CDS_STR = ["no info", "no disc", "tray open", "drive not read", "disc ok"]
CDROM_DISC_STATUS = 0x5327
CDS_AUDIO = 100
CDS_DATA_1 = 101
CDS_DATA_2 = 102
CDROM_LOCKDOOR = 0x5329
CDROM_EJECT = 0x5309
2022-09-02 17:04:07 -06:00
SECOND = 1
MINUTE = 60 * SECOND
HOUR = 60 * MINUTE
2022-08-25 10:17:25 -06:00
class Reader(worker.Worker):
def __init__(self, device, directory):
2022-08-25 10:17:25 -06:00
super().__init__(directory)
2022-02-26 08:05:20 -07:00
self.device = device
2022-08-20 16:42:53 -06:00
self.staleness = 0
self.drive = None
logging.info("Starting reader on %s" % self.device)
2022-02-26 08:05:20 -07:00
2022-08-20 16:42:53 -06:00
def reopen(self):
2022-09-02 17:04:07 -06:00
if self.drive and (self.staleness < 15):
2022-08-20 16:42:53 -06:00
self.staleness += 1
2022-09-02 17:04:07 -06:00
return True
self.staleness = 0
if self.drive:
os.close(self.drive)
self.drive = None
try:
self.drive = os.open(self.device, os.O_RDONLY | os.O_NONBLOCK)
logging.debug("Reopened %s" % self.device)
return True
except FileNotFoundError:
return False
2022-08-20 16:42:53 -06:00
2022-09-02 17:04:07 -06:00
def once(self):
self.status["type"] = "reader"
self.status["device"] = self.device
if not self.reopen():
time.sleep(10 * SECOND)
return
rv = fcntl.ioctl(self.drive, CDROM_DRIVE_STATUS)
if rv == CDS_DISC_OK:
rv = fcntl.ioctl(self.drive, CDROM_DISC_STATUS)
if rv == CDS_AUDIO:
self.handle(False)
elif rv in [CDS_DATA_1, CDS_DATA_2]:
self.handle(True)
2022-02-26 08:05:20 -07:00
else:
2022-09-02 17:04:07 -06:00
logging.info("Can't handle disc type %d" % rv)
self.eject()
elif rv in (CDS_TRAY_OPEN, CDS_NO_DISC, CDS_DRIVE_NOT_READ):
time.sleep(3 * SECOND)
else:
logging.info("CDROM_DRIVE_STATUS: %d (%s)" % (rv, CDS_STR[rv]))
time.sleep(3 * SECOND)
2022-02-26 08:05:20 -07:00
def eject(self):
for i in range(20):
try:
fcntl.ioctl(self.drive, CDROM_LOCKDOOR, 0)
fcntl.ioctl(self.drive, CDROM_EJECT)
return
except Exception as e:
2022-08-20 16:42:53 -06:00
logging.error("Ejecting: %v" % e)
2022-02-26 08:05:20 -07:00
time.sleep(i * 5)
2022-08-25 10:17:25 -06:00
def handle(self, video):
2022-11-06 10:34:43 -07:00
logging.info("Handling media, video=%r" % video)
2022-08-25 10:17:25 -06:00
self.status["video"] = video
self.status["state"] = "reading"
2022-02-26 08:05:20 -07:00
2022-08-25 10:17:25 -06:00
state = {}
state["video"] = video
if video:
media = dvd
2022-08-25 10:17:25 -06:00
else:
media = cd
2022-08-23 22:06:44 -06:00
2022-08-25 10:17:25 -06:00
media.scan(state, self.device)
self.status["title"] = state["title"]
subdir = slugify.slugify(state["title"])
2022-08-25 10:17:25 -06:00
workdir = self.workdir(subdir)
os.makedirs(workdir, exist_ok=True)
2022-08-23 22:06:44 -06:00
self.status["state"] = "copying"
2022-08-25 10:17:25 -06:00
for pct in media.copy(state, self.device, workdir):
2022-08-25 10:17:25 -06:00
self.status["complete"] = pct
2022-08-23 22:06:44 -06:00
2022-08-25 10:17:25 -06:00
self.write_state(subdir, state)
2022-02-26 08:05:20 -07:00
# vi: sw=4 ts=4 et ai