Merge branch 'saas-dev' of https://github.com/sourcefabric/Airtime into saas-dev

This commit is contained in:
Duncan Sommerville 2015-05-27 14:02:00 -04:00
commit 51a3f19f43
31 changed files with 501 additions and 323 deletions

View file

@ -101,6 +101,11 @@ class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
$csrf_namespace->authtoken = sha1(uniqid(rand(), 1));
$csrf_namespace->setExpirationSeconds(2 * 60 * 60);
}
//Here we are closing the session for writing because otherwise no requests
//in this session will be handled in parallel. This gives a major boost to the perceived performance
//of the application (page load times are more consistent, no lock contention).
session_write_close();
}
/**

View file

@ -2,6 +2,10 @@
class Application_Common_TuneIn
{
/**
* @param $title url encoded string
* @param $artist url encoded string
*/
public static function sendMetadataToTunein($title, $artist)
{
$credQryStr = self::getCredentialsQueryString();
@ -13,12 +17,20 @@ class Application_Common_TuneIn
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_exec($ch);
$xmlResponse = curl_exec($ch);
if (curl_error($ch)) {
Logging::error("Failed to reach TuneIn: ". curl_errno($ch)." - ". curl_error($ch) . " - " . curl_getinfo($ch, CURLINFO_EFFECTIVE_URL));
}
curl_close($ch);
$xmlObj = new SimpleXMLElement($xmlResponse);
if (!$xmlObj || $xmlObj->head->status != "200") {
Logging::info("Error occurred pushing metadata to TuneIn:");
Logging::info($xmlResponse);
} else if ($xmlObj->head->status == "200") {
Application_Model_Preference::setLastTuneinMetadataUpdate(time());
}
}
private static function getCredentialsQueryString() {
@ -29,20 +41,4 @@ class Application_Common_TuneIn
return "?partnerId=".$tuneInPartnerID."&partnerKey=".$tuneInPartnerKey."&id=".$tuneInStationID;
}
public static function updateOfflineMetadata() {
$credQryStr = self::getCredentialsQueryString();
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, TUNEIN_API_URL . $credQryStr . "&commercial=true");
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_exec($ch);
if (curl_error($ch)) {
Logging::error("Failed to reach TuneIn: ". curl_errno($ch)." - ". curl_error($ch) . " - " . curl_getinfo($ch, CURLINFO_EFFECTIVE_URL));
}
curl_close($ch);
}
}

View file

@ -1515,5 +1515,30 @@ class ApiController extends Zend_Controller_Action
$this->_helper->json($result);
}
/**
* This function is called from PYPO (pypofetch) every 2 minutes and updates
* metadata on TuneIn if we haven't done so in the last 4 minutes. We have
* to do this because TuneIn turns off metadata if it has not received a
* request within 5 minutes. This is necessary for long tracks > 5 minutes.
*/
public function updateMetadataOnTuneinAction()
{
if (!Application_Model_Preference::getTuneinEnabled()) {
$this->_helper->json->sendJson(array(0));
}
$lastTuneInMetadataUpdate = Application_Model_Preference::geLastTuneinMetadataUpdate();
if (time() - $lastTuneInMetadataUpdate >= 240) {
$metadata = $metadata = Application_Model_Schedule::getCurrentPlayingTrack();
if (!is_null($metadata)) {
Application_Common_TuneIn::sendMetadataToTunein(
$metadata["title"],
$metadata["artist"]
);
}
}
$this->_helper->json->sendJson(array(1));
}
}

View file

@ -8,6 +8,8 @@ class LoginController extends Zend_Controller_Action
public function init()
{
//Open the session for writing, because we close it for writing by default in Bootstrap.php as an optimization.
session_start();
}
public function indexAction()

View file

@ -31,6 +31,8 @@ class PlaylistController extends Zend_Controller_Action
->addActionContext('empty-content', 'json')
->initContext();
//This controller writes to the session all over the place, so we're going to reopen it for writing here.
session_start(); //Reopen the session for writing
}
private function getPlaylist($p_type)

View file

@ -32,6 +32,7 @@ class PreferenceController extends Zend_Controller_Action
$form = new Application_Form_Preferences();
$values = array();
session_start(); //Open session for writing.
if ($request->isPost()) {
$values = $request->getPost();
@ -94,6 +95,8 @@ class PreferenceController extends Zend_Controller_Action
$this->view->headScript()->appendFile($baseUrl.'js/airtime/preferences/support-setting.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
$this->view->statusMsg = "";
session_start(); //Open session for writing.
$form = new Application_Form_SupportSettings();
if ($request->isPost()) {
$values = $request->getPost();
@ -128,6 +131,8 @@ class PreferenceController extends Zend_Controller_Action
public function removeLogoAction()
{
session_start(); //Open session for writing.
$this->view->layout()->disableLayout();
// Remove reliance on .phtml files to render requests
$this->_helper->viewRenderer->setNoRender(true);
@ -145,6 +150,8 @@ class PreferenceController extends Zend_Controller_Action
$this->view->headScript()->appendFile($baseUrl.'js/airtime/preferences/streamsetting.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
session_start(); //Open session for writing.
// get current settings
$setting = Application_Model_StreamSetting::getStreamSetting();
@ -435,6 +442,8 @@ class PreferenceController extends Zend_Controller_Action
public function setSourceConnectionUrlAction()
{
session_start(); //Open session for writing.
$request = $this->getRequest();
$type = $request->getParam("type", null);
$url = urldecode($request->getParam("url", null));
@ -453,6 +462,8 @@ class PreferenceController extends Zend_Controller_Action
public function getAdminPasswordStatusAction()
{
session_start(); //Open session for writing.
$out = array();
$num_of_stream = intval(Application_Model_Preference::GetNumOfStreams());
for ($i=1; $i<=$num_of_stream; $i++) {

View file

@ -51,6 +51,11 @@ class ScheduleController extends Zend_Controller_Action
$baseUrl = Application_Common_OsPath::getBaseDir();
//Embed the schedule in our page response so we don't have to make an AJAX request to get this data after the page load.
$scheduleController = new ScheduleController($this->getRequest(), $this->getResponse());
$scheduleController->eventFeedPreloadAction();
$events = json_encode($scheduleController->view->events);
$this->view->headScript()->appendScript(
"var calendarPref = {};\n".
"calendarPref.weekStart = ".Application_Model_Preference::GetWeekStartDay().";\n".
@ -59,7 +64,7 @@ class ScheduleController extends Zend_Controller_Action
"calendarPref.timeScale = '".Application_Model_Preference::GetCalendarTimeScale()."';\n".
"calendarPref.timeInterval = ".Application_Model_Preference::GetCalendarTimeInterval().";\n".
"calendarPref.weekStartDay = ".Application_Model_Preference::GetWeekStartDay().";\n".
"var calendarEvents = null;"
"var calendarEvents = $events;"
);
$this->view->headScript()->appendFile($baseUrl.'js/contextmenu/jquery.contextMenu.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
@ -145,7 +150,7 @@ class ScheduleController extends Zend_Controller_Action
} else if ($calendar_interval == "agendaWeek") {
list($start, $end) = Application_Model_Show::getStartEndCurrentWeekView();
} else if ($calendar_interval == "month") {
list($start, $end) = Application_Model_Show::getStartEndCurrentMonthView();
list($start, $end) = Application_Model_Show::getStartEndCurrentMonthPlusView();
} else {
Logging::error("Invalid Calendar Interval '$calendar_interval'");
}
@ -295,17 +300,21 @@ class ScheduleController extends Zend_Controller_Action
}
}
/** This is a nasty hack to let us embed the the data the dashboard needs into the HTML response for each page.
* This was originally loaded AFTER page load by AJAX, which is needlessly slow. This should have been templated in.
*/
public static function printCurrentPlaylistForEmbedding()
{
$front = Zend_Controller_Front::getInstance();
$scheduleController = new ScheduleController($front->getRequest(), $front->getResponse());
$scheduleController->getCurrentPlaylistAction();
echo(json_encode($scheduleController->view));
}
public function getCurrentPlaylistAction()
{
$range = Application_Model_Schedule::GetPlayOrderRangeOld();
// If there is no current track playing update TuneIn so it doesn't
// display outdated metadata
//TODO: find a better solution for this so we don't spam the station on TuneIn
/*if (is_null($range["current"]) && Application_Model_Preference::getTuneinEnabled()) {
Application_Common_TuneIn::updateOfflineMetadata();
}*/
$show = Application_Model_Show::getCurrentShow();
/* Convert all UTC times to localtime before sending back to user. */

View file

@ -42,7 +42,7 @@ class ShowbuilderController extends Zend_Controller_Action
$this->view->headScript()->appendFile($baseUrl.'js/datatables/plugin/dataTables.pluginAPI.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
$this->view->headScript()->appendFile($baseUrl.'js/datatables/plugin/dataTables.fnSetFilteringDelay.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
$this->view->headScript()->appendFile($baseUrl.'js/datatables/plugin/dataTables.ColVis.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
$this->view->headScript()->appendFile($baseUrl.'js/datatables/plugin/dataTables.ColReorder.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
//$this->view->headScript()->appendFile($baseUrl.'js/datatables/plugin/dataTables.ColReorder.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
$this->view->headScript()->appendFile($baseUrl.'js/datatables/plugin/dataTables.FixedColumns.js?'.$CC_CONFIG['airtime_version'],'text/javascript');
$this->view->headScript()->appendFile($baseUrl.'js/datatables/plugin/dataTables.columnFilter.js?'.$CC_CONFIG['airtime_version'], 'text/javascript');
@ -67,7 +67,8 @@ class ShowbuilderController extends Zend_Controller_Action
if (isset($values["Privacy"])) {
Application_Model_Preference::SetPrivacyPolicyCheck($values["Privacy"]);
}
// unset session
session_start(); //open session for writing again
// unset referrer
Zend_Session::namespaceUnset('referrer');
} elseif ($values["Publicise"] == '1' && $form->isValid($values)) {
Application_Model_Preference::SetHeadTitle($values["stnName"], $this->view);
@ -88,7 +89,8 @@ class ShowbuilderController extends Zend_Controller_Action
if (isset($values["Privacy"])) {
Application_Model_Preference::SetPrivacyPolicyCheck($values["Privacy"]);
}
// unset session
session_start(); //open session for writing again
// unset referrer
Zend_Session::namespaceUnset('referrer');
} else {
$logo = Application_Model_Preference::GetStationLogo();
@ -156,7 +158,7 @@ class ShowbuilderController extends Zend_Controller_Action
//populate date range form for show builder.
$now = time();
$from = $request->getParam("from", $now);
$to = $request->getParam("to", $now + (24*60*60));
$to = $request->getParam("to", $now + (3*60*60));
$utcTimezone = new DateTimeZone("UTC");
$displayTimeZone = new DateTimeZone(Application_Model_Preference::GetTimezone());
@ -341,7 +343,8 @@ class ShowbuilderController extends Zend_Controller_Action
$request = $this->getRequest();
$selectedItems = $request->getParam("selectedItem");
$afterItem = $request->getParam("afterItem");
/*
$log_vars = array();
$log_vars["url"] = $_SERVER['HTTP_HOST'];
$log_vars["action"] = "showbuilder/schedule-move";
@ -349,6 +352,7 @@ class ShowbuilderController extends Zend_Controller_Action
$log_vars["params"]["selected_items"] = $selectedItems;
$log_vars["params"]["destination_after_item"] = $afterItem;
Logging::info($log_vars);
*/
try {
$scheduler = new Application_Model_Scheduler();

View file

@ -13,16 +13,18 @@ class SystemstatusController extends Zend_Controller_Action
public function indexAction()
{
/*
$services = array(
"pypo"=>Application_Model_Systemstatus::GetPypoStatus(),
"liquidsoap"=>Application_Model_Systemstatus::GetLiquidsoapStatus(),
//"media-monitor"=>Application_Model_Systemstatus::GetMediaMonitorStatus(),
);
*/
$partitions = Application_Model_Systemstatus::GetDiskInfo();
$this->view->status = new StdClass;
$this->view->status->services = $services;
//$this->view->status->services = $services;
$this->view->status->partitions = $partitions;
}
}

View file

@ -16,6 +16,9 @@ class UserController extends Zend_Controller_Action
public function addUserAction()
{
// Start the session to re-open write permission to the session so we can
// create the namespace for our csrf token verification
session_start();
$CC_CONFIG = Config::getConfig();
$request = $this->getRequest();
@ -118,7 +121,8 @@ class UserController extends Zend_Controller_Action
}
public function editUserAction()
{
{
session_start(); //Reopen session for writing.
$request = $this->getRequest();
$form = new Application_Form_EditUser();
if ($request->isPost()) {

View file

@ -61,28 +61,23 @@ class UsersettingsController extends Zend_Controller_Action
public function getTimelineDatatableAction()
{
$start = microtime(true);
$data = Application_Model_Preference::getTimelineDatatableSetting();
if (!is_null($data)) {
$this->view->settings = $data;
}
$end = microtime(true);
Logging::debug("getting timeline datatables info took:");
Logging::debug(floatval($end) - floatval($start));
}
public function remindmeAction()
{
// unset session
session_start(); //open session for writing again
Zend_Session::namespaceUnset('referrer');
Application_Model_Preference::SetRemindMeDate();
}
public function remindmeNeverAction()
{
session_start(); //open session for writing again
Zend_Session::namespaceUnset('referrer');
//pass in true to indicate 'Remind me never' was clicked
Application_Model_Preference::SetRemindMeDate(true);
@ -91,6 +86,7 @@ class UsersettingsController extends Zend_Controller_Action
public function donotshowregistrationpopupAction()
{
// unset session
session_start(); //open session for writing again
Zend_Session::namespaceUnset('referrer');
}

View file

@ -87,43 +87,8 @@ class Application_Form_TuneInPreferences extends Zend_Form_SubForm
if (!$xmlObj || $xmlObj->head->status != "200") {
$valid = false;
} else if ($xmlObj->head->status == "200") {
Application_Model_Preference::setLastTuneinMetadataUpdate(time());
$valid = true;
// Make another request to TuneIn to update the metadata right away
// and to turn off the commercial flag.
/*$metadata = Application_Model_Schedule::getCurrentPlayingTrack();
if (!is_null($metadata)) {
Logging::info($metadata);
// Replace empty strings with "n/a" since the TuneIn API will complain
// and return an error that title and/or artist is not set.
$metadata["artist"] = empty($metadata["artist"]) ? "n/a" : $metadata["artist"];
$metadata["title"] = empty($metadata["title"]) ? "n/a" : $metadata["title"];
Logging::info($metadata);
$metadataQryStr = "&artist=" . $metadata["artist"] . "&title=" . $metadata["title"];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, TUNEIN_API_URL . $qry_str . "&commercial=false" . $metadataQryStr);
curl_setopt($ch, CURLOPT_FAILONERROR, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$xmlData = curl_exec($ch);
Logging::info($xmlData);
if (curl_error($ch)) {
Logging::error("Failed to reach TuneIn: " . curl_errno($ch) . " - " . curl_error($ch) . " - " . curl_getinfo($ch, CURLINFO_EFFECTIVE_URL));
}
curl_close($ch);
$xmlObj = new SimpleXMLElement($xmlData);
if (!$xmlObj || $xmlObj->head->status != "200") {
Logging::error("Failed updating metadata on TuneIn");
}
}*/
}
}
} else {

View file

@ -34,6 +34,23 @@ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
"scheduled_play_switch"=>$sss['scheduled_play'])) ?>
<?php $partial = array('menu.phtml', 'default');
$this->navigation()->menu()->setPartial($partial); ?>
<script type="text/javascript">
var schedulePreLoaded = <?php
//Awful hack to speed up loading - Embed the schedule in the response so that the dashboard
//doesn't have to make a separate AJAX request to get this data.
require_once("ScheduleController.php");
ScheduleController::printCurrentPlaylistForEmbedding();
?>;
//The DOM elements that these calls depend on exist by this point:
parseItems(schedulePreLoaded.entries);
parseSourceStatus(schedulePreLoaded.source_status);
parseSwitchStatus(schedulePreLoaded.switch_status);
</script>
<div id="nav">
<div class="logo"></div>
<div class="personal-block solo">

View file

@ -1493,4 +1493,14 @@ class Application_Model_Preference
{
return self::getValue("tunein_station_id");
}
public static function geLastTuneinMetadataUpdate()
{
return self::getValue("last_tunein_metadata_update");
}
public static function setLastTuneinMetadataUpdate($value)
{
self::setValue("last_tunein_metadata_update", $value);
}
}

View file

@ -98,10 +98,8 @@ SQL;
$utcNow = new DateTime("now", new DateTimeZone("UTC"));
$shows = Application_Model_Show::getPrevCurrentNext($utcNow, $utcTimeEnd, $showsToRetrieve);
$previousShowID = count($shows['previousShow'])>0?$shows['previousShow'][0]['instance_id']:null;
$currentShowID = count($shows['currentShow'])>0?$shows['currentShow']['instance_id']:null;
$nextShowID = count($shows['nextShow'])>0?$shows['nextShow'][0]['instance_id']:null;
$results = self::GetPrevCurrentNext($previousShowID, $currentShowID, $nextShowID, $utcNow);
$results = Application_Model_Schedule::getPreviousCurrentNextMedia($utcNow, $currentShowID);
$range = array(
"station" => array (
@ -136,10 +134,8 @@ SQL;
$utcNow = new DateTime("now", new DateTimeZone("UTC"));
$shows = Application_Model_Show::getPrevCurrentNextOld($utcNow);
$previousShowID = count($shows['previousShow'])>0?$shows['previousShow'][0]['instance_id']:null;
$currentShowID = count($shows['currentShow'])>0?$shows['currentShow'][0]['instance_id']:null;
$nextShowID = count($shows['nextShow'])>0?$shows['nextShow'][0]['instance_id']:null;
$results = self::GetPrevCurrentNext($previousShowID, $currentShowID, $nextShowID, $utcNow);
$results = Application_Model_Schedule::getPreviousCurrentNextMedia($utcNow, $currentShowID);
$range = array(
"env" => APPLICATION_ENV,
@ -157,129 +153,158 @@ SQL;
}
/**
* Queries the database for the set of schedules one hour before
* and after the given time. If a show starts and ends within that
* time that is considered the current show. Then the scheduled item
* before it is the previous show, and the scheduled item after it
* is the next show. This way the dashboard getCurrentPlaylist is
* very fast. But if any one of the three show types are not found
* through this mechanism a call is made to the old way of querying
* the database to find the track info.
**/
public static function GetPrevCurrentNext($p_previousShowID, $p_currentShowID, $p_nextShowID, $utcNow)
* Attempts to find a media item (track or webstream) that is currently playing.
* If a current media item is currently playing, this function then attempts to
* find an item that played previously and is scheduled to play next.
*
* @param $utcNow DateTime current time in UTC
* @param $currentShowInstanceId cc_show_instance id of the show instance currently playing
* @return array with data about the previous, current, and next media items playing.
* Returns an empty arrays if there is no media item currently playing
*/
public static function getPreviousCurrentNextMedia($utcNow, $currentShowInstanceId)
{
$timeZone = new DateTimeZone("UTC"); //This function works entirely in UTC.
assert(get_class($utcNow) === "DateTime");
assert($utcNow->getTimeZone() == $timeZone);
if ($p_previousShowID == null && $p_currentShowID == null && $p_nextShowID == null) {
return;
}
$sql = "SELECT %%columns%% st.starts as starts, st.ends as ends,
st.media_item_played as media_item_played, si.ends as show_ends
%%tables%% WHERE ";
$fileColumns = "ft.artist_name, ft.track_title, ";
$fileJoin = "FROM cc_schedule st JOIN cc_files ft ON st.file_id = ft.id
LEFT JOIN cc_show_instances si ON st.instance_id = si.id";
$streamColumns = "ws.name AS artist_name, wm.liquidsoap_data AS track_title, ";
$streamJoin = <<<SQL
FROM cc_schedule AS st
JOIN cc_webstream ws ON st.stream_id = ws.id
LEFT JOIN cc_show_instances AS si ON st.instance_id = si.id
LEFT JOIN cc_subjs AS sub ON sub.id = ws.creator_id
LEFT JOIN
(SELECT *
FROM cc_webstream_metadata
ORDER BY start_time DESC LIMIT 1) AS wm ON st.id = wm.instance_id
SQL;
$predicateArr = array();
$paramMap = array();
if (isset($p_previousShowID)) {
$predicateArr[] = 'st.instance_id = :previousShowId';
$paramMap[':previousShowId'] = $p_previousShowID;
}
if (isset($p_currentShowID)) {
$predicateArr[] = 'st.instance_id = :currentShowId';
$paramMap[':currentShowId'] = $p_currentShowID;
}
if (isset($p_nextShowID)) {
$predicateArr[] = 'st.instance_id = :nextShowId';
$paramMap[':nextShowId'] = $p_nextShowID;
}
$sql .= " (".implode(" OR ", $predicateArr).") ";
$sql .= ' AND st.playout_status > 0 ORDER BY st.starts';
$filesSql = str_replace("%%columns%%", $fileColumns, $sql);
$filesSql = str_replace("%%tables%%", $fileJoin, $filesSql);
$streamSql = str_replace("%%columns%%", $streamColumns, $sql);
$streamSql = str_replace("%%tables%%", $streamJoin, $streamSql);
$sql = "SELECT * FROM (($filesSql) UNION ($streamSql)) AS unioned ORDER BY starts";
$rows = Application_Common_Database::prepareAndExecute($sql, $paramMap);
$numberOfRows = count($rows);
$results['previous'] = null;
$results['current'] = null;
$results['next'] = null;
for ($i = 0; $i < $numberOfRows; ++$i) {
$sql = "select s.id, s.starts, s.ends, s.file_id, s.stream_id, s.media_item_played,
s.instance_id, si.ends as show_ends from cc_schedule s left join cc_show_instances si
on s.instance_id = si.id where s.playout_status > 0 and s.starts <= :p1
and s.ends >= :p2 and s.instance_id = :p3 order by starts desc limit 1";
// if the show is overbooked, then update the track end time to the end of the show time.
if ($rows[$i]['ends'] > $rows[$i]["show_ends"]) {
$rows[$i]['ends'] = $rows[$i]["show_ends"];
}
$params = array(
":p1" => $utcNow->format("Y-m-d H:i:s"),
":p2" => $utcNow->format("Y-m-d H:i:s"),
":p3" => $currentShowInstanceId
);
$curShowStartTime = new DateTime($rows[$i]['starts'], $timeZone);
$curShowEndTime = new DateTime($rows[$i]['ends'], $timeZone);
$rows = Application_Common_Database::prepareAndExecute($sql, $params);
if (($curShowStartTime <= $utcNow) && ($curShowEndTime >= $utcNow)) {
if ($i - 1 >= 0) {
$results['previous'] = array("name"=>$rows[$i-1]["artist_name"]." - ".$rows[$i-1]["track_title"],
"starts"=>$rows[$i-1]["starts"],
"ends"=>$rows[$i-1]["ends"],
"type"=>'track');
}
$results['current'] = array("name"=>$rows[$i]["artist_name"]." - ".$rows[$i]["track_title"],
"starts"=>$rows[$i]["starts"],
"ends"=> (($rows[$i]["ends"] > $rows[$i]["show_ends"]) ? $rows[$i]["show_ends"]: $rows[$i]["ends"]),
"media_item_played"=>$rows[$i]["media_item_played"],
"record"=>0,
"type"=>'track');
if (isset($rows[$i+1])) {
$results['next'] = array("name"=>$rows[$i+1]["artist_name"]." - ".$rows[$i+1]["track_title"],
"starts"=>$rows[$i+1]["starts"],
"ends"=>$rows[$i+1]["ends"],
"type"=>'track');
}
break;
}
if ($curShowEndTime < $utcNow ) {
$previousIndex = $i;
}
if ($curShowStartTime > $utcNow) {
$results['next'] = array("name"=>$rows[$i]["artist_name"]." - ".$rows[$i]["track_title"],
"starts"=>$rows[$i]["starts"],
"ends"=>$rows[$i]["ends"],
"type"=>'track');
break;
}
if (count($rows) < 1) {
return $results;
}
//If we didn't find a a current show because the time didn't fit we may still have
//found a previous show so use it.
if ($results['previous'] === null && isset($previousIndex)) {
$results['previous'] = array("name"=>$rows[$previousIndex]["artist_name"]." - ".$rows[$previousIndex]["track_title"],
"starts"=>$rows[$previousIndex]["starts"],
"ends"=>$rows[$previousIndex]["ends"]);;
if ($rows[0]["show_ends"] < $utcNow->format("Y-m-d H:i:s")) {
return $results;
}
$currentMedia = $rows[0];
if ($currentMedia["ends"] > $currentMedia["show_ends"]) {
$currentMedia["ends"] = $currentMedia["show_ends"];
}
$currentMediaScheduleId = $currentMedia["id"];
$currentMediaFileId = $currentMedia["file_id"];
$currentMediaStreamId = $currentMedia["stream_id"];
if (isset($currentMediaFileId)) {
$currentMediaType = "track";
$currentFile = CcFilesQuery::create()
->filterByDbId($currentMediaFileId)
->findOne();
$currentMediaName = $currentFile->getDbArtistName() . " - " . $currentFile->getDbTrackTitle();
} else if (isset($currentMediaStreamId)) {
$currentMediaType = "webstream";
$currentWebstream = CcWebstreamQuery::create()
->filterByDbId($currentMediaStreamId)
->findOne();
$currentWebstreamMetadata = CcWebstreamMetadataQuery::create()
->filterByDbInstanceId($currentMedia["instance_id"])
->orderByDbStartTime(Criteria::DESC)
->findOne();
$currentMediaName = $currentWebstream->getDbName();
if (isset($currentWebstreamMetadata)) {
$currentMediaName .= " - " . $currentWebstreamMetadata->getDbLiquidsoapData();
}
} else {
$currentMediaType = null;
}
$results["current"] = array(
"starts" => $currentMedia["starts"],
"ends" => $currentMedia["ends"],
"type" => $currentMediaType,
"name" => $currentMediaName,
"media_item_played" => $currentMedia["media_item_played"],
"record" => "0"
);
$previousMedia = CcScheduleQuery::create()
->filterByDbId($currentMediaScheduleId-1)
->filterByDbPlayoutStatus(0, Criteria::GREATER_THAN)
->orderByDbStarts()
->findOne();
if (isset($previousMedia)) {
$previousMediaFileId = $previousMedia->getDbFileId();
$previousMediaStreamId = $previousMedia->getDbStreamId();
if (isset($previousMediaFileId)) {
$previousMediaType = "track";
$previousFile = CcFilesQuery::create()
->filterByDbId($previousMediaFileId)
->findOne();
$previousMediaName = $previousFile->getDbArtistName() . " - " . $previousFile->getDbTrackTitle();
} else if (isset($previousMediaStreamId)) {
$previousMediaName = null;
$previousMediaType = "webstream";
$previousWebstream = CcWebstreamQuery::create()
->filterByDbId($previousMediaStreamId)
->findOne();
/*$previousWebstreamMetadata = CcWebstreamMetadataQuery::create()
->filterByDbInstanceId($previousMedia->getDbInstanceId())
->orderByDbStartTime(Criteria::DESC)
->findOne();*/
$previousMediaName = $previousWebstream->getDbName();
} else {
$previousMediaType = null;
}
$results["previous"] = array(
"starts" => $previousMedia->getDbStarts(),
"ends" => $previousMedia->getDbEnds(),
"type" => $previousMediaType,
"name" => $previousMediaName
);
}
$nextMedia = CcScheduleQuery::create()
->filterByDbId($currentMediaScheduleId+1)
->orderByDbStarts()
->findOne();
if (isset($nextMedia)) {
$nextMediaFileId = $nextMedia->getDbFileId();
$nextMediaStreamId = $nextMedia->getDbStreamId();
if (isset($nextMediaFileId)) {
$nextMediaType = "track";
$nextFile = CcFilesQuery::create()
->filterByDbId($nextMediaFileId)
->findOne();
$nextMediaName = $nextFile->getDbArtistName() . " - " . $nextFile->getDbTrackTitle();
} else if (isset($nextMediaStreamId)) {
$nextMediaType = "webstream";
$nextWebstream = CcWebstreamQuery::create()
->filterByDbId($nextMediaStreamId)
->findOne();
/*$nextWebstreamMetadata = CcWebstreamMetadataQuery::create()
->filterByDbInstanceId($nextMedia->getDbInstanceId())
->orderByDbStartTime(Criteria::DESC)
->findOne();*/
$nextMediaName = $nextWebstream->getDbName();
} else {
$nextMediaType = null;
}
$results["next"] = array(
"starts" => $nextMedia->getDbStarts(),
"ends" => $nextMedia->getDbEnds(),
"type" => $nextMediaType,
"name" => $nextMediaName
);
}
return $results;
}
public static function GetLastScheduleItem($p_timeNow)

View file

@ -1012,10 +1012,10 @@ class Application_Model_Scheduler
*/
public function moveItem($selectedItems, $afterItems, $adjustSched = true)
{
$startProfile = microtime(true);
//$startProfile = microtime(true);
$this->con->beginTransaction();
$this->con->useDebug(true);
//$this->con->useDebug(true);
try {
@ -1024,8 +1024,8 @@ class Application_Model_Scheduler
$this->validateRequest($afterItems);
$endProfile = microtime(true);
Logging::debug("validating move request took:");
Logging::debug(floatval($endProfile) - floatval($startProfile));
//Logging::debug("validating move request took:");
//Logging::debug(floatval($endProfile) - floatval($startProfile));
$afterInstance = CcShowInstancesQuery::create()->findPK($afterItems[0]["instance"], $this->con);
@ -1066,18 +1066,18 @@ class Application_Model_Scheduler
$this->removeGaps($instance, $schedIds);
$endProfile = microtime(true);
Logging::debug("removing gaps from instance $instance:");
Logging::debug(floatval($endProfile) - floatval($startProfile));
//$endProfile = microtime(true);
//Logging::debug("removing gaps from instance $instance:");
//Logging::debug(floatval($endProfile) - floatval($startProfile));
}
$startProfile = microtime(true);
//$startProfile = microtime(true);
$this->insertAfter($afterItems, null, $movedData, $adjustSched, true);
$endProfile = microtime(true);
Logging::debug("inserting after removing gaps.");
Logging::debug(floatval($endProfile) - floatval($startProfile));
//$endProfile = microtime(true);
//Logging::debug("inserting after removing gaps.");
//Logging::debug(floatval($endProfile) - floatval($startProfile));
$modified = array_keys($modifiedMap);
//need to adjust shows we have moved items from.
@ -1087,7 +1087,7 @@ class Application_Model_Scheduler
$instance->updateScheduleStatus($this->con);
}
$this->con->useDebug(false);
//$this->con->useDebug(false);
$this->con->commit();
Application_Model_RabbitMq::PushSchedule();

View file

@ -974,10 +974,7 @@ SQL;
foreach ($shows as &$show) {
$options = array();
//only bother calculating percent for week or day view.
if (intval($days) <= 7) {
$options["percent"] = Application_Model_Show::getPercentScheduled($show["starts"], $show["ends"], $show["time_filled"]);
}
$options["percent"] = Application_Model_Show::getPercentScheduled($show["starts"], $show["ends"], $show["time_filled"]);
if (isset($show["parent_starts"])) {
$parentStartsDT = new DateTime($show["parent_starts"], $utcTimezone);
@ -1432,39 +1429,70 @@ SQL;
}
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);
$utcTimeZone = new DateTimeZone("UTC");
//We have to get the start of the day in the user's timezone, and then convert that to UTC.
$start = new DateTime("first day of this month", new DateTimeZone(Application_Model_Preference::GetUserTimezone()));
$start->setTimezone($utcTimeZone); //Covert it to UTC.
$monthInterval = new DateInterval("P1M");
$end = clone($start);
$end->add($monthInterval);
return array($start, $end);
}
/** Returns the start and end date that FullCalendar will display for today's month.
*
* FullCalendar displays 6 weeks, starting on a Sunday, for a total of 42 days. This function returns 42 days worth
* of data (a few days before, and a few days after.)
*/
public static function getStartEndCurrentMonthPlusView() {
$utcTimeZone = new DateTimeZone("UTC");
//We have to get the start of the day in the user's timezone, and then convert that to UTC.
$start = new DateTime("first day of this month", new DateTimeZone(Application_Model_Preference::GetUserTimezone()));
$dayOfWeekNumeric = $start->format('w');
$start->sub(new DateInterval("P{$dayOfWeekNumeric}D")); //Subtract the index of the day of the week the month starts on. (adds this many days from the previous month)
$start->setTimezone($utcTimeZone); //Covert it to UTC.
$fullCalendarMonthInterval = new DateInterval("P42D"); //42 days
$end = clone($start);
$end->add($fullCalendarMonthInterval);
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);
$weekStartDayNum = Application_Model_Preference::GetWeekStartDay();
$utcTimeZone = new DateTimeZone("UTC");
//We have to get the start of the week in the user's timezone, and then convert that to UTC.
$start = new DateTime("Sunday last week", new DateTimeZone(Application_Model_Preference::GetUserTimezone()));
$start->add(new DateInterval("P{$weekStartDayNum}D")); //Shift the start date to the station's "Week Starts on Day"
$start->setTimezone($utcTimeZone); //Covert it to UTC.
$weekInterval = new DateInterval("P1W");
$end = clone($start);
$end->add($weekInterval);
return array($start, $end);
}
public static function getStartEndCurrentDayView() {
$today = mktime(0, 0, 0, date("n"), date("j"));
$tomorrow = $today + 3600*24;
$utcTimeZone = new DateTimeZone("UTC");
$start = new DateTime("@".$today);
$end = new DateTime("@".$tomorrow);
//We have to get the start of the day in the user's timezone, and then convert that to UTC.
$start = new DateTime("today", new DateTimeZone(Application_Model_Preference::GetUserTimezone()));
$start->setTimezone($utcTimeZone); //Covert it to UTC.
$dayInterval = new DateInterval("P1D");
$end = clone($start);
$end->add($dayInterval);
return array($start, $end);
}

View file

@ -1,31 +1,6 @@
<table width="60%" cellpadding="0" cellspacing="0" border="0" class="statustable">
<thead>
<tr class="ui-state-default strong">
<td><?php echo _("Service") ?></td>
<td><?php echo _("Status") ?></td>
<td><?php echo _("Uptime") ?></td>
<td><?php echo _("CPU") ?></td>
<td><?php echo _("Memory") ?></td>
</tr>
</thead>
<tbody>
<!--
<tr class="odd">
<td><?php echo sprintf(_("%s Version"), PRODUCT_NAME) ?></td>
<td>1.9.3</td>
<td>&nbsp;</td>
</tr>
-->
<?php $i=0; ?>
<?php foreach($this->status->services as $key=>$value): ?>
<tr class="<?php echo ($i&1) == 0 ? "even":"odd"; $i++; ?>" id="<?php echo $value["name"]; ?>">
<td><?php echo $value["name"]; ?></td>
<td><span></span></td>
<td></td>
<td></td>
<td></td>
</tr>
<?php endforeach; ?>
<tr id="partitions" class="even">
<th colspan="5"><?php echo _("Disk Space") ?></th>
</tr>