diff --git a/VERSION b/VERSION index 682777c6f..c7aac0e6d 100644 --- a/VERSION +++ b/VERSION @@ -1,2 +1,2 @@ PRODUCT_ID=Airtime -PRODUCT_RELEASE=2.1.3 +PRODUCT_RELEASE=2.2.0 diff --git a/airtime_mvc/application/Bootstrap.php b/airtime_mvc/application/Bootstrap.php index db868cff6..72902ab6a 100644 --- a/airtime_mvc/application/Bootstrap.php +++ b/airtime_mvc/application/Bootstrap.php @@ -96,6 +96,7 @@ class Bootstrap extends Zend_Application_Bootstrap_Bootstrap $view->headScript()->appendScript("var baseUrl='$baseUrl'"); //scripts for now playing bar + $view->headScript()->appendFile($baseUrl.'/js/airtime/airtime_bootstrap.js?'.$CC_CONFIG['airtime_version'],'text/javascript'); $view->headScript()->appendFile($baseUrl.'/js/airtime/dashboard/helperfunctions.js?'.$CC_CONFIG['airtime_version'],'text/javascript'); $view->headScript()->appendFile($baseUrl.'/js/airtime/dashboard/dashboard.js?'.$CC_CONFIG['airtime_version'],'text/javascript'); $view->headScript()->appendFile($baseUrl.'/js/airtime/dashboard/versiontooltip.js?'.$CC_CONFIG['airtime_version'],'text/javascript'); @@ -112,8 +113,6 @@ class Bootstrap extends Zend_Application_Bootstrap_Bootstrap } $view->headScript()->appendScript("var userType = '$userType';"); - - 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/controllers/ApiController.php b/airtime_mvc/application/controllers/ApiController.php index 1e3cee844..6572774cc 100644 --- a/airtime_mvc/application/controllers/ApiController.php +++ b/airtime_mvc/application/controllers/ApiController.php @@ -313,7 +313,7 @@ class ApiController extends Zend_Controller_Action } //used by caller to determine if the airtime they are running or widgets in use is out of date. - $result['AIRTIME_API_VERSION'] = AIRTIME_API_VERSION; + $result['AIRTIME_API_VERSION'] = AIRTIME_API_VERSION; header("Content-type: text/javascript"); // If a callback is not given, then just provide the raw JSON. echo isset($_GET['callback']) ? $_GET['callback'].'('.json_encode($result).')' : json_encode($result); @@ -830,8 +830,8 @@ class ApiController extends Zend_Controller_Action if ($djtype == 'master') { //check against master - if ($username == Application_Model_Preference::GetLiveSteamMasterUsername() - && $password == Application_Model_Preference::GetLiveSteamMasterPassword()) { + if ($username == Application_Model_Preference::GetLiveStreamMasterUsername() + && $password == Application_Model_Preference::GetLiveStreamMasterPassword()) { $this->view->msg = true; } else { $this->view->msg = false; diff --git a/airtime_mvc/application/controllers/AudiopreviewController.php b/airtime_mvc/application/controllers/AudiopreviewController.php index d5103335c..45f3f0cb8 100644 --- a/airtime_mvc/application/controllers/AudiopreviewController.php +++ b/airtime_mvc/application/controllers/AudiopreviewController.php @@ -276,6 +276,7 @@ class AudiopreviewController extends Zend_Controller_Action 'element_artist' => isset($track['creator']) ? $track['creator'] : "", 'element_position' => $position, 'element_id' => ++$position, + 'mime' => isset($track['mime'])?$track['mime']:"" ); $elementMap['type'] = $track['type']; diff --git a/airtime_mvc/application/controllers/PreferenceController.php b/airtime_mvc/application/controllers/PreferenceController.php index 91a0021f4..8cfa1b85d 100644 --- a/airtime_mvc/application/controllers/PreferenceController.php +++ b/airtime_mvc/application/controllers/PreferenceController.php @@ -224,8 +224,8 @@ class PreferenceController extends Zend_Controller_Action // this goes into cc_pref table Application_Model_Preference::SetStreamLabelFormat($values['streamFormat']); - Application_Model_Preference::SetLiveSteamMasterUsername($values["master_username"]); - Application_Model_Preference::SetLiveSteamMasterPassword($values["master_password"]); + Application_Model_Preference::SetLiveStreamMasterUsername($values["master_username"]); + Application_Model_Preference::SetLiveStreamMasterPassword($values["master_password"]); Application_Model_Preference::SetDefaultTransitionFade($values["transition_fade"]); Application_Model_Preference::SetAutoTransition($values["auto_transition"]); Application_Model_Preference::SetAutoSwitch($values["auto_switch"]); diff --git a/airtime_mvc/application/controllers/ShowbuilderController.php b/airtime_mvc/application/controllers/ShowbuilderController.php index 9c4b8e750..d2d7a830a 100644 --- a/airtime_mvc/application/controllers/ShowbuilderController.php +++ b/airtime_mvc/application/controllers/ShowbuilderController.php @@ -189,8 +189,8 @@ class ShowbuilderController extends Zend_Controller_Action $menu["preview"] = array("name"=> "Preview", "icon" => "play"); //select the cursor - $menu["selCurs"] = array("name"=> "Select Cursor","icon" => "select-cursor"); - $menu["delCurs"] = array("name"=> "Remove Cursor","icon" => "select-cursor"); + $menu["selCurs"] = array("name"=> "Select cursor","icon" => "select-cursor"); + $menu["delCurs"] = array("name"=> "Remove cursor","icon" => "select-cursor"); if ($now < floatval($item->getDbEnds("U.u")) && $user->canSchedule($instance->getDbShowId())) { diff --git a/airtime_mvc/application/forms/AddShowWhen.php b/airtime_mvc/application/forms/AddShowWhen.php index a81c8d05d..e6d164022 100644 --- a/airtime_mvc/application/forms/AddShowWhen.php +++ b/airtime_mvc/application/forms/AddShowWhen.php @@ -143,10 +143,12 @@ class Application_Form_AddShowWhen extends Zend_Form_SubForm * upto this point */ if ($valid) { + $utc = new DateTimeZone('UTC'); + $localTimezone = new DateTimeZone(Application_Model_Preference::GetTimezone()); $show_start = new DateTime($start_time); - $show_start->setTimezone(new DateTimeZone('UTC')); + $show_start->setTimezone($utc); $show_end = new DateTime($end_time); - $show_end->setTimezone(new DateTimeZone('UTC')); + $show_end->setTimezone($utc); if ($formData["add_show_repeats"]) { @@ -155,7 +157,7 @@ class Application_Form_AddShowWhen extends Zend_Form_SubForm $date = Application_Model_Preference::GetShowsPopulatedUntil(); if (is_null($date)) { - $populateUntilDateTime = new DateTime("now", new DateTimeZone('UTC')); + $populateUntilDateTime = new DateTime("now", $utc); Application_Model_Preference::SetShowsPopulatedUntil($populateUntilDateTime); } else { $populateUntilDateTime = clone $date; @@ -164,7 +166,7 @@ class Application_Form_AddShowWhen extends Zend_Form_SubForm } elseif (!$formData["add_show_no_end"]) { $popUntil = $formData["add_show_end_date"]." ".$formData["add_show_end_time"]; $populateUntilDateTime = new DateTime($popUntil); - $populateUntilDateTime->setTimezone(new DateTimeZone('UTC')); + $populateUntilDateTime->setTimezone($utc); } //get repeat interval @@ -179,7 +181,14 @@ class Application_Form_AddShowWhen extends Zend_Form_SubForm /* Check first show * Continue if the first show does not overlap */ - $overlapping = Application_Model_Schedule::checkOverlappingShows($show_start, $show_end, $update, $instanceId); + if ($update) { + $overlapping = Application_Model_Schedule::checkOverlappingShows( + $show_start, $show_end, $update, null, $formData["add_show_id"]); + } else { + $overlapping = Application_Model_Schedule::checkOverlappingShows( + $show_start, $show_end); + } + //$overlapping = Application_Model_Schedule::checkOverlappingShows($show_start, $show_end, $update, $instanceId); /* Check if repeats overlap with previously scheduled shows * Do this for each show day @@ -196,8 +205,18 @@ class Application_Form_AddShowWhen extends Zend_Form_SubForm else $daysAdd = $day - $startDow; + /* In case we are crossing daylights saving time we need + * to convert show start and show end to local time before + * adding the interval for the next repeating show + */ + + $repeatShowStart->setTimezone($localTimezone); + $repeatShowEnd->setTimezone($localTimezone); $repeatShowStart->add(new DateInterval("P".$daysAdd."D")); $repeatShowEnd->add(new DateInterval("P".$daysAdd."D")); + //set back to UTC + $repeatShowStart->setTimezone($utc); + $repeatShowEnd->setTimezone($utc); } /* Here we are checking each repeating show by * the show day. @@ -208,9 +227,22 @@ class Application_Form_AddShowWhen extends Zend_Form_SubForm //this is a new show $overlapping = Application_Model_Schedule::checkOverlappingShows( $repeatShowStart, $repeatShowEnd); + + /* If the repeating show is rebroadcasted we need to check + * the rebroadcast dates relative to the repeating show + */ + if (!$overlapping && $formData['add_show_rebroadcast']) { + $overlapping = self::checkRebroadcastDates( + $repeatShowStart, $formData, $hours, $minutes); + } } else { $overlapping = Application_Model_Schedule::checkOverlappingShows( $repeatShowStart, $repeatShowEnd, $update, null, $formData["add_show_id"]); + + if (!$overlapping && $formData['add_show_rebroadcast']) { + $overlapping = self::checkRebroadcastDates( + $repeatShowStart, $formData, $hours, $minutes, true); + } } if ($overlapping) { @@ -218,8 +250,12 @@ class Application_Form_AddShowWhen extends Zend_Form_SubForm $this->getElement('add_show_duration')->setErrors(array('Cannot schedule overlapping shows')); break 1; } else { + $repeatShowStart->setTimezone($localTimezone); + $repeatShowEnd->setTimezone($localTimezone); $repeatShowStart->add(new DateInterval($interval)); $repeatShowEnd->add(new DateInterval($interval)); + $repeatShowStart->setTimezone($utc); + $repeatShowEnd->setTimezone($utc); } } } @@ -234,15 +270,8 @@ class Application_Form_AddShowWhen extends Zend_Form_SubForm $overlapping = Application_Model_Schedule::checkOverlappingShows($show_start, $show_end, $update, $instanceId); if (!$overlapping) { + $durationToAdd = "PT".$hours."H".$minutes."M"; for ($i = 1; $i <= 10; $i++) { - $hours = ltrim($hours, '0'); - if ($minutes != "00") { - $minutes = ltrim($minutes, '0'); - $durationToAdd = "PT".$hours."H".$minutes."I"; - } else { - $minutes = "0"; - $durationToAdd = "PT".$hours."H"; - } if (empty($formData["add_show_rebroadcast_date_absolute_".$i])) break; @@ -275,6 +304,39 @@ class Application_Form_AddShowWhen extends Zend_Form_SubForm return $valid; } + public function checkRebroadcastDates($repeatShowStart, $formData, $hours, $minutes, $showEdit=false) { + $overlapping = false; + for ($i = 1; $i <= 10; $i++) { + if (empty($formData["add_show_rebroadcast_date_".$i])) break; + $rebroadcastShowStart = clone $repeatShowStart; + /* formData is in local time so we need to set the + * show start back to local time + */ + $rebroadcastShowStart->setTimezone(new DateTimeZone( + Application_Model_Preference::GetTimezone())); + $rebroadcastWhenDays = explode(" ", $formData["add_show_rebroadcast_date_".$i]); + $rebroadcastWhenTime = explode(":", $formData["add_show_rebroadcast_time_".$i]); + $rebroadcastShowStart->add(new DateInterval("P".$rebroadcastWhenDays[0]."D")); + $rebroadcastShowStart->setTime($rebroadcastWhenTime[0], $rebroadcastWhenTime[1]); + $rebroadcastShowStart->setTimezone(new DateTimeZone('UTC')); + + $rebroadcastShowEnd = clone $rebroadcastShowStart; + $rebroadcastShowEnd->add(new DateInterval("PT".$hours."H".$minutes."M")); + + if ($showEdit) { + $overlapping = Application_Model_Schedule::checkOverlappingShows( + $rebroadcastShowStart, $rebroadcastShowEnd, true, null, $formData['add_show_id']); + } else { + $overlapping = Application_Model_Schedule::checkOverlappingShows( + $rebroadcastShowStart, $rebroadcastShowEnd); + } + + if ($overlapping) break; + } + + return $overlapping; + } + public function disable() { $elements = $this->getElements(); diff --git a/airtime_mvc/application/forms/EditAudioMD.php b/airtime_mvc/application/forms/EditAudioMD.php index e067b00a0..ba5b61fbf 100644 --- a/airtime_mvc/application/forms/EditAudioMD.php +++ b/airtime_mvc/application/forms/EditAudioMD.php @@ -33,9 +33,7 @@ class Application_Form_EditAudioMD extends Zend_Form $this->addElement('text', 'track_number', array( 'label' => 'Track:', 'class' => 'input_text', - 'filters' => array('StringTrim'), - 'validators' => array('Int'), - 'required' => true + 'filters' => array('StringTrim') )); // Add genre field diff --git a/airtime_mvc/application/forms/LiveStreamingPreferences.php b/airtime_mvc/application/forms/LiveStreamingPreferences.php index 8f7ac95c0..e66976c8b 100644 --- a/airtime_mvc/application/forms/LiveStreamingPreferences.php +++ b/airtime_mvc/application/forms/LiveStreamingPreferences.php @@ -45,7 +45,7 @@ class Application_Form_LiveStreamingPreferences extends Zend_Form_SubForm ->setAllowEmpty(true) ->setLabel('Master Username') ->setFilters(array('StringTrim')) - ->setValue(Application_Model_Preference::GetLiveSteamMasterUsername()) + ->setValue(Application_Model_Preference::GetLiveStreamMasterUsername()) ->setDecorators(array('ViewHelper')); $this->addElement($master_username); @@ -59,7 +59,7 @@ class Application_Form_LiveStreamingPreferences extends Zend_Form_SubForm $master_password->setAttrib('autocomplete', 'off') ->setAttrib('renderPassword','true') ->setAllowEmpty(true) - ->setValue(Application_Model_Preference::GetLiveSteamMasterPassword()) + ->setValue(Application_Model_Preference::GetLiveStreamMasterPassword()) ->setLabel('Master Password') ->setFilters(array('StringTrim')) ->setDecorators(array('ViewHelper')); diff --git a/airtime_mvc/application/models/Block.php b/airtime_mvc/application/models/Block.php index 4d62b8329..eb1aab691 100644 --- a/airtime_mvc/application/models/Block.php +++ b/airtime_mvc/application/models/Block.php @@ -319,12 +319,12 @@ SQL; if ($mins >59) { $hour = intval($mins/60); $hour = str_pad($hour, 2, "0", STR_PAD_LEFT); - $value = $mins%60; + $mins = $mins%60; } } $hour = str_pad($hour, 2, "0", STR_PAD_LEFT); - $value = str_pad($value, 2, "0", STR_PAD_LEFT); - $length = $hour.":".$value.":00"; + $mins = str_pad($mins, 2, "0", STR_PAD_LEFT); + $length = $hour.":".$mins.":00"; } return $length; diff --git a/airtime_mvc/application/models/PlayoutHistory.php b/airtime_mvc/application/models/PlayoutHistory.php index ba845fa33..7da1ff2c2 100644 --- a/airtime_mvc/application/models/PlayoutHistory.php +++ b/airtime_mvc/application/models/PlayoutHistory.php @@ -16,12 +16,12 @@ class Application_Model_PlayoutHistory private $opts; private $mDataPropMap = array( - "artist" => "file.artist_name", - "title" => "file.track_title", - "played" => "playout.played", - "length" => "file.length", - "composer" => "file.composer", - "copyright" => "file.copyright", + "artist" => "artist_name", + "title" => "track_title", + "played" => "played", + "length" => "length", + "composer" => "composer", + "copyright" => "copyright", ); public function __construct($p_startDT, $p_endDT, $p_opts) diff --git a/airtime_mvc/application/models/Preference.php b/airtime_mvc/application/models/Preference.php index 0cd058d41..8aad4364b 100644 --- a/airtime_mvc/application/models/Preference.php +++ b/airtime_mvc/application/models/Preference.php @@ -893,22 +893,22 @@ class Application_Model_Preference return (strlen($val) == 0) ? 0 : $val; } - public static function SetLiveSteamMasterUsername($value) + public static function SetLiveStreamMasterUsername($value) { self::setValue("live_stream_master_username", $value, false); } - public static function GetLiveSteamMasterUsername() + public static function GetLiveStreamMasterUsername() { return self::getValue("live_stream_master_username"); } - public static function SetLiveSteamMasterPassword($value) + public static function SetLiveStreamMasterPassword($value) { self::setValue("live_stream_master_password", $value, false); } - public static function GetLiveSteamMasterPassword() + public static function GetLiveStreamMasterPassword() { return self::getValue("live_stream_master_password"); } @@ -1094,7 +1094,7 @@ class Application_Model_Preference - public static function getOrderingMap($pref_param) + public static function getOrderingMap($pref_param) { $v = self::getValue($pref_param, true); diff --git a/airtime_mvc/application/models/Show.php b/airtime_mvc/application/models/Show.php index bb58409fd..5da348b52 100644 --- a/airtime_mvc/application/models/Show.php +++ b/airtime_mvc/application/models/Show.php @@ -1789,9 +1789,9 @@ SQL; $showInstance = new Application_Model_ShowInstance( $show["instance_id"]); - $showContent = $showInstance->getShowListContent(); + //$showContent = $showInstance->getShowListContent(); - $options["show_empty"] = empty($showContent) ? 1 : 0; + $options["show_empty"] = ($showInstance->showEmpty()) ? 1 : 0; $events[] = &self::makeFullCalendarEvent($show, $options, $startsDT, $endsDT, $startsEpochStr, $endsEpochStr); diff --git a/airtime_mvc/application/models/ShowInstance.php b/airtime_mvc/application/models/ShowInstance.php index b08a0e37c..e657494f9 100644 --- a/airtime_mvc/application/models/ShowInstance.php +++ b/airtime_mvc/application/models/ShowInstance.php @@ -661,6 +661,28 @@ SQL; return $returnStr; } + + public function showEmpty() + { + $sql = <<= 0 + AND ((s.stream_id IS NOT NULL) + OR (s.file_id IS NOT NULL)) LIMIT 1 +SQL; + # TODO : use prepareAndExecute properly + $res = Application_Common_Database::prepareAndExecute($sql, + array( ':instance_id' => $this->_instanceId ), 'all' ); + # TODO : A bit retarded. fix this later + foreach ($res as $r) { + return false; + } + return true; + + } + public function getShowListContent() { $con = Propel::getConnection(); @@ -670,14 +692,15 @@ SELECT * FROM ( (SELECT s.starts, 0::INTEGER as type , - f.id AS item_id, + f.id AS item_id, f.track_title, - f.album_title AS album, - f.genre AS genre, - f.length AS length, - f.artist_name AS creator, - f.file_exists AS EXISTS, - f.filepath AS filepath + f.album_title AS album, + f.genre AS genre, + f.length AS length, + f.artist_name AS creator, + f.file_exists AS EXISTS, + f.filepath AS filepath, + f.mime AS mime FROM cc_schedule AS s LEFT JOIN cc_files AS f ON f.id = s.file_id WHERE s.instance_id = :instance_id1 @@ -688,12 +711,13 @@ FROM ( 1::INTEGER as type, ws.id AS item_id, (ws.name || ': ' || ws.url) AS title, - null AS album, - null AS genre, - ws.length AS length, - sub.login AS creator, - 't'::boolean AS EXISTS, - ws.url AS filepath + null AS album, + null AS genre, + ws.length AS length, + sub.login AS creator, + 't'::boolean AS EXISTS, + ws.url AS filepath, + ws.mime as mime FROM cc_schedule AS s LEFT JOIN cc_webstream AS ws ON ws.id = s.stream_id LEFT JOIN cc_subjs AS sub ON ws.creator_id = sub.id diff --git a/airtime_mvc/application/models/StoredFile.php b/airtime_mvc/application/models/StoredFile.php index 2529bd34e..ffdb31d1f 100644 --- a/airtime_mvc/application/models/StoredFile.php +++ b/airtime_mvc/application/models/StoredFile.php @@ -196,6 +196,10 @@ class Application_Model_StoredFile if (isset($this->_dbMD[$dbColumn])) { $propelColumn = $this->_dbMD[$dbColumn]; $method = "set$propelColumn"; + + /* We need to set track_number to null if it is an empty string + * because propel defaults empty strings to zeros */ + if ($dbColumn == "track_number" && empty($mdValue)) $mdValue = null; $this->_file->$method($mdValue); } } diff --git a/airtime_mvc/application/models/StreamSetting.php b/airtime_mvc/application/models/StreamSetting.php index a5740c70f..cdd7747b7 100644 --- a/airtime_mvc/application/models/StreamSetting.php +++ b/airtime_mvc/application/models/StreamSetting.php @@ -219,6 +219,25 @@ class Application_Model_StreamSetting } } + /* + * Sets indivisual stream setting. + * + * $data - data array. $data is []. + * TODO: Make this SQL a prepared statement! + * + * Do not remove this function. It is called by airtime-system.php + */ + public static function setIndividualStreamSetting($data) + { + $con = Propel::getConnection(); + + foreach ($data as $keyname => $v) { + $sql = "UPDATE cc_stream_setting SET value='$v' WHERE keyname='$keyname'"; + $con->exec($sql); + } + } + + /* * Stores liquidsoap status if $boot_time > save time. * save time is the time that user clicked save on stream setting page diff --git a/airtime_mvc/application/models/airtime/CcBlockcontents.php b/airtime_mvc/application/models/airtime/CcBlockcontents.php index 5fcfbbf24..caae46f6a 100644 --- a/airtime_mvc/application/models/airtime/CcBlockcontents.php +++ b/airtime_mvc/application/models/airtime/CcBlockcontents.php @@ -5,7 +5,7 @@ /** * Skeleton subclass for representing a row from the 'cc_blockcontents' table. * - * + * * * You should add additional methods to this class to meet the * application requirements. This class will only be generated as @@ -44,11 +44,16 @@ class CcBlockcontents extends BaseCcBlockcontents { */ public function setDbFadein($v) { + $microsecond = 0; if ($v instanceof DateTime) { $dt = $v; } else if (preg_match('/^[0-9]{1,2}(\.\d{1,6})?$/', $v)) { - $dt = DateTime::createFromFormat("s.u", $v); + // in php 5.3.2 createFromFormat() with "u" is not supported(bug) + // Hence we need to do parsing. + $info = explode('.', $v); + $microsecond = $info[1]; + $dt = DateTime::createFromFormat("s", $info[0]); } else { try { @@ -58,7 +63,11 @@ class CcBlockcontents extends BaseCcBlockcontents { } } - $this->fadein = $dt->format('H:i:s.u'); + if ($microsecond == 0) { + $this->fadein = $dt->format('H:i:s.u'); + } else { + $this->fadein = $dt->format('H:i:s').".".$microsecond; + } $this->modifiedColumns[] = CcBlockcontentsPeer::FADEIN; return $this; @@ -72,11 +81,16 @@ class CcBlockcontents extends BaseCcBlockcontents { */ public function setDbFadeout($v) { + $microsecond = 0; if ($v instanceof DateTime) { $dt = $v; } else if (preg_match('/^[0-9]{1,2}(\.\d{1,6})?$/', $v)) { - $dt = DateTime::createFromFormat("s.u", $v); + // in php 5.3.2 createFromFormat() with "u" is not supported(bug) + // Hence we need to do parsing. + $info = explode('.', $v); + $microsecond = $info[1]; + $dt = DateTime::createFromFormat("s", $info[0]); } else { try { @@ -85,8 +99,12 @@ class CcBlockcontents extends BaseCcBlockcontents { throw new PropelException('Error parsing date/time value: ' . var_export($v, true), $x); } } - - $this->fadeout = $dt->format('H:i:s.u'); + + if ($microsecond == 0) { + $this->fadeout = $dt->format('H:i:s.u'); + } else { + $this->fadeout = $dt->format('H:i:s').".".$microsecond; + } $this->modifiedColumns[] = CcBlockcontentsPeer::FADEOUT; return $this; diff --git a/airtime_mvc/application/models/airtime/CcPlaylistcontents.php b/airtime_mvc/application/models/airtime/CcPlaylistcontents.php index b5125de32..ab0aa6d56 100644 --- a/airtime_mvc/application/models/airtime/CcPlaylistcontents.php +++ b/airtime_mvc/application/models/airtime/CcPlaylistcontents.php @@ -43,11 +43,16 @@ class CcPlaylistcontents extends BaseCcPlaylistcontents { */ public function setDbFadein($v) { + $microsecond = 0; if ($v instanceof DateTime) { $dt = $v; } else if (preg_match('/^[0-9]{1,2}(\.\d{1,6})?$/', $v)) { - $dt = DateTime::createFromFormat("s.u", $v); + // in php 5.3.2 createFromFormat() with "u" is not supported(bug) + // Hence we need to do parsing. + $info = explode('.', $v); + $microsecond = $info[1]; + $dt = DateTime::createFromFormat("s", $info[0]); } else { try { @@ -57,7 +62,11 @@ class CcPlaylistcontents extends BaseCcPlaylistcontents { } } - $this->fadein = $dt->format('H:i:s.u'); + if ($microsecond == 0) { + $this->fadein = $dt->format('H:i:s.u'); + } else { + $this->fadein = $dt->format('H:i:s').".".$microsecond; + } $this->modifiedColumns[] = CcPlaylistcontentsPeer::FADEIN; return $this; @@ -71,11 +80,16 @@ class CcPlaylistcontents extends BaseCcPlaylistcontents { */ public function setDbFadeout($v) { + $microsecond = 0; if ($v instanceof DateTime) { $dt = $v; } else if (preg_match('/^[0-9]{1,2}(\.\d{1,6})?$/', $v)) { - $dt = DateTime::createFromFormat("s.u", $v); + // in php 5.3.2 createFromFormat() with "u" is not supported(bug) + // Hence we need to do parsing. + $info = explode('.', $v); + $microsecond = $info[1]; + $dt = DateTime::createFromFormat("s", $info[0]); } else { try { @@ -85,7 +99,11 @@ class CcPlaylistcontents extends BaseCcPlaylistcontents { } } - $this->fadeout = $dt->format('H:i:s.u'); + if ($microsecond == 0) { + $this->fadeout = $dt->format('H:i:s.u'); + } else { + $this->fadeout = $dt->format('H:i:s').".".$microsecond; + } $this->modifiedColumns[] = CcPlaylistcontentsPeer::FADEOUT; return $this; diff --git a/airtime_mvc/application/models/airtime/CcSchedule.php b/airtime_mvc/application/models/airtime/CcSchedule.php index 75a01e758..e051df6c3 100644 --- a/airtime_mvc/application/models/airtime/CcSchedule.php +++ b/airtime_mvc/application/models/airtime/CcSchedule.php @@ -107,11 +107,16 @@ class CcSchedule extends BaseCcSchedule { */ public function setDbFadeIn($v) { + $microsecond = 0; if ($v instanceof DateTime) { $dt = $v; } else if (preg_match('/^[0-9]{1,2}(\.\d{1,6})?$/', $v)) { - $dt = DateTime::createFromFormat("s.u", $v); + // in php 5.3.2 createFromFormat() with "u" is not supported(bug) + // Hence we need to do parsing. + $info = explode('.', $v); + $microsecond = $info[1]; + $dt = DateTime::createFromFormat("s", $info[0]); } else { try { @@ -120,7 +125,12 @@ class CcSchedule extends BaseCcSchedule { throw new PropelException('Error parsing date/time value: ' . var_export($v, true), $x); } } - $this->fade_in = $dt->format('H:i:s.u'); + + if ($microsecond == 0) { + $this->fadein = $dt->format('H:i:s.u'); + } else { + $this->fadein = $dt->format('H:i:s').".".$microsecond; + } $this->modifiedColumns[] = CcSchedulePeer::FADE_IN; return $this; @@ -134,11 +144,16 @@ class CcSchedule extends BaseCcSchedule { */ public function setDbFadeOut($v) { + $microsecond = 0; if ($v instanceof DateTime) { $dt = $v; } else if (preg_match('/^[0-9]{1,2}(\.\d{1,6})?$/', $v)) { - $dt = DateTime::createFromFormat("s.u", $v); + // in php 5.3.2 createFromFormat() with "u" is not supported(bug) + // Hence we need to do parsing. + $info = explode('.', $v); + $microsecond = $info[1]; + $dt = DateTime::createFromFormat("s", $info[0]); } else { try { @@ -148,7 +163,11 @@ class CcSchedule extends BaseCcSchedule { } } - $this->fade_out = $dt->format('H:i:s.u'); + if ($microsecond == 0) { + $this->fadeout = $dt->format('H:i:s.u'); + } else { + $this->fadeout = $dt->format('H:i:s').".".$microsecond; + } $this->modifiedColumns[] = CcSchedulePeer::FADE_OUT; return $this; diff --git a/airtime_mvc/application/views/scripts/audiopreview/audio-preview.phtml b/airtime_mvc/application/views/scripts/audiopreview/audio-preview.phtml index b4ec52bdf..f76249b9f 100644 --- a/airtime_mvc/application/views/scripts/audiopreview/audio-preview.phtml +++ b/airtime_mvc/application/views/scripts/audiopreview/audio-preview.phtml @@ -4,8 +4,8 @@ playlistID" ?> playlistIndex" ?> blockId)): ?> - blockId" ?> - blockIndex" ?> + + uri)): ?> @@ -51,7 +51,7 @@
unmute -
+
diff --git a/airtime_mvc/application/views/scripts/playlist/update.phtml b/airtime_mvc/application/views/scripts/playlist/update.phtml index a51fd37db..70176ff9e 100644 --- a/airtime_mvc/application/views/scripts/playlist/update.phtml +++ b/airtime_mvc/application/views/scripts/playlist/update.phtml @@ -21,7 +21,7 @@ if ($item['type'] == 2) { -
"> +
" blocktype="">
diff --git a/airtime_mvc/public/css/playlist_builder.css b/airtime_mvc/public/css/playlist_builder.css index ea8a35586..43b942a7f 100644 --- a/airtime_mvc/public/css/playlist_builder.css +++ b/airtime_mvc/public/css/playlist_builder.css @@ -85,7 +85,7 @@ font-size: 9px; height: 15px; /*right: 35px;*/ - width: 120px; + width: 124px; margin-top: 2px; cursor: pointer; color: #fff; @@ -584,4 +584,4 @@ li.spl_empty { } .expand-block-separate { border-top: 1px solid #5B5B5B; -} \ No newline at end of file +} diff --git a/airtime_mvc/public/js/airtime/airtime_bootstrap.js b/airtime_mvc/public/js/airtime/airtime_bootstrap.js new file mode 100644 index 000000000..632d61627 --- /dev/null +++ b/airtime_mvc/public/js/airtime/airtime_bootstrap.js @@ -0,0 +1,5 @@ +$(document).ready(function() { + $.ajaxSetup({ + cache: false + }); +}); diff --git a/airtime_mvc/public/js/airtime/audiopreview/preview_jplayer.js b/airtime_mvc/public/js/airtime/audiopreview/preview_jplayer.js index 228e6bbd1..a90f8d46f 100644 --- a/airtime_mvc/public/js/airtime/audiopreview/preview_jplayer.js +++ b/airtime_mvc/public/js/airtime/audiopreview/preview_jplayer.js @@ -123,6 +123,7 @@ function buildplaylist(p_url, p_playIndex) { var media; var index; var total = 0; + var skipped = 0; for(index in data) { if (data[index]['type'] == 0) { @@ -146,22 +147,30 @@ function buildplaylist(p_url, p_playIndex) { artist: data[index]['element_artist'], wav:data[index]['uri'] }; - } + } else { + // skip this track since it's not supported + console.log("continue"); + skipped++; + continue; + } } else if (data[index]['type'] == 1) { media = {title: data[index]['element_title'], artist: data[index]['element_artist'], mp3:data[index]['uri'] }; } + console.log(data[index]); if (media && isAudioSupported(data[index]['mime'])) { - myPlaylist[index] = media; + // javascript doesn't support associative array with numeric key + // so we need to remove the gap if we skip any of tracks due to + // browser incompatibility. + myPlaylist[index-skipped] = media; } // we should create a map according to the new position in the // player itself total is the index on the player _idToPostionLookUp[data[index]['element_id']] = total; total++; } - _playlist_jplayer.setPlaylist(myPlaylist); _playlist_jplayer.option("autoPlay", true); play(p_playIndex); diff --git a/airtime_mvc/public/js/airtime/common/common.js b/airtime_mvc/public/js/airtime/common/common.js index 06ae37fb7..8d15efa7a 100644 --- a/airtime_mvc/public/js/airtime/common/common.js +++ b/airtime_mvc/public/js/airtime/common/common.js @@ -53,7 +53,8 @@ function open_audio_preview(type, id, audioFileTitle, audioFileArtist) { if(index != -1){ audioFileTitle = audioFileTitle.substring(0,index); } - openPreviewWindow(baseUrl+'/audiopreview/audio-preview/audioFileID/'+id+'/audioFileArtist/'+audioFileArtist+'/audioFileTitle/'+audioFileTitle+'/type/'+type); + openPreviewWindow(baseUrl+'audiopreview/audio-preview/audioFileID/'+id+'/audioFileArtist/'+encodeURIComponent(audioFileArtist)+'/audioFileTitle/'+encodeURIComponent(audioFileTitle)+'/type/'+type); + _preview_window.focus(); } diff --git a/airtime_mvc/public/js/airtime/library/library.js b/airtime_mvc/public/js/airtime/library/library.js index 5f4b69e31..4a4d77ffc 100644 --- a/airtime_mvc/public/js/airtime/library/library.js +++ b/airtime_mvc/public/js/airtime/library/library.js @@ -815,9 +815,10 @@ var AIRTIME = (function(AIRTIME) { //playlist screen if this is the currently edited playlist. if ((data.ftype === "playlist" || data.ftype === "block") && screen === "playlist") { callback = function() { - + aMedia = []; + aMedia.push({"id": data.id, "type": data.ftype}); if (confirm('Are you sure you want to delete the selected item?')) { - AIRTIME.playlist.fnDelete(data.id); + AIRTIME.library.fnDeleteItems(aMedia); } }; } diff --git a/airtime_mvc/public/js/airtime/library/spl.js b/airtime_mvc/public/js/airtime/library/spl.js index 38d995c15..931b83c49 100644 --- a/airtime_mvc/public/js/airtime/library/spl.js +++ b/airtime_mvc/public/js/airtime/library/spl.js @@ -367,7 +367,7 @@ var AIRTIME = (function(AIRTIME){ //and verify whether they can be previewed by the browser or not. If not //then the playlist element is greyed out mod.validatePlaylistElements = function(){ - $.each($(".big_play ui-icon-play"), function(index, value){ + $.each($("div .big_play"), function(index, value){ if ($(value).attr('blockId') === undefined) { var mime = $(value).attr("data-mime-type"); if (isAudioSupported(mime)) { @@ -394,6 +394,31 @@ var AIRTIME = (function(AIRTIME){ }, }) } + } else { + if ($(value).attr('blocktype') === 'dynamic') { + $(value).attr("class", "big_play_disabled dark_class"); + $(value).qtip({ + content: 'Dynamic block is not previewable', + show: 'mouseover', + hide: { + delay: 500, + fixed: true + }, + style: { + border: { + width: 0, + radius: 4 + }, + classes: "ui-tooltip-dark ui-tooltip-rounded" + }, + position: { + my: "left bottom", + at: "right center" + }, + }) + } else { + $(value).bind("click", openAudioPreview); + } } }); } diff --git a/airtime_mvc/public/js/airtime/playlist/smart_blockbuilder.js b/airtime_mvc/public/js/airtime/playlist/smart_blockbuilder.js index 9862eb48e..0dc3bc0a9 100644 --- a/airtime_mvc/public/js/airtime/playlist/smart_blockbuilder.js +++ b/airtime_mvc/public/js/airtime/playlist/smart_blockbuilder.js @@ -363,7 +363,7 @@ function setupUI() { $(".playlist_type_help_icon").qtip({ content: { - text: "A static smart block will save the criteria and generate the block content immediately." + + text: "A static smart block will save the criteria and generate the block content immediately. " + "This allows you to edit and view it in the Library before adding it to a show.

" + "A dynamic smart block will only save the criteria. The block content will get generated upon " + "adding it to a show. You will not be able to view and edit the content in the Library." 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 415ae3ef1..006954154 100644 --- a/airtime_mvc/public/js/airtime/schedule/full-calendar-functions.js +++ b/airtime_mvc/public/js/airtime/schedule/full-calendar-functions.js @@ -206,7 +206,6 @@ function viewDisplay( view ) { } function eventRender(event, element, view) { - getCurrentShow(); $(element).data("event", event); @@ -367,7 +366,9 @@ function checkSCUploadStatus(){ }); }); } - +/** This function adds and removes the current + * show icon + */ function getCurrentShow(){ var url = baseUrl+'/Schedule/get-current-show/format/json', id, diff --git a/install_minimal/upgrades/airtime-2.1.0/propel/airtime/CcPlaylistcontents.php b/install_minimal/upgrades/airtime-2.1.0/propel/airtime/CcPlaylistcontents.php index b5125de32..ab0aa6d56 100644 --- a/install_minimal/upgrades/airtime-2.1.0/propel/airtime/CcPlaylistcontents.php +++ b/install_minimal/upgrades/airtime-2.1.0/propel/airtime/CcPlaylistcontents.php @@ -43,11 +43,16 @@ class CcPlaylistcontents extends BaseCcPlaylistcontents { */ public function setDbFadein($v) { + $microsecond = 0; if ($v instanceof DateTime) { $dt = $v; } else if (preg_match('/^[0-9]{1,2}(\.\d{1,6})?$/', $v)) { - $dt = DateTime::createFromFormat("s.u", $v); + // in php 5.3.2 createFromFormat() with "u" is not supported(bug) + // Hence we need to do parsing. + $info = explode('.', $v); + $microsecond = $info[1]; + $dt = DateTime::createFromFormat("s", $info[0]); } else { try { @@ -57,7 +62,11 @@ class CcPlaylistcontents extends BaseCcPlaylistcontents { } } - $this->fadein = $dt->format('H:i:s.u'); + if ($microsecond == 0) { + $this->fadein = $dt->format('H:i:s.u'); + } else { + $this->fadein = $dt->format('H:i:s').".".$microsecond; + } $this->modifiedColumns[] = CcPlaylistcontentsPeer::FADEIN; return $this; @@ -71,11 +80,16 @@ class CcPlaylistcontents extends BaseCcPlaylistcontents { */ public function setDbFadeout($v) { + $microsecond = 0; if ($v instanceof DateTime) { $dt = $v; } else if (preg_match('/^[0-9]{1,2}(\.\d{1,6})?$/', $v)) { - $dt = DateTime::createFromFormat("s.u", $v); + // in php 5.3.2 createFromFormat() with "u" is not supported(bug) + // Hence we need to do parsing. + $info = explode('.', $v); + $microsecond = $info[1]; + $dt = DateTime::createFromFormat("s", $info[0]); } else { try { @@ -85,7 +99,11 @@ class CcPlaylistcontents extends BaseCcPlaylistcontents { } } - $this->fadeout = $dt->format('H:i:s.u'); + if ($microsecond == 0) { + $this->fadeout = $dt->format('H:i:s.u'); + } else { + $this->fadeout = $dt->format('H:i:s').".".$microsecond; + } $this->modifiedColumns[] = CcPlaylistcontentsPeer::FADEOUT; return $this; diff --git a/install_minimal/upgrades/airtime-2.1.0/propel/airtime/CcSchedule.php b/install_minimal/upgrades/airtime-2.1.0/propel/airtime/CcSchedule.php index 75a01e758..b411d410e 100644 --- a/install_minimal/upgrades/airtime-2.1.0/propel/airtime/CcSchedule.php +++ b/install_minimal/upgrades/airtime-2.1.0/propel/airtime/CcSchedule.php @@ -107,11 +107,16 @@ class CcSchedule extends BaseCcSchedule { */ public function setDbFadeIn($v) { + $microsecond = 0; if ($v instanceof DateTime) { $dt = $v; } else if (preg_match('/^[0-9]{1,2}(\.\d{1,6})?$/', $v)) { - $dt = DateTime::createFromFormat("s.u", $v); + // in php 5.3.2 createFromFormat() with "u" is not supported(bug) + // Hence we need to do parsing. + $info = explode('.', $v); + $microsecond = $info[1]; + $dt = DateTime::createFromFormat("s", $info[0]); } else { try { @@ -120,7 +125,11 @@ class CcSchedule extends BaseCcSchedule { throw new PropelException('Error parsing date/time value: ' . var_export($v, true), $x); } } - $this->fade_in = $dt->format('H:i:s.u'); + if ($microsecond == 0) { + $this->fadein = $dt->format('H:i:s.u'); + } else { + $this->fadein = $dt->format('H:i:s').".".$microsecond; + } $this->modifiedColumns[] = CcSchedulePeer::FADE_IN; return $this; @@ -134,11 +143,16 @@ class CcSchedule extends BaseCcSchedule { */ public function setDbFadeOut($v) { + $microsecond = 0; if ($v instanceof DateTime) { $dt = $v; } else if (preg_match('/^[0-9]{1,2}(\.\d{1,6})?$/', $v)) { - $dt = DateTime::createFromFormat("s.u", $v); + // in php 5.3.2 createFromFormat() with "u" is not supported(bug) + // Hence we need to do parsing. + $info = explode('.', $v); + $microsecond = $info[1]; + $dt = DateTime::createFromFormat("s", $info[0]); } else { try { @@ -148,7 +162,11 @@ class CcSchedule extends BaseCcSchedule { } } - $this->fade_out = $dt->format('H:i:s.u'); + if ($microsecond == 0) { + $this->fadeout = $dt->format('H:i:s.u'); + } else { + $this->fadeout = $dt->format('H:i:s').".".$microsecond; + } $this->modifiedColumns[] = CcSchedulePeer::FADE_OUT; return $this; diff --git a/install_minimal/upgrades/airtime-2.2.0/common/UpgradeCommon.php b/install_minimal/upgrades/airtime-2.2.0/common/UpgradeCommon.php index 1d7183bcc..77c297a65 100644 --- a/install_minimal/upgrades/airtime-2.2.0/common/UpgradeCommon.php +++ b/install_minimal/upgrades/airtime-2.2.0/common/UpgradeCommon.php @@ -105,6 +105,12 @@ class UpgradeCommon{ self::CreateIniFiles(UpgradeCommon::CONF_BACKUP_SUFFIX); self::MergeConfigFiles($configFiles, $suffix); + + //HACK: This will fix a last minute bug we discovered with our upgrade scripts. + //Will be fixed properly in 2.3.0 + $old = "list_all_db_files = 'list-all-files/format/json/api_key/%%api_key%%/dir_id/%%dir_id%%'"; + $new = "list_all_db_files = 'list-all-files/format/json/api_key/%%api_key%%/dir_id/%%dir_id%%/all/%%all%%'"; + exec("sed -i \"s#$old#$new#g\" /etc/airtime/api_client.cfg"); } /** @@ -162,11 +168,13 @@ class UpgradeCommon{ foreach($sectionKeys as $sectionKey) { if(isset($oldSettings[$section][$sectionKey])) { - self::UpdateIniValue($conf, $sectionKey, $oldSettings[$section][$sectionKey]); + self::UpdateIniValue($conf, $sectionKey, + $oldSettings[$section][$sectionKey]); } } } else { - self::UpdateIniValue($conf, $section, $oldSettings[$section]); + self::UpdateIniValue($conf, $section, + $oldSettings[$section]); } } } diff --git a/install_minimal/upgrades/airtime-2.2.0/data/upgrade.sql b/install_minimal/upgrades/airtime-2.2.0/data/upgrade.sql index 8f8c5486c..36b4f5734 100644 --- a/install_minimal/upgrades/airtime-2.2.0/data/upgrade.sql +++ b/install_minimal/upgrades/airtime-2.2.0/data/upgrade.sql @@ -22,7 +22,7 @@ WHERE id IN (SELECT s.id FROM cc_schedule s LEFT JOIN cc_show_instances si ON s.instance_id = si.id - AND si.modified_instance = 't'); + WHERE si.modified_instance = 't'); ALTER TABLE cc_files DROP CONSTRAINT cc_files_gunid_idx; diff --git a/python_apps/media-monitor2/media/monitor/events.py b/python_apps/media-monitor2/media/monitor/events.py index 932c78d69..a8ccc3b54 100644 --- a/python_apps/media-monitor2/media/monitor/events.py +++ b/python_apps/media-monitor2/media/monitor/events.py @@ -43,7 +43,7 @@ class EventRegistry(object): methods") -class EventProxy(object): +class EventProxy(Loggable): """ A container object for instances of BaseEvent (or it's subclasses) used for event contractor diff --git a/python_apps/media-monitor2/media/monitor/metadata.py b/python_apps/media-monitor2/media/monitor/metadata.py index 8ceaf2aa9..bd42e434c 100644 --- a/python_apps/media-monitor2/media/monitor/metadata.py +++ b/python_apps/media-monitor2/media/monitor/metadata.py @@ -182,7 +182,7 @@ class Metadata(Loggable): that does not exist. Setting metadata to {}") self.__metadata = {} return - # TODO : Simplify the way all of these rules are handled right not it's + # TODO : Simplify the way all of these rules are handled right now it's # extremely unclear and needs to be refactored. #if full_mutagen is None: raise BadSongFile(fpath) if full_mutagen is None: full_mutagen = FakeMutagen(fpath) @@ -190,7 +190,6 @@ class Metadata(Loggable): # Now we extra the special values that are calculated from the mutagen # object itself: - # Hickity Hackity for .wav files. Properly do this later if mmp.extension(fpath) == 'wav': full_mutagen.set_length(mmp.read_wave_duration(fpath)) diff --git a/python_apps/media-monitor2/media/monitor/watchersyncer.py b/python_apps/media-monitor2/media/monitor/watchersyncer.py index 61146326a..e7a2cf9c0 100644 --- a/python_apps/media-monitor2/media/monitor/watchersyncer.py +++ b/python_apps/media-monitor2/media/monitor/watchersyncer.py @@ -126,7 +126,8 @@ class WatchSyncer(ReportHandler,Loggable): try: # If there is a strange bug anywhere in the code the next line # should be a suspect - if self.contractor.register(EventProxy(event)): self.push_queue( event ) + ev = EventProxy(event) + if self.contractor.register(ev): self.push_queue(ev) #self.push_queue( event ) except BadSongFile as e: self.fatal_exception("Received bas song file '%s'" % e.path, e) diff --git a/python_apps/media-monitor2/tests/test_pure.py b/python_apps/media-monitor2/tests/test_pure.py index 5dfaaedc2..64d09dc62 100644 --- a/python_apps/media-monitor2/tests/test_pure.py +++ b/python_apps/media-monitor2/tests/test_pure.py @@ -39,7 +39,7 @@ class TestMMP(unittest.TestCase): orig = Metadata.airtime_dict({ 'date' : [u'2012-08-21'], 'tracknumber' : [u'2'], - 'title' : [u'11-29-00-record'], + 'title' : [u'record-2012-08-21-11:29:00'], 'artist' : [u'Airtime Show Recorder'] }) orga = Metadata.airtime_dict({ @@ -57,7 +57,7 @@ class TestMMP(unittest.TestCase): self.assertEqual( orga, normalized ) - organized_base_name = "2012-08-21-11-29-00-record-256kbps.ogg" + organized_base_name = "11:29:00-record-256kbps.ogg" base = "/srv/airtime/stor/" organized_path = mmp.organized_path(old_path,base, normalized) self.assertEqual(os.path.basename(organized_path), organized_base_name) diff --git a/python_apps/pypo/pypopush.py b/python_apps/pypo/pypopush.py index aaacc1687..87e1704bf 100644 --- a/python_apps/pypo/pypopush.py +++ b/python_apps/pypo/pypopush.py @@ -399,7 +399,15 @@ class PypoPush(Thread): def date_interval_to_seconds(self, interval): - return (interval.microseconds + (interval.seconds + interval.days * 24 * 3600) * 10 ** 6) / float(10 ** 6) + """ + Convert timedelta object into int representing the number of seconds. If + number of seconds is less than 0, then return 0. + """ + seconds = (interval.microseconds + \ + (interval.seconds + interval.days * 24 * 3600) * 10 ** 6) / float(10 ** 6) + if seconds < 0: seconds = 0 + + return seconds def push_to_liquidsoap(self, event_chain):