Merge pull request #121 from radiorabe/feature/restore-recording-feature-part-2

Fix recording through ecasound
This commit is contained in:
Robb 2017-03-26 00:19:49 -04:00 committed by GitHub
commit e73a2941fd
5 changed files with 55 additions and 36 deletions

View File

@ -73,10 +73,6 @@ class Config {
$CC_CONFIG['apiKey'] = array($values['general']['api_key']); $CC_CONFIG['apiKey'] = array($values['general']['api_key']);
if (defined('APPLICATION_ENV') && APPLICATION_ENV == "development"){
$CC_CONFIG['apiKey'][] = "";
}
$CC_CONFIG['soundcloud-connection-retries'] = $values['soundcloud']['connection_retries']; $CC_CONFIG['soundcloud-connection-retries'] = $values['soundcloud']['connection_retries'];
$CC_CONFIG['soundcloud-connection-wait'] = $values['soundcloud']['time_between_retries']; $CC_CONFIG['soundcloud-connection-wait'] = $values['soundcloud']['time_between_retries'];

View File

@ -642,25 +642,6 @@ class ApiController extends Zend_Controller_Action
} }
} }
public function uploadFileAction()
{
Logging::error("FIXME: Change the show recorder to use the File Upload API and remove this function."); // Albert - April 3, 2014
/**
$upload_dir = ini_get("upload_tmp_dir");
$tempFilePath = Application_Model_StoredFile::uploadFile($upload_dir);
$tempFileName = basename($tempFilePath);
$fileName = isset($_REQUEST["name"]) ? $_REQUEST["name"] : '';
$result = Application_Model_StoredFile::copyFileToStor($upload_dir, $fileName, $tempFileName);
if (!is_null($result)) {
$this->_helper->json->sendJson(
array("jsonrpc" => "2.0", "error" => array("code" => $result['code'], "message" => $result['message']))
);
}
**/
}
public function uploadRecordedAction() public function uploadRecordedAction()
{ {
$show_instance_id = $this->_getParam('showinstanceid'); $show_instance_id = $this->_getParam('showinstanceid');

View File

@ -87,6 +87,8 @@ yum install -y \
fdk-aac \ fdk-aac \
liquidsoap \ liquidsoap \
silan \ silan \
ecasound \
alsa-utils \
icecast \ icecast \
python-pip \ python-pip \
selinux-policy \ selinux-policy \
@ -155,3 +157,6 @@ systemctl restart httpd
# icecast needs to be available to everyone # icecast needs to be available to everyone
sed -i -e 's@<bind-address>127.0.0.1</bind-address>@<bind-address>0.0.0.0</bind-address>@' /etc/icecast.xml sed -i -e 's@<bind-address>127.0.0.1</bind-address>@<bind-address>0.0.0.0</bind-address>@' /etc/icecast.xml
systemctl enable --now icecast systemctl enable --now icecast
# let em use alsa
usermod -a -G audio apache

View File

@ -10,6 +10,7 @@ import sys
import time import time
import urllib import urllib
import urllib2 import urllib2
import requests
import socket import socket
import logging import logging
import json import json
@ -61,7 +62,7 @@ api_config['reload_metadata_group'] = 'reload-metadata-group/format/json/api_key
api_config['handle_watched_dir_missing'] = 'handle-watched-dir-missing/format/json/api_key/%%api_key%%/dir/%%dir%%' api_config['handle_watched_dir_missing'] = 'handle-watched-dir-missing/format/json/api_key/%%api_key%%/dir/%%dir%%'
#show-recorder #show-recorder
api_config['show_schedule_url'] = 'recorded-shows/format/json/api_key/%%api_key%%' api_config['show_schedule_url'] = 'recorded-shows/format/json/api_key/%%api_key%%'
api_config['upload_file_url'] = 'upload-file/format/json/api_key/%%api_key%%' api_config['upload_file_url'] = 'rest/media'
api_config['upload_retries'] = '3' api_config['upload_retries'] = '3'
api_config['upload_wait'] = '60' api_config['upload_wait'] = '60'
#pypo #pypo
@ -278,33 +279,57 @@ class AirtimeApiClient(object):
self.logger.error(str(e)) self.logger.error(str(e))
return None return None
def upload_recorded_show(self, data, headers): def upload_recorded_show(self, files, show_id):
logger = self.logger logger = self.logger
response = '' response = ''
retries = int(self.config["upload_retries"]) retries = int(self.config["upload_retries"])
retries_wait = int(self.config["upload_wait"]) retries_wait = int(self.config["upload_wait"])
url = self.construct_url("upload_file_url") url = self.construct_rest_url("upload_file_url")
logger.debug(url) logger.debug(url)
for i in range(0, retries): for i in range(0, retries):
logger.debug("Upload attempt: %s", i + 1) logger.debug("Upload attempt: %s", i + 1)
logger.debug(files)
logger.debug(ApiRequest.API_HTTP_REQUEST_TIMEOUT)
try: try:
request = urllib2.Request(url, data, headers) request = requests.post(url, files=files, timeout=float(ApiRequest.API_HTTP_REQUEST_TIMEOUT))
response = urllib2.urlopen(request, timeout=ApiClient.API_HTTP_REQUEST_TIMEOUT).read().strip() response = request.json()
logger.debug(response)
logger.info("uploaded show result %s", response) """
FIXME: We need to tell LibreTime that the uploaded track was recorded for a specific show
My issue here is that response does not yet have an id. The id gets generated at the point
where analyzer is done with it's work. We probably need to do what is below in analyzer
and also make sure that the show instance id is routed all the way through.
It already gets uploaded by this but the RestController does not seem to care about it. In
the end analyzer doesn't have the info in it's rabbitmq message and imports the show as a
regular track.
logger.info("uploaded show result as file id %s", response.id)
url = self.construct_url("upload_recorded")
url = url.replace('%%fileid%%', response.id)
url = url.replace('%%showinstanceid%%', show_id)
request.get(url)
logger.info("associated uploaded file %s with show instance %s", response.id, show_id)
"""
break break
except urllib2.HTTPError, e: except requests.exceptions.HTTPError, e:
logger.error("Http error code: %s", e.code) logger.error("Http error code: %s", e.code)
except urllib2.URLError, e: logger.error("traceback: %s", traceback.format_exc())
except requests.exceptions.ConnectionError, e:
logger.error("Server is down: %s", e.args) logger.error("Server is down: %s", e.args)
logger.error("traceback: %s", traceback.format_exc())
except Exception, e: except Exception, e:
logger.error("Exception: %s", e) logger.error("Exception: %s", e)
logger.error("traceback: %s", traceback.format_exc())
#wait some time before next retry #wait some time before next retry
time.sleep(retries_wait) time.sleep(retries_wait)
@ -332,6 +357,19 @@ class AirtimeApiClient(object):
url = url.replace("%%api_key%%", self.config["general"]["api_key"]) url = url.replace("%%api_key%%", self.config["general"]["api_key"])
return url return url
def construct_rest_url(self,config_action_key):
"""Constructs the base url for RESTful requests"""
if self.config["general"]["base_dir"].startswith("/"):
self.config["general"]["base_dir"] = self.config["general"]["base_dir"][1:]
url = "%s://%s:@%s:%s/%s/%s" % \
(str(("http", "https")[int(self.config["general"]["base_port"]) == 443]),
self.config["general"]["api_key"],
self.config["general"]["base_url"], str(self.config["general"]["base_port"]),
self.config["general"]["base_dir"],
self.config[config_action_key])
return url
""" """
Caller of this method needs to catch any exceptions such as Caller of this method needs to catch any exceptions such as
ValueError thrown by json.loads or URLError by urllib2.urlopen ValueError thrown by json.loads or URLError by urllib2.urlopen

View File

@ -95,7 +95,7 @@ class ShowRecorder(Thread):
self.logger.info("starting record") self.logger.info("starting record")
self.logger.info("command " + command) self.logger.info("command " + command)
self.p = Popen(args,stdout=PIPE) self.p = Popen(args,stdout=PIPE,stderr=PIPE)
#blocks at the following line until the child process #blocks at the following line until the child process
#quits #quits
@ -129,11 +129,10 @@ class ShowRecorder(Thread):
# Register the streaming http handlers with urllib2 # Register the streaming http handlers with urllib2
register_openers() register_openers()
# headers contains the necessary Content-Type and Content-Length # files is what requests actually expects
# datagen is a generator object that yields the encoded parameters files = {'file': open(filepath, "rb"), 'name': filename, 'show_instance': str(self.show_instance)}
datagen, headers = multipart_encode({"file": open(filepath, "rb"), 'name': filename, 'show_instance': self.show_instance})
self.api_client.upload_recorded_show(datagen, headers) self.api_client.upload_recorded_show(files, self.show_instance)
def set_metadata_and_save(self, filepath): def set_metadata_and_save(self, filepath):
""" """