sintonia/python_apps/media-monitor2/media/monitor/organizer.py

92 lines
3.8 KiB
Python

# -*- coding: utf-8 -*-
import media.monitor.pure as mmp
import media.monitor.owners as owners
from media.monitor.handler import ReportHandler
from media.monitor.log import Loggable
from media.monitor.exceptions import BadSongFile
from media.monitor.events import OrganizeFile
from pydispatch import dispatcher
from os.path import dirname
import os.path
class Organizer(ReportHandler,Loggable):
"""
Organizer is responsible to to listening to OrganizeListener events
and committing the appropriate changes to the filesystem. It does
not in any interact with WatchSyncer's even when the the WatchSyncer
is a "storage directory". The "storage" directory picks up all of
its events through pyinotify. (These events are fed to it through
StoreWatchListener)
"""
# Commented out making this class a singleton because it's just a band aid
# for the real issue. The real issue being making multiple Organizer
# instances with pydispatch
#_instance = None
#def __new__(cls, channel, target_path, recorded_path):
#if cls._instance:
#cls._instance.channel = channel
#cls._instance.target_path = target_path
#cls._instance.recorded_path = recorded_path
#else:
#cls._instance = super(Organizer, cls).__new__( cls, channel,
#target_path, recorded_path)
#return cls._instance
def __init__(self, channel, target_path, recorded_path):
self.channel = channel
self.target_path = target_path
self.recorded_path = recorded_path
super(Organizer, self).__init__(signal=self.channel, weak=False)
def handle(self, sender, event):
"""
Intercept events where a new file has been added to the organize
directory and place it in the correct path (starting with
self.target_path)
"""
# Only handle this event type
assert isinstance(event, OrganizeFile), \
"Organizer can only handle OrganizeFile events.Given '%s'" % event
try:
# We must select the target_path based on whether file was recorded
# by airtime or not.
# Do we need to "massage" the path using mmp.organized_path?
target_path = self.recorded_path if event.metadata.is_recorded() \
else self.target_path
# nasty hack do this properly
owner_id = mmp.owner_id(event.path)
if owner_id != -1:
target_path = os.path.join(target_path, unicode(owner_id))
mdata = event.metadata.extract()
new_path = mmp.organized_path(event.path, target_path, mdata)
# See hack in mmp.magic_move
def new_dir_watch(d):
def cb():
dispatcher.send(signal="add_subwatch", sender=self,
directory=d)
return cb
mmp.magic_move(event.path, new_path,
after_dir_make=new_dir_watch(dirname(new_path)))
# The reason we need to go around saving the owner in this ass
# backwards way is bewcause we are unable to encode the owner id
# into the file itself so that the StoreWatchListener listener can
# detect it from the file
owners.add_file_owner(new_path, owner_id )
self.logger.info('Organized: "%s" into "%s"' %
(event.path, new_path))
except BadSongFile as e:
self.report_problem_file(event=event, exception=e)
# probably general error in mmp.magic.move...
except Exception as e:
self.unexpected_exception( e )
self.report_problem_file(event=event, exception=e)