Merge branch 'master' of dev.sourcefabric.org:airtime
This commit is contained in:
commit
c4b632e8ad
|
@ -109,6 +109,16 @@ class ApiController extends Zend_Controller_Action
|
|||
$this->_helper->viewRenderer->setNoRender(true);
|
||||
|
||||
$result = Schedule::GetPlayOrderRange(0, 1);
|
||||
|
||||
$date = new Application_Model_DateHelper;
|
||||
$timeNow = $date->getDate();
|
||||
$result = array("env"=>APPLICATION_ENV,
|
||||
"schedulerTime"=>gmdate("Y-m-d H:i:s"),
|
||||
"currentShow"=>Show_DAL::GetCurrentShow($timeNow),
|
||||
"nextShow"=>Show_DAL::GetNextShows($timeNow, 5),
|
||||
"timezone"=> date("T"),
|
||||
"timezoneOffset"=> date("Z"));
|
||||
|
||||
//echo json_encode($result);
|
||||
header("Content-type: text/javascript");
|
||||
echo $_GET['callback'].'('.json_encode($result).')';
|
||||
|
|
|
@ -24,41 +24,6 @@ class ScheduleGroup {
|
|||
return $result != "0";
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a date to an ID by stripping out all characters
|
||||
* and padding with zeros.
|
||||
*
|
||||
* @param string $p_dateStr
|
||||
*/
|
||||
public static function dateToId($p_dateStr) {
|
||||
$p_dateStr = str_replace(":", "", $p_dateStr);
|
||||
$p_dateStr = str_replace(" ", "", $p_dateStr);
|
||||
$p_dateStr = str_replace(".", "", $p_dateStr);
|
||||
$p_dateStr = str_replace("-", "", $p_dateStr);
|
||||
$p_dateStr = substr($p_dateStr, 0, 17);
|
||||
$p_dateStr = str_pad($p_dateStr, 17, "0");
|
||||
return $p_dateStr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the two times together, return the result.
|
||||
*
|
||||
* @param string $p_baseTime
|
||||
* Specified as YYYY-MM-DD HH:MM:SS
|
||||
*
|
||||
* @param string $p_addTime
|
||||
* Specified as HH:MM:SS.nnnnnn
|
||||
*
|
||||
* @return string
|
||||
* The end time, to the nearest second.
|
||||
*/
|
||||
// protected function calculateEndTime($p_startTime, $p_trackTime) {
|
||||
// $p_trackTime = substr($p_startTime, 0, );
|
||||
// $start = new DateTime();
|
||||
// $interval = new DateInterval()
|
||||
//
|
||||
// }
|
||||
|
||||
/**
|
||||
* Add a music clip or playlist to the schedule.
|
||||
*
|
||||
|
@ -77,6 +42,7 @@ class ScheduleGroup {
|
|||
*/
|
||||
public function add($show_instance, $p_datetime, $p_audioFileId = null, $p_playlistId = null, $p_options = null) {
|
||||
global $CC_CONFIG, $CC_DBC;
|
||||
|
||||
if (!is_null($p_audioFileId)) {
|
||||
// Schedule a single audio track
|
||||
|
||||
|
@ -92,26 +58,24 @@ class ScheduleGroup {
|
|||
if (empty($length)) {
|
||||
return new PEAR_Error("Length is empty.");
|
||||
}
|
||||
if (!Schedule::isScheduleEmptyInRange($p_datetime, $length)) {
|
||||
return new PEAR_Error("Schedule conflict.", 555);
|
||||
}
|
||||
|
||||
|
||||
// Insert into the table
|
||||
$this->groupId = $CC_DBC->GetOne("SELECT nextval('schedule_group_id_seq')");
|
||||
$id = $this->dateToId($p_datetime);
|
||||
|
||||
$sql = "INSERT INTO ".$CC_CONFIG["scheduleTable"]
|
||||
." (playlist_id, starts, ends, clip_length, group_id, file_id)"
|
||||
." VALUES (0, TIMESTAMP '$p_datetime', "
|
||||
." (instance_id, starts, ends, clip_length, group_id, file_id, cue_out)"
|
||||
." VALUES ($show_instance, TIMESTAMP '$p_datetime', "
|
||||
." (TIMESTAMP '$p_datetime' + INTERVAL '$length'),"
|
||||
." '$length',"
|
||||
." {$this->groupId}, $p_audioFileId)";
|
||||
." {$this->groupId}, $p_audioFileId, '$length')";
|
||||
$result = $CC_DBC->query($sql);
|
||||
if (PEAR::isError($result)) {
|
||||
//var_dump($sql);
|
||||
return $result;
|
||||
}
|
||||
|
||||
} elseif (!is_null($p_playlistId)){
|
||||
}
|
||||
elseif (!is_null($p_playlistId)){
|
||||
// Schedule a whole playlist
|
||||
|
||||
// Load existing playlist
|
||||
|
@ -129,7 +93,6 @@ class ScheduleGroup {
|
|||
|
||||
// Insert all items into the schedule
|
||||
$this->groupId = $CC_DBC->GetOne("SELECT nextval('schedule_group_id_seq')");
|
||||
$id = $this->dateToId($p_datetime);
|
||||
$itemStartTime = $p_datetime;
|
||||
|
||||
$plItems = $playlist->getContents();
|
||||
|
@ -150,14 +113,13 @@ class ScheduleGroup {
|
|||
return $result;
|
||||
}
|
||||
$itemStartTime = $CC_DBC->getOne("SELECT TIMESTAMP '$itemStartTime' + INTERVAL '$trackLength'");
|
||||
$id = $this->dateToId($itemStartTime);
|
||||
}
|
||||
}
|
||||
RabbitMq::PushSchedule();
|
||||
return $this->groupId;
|
||||
}
|
||||
|
||||
public function addAfter($show_instance, $p_groupId, $p_audioFileId) {
|
||||
public function addFileAfter($show_instance, $p_groupId, $p_audioFileId) {
|
||||
global $CC_CONFIG, $CC_DBC;
|
||||
// Get the end time for the given entry
|
||||
$sql = "SELECT MAX(ends) FROM ".$CC_CONFIG["scheduleTable"]
|
||||
|
@ -471,7 +433,7 @@ class Schedule {
|
|||
"current"=>Schedule::GetScheduledItemData($timeNow, 0),
|
||||
"next"=>Schedule::GetScheduledItemData($timeNow, 1, $next, "48 hours"),
|
||||
"currentShow"=>Show_DAL::GetCurrentShow($timeNow),
|
||||
"nextShow"=>Show_DAL::GetNextShow($timeNow),
|
||||
"nextShow"=>Show_DAL::GetNextShows($timeNow, 1),
|
||||
"timezone"=> date("T"),
|
||||
"timezoneOffset"=> date("Z"),
|
||||
"apiKey"=>$CC_CONFIG['apiKey'][0]);
|
||||
|
|
|
@ -678,7 +678,7 @@ class ShowInstance {
|
|||
}
|
||||
|
||||
public function addPlaylistToShow($plId)
|
||||
{
|
||||
{
|
||||
$sched = new ScheduleGroup();
|
||||
$lastGroupId = $this->getLastGroupId();
|
||||
|
||||
|
@ -692,12 +692,26 @@ class ShowInstance {
|
|||
RabbitMq::PushSchedule();
|
||||
}
|
||||
|
||||
public function scheduleShow($plIds)
|
||||
{
|
||||
public function addFileToShow($file_id)
|
||||
{
|
||||
$sched = new ScheduleGroup();
|
||||
$lastGroupId = $this->getLastGroupId();
|
||||
|
||||
if(is_null($lastGroupId)) {
|
||||
|
||||
$groupId = $sched->add($this->_instanceId, $this->getShowStart(), $file_id);
|
||||
}
|
||||
else {
|
||||
$groupId = $sched->addFileAfter($this->_instanceId, $lastGroupId, $file_id);
|
||||
}
|
||||
RabbitMq::PushSchedule();
|
||||
}
|
||||
|
||||
public function scheduleShow($plIds) {
|
||||
|
||||
foreach($plIds as $plId) {
|
||||
$this->addPlaylistToShow($plId);
|
||||
}
|
||||
RabbitMq::PushSchedule();
|
||||
}
|
||||
|
||||
public function removeGroupFromShow($group_id)
|
||||
|
@ -744,6 +758,17 @@ class ShowInstance {
|
|||
->findPK($this->_instanceId);
|
||||
$showInstance->setDbRecordedFile($file_id)
|
||||
->save();
|
||||
|
||||
$rebroadcasts = CcShowInstancesQuery::create()
|
||||
->filterByDbOriginalShow($this->_instanceId)
|
||||
->find();
|
||||
|
||||
foreach ($rebroadcasts as $rebroadcast) {
|
||||
|
||||
$rebroad = new ShowInstance($rebroadcast->getDbId());
|
||||
$rebroad->addFileToShow($file_id);
|
||||
RabbitMq::PushSchedule();
|
||||
}
|
||||
}
|
||||
|
||||
public function getTimeScheduled()
|
||||
|
@ -864,7 +889,7 @@ class Show_DAL {
|
|||
return $rows;
|
||||
}
|
||||
|
||||
public static function GetNextShow($timeNow)
|
||||
public static function GetNextShows($timeNow, $limit)
|
||||
{
|
||||
global $CC_CONFIG, $CC_DBC;
|
||||
|
||||
|
@ -874,7 +899,7 @@ class Show_DAL {
|
|||
." AND si.starts >= TIMESTAMP '$timeNow'"
|
||||
." AND si.starts < TIMESTAMP '$timeNow' + INTERVAL '48 hours'"
|
||||
." ORDER BY si.starts"
|
||||
." LIMIT 1";
|
||||
." LIMIT $limit";
|
||||
|
||||
$rows = $CC_DBC->GetAll($sql);
|
||||
return $rows;
|
||||
|
|
|
@ -39,7 +39,7 @@ class CcScheduleTableMap extends TableMap {
|
|||
$this->setPrimaryKeyMethodInfo('cc_schedule_id_seq');
|
||||
// columns
|
||||
$this->addPrimaryKey('ID', 'DbId', 'INTEGER', true, null, null);
|
||||
$this->addColumn('PLAYLIST_ID', 'DbPlaylistId', 'INTEGER', true, null, null);
|
||||
$this->addColumn('PLAYLIST_ID', 'DbPlaylistId', 'INTEGER', false, null, null);
|
||||
$this->addColumn('STARTS', 'DbStarts', 'TIMESTAMP', true, null, null);
|
||||
$this->addColumn('ENDS', 'DbEnds', 'TIMESTAMP', true, null, null);
|
||||
$this->addColumn('GROUP_ID', 'DbGroupId', 'INTEGER', false, null, null);
|
||||
|
|
|
@ -234,7 +234,7 @@
|
|||
</table>
|
||||
<table name="cc_schedule" phpName="CcSchedule">
|
||||
<column name="id" phpName="DbId" type="INTEGER" primaryKey="true" autoIncrement="true" required="true"/>
|
||||
<column name="playlist_id" phpName="DbPlaylistId" type="INTEGER" required="true"/>
|
||||
<column name="playlist_id" phpName="DbPlaylistId" type="INTEGER" required="false"/>
|
||||
<column name="starts" phpName="DbStarts" type="TIMESTAMP" required="true"/>
|
||||
<column name="ends" phpName="DbEnds" type="TIMESTAMP" required="true"/>
|
||||
<column name="group_id" phpName="DbGroupId" type="INTEGER" required="false"/>
|
||||
|
|
|
@ -345,7 +345,7 @@ DROP TABLE "cc_schedule" CASCADE;
|
|||
CREATE TABLE "cc_schedule"
|
||||
(
|
||||
"id" serial NOT NULL,
|
||||
"playlist_id" INTEGER NOT NULL,
|
||||
"playlist_id" INTEGER,
|
||||
"starts" TIMESTAMP NOT NULL,
|
||||
"ends" TIMESTAMP NOT NULL,
|
||||
"group_id" INTEGER,
|
||||
|
|
|
@ -55,6 +55,9 @@ AirtimeInstall::SetUpPythonEggs();
|
|||
echo PHP_EOL."*** Pypo Installation ***".PHP_EOL;
|
||||
system("python ".__DIR__."/../pypo/install/pypo-install.py");
|
||||
|
||||
echo PHP_EOL."*** Recorder Installation ***".PHP_EOL;
|
||||
system("python ".__DIR__."/../python_apps/show-recorder/install/recorder-install.py");
|
||||
|
||||
|
||||
echo "******************************* Install Complete *******************************".PHP_EOL;
|
||||
|
||||
|
|
|
@ -83,5 +83,8 @@ AirtimeInstall::DeleteFilesRecursive($CC_CONFIG['storageDir']);
|
|||
|
||||
$command = "python ".__DIR__."/../pypo/install/pypo-uninstall.py";
|
||||
system($command);
|
||||
|
||||
$command = "python ".__DIR__."/../python_apps/show-recorder/install/recorder-uninstall.py";
|
||||
system($command);
|
||||
echo "****************************** Uninstall Complete ******************************".PHP_EOL;
|
||||
|
||||
|
|
|
@ -2,25 +2,64 @@
|
|||
$.fn.airtimeShowSchedule = function(options) {
|
||||
|
||||
var defaults = {
|
||||
updatePeriod: 5, //seconds
|
||||
updatePeriod: 20, //seconds
|
||||
sourceDomain: "http://localhost/", //where to get show status from
|
||||
};
|
||||
var options = $.extend(defaults, options);
|
||||
|
||||
return this.each(function() {
|
||||
var obj = $(this);
|
||||
var sd;
|
||||
|
||||
obj.append("<h3>On air today</h3>");
|
||||
obj.append(
|
||||
"<table width='100%' border='0' cellspacing='0' cellpadding='0' class='widget widget no-playing-list small'>"+
|
||||
"<tbody><tr>" +
|
||||
"<td class='time'>13:15 - 13:30</td>" +
|
||||
"<td><a href='#'>Program name</a> <a href='#' class='listen'>Listen</a></td>" +
|
||||
"</tr>"+
|
||||
"<tr>"+
|
||||
"<td class='time'>13:15 - 13:30</td>"+
|
||||
"<td><a href='#'>Lorem ipsum dolor</a></td>"+
|
||||
"</tr>"+
|
||||
"</tbody></table>");
|
||||
getServerData();
|
||||
|
||||
function updateWidget(){
|
||||
var currentShow = sd.getCurrentShow();
|
||||
var nextShows = sd.getNextShows();
|
||||
|
||||
var currentShowName = "";
|
||||
var nextShowName = ""
|
||||
|
||||
if (currentShow.length > 0){
|
||||
currentShowName = currentShow[0].getName();
|
||||
}
|
||||
|
||||
if (nextShows.length > 0){
|
||||
nextShowName = nextShows[0].getName();
|
||||
}
|
||||
|
||||
tableString = "";
|
||||
tableString += "<h3>On air today</h3>";
|
||||
tableString += "<table width='100%' border='0' cellspacing='0' cellpadding='0' class='widget widget no-playing-list small'>"+
|
||||
"<tbody>";
|
||||
|
||||
var shows=currentShow.concat(nextShows);
|
||||
|
||||
obj.empty();
|
||||
for (var i=0; i<shows.length; i++){
|
||||
tableString +=
|
||||
"<tr>" +
|
||||
"<td class='time'>"+shows[i].getRange()+"</td>" +
|
||||
"<td><a href='#'>"+shows[i].getName()+"</a> <a href='#' class='listen'>Listen</a></td>" +
|
||||
"</tr>";
|
||||
}
|
||||
|
||||
tableString += "</tbody></table>";
|
||||
|
||||
obj.append(tableString);
|
||||
}
|
||||
|
||||
function processData(data){
|
||||
sd = new ScheduleData(data);
|
||||
updateWidget();
|
||||
}
|
||||
|
||||
function getServerData(){
|
||||
$.ajax({ url: options.sourceDomain + "api/live-info/", dataType:"jsonp", success:function(data){
|
||||
processData(data);
|
||||
}, error:function(jqXHR, textStatus, errorThrown){}});
|
||||
setTimeout(getServerData, defaults.updatePeriod*1000);
|
||||
}
|
||||
});
|
||||
};
|
||||
})(jQuery);
|
||||
|
@ -42,24 +81,42 @@
|
|||
getServerData();
|
||||
|
||||
function updateWidget(){
|
||||
var currentShow = sd.getCurrentShowName();
|
||||
var timeRemaining = sd.getCurrentShowTimeRemaining();
|
||||
var timeElapsed = sd.getCurrentShowTimeElapsed();
|
||||
var showStatus = sd.getCurrentShowStatus();
|
||||
var currentShow = sd.getCurrentShow();
|
||||
var nextShows = sd.getNextShows();
|
||||
|
||||
var nextShow = sd.getNextShowName();
|
||||
var nextShowRange = sd.getNextShowRange();
|
||||
var showStatus = "Offline";
|
||||
var currentShowName = "";
|
||||
var timeElapsed = "";
|
||||
var timeRemaining = "";
|
||||
|
||||
var nextShowName = "";
|
||||
var nextShowRange = "";
|
||||
|
||||
if (currentShow.length > 0){
|
||||
showStatus = "On Air Now";
|
||||
currentShowName = currentShow[0].getName();
|
||||
|
||||
timeElapsed = sd.getShowTimeElapsed(currentShow[0]);
|
||||
timeRemaining = sd.getShowTimeRemaining(currentShow[0]);
|
||||
}
|
||||
|
||||
if (nextShows.length > 0){
|
||||
nextShowName = nextShows[0].getName();
|
||||
nextShowRange = nextShows[0].getRange();
|
||||
}
|
||||
|
||||
obj.empty();
|
||||
obj.append("<a id='listenWadrLive'><span>Listen WADR Live</span></a>");
|
||||
obj.append("<h4>"+showStatus+" >></h4>");
|
||||
obj.append("<ul class='widget no-playing-bar'>" +
|
||||
"<li class='current'>"+currentShow+ "<span id='time-elapsed' class='time-elapsed'>"+timeElapsed+"</span>" +
|
||||
"<span id='time-remaining' class='time-remaining'>"+timeRemaining+"</span></li>" +
|
||||
"<li class='next'>"+nextShow+"<span>"+nextShowRange+"</span></li>" +
|
||||
"<li class='current'>Current: "+currentShowName+
|
||||
"<span id='time-elapsed' class='time-elapsed'>"+timeElapsed+"</span>" +
|
||||
"<span id='time-remaining' class='time-remaining'>"+timeRemaining+"</span>"+
|
||||
"</li>" +
|
||||
"<li class='next'>Next: "+nextShowName+"<span>"+nextShowRange+"</span></li>" +
|
||||
"</ul>");
|
||||
|
||||
//refresh the UI
|
||||
//refresh the UI to update the elapsed/remaining time
|
||||
setTimeout(updateWidget, 1000);
|
||||
}
|
||||
|
||||
|
@ -78,12 +135,23 @@
|
|||
};
|
||||
})(jQuery);
|
||||
|
||||
/* The rest of this file is the ScheduleData class */
|
||||
/* ScheduleData class BEGIN */
|
||||
function ScheduleData(data){
|
||||
this.data = data;
|
||||
this.estimatedSchedulePosixTime;
|
||||
|
||||
this.schedulePosixTime = this.convertDateToPosixTime(data.schedulerTime);
|
||||
this.currentShow = new Array();
|
||||
for (var i=0; i< data.currentShow.length; i++){
|
||||
this.currentShow[i] = new Show(data.currentShow[i]);
|
||||
}
|
||||
|
||||
this.nextShows = new Array();
|
||||
for (var i=0; i< data.nextShow.length; i++){
|
||||
this.nextShows[i] = new Show(data.nextShow[i]);
|
||||
}
|
||||
|
||||
|
||||
this.schedulePosixTime = convertDateToPosixTime(data.schedulerTime);
|
||||
this.schedulePosixTime += parseInt(data.timezoneOffset)*1000;
|
||||
var date = new Date();
|
||||
this.localRemoteTimeOffset = date.getTime() - this.schedulePosixTime;
|
||||
|
@ -95,72 +163,57 @@ ScheduleData.prototype.secondsTimer = function(){
|
|||
this.estimatedSchedulePosixTime = date.getTime() - this.localRemoteTimeOffset;
|
||||
}
|
||||
|
||||
ScheduleData.prototype.getCurrentShowName = function() {
|
||||
var currentShow = this.data.currentShow;
|
||||
if (currentShow.length > 0){
|
||||
return "Current: " + currentShow[0].name;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
ScheduleData.prototype.getCurrentShow = function(){
|
||||
return this.currentShow;
|
||||
}
|
||||
|
||||
ScheduleData.prototype.getCurrentShowStatus = function() {
|
||||
var currentShow = this.data.currentShow;
|
||||
if (currentShow.length > 0){
|
||||
return "On Air Now";
|
||||
} else {
|
||||
return "Offline";
|
||||
}
|
||||
};
|
||||
ScheduleData.prototype.getNextShows = function() {
|
||||
return this.nextShows;
|
||||
}
|
||||
|
||||
ScheduleData.prototype.getNextShowName = function() {
|
||||
var nextShow = this.data.nextShow;
|
||||
if (nextShow.length > 0){
|
||||
return "Next: " + nextShow[0].name;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
ScheduleData.prototype.getNextShowRange = function() {
|
||||
var nextShow = this.data.nextShow;
|
||||
if (nextShow.length > 0){
|
||||
return this.getTime(nextShow[0].start_timestamp) + " - " + this.getTime(nextShow[0].end_timestamp);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
ScheduleData.prototype.getCurrentShowTimeElapsed = function() {
|
||||
ScheduleData.prototype.getShowTimeElapsed = function(show) {
|
||||
this.secondsTimer();
|
||||
var currentShow = this.data.currentShow;
|
||||
if (currentShow.length > 0){
|
||||
var showStart = this.convertDateToPosixTime(currentShow[0].start_timestamp);
|
||||
return this.convertToHHMMSS(this.estimatedSchedulePosixTime - showStart);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
|
||||
var showStart = convertDateToPosixTime(show.getStartTimestamp());
|
||||
return convertToHHMMSS(this.estimatedSchedulePosixTime - showStart);
|
||||
};
|
||||
|
||||
ScheduleData.prototype.getCurrentShowTimeRemaining = function() {
|
||||
ScheduleData.prototype.getShowTimeRemaining = function(show) {
|
||||
this.secondsTimer();
|
||||
var currentShow = this.data.currentShow;
|
||||
if (currentShow.length > 0){
|
||||
var showEnd = this.convertDateToPosixTime(currentShow[0].end_timestamp);
|
||||
return this.convertToHHMMSS(showEnd - this.estimatedSchedulePosixTime);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
ScheduleData.prototype.getTime = function(timestamp) {
|
||||
return timestamp.split(" ")[1];
|
||||
var showEnd = convertDateToPosixTime(show.getEndTimestamp());
|
||||
return convertToHHMMSS(showEnd - this.estimatedSchedulePosixTime);
|
||||
};
|
||||
/* ScheduleData class END */
|
||||
|
||||
/* Show class BEGIN */
|
||||
function Show(showData){
|
||||
this.showData = showData;
|
||||
}
|
||||
|
||||
Show.prototype.getName = function(){
|
||||
return this.showData.name;
|
||||
}
|
||||
Show.prototype.getRange = function(){
|
||||
return getTime(this.showData.start_timestamp) + " - " + getTime(this.showData.end_timestamp);
|
||||
}
|
||||
Show.prototype.getStartTimestamp = function(){
|
||||
return this.showData.start_timestamp;
|
||||
}
|
||||
Show.prototype.getEndTimestamp = function(){
|
||||
return this.showData.end_timestamp;
|
||||
}
|
||||
/* Show class END */
|
||||
|
||||
|
||||
function getTime(timestamp) {
|
||||
var time = timestamp.split(" ")[1].split(":");
|
||||
return time[0] + ":" + time[1];
|
||||
};
|
||||
|
||||
/* Takes an input parameter of milliseconds and converts these into
|
||||
* the format HH:MM:SS */
|
||||
ScheduleData.prototype.convertToHHMMSS = function(timeInMS){
|
||||
function convertToHHMMSS(timeInMS){
|
||||
var time = parseInt(timeInMS);
|
||||
|
||||
var hours = parseInt(time / 3600000);
|
||||
|
@ -189,7 +242,7 @@ ScheduleData.prototype.convertToHHMMSS = function(timeInMS){
|
|||
|
||||
/* Takes in a string of format similar to 2011-02-07 02:59:57,
|
||||
* and converts this to epoch/posix time. */
|
||||
ScheduleData.prototype.convertDateToPosixTime = function(s){
|
||||
function convertDateToPosixTime(s){
|
||||
var datetime = s.split(" ");
|
||||
|
||||
var date = datetime[0].split("-");
|
||||
|
|
|
@ -169,7 +169,7 @@ function updatePlaybar(){
|
|||
$('#playlist').text(currentShow[0].name);
|
||||
|
||||
var recElem = $('.recording-show');
|
||||
currentShow[0].record ? recElem.show(): recElem.hide();
|
||||
(currentShow[0].record == "1") ? recElem.show(): recElem.hide();
|
||||
}
|
||||
|
||||
$('#show-length').empty();
|
||||
|
|
|
@ -44,6 +44,8 @@ def create_user(username):
|
|||
print "User already exists."
|
||||
#add pypo to audio group
|
||||
os.system("adduser " + username + " audio 1>/dev/null 2>&1")
|
||||
#add pypo to pulse-access group
|
||||
#os.system("adduser " + username + " pulse-access 1>/dev/null 2>&1")
|
||||
|
||||
def copy_dir(src_dir, dest_dir):
|
||||
if (os.path.exists(dest_dir)) and (dest_dir != "/"):
|
||||
|
|
|
@ -6,4 +6,4 @@ show_schedule_url = 'Recorder/get-show-schedule/format/json'
|
|||
upload_file_url = 'Plupload/upload-recorded/format/json'
|
||||
|
||||
# base path to store recordered shows at
|
||||
base_recorded_files = '/home/naomi/Music/'
|
||||
base_recorded_files = '/home/pypo/Music/'
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
#!/bin/sh
|
||||
exec setuidgid pypo multilog t ./main
|
|
@ -0,0 +1,12 @@
|
|||
#!/bin/sh
|
||||
recorder_user="pypo"
|
||||
export HOME="/home/pypo/"
|
||||
# Location of pypo_cli.py Python script
|
||||
recorder_path="/opt/recorder/bin/"
|
||||
recorder_script="testrecordscript.py"
|
||||
echo "*** Daemontools: starting daemon"
|
||||
cd ${recorder_path}
|
||||
exec 2>&1
|
||||
# Note the -u when calling python! we need it to get unbuffered binary stdout and stderr
|
||||
exec sudo python -u ${recorder_path}${recorder_script} -f
|
||||
# EOF
|
|
@ -0,0 +1,128 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import time
|
||||
import os
|
||||
import traceback
|
||||
from optparse import *
|
||||
import sys
|
||||
import time
|
||||
import datetime
|
||||
import logging
|
||||
import logging.config
|
||||
import shutil
|
||||
import string
|
||||
import platform
|
||||
from subprocess import Popen, PIPE, STDOUT
|
||||
|
||||
if os.geteuid() != 0:
|
||||
print "Please run this as root."
|
||||
sys.exit(1)
|
||||
|
||||
BASE_PATH = '/opt/recorder/'
|
||||
|
||||
def create_path(path):
|
||||
if not (os.path.exists(path)):
|
||||
print "Creating directory " + path
|
||||
os.makedirs(path)
|
||||
|
||||
def create_user(username):
|
||||
print "Checking for user "+username
|
||||
p = Popen('id '+username, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
|
||||
output = p.stdout.read()
|
||||
if (output[0:3] != "uid"):
|
||||
# Make the pypo user
|
||||
print "Creating user "+username
|
||||
os.system("adduser --system --quiet --group --shell /bin/bash "+username)
|
||||
|
||||
#set pypo password
|
||||
p = os.popen('/usr/bin/passwd pypo 1>/dev/null 2>&1', 'w')
|
||||
p.write('pypo\n')
|
||||
p.write('pypo\n')
|
||||
p.close()
|
||||
else:
|
||||
print "User already exists."
|
||||
#add pypo to audio group
|
||||
os.system("adduser " + username + " audio 1>/dev/null 2>&1")
|
||||
|
||||
def copy_dir(src_dir, dest_dir):
|
||||
if (os.path.exists(dest_dir)) and (dest_dir != "/"):
|
||||
print "Removing old directory "+dest_dir
|
||||
shutil.rmtree(dest_dir)
|
||||
if not (os.path.exists(dest_dir)):
|
||||
print "Copying directory "+src_dir+" to "+dest_dir
|
||||
shutil.copytree(src_dir, dest_dir)
|
||||
|
||||
def get_current_script_dir():
|
||||
current_script_dir = os.path.realpath(__file__)
|
||||
index = current_script_dir.rindex('/')
|
||||
print current_script_dir[0:index]
|
||||
return current_script_dir[0:index]
|
||||
|
||||
|
||||
try:
|
||||
current_script_dir = get_current_script_dir()
|
||||
print "Checking and removing any existing recorder processes"
|
||||
os.system("python %s/recorder-uninstall.py 1>/dev/null 2>&1"% current_script_dir)
|
||||
time.sleep(5)
|
||||
|
||||
# Create users
|
||||
create_user("pypo")
|
||||
|
||||
print "Creating home directory"
|
||||
create_path("/home/pypo")
|
||||
os.system("chmod -R 755 /home/pypo")
|
||||
os.system("chown -R pypo:pypo /home/pypo")
|
||||
|
||||
print "Creating home directory"
|
||||
create_path("/home/pypo/Music")
|
||||
os.system("chmod -R 755 /home/pypo/Music")
|
||||
os.system("chown -R pypo:pypo /home/pypo/Music")
|
||||
|
||||
print "Creating log directories"
|
||||
create_path("/var/log/recorder")
|
||||
os.system("chmod -R 755 /var/log/recorder")
|
||||
os.system("chown -R pypo:pypo /var/log/recorder")
|
||||
|
||||
create_path(BASE_PATH)
|
||||
create_path(BASE_PATH+"bin")
|
||||
create_path(BASE_PATH+"cache")
|
||||
create_path(BASE_PATH+"files")
|
||||
create_path(BASE_PATH+"tmp")
|
||||
create_path(BASE_PATH+"archive")
|
||||
|
||||
copy_dir("%s/.."%current_script_dir, BASE_PATH+"bin/")
|
||||
|
||||
print "Setting permissions"
|
||||
os.system("chmod -R 755 "+BASE_PATH)
|
||||
os.system("chown -R pypo:pypo "+BASE_PATH)
|
||||
|
||||
print "Installing recorder daemon"
|
||||
create_path("/etc/service/recorder")
|
||||
create_path("/etc/service/recorder/log")
|
||||
shutil.copy("%s/recorder-daemontools.sh"%current_script_dir, "/etc/service/recorder/run")
|
||||
shutil.copy("%s/recorder-daemontools-logger.sh"%current_script_dir, "/etc/service/recorder/log/run")
|
||||
os.system("chmod -R 755 /etc/service/recorder")
|
||||
os.system("chown -R pypo:pypo /etc/service/recorder")
|
||||
|
||||
print "Waiting for processes to start..."
|
||||
time.sleep(5)
|
||||
os.system("python %s/recorder-start.py" % (get_current_script_dir()))
|
||||
time.sleep(2)
|
||||
|
||||
found = True
|
||||
|
||||
p = Popen('svstat /etc/service/recorder', shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
|
||||
output = p.stdout.read()
|
||||
if (output.find("unable to open supervise/ok: file does not exist") >= 0):
|
||||
found = False
|
||||
print output
|
||||
|
||||
if not found:
|
||||
print "Recorder 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)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
if os.geteuid() != 0:
|
||||
print "Please run this as root."
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
print "Starting daemontool script recorder"
|
||||
os.system("svc -u /etc/service/recorder")
|
||||
|
||||
except Exception, e:
|
||||
print "exception:" + str(e)
|
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
if os.geteuid() != 0:
|
||||
print "Please run this as root."
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
print "Stopping daemontool script pypo"
|
||||
os.system("svc -dx /etc/service/pypo 1>/dev/null 2>&1")
|
||||
|
||||
if os.path.exists("/etc/service/pypo-fetch"):
|
||||
os.system("svc -dx /etc/service/pypo-fetch 1>/dev/null 2>&1")
|
||||
if os.path.exists("/etc/service/pypo-push"):
|
||||
os.system("svc -dx /etc/service/pypo-push 1>/dev/null 2>&1")
|
||||
|
||||
print "Stopping daemontool script pypo-liquidsoap"
|
||||
os.system("svc -dx /etc/service/pypo-liquidsoap 1>/dev/null 2>&1")
|
||||
os.system("killall liquidsoap")
|
||||
|
||||
except Exception, e:
|
||||
print "exception:" + str(e)
|
|
@ -0,0 +1,46 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
if os.geteuid() != 0:
|
||||
print "Please run this as root."
|
||||
sys.exit(1)
|
||||
|
||||
BASE_PATH = '/opt/recorder/'
|
||||
|
||||
def remove_path(path):
|
||||
os.system("rm -rf " + path)
|
||||
|
||||
def remove_user(username):
|
||||
os.system("killall -u %s 1>/dev/null 2>&1" % username)
|
||||
|
||||
#allow all process to be completely closed before we attempt to delete user
|
||||
print "Waiting for processes to close..."
|
||||
time.sleep(5)
|
||||
|
||||
os.system("deluser --remove-home " + username + " 1>/dev/null 2>&1")
|
||||
|
||||
def get_current_script_dir():
|
||||
current_script_dir = os.path.realpath(__file__)
|
||||
index = current_script_dir.rindex('/')
|
||||
return current_script_dir[0:index]
|
||||
|
||||
try:
|
||||
os.system("python %s/recorder-stop.py" % get_current_script_dir())
|
||||
|
||||
print "Removing log directories"
|
||||
remove_path("/var/log/recorder")
|
||||
|
||||
print "Removing recorder files"
|
||||
remove_path(BASE_PATH)
|
||||
|
||||
print "Removing daemontool script recorder"
|
||||
remove_path("rm -rf /etc/service/recorder")
|
||||
|
||||
remove_user("pypo")
|
||||
print "Uninstall complete."
|
||||
except Exception, e:
|
||||
print "exception:" + str(e)
|
|
@ -1,59 +0,0 @@
|
|||
import webbrowser
|
||||
import scapi
|
||||
|
||||
# the host to connect to. Normally, this
|
||||
# would be api.soundcloud.com
|
||||
API_HOST = "api.soundcloud.com"
|
||||
|
||||
# This needs to be the consumer ID you got from
|
||||
# http://soundcloud.com/settings/applications/new
|
||||
CONSUMER = "2CLCxcSXYzx7QhhPVHN4A"
|
||||
# This needs to be the consumer secret password you got from
|
||||
# http://soundcloud.com/settings/applications/new
|
||||
CONSUMER_SECRET = "pZ7beWmF06epXLHVUP1ufOg2oEnIt9XhE8l8xt0bBs"
|
||||
|
||||
# first, we create an OAuthAuthenticator that only knows about consumer
|
||||
# credentials. This is done so that we can get an request-token as
|
||||
# first step.
|
||||
oauth_authenticator = scapi.authentication.OAuthAuthenticator(CONSUMER,
|
||||
CONSUMER_SECRET,
|
||||
None,
|
||||
None)
|
||||
|
||||
# The connector works with the authenticator to create and sign the requests. It
|
||||
# has some helper-methods that allow us to do the OAuth-dance.
|
||||
connector = scapi.ApiConnector(host=API_HOST, authenticator=oauth_authenticator)
|
||||
|
||||
# First step is to get a request-token, and to let the user authorize that
|
||||
# via the browser.
|
||||
token, secret = connector.fetch_request_token()
|
||||
authorization_url = connector.get_request_token_authorization_url(token)
|
||||
webbrowser.open(authorization_url)
|
||||
oauth_verifier = raw_input("please enter verifier code as seen in the browser:")
|
||||
|
||||
# Now we create a new authenticator with the temporary token & secret we got from
|
||||
# the request-token. This will give us the access-token
|
||||
oauth_authenticator = scapi.authentication.OAuthAuthenticator(CONSUMER,
|
||||
CONSUMER_SECRET,
|
||||
token,
|
||||
secret)
|
||||
|
||||
# we need a new connector with the new authenticator!
|
||||
connector = scapi.ApiConnector(API_HOST, authenticator=oauth_authenticator)
|
||||
token, secret = connector.fetch_access_token(oauth_verifier)
|
||||
|
||||
|
||||
# now we are finally ready to go - with all four parameters OAuth requires,
|
||||
# we can setup an authenticator that allows for actual API-calls.
|
||||
oauth_authenticator = scapi.authentication.OAuthAuthenticator(CONSUMER,
|
||||
CONSUMER_SECRET,
|
||||
token,
|
||||
secret)
|
||||
|
||||
# we pass the connector to a Scope - a Scope is essentially a path in the REST-url-space.
|
||||
# Without any path-component, it's the root from which we can then query into the
|
||||
# resources.
|
||||
root = scapi.Scope(scapi.ApiConnector(host=API_HOST, authenticator=oauth_authenticator))
|
||||
|
||||
# Hey, nice meeting you! Connected to SoundCloud using OAuth will allow you to access protected resources, like the current user's name.
|
||||
print "Hello, %s" % root.me().username
|
Loading…
Reference in New Issue