diff --git a/python_apps/media-monitor/airtimefilemonitor/airtimemediamonitorbootstrap.py b/python_apps/media-monitor/airtimefilemonitor/airtimemediamonitorbootstrap.py index 998446596..fca41e8b6 100644 --- a/python_apps/media-monitor/airtimefilemonitor/airtimemediamonitorbootstrap.py +++ b/python_apps/media-monitor/airtimefilemonitor/airtimemediamonitorbootstrap.py @@ -5,11 +5,8 @@ import time import pyinotify import shutil -from subprocess import Popen, PIPE -from api_clients import api_client - class AirtimeMediaMonitorBootstrap(): - + """AirtimeMediaMonitorBootstrap constructor Keyword Arguments: @@ -29,11 +26,11 @@ class AirtimeMediaMonitorBootstrap(): self.curr_mtab_file = "/var/tmp/airtime/media-monitor/currMtab" self.logger.info("Adding %s on watch list...", self.mount_file) self.wm.add_watch(self.mount_file, pyinotify.ALL_EVENTS, rec=False, auto_add=False) - + tmp_dir = os.path.dirname(self.curr_mtab_file) if not os.path.exists(tmp_dir): os.makedirs(tmp_dir) - + # create currMtab file if it's the first time if not os.path.exists(self.curr_mtab_file): shutil.copy('/etc/mtab', self.curr_mtab_file) @@ -77,10 +74,10 @@ class AirtimeMediaMonitorBootstrap(): dir -- pathname of the directory """ def sync_database_to_filesystem(self, dir_id, dir): - - dir = os.path.normpath(dir)+"/" - - + + dir = os.path.normpath(dir) + "/" + + """ set to hold new and/or modified files. We use a set to make it ok if files are added twice. This is because some of the tests for new files return result sets that are not @@ -109,13 +106,13 @@ class AirtimeMediaMonitorBootstrap(): if os.path.exists(self.mmc.timestamp_file): """find files that have been modified since the last time media-monitor process started.""" time_diff_sec = time.time() - os.path.getmtime(self.mmc.timestamp_file) - command = "find '%s' -iname '*.ogg' -o -iname '*.mp3' -type f -readable -mmin -%d" % (dir, time_diff_sec/60+1) + command = "find '%s' -iname '*.ogg' -o -iname '*.mp3' -type f -readable -mmin -%d" % (dir, time_diff_sec / 60 + 1) else: command = "find '%s' -iname '*.ogg' -o -iname '*.mp3' -type f -readable" % dir self.logger.debug(command) stdout = self.mmc.exec_command(command) - + if stdout is None: self.logger.error("Unrecoverable error when syncing db to filesystem.") return diff --git a/python_apps/media-monitor/airtimefilemonitor/airtimemetadata.py b/python_apps/media-monitor/airtimefilemonitor/airtimemetadata.py index e7b6ad01d..8a4c3e3ea 100644 --- a/python_apps/media-monitor/airtimefilemonitor/airtimemetadata.py +++ b/python_apps/media-monitor/airtimefilemonitor/airtimemetadata.py @@ -1,13 +1,14 @@ # -*- coding: utf-8 -*- +import replay_gain + import os import hashlib import mutagen import logging import math -import re import traceback -from api_clients import api_client + """ list of supported easy tags in mutagen version 1.20 @@ -18,39 +19,39 @@ class AirtimeMetadata: def __init__(self): self.airtime2mutagen = {\ - "MDATA_KEY_TITLE": "title",\ - "MDATA_KEY_CREATOR": "artist",\ - "MDATA_KEY_SOURCE": "album",\ - "MDATA_KEY_GENRE": "genre",\ - "MDATA_KEY_MOOD": "mood",\ - "MDATA_KEY_TRACKNUMBER": "tracknumber",\ - "MDATA_KEY_BPM": "bpm",\ - "MDATA_KEY_LABEL": "organization",\ - "MDATA_KEY_COMPOSER": "composer",\ - "MDATA_KEY_ENCODER": "encodedby",\ - "MDATA_KEY_CONDUCTOR": "conductor",\ - "MDATA_KEY_YEAR": "date",\ - "MDATA_KEY_URL": "website",\ - "MDATA_KEY_ISRC": "isrc",\ - "MDATA_KEY_COPYRIGHT": "copyright",\ + "MDATA_KEY_TITLE": "title", \ + "MDATA_KEY_CREATOR": "artist", \ + "MDATA_KEY_SOURCE": "album", \ + "MDATA_KEY_GENRE": "genre", \ + "MDATA_KEY_MOOD": "mood", \ + "MDATA_KEY_TRACKNUMBER": "tracknumber", \ + "MDATA_KEY_BPM": "bpm", \ + "MDATA_KEY_LABEL": "organization", \ + "MDATA_KEY_COMPOSER": "composer", \ + "MDATA_KEY_ENCODER": "encodedby", \ + "MDATA_KEY_CONDUCTOR": "conductor", \ + "MDATA_KEY_YEAR": "date", \ + "MDATA_KEY_URL": "website", \ + "MDATA_KEY_ISRC": "isrc", \ + "MDATA_KEY_COPYRIGHT": "copyright", \ } self.mutagen2airtime = {\ - "title": "MDATA_KEY_TITLE",\ - "artist": "MDATA_KEY_CREATOR",\ - "album": "MDATA_KEY_SOURCE",\ - "genre": "MDATA_KEY_GENRE",\ - "mood": "MDATA_KEY_MOOD",\ - "tracknumber": "MDATA_KEY_TRACKNUMBER",\ - "bpm": "MDATA_KEY_BPM",\ - "organization": "MDATA_KEY_LABEL",\ - "composer": "MDATA_KEY_COMPOSER",\ - "encodedby": "MDATA_KEY_ENCODER",\ - "conductor": "MDATA_KEY_CONDUCTOR",\ - "date": "MDATA_KEY_YEAR",\ - "website": "MDATA_KEY_URL",\ - "isrc": "MDATA_KEY_ISRC",\ - "copyright": "MDATA_KEY_COPYRIGHT",\ + "title": "MDATA_KEY_TITLE", \ + "artist": "MDATA_KEY_CREATOR", \ + "album": "MDATA_KEY_SOURCE", \ + "genre": "MDATA_KEY_GENRE", \ + "mood": "MDATA_KEY_MOOD", \ + "tracknumber": "MDATA_KEY_TRACKNUMBER", \ + "bpm": "MDATA_KEY_BPM", \ + "organization": "MDATA_KEY_LABEL", \ + "composer": "MDATA_KEY_COMPOSER", \ + "encodedby": "MDATA_KEY_ENCODER", \ + "conductor": "MDATA_KEY_CONDUCTOR", \ + "date": "MDATA_KEY_YEAR", \ + "website": "MDATA_KEY_URL", \ + "isrc": "MDATA_KEY_ISRC", \ + "copyright": "MDATA_KEY_COPYRIGHT", \ } self.logger = logging.getLogger() @@ -67,9 +68,9 @@ class AirtimeMetadata: ## return format hh:mm:ss.uuu def format_length(self, mutagen_length): t = float(mutagen_length) - h = int(math.floor(t/3600)) + h = int(math.floor(t / 3600)) t = t % 3600 - m = int(math.floor(t/60)) + m = int(math.floor(t / 60)) s = t % 60 # will be ss.uuu @@ -94,12 +95,12 @@ class AirtimeMetadata: for key in m: if key in self.airtime2mutagen: value = m[key] - + if value is not None: value = unicode(value) else: value = unicode(''); - + #if len(value) > 0: self.logger.debug("Saving key '%s' with value '%s' to file", key, value) airtime_file[self.airtime2mutagen[key]] = value @@ -123,8 +124,14 @@ class AirtimeMetadata: self.logger.info("getting info from filepath %s", filepath) + md = {} + + replay_gain_val = replay_gain.calculate_replay_gain(filepath) + self.logger.info('ReplayGain calculated as %s for %s' % (replay_gain_val, filepath)) + md['MDATA_KEY_REPLAYGAIN'] = replay_gain_val + try: - md = {} + md5 = self.get_md5(filepath) md['MDATA_KEY_MD5'] = md5 @@ -135,6 +142,7 @@ class AirtimeMetadata: self.logger.error("Exception %s", e) return None + #check if file has any metadata if file_info is None: return None @@ -149,6 +157,7 @@ class AirtimeMetadata: except Exception, e: self.logger.error('Exception: %s', e) self.logger.error("traceback: %s", traceback.format_exc()) + if 'MDATA_KEY_TITLE' not in md: #get rid of file extension from original name, name might have more than 1 '.' in it. original_name = os.path.basename(filepath) @@ -165,8 +174,6 @@ class AirtimeMetadata: pass if isinstance(md['MDATA_KEY_TRACKNUMBER'], basestring): - match = re.search('^(\d*/\d*)?', md['MDATA_KEY_TRACKNUMBER']) - try: md['MDATA_KEY_TRACKNUMBER'] = int(md['MDATA_KEY_TRACKNUMBER'].split("/")[0], 10) except Exception, e: @@ -223,7 +230,7 @@ class AirtimeMetadata: md['MDATA_KEY_BITRATE'] = getattr(file_info.info, "bitrate", None) md['MDATA_KEY_SAMPLERATE'] = getattr(file_info.info, "sample_rate", None) - self.logger.info( "Bitrate: %s , Samplerate: %s", md['MDATA_KEY_BITRATE'], md['MDATA_KEY_SAMPLERATE'] ) + self.logger.info("Bitrate: %s , Samplerate: %s", md['MDATA_KEY_BITRATE'], md['MDATA_KEY_SAMPLERATE']) try: md['MDATA_KEY_DURATION'] = self.format_length(file_info.info.length) except Exception as e: self.logger.warn("File: '%s' raises: %s", filepath, str(e)) diff --git a/python_apps/media-monitor/airtimefilemonitor/airtimenotifier.py b/python_apps/media-monitor/airtimefilemonitor/airtimenotifier.py index 274dc26d0..e35a8f049 100644 --- a/python_apps/media-monitor/airtimefilemonitor/airtimenotifier.py +++ b/python_apps/media-monitor/airtimefilemonitor/airtimenotifier.py @@ -8,13 +8,11 @@ import traceback # For RabbitMQ from kombu.connection import BrokerConnection -from kombu.messaging import Exchange, Queue, Consumer, Producer +from kombu.messaging import Exchange, Queue, Consumer import pyinotify from pyinotify import Notifier -#from api_clients import api_client -from api_clients import api_client from airtimemetadata import AirtimeMetadata class AirtimeNotifier(Notifier): @@ -153,7 +151,6 @@ class AirtimeNotifier(Notifier): md.update(file_md) else: file_md = None - data = None if (os.path.exists(filepath) and (mode == self.config.MODE_CREATE)): if file_md is None: @@ -184,7 +181,7 @@ class AirtimeNotifier(Notifier): self.api_client.update_media_metadata(md, mode) elif (mode == self.config.MODE_DELETE): self.api_client.update_media_metadata(md, mode) - + elif (mode == self.config.MODE_DELETE_DIR): self.api_client.update_media_metadata(md, mode) diff --git a/python_apps/media-monitor/airtimefilemonitor/airtimeprocessevent.py b/python_apps/media-monitor/airtimefilemonitor/airtimeprocessevent.py index 2195e9d91..5b7e21e7e 100644 --- a/python_apps/media-monitor/airtimefilemonitor/airtimeprocessevent.py +++ b/python_apps/media-monitor/airtimefilemonitor/airtimeprocessevent.py @@ -9,7 +9,6 @@ import difflib import traceback from subprocess import Popen, PIPE -import pyinotify from pyinotify import ProcessEvent from airtimemetadata import AirtimeMetadata @@ -59,8 +58,8 @@ class AirtimeProcessEvent(ProcessEvent): if "-unknown-path" in path: unknown_path = path pos = path.find("-unknown-path") - path = path[0:pos]+"/" - + path = path[0:pos] + "/" + list = self.api_client.list_all_watched_dirs() # case where the dir that is being watched is moved to somewhere if path in list[u'dirs'].values(): @@ -81,14 +80,14 @@ class AirtimeProcessEvent(ProcessEvent): self.logger.info("Removing watch on: %s wd %s", unknown_path, wd) self.wm.rm_watch(wd, rec=True) self.file_events.append({'mode': self.config.MODE_DELETE_DIR, 'filepath': path}) - - + + def process_IN_DELETE_SELF(self, event): - + #we only care about files that have been moved away from imported/ or organize/ dir if event.path in self.config.problem_directory or event.path in self.config.organize_directory: return - + self.logger.info("event: %s", event) path = event.path + '/' if event.dir: @@ -103,7 +102,7 @@ class AirtimeProcessEvent(ProcessEvent): self.logger.info("%s removed from watch folder list successfully.", path) else: self.logger.info("Removing the watch folder failed: %s", res['msg']['error']) - + def process_IN_CREATE(self, event): if event.path in self.mount_file_dir: return @@ -111,7 +110,7 @@ class AirtimeProcessEvent(ProcessEvent): if not event.dir: # record the timestamp of the time on IN_CREATE event self.create_dict[event.pathname] = time.time() - + #event.dir: True if the event was raised against a directory. #event.name: filename #event.pathname: pathname (str): Concatenation of 'path' and 'name'. @@ -122,7 +121,7 @@ class AirtimeProcessEvent(ProcessEvent): return self.logger.info("event: %s", event) self.logger.info("create_dict: %s", self.create_dict) - + try: del self.create_dict[event.pathname] self.handle_created_file(event.dir, event.pathname, event.name) @@ -130,8 +129,8 @@ class AirtimeProcessEvent(ProcessEvent): pass #self.logger.warn("%s does not exist in create_dict", event.pathname) #Uncomment the above warning when we fix CC-3830 for 2.1.1 - - + + def handle_created_file(self, dir, pathname, name): if not dir: self.logger.debug("PROCESS_IN_CLOSE_WRITE: %s, name: %s, pathname: %s ", dir, name, pathname) @@ -145,12 +144,12 @@ class AirtimeProcessEvent(ProcessEvent): self.temp_files[pathname] = None elif self.mmc.is_audio_file(name): if self.mmc.is_parent_directory(pathname, self.config.organize_directory): - + #file was created in /srv/airtime/stor/organize. Need to process and move #to /srv/airtime/stor/imported file_md = self.md_manager.get_md_from_file(pathname) playable = self.mmc.test_file_playability(pathname) - + if file_md and playable: self.mmc.organize_new_file(pathname, file_md) else: @@ -182,7 +181,7 @@ class AirtimeProcessEvent(ProcessEvent): if self.mmc.is_audio_file(name): is_recorded = self.mmc.is_parent_directory(pathname, self.config.recorded_directory) self.file_events.append({'filepath': pathname, 'mode': self.config.MODE_MODIFY, 'is_recorded_show': is_recorded}) - + # if change is detected on /etc/mtab, we check what mount(file system) was added/removed # and act accordingly def handle_mount_change(self): @@ -192,41 +191,41 @@ class AirtimeProcessEvent(ProcessEvent): shutil.move(self.curr_mtab_file, self.prev_mtab_file) # create the file shutil.copy(self.mount_file, self.curr_mtab_file) - + d = difflib.Differ() curr_fh = open(self.curr_mtab_file, 'r') prev_fh = open(self.prev_mtab_file, 'r') - + diff = list(d.compare(prev_fh.readlines(), curr_fh.readlines())) added_mount_points = [] removed_mount_points = [] - + for dir in diff: info = dir.split(' ') if info[0] == '+': added_mount_points.append(info[2]) elif info[0] == '-': removed_mount_points.append(info[2]) - + self.logger.info("added: %s", added_mount_points) self.logger.info("removed: %s", removed_mount_points) - + # send current mount information to Airtime self.api_client.update_file_system_mount(added_mount_points, removed_mount_points); - + def handle_watched_dir_missing(self, dir): self.api_client.handle_watched_dir_missing(dir); - + #if a file is moved somewhere, this callback is run. With details about #where the file is being moved from. The corresponding process_IN_MOVED_TO #callback is only called if the destination of the file is also in a watched #directory. def process_IN_MOVED_FROM(self, event): - + #we don't care about files that have been moved from problem_directory if event.path in self.config.problem_directory: return - + self.logger.info("process_IN_MOVED_FROM: %s", event) if not event.dir: if event.pathname in self.temp_files: @@ -241,10 +240,10 @@ class AirtimeProcessEvent(ProcessEvent): def process_IN_MOVED_TO(self, event): self.logger.info("process_IN_MOVED_TO: %s", event) # if /etc/mtab is modified - filename = self.mount_file_dir +"/mtab" + filename = self.mount_file_dir + "/mtab" if event.pathname in filename: self.handle_mount_change() - + if event.path in self.config.problem_directory: return @@ -265,15 +264,15 @@ class AirtimeProcessEvent(ProcessEvent): #to /srv/airtime/stor/imported file_md = self.md_manager.get_md_from_file(pathname) playable = self.mmc.test_file_playability(pathname) - + if file_md and playable: filepath = self.mmc.organize_new_file(pathname, file_md) else: #move to problem_files self.mmc.move_to_problem_dir(pathname) - - - + + + else: filepath = event.pathname @@ -283,23 +282,23 @@ class AirtimeProcessEvent(ProcessEvent): #file's original location is from outside an inotify watched dir. pathname = event.pathname if self.mmc.is_parent_directory(pathname, self.config.organize_directory): - - - - + + + + #file was created in /srv/airtime/stor/organize. Need to process and move #to /srv/airtime/stor/imported file_md = self.md_manager.get_md_from_file(pathname) playable = self.mmc.test_file_playability(pathname) - + if file_md and playable: self.mmc.organize_new_file(pathname, file_md) else: #move to problem_files self.mmc.move_to_problem_dir(pathname) - - - + + + else: #show moved from unwatched folder into a watched folder. Do not "organize". @@ -309,33 +308,33 @@ class AirtimeProcessEvent(ProcessEvent): #When we move a directory into a watched_dir, we only get a notification that the dir was created, #and no additional information about files that came along with that directory. #need to scan the entire directory for files. - + if event.cookie in self.cookies_IN_MOVED_FROM: del self.cookies_IN_MOVED_FROM[event.cookie] mode = self.config.MODE_MOVED else: mode = self.config.MODE_CREATE - + files = self.mmc.scan_dir_for_new_files(event.pathname) if self.mmc.is_parent_directory(event.pathname, self.config.organize_directory): for pathname in files: - - - + + + #file was created in /srv/airtime/stor/organize. Need to process and move #to /srv/airtime/stor/imported file_md = self.md_manager.get_md_from_file(pathname) playable = self.mmc.test_file_playability(pathname) - + if file_md and playable: self.mmc.organize_new_file(pathname, file_md) #self.file_events.append({'mode': mode, 'filepath': filepath, 'is_recorded_show': False}) else: #move to problem_files self.mmc.move_to_problem_dir(pathname) - - - + + + else: for file in files: self.file_events.append({'mode': mode, 'filepath': file, 'is_recorded_show': False}) @@ -368,12 +367,12 @@ class AirtimeProcessEvent(ProcessEvent): for event in self.file_events: self.multi_queue.put(event) self.mmc.touch_index_file() - + self.file_events = [] #yield to worker thread time.sleep(0) - + #use items() because we are going to be modifying this #dictionary while iterating over it. for k, pair in self.cookies_IN_MOVED_FROM.items(): @@ -390,7 +389,7 @@ class AirtimeProcessEvent(ProcessEvent): #it from the Airtime directory. del self.cookies_IN_MOVED_FROM[k] self.handle_removed_file(False, event.pathname) - + # we don't want create_dict grow infinitely # this part is like a garbage collector for k, t in self.create_dict.items(): @@ -404,14 +403,14 @@ class AirtimeProcessEvent(ProcessEvent): if os.path.exists(k): # check if file is open try: - command = "lsof "+k + command = "lsof " + k #f = os.popen(command) f = Popen(command, shell=True, stdout=PIPE).stdout except Exception, e: self.logger.error('Exception: %s', e) self.logger.error("traceback: %s", traceback.format_exc()) continue - + if not f.readlines(): self.logger.info("Handling file: %s", k) self.handle_created_file(False, k, os.path.basename(k)) diff --git a/python_apps/media-monitor/airtimefilemonitor/mediamonitorcommon.py b/python_apps/media-monitor/airtimefilemonitor/mediamonitorcommon.py index 0c2f5b68a..c8338e01e 100644 --- a/python_apps/media-monitor/airtimefilemonitor/mediamonitorcommon.py +++ b/python_apps/media-monitor/airtimefilemonitor/mediamonitorcommon.py @@ -10,7 +10,6 @@ import traceback from subprocess import Popen, PIPE from airtimemetadata import AirtimeMetadata -from api_clients import api_client import pyinotify class MediaMonitorCommon: @@ -75,7 +74,7 @@ class MediaMonitorCommon: try: return self.is_user_readable(item, 'www-data', 'www-data') \ and self.is_user_readable(item, 'pypo', 'pypo') - except Exception, e: + except Exception: self.logger.warn(u"Failed to check owner/group/permissions for %s", item) return False @@ -110,7 +109,7 @@ class MediaMonitorCommon: else: pathname = dirname is_dir = True - except Exception, e: + except Exception: #something went wrong while we were trying to make world readable. return False @@ -194,7 +193,7 @@ class MediaMonitorCommon: break except Exception, e: - self.logger.error("Exception %s", e) + self.logger.error("Exception %s", e) return filepath @@ -273,7 +272,7 @@ class MediaMonitorCommon: File name charset encoding is UTF-8. """ stdout = stdout.decode("UTF-8") - except Exception, e: + except Exception: stdout = None self.logger.error("Could not decode %s using UTF-8" % stdout) diff --git a/python_apps/media-monitor/airtimefilemonitor/replay_gain.py b/python_apps/media-monitor/airtimefilemonitor/replay_gain.py new file mode 100644 index 000000000..0fd797700 --- /dev/null +++ b/python_apps/media-monitor/airtimefilemonitor/replay_gain.py @@ -0,0 +1,81 @@ +from subprocess import Popen, PIPE +import re +import os +import sys + +def get_process_output(command): + """ + Run subprocess and return stdout + """ + p = Popen(command, shell=True, stdout=PIPE) + return p.communicate()[0].strip() + +def run_process(command): + """ + Run subprocess and return "return code" + """ + p = Popen(command, shell=True) + return os.waitpid(p.pid, 0)[1] + +def get_mime_type(file_path): + """ + Attempts to get the mime type but will return prematurely if the process + takes longer than 5 seconds. Note that this function should only be called + for files which do not have a mp3/ogg/flac extension. + """ + + return get_process_output("timeout 5 file -b --mime-type %s" % file_path) + +def calculate_replay_gain(file_path): + """ + This function accepts files of type mp3/ogg/flac and returns a calculated ReplayGain value. + If the value cannot be calculated for some reason, then we default to 1. + + TODO: + Currently some of the subprocesses called will actually insert metadata into the file itself, + which we do *not* want as this changes the file's hash. Need to make a copy of the file before + we run this function. + + http://wiki.hydrogenaudio.org/index.php?title=ReplayGain_1.0_specification + """ + + search = None + if re.search(r'mp3$', file_path, re.IGNORECASE) or get_mime_type(file_path) == "audio/mpeg": + if run_process("which mp3gain > /dev/null") == 0: + out = get_process_output('mp3gain -q "%s" 2> /dev/null' % file_path) + search = re.search(r'Recommended "Track" dB change: (.*)', out) + else: + print "mp3gain not found" + #Log warning + elif re.search(r'ogg$', file_path, re.IGNORECASE) or get_mime_type(file_path) == "application/ogg": + if run_process("which vorbisgain > /dev/null && which ogginfo > dev/null") == 0: + run_process('vorbisgain -q -f "%s" 2>/dev/null >/dev/null' % file_path) + out = get_process_output('ogginfo "%s"' % file_path) + search = re.search(r'REPLAYGAIN_TRACK_GAIN=(.*) dB', out) + else: + print "vorbisgain/ogginfo not found" + #Log warning + elif re.search(r'flac$', file_path, re.IGNORECASE) or get_mime_type(file_path) == "audio/x-flac": + if run_process("which metaflac > /dev/null") == 0: + out = get_process_output('metaflac --show-tag=REPLAYGAIN_TRACK_GAIN "%s"' % file_path) + search = re.search(r'REPLAYGAIN_TRACK_GAIN=(.*) dB', out) + else: + print "metaflac not found" + #Log warning + else: + pass + #Log unknown file type. + + replay_gain = 1 + if search: + matches = search.groups() + if len(matches) == 1: + replay_gain = matches[0] + + return replay_gain + + +# Example of running from command line: +# python replay_gain.py /path/to/filename.mp3 +if __name__ == "__main__": + print calculate_replay_gain(sys.argv[1]) diff --git a/python_apps/media-monitor/airtimefilemonitor/workerprocess.py b/python_apps/media-monitor/airtimefilemonitor/workerprocess.py index deccd736c..73bde5045 100644 --- a/python_apps/media-monitor/airtimefilemonitor/workerprocess.py +++ b/python_apps/media-monitor/airtimefilemonitor/workerprocess.py @@ -1,11 +1,10 @@ # -*- coding: utf-8 -*- -from mediaconfig import AirtimeMediaConfig import traceback import os class MediaMonitorWorkerProcess: - + def __init__(self, config, mmc): self.config = config self.mmc = mmc