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); ?> + + + + +