diff --git a/airtime_mvc/application/controllers/PlaylistController.php b/airtime_mvc/application/controllers/PlaylistController.php index 3a93d0232..85b3c5edb 100644 --- a/airtime_mvc/application/controllers/PlaylistController.php +++ b/airtime_mvc/application/controllers/PlaylistController.php @@ -125,6 +125,8 @@ class PlaylistController extends Zend_Controller_Action private function playlistNoPermission($p_type) { $this->view->error = "You don't have permission to delete selected {$p_type}(s)."; + $this->changePlaylist(null, $p_type); + $this->createFullResponse(null); } private function playlistUnknownError($e) @@ -221,6 +223,8 @@ class PlaylistController extends Zend_Controller_Action $this->createFullResponse($obj); } catch (PlaylistNoPermissionException $e) { $this->playlistNoPermission($type); + } catch (BlockNoPermissionException $e) { + $this->playlistNoPermission($type); } catch (PlaylistNotFoundException $e) { $this->playlistNotFound($type); } catch (Exception $e) { diff --git a/airtime_mvc/application/models/Block.php b/airtime_mvc/application/models/Block.php index f1941e73d..3bc4d64d2 100644 --- a/airtime_mvc/application/models/Block.php +++ b/airtime_mvc/application/models/Block.php @@ -192,7 +192,7 @@ class Application_Model_Block implements Application_Model_LibraryEditable $files = array(); $sql = <<<"EOT" - SELECT pc.id as id, pc.position, pc.cliplength as length, pc.cuein, pc.cueout, pc.fadein, pc.fadeout, bl.type, + SELECT pc.id as id, pc.position, pc.cliplength as length, pc.cuein, pc.cueout, pc.fadein, pc.fadeout, bl.type, f.length as orig_length, f.id as item_id, f.track_title, f.artist_name as creator, f.file_exists as exists, f.filepath as path FROM cc_blockcontents AS pc LEFT JOIN cc_files AS f ON pc.file_id=f.id LEFT JOIN cc_block AS bl ON pc.block_id = bl.id @@ -220,6 +220,10 @@ EOT; $fades = $this->getFadeInfo($row['position']); $row['fadein'] = $fades[0]; $row['fadeout'] = $fades[1]; + + //format original length + $formatter = new LengthFormatter($row['orig_length']); + $row['orig_length'] = $formatter->format(); } return $rows; @@ -871,11 +875,20 @@ EOT; */ public static function deleteBlocks($p_ids, $p_userId) { - $leftOver = self::blocksNotOwnedByUser($p_ids, $p_userId); - if (count($leftOver) == 0) { - CcBlockQuery::create()->findPKs($p_ids)->delete(); + $userInfo = Zend_Auth::getInstance()->getStorage()->read(); + $user = new Application_Model_User($userInfo->id); + $isAdminOrPM = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER)); + + if (!$isAdminOrPM) { + $leftOver = self::blocksNotOwnedByUser($p_ids, $p_userId); + + if (count($leftOver) == 0) { + CcBlockQuery::create()->findPKs($p_ids)->delete(); + } else { + throw new BlockNoPermissionException; + } } else { - throw new BlockNoPermissionException; + CcBlockQuery::create()->findPKs($p_ids)->delete(); } } diff --git a/airtime_mvc/application/models/Datatables.php b/airtime_mvc/application/models/Datatables.php index 66737b7d9..c4ec7df35 100644 --- a/airtime_mvc/application/models/Datatables.php +++ b/airtime_mvc/application/models/Datatables.php @@ -90,17 +90,21 @@ class Application_Model_Datatables // we need to go over all items and fix length for playlist // in case the playlist contains dynamic block foreach ($results as &$r) { - if ($r['ftype'] == 'playlist') { - $pl = new Application_Model_Playlist($r['id']); - $r['length'] = $pl->getLength(); - } else if ($r['ftype'] == "block") { - $bl = new Application_Model_Block($r['id']); - if ($bl->isStatic()) { - $r['bl_type'] = 'static'; - } else { - $r['bl_type'] = 'dynamic'; + //this function is also called for Manage Users so in + //this case there will be no 'ftype' + if (isset($r['ftype'])) { + if ($r['ftype'] == 'playlist') { + $pl = new Application_Model_Playlist($r['id']); + $r['length'] = $pl->getLength(); + } else if ($r['ftype'] == "block") { + $bl = new Application_Model_Block($r['id']); + if ($bl->isStatic()) { + $r['bl_type'] = 'static'; + } else { + $r['bl_type'] = 'dynamic'; + } + $r['length'] = $bl->getLength(); } - $r['length'] = $bl->getLength(); } } } catch (Exception $e) { diff --git a/airtime_mvc/application/models/Playlist.php b/airtime_mvc/application/models/Playlist.php index 31fdbb6ed..a8d35adee 100644 --- a/airtime_mvc/application/models/Playlist.php +++ b/airtime_mvc/application/models/Playlist.php @@ -171,7 +171,8 @@ class Application_Model_Playlist implements Application_Model_LibraryEditable f.track_title, f.artist_name AS creator, f.file_exists AS EXISTS, - f.filepath AS path + f.filepath AS path, + f.length AS orig_length FROM cc_playlistcontents AS pc JOIN cc_files AS f ON pc.file_id=f.id WHERE pc.playlist_id = {$this->id} @@ -188,7 +189,8 @@ class Application_Model_Playlist implements Application_Model_LibraryEditable (ws.name || ': ' || ws.url) AS title, sub.login AS creator, 't'::boolean AS EXISTS, - ws.url AS path + ws.url AS path, + ws.length AS orig_length FROM cc_playlistcontents AS pc JOIN cc_webstream AS ws ON pc.stream_id=ws.id LEFT JOIN cc_subjs AS sub ON sub.id = ws.creator_id @@ -206,7 +208,8 @@ class Application_Model_Playlist implements Application_Model_LibraryEditable bl.name AS title, sbj.login AS creator, 't'::boolean AS EXISTS, - NULL::text AS path + NULL::text AS path, + bl.length AS orig_length FROM cc_playlistcontents AS pc JOIN cc_block AS bl ON pc.block_id=bl.id JOIN cc_subjs AS sbj ON bl.creator_id=sbj.id @@ -240,6 +243,10 @@ SQL; $fades = $this->getFadeInfo($row['position']); $row['fadein'] = $fades[0]; $row['fadeout'] = $fades[1]; + + //format original length + $formatter = new LengthFormatter($row['orig_length']); + $row['orig_length'] = $formatter->format(); } return $rows; @@ -867,11 +874,19 @@ SQL; */ public static function deletePlaylists($p_ids, $p_userId) { - $leftOver = self::playlistsNotOwnedByUser($p_ids, $p_userId); - if (count($leftOver) == 0) { - CcPlaylistQuery::create()->findPKs($p_ids)->delete(); + $userInfo = Zend_Auth::getInstance()->getStorage()->read(); + $user = new Application_Model_User($userInfo->id); + $isAdminOrPM = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER)); + + if (!$isAdminOrPM) { + $leftOver = self::playlistsNotOwnedByUser($p_ids, $p_userId); + if (count($leftOver) == 0) { + CcPlaylistQuery::create()->findPKs($p_ids)->delete(); + } else { + throw new PlaylistNoPermissionException; + } } else { - throw new PlaylistNoPermissionException; + CcPlaylistQuery::create()->findPKs($p_ids)->delete(); } } diff --git a/airtime_mvc/application/models/Show.php b/airtime_mvc/application/models/Show.php index 874fe2402..8cca2cf69 100644 --- a/airtime_mvc/application/models/Show.php +++ b/airtime_mvc/application/models/Show.php @@ -1549,7 +1549,7 @@ class Application_Model_Show $sql = $sql." AND ({$exclude})"; } - $result = $con->query($sql); + $result = $con->query($sql)->fetchAll(); return $result; } diff --git a/airtime_mvc/application/views/scripts/playlist/update.phtml b/airtime_mvc/application/views/scripts/playlist/update.phtml index 280437d87..a66b9f94a 100644 --- a/airtime_mvc/application/views/scripts/playlist/update.phtml +++ b/airtime_mvc/application/views/scripts/playlist/update.phtml @@ -55,7 +55,7 @@ if ($item['type'] == 2) { 'id' => $item["id"], 'cueIn' => $item['cuein'], 'cueOut' => $item['cueout'], - 'origLength' => $item['length'])); ?> + 'origLength' => $item['orig_length'])); ?> diff --git a/python_apps/media-monitor2/media/monitor/eventcontractor.py b/python_apps/media-monitor2/media/monitor/eventcontractor.py index 77a5045fb..7e444b3ea 100644 --- a/python_apps/media-monitor2/media/monitor/eventcontractor.py +++ b/python_apps/media-monitor2/media/monitor/eventcontractor.py @@ -59,4 +59,6 @@ class EventContractor(Loggable): try: del self.store[evt.path] except Exception as e: self.unexpected_exception(e) - self.logger.info("Unregistering. Left: '%d'" % len(self.store.keys())) + # the next line is commented out because it clutters up logging real + # bad + #self.logger.info("Unregistering. Left: '%d'" % len(self.store.keys())) diff --git a/python_apps/media-monitor2/media/monitor/metadata.py b/python_apps/media-monitor2/media/monitor/metadata.py index a8c982b9a..5f222c4b4 100644 --- a/python_apps/media-monitor2/media/monitor/metadata.py +++ b/python_apps/media-monitor2/media/monitor/metadata.py @@ -105,10 +105,38 @@ class Metadata(Loggable): # little bit messy. Some of the handling is in m.m.pure while the rest is # here. Also interface is not very consistent + @staticmethod + def airtime_dict(d): + """ + Converts mutagen dictionary 'd' into airtime dictionary + """ + temp_dict = {} + for m_key, m_val in d.iteritems(): + # TODO : some files have multiple fields for the same metadata. + # genre is one example. In that case mutagen will return a list + # of values + assign_val = m_val[0] if isinstance(m_val, list) else m_val + temp_dict[ m_key ] = assign_val + airtime_dictionary = {} + for muta_k, muta_v in temp_dict.iteritems(): + # We must check if we can actually translate the mutagen key into + # an airtime key before doing the conversion + if muta_k in mutagen2airtime: + airtime_key = mutagen2airtime[muta_k] + # Apply truncation in the case where airtime_key is in our + # truncation table + muta_v = \ + truncate_to_length(muta_v, truncate_table[airtime_key])\ + if airtime_key in truncate_table else muta_v + airtime_dictionary[ airtime_key ] = muta_v + return airtime_dictionary + @staticmethod def write_unsafe(path,md): """ - Writes 'md' metadata into 'path' through mutagen + Writes 'md' metadata into 'path' through mutagen. Converts all + dictionary values to strings because mutagen will not write anything + else """ if not os.path.exists(path): raise BadSongFile(path) song_file = mutagen.File(path, easy=True) @@ -128,37 +156,13 @@ class Metadata(Loggable): self.path = fpath # TODO : Simplify the way all of these rules are handled right not it's # extremely unclear and needs to be refactored. - metadata = {} - # Load only the metadata avilable in mutagen into metdata - for k,v in full_mutagen.iteritems(): - # Special handling of attributes here - if isinstance(v, list): - # TODO : some files have multiple fields for the same metadata. - # genre is one example. In that case mutagen will return a list - # of values - metadata[k] = v[0] - #if len(v) == 1: metadata[k] = v[0] - #else: raise Exception("Unknown mutagen %s:%s" % (k,str(v))) - else: metadata[k] = v - self.__metadata = {} - # Start populating a dictionary of airtime metadata in __metadata - for muta_k, muta_v in metadata.iteritems(): - # We must check if we can actually translate the mutagen key into - # an airtime key before doing the conversion - if muta_k in mutagen2airtime: - airtime_key = mutagen2airtime[muta_k] - # Apply truncation in the case where airtime_key is in our - # truncation table - muta_v = \ - truncate_to_length(muta_v, truncate_table[airtime_key])\ - if airtime_key in truncate_table else muta_v - self.__metadata[ airtime_key ] = muta_v + self.__metadata = Metadata.airtime_dict(full_mutagen) # Now we extra the special values that are calculated from the mutagen # object itself: for special_key,f in airtime_special.iteritems(): new_val = f(full_mutagen) if new_val is not None: - self.__metadata[special_key] = f(full_mutagen) + self.__metadata[special_key] = new_val # Finally, we "normalize" all the metadata here: self.__metadata = mmp.normalized_metadata(self.__metadata, fpath) # Now we must load the md5: diff --git a/python_apps/media-monitor2/media/monitor/pure.py b/python_apps/media-monitor2/media/monitor/pure.py index 3f0b8bbe4..89c859ace 100644 --- a/python_apps/media-monitor2/media/monitor/pure.py +++ b/python_apps/media-monitor2/media/monitor/pure.py @@ -2,6 +2,7 @@ import copy import os import shutil +import re import sys import hashlib import locale @@ -228,34 +229,33 @@ def normalized_metadata(md, original_path): # Specific rules that are applied in a per attribute basis format_rules = { 'MDATA_KEY_TRACKNUMBER' : parse_int, - 'MDATA_KEY_BITRATE' : lambda x: str(int(x) / 1000) + "kbps", 'MDATA_KEY_FILEPATH' : lambda x: os.path.normpath(x), 'MDATA_KEY_MIME' : lambda x: x.replace('-','/'), 'MDATA_KEY_BPM' : lambda x: x[0:8], } - new_md = remove_whitespace(new_md) + new_md = remove_whitespace(new_md) # remove whitespace fields + # Format all the fields in format_rules new_md = apply_rules_dict(new_md, format_rules) - new_md = default_to(dictionary=new_md, keys=['MDATA_KEY_TITLE'], - default=no_extension_basename(original_path)) - new_md = default_to(dictionary=new_md, keys=['MDATA_KEY_CREATOR', - 'MDATA_KEY_SOURCE'], default=u'') + # set filetype to audioclip by default new_md = default_to(dictionary=new_md, keys=['MDATA_KEY_FTYPE'], default=u'audioclip') - # In the case where the creator is 'Airtime Show Recorder' we would like to - # format the MDATA_KEY_TITLE slightly differently - # Note: I don't know why I'm doing a unicode string comparison here - # that part is copied from the original code + + # Try to parse bpm but delete the whole key if that fails + if 'MDATA_KEY_BPM' in new_md: + new_md['MDATA_KEY_BPM'] = parse_int(new_md['MDATA_KEY_BPM']) + if new_md['MDATA_KEY_BPM'] is None: + del new_md['MDATA_KEY_BPM'] + if is_airtime_recorded(new_md): - hour,minute,second,name = md['MDATA_KEY_TITLE'].split("-",3) - # We assume that MDATA_KEY_YEAR is always given for airtime recorded - # shows + hour,minute,second,name = new_md['MDATA_KEY_TITLE'].split("-",3) new_md['MDATA_KEY_TITLE'] = u'%s-%s-%s:%s:%s' % \ (name, new_md['MDATA_KEY_YEAR'], hour, minute, second) - # IMPORTANT: in the original code. MDATA_KEY_FILEPATH would also - # be set to the original path of the file for airtime recorded shows - # (before it was "organized"). We will skip this procedure for now - # because it's not clear why it was done + else: + # Read title from filename if it does not exist + new_md = default_to(dictionary=new_md, keys=['MDATA_KEY_TITLE'], + default=no_extension_basename(original_path)) + return new_md def organized_path(old_path, root_path, orig_md): @@ -274,15 +274,26 @@ def organized_path(old_path, root_path, orig_md): if key in dictionary: return len(dictionary[key]) == 0 else: return True # We set some metadata elements to a default "unknown" value because we use - # these fields to create a path hence they cannot be empty + # these fields to create a path hence they cannot be empty Here "normal" + # means normalized only for organized path + + # MDATA_KEY_BITRATE is in bytes/second i.e. (256000) we want to turn this + # into 254kbps normal_md = default_to_f(orig_md, path_md, unicode_unknown, default_f) + if normal_md['MDATA_KEY_BITRATE']: + formatted = str(int(normal_md['MDATA_KEY_BITRATE']) / 1000) + normal_md['MDATA_KEY_BITRATE'] = formatted + 'kbps' + else: normal_md['MDATA_KEY_BITRATE'] = unicode_unknown + if is_airtime_recorded(normal_md): - fname = u'%s-%s-%s.%s' % ( normal_md['MDATA_KEY_YEAR'], - normal_md['MDATA_KEY_TITLE'], - normal_md['MDATA_KEY_BITRATE'], ext ) - yyyy, mm, _ = normal_md['MDATA_KEY_YEAR'].split('-',3) - path = os.path.join(root_path, yyyy, mm) - filepath = os.path.join(path,fname) + title_re = re.match("(?P\w+)-(?P\d+-\d+-\d+-\d+:\d+:\d+)$", + normal_md['MDATA_KEY_TITLE']) + show_name, = title_re.group('show'), + date = title_re.group('date').replace(':','-') + yyyy, mm, _ = normal_md['MDATA_KEY_YEAR'].split('-',2) + fname_base = '%s-%s-%s.%s' % \ + (date, show_name, normal_md['MDATA_KEY_BITRATE'], ext) + filepath = os.path.join(root_path, yyyy, mm, fname_base) elif len(normal_md['MDATA_KEY_TRACKNUMBER']) == 0: fname = u'%s-%s.%s' % (normal_md['MDATA_KEY_TITLE'], normal_md['MDATA_KEY_BITRATE'], ext) diff --git a/python_apps/media-monitor2/mm2.py b/python_apps/media-monitor2/mm2.py index 752076da2..dbfa1ebd5 100644 --- a/python_apps/media-monitor2/mm2.py +++ b/python_apps/media-monitor2/mm2.py @@ -127,6 +127,8 @@ def main(global_config, api_client_config, log_config, tt = ToucherThread(path=config['index_path'], interval=int(config['touch_interval'])) + apiclient.register_component('media-monitor') + pyi = manager.pyinotify() pyi.loop() diff --git a/python_apps/media-monitor2/tests/test_pure.py b/python_apps/media-monitor2/tests/test_pure.py index 611c42f60..e822f3cf5 100644 --- a/python_apps/media-monitor2/tests/test_pure.py +++ b/python_apps/media-monitor2/tests/test_pure.py @@ -2,6 +2,7 @@ import unittest import os import media.monitor.pure as mmp +from media.monitor.metadata import Metadata class TestMMP(unittest.TestCase): def setUp(self): @@ -34,23 +35,32 @@ class TestMMP(unittest.TestCase): for k in def_keys: self.assertEqual( sd[k], 'DEF' ) def test_normalized_metadata(self): - normal = mmp.normalized_metadata(self.md1,"") - self.assertTrue(hasattr(normal['MDATA_KEY_CREATOR'],'startswith')) - self.assertTrue('MDATA_KEY_CREATOR' in normal) - self.assertTrue('MDATA_KEY_SOURCE' in normal) + # Recorded show test first + orig = Metadata.airtime_dict({ + 'date': [u'2012-08-21'], + 'tracknumber': [u'2'], + 'title': [u'11-29-00-record'], + 'artist': [u'Airtime Show Recorder'] + }) + orga = Metadata.airtime_dict({ + 'date': [u'2012-08-21'], + 'tracknumber': [u'2'], + 'artist': [u'Airtime Show Recorder'], + 'title': [u'record-2012-08-21-11:29:00'] + }) + orga['MDATA_KEY_FTYPE'] = u'audioclip' + orig['MDATA_KEY_BITRATE'] = u'256000' + orga['MDATA_KEY_BITRATE'] = u'256kbps' - def test_organized_path(self): - o_path = '/home/rudi/throwaway/ACDC_-_Back_In_Black-sample-64kbps.ogg' - normal = mmp.normalized_metadata(self.md1,o_path) - og = mmp.organized_path(o_path, - '/home/rudi/throwaway/fucking_around/watch/', - normal) - real_path1 = \ - u'/home/rudi/throwaway/fucking_around/watch/unknown/unknown/ACDC_-_Back_In_Black-sample-64kbps-64kbps.ogg' - self.assertTrue( 'unknown' in og, True ) - self.assertEqual( og, real_path1 ) # TODO : fix this failure - # for recorded it should be something like this - # ./recorded/2012/07/2012-07-09-17-55-00-Untitled Show-256kbps.ogg + old_path = "/home/rudi/recorded/2012-08-21-11:29:00.ogg" + normalized = mmp.normalized_metadata(orig, old_path) + print(normalized) + self.assertEqual( orga, normalized ) + + organized_base_name = "2012-08-21-11-29-00-record-256kbps.ogg" + base = "/srv/airtime/stor/" + organized_path = mmp.organized_path(old_path,base, normalized) + self.assertEqual(os.path.basename(organized_path), organized_base_name) def test_file_md5(self): p = os.path.realpath(__file__) diff --git a/python_apps/pypo/recorder.py b/python_apps/pypo/recorder.py index 00d51c010..f5601fa6c 100644 --- a/python_apps/pypo/recorder.py +++ b/python_apps/pypo/recorder.py @@ -9,6 +9,7 @@ import sys import pytz import signal import math +import traceback from configobj import ConfigObj @@ -55,16 +56,16 @@ class ShowRecorder(Thread): def __init__ (self, show_instance, show_name, filelength, start_time): Thread.__init__(self) - self.logger = logging.getLogger('recorder') - self.api_client = api_client(self.logger) - self.filelength = filelength - self.start_time = start_time + self.logger = logging.getLogger('recorder') + self.api_client = api_client(self.logger) + self.filelength = filelength + self.start_time = start_time self.show_instance = show_instance - self.show_name = show_name - self.p = None + self.show_name = show_name + self.p = None def record_show(self): - length = str(self.filelength) + ".0" + length = str(self.filelength) + ".0" filename = self.start_time filename = filename.replace(" ", "-") @@ -73,16 +74,18 @@ class ShowRecorder(Thread): else: filetype = "ogg"; - filepath = "%s%s.%s" % (config["base_recorded_files"], filename, filetype) + joined_path = os.path.join(config["base_recorded_files"], filename) + filepath = "%s.%s" % (joined_path, filetype) br = config["record_bitrate"] sr = config["record_samplerate"] - c = config["record_channels"] + c = config["record_channels"] ss = config["record_sample_size"] #-f:16,2,44100 #-b:256 - command = "ecasound -f:%s,%s,%s -i alsa -o %s,%s000 -t:%s" % (ss, c, sr, filepath, br, length) + command = "ecasound -f:%s,%s,%s -i alsa -o %s,%s000 -t:%s" % \ + (ss, c, sr, filepath, br, length) args = command.split(" ") self.logger.info("starting record") @@ -144,17 +147,16 @@ class ShowRecorder(Thread): artist = "Airtime Show Recorder" #set some metadata for our file daemon - recorded_file = mutagen.File(filepath, easy=True) - recorded_file['title'] = name + recorded_file = mutagen.File(filepath, easy = True) + recorded_file['title'] = name recorded_file['artist'] = artist - recorded_file['date'] = md[0] + recorded_file['date'] = md[0] #recorded_file['date'] = md[0].split("-")[0] #You cannot pass ints into the metadata of a file. Even tracknumber needs to be a string recorded_file['tracknumber'] = unicode(self.show_instance) recorded_file.save() except Exception, e: - import traceback top = traceback.format_exc() self.logger.error('Exception: %s', e) self.logger.error("traceback: %s", top) @@ -180,20 +182,20 @@ class ShowRecorder(Thread): class Recorder(Thread): def __init__(self, q): Thread.__init__(self) - self.logger = logging.getLogger('recorder') - self.api_client = api_client(self.logger) - self.api_client.register_component("show-recorder") - self.sr = None + self.logger = logging.getLogger('recorder') + self.api_client = api_client(self.logger) + self.sr = None self.shows_to_record = {} self.server_timezone = '' - self.queue = q + self.queue = q + self.loops = 0 + self.api_client.register_component("show-recorder") self.logger.info("RecorderFetch: init complete") - self.loops = 0 def handle_message(self): if not self.queue.empty(): message = self.queue.get() - msg = json.loads(message) + msg = json.loads(message) command = msg["event_type"] self.logger.info("Received msg from Pypo Message Handler: %s", msg) if command == 'cancel_recording': @@ -212,8 +214,8 @@ class Recorder(Thread): shows = m['shows'] for show in shows: show_starts = getDateTimeObj(show[u'starts']) - show_end = getDateTimeObj(show[u'ends']) - time_delta = show_end - show_starts + show_end = getDateTimeObj(show[u'ends']) + time_delta = show_end - show_starts temp_shows_to_record[show[u'starts']] = [time_delta, show[u'instance_id'], show[u'name'], m['server_timezone']] self.shows_to_record = temp_shows_to_record @@ -223,10 +225,10 @@ class Recorder(Thread): tnow = datetime.datetime.utcnow() sorted_show_keys = sorted(self.shows_to_record.keys()) - start_time = sorted_show_keys[0] - next_show = getDateTimeObj(start_time) + start_time = sorted_show_keys[0] + next_show = getDateTimeObj(start_time) - delta = next_show - tnow + delta = next_show - tnow s = '%s.%s' % (delta.seconds, delta.microseconds) out = float(s) @@ -237,36 +239,35 @@ class Recorder(Thread): return out def start_record(self): - if len(self.shows_to_record) != 0: - try: - delta = self.get_time_till_next_show() - if delta < 5: - self.logger.debug("sleeping %s seconds until show", delta) - time.sleep(delta) + if len(self.shows_to_record) == 0: return None + try: + delta = self.get_time_till_next_show() + if delta < 5: + self.logger.debug("sleeping %s seconds until show", delta) + time.sleep(delta) - sorted_show_keys = sorted(self.shows_to_record.keys()) - start_time = sorted_show_keys[0] - show_length = self.shows_to_record[start_time][0] - show_instance = self.shows_to_record[start_time][1] - show_name = self.shows_to_record[start_time][2] - server_timezone = self.shows_to_record[start_time][3] + sorted_show_keys = sorted(self.shows_to_record.keys()) + start_time = sorted_show_keys[0] + show_length = self.shows_to_record[start_time][0] + show_instance = self.shows_to_record[start_time][1] + show_name = self.shows_to_record[start_time][2] + server_timezone = self.shows_to_record[start_time][3] - T = pytz.timezone(server_timezone) - start_time_on_UTC = getDateTimeObj(start_time) - start_time_on_server = start_time_on_UTC.replace(tzinfo=pytz.utc).astimezone(T) - start_time_formatted = '%(year)d-%(month)02d-%(day)02d %(hour)02d:%(min)02d:%(sec)02d' % \ - {'year': start_time_on_server.year, 'month': start_time_on_server.month, 'day': start_time_on_server.day, \ - 'hour': start_time_on_server.hour, 'min': start_time_on_server.minute, 'sec': start_time_on_server.second} - self.sr = ShowRecorder(show_instance, show_name, show_length.seconds, start_time_formatted) - self.sr.start() - #remove show from shows to record. - del self.shows_to_record[start_time] - #self.time_till_next_show = self.get_time_till_next_show() - except Exception, e : - import traceback - top = traceback.format_exc() - self.logger.error('Exception: %s', e) - self.logger.error("traceback: %s", top) + T = pytz.timezone(server_timezone) + start_time_on_UTC = getDateTimeObj(start_time) + start_time_on_server = start_time_on_UTC.replace(tzinfo=pytz.utc).astimezone(T) + start_time_formatted = '%(year)d-%(month)02d-%(day)02d %(hour)02d:%(min)02d:%(sec)02d' % \ + {'year': start_time_on_server.year, 'month': start_time_on_server.month, 'day': start_time_on_server.day, \ + 'hour': start_time_on_server.hour, 'min': start_time_on_server.minute, 'sec': start_time_on_server.second} + self.sr = ShowRecorder(show_instance, show_name, show_length.seconds, start_time_formatted) + self.sr.start() + #remove show from shows to record. + del self.shows_to_record[start_time] + #self.time_till_next_show = self.get_time_till_next_show() + except Exception, e : + top = traceback.format_exc() + self.logger.error('Exception: %s', e) + self.logger.error("traceback: %s", top) """ Main loop of the thread: @@ -284,6 +285,7 @@ class Recorder(Thread): self.process_recorder_schedule(temp) self.logger.info("Bootstrap recorder schedule received: %s", temp) except Exception, e: + self.logger.error( traceback.format_exc() ) self.logger.error(e) self.logger.info("Bootstrap complete: got initial copy of the schedule") @@ -305,14 +307,15 @@ class Recorder(Thread): self.process_recorder_schedule(temp) self.logger.info("updated recorder schedule received: %s", temp) except Exception, e: + self.logger.error( traceback.format_exc() ) self.logger.error(e) try: self.handle_message() except Exception, e: + self.logger.error( traceback.format_exc() ) self.logger.error('Pypo Recorder Exception: %s', e) time.sleep(PUSH_INTERVAL) self.loops += 1 except Exception, e : - import traceback top = traceback.format_exc() self.logger.error('Exception: %s', e) self.logger.error("traceback: %s", top)