diff --git a/airtime_mvc/application/controllers/AudiopreviewController.php b/airtime_mvc/application/controllers/AudiopreviewController.php
index e094a7450..302e8c545 100644
--- a/airtime_mvc/application/controllers/AudiopreviewController.php
+++ b/airtime_mvc/application/controllers/AudiopreviewController.php
@@ -60,8 +60,10 @@ class AudiopreviewController extends Zend_Controller_Action
$this->view->uri = $uri;
$this->view->mime = $mime;
$this->view->audioFileID = $audioFileID;
- $this->view->audioFileArtist = $audioFileArtist;
- $this->view->audioFileTitle = $audioFileTitle;
+ // We need to decode artist and title because it gets
+ // encoded twice in js
+ $this->view->audioFileArtist = urldecode($audioFileArtist);
+ $this->view->audioFileTitle = urldecode($audioFileTitle);
$this->view->type = $type;
$this->_helper->viewRenderer->setRender('audio-preview');
diff --git a/airtime_mvc/application/controllers/LibraryController.php b/airtime_mvc/application/controllers/LibraryController.php
index 2974d85a1..2d0177dbd 100644
--- a/airtime_mvc/application/controllers/LibraryController.php
+++ b/airtime_mvc/application/controllers/LibraryController.php
@@ -412,7 +412,7 @@ class LibraryController extends Zend_Controller_Action
$formValues = $this->_getParam('data', null);
$formdata = array();
foreach ($formValues as $val) {
- $formdata[$val["name"]] = $val["value"];
+ $formdata[$val["name"]] = htmlspecialchars($val["value"]);
}
$file->setDbColMetadata($formdata);
diff --git a/airtime_mvc/application/controllers/LocaleController.php b/airtime_mvc/application/controllers/LocaleController.php
index d689417be..efdecff80 100644
--- a/airtime_mvc/application/controllers/LocaleController.php
+++ b/airtime_mvc/application/controllers/LocaleController.php
@@ -4,10 +4,6 @@ class LocaleController extends Zend_Controller_Action
{
public function init()
{
- $ajaxContext = $this->_helper->getHelper("AjaxContext");
- $ajaxContext->addActionContext("general-translation-table", "json")
- ->addActionContext("datatables-translation-table", "json")
- ->initContext();
}
public function datatablesTranslationTableAction()
@@ -26,7 +22,7 @@ class LocaleController extends Zend_Controller_Action
$locale.".txt")
);
}
-
+
public function generalTranslationTableAction()
{
$translations = array (
diff --git a/airtime_mvc/application/controllers/PreferenceController.php b/airtime_mvc/application/controllers/PreferenceController.php
index af78f996a..33a021aa4 100644
--- a/airtime_mvc/application/controllers/PreferenceController.php
+++ b/airtime_mvc/application/controllers/PreferenceController.php
@@ -274,6 +274,7 @@ class PreferenceController extends Zend_Controller_Action
Application_Model_Preference::setReplayGainModifier($values["replayGainModifier"]);
$md = array('schedule' => Application_Model_Schedule::getSchedule());
Application_Model_RabbitMq::SendMessageToPypo("update_schedule", $md);
+ //Application_Model_RabbitMq::PushSchedule();
}
if (!Application_Model_Preference::GetMasterDjConnectionUrlOverride()) {
diff --git a/airtime_mvc/application/controllers/ScheduleController.php b/airtime_mvc/application/controllers/ScheduleController.php
index 1a22506b4..3ce212513 100644
--- a/airtime_mvc/application/controllers/ScheduleController.php
+++ b/airtime_mvc/application/controllers/ScheduleController.php
@@ -9,6 +9,7 @@ class ScheduleController extends Zend_Controller_Action
{
$ajaxContext = $this->_helper->getHelper('AjaxContext');
$ajaxContext->addActionContext('event-feed', 'json')
+ ->addActionContext('event-feed-preload', 'json')
->addActionContext('make-context-menu', 'json')
->addActionContext('add-show-dialog', 'json')
->addActionContext('add-show', 'json')
@@ -89,15 +90,23 @@ class ScheduleController extends Zend_Controller_Action
$this->view->headLink()->appendStylesheet($baseUrl.'css/showbuilder.css?'.$CC_CONFIG['airtime_version']);
//End Show builder JS/CSS requirements
+
Application_Model_Schedule::createNewFormSections($this->view);
-
$user = Application_Model_User::getCurrentUser();
-
if ($user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
$this->view->preloadShowForm = true;
}
- $this->view->headScript()->appendScript("var weekStart = ".Application_Model_Preference::GetWeekStartDay().";");
+ $this->view->headScript()->appendScript(
+ "var calendarPref = {};\n".
+ "calendarPref.weekStart = ".Application_Model_Preference::GetWeekStartDay().";\n".
+ "calendarPref.timestamp = ".time().";\n".
+ "calendarPref.timezoneOffset = ".date("Z").";\n".
+ "calendarPref.timeScale = '".Application_Model_Preference::GetCalendarTimeScale()."';\n".
+ "calendarPref.timeInterval = ".Application_Model_Preference::GetCalendarTimeInterval().";\n".
+ "calendarPref.weekStartDay = ".Application_Model_Preference::GetWeekStartDay().";\n".
+ "var calendarEvents = null;"
+ );
}
public function eventFeedAction()
@@ -109,10 +118,28 @@ class ScheduleController extends Zend_Controller_Action
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
$user = new Application_Model_User($userInfo->id);
- if ($user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
- $editable = true;
+ $editable = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
+
+ $events = &Application_Model_Show::getFullCalendarEvents($start, $end, $editable);
+ $this->view->events = $events;
+ }
+
+ public function eventFeedPreloadAction()
+ {
+ $userInfo = Zend_Auth::getInstance()->getStorage()->read();
+ $user = new Application_Model_User($userInfo->id);
+ $editable = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER));
+
+ $calendar_interval = Application_Model_Preference::GetCalendarTimeScale();
+ Logging::info($calendar_interval);
+ if ($calendar_interval == "agendaDay") {
+ list($start, $end) = Application_Model_Show::getStartEndCurrentDayView();
+ } else if ($calendar_interval == "agendaWeek") {
+ list($start, $end) = Application_Model_Show::getStartEndCurrentWeekView();
+ } else if ($calendar_interval == "month") {
+ list($start, $end) = Application_Model_Show::getStartEndCurrentMonthView();
} else {
- $editable = false;
+ Logging::error("Invalid Calendar Interval '$calendar_interval'");
}
$events = &Application_Model_Show::getFullCalendarEvents($start, $end, $editable);
diff --git a/airtime_mvc/application/controllers/plugins/Acl_plugin.php b/airtime_mvc/application/controllers/plugins/Acl_plugin.php
index 4cadba9db..44555e533 100644
--- a/airtime_mvc/application/controllers/plugins/Acl_plugin.php
+++ b/airtime_mvc/application/controllers/plugins/Acl_plugin.php
@@ -110,7 +110,7 @@ class Zend_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract
{
$controller = strtolower($request->getControllerName());
- if (in_array($controller, array("api", "auth"))) {
+ if (in_array($controller, array("api", "auth", "locale"))) {
$this->setRoleName("G");
} elseif (!Zend_Auth::getInstance()->hasIdentity()) {
diff --git a/airtime_mvc/application/forms/RegisterAirtime.php b/airtime_mvc/application/forms/RegisterAirtime.php
index d1557612a..2da7083c8 100644
--- a/airtime_mvc/application/forms/RegisterAirtime.php
+++ b/airtime_mvc/application/forms/RegisterAirtime.php
@@ -7,7 +7,7 @@ class Application_Form_RegisterAirtime extends Zend_Form
public function init()
{
- $this->setAction(Application_Common_OsPath::getBaseDir().'/Showbuilder');
+ $this->setAction(Application_Common_OsPath::getBaseDir().'Showbuilder');
$this->setMethod('post');
$country_list = Application_Model_Preference::GetCountryList();
diff --git a/airtime_mvc/application/layouts/scripts/layout.phtml b/airtime_mvc/application/layouts/scripts/layout.phtml
index 29d04c0d6..dedda7c88 100644
--- a/airtime_mvc/application/layouts/scripts/layout.phtml
+++ b/airtime_mvc/application/layouts/scripts/layout.phtml
@@ -24,7 +24,7 @@
diff --git a/airtime_mvc/application/logging/Logging.php b/airtime_mvc/application/logging/Logging.php
index dfe7e1fbe..65a8f6dc2 100644
--- a/airtime_mvc/application/logging/Logging.php
+++ b/airtime_mvc/application/logging/Logging.php
@@ -32,6 +32,8 @@ class Logging {
{
if (is_array($p_msg) || is_object($p_msg)) {
return print_r($p_msg, true);
+ } else if (is_bool($p_msg)) {
+ return $p_msg ? "true" : "false";
} else {
return $p_msg;
}
diff --git a/airtime_mvc/application/models/Schedule.php b/airtime_mvc/application/models/Schedule.php
index ca31a4378..1aac2566e 100644
--- a/airtime_mvc/application/models/Schedule.php
+++ b/airtime_mvc/application/models/Schedule.php
@@ -731,6 +731,10 @@ SQL;
'replay_gain' => $replay_gain,
'independent_event' => $independent_event,
);
+
+ if ($schedule_item['cue_in'] > $schedule_item['cue_out']) {
+ $schedule_item['cue_in'] = $schedule_item['cue_out'];
+ }
self::appendScheduleItem($data, $start, $schedule_item);
}
@@ -941,7 +945,6 @@ SQL;
self::createScheduledEvents($data, $range_start, $range_end);
self::foldData($data["media"]);
-
return $data;
}
diff --git a/airtime_mvc/application/models/Scheduler.php b/airtime_mvc/application/models/Scheduler.php
index 4aa14bfff..2f62af6aa 100644
--- a/airtime_mvc/application/models/Scheduler.php
+++ b/airtime_mvc/application/models/Scheduler.php
@@ -136,13 +136,17 @@ class Application_Model_Scheduler
if ($type === "audioclip") {
$file = CcFilesQuery::create()->findPK($id, $this->con);
+ $storedFile = new Application_Model_StoredFile($file->getDbId());
if (is_null($file) || !$file->visible()) {
throw new Exception(_("A selected File does not exist!"));
} else {
$data = $this->fileInfo;
$data["id"] = $id;
- $data["cliplength"] = $file->getDbLength();
+ $data["cliplength"] = $storedFile->getRealClipLength(
+ $file->getDbCuein(),
+ $file->getDbCueout());
+
$data["cuein"] = $file->getDbCuein();
$data["cueout"] = $file->getDbCueout();
@@ -438,7 +442,6 @@ class Application_Model_Scheduler
}
foreach ($schedFiles as $file) {
-
$endTimeDT = $this->findEndTime($nextStartDT, $file['cliplength']);
//item existed previously and is being moved.
diff --git a/airtime_mvc/application/models/Show.php b/airtime_mvc/application/models/Show.php
index 20e6e3e23..933c2c841 100644
--- a/airtime_mvc/application/models/Show.php
+++ b/airtime_mvc/application/models/Show.php
@@ -1750,14 +1750,15 @@ SQL;
$interval = $p_start->diff($p_end);
$days = $interval->format('%a');
$shows = Application_Model_Show::getShows($p_start, $p_end);
- $nowEpoch = time();
$content_count = Application_Model_ShowInstance::getContentCount(
$p_start, $p_end);
$isFull = Application_Model_ShowInstance::getIsFull($p_start, $p_end);
$timezone = date_default_timezone_get();
+ $current_timezone = new DateTimeZone($timezone);
$utc = new DateTimeZone("UTC");
+ $now = new DateTime("now", $utc);
- foreach ($shows as $show) {
+ foreach ($shows as &$show) {
$options = array();
//only bother calculating percent for week or day view.
@@ -1767,7 +1768,6 @@ SQL;
if (isset($show["parent_starts"])) {
$parentStartsDT = new DateTime($show["parent_starts"], $utc);
- $parentStartsEpoch = intval($parentStartsDT->format("U"));
}
$startsDT = DateTime::createFromFormat("Y-m-d G:i:s",
@@ -1775,35 +1775,53 @@ SQL;
$endsDT = DateTime::createFromFormat("Y-m-d G:i:s",
$show["ends"], $utc);
- $startsEpochStr = $startsDT->format("U");
- $endsEpochStr = $endsDT->format("U");
-
- $startsEpoch = intval($startsEpochStr);
- $endsEpoch = intval($endsEpochStr);
-
- $startsDT->setTimezone(new DateTimeZone($timezone));
- $endsDT->setTimezone(new DateTimeZone($timezone));
-
if( $p_editable ) {
- if ($show["record"] && $nowEpoch > $startsEpoch) {
+ if ($show["record"] && $now > $startsDT) {
$options["editable"] = false;
} elseif ($show["rebroadcast"] &&
- $nowEpoch > $parentStartsEpoch) {
+ $now > $parentStartsDT) {
$options["editable"] = false;
- } elseif ($nowEpoch < $endsEpoch) {
+ } elseif ($now < $endsDT) {
$options["editable"] = true;
}
}
+ $startsDT->setTimezone($current_timezone);
+ $endsDT->setTimezone($current_timezone);
+
$options["show_empty"] = (array_key_exists($show['instance_id'],
$content_count)) ? 0 : 1;
$options["show_partial_filled"] = !$isFull[$show['instance_id']];
- $events[] = &self::makeFullCalendarEvent($show, $options,
- $startsDT, $endsDT, $startsEpochStr, $endsEpochStr);
- }
+ $event = array();
+ $event["id"] = intval($show["instance_id"]);
+ $event["title"] = $show["name"];
+ $event["start"] = $startsDT->format("Y-m-d H:i:s");
+ $event["end"] = $endsDT->format("Y-m-d H:i:s");
+ $event["allDay"] = false;
+ $event["showId"] = intval($show["show_id"]);
+ $event["record"] = intval($show["record"]);
+ $event["rebroadcast"] = intval($show["rebroadcast"]);
+ $event["soundcloud_id"] = is_null($show["soundcloud_id"])
+ ? -1 : $show["soundcloud_id"];
+
+ //event colouring
+ if ($show["color"] != "") {
+ $event["textColor"] = "#".$show["color"];
+ }
+
+ if ($show["background_color"] != "") {
+ $event["color"] = "#".$show["background_color"];
+ }
+
+ foreach ($options as $key => $value) {
+ $event[$key] = $value;
+ }
+
+ $events[] = $event;
+ }
return $events;
}
@@ -1820,7 +1838,7 @@ SQL;
return $percent;
}
- private static function &makeFullCalendarEvent(&$show, $options=array(), $startDateTime, $endDateTime, $startsEpoch, $endsEpoch)
+/* private static function &makeFullCalendarEvent(&$show, $options=array(), $startDateTime, $endDateTime, $startsEpoch, $endsEpoch)
{
$event = array();
@@ -1851,7 +1869,7 @@ SQL;
}
return $event;
- }
+ }*/
/* Takes in a UTC DateTime object.
* Converts this to local time, since cc_show days
@@ -2158,4 +2176,42 @@ SQL;
}
return $assocArray;
}
+
+ public static function getStartEndCurrentMonthView() {
+ $first_day_of_calendar_month_view = mktime(0, 0, 0, date("n"), 1);
+ $weekStart = Application_Model_Preference::GetWeekStartDay();
+ while (date('w', $first_day_of_calendar_month_view) != $weekStart) {
+ $first_day_of_calendar_month_view -= 60*60*24;
+ }
+ $last_day_of_calendar_view = $first_day_of_calendar_month_view + 3600*24*42;
+
+ $start = new DateTime("@".$first_day_of_calendar_month_view);
+ $end = new DateTime("@".$last_day_of_calendar_view);
+
+ return array($start, $end);
+ }
+
+ public static function getStartEndCurrentWeekView() {
+ $first_day_of_calendar_week_view = mktime(0, 0, 0, date("n"), date("j"));
+ $weekStart = Application_Model_Preference::GetWeekStartDay();
+ while (date('w', $first_day_of_calendar_week_view) != $weekStart) {
+ $first_day_of_calendar_week_view -= 60*60*24;
+ }
+ $last_day_of_calendar_view = $first_day_of_calendar_week_view + 3600*24*7;
+
+ $start = new DateTime("@".$first_day_of_calendar_week_view);
+ $end = new DateTime("@".$last_day_of_calendar_view);
+
+ return array($start, $end);
+ }
+
+ public static function getStartEndCurrentDayView() {
+ $today = mktime(0, 0, 0, date("n"), date("j"));
+ $tomorrow = $today + 3600*24;
+
+ $start = new DateTime("@".$today);
+ $end = new DateTime("@".$tomorrow);
+
+ return array($start, $end);
+ }
}
diff --git a/airtime_mvc/application/models/ShowBuilder.php b/airtime_mvc/application/models/ShowBuilder.php
index a1ef7c588..72a5f6ab0 100644
--- a/airtime_mvc/application/models/ShowBuilder.php
+++ b/airtime_mvc/application/models/ShowBuilder.php
@@ -227,7 +227,7 @@ class Application_Model_ShowBuilder
$row["endDate"] = $showEndDT->format("Y-m-d");
$row["endTime"] = $showEndDT->format("H:i");
$row["duration"] = floatval($showEndDT->format("U.u")) - floatval($showStartDT->format("U.u"));
- $row["title"] = $p_item["show_name"];
+ $row["title"] = htmlspecialchars($p_item["show_name"]);
$row["instance"] = intval($p_item["si_id"]);
$row["image"] = '';
diff --git a/airtime_mvc/application/models/StoredFile.php b/airtime_mvc/application/models/StoredFile.php
index 98b1bfe6c..403ba5d53 100644
--- a/airtime_mvc/application/models/StoredFile.php
+++ b/airtime_mvc/application/models/StoredFile.php
@@ -1310,6 +1310,14 @@ SQL;
return $updateIsScheduled;
}
+
+ public function getRealClipLength($p_cuein, $p_cueout) {
+ $sql = "SELECT :cueout::INTERVAL - :cuein::INTERVAL";
+
+ return Application_Common_Database::prepareAndExecute($sql, array(
+ ':cueout' => $p_cueout,
+ ':cuein' => $p_cuein), 'column');
+ }
}
class DeleteScheduledFileException extends Exception {}
diff --git a/airtime_mvc/application/models/Systemstatus.php b/airtime_mvc/application/models/Systemstatus.php
index ef694ccf2..6f6a05fff 100644
--- a/airtime_mvc/application/models/Systemstatus.php
+++ b/airtime_mvc/application/models/Systemstatus.php
@@ -214,35 +214,22 @@ class Application_Model_Systemstatus
{
$partions = array();
- if (isset($_SERVER['AIRTIME_SRV'])) {
- //connect to DB and find how much total space user has allocated.
- $totalSpace = Application_Model_Preference::GetDiskQuota();
+ /* First lets get all the watched directories. Then we can group them
+ * into the same partitions by comparing the partition sizes. */
+ $musicDirs = Application_Model_MusicDir::getWatchedDirs();
+ $musicDirs[] = Application_Model_MusicDir::getStorDir();
- $storPath = Application_Model_MusicDir::getStorDir()->getDirectory();
+ foreach ($musicDirs as $md) {
+ $totalSpace = disk_total_space($md->getDirectory());
- list($usedSpace,) = preg_split("/[\s]+/", exec("du -bs $storPath"));
+ if (!isset($partitions[$totalSpace])) {
+ $partitions[$totalSpace] = new StdClass;
+ $partitions[$totalSpace]->totalSpace = $totalSpace;
+ $partitions[$totalSpace]->totalFreeSpace = disk_free_space($md->getDirectory());
- $partitions[$totalSpace]->totalSpace = $totalSpace;
- $partitions[$totalSpace]->totalFreeSpace = $totalSpace - $usedSpace;
- Logging::info($partitions[$totalSpace]->totalFreeSpace);
- } else {
- /* First lets get all the watched directories. Then we can group them
- * into the same partitions by comparing the partition sizes. */
- $musicDirs = Application_Model_MusicDir::getWatchedDirs();
- $musicDirs[] = Application_Model_MusicDir::getStorDir();
-
- foreach ($musicDirs as $md) {
- $totalSpace = disk_total_space($md->getDirectory());
-
- if (!isset($partitions[$totalSpace])) {
- $partitions[$totalSpace] = new StdClass;
- $partitions[$totalSpace]->totalSpace = $totalSpace;
- $partitions[$totalSpace]->totalFreeSpace = disk_free_space($md->getDirectory());
-
- }
-
- $partitions[$totalSpace]->dirs[] = $md->getDirectory();
}
+
+ $partitions[$totalSpace]->dirs[] = $md->getDirectory();
}
return array_values($partitions);
diff --git a/airtime_mvc/application/models/User.php b/airtime_mvc/application/models/User.php
index 63b82820a..97c9ca3ad 100644
--- a/airtime_mvc/application/models/User.php
+++ b/airtime_mvc/application/models/User.php
@@ -335,6 +335,8 @@ class Application_Model_User
} else {
$record['delete'] = "";
}
+
+ $record = array_map('htmlspecialchars', $record);
}
return $res;
diff --git a/airtime_mvc/application/views/scripts/form/edit-user.phtml b/airtime_mvc/application/views/scripts/form/edit-user.phtml
index cd4b70bd9..79a0081fc 100644
--- a/airtime_mvc/application/views/scripts/form/edit-user.phtml
+++ b/airtime_mvc/application/views/scripts/form/edit-user.phtml
@@ -1,4 +1,4 @@
- echo sprintf(_("%s's Settings"), $this->currentUser) ?>
+ echo sprintf(_("%s's Settings"), $this->escape($this->currentUser)) ?>
\ No newline at end of file
+
diff --git a/airtime_mvc/application/views/scripts/form/preferences_watched_dirs.phtml b/airtime_mvc/application/views/scripts/form/preferences_watched_dirs.phtml
index 4889892dd..ad8e77797 100644
--- a/airtime_mvc/application/views/scripts/form/preferences_watched_dirs.phtml
+++ b/airtime_mvc/application/views/scripts/form/preferences_watched_dirs.phtml
@@ -11,7 +11,7 @@
element->getElement('storageFolder')->hasErrors()) : ?>
element->getElement('storageFolder')->getMessages() as $error): ?>
-
+ - escape($error); ?>
@@ -29,7 +29,7 @@
element->getElement('watchedFolder')->hasErrors()) : ?>
element->getElement('watchedFolder')->getMessages() as $error): ?>
-
+ - escape($error); ?>
diff --git a/airtime_mvc/application/views/scripts/playlist/playlist.phtml b/airtime_mvc/application/views/scripts/playlist/playlist.phtml
index 3d388bf36..5a31ba2b5 100644
--- a/airtime_mvc/application/views/scripts/playlist/playlist.phtml
+++ b/airtime_mvc/application/views/scripts/playlist/playlist.phtml
@@ -42,7 +42,7 @@ if (isset($this->obj)) {
diff --git a/airtime_mvc/public/js/airtime/login/login.js b/airtime_mvc/public/js/airtime/login/login.js
index a37210b35..f21043c31 100644
--- a/airtime_mvc/public/js/airtime/login/login.js
+++ b/airtime_mvc/public/js/airtime/login/login.js
@@ -1,6 +1,6 @@
$(window).load(function(){
$("#username").focus();
- $("#locale").val($.cookie("airtime_locale")!== null?$.cookie("airtime_locale"):'en_CA');
+ $("#locale").val($.cookie("airtime_locale")!== null?$.cookie("airtime_locale"):$.cookie("default_airtime_locale"));
});
$(document).ready(function() {
diff --git a/airtime_mvc/public/js/airtime/preferences/preferences.js b/airtime_mvc/public/js/airtime/preferences/preferences.js
index 1d529617d..eec5e1c7e 100644
--- a/airtime_mvc/public/js/airtime/preferences/preferences.js
+++ b/airtime_mvc/public/js/airtime/preferences/preferences.js
@@ -111,6 +111,7 @@ $(document).ready(function() {
$.post(url, {format: "json", data: data}, function(data){
var json = $.parseJSON(data);
$('#content').empty().append(json.html);
+ $.cookie("default_airtime_locale", $('#locale').val(), {path: '/'});
setTimeout(removeSuccessMsg, 5000);
showErrorSections();
});
diff --git a/airtime_mvc/public/js/airtime/preferences/streamsetting.js b/airtime_mvc/public/js/airtime/preferences/streamsetting.js
index 54bb986ca..6e76b693c 100644
--- a/airtime_mvc/public/js/airtime/preferences/streamsetting.js
+++ b/airtime_mvc/public/js/airtime/preferences/streamsetting.js
@@ -28,7 +28,7 @@ function rebuildStreamURL(ele){
}else{
streamurl = "http://"+host+":"+port+"/"
}
- div.find("#stream_url").html(streamurl)
+ div.find("#stream_url").text(streamurl)
}
function restrictOggBitrate(ele, on){
var div = ele.closest("div")
diff --git a/airtime_mvc/public/js/airtime/schedule/add-show.js b/airtime_mvc/public/js/airtime/schedule/add-show.js
index 2242f3c66..4f33ccdc7 100644
--- a/airtime_mvc/public/js/airtime/schedule/add-show.js
+++ b/airtime_mvc/public/js/airtime/schedule/add-show.js
@@ -37,7 +37,7 @@ function createDateInput(el, onSelect) {
dayNamesMin: i18n_days_short,
closeText: $.i18n._('Close'),
//showButtonPanel: true,
- firstDay: weekStart
+ firstDay: calendarPref.weekStart
});
}
@@ -324,7 +324,7 @@ function setAddShowEvents() {
dayNamesMin: i18n_days_short,
closeText: 'Close',
showButtonPanel: true,
- firstDay: weekStart
+ firstDay: calendarPref.weekStart
});
form.find('input[name^="add_show_rebroadcast_time"]').timepicker({
amPmText: ['', ''],
diff --git a/airtime_mvc/public/js/airtime/schedule/full-calendar-functions.js b/airtime_mvc/public/js/airtime/schedule/full-calendar-functions.js
index 08dd31116..810ce0d88 100644
--- a/airtime_mvc/public/js/airtime/schedule/full-calendar-functions.js
+++ b/airtime_mvc/public/js/airtime/schedule/full-calendar-functions.js
@@ -326,21 +326,36 @@ function eventResize( event, dayDelta, minuteDelta, revertFunc, jsEvent, ui, vie
});
}
-function getFullCalendarEvents(start, end, callback) {
- var url, start_date, end_date;
-
- start_date = makeTimeStamp(start);
- end_date = makeTimeStamp(end);
-
- url = baseUrl+'Schedule/event-feed';
-
+function preloadEventFeed () {
+ var url = baseUrl+'Schedule/event-feed-preload';
var d = new Date();
-
- $.post(url, {format: "json", start: start_date, end: end_date, cachep: d.getTime()}, function(json){
- callback(json.events);
+
+ $.post(url, {format: "json", cachep: d.getTime()}, function(json){
+ calendarEvents = json.events;
+ createFullCalendar({calendarInit: calendarPref});
});
}
+var initialLoad = true;
+function getFullCalendarEvents(start, end, callback) {
+
+ if (initialLoad) {
+ initialLoad = false;
+ callback(calendarEvents);
+ } else {
+ var url, start_date, end_date;
+
+ start_date = makeTimeStamp(start);
+ end_date = makeTimeStamp(end);
+ url = baseUrl+'Schedule/event-feed';
+
+ var d = new Date();
+ $.post(url, {format: "json", start: start_date, end: end_date, cachep: d.getTime()}, function(json){
+ callback(json.events);
+ });
+ }
+}
+
function checkSCUploadStatus(){
var url = baseUrl+'Library/get-upload-to-soundcloud-status/format/json';
$("span[class*=progress]").each(function(){
@@ -541,6 +556,7 @@ function alertShowErrorAndReload(){
window.location.reload();
}
+preloadEventFeed();
$(document).ready(function(){
setInterval( "checkSCUploadStatus()", 5000 );
setInterval( "getCurrentShow()", 5000 );
diff --git a/airtime_mvc/public/js/airtime/schedule/schedule.js b/airtime_mvc/public/js/airtime/schedule/schedule.js
index 2de53cdb5..3c4f9fd3b 100644
--- a/airtime_mvc/public/js/airtime/schedule/schedule.js
+++ b/airtime_mvc/public/js/airtime/schedule/schedule.js
@@ -328,9 +328,6 @@ function alertShowErrorAndReload(){
}
$(document).ready(function() {
- $.ajax({ url: baseUrl+"Api/calendar-init/format/json", dataType:"json", success:createFullCalendar
- , error:function(jqXHR, textStatus, errorThrown){}});
-
setInterval(checkCalendarSCUploadStatus, 5000);
$.contextMenu({
diff --git a/changelog b/changelog
index 9aa22c634..aff42ec52 100644
--- a/changelog
+++ b/changelog
@@ -1,6 +1,7 @@
2.3.0 - Jan 21st, 2013
* New features
- * Localization (Brazilian, Chinese, Czech, English, French, German, Italian, Korean, Portugese, Russian, Spanish)
+ * Localization (Chinese, Czech, English, French, German, Italian, Korean,
+ Portuguese, Russian, Spanish)
* User management page for non-admin users
* Listener statistics (Icecast/Shoutcast)
* Airtime no longer requires Apache document root
diff --git a/install_minimal/upgrades/airtime-2.3.0/data/upgrade.sql b/install_minimal/upgrades/airtime-2.3.0/data/upgrade.sql
index c2d176b23..cd34a28bb 100644
--- a/install_minimal/upgrades/airtime-2.3.0/data/upgrade.sql
+++ b/install_minimal/upgrades/airtime-2.3.0/data/upgrade.sql
@@ -15,6 +15,8 @@ INSERT INTO cc_stream_setting ("keyname", "value", "type") VALUES ('s3_admin_pas
UPDATE cc_music_dirs SET directory = directory || '/' where id in (select id from cc_music_dirs where substr(directory, length(directory)) != '/');
UPDATE cc_files SET filepath = substring(filepath from 2) where id in (select id from cc_files where substring(filepath from 1 for 1) = '/');
+UPDATE cc_files SET cueout = length where cueout = '00:00:00';
+
INSERT INTO cc_pref("keystr", "valstr") VALUES('locale', 'en_CA');
INSERT INTO cc_pref("subjid", "keystr", "valstr") VALUES(1, 'user_locale', 'en_CA');
diff --git a/python_apps/api_clients/api_client.py b/python_apps/api_clients/api_client.py
index 048da729c..b28a4ca5a 100644
--- a/python_apps/api_clients/api_client.py
+++ b/python_apps/api_clients/api_client.py
@@ -73,17 +73,26 @@ class ApcUrl(object):
else: return self.base_url
class ApiRequest(object):
- def __init__(self, name, url):
+ def __init__(self, name, url, logger=None):
self.name = name
self.url = url
self.__req = None
+ if logger is None: self.logger = logging
+ else: self.logger = logger
def __call__(self,_post_data=None, **kwargs):
# TODO : get rid of god damn urllib and replace everything with
# grequests or requests at least
final_url = self.url.params(**kwargs).url()
if _post_data is not None: _post_data = urllib.urlencode(_post_data)
- req = urllib2.Request(final_url, _post_data)
- response = urllib2.urlopen(req).read()
+ try:
+ req = urllib2.Request(final_url, _post_data)
+ response = urllib2.urlopen(req).read()
+ except Exception, e:
+ self.logger.error('Exception: %s', e)
+ import traceback
+ top = traceback.format_exc()
+ self.logger.error("traceback: %s", top)
+ response = ""
# Ghetto hack for now because we don't the content type we are getting
# (Pointless to look at mime since it's not being set correctly always)
try: return json.loads(response)
@@ -168,9 +177,9 @@ class AirtimeApiClient(object):
def get_schedule(self):
# TODO : properly refactor this routine
- # For now thre return type is a little fucked for compatibility reasons
+ # For now the return type is a little fucked for compatibility reasons
try: return (True, self.services.export_url())
- except: (False, "")
+ except: return (False, None)
def notify_liquidsoap_started(self):
return self.services.notify_liquidsoap_started()
@@ -356,7 +365,7 @@ class AirtimeApiClient(object):
"""
#http://localhost/api/get-files-without-replay-gain/dir_id/1
return self.services.get_files_without_replay_gain(dir_id=dir_id)
-
+
def get_files_without_silan_value(self):
"""
Download a list of files that need to have their cue in/out value
@@ -372,7 +381,7 @@ class AirtimeApiClient(object):
"""
self.logger.debug(self.services.update_replay_gain_value(
_post_data={'data': json.dumps(pairs)}))
-
+
def update_cue_values_by_silan(self, pairs):
"""
'pairs' is a list of pairs in (x, y), where x is the file's database
diff --git a/python_apps/pypo/airtime-liquidsoap-init-d b/python_apps/pypo/airtime-liquidsoap-init-d
index 4180d5c67..7096bc59c 100755
--- a/python_apps/pypo/airtime-liquidsoap-init-d
+++ b/python_apps/pypo/airtime-liquidsoap-init-d
@@ -28,10 +28,10 @@ start () {
stop () {
monit unmonitor airtime-liquidsoap >/dev/null 2>&1
- /usr/lib/airtime/airtime_virtualenv/bin/python /usr/lib/airtime/pypo/bin/liquidsoap_scripts/liquidsoap_prepare_terminate.py
-
+ #send term signal after 10 seconds
+ timeout 10 /usr/lib/airtime/airtime_virtualenv/bin/python /usr/lib/airtime/pypo/bin/liquidsoap_scripts/liquidsoap_prepare_terminate.py
# Send TERM after 5 seconds, wait at most 30 seconds.
- start-stop-daemon --stop --oknodo --retry 5 --quiet --pidfile $PIDFILE
+ start-stop-daemon --stop --oknodo --retry=TERM/10/KILL/5 --quiet --pidfile $PIDFILE
rm -f $PIDFILE
}
diff --git a/python_apps/pypo/liquidsoap_scripts/liquidsoap_prepare_terminate.py b/python_apps/pypo/liquidsoap_scripts/liquidsoap_prepare_terminate.py
index e1dac82b6..2f632d9c7 100644
--- a/python_apps/pypo/liquidsoap_scripts/liquidsoap_prepare_terminate.py
+++ b/python_apps/pypo/liquidsoap_scripts/liquidsoap_prepare_terminate.py
@@ -6,14 +6,14 @@ try:
config = ConfigObj('/etc/airtime/pypo.cfg')
LS_HOST = config['ls_host']
LS_PORT = config['ls_port']
-
+
tn = telnetlib.Telnet(LS_HOST, LS_PORT)
tn.write("master_harbor.stop\n")
tn.write("live_dj_harbor.stop\n")
tn.write('exit\n')
tn.read_all()
-
+
except Exception, e:
print('Error loading config file: %s', e)
sys.exit()
-
\ No newline at end of file
+
diff --git a/python_apps/pypo/liquidsoap_scripts/ls_script.liq b/python_apps/pypo/liquidsoap_scripts/ls_script.liq
index cd01ad453..489d494a3 100644
--- a/python_apps/pypo/liquidsoap_scripts/ls_script.liq
+++ b/python_apps/pypo/liquidsoap_scripts/ls_script.liq
@@ -195,28 +195,81 @@ def check_dj_client(user,password) =
hd == "True"
end
-def append_dj_inputs(master_harbor_input_port, master_harbor_input_mount_point, dj_harbor_input_port, dj_harbor_input_mount_point, s) =
- if master_harbor_input_port != 0 and master_harbor_input_mount_point != "" and dj_harbor_input_port != 0 and dj_harbor_input_mount_point != "" then
- master_dj = mksafe(audio_to_stereo(input.harbor(id="master_harbor", master_harbor_input_mount_point, port=master_harbor_input_port, auth=check_master_dj_client,
- max=40., on_connect=master_dj_connect, on_disconnect=master_dj_disconnect)))
- dj_live = mksafe(audio_to_stereo(input.harbor(id="live_dj_harbor", dj_harbor_input_mount_point, port=dj_harbor_input_port, auth=check_dj_client,
- max=40., on_connect=live_dj_connect, on_disconnect=live_dj_disconnect)))
+def append_dj_inputs(master_harbor_input_port,
+ master_harbor_input_mount_point,
+ dj_harbor_input_port,
+ dj_harbor_input_mount_point,
+ s) =
+ if master_harbor_input_port != 0
+ and master_harbor_input_mount_point != ""
+ and dj_harbor_input_port != 0
+ and dj_harbor_input_mount_point != "" then
+
+ master_dj = mksafe(
+ audio_to_stereo(
+ input.harbor(id="master_harbor",
+ master_harbor_input_mount_point,
+ port=master_harbor_input_port,
+ auth=check_master_dj_client,
+ max=40.,
+ on_connect=master_dj_connect,
+ on_disconnect=master_dj_disconnect)))
+
+ dj_live = mksafe(
+ audio_to_stereo(
+ input.harbor(id="live_dj_harbor",
+ dj_harbor_input_mount_point,
+ port=dj_harbor_input_port,
+ auth=check_dj_client,
+ max=40.,
+ on_connect=live_dj_connect,
+ on_disconnect=live_dj_disconnect)))
ignore(output.dummy(master_dj, fallible=true))
ignore(output.dummy(dj_live, fallible=true))
- switch(id="master_dj_switch", track_sensitive=false, transitions=[transition, transition, transition], [({!master_dj_enabled},master_dj), ({!live_dj_enabled},dj_live), ({true}, s)])
+
+ switch(id="master_dj_switch",
+ track_sensitive=false,
+ transitions=[transition, transition, transition],
+ [({!master_dj_enabled},master_dj),
+ ({!live_dj_enabled},dj_live),
+ ({true}, s)])
+
elsif master_harbor_input_port != 0 and master_harbor_input_mount_point != "" then
- master_dj = mksafe(audio_to_stereo(input.harbor(id="master_harbor", master_harbor_input_mount_point, port=master_harbor_input_port, auth=check_master_dj_client,
- max=40., on_connect=master_dj_connect, on_disconnect=master_dj_disconnect)))
+ master_dj = mksafe(
+ audio_to_stereo(
+ input.harbor(id="master_harbor",
+ master_harbor_input_mount_point,
+ port=master_harbor_input_port,
+ auth=check_master_dj_client,
+ max=40.,
+ on_connect=master_dj_connect,
+ on_disconnect=master_dj_disconnect)))
+
ignore(output.dummy(master_dj, fallible=true))
- switch(id="master_dj_switch", track_sensitive=false, transitions=[transition, transition], [({!master_dj_enabled},master_dj), ({true}, s)])
+ switch(id="master_dj_switch",
+ track_sensitive=false,
+ transitions=[transition, transition],
+ [({!master_dj_enabled},master_dj), ({true}, s)])
+
elsif dj_harbor_input_port != 0 and dj_harbor_input_mount_point != "" then
- dj_live = mksafe(audio_to_stereo(input.harbor(id="live_dj_harbor", dj_harbor_input_mount_point, port=dj_harbor_input_port, auth=check_dj_client,
- max=40., on_connect=live_dj_connect, on_disconnect=live_dj_disconnect)))
+ dj_live = mksafe(
+ audio_to_stereo(
+ input.harbor(id="live_dj_harbor",
+ dj_harbor_input_mount_point,
+ port=dj_harbor_input_port,
+ auth=check_dj_client,
+ max=40.,
+ on_connect=live_dj_connect,
+ on_disconnect=live_dj_disconnect)))
ignore(output.dummy(dj_live, fallible=true))
- switch(id="live_dj_switch", track_sensitive=false, transitions=[transition, transition], [({!live_dj_enabled},dj_live), ({true}, s)])
+
+ switch(id="live_dj_switch",
+ track_sensitive=false,
+ transitions=[transition, transition],
+ [({!live_dj_enabled},dj_live), ({true}, s)])
else
s
end
diff --git a/python_apps/pypo/monit-airtime-playout.cfg b/python_apps/pypo/monit-airtime-playout.cfg
index 5b096c72a..453f4efec 100644
--- a/python_apps/pypo/monit-airtime-playout.cfg
+++ b/python_apps/pypo/monit-airtime-playout.cfg
@@ -5,5 +5,5 @@
check process airtime-playout
with pidfile "/var/run/airtime-playout.pid"
- start program = "/etc/init.d/airtime-playout monit-restart" with timeout 5 seconds
+ start program = "/etc/init.d/airtime-playout start" with timeout 5 seconds
stop program = "/etc/init.d/airtime-playout stop"
diff --git a/python_apps/pypo/pypocli.py b/python_apps/pypo/pypocli.py
index ea8950d41..93a1718aa 100644
--- a/python_apps/pypo/pypocli.py
+++ b/python_apps/pypo/pypocli.py
@@ -176,7 +176,7 @@ if __name__ == '__main__':
sys.exit()
api_client = api_client.AirtimeApiClient()
-
+
ReplayGainUpdater.start_reply_gain(api_client)
api_client.register_component("pypo")
diff --git a/python_apps/pypo/pypofetch.py b/python_apps/pypo/pypofetch.py
index ec3ef11ce..2d6ad0fb5 100644
--- a/python_apps/pypo/pypofetch.py
+++ b/python_apps/pypo/pypofetch.py
@@ -18,7 +18,8 @@ from std_err_override import LogWriter
from configobj import ConfigObj
# configure logging
-logging.config.fileConfig("logging.cfg")
+logging_cfg = os.path.join(os.path.dirname(__file__), "logging.cfg")
+logging.config.fileConfig(logging_cfg)
logger = logging.getLogger()
LogWriter.override_std_err(logger)
@@ -132,9 +133,10 @@ class PypoFetch(Thread):
elif(sourcename == "live_dj"):
command += "live_dj_harbor.kick\n"
- lock.acquire()
try:
+ lock.acquire()
tn = telnetlib.Telnet(LS_HOST, LS_PORT)
+ logger.info(command)
tn.write(command)
tn.write('exit\n')
tn.read_all()
@@ -143,6 +145,24 @@ class PypoFetch(Thread):
finally:
lock.release()
+ @staticmethod
+ def telnet_send(logger, lock, commands):
+ try:
+ lock.acquire()
+
+ tn = telnetlib.Telnet(LS_HOST, LS_PORT)
+ for i in commands:
+ logger.info(i)
+ tn.write(i)
+
+ tn.write('exit\n')
+ tn.read_all()
+ except Exception, e:
+ logger.error(str(e))
+ finally:
+ lock.release()
+
+
@staticmethod
def switch_source(logger, lock, sourcename, status):
logger.debug('Switching source: %s to "%s" status', sourcename, status)
@@ -159,16 +179,26 @@ class PypoFetch(Thread):
else:
command += "stop\n"
- lock.acquire()
- try:
- tn = telnetlib.Telnet(LS_HOST, LS_PORT)
- tn.write(command)
- tn.write('exit\n')
- tn.read_all()
- except Exception, e:
- logger.error(str(e))
- finally:
- lock.release()
+ PypoFetch.telnet_send(logger, lock, [command])
+
+
+ #TODO: Merge this with switch_source
+ def switch_source_temp(self, sourcename, status):
+ self.logger.debug('Switching source: %s to "%s" status', sourcename, status)
+ command = "streams."
+ if sourcename == "master_dj":
+ command += "master_dj_"
+ elif sourcename == "live_dj":
+ command += "live_dj_"
+ elif sourcename == "scheduled_play":
+ command += "scheduled_play_"
+
+ if status == "on":
+ command += "start\n"
+ else:
+ command += "stop\n"
+
+ return command
"""
grabs some information that are needed to be set on bootstrap time
@@ -179,19 +209,25 @@ class PypoFetch(Thread):
info = self.api_client.get_bootstrap_info()
if info is None:
self.logger.error('Unable to get bootstrap info.. Exiting pypo...')
- sys.exit(1)
else:
self.logger.debug('info:%s', info)
+ commands = []
for k, v in info['switch_status'].iteritems():
- self.switch_source(self.logger, self.telnet_lock, k, v)
- self.update_liquidsoap_stream_format(info['stream_label'])
- self.update_liquidsoap_station_name(info['station_name'])
- self.update_liquidsoap_transition_fade(info['transition_fade'])
+ commands.append(self.switch_source_temp(k, v))
+
+ stream_format = info['stream_label']
+ station_name = info['station_name']
+ fade = info['transition_fade']
+
+ commands.append(('vars.stream_metadata_type %s\n' % stream_format).encode('utf-8'))
+ commands.append(('vars.station_name %s\n' % station_name).encode('utf-8'))
+ commands.append(('vars.default_dj_fade %s\n' % fade).encode('utf-8'))
+ PypoFetch.telnet_send(self.logger, self.telnet_lock, commands)
def restart_liquidsoap(self):
- self.telnet_lock.acquire()
try:
+ self.telnet_lock.acquire()
self.logger.info("Restarting Liquidsoap")
subprocess.call('/etc/init.d/airtime-liquidsoap restart', shell=True)
@@ -217,7 +253,7 @@ class PypoFetch(Thread):
self.set_bootstrap_variables()
#get the most up to date schedule, which will #initiate the process
#of making sure Liquidsoap is playing the schedule
- self.manual_schedule_fetch()
+ self.persistent_manual_schedule_fetch(max_attempts=5)
except Exception, e:
self.logger.error(str(e))
@@ -322,16 +358,21 @@ class PypoFetch(Thread):
This function updates the bootup time variable in Liquidsoap script
"""
- self.telnet_lock.acquire()
try:
+ self.telnet_lock.acquire()
tn = telnetlib.Telnet(LS_HOST, LS_PORT)
# update the boot up time of Liquidsoap. Since Liquidsoap is not restarting,
# we are manually adjusting the bootup time variable so the status msg will get
# updated.
current_time = time.time()
boot_up_time_command = "vars.bootup_time " + str(current_time) + "\n"
+ self.logger.info(boot_up_time_command)
tn.write(boot_up_time_command)
- tn.write("streams.connection_status\n")
+
+ connection_status = "streams.connection_status\n"
+ self.logger.info(connection_status)
+ tn.write(connection_status)
+
tn.write('exit\n')
output = tn.read_all()
@@ -356,6 +397,7 @@ class PypoFetch(Thread):
if(status == "true"):
self.api_client.notify_liquidsoap_status("OK", stream_id, str(fake_time))
+
def update_liquidsoap_stream_format(self, stream_format):
# Push stream metadata to liquidsoap
# TODO: THIS LIQUIDSOAP STUFF NEEDS TO BE MOVED TO PYPO-PUSH!!!
@@ -395,8 +437,8 @@ class PypoFetch(Thread):
self.logger.info(LS_HOST)
self.logger.info(LS_PORT)
- self.telnet_lock.acquire()
try:
+ self.telnet_lock.acquire()
tn = telnetlib.Telnet(LS_HOST, LS_PORT)
command = ('vars.station_name %s\n' % station_name).encode('utf-8')
self.logger.info(command)
@@ -488,10 +530,20 @@ class PypoFetch(Thread):
self.process_schedule(self.schedule_data)
return success
+ def persistent_manual_schedule_fetch(self, max_attempts=1):
+ success = False
+ num_attempts = 0
+ while not success and num_attempts < max_attempts:
+ success = self.manual_schedule_fetch()
+ num_attempts += 1
+
+ return success
+
+
def main(self):
# Bootstrap: since we are just starting up, we need to grab the
# most recent schedule. After that we can just wait for updates.
- success = self.manual_schedule_fetch()
+ success = self.persistent_manual_schedule_fetch(max_attempts=5)
if success:
self.logger.info("Bootstrap schedule received: %s", self.schedule_data)
self.set_bootstrap_variables()
@@ -519,7 +571,7 @@ class PypoFetch(Thread):
self.handle_message(message)
except Empty, e:
self.logger.info("Queue timeout. Fetching schedule manually")
- self.manual_schedule_fetch()
+ self.persistent_manual_schedule_fetch(max_attempts=5)
except Exception, e:
import traceback
top = traceback.format_exc()
diff --git a/python_apps/pypo/pyponotify.py b/python_apps/pypo/pyponotify.py
index 9c2f1688c..797d1ce9b 100644
--- a/python_apps/pypo/pyponotify.py
+++ b/python_apps/pypo/pyponotify.py
@@ -43,7 +43,7 @@ parser.add_option("-t", "--time", help="Liquidsoap boot up time", action="store"
parser.add_option("-x", "--source-name", help="source connection name", metavar="source_name")
parser.add_option("-y", "--source-status", help="source connection status", metavar="source_status")
parser.add_option("-w", "--webstream", help="JSON metadata associated with webstream", metavar="json_data")
-parser.add_option("-n", "--liquidsoap-started", help="notify liquidsoap started", metavar="json_data", action="store_true", default=True)
+parser.add_option("-n", "--liquidsoap-started", help="notify liquidsoap started", metavar="json_data", action="store_true", default=False)
# parse options
diff --git a/python_apps/pypo/pypopush.py b/python_apps/pypo/pypopush.py
index 6fedfab1b..f438b3bb1 100644
--- a/python_apps/pypo/pypopush.py
+++ b/python_apps/pypo/pypopush.py
@@ -9,6 +9,7 @@ import logging.config
import telnetlib
import calendar
import math
+import os
from pypofetch import PypoFetch
from Queue import Empty
@@ -21,7 +22,8 @@ from configobj import ConfigObj
# configure logging
-logging.config.fileConfig("logging.cfg")
+logging_cfg = os.path.join(os.path.dirname(__file__), "logging.cfg")
+logging.config.fileConfig(logging_cfg)
logger = logging.getLogger()
LogWriter.override_std_err(logger)
@@ -249,7 +251,7 @@ class PypoPush(Thread):
self.start_web_stream_buffer(current_item)
self.start_web_stream(current_item)
if is_file(current_item):
- self.modify_cue_point(file_chain[0])
+ file_chain = self.modify_first_link_cue_point(file_chain)
self.push_to_liquidsoap(file_chain)
#we've changed the queue, so let's refetch it
liquidsoap_queue_approx = self.get_queue_items_from_liquidsoap()
@@ -279,7 +281,7 @@ class PypoPush(Thread):
chain_to_push = file_chain[problem_at_iteration:]
if len(chain_to_push) > 0:
- self.modify_cue_point(chain_to_push[0])
+ chain_to_push = self.modify_first_link_cue_point(chain_to_push)
self.push_to_liquidsoap(chain_to_push)
@@ -363,6 +365,18 @@ class PypoPush(Thread):
original_cue_in_td = timedelta(seconds=float(link['cue_in']))
link['cue_in'] = self.date_interval_to_seconds(original_cue_in_td) + diff_sec
+ def modify_first_link_cue_point(self, chain):
+ if not len(chain):
+ return []
+
+ first_link = chain[0]
+
+ self.modify_cue_point(first_link)
+ if float(first_link['cue_in']) >= float(first_link['cue_out']):
+ chain = chain [1:]
+
+ return chain
+
"""
Returns two chains, original chain and current_chain. current_chain is a subset of
original_chain but can also be equal to original chain.
diff --git a/python_apps/pypo/tests/run_tests.sh b/python_apps/pypo/tests/run_tests.sh
new file mode 100755
index 000000000..830a9bb85
--- /dev/null
+++ b/python_apps/pypo/tests/run_tests.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+which py.test
+pytest_exist=$?
+
+if [ "$pytest_exist" != "0" ]; then
+ echo "Need to have py.test installed. Exiting..."
+ exit 1
+fi
+
+SCRIPT=`readlink -f $0`
+# Absolute directory this script is in
+SCRIPTPATH=`dirname $SCRIPT`
+
+export PYTHONPATH=$PYTHONPATH:$SCRIPTPATH/..:$SCRIPTPATH/../..
+
+py.test
+
diff --git a/python_apps/pypo/tests/test_modify_cue_in.py b/python_apps/pypo/tests/test_modify_cue_in.py
new file mode 100644
index 000000000..da17fd53f
--- /dev/null
+++ b/python_apps/pypo/tests/test_modify_cue_in.py
@@ -0,0 +1,26 @@
+from pypopush import PypoPush
+from threading import Lock
+from Queue import Queue
+
+import datetime
+
+pypoPush_q = Queue()
+telnet_lock = Lock()
+
+pp = PypoPush(pypoPush_q, telnet_lock)
+
+def test_modify_cue_in():
+ link = pp.modify_first_link_cue_point([])
+ assert len(link) == 0
+
+ min_ago = datetime.datetime.utcnow() - datetime.timedelta(minutes = 1)
+ link = [{"start":min_ago.strftime("%Y-%m-%d-%H-%M-%S"),
+ "cue_in":"0", "cue_out":"30"}]
+ link = pp.modify_first_link_cue_point(link)
+ assert len(link) == 0
+
+ link = [{"start":min_ago.strftime("%Y-%m-%d-%H-%M-%S"),
+ "cue_in":"0", "cue_out":"70"}]
+ link = pp.modify_first_link_cue_point(link)
+ assert len(link) == 1
+
diff --git a/utils/airtime-import/airtime-import.py b/utils/airtime-import/airtime-import.py
index 1e55c732c..2b3ce03cd 100644
--- a/utils/airtime-import/airtime-import.py
+++ b/utils/airtime-import/airtime-import.py
@@ -170,6 +170,8 @@ def WatchAddAction(option, opt, value, parser):
print "%s added to watched folder list successfully" % path
else:
print "Adding a watched folder failed: %s" % res['msg']['error']
+ print "This error most likely caused by wrong permissions"
+ print "Try fixing this error by chmodding the parent directory(ies)"
else:
print "Given path is not a directory: %s" % path