|
|
|
import os
|
|
|
|
|
|
|
|
from bureau import Bureau, add_command
|
|
|
|
import pyudev
|
|
|
|
|
|
|
|
AUDIO_FILETYPES = (".mp3", ".ogg", ".oga", ".flac", ".spx", ".opus", ".wav",
|
|
|
|
".aac", ".mka", ".m4a")
|
|
|
|
PICTURE_FILETYPES = (".jpg", ".jpeg", ".png", ".gif", ".tif", ".bmp")
|
|
|
|
PDF_FILETYPES = (".pdf", ".djvu", ".djv", ".ps", ".eps")
|
|
|
|
|
|
|
|
class Archives(Bureau):
|
|
|
|
"""
|
|
|
|
The Archives is the central library resource for the storage and retreival
|
|
|
|
of persistent data files. Audio, graphic and textual documents may be
|
|
|
|
managed for the use of any other bureau.
|
|
|
|
"""
|
|
|
|
|
|
|
|
name = "Central Archives"
|
|
|
|
prefix = "AR"
|
|
|
|
version = 0
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
Bureau.__init__(self)
|
|
|
|
|
|
|
|
# TODO: get location of archive root storage from config
|
|
|
|
self.mounts = {}
|
|
|
|
|
|
|
|
# create a db to map shortcodes to folders on external drives
|
|
|
|
self.dirmap = self.open_db("dirmap")
|
|
|
|
|
|
|
|
def __scandir(self, dir_to_scan):
|
|
|
|
"""
|
|
|
|
recursive directory scan
|
|
|
|
returns a tuple of lists of directory paths if any interesting media
|
|
|
|
are found
|
|
|
|
([dirs_with_audio], [dirs_with_pictures], [dirs_with_pdfs])
|
|
|
|
"""
|
|
|
|
dirs_with_audio = []
|
|
|
|
dirs_with_pictures = []
|
|
|
|
dirs_with_pdfs = []
|
|
|
|
for root, dirs, files in os.walk(dir_to_scan):
|
|
|
|
audio_found = False
|
|
|
|
pic_found = False
|
|
|
|
pdf_found = False
|
|
|
|
for file in files:
|
|
|
|
_, file_ext = os.path.splitext(file)
|
|
|
|
file_ext = file_ext.lower()
|
|
|
|
if file_ext in AUDIO_FILETYPES:
|
|
|
|
audio_found = True
|
|
|
|
elif file_ext in PICTURE_FILETYPES:
|
|
|
|
pic_found = True
|
|
|
|
elif file_ext in PDF_FILETYPES:
|
|
|
|
pdf_found = True
|
|
|
|
if audio_found:
|
|
|
|
dirs_with_audio.append(root)
|
|
|
|
if pic_found:
|
|
|
|
dirs_with_pictures.append(root)
|
|
|
|
if pdf_found:
|
|
|
|
dirs_with_pdfs.append(root)
|
|
|
|
return dirs_with_audio, dirs_with_pictures, dirs_with_pdfs
|
|
|
|
|
|
|
|
def _mount_and_archive(self, dev):
|
|
|
|
# TODO: small print options to import stuff
|
|
|
|
_, dev_base = os.path.split(dev)
|
|
|
|
mountpoint = os.path.join("/media", dev_base)
|
|
|
|
print("MOUNTING EXTERNAL MEDIUM: ", dev, "on", mountpoint)
|
|
|
|
if len(self.mounts) < 26:
|
|
|
|
mount_index = chr(65 + len(self.mounts))
|
|
|
|
else:
|
|
|
|
print("WTF!? You have over 26 drives plugged in you wierdo. No more!")
|
|
|
|
#TODO: handle this properly and make sure we don't overlap indices
|
|
|
|
|
|
|
|
# pmount dev
|
|
|
|
# path is always /media/device
|
|
|
|
os.system("pmount " + str(dev))
|
|
|
|
self.mounts[mount_index] = {"dev": dev, "mount": mountpoint, "dirs": []}
|
|
|
|
prn = self._get_small_printer()
|
|
|
|
prn.textln("Achive has found external medium: ")
|
|
|
|
prn.textln(mountpoint)
|
|
|
|
prn.textln("EJECT DRIVE:")
|
|
|
|
prn.soft_barcode("code128", "ARej." + mount_index, module_width=0.16)
|
|
|
|
|
|
|
|
audio_dirs, pic_dirs, pdf_dirs = self.__scandir(mountpoint)
|
|
|
|
|
|
|
|
# small_print list of media/directories that we can import
|
|
|
|
# TODO: make short codes for each dir
|
|
|
|
# TODO: make command that will import the dir
|
|
|
|
for adir in audio_dirs:
|
|
|
|
print("could add audio DIR", adir)
|
|
|
|
prn.textln("Import Audio Folder:")
|
|
|
|
prn.textln(adir)
|
|
|
|
shortcode = self.dirmap.store_and_get_shortcode(adir)
|
|
|
|
prn.soft_barcode("code128", "ARia." + shortcode, module_width=0.16)
|
|
|
|
self.mounts[mount_index]["dirs"].append(shortcode)
|
|
|
|
|
|
|
|
for pdir in pic_dirs:
|
|
|
|
print("could add picture DIR", pdir)
|
|
|
|
prn.textln("Import Image Folder:")
|
|
|
|
prn.textln(pdir)
|
|
|
|
shortcode = self.dirmap.store_and_get_shortcode(pdir)
|
|
|
|
prn.soft_barcode("code128", "ARii." + shortcode, module_width=0.16)
|
|
|
|
self.mounts[mount_index]["dirs"].append(shortcode)
|
|
|
|
|
|
|
|
for pdir in pdf_dirs:
|
|
|
|
print("could add document DIR", pdir)
|
|
|
|
prn.textln("Import Document Folder:")
|
|
|
|
prn.textln(pdir)
|
|
|
|
shortcode = self.dirmap.store_and_get_shortcode(pdir)
|
|
|
|
prn.soft_barcode("code128", "ARip." + shortcode, module_width=0.16)
|
|
|
|
self.mounts[mount_index]["dirs"].append(shortcode)
|
|
|
|
|
|
|
|
self._free_small_printer(prn)
|
|
|
|
|
|
|
|
@add_command("ej", "Eject Drive")
|
|
|
|
def unmount_device(self, data):
|
|
|
|
"""
|
|
|
|
Safely eject external media like USB Flash Drives or SD Cards
|
|
|
|
"""
|
|
|
|
device_idx, _ = data.split(".")
|
|
|
|
dev = self.mounts[device_idx]["dev"]
|
|
|
|
os.system("pumount " + str(dev))
|
|
|
|
# clean up the references
|
|
|
|
for shortcode in self.mounts[device_idx]["dirs"]:
|
|
|
|
self.dirmap.delete(shortcode)
|
|
|
|
del(mounts[device_idx])
|
|
|
|
|
|
|
|
@add_command("ia", "Import Audio Folder")
|
|
|
|
def import_audio(self, data):
|
|
|
|
"""
|
|
|
|
Import audio files from external media into the
|
|
|
|
"""
|
|
|
|
shortcode, _ = data.split(".")
|
|
|
|
indir = self.dirmap.get(shortcode)
|
|
|
|
print("Importing audio:", indir)
|
|
|
|
print("NOT IMPLEMENTED YET")
|
|
|
|
|
|
|
|
def run_io(self):
|
|
|
|
# monitor for insert of any removable block storage devices (SD/USB)
|
|
|
|
context = pyudev.Context()
|
|
|
|
monitor = pyudev.Monitor.from_netlink(context)
|
|
|
|
monitor.filter_by('block')
|
|
|
|
for device in iter(monitor.poll, None):
|
|
|
|
if ('ID_FS_TYPE' in device) and (device.action == "add"):
|
|
|
|
self._mount_and_archive(device.device_node)
|
|
|
|
|
|
|
|
|
|
|
|
def main():
|
|
|
|
ar = Archives()
|
|
|
|
ar.run()
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|