diff --git a/airtime_mvc/application/configs/conf.php b/airtime_mvc/application/configs/conf.php
index dc3e03a2b..fcdece4bc 100644
--- a/airtime_mvc/application/configs/conf.php
+++ b/airtime_mvc/application/configs/conf.php
@@ -62,6 +62,8 @@ class Config {
$CC_CONFIG['baseUrl'] = $values['general']['base_url'];
$CC_CONFIG['basePort'] = $values['general']['base_port'];
+ $CC_CONFIG['cache_ahead_hours'] = $values['general']['cache_ahead_hours'];
+
// Database config
$CC_CONFIG['dsn']['username'] = $values['database']['dbuser'];
$CC_CONFIG['dsn']['password'] = $values['database']['dbpass'];
diff --git a/airtime_mvc/application/controllers/ApiController.php b/airtime_mvc/application/controllers/ApiController.php
index d32f2ad30..5a0d53cd9 100644
--- a/airtime_mvc/application/controllers/ApiController.php
+++ b/airtime_mvc/application/controllers/ApiController.php
@@ -150,8 +150,11 @@ class ApiController extends Zend_Controller_Action
//user clicks play button for track and downloads it.
header('Content-Disposition: inline; filename="'.$file_base_name.'"');
}
-
- $this->smartReadFile($filepath, 'audio/'.$ext);
+ if ($ext === 'mp3'){
+ $this->smartReadFile($filepath, 'audio/mpeg');
+ } else {
+ $this->smartReadFile($filepath, 'audio/'.$ext);
+ }
exit;
}else{
header ("HTTP/1.1 404 Not Found");
diff --git a/airtime_mvc/application/controllers/PreferenceController.php b/airtime_mvc/application/controllers/PreferenceController.php
index d13cd678d..607592217 100644
--- a/airtime_mvc/application/controllers/PreferenceController.php
+++ b/airtime_mvc/application/controllers/PreferenceController.php
@@ -232,6 +232,9 @@ class PreferenceController extends Zend_Controller_Action
$this->view->statusMsg = "
Stream Setting Updated.
";
}
}
+
+ $this->view->confirm_pypo_restart_text = "Updating settings will temporarily interrupt any currently playing shows. Click \'OK\' to continue.";
+
$this->view->num_stream = $num_of_stream;
$this->view->enable_stream_conf = Application_Model_Preference::GetEnableStreamConf();
$this->view->form = $form;
diff --git a/airtime_mvc/application/controllers/ScheduleController.php b/airtime_mvc/application/controllers/ScheduleController.php
index 57c285835..583f97f49 100644
--- a/airtime_mvc/application/controllers/ScheduleController.php
+++ b/airtime_mvc/application/controllers/ScheduleController.php
@@ -778,15 +778,13 @@ class ScheduleController extends Zend_Controller_Action
try {
$showInstance = new Application_Model_ShowInstance($showInstanceId);
- }
- catch(Exception $e){
+ } catch(Exception $e) {
$this->view->show_error = true;
return false;
}
$show = new Application_Model_Show($showInstance->getShowId());
$show->cancelShow($showInstance->getShowInstanceStart());
-
$this->view->show_id = $showInstance->getShowId();
}
}
@@ -806,8 +804,8 @@ class ScheduleController extends Zend_Controller_Action
}
$showInstance->clearShow();
$showInstance->delete();
- // send 'cancel-current-show' command to pypo
- Application_Model_RabbitMq::SendMessageToPypo("cancel_current_show", array());
+
+ Application_Model_RabbitMq::PushSchedule();
}
}
diff --git a/airtime_mvc/application/models/Schedule.php b/airtime_mvc/application/models/Schedule.php
index b924ee4c0..204d5d983 100644
--- a/airtime_mvc/application/models/Schedule.php
+++ b/airtime_mvc/application/models/Schedule.php
@@ -64,14 +64,16 @@ class Application_Model_Schedule {
$utcTimeNow = $date->getUtcTimestamp();
$shows = Application_Model_Show::getPrevCurrentNext($utcTimeNow);
+ $previousShowID = count($shows['previousShow'])>0?$shows['previousShow'][0]['id']:null;
$currentShowID = count($shows['currentShow'])>0?$shows['currentShow'][0]['id']:null;
- $results = Application_Model_Schedule::GetPrevCurrentNext($currentShowID, $utcTimeNow);
+ $nextShowID = count($shows['nextShow'])>0?$shows['nextShow'][0]['id']:null;
+ $results = Application_Model_Schedule::GetPrevCurrentNext($previousShowID, $currentShowID, $nextShowID, $utcTimeNow);
$range = array("env"=>APPLICATION_ENV,
"schedulerTime"=>$timeNow,
- "previous"=>isset($results['previous'])?$results['previous']:(count($shows['previousShow'])>0?$shows['previousShow'][0]:null),
- "current"=>isset($results['current'])?$results['current']:null,
- "next"=> isset($results['next'])?$results['next']:(count($shows['nextShow'])>0?$shows['nextShow'][0]:null),
+ "previous"=>$results['previous'] !=null?$results['previous']:(count($shows['previousShow'])>0?$shows['previousShow'][0]:null),
+ "current"=>$results['current'] !=null?$results['current']:null,
+ "next"=> $results['next'] !=null?$results['next']:(count($shows['nextShow'])>0?$shows['nextShow'][0]:null),
"currentShow"=>$shows['currentShow'],
"nextShow"=>$shows['nextShow'],
"timezone"=> date("T"),
@@ -88,19 +90,39 @@ class Application_Model_Schedule {
* show types are not found through this mechanism a call is made to the old way of querying
* the database to find the track info.
**/
- public static function GetPrevCurrentNext($p_currentShowID, $p_timeNow)
+ public static function GetPrevCurrentNext($p_previousShowID, $p_currentShowID, $p_nextShowID, $p_timeNow)
{
+ if ($p_previousShowID == null && $p_currentShowID == null && $p_nextShowID == null)
+ return;
+
global $CC_CONFIG, $CC_DBC;
-
- if (!isset($p_currentShowID)) {
- return array();
- }
- $sql = "Select ft.artist_name, ft.track_title, st.starts as starts, st.ends as ends, st.media_item_played as media_item_played
+ $sql = 'Select ft.artist_name, ft.track_title, st.starts as starts, st.ends as ends, st.media_item_played as media_item_played
FROM cc_schedule st LEFT JOIN cc_files ft ON st.file_id = ft.id
- WHERE st.instance_id = '$p_currentShowID' AND st.playout_status > 0
- ORDER BY st.starts";
+ WHERE ';
+
+ if (isset($p_previousShowID)){
+ if (isset($p_nextShowID) || isset($p_currentShowID))
+ $sql .= '(';
+ $sql .= 'st.instance_id = '.$p_previousShowID;
+ }
+ if ($p_currentShowID != null){
+ if ($p_previousShowID != null)
+ $sql .= ' OR ';
+ else if($p_nextShowID != null)
+ $sql .= '(';
+ $sql .= 'st.instance_id = '.$p_currentShowID;
+ }
+ if ($p_nextShowID != null) {
+ if ($p_previousShowID != null || $p_currentShowID != null)
+ $sql .= ' OR ';
+ $sql .= 'st.instance_id = '.$p_nextShowID;
+ if($p_previousShowID != null || $p_currentShowID != null)
+ $sql .= ')';
+ } else if($p_previousShowID != null && $p_currentShowID != null)
+ $sql .= ')';
+
+ $sql .= ' AND st.playout_status > 0 ORDER BY st.starts';
- //Logging::log($sql);
$rows = $CC_DBC->GetAll($sql);
$numberOfRows = count($rows);
@@ -587,7 +609,17 @@ class Application_Model_Schedule {
}
if (is_null($p_fromDateTime)) {
$t2 = new DateTime("@".time());
- $t2->add(new DateInterval("PT30M"));
+
+ $cache_ahead_hours = $CC_CONFIG["cache_ahead_hours"];
+
+ if (is_numeric($cache_ahead_hours)){
+ //make sure we are not dealing with a float
+ $cache_ahead_hours = intval($cache_ahead_hours);
+ } else {
+ $cache_ahead_hours = 1;
+ }
+
+ $t2->add(new DateInterval("PT".$cache_ahead_hours."H"));
$range_end = $t2->format("Y-m-d H:i:s");
} else {
$range_end = Application_Model_Schedule::PypoTimeToAirtimeTime($p_toDateTime);
diff --git a/airtime_mvc/application/models/Show.php b/airtime_mvc/application/models/Show.php
index afd9255b7..762ace161 100644
--- a/airtime_mvc/application/models/Show.php
+++ b/airtime_mvc/application/models/Show.php
@@ -199,9 +199,6 @@ class Application_Model_Show {
->filterByDbShowId($this->_showId)
->update(array('DbLastShow' => $timeinfo[0]));
- //$sql = "DELETE FROM cc_show_instances
- // WHERE starts >= '{$day_timestamp}' AND show_id = {$this->_showId}";
-
$sql = "UPDATE cc_show_instances
SET modified_instance = TRUE
WHERE starts >= '{$day_timestamp}' AND show_id = {$this->_showId}";
@@ -1762,7 +1759,9 @@ class Application_Model_Show {
//Find the show that is within the current time.
if ((strtotime($rows[$i]['starts']) <= $timeNowAsMillis) && (strtotime($rows[$i]['ends']) >= $timeNowAsMillis)){
if ( $i - 1 >= 0){
- $results['previousShow'][0] = array("name"=>$rows[$i-1]['name'],
+ $results['previousShow'][0] = array(
+ "id"=>$rows[$i-1]['id'],
+ "name"=>$rows[$i-1]['name'],
"start_timestamp"=>$rows[$i-1]['start_timestamp'],
"end_timestamp"=>$rows[$i-1]['end_timestamp'],
"starts"=>$rows[$i-1]['starts'],
@@ -1772,7 +1771,9 @@ class Application_Model_Show {
$results['currentShow'][0] = $rows[$i];
if ( isset($rows[$i+1])){
- $results['nextShow'][0] = array("name"=>$rows[$i+1]['name'],
+ $results['nextShow'][0] = array(
+ "id"=>$rows[$i+1]['id'],
+ "name"=>$rows[$i+1]['name'],
"start_timestamp"=>$rows[$i+1]['start_timestamp'],
"end_timestamp"=>$rows[$i+1]['end_timestamp'],
"starts"=>$rows[$i+1]['starts'],
@@ -1787,7 +1788,9 @@ class Application_Model_Show {
}
//if we hit this we know we've gone to far and can stop looping.
if (strtotime($rows[$i]['starts']) > $timeNowAsMillis) {
- $results['nextShow'][0] = array("name"=>$rows[$i]['name'],
+ $results['nextShow'][0] = array(
+ "id"=>$rows[$i]['id'],
+ "name"=>$rows[$i]['name'],
"start_timestamp"=>$rows[$i]['start_timestamp'],
"end_timestamp"=>$rows[$i]['end_timestamp'],
"starts"=>$rows[$i]['starts'],
@@ -1798,7 +1801,9 @@ class Application_Model_Show {
//If we didn't find a a current show because the time didn't fit we may still have
//found a previous show so use it.
if (count($results['previousShow']) == 0 && isset($previousShowIndex)) {
- $results['previousShow'][0] = array("name"=>$rows[$previousShowIndex]['name'],
+ $results['previousShow'][0] = array(
+ "id"=>$rows[$previousShowIndex]['id'],
+ "name"=>$rows[$previousShowIndex]['name'],
"start_timestamp"=>$rows[$previousShowIndex]['start_timestamp'],
"end_timestamp"=>$rows[$previousShowIndex]['end_timestamp'],
"starts"=>$rows[$previousShowIndex]['starts'],
diff --git a/airtime_mvc/application/views/scripts/preference/stream-setting.phtml b/airtime_mvc/application/views/scripts/preference/stream-setting.phtml
index 58332bde8..ed88f61e0 100644
--- a/airtime_mvc/application/views/scripts/preference/stream-setting.phtml
+++ b/airtime_mvc/application/views/scripts/preference/stream-setting.phtml
@@ -1,7 +1,7 @@
enable_stream_conf == "true"){?>style="float:left">Stream Settings
enable_stream_conf == "true"){?>
-
-
\ No newline at end of file
+
diff --git a/airtime_mvc/build/airtime.conf b/airtime_mvc/build/airtime.conf
index b11e672ce..2c36648ed 100644
--- a/airtime_mvc/build/airtime.conf
+++ b/airtime_mvc/build/airtime.conf
@@ -18,6 +18,10 @@ airtime_dir = x
base_url = localhost
base_port = 80
+#How many hours ahead of time should Airtime playout engine (PYPO)
+#cache scheduled media files.
+cache_ahead_hours = 1
+
[soundcloud]
connection_retries = 3
time_between_retries = 60
diff --git a/airtime_mvc/public/js/jplayer/preview_jplayer.js b/airtime_mvc/public/js/jplayer/preview_jplayer.js
index 2f6c2bd6f..e954a74b5 100644
--- a/airtime_mvc/public/js/jplayer/preview_jplayer.js
+++ b/airtime_mvc/public/js/jplayer/preview_jplayer.js
@@ -8,16 +8,22 @@ var _idToPostionLookUp;
*/
$(document).ready(function(){
+ if (useFlash())
+ mySupplied = "oga, mp3, m4v";
+ else
+ mySupplied = "oga, mp3";
+
_playlist_jplayer = new jPlayerPlaylist({
jPlayer: "#jquery_jplayer_1",
cssSelectorAncestor: "#jp_container_1"
},[], //array of songs will be filled with below's json call
{
swfPath: "/js/jplayer",
- //supplied: "mp3,oga",
+ supplied:mySupplied,
wmode: "window"
});
+
$.jPlayer.timeFormat.showHour = true;
var audioFileID = $('.audioFileID').text();
@@ -35,6 +41,10 @@ $(document).ready(function(){
}
});
+function useFlash() {
+ console.log(navigator.userAgent);
+ return navigator.userAgent.toLowerCase().match('firefox');
+}
/**
* Sets up the jPlayerPlaylist to play.
* - Get the playlist info based on the playlistID give.
@@ -122,7 +132,7 @@ function play(p_playlistIndex){
function playOne(p_audioFileID) {
var playlist = new Array();
var fileExtensioin = p_audioFileID.split('.').pop();
-
+ console.log(p_audioFileID);
if (fileExtensioin === 'mp3') {
media = {title: $('.audioFileTitle').text() !== 'null' ?$('.audioFileTitle').text():"",
artist: $('.audioFileArtist').text() !== 'null' ?$('.audioFileArtist').text():"",
@@ -135,7 +145,7 @@ function playOne(p_audioFileID) {
};
}
_playlist_jplayer.option("autoPlay", true);
-
+ console.log(media);
playlist[0] = media;
//_playlist_jplayer.setPlaylist(playlist); --if I use this the player will call _init on the setPlaylist and on the ready
_playlist_jplayer._initPlaylist(playlist);
diff --git a/dev_tools/compare_cc_files_to_fs.py b/dev_tools/compare_cc_files_to_fs.py
new file mode 100644
index 000000000..3f35fc033
--- /dev/null
+++ b/dev_tools/compare_cc_files_to_fs.py
@@ -0,0 +1,131 @@
+import os
+import time
+import shutil
+import sys
+import logging
+
+from configobj import ConfigObj
+from subprocess import Popen, PIPE
+from api_clients import api_client as apc
+
+"""
+The purpose of this script is that you can run it, and it will compare what the database has to what your filesystem
+has. It will then report if there are any differences. It will *NOT* make any changes, unlike media-monitor which uses
+similar code when it starts up (but then makes changes if something is different)
+"""
+
+
+class AirtimeMediaMonitorBootstrap():
+
+ """AirtimeMediaMonitorBootstrap constructor
+
+ Keyword Arguments:
+ logger -- reference to the media-monitor logging facility
+ pe -- reference to an instance of ProcessEvent
+ api_clients -- reference of api_clients to communicate with airtime-server
+ """
+ def __init__(self):
+ config = ConfigObj('/etc/airtime/media-monitor.cfg')
+ self.api_client = apc.api_client_factory(config)
+
+ """
+ try:
+ logging.config.fileConfig("logging.cfg")
+ except Exception, e:
+ print 'Error configuring logging: ', e
+ sys.exit(1)
+ """
+
+ self.logger = logging.getLogger()
+ self.logger.info("Adding %s on watch list...", "xxx")
+
+ self.scan()
+
+ """On bootup we want to scan all directories and look for files that
+ weren't there or files that changed before media-monitor process
+ went offline.
+ """
+ def scan(self):
+ directories = self.get_list_of_watched_dirs();
+
+ self.logger.info("watched directories found: %s", directories)
+
+ for id, dir in directories.iteritems():
+ self.logger.debug("%s, %s", id, dir)
+ #CHANGED!!!
+ #self.sync_database_to_filesystem(id, api_client.encode_to(dir, "utf-8"))
+ self.sync_database_to_filesystem(id, dir)
+
+ """Gets a list of files that the Airtime database knows for a specific directory.
+ You need to provide the directory's row ID, which is obtained when calling
+ get_list_of_watched_dirs function.
+ dir_id -- row id of the directory in the cc_watched_dirs database table
+ """
+ def list_db_files(self, dir_id):
+ 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 Stor directory, which can be identified by its row id (always has value of "1")
+ """
+ def get_list_of_watched_dirs(self):
+ json = self.api_client.list_all_watched_dirs()
+ return json["dirs"]
+
+ def scan_dir_for_existing_files(self, dir):
+ command = 'find "%s" -type f -iname "*.ogg" -o -iname "*.mp3" -readable' % dir.replace('"', '\\"')
+ self.logger.debug(command)
+ #CHANGED!!
+ stdout = self.exec_command(command).decode("UTF-8")
+
+ return stdout.splitlines()
+
+ def exec_command(self, command):
+ p = Popen(command, shell=True, stdout=PIPE, stderr=PIPE)
+ stdout, stderr = p.communicate()
+ if p.returncode != 0:
+ self.logger.warn("command \n%s\n return with a non-zero return value", command)
+ self.logger.error(stderr)
+ return stdout
+
+ """
+ This function takes in a path name provided by the database (and its corresponding row id)
+ and reads the list of files in the local file system. Its purpose is to discover which files
+ exist on the file system but not in the database and vice versa, as well as which files have
+ been modified since the database was last updated. In each case, this method will call an
+ appropiate method to ensure that the database actually represents the filesystem.
+ dir_id -- row id of the directory in the cc_watched_dirs database table
+ dir -- pathname of the directory
+ """
+ def sync_database_to_filesystem(self, dir_id, 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
+ mutually exclusive from each other.
+ """
+ db_known_files_set = set()
+
+ files = self.list_db_files(dir_id)
+ for file in files['files']:
+ db_known_files_set.add(file)
+
+ existing_files = self.scan_dir_for_existing_files(dir)
+
+ existing_files_set = set()
+ for file_path in existing_files:
+ if len(file_path.strip(" \n")) > 0:
+ existing_files_set.add(file_path[len(dir):])
+
+
+ deleted_files_set = db_known_files_set - existing_files_set
+ new_files_set = existing_files_set - db_known_files_set
+
+
+ print ("DB Known files: \n%s\n\n"%len(db_known_files_set))
+ print ("FS Known files: \n%s\n\n"%len(existing_files_set))
+
+ print ("Deleted files: \n%s\n\n"%deleted_files_set)
+ print ("New files: \n%s\n\n"%new_files_set)
+
+if __name__ == "__main__":
+ AirtimeMediaMonitorBootstrap()
diff --git a/dev_tools/fabric/fab_liquidsoap_compile.cfg b/dev_tools/fabric/fab_liquidsoap_compile.cfg
new file mode 100644
index 000000000..bf6d462d8
--- /dev/null
+++ b/dev_tools/fabric/fab_liquidsoap_compile.cfg
@@ -0,0 +1,2 @@
+[main]
+liquidsoap_tar_url = http://dl.dropbox.com/u/256410/airtime/liquidsoap.tar.gz
diff --git a/dev_tools/fabric/fab_liquidsoap_compile.py b/dev_tools/fabric/fab_liquidsoap_compile.py
index 68064395d..06ca05730 100644
--- a/dev_tools/fabric/fab_liquidsoap_compile.py
+++ b/dev_tools/fabric/fab_liquidsoap_compile.py
@@ -10,6 +10,8 @@ import sys
from fabric.api import *
from fabric.contrib.files import comment, sed, append
+from ConfigParser import ConfigParser
+
from xml.dom.minidom import parse
from xml.dom.minidom import Node
from xml.dom.minidom import Element
@@ -157,7 +159,13 @@ def debian_squeeze_64(fresh_os=True):
def compile_liquidsoap(filename="liquidsoap"):
-
+
+ config = ConfigParser()
+ config.readfp(open('fab_liquidsoap_compile.cfg'))
+ url = config.get('main', 'liquidsoap_tar_url')
+
+ print "Will get liquidsoap from " + url
+
do_sudo('apt-get update')
do_sudo('apt-get upgrade -y --force-yes')
do_sudo('apt-get install -y --force-yes ocaml-findlib libao-ocaml-dev libportaudio-ocaml-dev ' + \
@@ -171,14 +179,15 @@ def compile_liquidsoap(filename="liquidsoap"):
do_run('mkdir -p %s' % root)
tmpPath = do_local("mktemp", capture=True)
- do_run('wget %s -O %s' % ('https://downloads.sourceforge.net/project/savonet/liquidsoap/1.0.0/liquidsoap-1.0.0-full.tar.bz2', tmpPath))
- do_run('mv %s %s/liquidsoap-1.0.0-full.tar.bz2' % (tmpPath, root))
- do_run('cd %s && bunzip2 liquidsoap-1.0.0-full.tar.bz2 && tar xf liquidsoap-1.0.0-full.tar' % root)
+ do_run('wget %s -O %s' % (url, tmpPath))
+ do_run('mv %s %s/liquidsoap.tar.gz' % (tmpPath, root))
+ do_run('cd %s && tar xzf liquidsoap.tar.gz' % root)
- do_run('cd %s/liquidsoap-1.0.0-full && cp PACKAGES.minimal PACKAGES' % root)
- sed('%s/liquidsoap-1.0.0-full/PACKAGES' % root, '#ocaml-portaudio', 'ocaml-portaudio')
- sed('%s/liquidsoap-1.0.0-full/PACKAGES' % root, '#ocaml-alsa', 'ocaml-alsa')
- sed('%s/liquidsoap-1.0.0-full/PACKAGES' % root, '#ocaml-pulseaudio', 'ocaml-pulseaudio')
- do_run('cd %s/liquidsoap-1.0.0-full && ./configure' % root)
- do_run('cd %s/liquidsoap-1.0.0-full && make' % root)
- get('%s/liquidsoap-1.0.0-full/liquidsoap-1.0.0/src/liquidsoap' % root, filename)
+ do_run('cd %s/savonet && cp PACKAGES.minimal PACKAGES' % root)
+ sed('%s/savonet/PACKAGES' % root, '#ocaml-portaudio', 'ocaml-portaudio')
+ sed('%s/savonet/PACKAGES' % root, '#ocaml-alsa', 'ocaml-alsa')
+ sed('%s/savonet/PACKAGES' % root, '#ocaml-pulseaudio', 'ocaml-pulseaudio')
+ do_run('cd %s/savonet && ./bootstrap' % root)
+ do_run('cd %s/savonet && ./configure' % root)
+ do_run('cd %s/savonet && make' % root)
+ get('%s/savonet/liquidsoap/src/liquidsoap' % root, filename)
diff --git a/python_apps/media-monitor/airtimefilemonitor/airtimemediamonitorbootstrap.py b/python_apps/media-monitor/airtimefilemonitor/airtimemediamonitorbootstrap.py
index 55b8856ff..d23651955 100644
--- a/python_apps/media-monitor/airtimefilemonitor/airtimemediamonitorbootstrap.py
+++ b/python_apps/media-monitor/airtimefilemonitor/airtimemediamonitorbootstrap.py
@@ -42,7 +42,7 @@ class AirtimeMediaMonitorBootstrap():
for id, dir in directories.iteritems():
self.logger.debug("%s, %s", id, dir)
- self.sync_database_to_filesystem(id, api_client.encode_to(dir, "utf-8"))
+ self.sync_database_to_filesystem(id, dir)
"""Gets a list of files that the Airtime database knows for a specific directory.
You need to provide the directory's row ID, which is obtained when calling
@@ -82,7 +82,7 @@ class AirtimeMediaMonitorBootstrap():
db_known_files_set = set()
files = self.list_db_files(dir_id)
for file in files['files']:
- db_known_files_set.add(api_client.encode_to(file, 'utf-8'))
+ db_known_files_set.add(file)
new_files = self.mmc.scan_dir_for_new_files(dir)
@@ -123,9 +123,6 @@ class AirtimeMediaMonitorBootstrap():
new_files_set = all_files_set - db_known_files_set
modified_files_set = new_and_modified_files - new_files_set
- #NAOMI: Please comment out the "Known files" line, if you find the bug.
- #it is for debugging purposes only (Too much data will be written to log). -mk
- #self.logger.info("Known files: \n%s\n\n"%db_known_files_set)
self.logger.info("Deleted files: \n%s\n\n"%deleted_files_set)
self.logger.info("New files: \n%s\n\n"%new_files_set)
self.logger.info("Modified files: \n%s\n\n"%modified_files_set)
diff --git a/python_apps/media-monitor/airtimefilemonitor/mediamonitorcommon.py b/python_apps/media-monitor/airtimefilemonitor/mediamonitorcommon.py
index 8927a9c4c..f526f2616 100644
--- a/python_apps/media-monitor/airtimefilemonitor/mediamonitorcommon.py
+++ b/python_apps/media-monitor/airtimefilemonitor/mediamonitorcommon.py
@@ -251,12 +251,29 @@ class MediaMonitorCommon:
if p.returncode != 0:
self.logger.warn("command \n%s\n return with a non-zero return value", command)
self.logger.error(stderr)
+
+ try:
+ """
+ File name charset encoding is UTF-8.
+ """
+ stdout = stdout.decode("UTF-8")
+ except Exception, e:
+ self.logger.error("Could not decode %s using UTF-8" % stdout)
+
return stdout
def scan_dir_for_new_files(self, dir):
command = 'find "%s" -type f -iname "*.ogg" -o -iname "*.mp3" -readable' % dir.replace('"', '\\"')
self.logger.debug(command)
- stdout = self.exec_command(command)
+ stdout = self.exec_command(command).decode("UTF-8")
+
+ try:
+ """
+ File name charset encoding is UTF-8.
+ """
+ stdout = stdout.decode("UTF-8")
+ except Exception, e:
+ self.logger.error("Could not decode %s using UTF-8" % stdout)
return stdout.splitlines()
diff --git a/python_apps/pypo/__init__.py b/python_apps/pypo/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/python_apps/pypo/pypo-notify.py b/python_apps/pypo/pypo-notify.py
index 0df1abab5..ebd8e0f5b 100644
--- a/python_apps/pypo/pypo-notify.py
+++ b/python_apps/pypo/pypo-notify.py
@@ -95,7 +95,7 @@ class Notify:
logger.debug("Response: "+json.dumps(response))
def notify_source_status(self, source_name, status):
- logger = logging.getLogger()
+ logger = logging.getLogger("notify")
logger.debug('#################################################')
logger.debug('# Calling server to update source status #')
diff --git a/python_apps/pypo/pypocli.py b/python_apps/pypo/pypocli.py
index 9eeb15a6f..6a9649d5a 100644
--- a/python_apps/pypo/pypocli.py
+++ b/python_apps/pypo/pypocli.py
@@ -5,13 +5,14 @@ Python part of radio playout (pypo)
import time
from optparse import *
import sys
-import os
import signal
import logging
import logging.config
import logging.handlers
from Queue import Queue
+from threading import Lock
+
from pypopush import PypoPush
from pypofetch import PypoFetch
from pypofile import PypoFile
@@ -125,6 +126,8 @@ if __name__ == '__main__':
recorder_q = Queue()
pypoPush_q = Queue()
+ telnet_lock = Lock()
+
"""
This queue is shared between pypo-fetch and pypo-file, where pypo-file
is the receiver. Pypo-fetch will send every schedule it gets to pypo-file
@@ -141,11 +144,11 @@ if __name__ == '__main__':
pfile.daemon = True
pfile.start()
- pf = PypoFetch(pypoFetch_q, pypoPush_q, media_q)
+ pf = PypoFetch(pypoFetch_q, pypoPush_q, media_q, telnet_lock)
pf.daemon = True
pf.start()
- pp = PypoPush(pypoPush_q)
+ pp = PypoPush(pypoPush_q, telnet_lock)
pp.daemon = True
pp.start()
diff --git a/python_apps/pypo/pypofetch.py b/python_apps/pypo/pypofetch.py
index c7634b878..7189f5ca9 100644
--- a/python_apps/pypo/pypofetch.py
+++ b/python_apps/pypo/pypofetch.py
@@ -1,22 +1,13 @@
import os
import sys
import time
-import calendar
import logging
import logging.config
import shutil
-import random
-import string
import json
import telnetlib
-import math
import copy
from threading import Thread
-from subprocess import Popen, PIPE
-from datetime import datetime
-from datetime import timedelta
-from Queue import Empty
-import filecmp
from api_clients import api_client
@@ -38,13 +29,15 @@ except Exception, e:
sys.exit()
class PypoFetch(Thread):
- def __init__(self, pypoFetch_q, pypoPush_q, media_q):
+ def __init__(self, pypoFetch_q, pypoPush_q, media_q, telnet_lock):
Thread.__init__(self)
self.api_client = api_client.api_client_factory(config)
self.fetch_queue = pypoFetch_q
self.push_queue = pypoPush_q
self.media_prepare_queue = media_q
+ self.telnet_lock = telnet_lock
+
self.logger = logging.getLogger();
self.cache_dir = os.path.join(config["cache_dir"], "scheduler")
@@ -79,7 +72,7 @@ class PypoFetch(Thread):
if command == 'update_schedule':
self.schedule_data = m['schedule']
- self.process_schedule(self.schedule_data, False)
+ self.process_schedule(self.schedule_data)
elif command == 'update_stream_setting':
self.logger.info("Updating stream setting...")
self.regenerateLiquidsoapConf(m['setting'])
@@ -89,9 +82,6 @@ class PypoFetch(Thread):
elif command == 'update_station_name':
self.logger.info("Updating station name...")
self.update_liquidsoap_station_name(m['station_name'])
- elif command == 'cancel_current_show':
- self.logger.info("Cancel current show command received...")
- self.stop_current_show()
elif command == 'switch_source':
self.logger.info("switch_on_source show command received...")
self.switch_source(m['sourcename'], m['status'])
@@ -113,14 +103,16 @@ class PypoFetch(Thread):
elif(sourcename == "live_dj"):
command += "live_dj_harbor.kick\n"
+ self.telnet_lock.acquire()
try:
tn = telnetlib.Telnet(LS_HOST, LS_PORT)
tn.write(command)
tn.write('exit\n')
tn.read_all()
except Exception, e:
- self.logger.debug(e)
- self.logger.debug('Could not connect to liquidsoap')
+ self.logger.error(str(e))
+ finally:
+ self.telnet_lock.release()
def switch_source(self, sourcename, status):
self.logger.debug('Switching source: %s to "%s" status', sourcename, status)
@@ -137,14 +129,16 @@ class PypoFetch(Thread):
else:
command += "stop\n"
+ self.telnet_lock.acquire()
try:
tn = telnetlib.Telnet(LS_HOST, LS_PORT)
tn.write(command)
tn.write('exit\n')
tn.read_all()
except Exception, e:
- self.logger.debug(e)
- self.logger.debug('Could not connect to liquidsoap')
+ self.logger.error(str(e))
+ finally:
+ self.telnet_lock.release()
"""
This check current switch status from Airtime and update the status
@@ -155,18 +149,7 @@ class PypoFetch(Thread):
self.logger.debug('switch_status:%s',switch_status)
for k, v in switch_status['status'].iteritems():
self.switch_source(k, v)
-
- def stop_current_show(self):
- self.logger.debug('Notifying Liquidsoap to stop playback.')
- try:
- tn = telnetlib.Telnet(LS_HOST, LS_PORT)
- tn.write('source.skip\n')
- tn.write('exit\n')
- tn.read_all()
- except Exception, e:
- self.logger.debug(e)
- self.logger.debug('Could not connect to liquidsoap')
-
+
def regenerateLiquidsoapConf(self, setting_p):
existing = {}
# create a temp file
@@ -252,19 +235,19 @@ class PypoFetch(Thread):
fh.write("# THIS FILE IS AUTO GENERATED. DO NOT CHANGE!! #\n")
fh.write("################################################\n")
for k, d in setting:
- buffer = d[u'keyname'] + " = "
+ buffer_str = d[u'keyname'] + " = "
if(d[u'type'] == 'string'):
temp = d[u'value']
if(temp == ""):
temp = ""
- buffer += "\"" + temp + "\""
+ buffer_str += "\"" + temp + "\""
else:
temp = d[u'value']
if(temp == ""):
temp = "0"
- buffer += temp
- buffer += "\n"
- fh.write(api_client.encode_to(buffer))
+ buffer_str += temp
+ buffer_str += "\n"
+ fh.write(api_client.encode_to(buffer_str))
fh.write("log_file = \"/var/log/airtime/pypo-liquidsoap/