diff --git a/airtime_mvc/application/configs/conf.php b/airtime_mvc/application/configs/conf.php index 937b91c75..13b4a06bd 100644 --- a/airtime_mvc/application/configs/conf.php +++ b/airtime_mvc/application/configs/conf.php @@ -26,6 +26,7 @@ class Config { $CC_CONFIG['webServerUser'] = $values['general']['web_server_user']; $CC_CONFIG['rabbitmq'] = $values['rabbitmq']; + $CC_CONFIG['baseDir'] = $values['general']['base_dir']; $CC_CONFIG['baseUrl'] = $values['general']['base_url']; $CC_CONFIG['basePort'] = $values['general']['base_port']; $CC_CONFIG['phpDir'] = $values['general']['airtime_dir']; diff --git a/airtime_mvc/application/controllers/PlaylistController.php b/airtime_mvc/application/controllers/PlaylistController.php index 2b48b40b7..1826bde3b 100644 --- a/airtime_mvc/application/controllers/PlaylistController.php +++ b/airtime_mvc/application/controllers/PlaylistController.php @@ -383,6 +383,7 @@ class PlaylistController extends Zend_Controller_Action $this->createUpdateResponse($obj); } else { $this->view->cue_error = $response["error"]; + $this->view->code = $response["type"]; } } catch (PlaylistOutDatedException $e) { $this->playlistOutdated($e); diff --git a/airtime_mvc/application/models/Playlist.php b/airtime_mvc/application/models/Playlist.php index aa74c78c4..74b1b62c7 100644 --- a/airtime_mvc/application/models/Playlist.php +++ b/airtime_mvc/application/models/Playlist.php @@ -10,6 +10,10 @@ require_once 'formatters/LengthFormatter.php'; */ class Application_Model_Playlist implements Application_Model_LibraryEditable { + const CUE_ALL_ERROR = 0; + const CUE_IN_ERROR = 1; + const CUE_OUT_ERROR = 2; + /** * propel connection object. */ @@ -792,6 +796,7 @@ SQL; try { if (is_null($cueIn) && is_null($cueOut)) { $errArray["error"] = _("Cue in and cue out are null."); + $errArray["type"] = self::CUE_ALL_ERROR; return $errArray; } @@ -822,6 +827,7 @@ SQL; $sql = "SELECT :cueIn::INTERVAL > :cueOut::INTERVAL"; if (Application_Common_Database::prepareAndExecute($sql, array(':cueIn'=>$cueIn, ':cueOut'=>$cueOut), 'column')) { $errArray["error"] = _("Can't set cue in to be larger than cue out."); + $errArray["type"] = self::CUE_IN_ERROR; return $errArray; } @@ -829,6 +835,7 @@ SQL; $sql = "SELECT :cueOut::INTERVAL > :origLength::INTERVAL"; if (Application_Common_Database::prepareAndExecute($sql, array(':cueOut'=>$cueOut, ':origLength'=>$origLength), 'column')) { $errArray["error"] = _("Can't set cue out to be greater than file length."); + $errArray["type"] = self::CUE_OUT_ERROR; return $errArray; } @@ -845,6 +852,7 @@ SQL; $sql = "SELECT :cueIn::INTERVAL > :oldCueOut::INTERVAL"; if (Application_Common_Database::prepareAndExecute($sql, array(':cueIn'=>$cueIn, ':oldCueOut'=>$oldCueOut), 'column')) { $errArray["error"] = _("Can't set cue in to be larger than cue out."); + $errArray["type"] = self::CUE_IN_ERROR; return $errArray; } @@ -863,6 +871,7 @@ SQL; $sql = "SELECT :cueOut::INTERVAL < :oldCueIn::INTERVAL"; if (Application_Common_Database::prepareAndExecute($sql, array(':cueOut'=>$cueOut, ':oldCueIn'=>$oldCueIn), 'column')) { $errArray["error"] = _("Can't set cue out to be smaller than cue in."); + $errArray["type"] = self::CUE_OUT_ERROR; return $errArray; } @@ -870,6 +879,7 @@ SQL; $sql = "SELECT :cueOut::INTERVAL > :origLength::INTERVAL"; if (Application_Common_Database::prepareAndExecute($sql, array(':cueOut'=>$cueOut, ':origLength'=>$origLength), 'column')) { $errArray["error"] = _("Can't set cue out to be greater than file length."); + $errArray["type"] = self::CUE_OUT_ERROR; return $errArray; } diff --git a/airtime_mvc/application/models/Scheduler.php b/airtime_mvc/application/models/Scheduler.php index 7cfe72908..25b01fa01 100644 --- a/airtime_mvc/application/models/Scheduler.php +++ b/airtime_mvc/application/models/Scheduler.php @@ -388,7 +388,7 @@ class Application_Model_Scheduler return $dt; } - private function findNextStartTime($DT, $instance) + private function findNextStartTime($DT, $instanceId) { $sEpoch = $DT->format("U.u"); $nEpoch = $this->epochNow; @@ -410,7 +410,7 @@ class Application_Model_Scheduler ->setDbCueIn('00:00:00') ->setDbCueOut('00:00:00') ->setDbPlayoutStatus(-1) - ->setDbInstanceId($instance->getDbId()) + ->setDbInstanceId($instanceId) ->save($this->con); } else { $nextDT = $DT; @@ -521,7 +521,12 @@ class Application_Model_Scheduler $linked = false; + $dropIndex_sql = "DROP INDEX cc_schedule_instance_id_idx"; + Application_Common_Database::prepareAndExecute( + $dropIndex_sql, array(), Application_Common_Database::EXECUTE); + foreach ($scheduleItems as $schedule) { + Logging::info($schedule); $id = intval($schedule["id"]); /* Find out if the show where the cursor position (where an item will @@ -531,12 +536,18 @@ class Application_Model_Scheduler * of inserted items */ if ($id != 0) { - $ccSchedule = CcScheduleQuery::create()->findPk($id); - $ccShowInstance = CcShowInstancesQuery::create()->findPk($ccSchedule->getDbInstanceId()); - $ccShow = $ccShowInstance->getCcShow(); - $linked = $ccShow->isLinked(); + $schedule_sql = "SELECT * FROM cc_schedule WHERE id = ".$id; + $ccSchedule = Application_Common_Database::prepareAndExecute( + $schedule_sql, array(), Application_Common_Database::SINGLE); + + $show_sql = "SELECT * FROM cc_show WHERE id IN (". + "SELECT show_id FROM cc_show_instances WHERE id = ".$ccSchedule["instance_id"].")"; + $ccShow = Application_Common_Database::prepareAndExecute( + $show_sql, array(), Application_Common_Database::SINGLE); + + $linked = $ccShow["linked"]; if ($linked) { - $unique = $ccShow->getDbId() . $ccSchedule->getDbPosition(); + $unique = $ccShow["id"] . $ccSchedule["position"]; if (!in_array($unique, $temp)) { $temp[] = $unique; } else { @@ -544,11 +555,14 @@ class Application_Model_Scheduler } } } else { - $ccShowInstance = CcShowInstancesQuery::create()->findPk($schedule["instance"]); - $ccShow = $ccShowInstance->getccShow(); - $linked = $ccShow->isLinked(); + $show_sql = "SELECT * FROM cc_show WHERE id IN (". + "SELECT show_id FROM cc_show_instances WHERE id = ".$schedule["instance"].")"; + $ccShow = Application_Common_Database::prepareAndExecute( + $show_sql, array(), Application_Common_Database::SINGLE); + + $linked = $ccShow["linked"]; if ($linked) { - $unique = $ccShow->getDbId() . "a"; + $unique = $ccShow["id"] . "a"; if (!in_array($unique, $temp)) { $temp[] = $unique; } else { @@ -562,38 +576,47 @@ class Application_Model_Scheduler * to that show */ if ($linked) { - $instances = $ccShow->getCcShowInstancess(); + $instance_sql = "SELECT * FROM cc_show_instances ". + "WHERE show_id = ".$ccShow["id"]; + $instances = Application_Common_Database::prepareAndExecute( + $instance_sql); } else { - $instances = array($ccShowInstance); + $instance_sql = "SELECT * FROM cc_show_instances ". + "WHERE id = ".$schedule["instance"]; + $instances = Application_Common_Database::prepareAndExecute( + $instance_sql); } foreach($instances as &$instance) { - $instanceId = $instance->getDbId(); + $instanceId = $instance["id"]; if ($id !== 0) { /* We use the selected cursor's position to find the same * positions in every other linked instance */ - $pos = $ccSchedule->getDbPosition(); + $pos = $ccSchedule["position"]; - $linkCcSchedule = CcScheduleQuery::create() - ->filterByDbInstanceId($instanceId) - ->filterByDbPosition($pos) - ->findOne(); + $linkedItem_sql = "SELECT ends FROM cc_schedule ". + "WHERE instance_id = {$instanceId} ". + "AND position = {$pos} ". + "AND playout_status IS NOT -1"; + $linkedItemEnds = Application_Common_Database::prepareAndExecute( + $linkedItem_sql, array(), Application_Common_Database::COLUMN); - $schedItemEndDT = $linkCcSchedule->getDbEnds(null); - $nextStartDT = $this->findNextStartTime($schedItemEndDT, $instance); + $nextStartDT = $this->findNextStartTime( + new DateTime($linkedItemEnds, new DateTimeZone("UTC")), + $instanceId); $pos++; } //selected empty row to add after else { - $showStartDT = $instance->getDbStarts(null); - $nextStartDT = $this->findNextStartTime($showStartDT, $instance); + $showStartDT = new DateTime($instance["starts"], new DateTimeZone("UTC")); + $nextStartDT = $this->findNextStartTime($showStartDT, $instanceId); //show is empty so start position counter at 0 $pos = 0; } - if (!in_array($instance->getDbId(), $affectedShowInstances)) { + if (!in_array($instanceId, $affectedShowInstances)) { $affectedShowInstances[] = $instanceId; } @@ -620,39 +643,50 @@ class Application_Model_Scheduler } } + $doInsert = false; + $doUpdate = false; + $values = array(); foreach ($filesToInsert as &$file) { //item existed previously and is being moved. //need to keep same id for resources if we want REST. if (isset($file['sched_id'])) { - $sched = CcScheduleQuery::create()->findPk($file["sched_id"]); + $doUpdate = true; + + $movedItem_sql = "SELECT * FROM cc_schedule ". + "WHERE id = ".$file["sched_id"]; + $sched = Application_Common_Database::prepareAndExecute( + $movedItem_sql, array(), Application_Common_Database::SINGLE); /* We need to keep a record of the original positon a track * is being moved from so we can use it to retrieve the correct * items in linked instances */ if (!isset($originalPosition)) { - $originalPosition = $sched->getDbPosition(); + $originalPosition = $sched["position"]; } /* If we are moving an item in a linked show we need to get * the relative item to move in each instance. We know what the * relative item is by its position */ - if ($linked && $moveAction) { - $sched = CcScheduleQuery::create() - ->filterByDbInstanceId($instanceId) - ->filterByDbPosition($originalPosition) - ->findOne(); - } - $excludeIds[] = intval($sched->getDbId()); + if ($linked) { + $movedItem_sql = "SELECT * FROM cc_schedule ". + "WHERE position = {$originalPosition} ". + "AND instance_id = {$instanceId}"; - $file["cliplength"] = $sched->getDbClipLength(); - $file["cuein"] = $sched->getDbCueIn(); - $file["cueout"] = $sched->getDbCueOut(); - $file["fadein"] = $sched->getDbFadeIn(); - $file["fadeout"] = $sched->getDbFadeOut(); + $sched = Application_Common_Database::prepareAndExecute( + $movedItem_sql, array(), Application_Common_Database::SINGLE); + } + $excludeIds[] = intval($sched["id"]); + + $file["cliplength"] = $sched["clip_length"]; + $file["cuein"] = $sched["cue_in"]; + $file["cueout"] = $sched["cue_out"]; + $file["fadein"] = $sched["fade_in"]; + $file["fadeout"] = $sched["fade_out"]; } else { - $sched = new CcSchedule(); + //$sched = new CcSchedule(); + $doInsert = true; } $endTimeDT = $this->findEndTime($nextStartDT, $file['cliplength']); @@ -661,30 +695,47 @@ class Application_Model_Scheduler $file['fadein'] = Application_Common_DateHelper::secondsToPlaylistTime($file['fadein']); $file['fadeout'] = Application_Common_DateHelper::secondsToPlaylistTime($file['fadeout']); - $sched->setDbStarts($nextStartDT) - ->setDbEnds($endTimeDT) - ->setDbCueIn($file['cuein']) - ->setDbCueOut($file['cueout']) - ->setDbFadeIn($file['fadein']) - ->setDbFadeOut($file['fadeout']) - ->setDbClipLength($file['cliplength']) - ->setDbPosition($pos); - - if (!$moveAction) { - $sched->setDbInstanceId($instanceId); - } - switch ($file["type"]) { case 0: - $sched->setDbFileId($file['id']); + $fileId = $file["id"]; + $streamId = "null"; break; case 1: - $sched->setDbStreamId($file['id']); + $streamId = $file["id"]; + $fileId = "null"; break; default: break; } - $sched->save($this->con); + if ($doInsert) { + $values[] = "(". + "'{$nextStartDT->format("Y-m-d H:i:s")}', ". + "'{$endTimeDT->format("Y-m-d H:i:s")}', ". + "'{$file["cuein"]}', ". + "'{$file["cueout"]}', ". + "'{$file["fadein"]}', ". + "'{$file["fadeout"]}', ". + "'{$file["cliplength"]}', ". + "{$pos}, ". + "{$instanceId}, ". + "{$fileId}, ". + "{$streamId})"; + + } elseif ($doUpdate) { + $update_sql = "UPDATE cc_schedule SET ". + "starts = '{$nextStartDT->format("Y-m-d H:i:s")}', ". + "ends = '{$endTimeDT->format("Y-m-d H:i:s")}', ". + "cue_in = '{$file["cuein"]}', ". + "cue_out = '{$file["cueout"]}', ". + "fade_in = '{$file["fadein"]}', ". + "fade_out = '{$file["fadeout"]}', ". + "clip_length = '{$file["cliplength"]}', ". + "position = {$pos} ". + "WHERE id = {$sched["id"]}"; + + Application_Common_Database::prepareAndExecute( + $update_sql, array(), Application_Common_Database::EXECUTE); + } $nextStartDT = $endTimeDT; $pos++; @@ -693,9 +744,18 @@ class Application_Model_Scheduler * after the insert location, we need to exclude the * schedule item we just inserted because it has correct * start and end times*/ - $excludeIds[] = $sched->getDbId(); + //$excludeIds[] = $lastInsertId; }//all files have been inserted/moved + if ($doInsert) { + $insert_sql = "INSERT INTO cc_schedule ". + "(starts, ends, cue_in, cue_out, fade_in, fade_out, ". + "clip_length, position, instance_id, file_id, stream_id) VALUES ". + implode($values, ","); + + Application_Common_Database::prepareAndExecute( + $insert_sql, array(), Application_Common_Database::EXECUTE); + } // update is_scheduled flag for each cc_file $fileIds = array(); @@ -717,22 +777,30 @@ class Application_Model_Scheduler } if ($adjustSched === true) { - $followingSchedItems = CcScheduleQuery::create() - ->filterByDBStarts($initalStartDT->format("Y-m-d H:i:s.u"), Criteria::GREATER_EQUAL) - ->filterByDbInstanceId($instance->getDbId()) - ->filterByDbId($excludeIds, Criteria::NOT_IN) - ->orderByDbStarts() - ->find($this->con); + $followingItems_sql = "SELECT * FROM cc_schedule ". + "WHERE starts >= '{$initalStartDT->format("Y-m-d H:i:s.u")}' ". + "AND instance_id = {$instanceId} "; + if (count($excludeIds) > 0) { + $followingItems_sql .= "AND id NOT IN (". implode($excludeIds, ",").") "; + } + $followingItems_sql .= "ORDER BY starts"; + + $followingSchedItems = Application_Common_Database::prepareAndExecute( + $followingItems_sql); $pstart = microtime(true); //recalculate the start/end times after the inserted items. foreach ($followingSchedItems as $item) { - $endTimeDT = $this->findEndTime($nextStartDT, $item->getDbClipLength()); - $item->setDbStarts($nextStartDT); - $item->setDbEnds($endTimeDT); - $item->setDbPosition($pos); - $item->save($this->con); + $endTimeDT = $this->findEndTime($nextStartDT, $item["clip_length"]); + $update_sql = "UPDATE cc_schedule SET ". + "starts = '{$nextStartDT->format("Y-m-d H:i:s")}', ". + "ends = '{$endTimeDT->format("Y-m-d H:i:s")}', ". + "position = {$pos} ". + "WHERE id = {$item["id"]}"; + Application_Common_Database::prepareAndExecute( + $update_sql, array(), Application_Common_Database::EXECUTE); + $nextStartDT = $endTimeDT; $pos++; } @@ -741,12 +809,16 @@ class Application_Model_Scheduler Logging::debug("adjusting all following items."); Logging::debug(floatval($pend) - floatval($pstart)); - $this->calculateCrossfades($instance->getDbId()); + $this->calculateCrossfades($instanceId); } }//for each instance - }//for each schedule location + $createIndex_sql = "CREATE INDEX cc_schedule_instance_id_idx ". + "ON cc_schedule USING btree(instance_id)"; + Application_Common_Database::prepareAndExecute( + $createIndex_sql, array(), Application_Common_Database::EXECUTE); + $endProfile = microtime(true); Logging::debug("finished adding scheduled items."); Logging::debug(floatval($endProfile) - floatval($startProfile)); @@ -782,6 +854,11 @@ class Application_Model_Scheduler } } + private function updateMovedItem() + { + + } + private function getInstances($instanceId) { $ccShowInstance = CcShowInstancesQuery::create()->findPk($instanceId); diff --git a/airtime_mvc/application/models/StoredFile.php b/airtime_mvc/application/models/StoredFile.php index 9169efaee..74e0a7a05 100644 --- a/airtime_mvc/application/models/StoredFile.php +++ b/airtime_mvc/application/models/StoredFile.php @@ -501,44 +501,25 @@ SQL; } /** - * Get the URL to access this file using the server name/address that - * this PHP script was invoked through. + * Get the URL to access this file */ public function getFileUrl() { - $serverName = $_SERVER['SERVER_NAME']; - $serverPort = $_SERVER['SERVER_PORT']; - - return $this->constructGetFileUrl($serverName, $serverPort); - } - - /** - * Get the URL to access this file using the server name/address that - * is specified in the airtime.conf config file. If either of these is - * not specified, then use values provided by the $_SERVER global variable. - */ - public function getFileUrlUsingConfigAddress() - { - $CC_CONFIG = Config::getConfig(); - - if (isset($CC_CONFIG['baseUrl'])) { - $serverName = $CC_CONFIG['baseUrl']; - } else { - $serverName = $_SERVER['SERVER_NAME']; - } - - if (isset($CC_CONFIG['basePort'])) { - $serverPort = $CC_CONFIG['basePort']; - } else { - $serverPort = $_SERVER['SERVER_PORT']; - } - - return $this->constructGetFileUrl($serverName, $serverPort); - } - - private function constructGetFileUrl($p_serverName, $p_serverPort) - { - return "http://$p_serverName:$p_serverPort/api/get-media/file/".$this->getId().".".$this->getFileExtension(); + $CC_CONFIG = Config::getConfig(); + + $protocol = empty($_SERVER['HTTPS']) ? "http" : "https"; + + $serverName = $_SERVER['SERVER_NAME']; + $serverPort = $_SERVER['SERVER_PORT']; + $subDir = $CC_CONFIG['baseDir']; + + if ($subDir[0] === "/") { + $subDir = substr($subDir, 1, strlen($subDir) - 1); + } + + $baseUrl = "{$protocol}://{$serverName}:{$serverPort}/{$subDir}"; + + return $this->getRelativeFileUrl($baseUrl); } /** @@ -547,6 +528,8 @@ SQL; */ public function getRelativeFileUrl($baseUrl) { + Logging::debug("Zend base url: $baseUrl"); + return $baseUrl."api/get-media/file/".$this->getId().".".$this->getFileExtension(); } diff --git a/airtime_mvc/application/services/SchedulerService.php b/airtime_mvc/application/services/SchedulerService.php index 7cfac160d..1d9c5e244 100644 --- a/airtime_mvc/application/services/SchedulerService.php +++ b/airtime_mvc/application/services/SchedulerService.php @@ -155,64 +155,105 @@ class Application_Service_SchedulerService * any other instances with content */ $instanceIds = $ccShow->getInstanceIds(); - $ccSchedules = CcScheduleQuery::create() - ->filterByDbInstanceId($instanceIds, Criteria::IN) - ->find(); - if (!$ccSchedules->isEmpty()) { + $schedule_sql = "SELECT * FROM cc_schedule ". + "WHERE instance_id IN (".implode($instanceIds, ",").")"; + $ccSchedules = Application_Common_Database::prepareAndExecute( + $schedule_sql); + + if (count($ccSchedules) > 0) { /* Find the show contents of just one of the instances. It doesn't * matter which instance we use since all the content is the same */ - $ccSchedule = $ccSchedules->getFirst(); - $showStamp = CcScheduleQuery::create() - ->filterByDbInstanceId($ccSchedule->getDbInstanceId()) - ->orderByDbStarts() - ->find(); + $ccSchedule = $ccSchedules[0]; + $showStamp_sql = "SELECT * FROM cc_schedule ". + "WHERE instance_id = {$ccSchedule["instance_id"]} ". + "ORDER BY starts"; + $showStamp = Application_Common_Database::prepareAndExecute( + $showStamp_sql); //get time_filled so we can update cc_show_instances - $timeFilled = $ccSchedule->getCcShowInstances()->getDbTimeFilled(); + $timeFilled_sql = "SELECT time_filled FROM cc_show_instances ". + "WHERE id = {$ccSchedule["instance_id"]}"; + $timeFilled = Application_Common_Database::prepareAndExecute( + $timeFilled_sql, array(), Application_Common_Database::COLUMN); + + $dropIndex_sql = "DROP INDEX cc_schedule_instance_id_idx"; + Application_Common_Database::prepareAndExecute( + $dropIndex_sql, array(), Application_Common_Database::EXECUTE); //need to find out which linked instances are empty - foreach ($ccShow->getCcShowInstancess() as $ccShowInstance) { - $ccSchedules = CcScheduleQuery::create() - ->filterByDbInstanceId($ccShowInstance->getDbId()) - ->find(); + $values = array(); + foreach ($instanceIds as $id) { + $instanceSched_sql = "SELECT * FROM cc_schedule ". + "WHERE instance_id = {$id} ". + "ORDER by starts"; + $ccSchedules = Application_Common_Database::prepareAndExecute( + $instanceSched_sql); + /* If the show instance is empty OR it has different content than - * the first instance, we cant to fill/replace with the show stamp + * the first instance, we need to fill/replace with the show stamp * (The show stamp is taken from the first show instance's content) */ - if ($ccSchedules->isEmpty() || - self::replaceInstanceContentCheck($ccShowInstance, $showStamp)) { + if (count($ccSchedules) < 1 || + self::replaceInstanceContentCheck($ccSchedules, $showStamp)) { - $nextStartDT = $ccShowInstance->getDbStarts(null); + //$nextStartDT = $ccShowInstance->getDbStarts(null); + $instanceStart_sql = "SELECT starts FROM cc_show_instances ". + "WHERE id = {$id}"; + $nextStartDT = new DateTime( + Application_Common_Database::prepareAndExecute( + $instanceStart_sql, array(), Application_Common_Database::EXECUTE), + new DateTimeZone("UTC")); foreach ($showStamp as $item) { - $endTimeDT = self::findEndTime($nextStartDT, $item->getDbClipLength()); + $endTimeDT = self::findEndTime($nextStartDT, $item["clip_length"]); - $ccSchedule = new CcSchedule(); - $ccSchedule - ->setDbStarts($nextStartDT) - ->setDbEnds($endTimeDT) - ->setDbFileId($item->getDbFileId()) - ->setDbStreamId($item->getDbStreamId()) - ->setDbClipLength($item->getDbClipLength()) - ->setDbFadeIn($item->getDbFadeIn()) - ->setDbFadeOut($item->getDbFadeOut()) - ->setDbCuein($item->getDbCueIn()) - ->setDbCueOut($item->getDbCueOut()) - ->setDbInstanceId($ccShowInstance->getDbId()) - ->setDbPosition($item->getDbPosition()) - ->save(); + if (is_null($item["file_id"])) { + $item["file_id"] = "null"; + } elseif (is_null($item["stream_id"])) { + $item["stream_id"] = "null"; + } + + $values[] = "(". + "'{$nextStartDT->format("Y-m-d H:i:s")}', ". + "'{$endTimeDT->format("Y-m-d H:i:s")}', ". + "'{$item["clip_length"]}', ". + "'{$item["fade_in"]}', ". + "'{$item["fade_out"]}', ". + "'{$item["cue_in"]}', ". + "'{$item["cue_out"]}', ". + "{$item["file_id"]}, ". + "{$item["stream_id"]}, ". + "{$id}, ". + "{$item["position"]})"; $nextStartDT = $endTimeDT; } //foreach show item - - //update time_filled in cc_show_instances - $ccShowInstance - ->setDbTimeFilled($timeFilled) - ->setDbLastScheduled(gmdate("Y-m-d H:i:s")) - ->save(); } } //foreach linked instance + + $insert_sql = "INSERT INTO cc_schedule (starts, ends, ". + "clip_length, fade_in, fade_out, cue_in, cue_out, ". + "file_id, stream_id, instance_id, position) VALUES ". + implode($values, ","); + + Application_Common_Database::prepareAndExecute( + $insert_sql, array(), Application_Common_Database::EXECUTE); + + $createIndex_sql = "CREATE INDEX cc_schedule_instance_id_idx ". + "ON cc_schedule USING btree(instance_id)"; + Application_Common_Database::prepareAndExecute( + $createIndex_sql, array(), Application_Common_Database::EXECUTE); + + //update time_filled in cc_show_instances + $now = gmdate("Y-m-d H:i:s"); + $update_sql = "UPDATE cc_show_instances SET ". + "time_filled = '{$timeFilled}', ". + "last_scheduled = '{$now}' ". + "WHERE show_id = {$ccShow->getDbId()}"; + Application_Common_Database::prepareAndExecute( + $update_sql, array(), Application_Common_Database::EXECUTE); + } //if at least one linked instance has content } @@ -259,20 +300,24 @@ class Application_Service_SchedulerService } } - private static function replaceInstanceContentCheck($ccShowInstance, $showStamp) + private static function replaceInstanceContentCheck($currentShowStamp, $showStamp) { - $currentShowStamp = CcScheduleQuery::create() + /*$currentShowStamp = CcScheduleQuery::create() ->filterByDbInstanceId($ccShowInstance->getDbId()) ->orderByDbStarts() - ->find(); + ->find();*/ $counter = 0; foreach ($showStamp as $item) { - if ($item->getDbFileId() != $currentShowStamp[$counter]->getDbFileId() || - $item->getDbStreamId() != $currentShowStamp[$counter]->getDbStreamId()) { - CcScheduleQuery::create() + if ($item["file_id"] != $currentShowStamp[$counter]["file_id"] || + $item["stream_id"] != $currentShowStamp[$counter]["stream_id"]) { + /*CcScheduleQuery::create() ->filterByDbInstanceId($ccShowInstance->getDbId()) - ->delete(); + ->delete();*/ + $delete_sql = "DELETE FROM cc_schedule ". + "WHERE instance_id = {$currentShowStamp[$counter]["instance_id"]}"; + Application_Common_Database::prepareAndExecute( + $delete_sql, array(), Application_Common_Database::EXECUTE); return true; } } diff --git a/airtime_mvc/public/js/airtime/dashboard/dashboard.js b/airtime_mvc/public/js/airtime/dashboard/dashboard.js index 5725d7b62..33bb89d46 100644 --- a/airtime_mvc/public/js/airtime/dashboard/dashboard.js +++ b/airtime_mvc/public/js/airtime/dashboard/dashboard.js @@ -22,6 +22,13 @@ var live_dj_on_air = false; var scheduled_play_on_air = false; var scheduled_play_source = false; + +//a reference returned by setTimeout. Useful for when we want clearTimeout() +var newSongTimeoutId = null; + +//a reference returned by setTimeout. Useful for when we want clearTimeout() +var newShowTimeoutId = null; + //keep track of how many UI refreshes the ON-AIR light has been off for. //For example, the uiUpdateInterval is every 200ms, so if onAirOffIterations //is 25, then that means 5 seconds have gone by. @@ -34,6 +41,8 @@ var nextSongPrepare = true; var nextShowPrepare = true; function secondsTimer(){ + /* This function constantly calls itself every 'uiUpdateInterval' + * micro-seconds and is responsible for updating the UI. */ if (localRemoteTimeOffset !== null){ var date = new Date(); approximateServerTime = date.getTime() - localRemoteTimeOffset; @@ -79,9 +88,11 @@ function updateProgressBarValue(){ var songElapsedTime = 0; songPercentDone = (approximateServerTime - currentSong.songStartPosixTime)/currentSong.songLengthMs*100; songElapsedTime = approximateServerTime - currentSong.songStartPosixTime; - if (songPercentDone < 0 || songPercentDone > 100){ + if (songPercentDone < 0) { songPercentDone = 0; //currentSong = null; + } else if (songPercentDone > 100) { + songPercentDone = 100; } else { if ((currentSong.media_item_played == true && currentShow.length > 0) || (songElapsedTime < 5000 && currentShow[0].record != 1)) { scheduled_play_line_to_switch.attr("class", "line-to-switch on"); @@ -95,40 +106,13 @@ function updateProgressBarValue(){ } $('#progress-show').attr("class", "progress-show"); } - } else if (nextSong == null) { + } else { scheduled_play_source = false; scheduled_play_line_to_switch.attr("class", "line-to-switch off"); scheduled_play_div.removeClass("ready"); $('#progress-show').attr("class", "progress-show-error"); } $('#progress-bar').attr("style", "width:"+songPercentDone+"%"); - - //calculate how much time left to next song if there is any - if (nextSong !== null && nextSongPrepare){ - var diff = nextSong.songStartPosixTime - approximateServerTime; - if (diff < serverUpdateInterval){ - - //sometimes the diff is negative (-100ms for example). Still looking - //into why this could sometimes happen. - if (diff < 0) - diff=0; - - nextSongPrepare = false; - setTimeout(newSongStart, diff); - } - } - - //calculate how much time left to next show if there is any - if (nextShow.length > 0 && nextShowPrepare){ - var diff = nextShow[0].showStartPosixTime - approximateServerTime; - if (diff < serverUpdateInterval){ - if (diff < 0) - diff=0; - - nextShowPrepare = false; - setTimeout(nextShowStart, diff); - } - } } function updatePlaybar(){ @@ -159,7 +143,7 @@ function updatePlaybar(){ } else { $('#current').html($.i18n._("Current")+": "+$.i18n._("Live Stream")+""); } - } else if (nextSong == null) { + } else { $('#current').html($.i18n._("Current")+": "+$.i18n._("Nothing Scheduled")+""); } } @@ -223,22 +207,66 @@ function calcAdditionalShowData(show){ } } -function parseItems(obj){ +function calculateTimeToNextSong() { + if (approximateServerTime === null) { + return; + } + + if (newSongTimeoutId !== null) { + /* We have a previous timeout set, let's unset it */ + clearTimeout(newSongTimeoutId); + newSongTimeoutId = null; + } + + var diff = nextSong.songStartPosixTime - approximateServerTime; + if (diff < 0) diff=0; + nextSongPrepare = false; + newSongTimeoutId= setTimeout(newSongStart, diff); +} + +function calculateTimeToNextShow() { + if (approximateServerTime === null) { + return; + } + + if (newShowTimeoutId !== null) { + /* We have a previous timeout set, let's unset it */ + clearTimeout(newShowTimeoutId); + newShowTimeoutId = null; + } + + var diff = nextShow[0].showStartPosixTime - approximateServerTime; + if (diff < 0) diff=0; + nextShowPrepare = false; + newShowTimeoutId= setTimeout(nextShowStart, diff); +} + +function parseItems(obj){ $('#time-zone').text(obj.timezone); + previousSong = obj.previous; currentSong = obj.current; nextSong = obj.next; - if (previousSong !== null) + if (previousSong !== null) { calcAdditionalData(previousSong); - if (currentSong !== null) + } + if (currentSong !== null) { calcAdditionalData(currentSong); - if (nextSong !== null) + } + if (nextSong !== null) { calcAdditionalData(nextSong); + calculateTimeToNextSong(); + } - calcAdditionalShowData(obj.currentShow); - calcAdditionalShowData(obj.nextShow); + if (obj.currentShow.length > 0) { + calcAdditionalShowData(obj.currentShow); + } + if (obj.nextShow.length > 0) { + calcAdditionalShowData(obj.nextShow); + calculateTimeToNextShow(); + } currentShow = obj.currentShow; nextShow = obj.nextShow; diff --git a/airtime_mvc/public/js/airtime/library/spl.js b/airtime_mvc/public/js/airtime/library/spl.js index a50684131..00f899f9c 100644 --- a/airtime_mvc/public/js/airtime/library/spl.js +++ b/airtime_mvc/public/js/airtime/library/spl.js @@ -144,7 +144,8 @@ var AIRTIME = (function(AIRTIME){ var url = baseUrl+"Playlist/set-cue", lastMod = getModified(), type = $('#obj_type').val(), - li; + li, + span; if (!isTimeValid(cueIn)){ $el.find('.cue-in-error').val($.i18n._("please put in a time '00:00:00 (.0)'")).show(); @@ -174,7 +175,27 @@ var AIRTIME = (function(AIRTIME){ return; } if (json.cue_error !== undefined) { - showError(span, json.cue_error); + + li = $('#side_playlist li[unqid='+id+']'); + + if (json.code === 0) { + + span = $('#spl_cue_in_'+id).find('span'); + showError(span, json.cue_error); + span = $('#spl_cue_out_'+id).find('span'); + showError(span, json.cue_error); + } + else if (json.code === 1) { + + span = $('#spl_cue_in_'+id).find('span'); + showError(span, json.cue_error); + } + else if (json.code === 2) { + + span = $('#spl_cue_out_'+id).find('span'); + showError(span, json.cue_error); + } + return; } diff --git a/python_apps/pypo/liquidsoap_scripts/ls_script.liq b/python_apps/pypo/liquidsoap_scripts/ls_script.liq index 97dc544c5..c2b898f3a 100644 --- a/python_apps/pypo/liquidsoap_scripts/ls_script.liq +++ b/python_apps/pypo/liquidsoap_scripts/ls_script.liq @@ -40,6 +40,14 @@ source_id = ref 0 def create_source() l = request.equeue(id="s#{!source_id}", length=0.5) l = cue_cut(l) + + l = audio_to_stereo(id="queue_src", l) + l = amplify(1., override="replay_gain", l) + + # the crossfade function controls fade in/out + l = crossfade_airtime(l) + + l = on_metadata(notify, l) sources := list.append([l], !sources) server.register(namespace="queues", "s#{!source_id}_skip", @@ -62,12 +70,6 @@ create_source() queue = add(!sources, normalize=false) -queue = audio_to_stereo(id="queue_src", queue) -queue = amplify(1., override="replay_gain", queue) - -# the crossfade function controls fade in/out -queue = crossfade_airtime(queue) -queue = on_metadata(notify, queue) output.dummy(fallible=true, queue) http = input.http_restart(id="http")