diff --git a/airtime_mvc/application/Bootstrap.php b/airtime_mvc/application/Bootstrap.php index af8cff19a..3cc24f73f 100644 --- a/airtime_mvc/application/Bootstrap.php +++ b/airtime_mvc/application/Bootstrap.php @@ -90,12 +90,7 @@ class Bootstrap extends Zend_Application_Bootstrap_Bootstrap $userType = ""; } $view->headScript()->appendScript("var userType = '$userType';"); - if (Application_Model_Preference::GetPlanLevel() != "disabled" - && !($_SERVER['REQUEST_URI'] == '/Dashboard/stream-player' || $_SERVER['REQUEST_URI'] == '/audiopreview/audio-preview-player')) { - $client_id = Application_Model_Preference::GetClientId(); - $view->headScript()->appendScript("var livechat_client_id = '$client_id';"); - $view->headScript()->appendFile($baseUrl . '/js/airtime/common/livechat.js?'.$CC_CONFIG['airtime_version'], 'text/javascript'); - } + if(isset($CC_CONFIG['demo']) && $CC_CONFIG['demo'] == 1){ $view->headScript()->appendFile($baseUrl.'/js/libs/google-analytics.js?'.$CC_CONFIG['airtime_version'],'text/javascript'); } diff --git a/airtime_mvc/application/configs/constants.php b/airtime_mvc/application/configs/constants.php index e561650f4..a1c6c7e1a 100644 --- a/airtime_mvc/application/configs/constants.php +++ b/airtime_mvc/application/configs/constants.php @@ -2,7 +2,7 @@ define('AIRTIME_COPYRIGHT_DATE', '2010-2012'); define('AIRTIME_REST_VERSION', '1.1'); -define('AIRTIME_API_VERSION', '1.0'); +define('AIRTIME_API_VERSION', '1.1'); // Metadata Keys for files define('MDATA_KEY_FILEPATH', 'filepath'); diff --git a/airtime_mvc/application/controllers/ApiController.php b/airtime_mvc/application/controllers/ApiController.php index a20e4afb2..7be9d2817 100644 --- a/airtime_mvc/application/controllers/ApiController.php +++ b/airtime_mvc/application/controllers/ApiController.php @@ -262,30 +262,28 @@ class ApiController extends Zend_Controller_Action $request = $this->getRequest(); $type = $request->getParam('type'); if ($type == "endofday") { - // make getNextShows use end of day + $limit = $request->getParam('limit'); + if($limit == "" || !is_numeric($limit)) { + $limit = "5"; + } + + // make GetNextShows use end of day $utcTimeEnd = Application_Common_DateHelper::GetDayEndTimestampInUtc(); $result = array("env"=>APPLICATION_ENV, "schedulerTime"=>gmdate("Y-m-d H:i:s"), - "nextShow"=>Application_Model_Show::getNextShows($utcTimeNow, 5, $utcTimeEnd)); - + "nextShow"=>Application_Model_Show::getNextShows($utcTimeNow, $limit, $utcTimeEnd)); + Application_Model_Show::convertToLocalTimeZone($result["nextShow"], array("starts", "ends", "start_timestamp", "end_timestamp")); } else { - - $limit = $request->getParam('limit'); - if ($limit == "" || !is_numeric($limit)) { - $limit = "5"; - } - $result = Application_Model_Schedule::GetPlayOrderRange(); - //Convert from UTC to localtime for user. + //Convert from UTC to localtime for Web Browser. Application_Model_Show::convertToLocalTimeZone($result["currentShow"], array("starts", "ends", "start_timestamp", "end_timestamp")); Application_Model_Show::convertToLocalTimeZone($result["nextShow"], array("starts", "ends", "start_timestamp", "end_timestamp")); } $result['AIRTIME_API_VERSION'] = AIRTIME_API_VERSION; //used by caller to determine if the airtime they are running or widgets in use is out of date. - //echo json_encode($result); header("Content-type: text/javascript"); echo $_GET['callback'].'('.json_encode($result).')'; } else { diff --git a/airtime_mvc/application/controllers/LibraryController.php b/airtime_mvc/application/controllers/LibraryController.php index 918efdca5..91e0c9a69 100644 --- a/airtime_mvc/application/controllers/LibraryController.php +++ b/airtime_mvc/application/controllers/LibraryController.php @@ -125,28 +125,11 @@ class LibraryController extends Zend_Controller_Action } } - $hasPermission = true; - if (count($playlists)) { - // make sure use has permission to delete all playslists in the list - if (!$isAdminOrPM) { - foreach ($playlists as $pid) { - $pl = new Application_Model_Playlist($pid); - if ($pl->getCreatorId() != $user->getId()) { - $hasPermission = false; - } - } - } - } - - if (!$isAdminOrPM && count($files)) { - $hasPermission = false; - } - if (!$hasPermission) { - $this->view->message = "You don't have a permission to delete all playlists/files that are selected."; - + try { + Application_Model_Playlist::deletePlaylists($playlists, $user->getId()); + } catch (PlaylistNoPermissionException $e) { + $this->view->message = "You don't have permission to delete selected playlists/files."; return; - } else { - Application_Model_Playlist::DeletePlaylists($playlists); } foreach ($files as $id) { diff --git a/airtime_mvc/application/controllers/PlaylistController.php b/airtime_mvc/application/controllers/PlaylistController.php index c29b4e947..237bbb570 100644 --- a/airtime_mvc/application/controllers/PlaylistController.php +++ b/airtime_mvc/application/controllers/PlaylistController.php @@ -82,7 +82,7 @@ class PlaylistController extends Zend_Controller_Action } } - private function playlistOutdated($pl, $e) + private function playlistOutdated($e) { $this->view->error = $e->getMessage(); } @@ -95,6 +95,10 @@ class PlaylistController extends Zend_Controller_Action $this->changePlaylist(null); $this->createFullResponse(null); } + + private function playlistNoPermission(){ + $this->view->error = "You don't have permission to delete selected playlist(s)."; + } private function playlistUnknownError($e) { @@ -137,7 +141,13 @@ class PlaylistController extends Zend_Controller_Action try { if (isset($this->pl_sess->id)) { $pl = new Application_Model_Playlist($this->pl_sess->id); - $this->view->pl = $pl; + $userInfo = Zend_Auth::getInstance()->getStorage()->read(); + $user = new Application_Model_User($userInfo->id); + $isAdminOrPM = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER)); + + if($isAdminOrPM || $pl->getCreatorId() == $userInfo->id){ + $this->view->pl = $pl; + } $formatter = new LengthFormatter($pl->getLength()); $this->view->length = $formatter->format(); @@ -186,6 +196,9 @@ class PlaylistController extends Zend_Controller_Action $ids = $this->_getParam('ids'); $ids = (!is_array($ids)) ? array($ids) : $ids; $pl = null; + + $userInfo = Zend_Auth::getInstance()->getStorage()->read(); + $user = new Application_Model_User($userInfo->id); try { @@ -198,9 +211,13 @@ class PlaylistController extends Zend_Controller_Action $pl = new Application_Model_Playlist($this->pl_sess->id); } - Application_Model_Playlist::DeletePlaylists($ids); + Application_Model_Playlist::deletePlaylists($ids, $userInfo->id); $this->createFullResponse($pl); - } catch (PlaylistNotFoundException $e) { + } + catch (PlaylistNoPermissionException $e) { + $this->playlistNoPermission(); + } + catch (PlaylistNotFoundException $e) { $this->playlistNotFound(); } catch (Exception $e) { $this->playlistUnknownError($e); @@ -219,7 +236,7 @@ class PlaylistController extends Zend_Controller_Action $pl->addAudioClips($ids, $afterItem, $addType); $this->createUpdateResponse($pl); } catch (PlaylistOutDatedException $e) { - $this->playlistOutdated($pl, $e); + $this->playlistOutdated($e); } catch (PlaylistNotFoundException $e) { $this->playlistNotFound(); } catch (Exception $e) { @@ -239,7 +256,7 @@ class PlaylistController extends Zend_Controller_Action $pl->moveAudioClips($ids, $afterItem); $this->createUpdateResponse($pl); } catch (PlaylistOutDatedException $e) { - $this->playlistOutdated($pl, $e); + $this->playlistOutdated($e); } catch (PlaylistNotFoundException $e) { $this->playlistNotFound(); } catch (Exception $e) { @@ -258,7 +275,7 @@ class PlaylistController extends Zend_Controller_Action $pl->delAudioClips($ids); $this->createUpdateResponse($pl); } catch (PlaylistOutDatedException $e) { - $this->playlistOutdated($pl, $e); + $this->playlistOutdated($e); } catch (PlaylistNotFoundException $e) { $this->playlistNotFound(); } catch (Exception $e) { @@ -283,7 +300,7 @@ class PlaylistController extends Zend_Controller_Action $this->view->cue_error = $response["error"]; } } catch (PlaylistOutDatedException $e) { - $this->playlistOutdated($pl, $e); + $this->playlistOutdated($e); } catch (PlaylistNotFoundException $e) { $this->playlistNotFound(); } catch (Exception $e) { @@ -308,7 +325,7 @@ class PlaylistController extends Zend_Controller_Action $this->view->fade_error = $response["error"]; } } catch (PlaylistOutDatedException $e) { - $this->playlistOutdated($pl, $e); + $this->playlistOutdated($e); } catch (PlaylistNotFoundException $e) { $this->playlistNotFound(); } catch (Exception $e) { @@ -326,7 +343,7 @@ class PlaylistController extends Zend_Controller_Action $fades = $pl->getFadeInfo($pl->getSize()-1); $this->view->fadeOut = $fades[1]; } catch (PlaylistOutDatedException $e) { - $this->playlistOutdated($pl, $e); + $this->playlistOutdated($e); } catch (PlaylistNotFoundException $e) { $this->playlistNotFound(); } catch (Exception $e) { @@ -349,7 +366,7 @@ class PlaylistController extends Zend_Controller_Action $pl->setPlaylistfades($fadeIn, $fadeOut); $this->view->modified = $pl->getLastModified("U"); } catch (PlaylistOutDatedException $e) { - $this->playlistOutdated($pl, $e); + $this->playlistOutdated($e); } catch (PlaylistNotFoundException $e) { $this->playlistNotFound(); } catch (Exception $e) { @@ -367,7 +384,7 @@ class PlaylistController extends Zend_Controller_Action $this->view->playlistName = $name; $this->view->modified = $pl->getLastModified("U"); } catch (PlaylistOutDatedException $e) { - $this->playlistOutdated($pl, $e); + $this->playlistOutdated($e); } catch (PlaylistNotFoundException $e) { $this->playlistNotFound(); } catch (Exception $e) { @@ -385,7 +402,7 @@ class PlaylistController extends Zend_Controller_Action $this->view->description = $pl->getDescription(); $this->view->modified = $pl->getLastModified("U"); } catch (PlaylistOutDatedException $e) { - $this->playlistOutdated($pl, $e); + $this->playlistOutdated($e); } catch (PlaylistNotFoundException $e) { $this->playlistNotFound(); } catch (Exception $e) { diff --git a/airtime_mvc/application/models/Playlist.php b/airtime_mvc/application/models/Playlist.php index cabd17563..f02c13f5e 100644 --- a/airtime_mvc/application/models/Playlist.php +++ b/airtime_mvc/application/models/Playlist.php @@ -453,13 +453,14 @@ class Application_Model_Playlist ->filterByDbPlaylistId($this->id) ->filterByDbPosition($pos) ->findOne(); + + - #Propel returns values in form 00.000000 format which is for only seconds. - $fadeIn = $row->getDbFadein(); - $fadeOut = $row->getDbFadeout(); - - return array($fadeIn, $fadeOut); - } + #Propel returns values in form 00.000000 format which is for only seconds. + $fadeIn = $row->getDbFadein(); + $fadeOut = $row->getDbFadeout(); + return array($fadeIn, $fadeOut); + } /** * Change fadeIn and fadeOut values for playlist Element @@ -800,12 +801,33 @@ class Application_Model_Playlist * Delete playlists that match the ids.. * @param array $p_ids */ - public static function DeletePlaylists($p_ids) + public static function deletePlaylists($p_ids, $p_userId) { - CcPlaylistQuery::create()->findPKs($p_ids)->delete(); + $leftOver = self::playlistsNotOwnedByUser($p_ids, $p_userId); + if (count($leftOver) == 0) { + CcPlaylistQuery::create()->findPKs($p_ids)->delete(); + } else { + throw new PlaylistNoPermissionException; + } + } + + // This function returns that are not owen by $p_user_id among $p_ids + private static function playlistsNotOwnedByUser($p_ids, $p_userId){ + $ownedByUser = CcPlaylistQuery::create()->filterByDbCreatorId($p_userId)->find()->getData(); + $selectedPls = $p_ids; + $ownedPls = array(); + foreach ($ownedByUser as $pl) { + if (in_array($pl->getDbId(), $selectedPls)) { + $ownedPls[] = $pl->getDbId(); + } + } + + $leftOvers = array_diff($selectedPls, $ownedPls); + return $leftOvers; } } // class Playlist class PlaylistNotFoundException extends Exception {} +class PlaylistNoPermissionException extends Exception {} class PlaylistOutDatedException extends Exception {} diff --git a/airtime_mvc/application/models/Schedule.php b/airtime_mvc/application/models/Schedule.php index 91676bd09..2db022b50 100644 --- a/airtime_mvc/application/models/Schedule.php +++ b/airtime_mvc/application/models/Schedule.php @@ -32,6 +32,7 @@ class Application_Model_Schedule { if (!is_int($p_prev) || !is_int($p_next)) { //must enter integers to specify ranges + Logging::log("Invalid range parameters: $p_prev or $p_next"); return array(); } @@ -49,7 +50,6 @@ class Application_Model_Schedule "schedulerTime"=>$timeNow, "previous"=>$results['previous'] !=null?$results['previous']:(count($shows['previousShow'])>0?$shows['previousShow'][0]:null), "current"=>$results['current'] !=null?$results['current']:((count($shows['currentShow'])>0 && $shows['currentShow'][0]['record'] == 1)?$shows['currentShow'][0]:null), - //"current"=>$results['current'] !=null?$results['current']:(count($shows['currentShow'])>0?$shows['currentShow'][0]:null), "next"=> $results['next'] !=null?$results['next']:(count($shows['nextShow'])>0?$shows['nextShow'][0]:null), "currentShow"=>$shows['currentShow'], "nextShow"=>$shows['nextShow'], diff --git a/airtime_mvc/application/models/Show.php b/airtime_mvc/application/models/Show.php index 947077378..a415ccd8d 100644 --- a/airtime_mvc/application/models/Show.php +++ b/airtime_mvc/application/models/Show.php @@ -1876,9 +1876,9 @@ class Application_Model_Show /** * Given a start time $timeStart and end time $timeEnd, returns the next $limit - * number of shows within the time interval; - * If $timeEnd not given, shows within next 48 hours from $timeStart are returned; - * If $limit not given, all shows within the intervals are returns; + * number of shows within the time interval + * If $timeEnd not given, shows within next 48 hours from $timeStart are returned + * If $limit not given, all shows within the intervals are returned * Times are all in UTC time. * * @param String $timeStart - interval start time (in UTC) diff --git a/airtime_mvc/public/js/airtime/schedule/add-show.js b/airtime_mvc/public/js/airtime/schedule/add-show.js index d85742e4b..9e1d8e704 100644 --- a/airtime_mvc/public/js/airtime/schedule/add-show.js +++ b/airtime_mvc/public/js/airtime/schedule/add-show.js @@ -118,6 +118,14 @@ function stringToColor(s) return intToRGB(hashCode(s)); } +function getContrastYIQ(hexcolor){ + var r = parseInt(hexcolor.substr(0,2),16); + var g = parseInt(hexcolor.substr(2,2),16); + var b = parseInt(hexcolor.substr(4,2),16); + var yiq = ((r*299)+(g*587)+(b*114))/1000; + return (yiq >= 128) ? '000000' : 'ffffff'; +} + function setAddShowEvents() { @@ -578,9 +586,11 @@ function setAddShowEvents() { } var bgColorEle = $("#add_show_background_color"); + var textColorEle = $("#add_show_color"); $('#add_show_name').bind('input', 'change', function(){ var colorCode = stringToColor($(this).val()); bgColorEle.val(colorCode); + textColorEle.val(getContrastYIQ(colorCode)); }); } diff --git a/airtime_mvc/public/js/airtime/schedule/schedule.js b/airtime_mvc/public/js/airtime/schedule/schedule.js index 75e881bfd..94ca5702c 100644 --- a/airtime_mvc/public/js/airtime/schedule/schedule.js +++ b/airtime_mvc/public/js/airtime/schedule/schedule.js @@ -132,7 +132,7 @@ function findViewportDimensions() { return { width: viewportwidth, - height: viewportheight + height: viewportheight-45 }; } diff --git a/airtime_mvc/public/js/airtime/showbuilder/builder.js b/airtime_mvc/public/js/airtime/showbuilder/builder.js index b1834ec4f..0b45f0c65 100644 --- a/airtime_mvc/public/js/airtime/showbuilder/builder.js +++ b/airtime_mvc/public/js/airtime/showbuilder/builder.js @@ -1136,13 +1136,11 @@ var AIRTIME = (function(AIRTIME){ if (oItems.del !== undefined) { callback = function() { - if (confirm("Delete selected item?")) { - AIRTIME.showbuilder.fnRemove([{ - id: data.id, - timestamp: data.timestamp, - instance: data.instance - }]); - } + AIRTIME.showbuilder.fnRemove([{ + id: data.id, + timestamp: data.timestamp, + instance: data.instance + }]); }; oItems.del.callback = callback; diff --git a/install_minimal/airtime-install b/install_minimal/airtime-install index 86691c427..f7598d7e6 100755 --- a/install_minimal/airtime-install +++ b/install_minimal/airtime-install @@ -107,12 +107,28 @@ echo "* Making sure /etc/default/locale is set properly" set +e update-locale cat /etc/default/locale | grep -i "LANG=.*UTF-\?8" -set -e if [ "$?" != "0" ]; then - echo "non UTF-8 default locale found in /etc/default/locale." + echo -e " * Fail\n" + echo "A non UTF-8 default locale found in /etc/default/locale. Airtime requires +a UTF-8 locale to run. To fix this please do the following: + +Ubuntu: +Put line 'en_US.UTF-8 UTF-8' (or similar) without quotes to '/var/lib/locales/supported.d/local', +replacing any existing lines. +A list of supported locales is available in '/usr/share/i18n/SUPPORTED' +Then run 'sudo dpkg-reconfigure locales' + +Debian: +Run 'sudo dpkg-reconfigure locales' and use the interface to select 'en_US.UTF-8 UTF-8' (or similar). +On the second page select this new locale as the default. + +After these changes have been made simply run install again. + +Now exiting install... +" exit 1 fi - +set -e # Check if airtime exists already set +e @@ -133,13 +149,14 @@ if [ "$result" -eq "0" ]; then rm -f "/etc/airtime/media-monitor.cfg" rm -f "/etc/airtime/pypo.cfg" elif [ "$result" -eq "1" -a "$reinstall" = "f" ]; then - echo " * Same version of Airtime already installed!" - exit 1; + echo " * Same version of Airtime already installed! Reusing database." + nodb='t' + overwrite='f' elif [ "$result" -eq "2" ]; then - echo " * Previous version of Airtime already installed..will perform upgrade" + echo " * Previous version of Airtime already installed..will perform upgrade." DO_UPGRADE="1" elif [ "$result" -eq "3" ]; then - echo " * You require at least Airtime 1.8.0 installed for upgrade" + echo " * You require at least Airtime 1.8.0 installed for upgrade." exit 1 fi diff --git a/install_minimal/airtime-uninstall b/install_minimal/airtime-uninstall index b99f04246..78e9b03e4 100755 --- a/install_minimal/airtime-uninstall +++ b/install_minimal/airtime-uninstall @@ -6,6 +6,28 @@ if [[ $EUID -ne 0 ]]; then exit 1 fi + +options=$(getopt -o p -l purge -- "$@") +if [ $? -ne 0 ]; then + echo "only -p or --purge parameter allowed" + exit 1 +fi +eval set -- "$options" + +purge='f' + +while true +do + case "$1" in + -p|--purge) purge='t'; shift;; + --) shift 1; break ;; + *) break ;; + esac +done + +#Make 'purge' env variable available to sub bash script +export purge + echo -e "\n******************************* Uninstall Begin ********************************" # Absolute path to this script, e.g. /home/user/bin/foo.sh diff --git a/install_minimal/include/airtime-uninitialize.sh b/install_minimal/include/airtime-uninitialize.sh index 1713ae7f2..b5460285a 100755 --- a/install_minimal/include/airtime-uninitialize.sh +++ b/install_minimal/include/airtime-uninitialize.sh @@ -19,7 +19,6 @@ set +e monit unmonitor airtime-media-monitor >/dev/null 2>&1 monit unmonitor airtime-liquidsoap >/dev/null 2>&1 monit unmonitor airtime-playout >/dev/null 2>&1 -#monit unmonitor airtime-show-recorder >/dev/null 2>&1 monit unmonitor rabbitmq-server set -e @@ -31,5 +30,7 @@ python $AIRTIMEROOT/python_apps/pypo/install/pypo-uninitialize.py python $AIRTIMEROOT/python_apps/media-monitor/install/media-monitor-uninitialize.py #python $AIRTIMEROOT/python_apps/show-recorder/install/recorder-uninitialize.py +if [ "$purge" = "t" ]; then #call Airtime uninstall script php --php-ini ${SCRIPTPATH}/../airtime-php.ini ${SCRIPTPATH}/airtime-uninstall.php +fi diff --git a/python_apps/api_clients/api_client.py b/python_apps/api_clients/api_client.py index 4eb4ff34f..91564ce01 100644 --- a/python_apps/api_clients/api_client.py +++ b/python_apps/api_clients/api_client.py @@ -39,7 +39,7 @@ def convert_dict_value_to_utf8(md): # Airtime API Client ################################################################################ -class AirTimeApiClient(): +class AirtimeApiClient(): def __init__(self, logger=None): if logger is None: @@ -437,10 +437,14 @@ class AirTimeApiClient(): response = self.get_response_from_server(url) response = json.loads(response) except Exception, e: - response = None + response = {} logger.error("Exception: %s", e) - return response + try: + return response["files"] + except KeyError: + self.logger.error("Could not find index 'files' in dictionary: %s", str(response)) + return [] def list_all_watched_dirs(self): logger = self.logger diff --git a/python_apps/media-monitor/airtimefilemonitor/airtimemediamonitorbootstrap.py b/python_apps/media-monitor/airtimefilemonitor/airtimemediamonitorbootstrap.py index a44a5cae8..7a57a74e6 100644 --- a/python_apps/media-monitor/airtimefilemonitor/airtimemediamonitorbootstrap.py +++ b/python_apps/media-monitor/airtimefilemonitor/airtimemediamonitorbootstrap.py @@ -40,8 +40,7 @@ class AirtimeMediaMonitorBootstrap(): went offline. """ def scan(self): - directories = self.get_list_of_watched_dirs(); - + directories = self.get_list_of_watched_dirs() self.logger.info("watched directories found: %s", directories) for id, dir in directories.iteritems(): @@ -57,12 +56,21 @@ class AirtimeMediaMonitorBootstrap(): return self.api_client.list_all_db_files(dir_id) """ - returns the path and the database row id for this path for all watched directories. Also + returns the path and its corresponding database row idfor all watched directories. Also returns the Stor directory, which can be identified by its row id (always has value of "1") + + Return type is a dictionary similar to: + {"1":"/srv/airtime/stor/"} """ def get_list_of_watched_dirs(self): json = self.api_client.list_all_watched_dirs() - return json["dirs"] + + try: + return json["dirs"] + except KeyError as e: + self.logger.error("Could not find index 'dirs' in dictionary: %s", str(json)) + self.logger.error(e) + return {} """ This function takes in a path name provided by the database (and its corresponding row id) @@ -86,8 +94,9 @@ class AirtimeMediaMonitorBootstrap(): db_known_files_set = set() files = self.list_db_files(dir_id) - for file in files['files']: - db_known_files_set.add(file) + + for f in files: + db_known_files_set.add(f) all_files = self.mmc.clean_dirty_file_paths( self.mmc.scan_dir_for_new_files(dir) ) @@ -111,10 +120,9 @@ class AirtimeMediaMonitorBootstrap(): stdout = self.mmc.exec_command(command) if stdout is None: - self.logger.error("Unrecoverable error when syncing db to filesystem.") - return - - new_files = self.mmc.clean_dirty_file_paths(stdout.splitlines()) + new_files = [] + else: + new_files = stdout.splitlines() new_and_modified_files = set() for file_path in new_files: diff --git a/python_apps/media-monitor/airtimefilemonitor/airtimemetadata.py b/python_apps/media-monitor/airtimefilemonitor/airtimemetadata.py index 7df87f546..f2963bea9 100644 --- a/python_apps/media-monitor/airtimefilemonitor/airtimemetadata.py +++ b/python_apps/media-monitor/airtimefilemonitor/airtimemetadata.py @@ -12,8 +12,17 @@ import traceback """ list of supported easy tags in mutagen version 1.20 -['albumartistsort', 'musicbrainz_albumstatus', 'lyricist', 'releasecountry', 'date', 'performer', 'musicbrainz_albumartistid', 'composer', 'encodedby', 'tracknumber', 'musicbrainz_albumid', 'album', 'asin', 'musicbrainz_artistid', 'mood', 'copyright', 'author', 'media', 'length', 'version', 'artistsort', 'titlesort', 'discsubtitle', 'website', 'musicip_fingerprint', 'conductor', 'compilation', 'barcode', 'performer:*', 'composersort', 'musicbrainz_discid', 'musicbrainz_albumtype', 'genre', 'isrc', 'discnumber', 'musicbrainz_trmid', 'replaygain_*_gain', 'musicip_puid', 'artist', 'title', 'bpm', 'musicbrainz_trackid', 'arranger', 'albumsort', 'replaygain_*_peak', 'organization'] +['albumartistsort', 'musicbrainz_albumstatus', 'lyricist', 'releasecountry', +'date', 'performer', 'musicbrainz_albumartistid', 'composer', 'encodedby', +'tracknumber', 'musicbrainz_albumid', 'album', 'asin', 'musicbrainz_artistid', +'mood', 'copyright', 'author', 'media', 'length', 'version', 'artistsort', +'titlesort', 'discsubtitle', 'website', 'musicip_fingerprint', 'conductor', +'compilation', 'barcode', 'performer:*', 'composersort', 'musicbrainz_discid', +'musicbrainz_albumtype', 'genre', 'isrc', 'discnumber', 'musicbrainz_trmid', +'replaygain_*_gain', 'musicip_puid', 'artist', 'title', 'bpm', 'musicbrainz_trackid', +'arranger', 'albumsort', 'replaygain_*_peak', 'organization'] """ + class AirtimeMetadata: def __init__(self): @@ -57,10 +66,17 @@ class AirtimeMetadata: self.logger = logging.getLogger() def get_md5(self, filepath): - f = open(filepath, 'rb') - m = hashlib.md5() - m.update(f.read()) - md5 = m.hexdigest() + """ + Returns an md5 of the file located at filepath. Returns an empty string + if there was an error reading the file. + """ + try: + f = open(filepath, 'rb') + m = hashlib.md5() + m.update(f.read()) + md5 = m.hexdigest() + except Exception, e: + return "" return md5 @@ -121,6 +137,10 @@ class AirtimeMetadata: return item def get_md_from_file(self, filepath): + """ + Returns None if error retrieving metadata. Otherwise returns a dictionary + representing the file's metadata + """ self.logger.info("getting info from filepath %s", filepath) @@ -136,7 +156,6 @@ class AirtimeMetadata: md['MDATA_KEY_MD5'] = md5 file_info = mutagen.File(filepath, easy=True) - except Exception, e: self.logger.error("failed getting metadata from %s", filepath) self.logger.error("Exception %s", e) @@ -146,18 +165,16 @@ class AirtimeMetadata: #check if file has any metadata if file_info is None: return None - #check if file has any metadata - if file_info is not None: - for key in file_info.keys() : - if key in self.mutagen2airtime: - val = file_info[key] - try: - if val is not None and len(val) > 0 and val[0] is not None and len(val[0]) > 0: - md[self.mutagen2airtime[key]] = val[0] - except Exception, e: - self.logger.error('Exception: %s', e) - self.logger.error("traceback: %s", traceback.format_exc()) + for key in file_info.keys() : + if key in self.mutagen2airtime: + val = file_info[key] + try: + if val is not None and len(val) > 0 and val[0] is not None and len(val[0]) > 0: + md[self.mutagen2airtime[key]] = val[0] + 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) @@ -228,18 +245,24 @@ class AirtimeMetadata: md['MDATA_KEY_COPYRIGHT'] = self.truncate_to_length(md['MDATA_KEY_COPYRIGHT'], 512) #end of db truncation checks. - 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']) - 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)) - - try: md['MDATA_KEY_MIME'] = file_info.mime[0] - except Exception as e: self.logger.warn("File: '%s' has no mime type", filepath, str(e)) + try: + md['MDATA_KEY_BITRATE'] = getattr(file_info.info, "bitrate", 0) + md['MDATA_KEY_SAMPLERATE'] = getattr(file_info.info, "sample_rate", 0) + + md['MDATA_KEY_DURATION'] = self.format_length(getattr(file_info.info, "length", 0.0)) + + md['MDATA_KEY_MIME'] = "" + if len(file_info.mime) > 0: + md['MDATA_KEY_MIME'] = file_info.mime[0] + except Exception as e: + self.logger.warn(e) if "mp3" in md['MDATA_KEY_MIME']: md['MDATA_KEY_FTYPE'] = "audioclip" elif "vorbis" in md['MDATA_KEY_MIME']: md['MDATA_KEY_FTYPE'] = "audioclip" + else: + self.logger.error("File %s of mime type %s does not appear to be a valid vorbis or mp3 file." % (filepath, md['MDATA_KEY_MIME'])) + return None return md diff --git a/python_apps/media-monitor/airtimefilemonitor/airtimenotifier.py b/python_apps/media-monitor/airtimefilemonitor/airtimenotifier.py index 03e389382..1077f5abb 100644 --- a/python_apps/media-monitor/airtimefilemonitor/airtimenotifier.py +++ b/python_apps/media-monitor/airtimefilemonitor/airtimenotifier.py @@ -36,6 +36,11 @@ class AirtimeNotifier(Notifier): time.sleep(5) def init_rabbit_mq(self): + """ + This function will attempt to connect to RabbitMQ Server and if successful + return 'True'. Returns 'False' otherwise. + """ + self.logger.info("Initializing RabbitMQ stuff") try: schedule_exchange = Exchange("airtime-media-monitor", "direct", durable=True, auto_delete=True) diff --git a/python_apps/media-monitor/airtimefilemonitor/mediamonitorcommon.py b/python_apps/media-monitor/airtimefilemonitor/mediamonitorcommon.py index 00b060267..c298ccf84 100644 --- a/python_apps/media-monitor/airtimefilemonitor/mediamonitorcommon.py +++ b/python_apps/media-monitor/airtimefilemonitor/mediamonitorcommon.py @@ -291,7 +291,10 @@ class MediaMonitorCommon: self.logger.debug(command) stdout = self.exec_command(command) - return stdout.splitlines() + if stdout is None: + return [] + else: + return stdout.splitlines() def touch_index_file(self): dirname = os.path.dirname(self.timestamp_file) diff --git a/python_apps/media-monitor/media_monitor.py b/python_apps/media-monitor/media_monitor.py index 84af612de..de286994a 100644 --- a/python_apps/media-monitor/media_monitor.py +++ b/python_apps/media-monitor/media_monitor.py @@ -80,7 +80,7 @@ try: configure_locale() config = AirtimeMediaConfig(logger) - api_client = apc.AirTimeApiClient() + api_client = apc.AirtimeApiClient() api_client.register_component("media-monitor") logger.info("Setting up monitor") diff --git a/python_apps/media-monitor2/media/update/replaygainupdater.py b/python_apps/media-monitor2/media/update/replaygainupdater.py index f144502ed..807559a15 100644 --- a/python_apps/media-monitor2/media/update/replaygainupdater.py +++ b/python_apps/media-monitor2/media/update/replaygainupdater.py @@ -23,7 +23,7 @@ class ReplayGainUpdater(Thread): def __init__(self, logger): Thread.__init__(self) self.logger = logger - self.api_client = api_client.AirTimeApiClient() + self.api_client = api_client.AirtimeApiClient() def main(self): diff --git a/python_apps/pypo/airtime-playout-init-d b/python_apps/pypo/airtime-playout-init-d index 0723a657d..c2e27f320 100755 --- a/python_apps/pypo/airtime-playout-init-d +++ b/python_apps/pypo/airtime-playout-init-d @@ -73,7 +73,7 @@ monit_restart() { start-stop-daemon --stop --oknodo --retry TERM/5/0/30 --quiet --pidfile $PIDFILE1 rm -f $PIDFILE1 - start-stop-daemon --start --background --quiet --chuid $USERID:$GROUPID --make-pidfile --pidfile $PIDFILE0 --startas $DAEMON0 + start-stop-daemon --start --background --quiet --chuid $ROOTUSERID:$ROOTUSERID --make-pidfile --pidfile $PIDFILE0 --startas $DAEMON0 start-stop-daemon --start --background --quiet --chuid $USERID:$GROUPID \ --nicelevel -15 --make-pidfile --pidfile $PIDFILE1 --startas $DAEMON1 diff --git a/python_apps/pypo/liquidsoap_scripts/generate_liquidsoap_cfg.py b/python_apps/pypo/liquidsoap_scripts/generate_liquidsoap_cfg.py index ad73c71ad..2ecda5aca 100644 --- a/python_apps/pypo/liquidsoap_scripts/generate_liquidsoap_cfg.py +++ b/python_apps/pypo/liquidsoap_scripts/generate_liquidsoap_cfg.py @@ -1,6 +1,6 @@ import logging import sys -from api_clients import api_client +from api_clients.api_client import AirtimeApiClient def generate_liquidsoap_config(ss): data = ss['msg'] @@ -9,22 +9,22 @@ def generate_liquidsoap_config(ss): fh.write("# THIS FILE IS AUTO GENERATED. DO NOT CHANGE!! #\n") fh.write("################################################\n") for d in data: + + key = d['keyname'] + str_buffer = d[u'keyname'] + " = " if(d[u'type'] == 'string'): - temp = d[u'value'] - str_buffer += '"%s"' % temp + val = '"%s"' % d['value'] else: - temp = d[u'value'] - if(temp == ""): - temp = "0" - str_buffer += temp - str_buffer += "\n" - fh.write(api_client.encode_to(str_buffer)) + val = d[u'value'] + val = val if len(val) > 0 else "0" + str_buffer = "%s = %s\n" % (key, val) + fh.write(str_buffer.encode('utf-8')) fh.write('log_file = "/var/log/airtime/pypo-liquidsoap/