diff --git a/application/controllers/ApiController.php b/application/controllers/ApiController.php index b4dd0d3a2..f7ff37eb1 100644 --- a/application/controllers/ApiController.php +++ b/application/controllers/ApiController.php @@ -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).')'; diff --git a/application/models/Schedule.php b/application/models/Schedule.php index 47faa7ddc..21419c4f0 100644 --- a/application/models/Schedule.php +++ b/application/models/Schedule.php @@ -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]); diff --git a/application/models/Shows.php b/application/models/Shows.php index ee7a9873c..f0a7a20bc 100644 --- a/application/models/Shows.php +++ b/application/models/Shows.php @@ -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; diff --git a/application/models/airtime/map/CcScheduleTableMap.php b/application/models/airtime/map/CcScheduleTableMap.php index 3f2502f1c..92afaab0c 100644 --- a/application/models/airtime/map/CcScheduleTableMap.php +++ b/application/models/airtime/map/CcScheduleTableMap.php @@ -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); diff --git a/build/schema.xml b/build/schema.xml index 36941da37..f00ad14fb 100644 --- a/build/schema.xml +++ b/build/schema.xml @@ -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"/> diff --git a/build/sql/schema.sql b/build/sql/schema.sql index ee2f9b109..71ff970ef 100644 --- a/build/sql/schema.sql +++ b/build/sql/schema.sql @@ -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, diff --git a/install/airtime-install.php b/install/airtime-install.php index 55d5ba068..ffcdea662 100644 --- a/install/airtime-install.php +++ b/install/airtime-install.php @@ -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; diff --git a/install/airtime-uninstall.php b/install/airtime-uninstall.php index 181006efd..d175856d5 100644 --- a/install/airtime-uninstall.php +++ b/install/airtime-uninstall.php @@ -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; diff --git a/plugins/jquery.showinfo.js b/plugins/jquery.showinfo.js index da5be1af8..c31381a10 100644 --- a/plugins/jquery.showinfo.js +++ b/plugins/jquery.showinfo.js @@ -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("-"); diff --git a/public/js/playlist/playlist.js b/public/js/playlist/playlist.js index 82f277d1c..98b227381 100644 --- a/public/js/playlist/playlist.js +++ b/public/js/playlist/playlist.js @@ -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(); diff --git a/pypo/install/pypo-install.py b/pypo/install/pypo-install.py index 07cb43cd9..b764dcec9 100644 --- a/pypo/install/pypo-install.py +++ b/pypo/install/pypo-install.py @@ -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 != "/"): diff --git a/python_apps/show-recorder/config.cfg b/python_apps/show-recorder/config.cfg index f75ea204c..d1bb763ab 100644 --- a/python_apps/show-recorder/config.cfg +++ b/python_apps/show-recorder/config.cfg @@ -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/' diff --git a/python_apps/show-recorder/install/recorder-daemontools-logger.sh b/python_apps/show-recorder/install/recorder-daemontools-logger.sh new file mode 100644 index 000000000..9673575db --- /dev/null +++ b/python_apps/show-recorder/install/recorder-daemontools-logger.sh @@ -0,0 +1,2 @@ +#!/bin/sh +exec setuidgid pypo multilog t ./main diff --git a/python_apps/show-recorder/install/recorder-daemontools.sh b/python_apps/show-recorder/install/recorder-daemontools.sh new file mode 100644 index 000000000..d9cec7146 --- /dev/null +++ b/python_apps/show-recorder/install/recorder-daemontools.sh @@ -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 diff --git a/python_apps/show-recorder/install/recorder-install.py b/python_apps/show-recorder/install/recorder-install.py new file mode 100644 index 000000000..1b8186391 --- /dev/null +++ b/python_apps/show-recorder/install/recorder-install.py @@ -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) + + + diff --git a/python_apps/show-recorder/install/recorder-start.py b/python_apps/show-recorder/install/recorder-start.py new file mode 100644 index 000000000..084b2b1ad --- /dev/null +++ b/python_apps/show-recorder/install/recorder-start.py @@ -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) diff --git a/python_apps/show-recorder/install/recorder-stop.py b/python_apps/show-recorder/install/recorder-stop.py new file mode 100644 index 000000000..388c0bc4b --- /dev/null +++ b/python_apps/show-recorder/install/recorder-stop.py @@ -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) diff --git a/python_apps/show-recorder/install/recorder-uninstall.py b/python_apps/show-recorder/install/recorder-uninstall.py new file mode 100644 index 000000000..f8ab96432 --- /dev/null +++ b/python_apps/show-recorder/install/recorder-uninstall.py @@ -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) diff --git a/python_apps/show-recorder/testsoundcloud.py b/python_apps/show-recorder/testsoundcloud.py deleted file mode 100644 index 0ba6fd20d..000000000 --- a/python_apps/show-recorder/testsoundcloud.py +++ /dev/null @@ -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