diff --git a/airtime_mvc/application/Bootstrap.php b/airtime_mvc/application/Bootstrap.php
index 0c56fc2bb..f7af625b3 100644
--- a/airtime_mvc/application/Bootstrap.php
+++ b/airtime_mvc/application/Bootstrap.php
@@ -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();
}
/**
diff --git a/airtime_mvc/application/common/TuneIn.php b/airtime_mvc/application/common/TuneIn.php
index 6040fb184..cbaf51871 100644
--- a/airtime_mvc/application/common/TuneIn.php
+++ b/airtime_mvc/application/common/TuneIn.php
@@ -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);
- }
-
}
diff --git a/airtime_mvc/application/controllers/ApiController.php b/airtime_mvc/application/controllers/ApiController.php
index 38c453d9e..490800085 100644
--- a/airtime_mvc/application/controllers/ApiController.php
+++ b/airtime_mvc/application/controllers/ApiController.php
@@ -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));
+ }
}
diff --git a/airtime_mvc/application/controllers/LoginController.php b/airtime_mvc/application/controllers/LoginController.php
index 9d2ef2f9d..920a258cc 100644
--- a/airtime_mvc/application/controllers/LoginController.php
+++ b/airtime_mvc/application/controllers/LoginController.php
@@ -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()
diff --git a/airtime_mvc/application/controllers/PlaylistController.php b/airtime_mvc/application/controllers/PlaylistController.php
index 4f511f4b5..2bbe691e1 100644
--- a/airtime_mvc/application/controllers/PlaylistController.php
+++ b/airtime_mvc/application/controllers/PlaylistController.php
@@ -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)
diff --git a/airtime_mvc/application/controllers/PreferenceController.php b/airtime_mvc/application/controllers/PreferenceController.php
index 710952ef8..3a0df1505 100644
--- a/airtime_mvc/application/controllers/PreferenceController.php
+++ b/airtime_mvc/application/controllers/PreferenceController.php
@@ -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++) {
diff --git a/airtime_mvc/application/controllers/ScheduleController.php b/airtime_mvc/application/controllers/ScheduleController.php
index 51b86c124..1890ac200 100644
--- a/airtime_mvc/application/controllers/ScheduleController.php
+++ b/airtime_mvc/application/controllers/ScheduleController.php
@@ -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. */
diff --git a/airtime_mvc/application/controllers/ShowbuilderController.php b/airtime_mvc/application/controllers/ShowbuilderController.php
index 3bb30abf4..712bc0348 100644
--- a/airtime_mvc/application/controllers/ShowbuilderController.php
+++ b/airtime_mvc/application/controllers/ShowbuilderController.php
@@ -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();
diff --git a/airtime_mvc/application/controllers/SystemstatusController.php b/airtime_mvc/application/controllers/SystemstatusController.php
index dfc2d019b..543fbef70 100644
--- a/airtime_mvc/application/controllers/SystemstatusController.php
+++ b/airtime_mvc/application/controllers/SystemstatusController.php
@@ -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;
}
}
diff --git a/airtime_mvc/application/controllers/UserController.php b/airtime_mvc/application/controllers/UserController.php
index 51ac869e7..4c3168f80 100644
--- a/airtime_mvc/application/controllers/UserController.php
+++ b/airtime_mvc/application/controllers/UserController.php
@@ -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()) {
diff --git a/airtime_mvc/application/controllers/UsersettingsController.php b/airtime_mvc/application/controllers/UsersettingsController.php
index 9d8154578..35fbb19e1 100644
--- a/airtime_mvc/application/controllers/UsersettingsController.php
+++ b/airtime_mvc/application/controllers/UsersettingsController.php
@@ -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');
}
diff --git a/airtime_mvc/application/forms/TuneInPreferences.php b/airtime_mvc/application/forms/TuneInPreferences.php
index 7eee0d56f..ad133255a 100644
--- a/airtime_mvc/application/forms/TuneInPreferences.php
+++ b/airtime_mvc/application/forms/TuneInPreferences.php
@@ -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 {
diff --git a/airtime_mvc/application/layouts/scripts/layout.phtml b/airtime_mvc/application/layouts/scripts/layout.phtml
index d7cbad25e..c3f5f5e2d 100644
--- a/airtime_mvc/application/layouts/scripts/layout.phtml
+++ b/airtime_mvc/application/layouts/scripts/layout.phtml
@@ -34,6 +34,23 @@ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
"scheduled_play_switch"=>$sss['scheduled_play'])) ?>
navigation()->menu()->setPartial($partial); ?>
+
+
+
+
+
diff --git a/airtime_mvc/application/models/Preference.php b/airtime_mvc/application/models/Preference.php
index 1387d326b..541870fde 100644
--- a/airtime_mvc/application/models/Preference.php
+++ b/airtime_mvc/application/models/Preference.php
@@ -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);
+ }
}
diff --git a/airtime_mvc/application/models/Schedule.php b/airtime_mvc/application/models/Schedule.php
index 66d00661b..d2e114243 100644
--- a/airtime_mvc/application/models/Schedule.php
+++ b/airtime_mvc/application/models/Schedule.php
@@ -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 = << 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)
diff --git a/airtime_mvc/application/models/Scheduler.php b/airtime_mvc/application/models/Scheduler.php
index edcf2da10..bcb01cf61 100644
--- a/airtime_mvc/application/models/Scheduler.php
+++ b/airtime_mvc/application/models/Scheduler.php
@@ -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();
diff --git a/airtime_mvc/application/models/Show.php b/airtime_mvc/application/models/Show.php
index 73925fc65..f96ad7ee0 100644
--- a/airtime_mvc/application/models/Show.php
+++ b/airtime_mvc/application/models/Show.php
@@ -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);
}
diff --git a/airtime_mvc/application/views/scripts/systemstatus/index.phtml b/airtime_mvc/application/views/scripts/systemstatus/index.phtml
index 2a31ac78e..de8dea94a 100644
--- a/airtime_mvc/application/views/scripts/systemstatus/index.phtml
+++ b/airtime_mvc/application/views/scripts/systemstatus/index.phtml
@@ -1,31 +1,6 @@
-
-
-
-
-
-
-
-
-
+
-
-
- status->services as $key=>$value): ?>
-
" id="">
-
-
-
-
-
-
-
diff --git a/airtime_mvc/public/js/airtime/dashboard/dashboard.js b/airtime_mvc/public/js/airtime/dashboard/dashboard.js
index e4ffc1faf..2f3cc0ae5 100644
--- a/airtime_mvc/public/js/airtime/dashboard/dashboard.js
+++ b/airtime_mvc/public/js/airtime/dashboard/dashboard.js
@@ -395,7 +395,6 @@ function getScheduleFromServer(){
parseSourceStatus(data.source_status);
parseSwitchStatus(data.switch_status);
showName = data.show_name;
- setTimeout(getScheduleFromServer, serverUpdateInterval);
}, error:function(jqXHR, textStatus, errorThrown){}});
}
@@ -456,8 +455,8 @@ var stream_window = null;
function init() {
//begin producer "thread"
- getScheduleFromServer();
-
+ setInterval(getScheduleFromServer, serverUpdateInterval);
+
//begin consumer "thread"
secondsTimer();
diff --git a/airtime_mvc/public/js/airtime/dashboard/helperfunctions.js b/airtime_mvc/public/js/airtime/dashboard/helperfunctions.js
index bccef632b..ad156dfe8 100644
--- a/airtime_mvc/public/js/airtime/dashboard/helperfunctions.js
+++ b/airtime_mvc/public/js/airtime/dashboard/helperfunctions.js
@@ -213,3 +213,21 @@ function resizeToMaxHeight(ele, targetHeight){
img.css("width", newWidth+"px");
}
}
+
+/* From http://stackoverflow.com/questions/123999/how-to-tell-if-a-dom-element-is-visible-in-the-current-viewport/#7557433 */
+function isInView(el) {
+ //special bonus for those using jQuery
+ if (typeof jQuery === "function" && el instanceof jQuery) {
+ el = el[0];
+ }
+
+ var rect = el.getBoundingClientRect();
+
+ return (
+ rect.top >= 0 &&
+ rect.left >= 0 &&
+ rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) && /*or $(window).height() */
+ rect.right <= (window.innerWidth || document.documentElement.clientWidth) /*or $(window).width() */
+ );
+}
+
diff --git a/airtime_mvc/public/js/airtime/library/events/library_showbuilder.js b/airtime_mvc/public/js/airtime/library/events/library_showbuilder.js
index f87dafcd7..315caf986 100644
--- a/airtime_mvc/public/js/airtime/library/events/library_showbuilder.js
+++ b/airtime_mvc/public/js/airtime/library/events/library_showbuilder.js
@@ -8,20 +8,31 @@ var AIRTIME = (function(AIRTIME) {
mod = AIRTIME.library;
mod.checkAddButton = function() {
- var selected = mod.getChosenItemsLength(), $cursor = $('tr.cursor-selected-row'), check = false;
+ var selected = mod.getChosenItemsLength(), $cursor = $('tr.sb-selected'), check = false,
+ shows = $('tr.sb-header'), current = $('tr.sb-current-show'),
+ cursorText = $.i18n._('Add to next show');
// make sure library items are selected and a cursor is selected.
- if (selected !== 0 && $cursor.length !== 0) {
+ if (selected !== 0) {
check = true;
}
+ if (shows.length === 0) {
+ check = false;
+ }
+
if (check === true) {
AIRTIME.button.enableButton("btn-group #library-plus", false);
} else {
AIRTIME.button.disableButton("btn-group #library-plus", false);
}
-
- AIRTIME.library.changeAddButtonText($('.btn-group #library-plus #lib-plus-text'), ' '+$.i18n._('Add to selected show'));
+
+ if ($cursor.length !== 0) {
+ cursorText = $.i18n._('Add before selected items');
+ } else if (current.length !== 0) {
+ cursorText = $.i18n._('Add to current show');
+ }
+ AIRTIME.library.changeAddButtonText($('.btn-group #library-plus #lib-plus-text'), ' '+ cursorText);
};
mod.fnRowCallback = function(nRow, aData, iDisplayIndex, iDisplayIndexFull) {
@@ -98,7 +109,7 @@ var AIRTIME = (function(AIRTIME) {
"type" : type
});
- $("#show_builder_table tr.cursor-selected-row").each(function(i, el) {
+ $("#show_builder_table tr.sb-selected").each(function(i, el) {
aData.push($(el).prev().data("aData"));
});
@@ -113,12 +124,35 @@ var AIRTIME = (function(AIRTIME) {
}
if (aSchedIds.length == 0) {
- alert($.i18n._("Please select a cursor position on timeline."));
- return false;
+ addToCurrentOrNext(aSchedIds);
}
+
AIRTIME.showbuilder.fnAdd(aMediaIds, aSchedIds);
};
+ function addToCurrentOrNext(arr) {
+ var el;
+ // Get the show instance id of the first non-data row (id = 0)
+ // The second last row in the table with that instance id is the
+ // last schedule item for the first show. (This is important for
+ // the Now Playing screen if multiple shows are in view).
+ el = $("[si_id="+$("#0").attr("si_id")+"]");
+ var temp = el.eq(-2).data("aData");
+ arr.push({
+ "id" : temp.id,
+ "instance" : temp.instance,
+ "timestamp" : temp.timestamp
+ });
+
+ if (!isInView(el)) {
+ $('.dataTables_scrolling.sb-padded').animate({
+ scrollTop: el.offset().top
+ }, 0);
+ }
+
+ return arr;
+ }
+
mod.setupLibraryToolbar = function() {
var $toolbar = $(".lib-content .fg-toolbar:first");
@@ -146,7 +180,7 @@ var AIRTIME = (function(AIRTIME) {
});
}
- $("#show_builder_table tr.cursor-selected-row")
+ $("#show_builder_table tr.sb-selected")
.each(function(i, el) {
aData.push($(el).prev().data("aData"));
});
@@ -161,6 +195,10 @@ var AIRTIME = (function(AIRTIME) {
"timestamp" : temp.timestamp
});
}
+
+ if (aSchedIds.length == 0) {
+ addToCurrentOrNext(aSchedIds);
+ }
AIRTIME.showbuilder.fnAdd(aMediaIds, aSchedIds);
});
diff --git a/airtime_mvc/public/js/airtime/library/library.js b/airtime_mvc/public/js/airtime/library/library.js
index 7f5471bfa..dae2d916e 100644
--- a/airtime_mvc/public/js/airtime/library/library.js
+++ b/airtime_mvc/public/js/airtime/library/library.js
@@ -109,7 +109,7 @@ var AIRTIME = (function(AIRTIME) {
mod.changeAddButtonText = function($button, btnText) {
$button.text(btnText);
- }
+ };
mod.createToolbarButtons = function() {
$menu = $("");
@@ -135,7 +135,7 @@ var AIRTIME = (function(AIRTIME) {
"" +
"" +
"");
- }
+ };
mod.createToolbarDropDown = function() {
$('#sb-select-page').click(function(){mod.selectCurrentPage();});
@@ -530,12 +530,14 @@ var AIRTIME = (function(AIRTIME) {
},
"fnStateSave": function (oSettings, oData) {
localStorage.setItem('datatables-library', JSON.stringify(oData));
+ /*
$.ajax({
url: baseUrl+"usersettings/set-library-datatable",
type: "POST",
data: {settings : oData, format: "json"},
dataType: "json"
});
+ */
colReorderMap = oData.ColReorder;
},
@@ -890,7 +892,6 @@ var AIRTIME = (function(AIRTIME) {
}
});
- checkImportStatus();
checkLibrarySCUploadStatus();
addQtipToSCIcons();
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 01b1096d5..0a3ae1b3b 100644
--- a/airtime_mvc/public/js/airtime/schedule/full-calendar-functions.js
+++ b/airtime_mvc/public/js/airtime/schedule/full-calendar-functions.js
@@ -360,13 +360,7 @@ function windowResize() {
}
function preloadEventFeed () {
- var url = baseUrl+'Schedule/event-feed-preload';
- var d = new Date();
-
- $.post(url, {format: "json", cachep: d.getTime()}, function(json){
- calendarEvents = json.events;
- createFullCalendar({calendarInit: calendarPref});
- });
+ createFullCalendar({calendarInit: calendarPref});
}
var initialLoad = true;
diff --git a/airtime_mvc/public/js/airtime/schedule/schedule.js b/airtime_mvc/public/js/airtime/schedule/schedule.js
index d734853ea..bf2937bcd 100644
--- a/airtime_mvc/public/js/airtime/schedule/schedule.js
+++ b/airtime_mvc/public/js/airtime/schedule/schedule.js
@@ -312,7 +312,7 @@ function createFullCalendar(data){
],
contentHeight: mainHeight,
theme: true,
- lazyFetching: false,
+ lazyFetching: true,
serverTimestamp: parseInt(data.calendarInit.timestamp, 10),
serverTimezoneOffset: parseInt(data.calendarInit.timezoneOffset, 10),
diff --git a/airtime_mvc/public/js/airtime/showbuilder/builder.js b/airtime_mvc/public/js/airtime/showbuilder/builder.js
index 3eee4d92f..8a57b4bd2 100644
--- a/airtime_mvc/public/js/airtime/showbuilder/builder.js
+++ b/airtime_mvc/public/js/airtime/showbuilder/builder.js
@@ -278,7 +278,8 @@ var AIRTIME = (function(AIRTIME){
oSchedTable.fnDraw();
mod.enableUI();
- $("#library_content").find("#library_display").dataTable().fnStandingRedraw();
+ //Unneccessary reload of the library pane after moving tracks in the showbuilder pane.
+ //$("#library_content").find("#library_display").dataTable().fnStandingRedraw();
};
mod.getSelectedCursors = function() {
@@ -398,13 +399,20 @@ var AIRTIME = (function(AIRTIME){
$scroll.scrollTop(currentTop - scrollingTop + scrolled);
}
-
+
mod.builderDataTable = function() {
$sbContent = $('#show_builder');
$lib = $("#library_content"),
$sbTable = $sbContent.find('table');
var isInitialized = false;
+ var emptyNode = document.createElement('div');
+ var lockedPreviewIcon = document.createElement('span');
+ lockedPreviewIcon.setAttribute('class', 'ui-icon ui-icon-locked');
+ var previewIcon = document.createElement('img');
+ previewIcon.setAttribute('src', baseUrl+'css/images/icon_audioclip.png');
+ previewIcon.setAttribute('title', $.i18n._("Track preview"));
+
oSchedTable = $sbTable.dataTable( {
"aoColumns": [
/* checkbox */ {"mDataProp": "allowed", "sTitle": "", "sWidth": "15px", "sClass": "sb-checkbox"},
@@ -429,6 +437,7 @@ var AIRTIME = (function(AIRTIME){
"bServerSide": true,
"bInfo": false,
"bAutoWidth": false,
+ "bDeferRender": true,
"bStateSave": true,
"fnStateSaveParams": function (oSettings, oData) {
@@ -439,13 +448,14 @@ var AIRTIME = (function(AIRTIME){
"fnStateSave": function fnStateSave(oSettings, oData) {
localStorage.setItem('datatables-timeline', JSON.stringify(oData));
-
+
+ /*
$.ajax({
url: baseUrl+"usersettings/set-timeline-datatable",
type: "POST",
data: {settings : oData, format: "json"},
dataType: "json"
- });
+ });*/
},
"fnStateLoad": function fnBuilderStateLoad(oSettings) {
var settings = localStorage.getItem('datatables-timeline');
@@ -466,7 +476,8 @@ var AIRTIME = (function(AIRTIME){
a[i] = (a[i] === "true") ? true : false;
}
}
-
+
+ /*
a = oData.ColReorder;
if (a) {
for (i = 0, length = a.length; i < length; i++) {
@@ -474,7 +485,7 @@ var AIRTIME = (function(AIRTIME){
a[i] = parseInt(a[i], 10);
}
}
- }
+ }*/
oData.iCreate = parseInt(oData.iCreate, 10);
},
@@ -494,8 +505,13 @@ var AIRTIME = (function(AIRTIME){
headerIcon;
fnPrepareSeparatorRow = function fnPrepareSeparatorRow(sRowContent, sClass, iNodeIndex) {
+ //Albert:
+ //$(nRow.children[iNodeIndex]).replaceWith(emptyNode);
+
+
$node = $(nRow.children[iNodeIndex]);
$node.html(sRowContent);
+
$node.attr('colspan',100);
for (i = iNodeIndex + 1, length = nRow.children.length; i < length; i = i+1) {
$node = $(nRow.children[i]);
@@ -504,6 +520,7 @@ var AIRTIME = (function(AIRTIME){
}
$nRow.addClass(sClass);
+
};
if (aData.header === true) {
@@ -576,7 +593,9 @@ var AIRTIME = (function(AIRTIME){
$nRow.find('td').removeClass();
$node = $(nRow.children[0]);
- $node.html('');
+ if ($node) {
+ $node.empty();
+ }
sSeparatorHTML = ''+$.i18n._("Show Empty")+'';
cl = cl + " sb-empty odd";
@@ -592,24 +611,32 @@ var AIRTIME = (function(AIRTIME){
sSeparatorHTML = ''+$.i18n._("Recording From Line In")+'';
cl = cl + " sb-record odd";
-
fnPrepareSeparatorRow(sSeparatorHTML, cl, 1);
}
else {
//add the play function if the file exists on disk.
$image = $nRow.find('td.sb-image');
+ $image.empty();
//check if the file exists.
if (aData.image === true) {
$nRow.addClass("lib-audio");
if (!isAudioSupported(aData.mime)) {
- $image.html('');
+ //$image.html('');
+ $image.append(lockedPreviewIcon);
} else {
+ /*
$image.html('')
.click(function() {
open_show_preview(aData.instance, aData.pos);
return false;
+ });*/
+ $image.append(previewIcon.cloneNode(false));
+ $image.click(function() {
+ open_show_preview(aData.instance, aData.pos);
+ return false;
});
+
}
}
else {
@@ -625,13 +652,13 @@ var AIRTIME = (function(AIRTIME){
hide: 'mouseout'
});
}
-
+
$node = $(nRow.children[0]);
if (aData.allowed === true && aData.scheduled >= 1 && aData.linked_allowed) {
$node.html('');
}
else {
- $node.html('');
+ $node.empty();
}
}
@@ -705,7 +732,6 @@ var AIRTIME = (function(AIRTIME){
$("#draggingContainer").remove();
},
"fnDrawCallback": function fnBuilderDrawCallback(oSettings, json) {
- var isInitialized = false;
if (!isInitialized) {
//when coming to 'Now Playing' page we want the page
@@ -730,7 +756,8 @@ var AIRTIME = (function(AIRTIME){
heights = [];
clearTimeout(mod.timeout);
-
+
+ /*
//only create the cursor arrows if the library is on the page.
if ($lib.length > 0 && $lib.filter(":visible").length > 0) {
@@ -775,18 +802,18 @@ var AIRTIME = (function(AIRTIME){
$tr = $table.find("tr[id="+cursorIds[i]+"][si_id="+showInstanceIds[i]+"]");
}
- /* If the currently playing track's cursor is selected,
- * and that track is deleted, the cursor position becomes
- * unavailble. We have to check the position is available
- * before re-highlighting it.
- */
+ //If the currently playing track's cursor is selected,
+ //and that track is deleted, the cursor position becomes
+ //unavailble. We have to check the position is available
+ // before re-highlighting it.
+ //
if ($tr.find(".sb-checkbox").children().hasClass("innerWrapper")) {
mod.selectCursor($tr);
- /* If the selected cursor is the footer row we need to
- * explicitly select it because that row does not have
- * innerWrapper class
- */
+ // If the selected cursor is the footer row we need to
+ //explicitly select it because that row does not have
+ // innerWrapper class
+ //
} else if ($tr.hasClass("sb-footer")) {
mod.selectCursor($tr);
}
@@ -801,8 +828,9 @@ var AIRTIME = (function(AIRTIME){
}
$parent.append($table);
+
}
-
+ */
//order of importance of elements for setting the next timeout.
elements = [
$sbTable.find("tr."+NOW_PLAYING_CLASS),
@@ -826,6 +854,7 @@ var AIRTIME = (function(AIRTIME){
break;
}
}
+
mod.checkToolBarIcons();
},
@@ -957,9 +986,9 @@ var AIRTIME = (function(AIRTIME){
//item was reordered.
else {
- ui.item
- .empty()
- .after(draggingContainer.html());
+ //ui.item
+ // .empty()
+ // .after(draggingContainer.html());
aItemData.push(ui.item.data("aData"));
fnMove();
@@ -968,9 +997,10 @@ var AIRTIME = (function(AIRTIME){
return {
placeholder: "sb-placeholder ui-state-highlight",
- forcePlaceholderSize: true,
+ //forcePlaceholderSize: true,
distance: 10,
- helper: function(event, item) {
+ helper:
+ function(event, item) {
var selected = mod.getSelectedData(NOW_PLAYING_CLASS),
thead = $("#show_builder_table thead"),
colspan = thead.find("th").length,
@@ -985,23 +1015,34 @@ var AIRTIME = (function(AIRTIME){
}
if (selected.length === 1) {
- message = $.i18n._("Moving 1 Item");
- }
- else {
- message = sprintf($.i18n._("Moving %s Items"), selected.length);
- }
-
- draggingContainer = $('