diff --git a/.zfproject.xml b/.zfproject.xml index bc8f59d24..17468e3fa 100644 --- a/.zfproject.xml +++ b/.zfproject.xml @@ -80,6 +80,7 @@ + @@ -258,6 +259,9 @@ + + + diff --git a/application/controllers/NowplayingController.php b/application/controllers/NowplayingController.php index d9f323335..d44091a35 100644 --- a/application/controllers/NowplayingController.php +++ b/application/controllers/NowplayingController.php @@ -5,24 +5,26 @@ class NowplayingController extends Zend_Controller_Action public function init() { - $ajaxContext = $this->_helper->getHelper('AjaxContext'); - $ajaxContext->addActionContext('get-data-grid-data', 'json')->initContext(); + $ajaxContext = $this->_helper->getHelper('AjaxContext'); + $ajaxContext->addActionContext('get-data-grid-data', 'json')->initContext(); } public function indexAction() { - $this->view->headScript()->appendFile('/js/datatables/js/jquery.dataTables.min.js','text/javascript'); - - - $this->view->headLink()->appendStylesheet('/css/datatables/css/demo_page.css'); - $this->view->headLink()->appendStylesheet('/css/datatables/css/demo_table.css'); - - //$this->_helper->viewRenderer->setResponseSegment('nowplaying'); + $this->view->headScript()->appendFile('/js/datatables/js/jquery.dataTables.min.js','text/javascript'); + $this->view->headLink()->appendStylesheet('/css/datatables/css/demo_page.css'); + $this->view->headLink()->appendStylesheet('/css/datatables/css/demo_table.css'); } public function getDataGridDataAction() { - $this->view->entries = Application_Model_Nowplaying::GetDataGridData(); + $this->view->entries = Application_Model_Nowplaying::GetDataGridData(); + } + + public function livestreamAction() + { + //use bare bones layout (no header bar or menu) + $this->_helper->layout->setLayout('bare'); } @@ -32,3 +34,5 @@ class NowplayingController extends Zend_Controller_Action + + diff --git a/application/layouts/scripts/bare.phtml b/application/layouts/scripts/bare.phtml new file mode 100644 index 000000000..068987e71 --- /dev/null +++ b/application/layouts/scripts/bare.phtml @@ -0,0 +1,11 @@ + +doctype() ?> + + + + Livestream + + +
layout()->content ?>
+ + diff --git a/application/models/Schedule.php b/application/models/Schedule.php index 76adbaa73..5c76d3dc4 100644 --- a/application/models/Schedule.php +++ b/application/models/Schedule.php @@ -481,11 +481,12 @@ class Schedule { global $CC_CONFIG, $CC_DBC; $sql = "SELECT pt.name, ft.track_title, ft.artist_name, ft.album_title, st.starts, st.ends, st.clip_length, sdt.start_time, sdt.end_time" ." FROM $CC_CONFIG[scheduleTable] st, $CC_CONFIG[filesTable] ft, $CC_CONFIG[playListTable] pt, $CC_CONFIG[showSchedule] sst, $CC_CONFIG[showDays] sdt" - ." WHERE (st.ends < TIMESTAMP '$timeNow')" - ." AND (st.playlist_id = pt.id)" - ." AND (st.file_id = ft.id)" - ." AND (st.group_id = sst.group_id)" - ." AND (sdt.show_id = sst.show_id)" + ." WHERE st.ends < TIMESTAMP '$timeNow'" + ." AND st.ends > (TIMESTAMP '$timeNow' - INTERVAL '1 days')" + ." AND st.playlist_id = pt.id" + ." AND st.file_id = ft.id" + ." AND st.group_id = sst.group_id" + ." AND sdt.show_id = sst.show_id" ." ORDER BY st.starts DESC" ." LIMIT $prevCount"; $rows = $CC_DBC->GetAll($sql); @@ -498,12 +499,12 @@ class Schedule { $sql = "SELECT pt.name, ft.track_title, ft.artist_name, ft.album_title, st.starts, st.ends, st.clip_length, sdt.start_time, sdt.end_time" ." FROM $CC_CONFIG[scheduleTable] st," ."$CC_CONFIG[filesTable] ft, $CC_CONFIG[playListTable] pt, $CC_CONFIG[showSchedule] sst, $CC_CONFIG[showDays] sdt" - ." WHERE (st.starts < TIMESTAMP '$timeNow')" - ." AND (st.ends > TIMESTAMP '$timeNow')" - ." AND (st.playlist_id = pt.id)" - ." AND (st.file_id = ft.id)" - ." AND (st.group_id = sst.group_id)" - ." AND (sdt.show_id = sst.show_id)"; + ." WHERE st.starts < TIMESTAMP '$timeNow'" + ." AND st.ends > TIMESTAMP '$timeNow'" + ." AND st.playlist_id = pt.id" + ." AND st.file_id = ft.id" + ." AND st.group_id = sst.group_id" + ." AND sdt.show_id = sst.show_id"; $rows = $CC_DBC->GetAll($sql); return $rows; } @@ -512,11 +513,12 @@ class Schedule { global $CC_CONFIG, $CC_DBC; $sql = "SELECT pt.name, ft.track_title, ft.artist_name, ft.album_title, st.starts, st.ends, st.clip_length, sdt.start_time, sdt.end_time" ." FROM $CC_CONFIG[scheduleTable] st, $CC_CONFIG[filesTable] ft, $CC_CONFIG[playListTable] pt, $CC_CONFIG[showSchedule] sst, $CC_CONFIG[showDays] sdt" - ." WHERE (st.starts > TIMESTAMP '$timeNow')" - ." AND (st.playlist_id = pt.id)" - ." AND (st.file_id = ft.id)" - ." AND (st.group_id = sst.group_id)" - ." AND (sdt.show_id = sst.show_id)" + ." WHERE st.starts > TIMESTAMP '$timeNow'" + ." AND st.ends < (TIMESTAMP '$timeNow' + INTERVAL '24 hours')" + ." AND st.playlist_id = pt.id" + ." AND st.file_id = ft.id" + ." AND st.group_id = sst.group_id" + ." AND sdt.show_id = sst.show_id" ." ORDER BY st.starts" ." LIMIT $nextCount"; $rows = $CC_DBC->GetAll($sql); diff --git a/application/views/scripts/nowplaying/livestream.phtml b/application/views/scripts/nowplaying/livestream.phtml new file mode 100644 index 000000000..871cbb5e4 --- /dev/null +++ b/application/views/scripts/nowplaying/livestream.phtml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/application/views/scripts/partialviews/header.phtml b/application/views/scripts/partialviews/header.phtml index d72cd2d57..2bb4e380d 100644 --- a/application/views/scripts/partialviews/header.phtml +++ b/application/views/scripts/partialviews/header.phtml @@ -1,5 +1,5 @@
@@ -30,7 +30,7 @@ function popup(mylink){ href=mylink; else href=mylink.href; - window.open(href, "player", 'width=400,height=200,scrollbars=yes'); + window.open(href, "player", 'width=300,height=100,scrollbars=yes'); return false; } diff --git a/install/airtime-install.php b/install/airtime-install.php index 36b931454..16917259d 100644 --- a/install/airtime-install.php +++ b/install/airtime-install.php @@ -44,7 +44,7 @@ foreach($lines as $key => $line){ fclose($fp); -echo "******************************* Install Begin ********************************\n"; +echo "******************************** Install Begin *********************************\n"; echo " *** Database Installation ***\n"; @@ -225,9 +225,13 @@ install_setDirPermissions($CC_CONFIG["storageDir"]); echo " * Importing sample audio clips \n"; $command = __DIR__."/../utils/airtime-import --copy ../audio_samples/ > /dev/null"; @exec($command, $output, $results); -echo "****************************** Database Install Complete ******************************\n"; $command = "python ".__DIR__."/../pypo/install/pypo-install.py"; + +$output = array(); @exec($command, $output, $results); -//print_r($output); +foreach ($output as $value){ + echo $value."\n"; +} +echo "******************************* Install Complete *******************************\n"; ?> diff --git a/install/airtime-uninstall.php b/install/airtime-uninstall.php index d343365e3..c50b724cb 100644 --- a/install/airtime-uninstall.php +++ b/install/airtime-uninstall.php @@ -21,9 +21,7 @@ if(exec("whoami") != "root"){ } -echo "***************************\n"; -echo "* StorageServer Uninstall *\n"; -echo "***************************\n"; +echo "******************************* Uninstall Begin ********************************\n"; require_once(dirname(__FILE__).'/../application/configs/conf.php'); require_once(dirname(__FILE__).'/installInit.php'); @@ -226,11 +224,11 @@ if ($results == 0) { airtime_uninstall_delete_files($CC_CONFIG['storageDir']); -echo "************************************\n"; -echo "* StorageServer Uninstall Complete *\n"; -echo "************************************\n"; - $command = "python ".__DIR__."/../pypo/install/pypo-uninstall.py"; +$output = array(); @exec($command, $output, $results); -//print_r($output); +foreach ($output as $value){ + echo $value."\n"; +} +echo "****************************** Uninstall Complete ******************************\n"; ?> diff --git a/public/js/playlist/playlist.js b/public/js/playlist/playlist.js index ae275ce99..77af88797 100644 --- a/public/js/playlist/playlist.js +++ b/public/js/playlist/playlist.js @@ -1,7 +1,6 @@ var estimatedSchedulePosixTime = -1; -var schedulePosixTime; -var currentRemoteTimeOffset; +var localRemoteTimeOffset; var previousSongs = new Array(); var currentSong = new Array(); @@ -9,15 +8,33 @@ var nextSongs = new Array(); var currentElem; -var updateInterval = 5000; +var serverUpdateInterval = 5000; +var uiUpdateInterval = 200; var songEndFunc; +var showStartPosixTime = 0; +var showEndPosixTime = 0; +var showLengthMs = 1; + +/* boolean flag to let us know if we should prepare to execute a function + * that flips the playlist to the next song. This flags purpose is to + * make sure the function is only executed once*/ +var nextSongPrepare = true; + +/* Another script can register its function here + * when it wishes to know when a song ends. */ function registerSongEndListener(func){ songEndFunc = func; } +function notifySongEndListener(){ + if (typeof songEndFunc == "function") + songEndFunc(); +} +/* Takes an input parameter of milliseconds and converts these into + * the format HH:MM:SS */ function convertToHHMMSS(timeInMS){ var time = parseInt(timeInMS); @@ -72,58 +89,64 @@ function getTrackInfo(song){ function secondsTimer(){ var date = new Date(); - estimatedSchedulePosixTime = date.getTime() - currentRemoteTimeOffset; + estimatedSchedulePosixTime = date.getTime() - localRemoteTimeOffset; updateProgressBarValue(); } -/* Called every 0.2 seconds. */ +function updateGlobalValues(obj){ + showStartPosixTime = obj.showStartPosixTime; + showEndPosixTime = obj.showEndPosixTime; + showLengthMs = showEndPosixTime - showStartPosixTime; +} + +function newSongStart(){ + nextSongPrepare = true; + currentSong[0] = nextSongs.shift(); + updateGlobalValues(currentSong[0]); + updatePlaybar(); + + notifySongEndListener(); +} + +/* Called every "uiUpdateInterval" mseconds. */ function updateProgressBarValue(){ if (estimatedSchedulePosixTime != -1){ + if (showStartPosixTime != 0){ + var showPercentDone = (estimatedSchedulePosixTime - showStartPosixTime)/showLengthMs*100; + if (showPercentDone < 0 || showPercentDone > 100){ + showPercentDone = 0; + } + $('#showprogressbar').progressBar(showPercentDone); + } + + var songPercentDone = 0; if (currentSong.length > 0){ - var percentDone = (estimatedSchedulePosixTime - currentSong[0].songStartPosixTime)/currentSong[0].songLengthMs*100; - if (percentDone <= 100){ - $('#progressbar').progressBar(percentDone); - } else { - if (nextSongs.length > 0){ - currentSong[0] = nextSongs.shift(); - } else { - currentSong = new Array(); - } - $('#progressbar').progressBar(0); - } - - - percentDone = (estimatedSchedulePosixTime - currentSong[0].showStartPosixTime)/currentSong[0].showLengthMs*100; - //$('#showprogressbar').text(currentSong[0].showLengthMs); - $('#showprogressbar').progressBar(percentDone); - } else { - $('#progressbar').progressBar(0); - - //calculate how much time left to next song if there is any - if (nextSongs.length > 0){ - if (nextSongs[0].songStartPosixTime - estimatedSchedulePosixTime < updateInterval){ - setTimeout(temp, nextSongs[0].songStartPosixTime - estimatedSchedulePosixTime); - } + songPercentDone = (estimatedSchedulePosixTime - currentSong[0].songStartPosixTime)/currentSong[0].songLengthMs*100; + if (songPercentDone < 0 || songPercentDone > 100){ + songPercentDone = 0; + currentSong = new Array(); } } - updatePlaylist(); + $('#progressbar').progressBar(songPercentDone); + + //calculate how much time left to next song if there is any + if (nextSongs.length > 0 && nextSongPrepare){ + if (nextSongs[0].songStartPosixTime - estimatedSchedulePosixTime < serverUpdateInterval){ + nextSongPrepare = false; + setTimeout(newSongStart, nextSongs[0].songStartPosixTime - estimatedSchedulePosixTime); + } + } + + updatePlaybar(); } - setTimeout(secondsTimer, 200); + setTimeout(secondsTimer, uiUpdateInterval); } -function temp(){ - currentSong[0] = nextSongs[0]; - updatePlaylist(); - - songEndFunc(); -} - -function updatePlaylist(){ +function updatePlaybar(){ /* Column 0 update */ - $('#listen'); - /* Column 1 update */ + $('#playlist').empty(); for (var i=0; i currentItem[i].end_time){ + //start_time is greater than end_time, so we rolled through midnight. + currentItem[i].showEndPosixTime += (1000*3600*24); //add 24 hours + } + + currentItem[i].showLengthMs = currentItem[i].showEndPosixTime - currentItem[i].showStartPosixTime; + + if (bUpdateGlobalValues){ + updateGlobalValues(currentItem[i]); + } } } function parseItems(obj){ - schedulePosixTime = convertDateToPosixTime(obj.schedulerTime); - - if (estimatedSchedulePosixTime == -1){ - var date = new Date(); - currentRemoteTimeOffset = date.getTime() - schedulePosixTime; - estimatedSchedulePosixTime = schedulePosixTime; - } + var schedulePosixTime = convertDateToPosixTime(obj.schedulerTime); previousSongs = obj.previous; currentSong = obj.current; nextSongs = obj.next; - calcAdditionalData(previousSongs); - calcAdditionalData(currentSong); - calcAdditionalData(nextSongs); + calcAdditionalData(previousSongs, false); + calcAdditionalData(currentSong, true); + calcAdditionalData(nextSongs, false); + + if (estimatedSchedulePosixTime == -1){ + var date = new Date(); + localRemoteTimeOffset = date.getTime() - schedulePosixTime; + estimatedSchedulePosixTime = schedulePosixTime; + } } function getScheduleFromServer(){ $.ajax({ url: "/Schedule/get-current-playlist/format/json", dataType:"json", success:function(data){ parseItems(data.entries); }}); - setTimeout(getScheduleFromServer, updateInterval); + setTimeout(getScheduleFromServer, serverUpdateInterval); } function init(elemID) { @@ -196,7 +246,10 @@ function init(elemID) { $('#progressbar').progressBar(0, {showText : false}); $('#showprogressbar').progressBar(0, {showText : false, barImage:'/js/progressbar/images/progressbg_red.gif'}); + //begin producer "thread" getScheduleFromServer(); + + //begin consumer "thread" updateProgressBarValue(); } diff --git a/pypo/install/pypo-install.py b/pypo/install/pypo-install.py index 4ff42d247..e82c2d314 100644 --- a/pypo/install/pypo-install.py +++ b/pypo/install/pypo-install.py @@ -150,9 +150,7 @@ try: print output if not found: - print "Install has completed, but daemontools is not running, please make sure you have it installed and then reboot." - else: - print "Install complete." + print "Pypo install has completed, but daemontools is not running, please make sure you have it installed and then reboot." except Exception, e: print "exception:" + str(e) diff --git a/pypo/scripts/ls_script.liq b/pypo/scripts/ls_script.liq index c246a0232..c28d235e5 100644 --- a/pypo/scripts/ls_script.liq +++ b/pypo/scripts/ls_script.liq @@ -42,6 +42,13 @@ def notify(m) print("./notify.sh --data='#{!pypo_data}' --media-id=#{m['media_id']}") end +def crossfade(s) + s = fade.in(type="log", s) + s = fade.out(type="log", s) + fader = fun (a,b) -> add(normalize=false,[b,a]) + cross(fader,s) +end + server.register(namespace="scheduler","push", scheduler_push) server.register(namespace="scheduler","flip", fun (s) -> begin scheduler_flip() end) server.register(namespace="vars", "pypo_data", fun (s) -> begin pypo_data := s "Done" end) @@ -51,6 +58,8 @@ radio = fallback(track_sensitive=false, [switch(track_sensitive=false, [(fun () #radio = on_metadata(notify, radio) +radio = crossfade(radio) + #out(radio) clock(id="clock_icecast", output.icecast(%mp3, diff --git a/pypo/test/airtime-schedule-insert.php b/pypo/test/airtime-schedule-insert.php index 1a5ce3e93..8861f1d55 100644 --- a/pypo/test/airtime-schedule-insert.php +++ b/pypo/test/airtime-schedule-insert.php @@ -42,19 +42,6 @@ $pl = new Playlist(); $pl->create($playlistName); -// Add a media clip -$mediaFile = StoredFile::findByOriginalName("ACDC_-_Back_In_Black-sample.ogg"); -if (is_null($mediaFile)) { - echo "Adding test audio clip to the database.\n"; - $v = array("filepath" => __DIR__."/../../audio_samples/OpSound/ACDC_-_Back_In_Black-sample.ogg"); - $mediaFile = StoredFile::Insert($v); - if (PEAR::isError($mediaFile)) { - var_dump($mediaFile); - exit(); - } -} -$pl->addAudioClip($mediaFile->getId()); - $mediaFile = StoredFile::findByOriginalName("Peter_Rudenko_-_Opening.mp3"); if (is_null($mediaFile)) { echo "Adding test audio clip to the database.\n";