Merge branch 'devel' of dev.sourcefabric.org:airtime into devel

This commit is contained in:
Rudi Grinberg 2012-09-10 14:15:07 -04:00
commit b085f9ef67
21 changed files with 225 additions and 142 deletions

View File

@ -336,7 +336,7 @@ class ApiController extends Zend_Controller_Action
$this->view->layout()->disableLayout(); $this->view->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true); $this->_helper->viewRenderer->setNoRender(true);
$data = Application_Model_Schedule::GetScheduledPlaylists(); $data = Application_Model_Schedule::getSchedule();
echo json_encode($data, JSON_FORCE_OBJECT); echo json_encode($data, JSON_FORCE_OBJECT);
} }

View File

@ -274,7 +274,7 @@ class ShowbuilderController extends Zend_Controller_Action
$opts = array("myShows" => $my_shows, "showFilter" => $show_filter); $opts = array("myShows" => $my_shows, "showFilter" => $show_filter);
$showBuilder = new Application_Model_ShowBuilder($startsDT, $endsDT, $opts); $showBuilder = new Application_Model_ShowBuilder($startsDT, $endsDT, $opts);
$data = $showBuilder->GetItems(); $data = $showBuilder->getItems();
$this->view->schedule = $data["schedule"]; $this->view->schedule = $data["schedule"];
$this->view->instances = $data["showInstances"]; $this->view->instances = $data["showInstances"];
$this->view->timestamp = $current_time; $this->view->timestamp = $current_time;

View File

@ -5,7 +5,7 @@ class RabbitMqPlugin extends Zend_Controller_Plugin_Abstract
public function dispatchLoopShutdown() public function dispatchLoopShutdown()
{ {
if (Application_Model_RabbitMq::$doPush) { if (Application_Model_RabbitMq::$doPush) {
$md = array('schedule' => Application_Model_Schedule::GetScheduledPlaylists()); $md = array('schedule' => Application_Model_Schedule::getSchedule());
Application_Model_RabbitMq::SendMessageToPypo("update_schedule", $md); Application_Model_RabbitMq::SendMessageToPypo("update_schedule", $md);
if (!isset($_SERVER['AIRTIME_SRV'])) { if (!isset($_SERVER['AIRTIME_SRV'])) {
Application_Model_RabbitMq::SendMessageToShowRecorder("update_recorder_schedule"); Application_Model_RabbitMq::SendMessageToShowRecorder("update_recorder_schedule");

View File

@ -132,7 +132,6 @@ class Application_Model_Preference
public static function GetHeadTitle() public static function GetHeadTitle()
{ {
$title = self::getValue("station_name"); $title = self::getValue("station_name");
$defaultNamespace->title = $title;
if (strlen($title) > 0) if (strlen($title) > 0)
$title .= " - "; $title .= " - ";

View File

@ -511,7 +511,7 @@ SQL;
* Returns null if nothing found, else an array of associative * Returns null if nothing found, else an array of associative
* arrays representing each row. * arrays representing each row.
*/ */
public static function GetItems($p_startTime, $p_endTime) public static function getItems($p_startTime, $p_endTime)
{ {
global $CC_CONFIG; global $CC_CONFIG;
@ -570,7 +570,127 @@ SQL;
return $rows; return $rows;
} }
public static function GetScheduledPlaylists($p_fromDateTime = null, $p_toDateTime = null) private static function createInputHarborKickTimes(&$data, $range_start, $range_end)
{
$utcTimeZone = new DateTimeZone("UTC");
$kick_times = Application_Model_ShowInstance::GetEndTimeOfNextShowWithLiveDJ($range_start, $range_end);
foreach ($kick_times as $kick_time_info) {
$kick_time = $kick_time_info['ends'];
$temp = explode('.', Application_Model_Preference::GetDefaultTransitionFade());
// we round down transition time since PHP cannot handle millisecond. We need to
// handle this better in the future
$transition_time = intval($temp[0]);
$switchOffDataTime = new DateTime($kick_time, $utcTimeZone);
$switch_off_time = $switchOffDataTime->sub(new DateInterval('PT'.$transition_time.'S'));
$switch_off_time = $switch_off_time->format("Y-m-d H:i:s");
$kick_start = self::AirtimeTimeToPypoTime($kick_time);
$data["media"][$kick_start]['start'] = $kick_start;
$data["media"][$kick_start]['end'] = $kick_start;
$data["media"][$kick_start]['event_type'] = "kick_out";
$data["media"][$kick_start]['type'] = "event";
$data["media"][$kick_start]['independent_event'] = true;
if ($kick_time !== $switch_off_time) {
$switch_start = self::AirtimeTimeToPypoTime($switch_off_time);
$data["media"][$switch_start]['start'] = $switch_start;
$data["media"][$switch_start]['end'] = $switch_start;
$data["media"][$switch_start]['event_type'] = "switch_off";
$data["media"][$switch_start]['independent_event'] = true;
}
}
}
private static function createFileScheduleEvent(&$data, $item, $media_id)
{
$start = self::AirtimeTimeToPypoTime($item["start"]);
$end = self::AirtimeTimeToPypoTime($item["end"]);
$schedule_item = array(
'id' => $media_id,
'type' => 'file',
'row_id' => $item["id"],
'uri' => $uri,
'fade_in' => Application_Model_Schedule::WallTimeToMillisecs($item["fade_in"]),
'fade_out' => Application_Model_Schedule::WallTimeToMillisecs($item["fade_out"]),
'cue_in' => Application_Common_DateHelper::CalculateLengthInSeconds($item["cue_in"]),
'cue_out' => Application_Common_DateHelper::CalculateLengthInSeconds($item["cue_out"]),
'start' => $start,
'end' => $end,
'show_name' => $showName,
'replay_gain' => is_null($item["replay_gain"]) ? "0": $item["replay_gain"],
'independent_event' => true
);
$data["media"][$start] = $schedule_item;
}
private static function createStreamScheduleEvent(&$data, $item, $media_id)
{
$start = self::AirtimeTimeToPypoTime($item["start"]);
$end = self::AirtimeTimeToPypoTime($item["end"]);
//create an event to start stream buffering 5 seconds ahead of the streams actual time.
$buffer_start = new DateTime($item["start"], new DateTimeZone('UTC'));
$buffer_start->sub(new DateInterval("PT5S"));
$stream_buffer_start = self::AirtimeTimeToPypoTime($buffer_start->format("Y-m-d H:i:s"));
$schedule_item = array(
'start' => $stream_buffer_start,
'end' => $stream_buffer_start,
'uri' => $uri,
'row_id' => $item["id"],
'type' => 'stream_buffer_start',
'independent_event' => true
);
//TODO: Make sure no other media is being overwritten!
$data["media"][$stream_buffer_start] = $schedule_item;
$schedule_item = array(
'id' => $media_id,
'type' => 'stream_output_start',
'row_id' => $item["id"],
'uri' => $uri,
'start' => $start,
'end' => $end,
'show_name' => $showName,
'independent_event' => true
);
$data["media"][$start] = $schedule_item;
//since a stream never ends we have to insert an additional "kick stream" event. The "start"
//time of this event is the "end" time of the stream minus 1 second.
$dt = new DateTime($item["end"], new DateTimeZone('UTC'));
$dt->sub(new DateInterval("PT1S"));
//make sure the webstream doesn't play past the end time of the show
if ($dt->getTimestamp() > $showEndDateTime->getTimestamp()) {
$dt = $showEndDateTime;
}
$stream_end = self::AirtimeTimeToPypoTime($dt->format("Y-m-d H:i:s"));
$schedule_item = array(
'start' => $stream_end,
'end' => $stream_end,
'uri' => $uri,
'type' => 'stream_buffer_end',
'independent_event' => true
);
$data["media"][$stream_end] = $schedule_item;
$schedule_item = array(
'start' => $stream_end,
'end' => $stream_end,
'uri' => $uri,
'type' => 'stream_output_end',
'independent_event' => true
);
$data["media"][$stream_end] = $schedule_item;
}
private static function getRangeStartAndEnd($p_fromDateTime, $p_toDateTime)
{ {
global $CC_CONFIG; global $CC_CONFIG;
@ -600,8 +720,13 @@ SQL;
$range_end = Application_Model_Schedule::PypoTimeToAirtimeTime($p_toDateTime); $range_end = Application_Model_Schedule::PypoTimeToAirtimeTime($p_toDateTime);
} }
// Scheduler wants everything in a playlist return array($range_start, $range_end);
$items = self::GetItems($range_start, $range_end); }
public static function getSchedule($p_fromDateTime = null, $p_toDateTime = null)
{
list($range_start, $range_end) = self::getRangeStartAndEnd($p_fromDateTime, $p_toDateTime);
$data = array(); $data = array();
$utcTimeZone = new DateTimeZone("UTC"); $utcTimeZone = new DateTimeZone("UTC");
@ -609,33 +734,9 @@ SQL;
$data["status"] = array(); $data["status"] = array();
$data["media"] = array(); $data["media"] = array();
$kick_times = Application_Model_ShowInstance::GetEndTimeOfNextShowWithLiveDJ($range_start, $range_end); self::createInputHarborKickTimes($data, $range_start, $range_end);
foreach ($kick_times as $kick_time_info) {
$kick_time = $kick_time_info['ends'];
$temp = explode('.', Application_Model_Preference::GetDefaultTransitionFade());
// we round down transition time since PHP cannot handle millisecond. We need to
// handle this better in the future
$transition_time = intval($temp[0]);
$switchOffDataTime = new DateTime($kick_time, $utcTimeZone);
$switch_off_time = $switchOffDataTime->sub(new DateInterval('PT'.$transition_time.'S'));
$switch_off_time = $switch_off_time->format("Y-m-d H:i:s");
$kick_start = Application_Model_Schedule::AirtimeTimeToPypoTime($kick_time);
$data["media"][$kick_start]['start'] = $kick_start;
$data["media"][$kick_start]['end'] = $kick_start;
$data["media"][$kick_start]['event_type'] = "kick_out";
$data["media"][$kick_start]['type'] = "event";
$data["media"][$kick_start]['independent_event'] = true;
if ($kick_time !== $switch_off_time) {
$switch_start = Application_Model_Schedule::AirtimeTimeToPypoTime($switch_off_time);
$data["media"][$switch_start]['start'] = $switch_start;
$data["media"][$switch_start]['end'] = $switch_start;
$data["media"][$switch_start]['event_type'] = "switch_off";
$data["media"][$switch_start]['independent_event'] = true;
}
}
$items = self::getItems($range_start, $range_end);
foreach ($items as $item) { foreach ($items as $item) {
$showInstance = CcShowInstancesQuery::create()->findPK($item["instance_id"]); $showInstance = CcShowInstancesQuery::create()->findPK($item["instance_id"]);
@ -648,11 +749,10 @@ SQL;
$trackEndDateTime = new DateTime($item["end"], $utcTimeZone); $trackEndDateTime = new DateTime($item["end"], $utcTimeZone);
if ($trackStartDateTime->getTimestamp() > $showEndDateTime->getTimestamp()) { if ($trackStartDateTime->getTimestamp() > $showEndDateTime->getTimestamp()) {
//do not send any tracks that start past their show's end time
continue; continue;
} }
/* Note: cue_out and end are always the same. */
/* TODO: Not all tracks will have "show_end" */
if ($trackEndDateTime->getTimestamp() > $showEndDateTime->getTimestamp()) { if ($trackEndDateTime->getTimestamp() > $showEndDateTime->getTimestamp()) {
$di = $trackStartDateTime->diff($showEndDateTime); $di = $trackStartDateTime->diff($showEndDateTime);
@ -665,78 +765,37 @@ SQL;
$media_id = $item['file_id']; $media_id = $item['file_id'];
$storedFile = Application_Model_StoredFile::Recall($media_id); $storedFile = Application_Model_StoredFile::Recall($media_id);
$uri = $storedFile->getFilePath(); $uri = $storedFile->getFilePath();
$type = "file"; self::createFileScheduleEvent($data, $item, $media_id, $uri);
$independent_event = false;
} elseif (!is_null($item['stream_id'])) { } elseif (!is_null($item['stream_id'])) {
//row is type "webstream" //row is type "webstream"
$media_id = $item['stream_id']; $media_id = $item['stream_id'];
$uri = $item['url']; $uri = $item['url'];
$type = "stream"; self::createStreamScheduleEvent($data, $item, $media_id, $uri);
$independent_event = true;
}
$start = Application_Model_Schedule::AirtimeTimeToPypoTime($item["start"]);
$end = Application_Model_Schedule::AirtimeTimeToPypoTime($item["end"]);
$data["media"][$start] = array(
'id' => $media_id,
'type' => $type,
'row_id' => $item["id"],
'uri' => $uri,
'fade_in' => Application_Model_Schedule::WallTimeToMillisecs($item["fade_in"]),
'fade_out' => Application_Model_Schedule::WallTimeToMillisecs($item["fade_out"]),
'cue_in' => Application_Common_DateHelper::CalculateLengthInSeconds($item["cue_in"]),
'cue_out' => Application_Common_DateHelper::CalculateLengthInSeconds($item["cue_out"]),
'start' => $start,
'end' => $end,
'show_name' => $showName,
'replay_gain' => is_null($item["replay_gain"]) ? "0": $item["replay_gain"],
'independent_event' => $independent_event
);
if ($type == "stream") {
//create an event to start stream buffering 5 seconds ahead of the streams actual time.
$buffer_start = new DateTime($item["start"], new DateTimeZone('UTC'));
$buffer_start->sub(new DateInterval("PT5S"));
$stream_buffer_start = Application_Model_Schedule::AirtimeTimeToPypoTime($buffer_start->format("Y-m-d H:i:s"));
//TODO: Make sure no other media is being overwritten!
$data["media"][$stream_buffer_start] = array(
'start' => $stream_buffer_start,
'end' => $stream_buffer_start,
'uri' => $uri,
'row_id' => $item["id"],
'type' => 'stream_buffer_start',
'independent_event' => true
);
//since a stream never ends we have to insert an additional "kick stream" event. The "start"
//time of this event is the "end" time of the stream minus 1 second.
$dt = new DateTime($item["end"], new DateTimeZone('UTC'));
$dt->sub(new DateInterval("PT1S"));
//make sure the webstream doesn't play past the end time of the show
if ($dt->getTimestamp() > $showEndDateTime->getTimestamp()) {
$dt = $showEndDateTime;
}
$stream_end = Application_Model_Schedule::AirtimeTimeToPypoTime($dt->format("Y-m-d H:i:s"));
$data["media"][$stream_end] = array(
'start' => $stream_end,
'end' => $stream_end,
'uri' => $uri,
'type' => 'stream_end',
'independent_event' => true
);
} }
} }
return $data; return $data;
} }
/*
private static function collapseEvents($data)
{
$keys = array_keys($data);
for ($i = 0, $len = count($keys); $i < $len; $i++) {
$cur = $data[$keys[$i]];
$next = null;
if ($i+1 < $len) {
$next = $data[$keys[$i+1]];
}
if ($cur['type'] == 'stream_buffer_end' && !is_null($next) && $next['type'] == 'stream_buffer_start') {
unset($data[$keys[$i]]);
}
}
}
*/
public static function deleteAll() public static function deleteAll()
{ {
global $CC_CONFIG; global $CC_CONFIG;

View File

@ -386,7 +386,7 @@ class Application_Model_ShowBuilder
return $outdated; return $outdated;
} }
public function GetItems() public function getItems()
{ {
$current_id = -1; $current_id = -1;
$display_items = array(); $display_items = array();

View File

@ -652,7 +652,7 @@ class Application_Model_StoredFile
$displayColumns = array("id", "track_title", "artist_name", "album_title", "genre", "length", $displayColumns = array("id", "track_title", "artist_name", "album_title", "genre", "length",
"year", "utime", "mtime", "ftype", "track_number", "mood", "bpm", "composer", "info_url", "year", "utime", "mtime", "ftype", "track_number", "mood", "bpm", "composer", "info_url",
"bit_rate", "sample_rate", "isrc_number", "encoded_by", "label", "copyright", "mime", "bit_rate", "sample_rate", "isrc_number", "encoded_by", "label", "copyright", "mime",
"language", "filepath","owner","conductor" "language", "filepath", "owner", "conductor", "replay_gain"
); );
//Logging::info($datatables); //Logging::info($datatables);

View File

@ -178,10 +178,9 @@ class Application_Model_Webstream implements Application_Model_LibraryEditable
if (is_null($mime)) { if (is_null($mime)) {
throw new Exception("No MIME type found for webstream."); throw new Exception("No MIME type found for webstream.");
} }
//TODO: return url
$mediaUrl = self::getMediaUrl($url, $mime, $content_length_found); $mediaUrl = self::getMediaUrl($url, $mime, $content_length_found);
if (preg_match("/(x-mpegurl)|(xspf\+xml)/", $mime)) { if (preg_match("/(x-mpegurl)|(xspf\+xml)|(pls\+xml)/", $mime)) {
list($mime, $content_length_found) = self::discoverStreamMime($mediaUrl); list($mime, $content_length_found) = self::discoverStreamMime($mediaUrl);
} }
} catch (Exception $e) { } catch (Exception $e) {
@ -222,7 +221,7 @@ class Application_Model_Webstream implements Application_Model_LibraryEditable
} }
private static function getXspfUrl($url) private static function getUrlData($url)
{ {
$ch = curl_init(); $ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_URL, $url);
@ -233,11 +232,18 @@ class Application_Model_Webstream implements Application_Model_LibraryEditable
//TODO: What if invalid url? //TODO: What if invalid url?
$content = curl_exec($ch); $content = curl_exec($ch);
Logging::info($content); Logging::debug($content);
// close cURL resource, and free up system resources // close cURL resource, and free up system resources
curl_close($ch); curl_close($ch);
return $content;
}
private static function getXspfUrl($url)
{
$content = self::getUrlData($url);
$dom = new DOMDocument; $dom = new DOMDocument;
//TODO: What if invalid xml? //TODO: What if invalid xml?
$dom->loadXML($content); $dom->loadXML($content);
@ -253,18 +259,22 @@ class Application_Model_Webstream implements Application_Model_LibraryEditable
throw new Exception("Could not parse XSPF playlist"); throw new Exception("Could not parse XSPF playlist");
} }
private static function getPlsUrl($url)
{
$content = self::getUrlData($url);
$ini = parse_ini_string($content, true);
if ($ini !== false && isset($ini["playlist"]) && isset($ini["playlist"]["File1"])) {
return $ini["playlist"]["File1"];
}
throw new Exception("Could not parse PLS playlist");
}
private static function getM3uUrl($url) private static function getM3uUrl($url)
{ {
$ch = curl_init(); $content = self::getUrlData($url);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// grab URL and pass it to the browser
//TODO: What if invalid url?
$content = curl_exec($ch);
Logging::info($content);
curl_close($ch);
//split into lines: //split into lines:
$delim = "\n"; $delim = "\n";
@ -288,6 +298,8 @@ class Application_Model_Webstream implements Application_Model_LibraryEditable
$media_url = self::getM3uUrl($url); $media_url = self::getM3uUrl($url);
} elseif (preg_match("/xspf\+xml/", $mime)) { } elseif (preg_match("/xspf\+xml/", $mime)) {
$media_url = self::getXspfUrl($url); $media_url = self::getXspfUrl($url);
} elseif (preg_match("/pls\+xml/", $mime)) {
$media_url = self::getPlsUrl($url);
} elseif (preg_match("/(mpeg|ogg)/", $mime)) { } elseif (preg_match("/(mpeg|ogg)/", $mime)) {
if ($content_length_found) { if ($content_length_found) {
throw new Exception("Invalid webstream - This appears to be a file download."); throw new Exception("Invalid webstream - This appears to be a file download.");
@ -314,8 +326,6 @@ class Application_Model_Webstream implements Application_Model_LibraryEditable
} }
if (preg_match("/^content-length:/i", $h)) { if (preg_match("/^content-length:/i", $h)) {
$content_length_found = true; $content_length_found = true;
//if content-length appears, this is not a web stream!!!!
//Aborting the save process.
} }
} }

View File

@ -100,7 +100,7 @@ class CcFilesTableMap extends TableMap {
$this->addColumn('SOUNDCLOUD_ERROR_MSG', 'DbSoundcloudErrorMsg', 'VARCHAR', false, 512, null); $this->addColumn('SOUNDCLOUD_ERROR_MSG', 'DbSoundcloudErrorMsg', 'VARCHAR', false, 512, null);
$this->addColumn('SOUNDCLOUD_LINK_TO_FILE', 'DbSoundcloudLinkToFile', 'VARCHAR', false, 4096, null); $this->addColumn('SOUNDCLOUD_LINK_TO_FILE', 'DbSoundcloudLinkToFile', 'VARCHAR', false, 4096, null);
$this->addColumn('SOUNDCLOUD_UPLOAD_TIME', 'DbSoundCloundUploadTime', 'TIMESTAMP', false, 6, null); $this->addColumn('SOUNDCLOUD_UPLOAD_TIME', 'DbSoundCloundUploadTime', 'TIMESTAMP', false, 6, null);
$this->addColumn('REPLAY_GAIN', 'DbReplayGain', 'VARCHAR', false, 16, null); $this->addColumn('REPLAY_GAIN', 'DbReplayGain', 'NUMERIC', false, null, null);
$this->addForeignKey('OWNER_ID', 'DbOwnerId', 'INTEGER', 'cc_subjs', 'ID', false, null, null); $this->addForeignKey('OWNER_ID', 'DbOwnerId', 'INTEGER', 'cc_subjs', 'ID', false, null, null);
// validators // validators
} // initialize() } // initialize()

View File

@ -1892,20 +1892,29 @@ abstract class BaseCcFilesQuery extends ModelCriteria
/** /**
* Filter the query on the replay_gain column * Filter the query on the replay_gain column
* *
* @param string $dbReplayGain The value to use as filter. * @param string|array $dbReplayGain The value to use as filter.
* Accepts wildcards (* and % trigger a LIKE) * Accepts an associative array('min' => $minValue, 'max' => $maxValue)
* @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL * @param string $comparison Operator to use for the column comparison, defaults to Criteria::EQUAL
* *
* @return CcFilesQuery The current query, for fluid interface * @return CcFilesQuery The current query, for fluid interface
*/ */
public function filterByDbReplayGain($dbReplayGain = null, $comparison = null) public function filterByDbReplayGain($dbReplayGain = null, $comparison = null)
{ {
if (null === $comparison) {
if (is_array($dbReplayGain)) { if (is_array($dbReplayGain)) {
$useMinMax = false;
if (isset($dbReplayGain['min'])) {
$this->addUsingAlias(CcFilesPeer::REPLAY_GAIN, $dbReplayGain['min'], Criteria::GREATER_EQUAL);
$useMinMax = true;
}
if (isset($dbReplayGain['max'])) {
$this->addUsingAlias(CcFilesPeer::REPLAY_GAIN, $dbReplayGain['max'], Criteria::LESS_EQUAL);
$useMinMax = true;
}
if ($useMinMax) {
return $this;
}
if (null === $comparison) {
$comparison = Criteria::IN; $comparison = Criteria::IN;
} elseif (preg_match('/[\%\*]/', $dbReplayGain)) {
$dbReplayGain = str_replace('*', '%', $dbReplayGain);
$comparison = Criteria::LIKE;
} }
} }
return $this->addUsingAlias(CcFilesPeer::REPLAY_GAIN, $dbReplayGain, $comparison); return $this->addUsingAlias(CcFilesPeer::REPLAY_GAIN, $dbReplayGain, $comparison);

View File

@ -104,7 +104,7 @@ class SchedulerTests extends PHPUnit_TestCase {
$groupId1 = $i1->add('2008-01-01 12:00:00.000', $this->storedFile->getId()); $groupId1 = $i1->add('2008-01-01 12:00:00.000', $this->storedFile->getId());
$i2 = new Application_Model_ScheduleGroup(); $i2 = new Application_Model_ScheduleGroup();
$i2->addAfter($groupId1, $this->storedFile->getId()); $i2->addAfter($groupId1, $this->storedFile->getId());
$items = Application_Model_Schedule::GetItems("2008-01-01", "2008-01-02"); $items = Application_Model_Schedule::getItems("2008-01-01", "2008-01-02");
if (count($items) != 2) { if (count($items) != 2) {
$this->fail("Wrong number of items returned."); $this->fail("Wrong number of items returned.");
return; return;

View File

@ -99,7 +99,7 @@ while ($showTime < $endDate) {
} }
if (Application_Model_RabbitMq::$doPush) { if (Application_Model_RabbitMq::$doPush) {
$md = array('schedule' => Application_Model_Schedule::GetScheduledPlaylists()); $md = array('schedule' => Application_Model_Schedule::getSchedule());
Application_Model_RabbitMq::SendMessageToPypo("update_schedule", $md); Application_Model_RabbitMq::SendMessageToPypo("update_schedule", $md);
} }

View File

@ -74,7 +74,7 @@
<column name="soundcloud_error_msg" phpName="DbSoundcloudErrorMsg" type="VARCHAR" size="512" required="false"/> <column name="soundcloud_error_msg" phpName="DbSoundcloudErrorMsg" type="VARCHAR" size="512" required="false"/>
<column name="soundcloud_link_to_file" phpName="DbSoundcloudLinkToFile" type="VARCHAR" size="4096" required="false"/> <column name="soundcloud_link_to_file" phpName="DbSoundcloudLinkToFile" type="VARCHAR" size="4096" required="false"/>
<column name="soundcloud_upload_time" phpName="DbSoundCloundUploadTime" type="TIMESTAMP" size="6" required="false"/> <column name="soundcloud_upload_time" phpName="DbSoundCloundUploadTime" type="TIMESTAMP" size="6" required="false"/>
<column name="replay_gain" phpName="DbReplayGain" type="VARCHAR" size="16" required="false"/> <column name="replay_gain" phpName="DbReplayGain" type="NUMERIC" required="false"/>
<column name="owner_id" phpName="DbOwnerId" type="INTEGER" required="false"/> <column name="owner_id" phpName="DbOwnerId" type="INTEGER" required="false"/>
<foreign-key foreignTable="cc_subjs" phpName="FkOwner" name="cc_files_owner_fkey"> <foreign-key foreignTable="cc_subjs" phpName="FkOwner" name="cc_files_owner_fkey">
<reference local="owner_id" foreign="id"/> <reference local="owner_id" foreign="id"/>

View File

@ -92,7 +92,7 @@ CREATE TABLE "cc_files"
"soundcloud_error_msg" VARCHAR(512), "soundcloud_error_msg" VARCHAR(512),
"soundcloud_link_to_file" VARCHAR(4096), "soundcloud_link_to_file" VARCHAR(4096),
"soundcloud_upload_time" TIMESTAMP(6), "soundcloud_upload_time" TIMESTAMP(6),
"replay_gain" VARCHAR(16), "replay_gain" NUMERIC,
"owner_id" INTEGER, "owner_id" INTEGER,
PRIMARY KEY ("id") PRIMARY KEY ("id")
); );
@ -633,7 +633,7 @@ CREATE TABLE "cc_webstream"
"id" serial NOT NULL, "id" serial NOT NULL,
"name" VARCHAR(255) NOT NULL, "name" VARCHAR(255) NOT NULL,
"description" VARCHAR(255) NOT NULL, "description" VARCHAR(255) NOT NULL,
"url" VARCHAR(255) NOT NULL, "url" VARCHAR(512) NOT NULL,
"length" interval default '00:00:00' NOT NULL, "length" interval default '00:00:00' NOT NULL,
"creator_id" INTEGER NOT NULL, "creator_id" INTEGER NOT NULL,
"mtime" TIMESTAMP(6) NOT NULL, "mtime" TIMESTAMP(6) NOT NULL,

View File

@ -36,7 +36,8 @@ var AIRTIME = (function(AIRTIME) {
"track_title" : "s", "track_title" : "s",
"track_num" : "n", "track_num" : "n",
"year" : "n", "year" : "n",
"owner" : "s" "owner" : "s",
"replay_gain" : "n"
}; };
if (AIRTIME.library === undefined) { if (AIRTIME.library === undefined) {
@ -414,7 +415,8 @@ var AIRTIME = (function(AIRTIME) {
/* Mime */ { "sTitle" : "Mime" , "mDataProp" : "mime" , "bVisible" : false , "sClass" : "library_mime" , "sWidth" : "80px" } , /* Mime */ { "sTitle" : "Mime" , "mDataProp" : "mime" , "bVisible" : false , "sClass" : "library_mime" , "sWidth" : "80px" } ,
/* Language */ { "sTitle" : "Language" , "mDataProp" : "language" , "bVisible" : false , "sClass" : "library_language" , "sWidth" : "125px" } , /* Language */ { "sTitle" : "Language" , "mDataProp" : "language" , "bVisible" : false , "sClass" : "library_language" , "sWidth" : "125px" } ,
/* Owner */ { "sTitle" : "Owner" , "mDataProp" : "owner" , "bVisible" : false , "sClass" : "library_language" , "sWidth" : "125px" } , /* Owner */ { "sTitle" : "Owner" , "mDataProp" : "owner" , "bVisible" : false , "sClass" : "library_language" , "sWidth" : "125px" } ,
/* Conductor */ { "sTitle" : "Conductor" , "mDataProp" : "conductor" , "bVisible" : false , "sClass" : "library_conductor" , "sWidth" : "125px" } /* Conductor */ { "sTitle" : "Conductor" , "mDataProp" : "conductor" , "bVisible" : false , "sClass" : "library_conductor" , "sWidth" : "125px" },
/* Replay Gain */ { "sTitle" : "Replay Gain" , "mDataProp" : "replay_gain" , "bVisible" : false , "sClass" : "library_language" , "sWidth" : "125px" }
], ],
"bProcessing": true, "bProcessing": true,

View File

@ -52,7 +52,8 @@ php-pear php5-gd postgresql odbc-postgresql python libsoundtouch-ocaml \
libtaglib-ocaml libao-ocaml libmad-ocaml ecasound \ libtaglib-ocaml libao-ocaml libmad-ocaml ecasound \
libesd0 libportaudio2 libsamplerate0 rabbitmq-server patch \ libesd0 libportaudio2 libsamplerate0 rabbitmq-server patch \
php5-curl mpg123 monit python-virtualenv multitail libcamomile-ocaml-data \ php5-curl mpg123 monit python-virtualenv multitail libcamomile-ocaml-data \
libpulse0 vorbis-tools lsb-release lsof sudo mp3gain vorbisgain flac vorbis-tools libpulse0 vorbis-tools lsb-release lsof sudo mp3gain vorbisgain flac vorbis-tools \
pwgen
#install packages with --force-yes option (this is useful in the case #install packages with --force-yes option (this is useful in the case
#of Debian, where these packages are unauthorized) #of Debian, where these packages are unauthorized)

View File

@ -43,7 +43,8 @@ php-pear php5-gd postgresql odbc-postgresql python libsoundtouch-ocaml \
libtaglib-ocaml libao-ocaml libmad-ocaml ecasound \ libtaglib-ocaml libao-ocaml libmad-ocaml ecasound \
libesd0 libportaudio2 libsamplerate0 rabbitmq-server patch \ libesd0 libportaudio2 libsamplerate0 rabbitmq-server patch \
php5-curl mpg123 monit python-virtualenv multitail libcamomile-ocaml-data \ php5-curl mpg123 monit python-virtualenv multitail libcamomile-ocaml-data \
libpulse0 vorbis-tools lsb-release lsof sudo mp3gain vorbisgain flac vorbis-tools libpulse0 vorbis-tools lsb-release lsof sudo mp3gain vorbisgain flac vorbis-tools \
pwgen
#install packages with --force-yes option (this is useful in the case #install packages with --force-yes option (this is useful in the case
#of Debian, where these packages are unauthorized) #of Debian, where these packages are unauthorized)

View File

@ -393,7 +393,7 @@ end
dyn_out = output.icecast(%wav, dyn_out = output.icecast(%wav,
host="localhost", host="localhost",
port=8999, port=8999,
password="hackme", password=stream_harbor_pass,
mount="test-harbor", mount="test-harbor",
fallible=true) fallible=true)
@ -406,7 +406,7 @@ end
# Function to create a playlist source and output it. # Function to create a playlist source and output it.
def create_dynamic_source(uri) = def create_dynamic_source(uri) =
# The playlist source # The playlist source
s = input.http(buffer=2., max=12., uri) s = audio_to_stereo(input.http(buffer=2., max=12., uri))
# The output # The output
active_dyn_out = dyn_out(s) active_dyn_out = dyn_out(s)

View File

@ -36,9 +36,11 @@ s2_namespace = ref ''
s3_namespace = ref '' s3_namespace = ref ''
just_switched = ref false just_switched = ref false
stream_harbor_pass = list.hd(get_process_lines('pwgen -s -N 1 -n 20'))
%include "ls_lib.liq" %include "ls_lib.liq"
web_stream = input.harbor("test-harbor", port=8999, password="hackme") web_stream = input.harbor("test-harbor", port=8999, password=stream_harbor_pass)
web_stream = on_metadata(notify_stream, web_stream) web_stream = on_metadata(notify_stream, web_stream)
queue = on_metadata(notify, queue) queue = on_metadata(notify, queue)

View File

@ -40,7 +40,7 @@ except Exception, e:
sys.exit() sys.exit()
def is_stream(media_item): def is_stream(media_item):
return media_item['type'] == 'stream' return media_item['type'] == 'stream_output_start'
def is_file(media_item): def is_file(media_item):
return media_item['type'] == 'file' return media_item['type'] == 'file'
@ -211,7 +211,7 @@ class PypoPush(Thread):
queue. queue.
""" """
file_chain = filter(lambda item: (item["type"] == "file"), current_event_chain) file_chain = filter(lambda item: (item["type"] == "file"), current_event_chain)
stream_chain = filter(lambda item: (item["type"] == "stream"), current_event_chain) stream_chain = filter(lambda item: (item["type"] == "stream_output_start"), current_event_chain)
self.logger.debug(self.current_stream_info) self.logger.debug(self.current_stream_info)
self.logger.debug(current_event_chain) self.logger.debug(current_event_chain)
@ -427,13 +427,13 @@ class PypoPush(Thread):
PypoFetch.switch_source(self.logger, self.telnet_lock, "live_dj", "off") PypoFetch.switch_source(self.logger, self.telnet_lock, "live_dj", "off")
elif media_item['type'] == 'stream_buffer_start': elif media_item['type'] == 'stream_buffer_start':
self.start_web_stream_buffer(media_item) self.start_web_stream_buffer(media_item)
elif media_item['type'] == "stream": elif media_item['type'] == "stream_output_start":
if media_item['row_id'] != self.current_prebuffering_stream_id: if media_item['row_id'] != self.current_prebuffering_stream_id:
#this is called if the stream wasn't scheduled sufficiently ahead of time #this is called if the stream wasn't scheduled sufficiently ahead of time
#so that the prebuffering stage could take effect. Let's do the prebuffering now. #so that the prebuffering stage could take effect. Let's do the prebuffering now.
self.start_web_stream_buffer(media_item) self.start_web_stream_buffer(media_item)
self.start_web_stream(media_item) self.start_web_stream(media_item)
elif media_item['type'] == "stream_end": elif media_item['type'] == "stream_buffer_end":
self.stop_web_stream(media_item) self.stop_web_stream(media_item)
except Exception, e: except Exception, e:
self.logger.error('Pypo Push Exception: %s', e) self.logger.error('Pypo Push Exception: %s', e)

View File

@ -78,7 +78,7 @@ echo "Removing everything from the scheduler between $startTime and $endTime..."
$scheduleClear = Schedule::isScheduleEmptyInRange($startTime, "01:00:00"); $scheduleClear = Schedule::isScheduleEmptyInRange($startTime, "01:00:00");
if (!$scheduleClear) { if (!$scheduleClear) {
echo "\nERROR: Schedule could not be cleared.\n\n"; echo "\nERROR: Schedule could not be cleared.\n\n";
var_dump(Schedule::GetItems($startTime, $endTime)); var_dump(Schedule::getItems($startTime, $endTime));
exit; exit;
} }
echo "done.\n"; echo "done.\n";