Merge branch 'saas' into saas-embed-player

This commit is contained in:
drigato 2015-03-23 15:46:03 -04:00
commit 5a373ac604
17 changed files with 291 additions and 79 deletions

View File

@ -37,7 +37,7 @@ require_once (APPLICATION_PATH."/logging/Logging.php");
Logging::setLogPath('/var/log/airtime/zendphp.log'); Logging::setLogPath('/var/log/airtime/zendphp.log');
// We need to manually route because we can't load Zend without the database being initialized first. // We need to manually route because we can't load Zend without the database being initialized first.
if (array_key_exists("REQUEST_URI", $_SERVER) && (strpos($_SERVER["REQUEST_URI"], "/provisioning/create") !== false)) { if (array_key_exists("REQUEST_URI", $_SERVER) && (stripos($_SERVER["REQUEST_URI"], "/provisioning/create") !== false)) {
$provisioningHelper = new ProvisioningHelper($CC_CONFIG["apiKey"][0]); $provisioningHelper = new ProvisioningHelper($CC_CONFIG["apiKey"][0]);
$provisioningHelper->createAction(); $provisioningHelper->createAction();
die(); die();
@ -52,6 +52,7 @@ Application_Model_Auth::pinSessionToClient(Zend_Auth::getInstance());
$front = Zend_Controller_Front::getInstance(); $front = Zend_Controller_Front::getInstance();
$front->registerPlugin(new RabbitMqPlugin()); $front->registerPlugin(new RabbitMqPlugin());
$front->throwExceptions(false);
//localization configuration //localization configuration
Application_Model_Locale::configureLocalization(); Application_Model_Locale::configureLocalization();

View File

@ -53,14 +53,30 @@ class Amazon_S3StorageBackend extends StorageBackend
// Records in the database will remain in case we have to restore the files. // Records in the database will remain in case we have to restore the files.
public function deleteAllCloudFileObjects() public function deleteAllCloudFileObjects()
{ {
$this->s3Client->deleteMatchingObjects( $bucket = $this->getBucket();
$bucket = $this->getBucket(), $prefix = $this->getFilePrefix();
$prefix = $this->getFilePrefix());
//Add a trailing slash in for safety
//(so that deleting /13/413 doesn't delete /13/41313 !)
$prefix = $prefix . "/";
//Do a bunch of safety checks to ensure we don't delete more than we intended.
//An valid prefix is like "12/4312" for instance 4312.
$slashPos = strpos($prefix, "/");
if (($slashPos === FALSE) || //Slash must exist
($slashPos != 2) || //Slash must be the third character
(strlen($prefix) <= $slashPos) || //String must have something after the first slash
(substr_count($prefix, "/") != 2)) //String must have two slashes
{
throw new Exception("Invalid file prefix in " . __FUNCTION__);
} }
$this->s3Client->deleteMatchingObjects($bucket, $prefix);
}
public function getFilePrefix() public function getFilePrefix()
{ {
$hostingId = Billing::getClientInstanceId(); $hostingId = Billing::getClientInstanceId();
return substr($hostingId, -2)."/".$hostingId; $filePrefix = substr($hostingId, -2)."/".$hostingId;
return $filePrefix;
} }
} }

View File

@ -10,6 +10,7 @@ class ProvisioningHelper
// Parameter values // Parameter values
private $dbuser, $dbpass, $dbname, $dbhost, $dbowner, $apikey; private $dbuser, $dbpass, $dbname, $dbhost, $dbowner, $apikey;
private $instanceId; private $instanceId;
private $station_name, $description;
public function __construct($apikey) public function __construct($apikey)
{ {
@ -34,34 +35,37 @@ class ProvisioningHelper
try { try {
$this->parsePostParams(); $this->parsePostParams();
//For security, the Airtime Pro provisioning system creates the database for the user. //For security, the Airtime Pro provisioning system creates the database for the user.
$this->setNewDatabaseConnection(); if ($this->dbhost && !empty($this->dbhost)) {
$this->setNewDatabaseConnection();
//if ($this->checkDatabaseExists()) { //if ($this->checkDatabaseExists()) {
// throw new Exception("ERROR: Airtime database already exists"); // throw new Exception("ERROR: Airtime database already exists");
//} //}
if (!$this->checkDatabaseExists()) { if (!$this->checkDatabaseExists()) {
throw new Exception("ERROR: $this->dbname database does not exist."); throw new Exception("ERROR: $this->dbname database does not exist.");
} }
//We really want to do this check because all the Propel-generated SQL starts with "DROP TABLE IF EXISTS". //We really want to do this check because all the Propel-generated SQL starts with "DROP TABLE IF EXISTS".
//If we don't check, then a second call to this API endpoint would wipe all the tables! //If we don't check, then a second call to this API endpoint would wipe all the tables!
if ($this->checkTablesExist()) { if ($this->checkTablesExist()) {
throw new Exception("ERROR: airtime tables already exists"); throw new Exception("ERROR: airtime tables already exists");
}
$this->createDatabaseTables();
$this->initializeMusicDirsTable($this->instanceId);
} }
//$this->createDatabase(); //$this->createDatabase();
//All we need to do is create the database tables. //All we need to do is create the database tables.
$this->createDatabaseTables(); $this->initializePrefs();
$this->initializeMusicDirsTable($this->instanceId);
} catch (Exception $e) { } catch (Exception $e) {
http_response_code(400); http_response_code(400);
Logging::error($e->getMessage() Logging::error($e->getMessage());
);
echo $e->getMessage() . PHP_EOL; echo $e->getMessage() . PHP_EOL;
return; return;
} }
@ -94,6 +98,7 @@ class ProvisioningHelper
// Result is either boolean FALSE (no table found) or PDOStatement Object (table found) // Result is either boolean FALSE (no table found) or PDOStatement Object (table found)
return $result !== FALSE; return $result !== FALSE;
} }
private function parsePostParams() private function parsePostParams()
{ {
$this->dbuser = $_POST['dbuser']; $this->dbuser = $_POST['dbuser'];
@ -102,6 +107,9 @@ class ProvisioningHelper
$this->dbhost = $_POST['dbhost']; $this->dbhost = $_POST['dbhost'];
$this->dbowner = $_POST['dbowner']; $this->dbowner = $_POST['dbowner'];
$this->instanceId = $_POST['instanceid']; $this->instanceId = $_POST['instanceid'];
$this->station_name = $_POST['station_name'];
$this->description = $_POST['description'];
} }
/** /**
@ -111,9 +119,9 @@ class ProvisioningHelper
private function setNewDatabaseConnection() private function setNewDatabaseConnection()
{ {
self::$dbh = new PDO("pgsql:host=" . $this->dbhost self::$dbh = new PDO("pgsql:host=" . $this->dbhost
. ";dbname=" . $this->dbname . ";dbname=" . $this->dbname
. ";port=5432" . ";user=" . $this->dbuser . ";port=5432" . ";user=" . $this->dbuser
. ";password=" . $this->dbpass); . ";password=" . $this->dbpass);
//Turn on PDO exceptions because they're off by default. //Turn on PDO exceptions because they're off by default.
//self::$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); //self::$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$err = self::$dbh->errorInfo(); $err = self::$dbh->errorInfo();
@ -130,8 +138,8 @@ class ProvisioningHelper
{ {
Logging::info("Creating database..."); Logging::info("Creating database...");
$statement = self::$dbh->prepare("CREATE DATABASE " . pg_escape_string($this->dbname) $statement = self::$dbh->prepare("CREATE DATABASE " . pg_escape_string($this->dbname)
. " WITH ENCODING 'UTF8' TEMPLATE template0" . " WITH ENCODING 'UTF8' TEMPLATE template0"
. " OWNER " . pg_escape_string($this->dbowner)); . " OWNER " . pg_escape_string($this->dbowner));
if (!$statement->execute()) { if (!$statement->execute()) {
throw new Exception("ERROR: Failed to create Airtime database"); throw new Exception("ERROR: Failed to create Airtime database");
} }
@ -182,5 +190,16 @@ class ProvisioningHelper
$musicDir->save(); $musicDir->save();
} }
/**
* Initialize preference values passed from the dashboard (if any exist)
*/
private function initializePrefs() {
if ($this->station_name) {
Application_Model_Preference::SetStationName($this->station_name);
}
if ($this->description) {
Application_Model_Preference::SetStationDescription($this->description);
}
}
} }

View File

@ -1,26 +1,40 @@
<?php <?php
class ErrorController extends Zend_Controller_Action {
class ErrorController extends Zend_Controller_Action public function init()
{
public function errorAction()
{ {
//The default layout includes the Dashboard header, which may contain private information.
//We cannot show that.
$this->view->layout()->disableLayout();
$this->setupCSS();
}
public function errorAction() {
$errors = $this->_getParam('error_handler'); $errors = $this->_getParam('error_handler');
switch ($errors->type) { if ($errors) {
case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ROUTE: // log error message and stack trace
case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER: Logging::error($errors->exception->getMessage());
case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION: Logging::error($errors->exception->getTraceAsString());
// 404 error -- controller or action not found switch ($errors->type) {
$this->getResponse()->setHttpResponseCode(404); case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ROUTE :
$this->view->message = _('Page not found'); case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_CONTROLLER :
break; $this->error404Action();
default: break;
// application error case Zend_Controller_Plugin_ErrorHandler::EXCEPTION_NO_ACTION :
$this->getResponse()->setHttpResponseCode(500); $this->error400Action();
$this->view->message = _('Application error'); break;
break; default :
$this->error500Action();
break;
}
} else {
$exceptions = $this->_getAllParams();
Logging::error($exceptions);
$this->error500Action();
return;
} }
// Log exception, if logger available // Log exception, if logger available
@ -33,11 +47,17 @@ class ErrorController extends Zend_Controller_Action
$this->view->exception = $errors->exception; $this->view->exception = $errors->exception;
} }
$this->view->request = $errors->request; $this->view->request = $errors->request;
} }
public function getLog() private function setupCSS()
{ {
$CC_CONFIG = Config::getConfig();
$staticBaseDir = Application_Common_OsPath::formatDirectoryWithDirectorySeparators($CC_CONFIG['staticBaseDir']);
$this->view->headLink()->appendStylesheet($staticBaseDir . 'css/styles.css?' . $CC_CONFIG['airtime_version']);
}
public function getLog() {
$bootstrap = $this->getInvokeArg('bootstrap'); $bootstrap = $this->getInvokeArg('bootstrap');
if (!$bootstrap->hasPluginResource('Log')) { if (!$bootstrap->hasPluginResource('Log')) {
return false; return false;
@ -47,9 +67,43 @@ class ErrorController extends Zend_Controller_Action
return $log; return $log;
} }
public function deniedAction() /**
{ * 404 error - route or controller
// action body */
public function error404Action() {
$this->_helper->viewRenderer('error-404');
$this->getResponse()->setHttpResponseCode(404);
$this->view->message = _('Page not found.');
} }
/**
* 400 error - no such action
*/
public function error400Action() {
$this->_helper->viewRenderer('error-400');
$this->getResponse()->setHttpResponseCode(400);
$this->view->message = _('The requested action is not supported.');
}
/**
* 403 error - permission denied
*/
public function error403Action() {
$this->_helper->viewRenderer('error-403');
$this->getResponse()->setHttpResponseCode(403);
$this->view->message = _('You do not have permission to access this resource.');
}
/**
* 500 error - internal server error
*/
public function error500Action() {
$this->_helper->viewRenderer('error-500');
$this->getResponse()->setHttpResponseCode(500);
$this->view->message = _('An internal application error has occurred.');
}
} }

View File

@ -18,6 +18,40 @@ class ProvisioningController extends Zend_Controller_Action
* *
*/ */
/**
* Endpoint to change Airtime preferences remotely.
* Mainly for use with the dashboard right now.
*/
public function changeAction() {
$this->view->layout()->disableLayout();
$this->_helper->viewRenderer->setNoRender(true);
if (!RestAuth::verifyAuth(true, false, $this)) {
return;
}
try {
// This is hacky and should be genericized
if ($_POST['station_name']) {
Application_Model_Preference::SetStationName($_POST['station_name']);
}
if ($_POST['description']) {
Application_Model_Preference::SetStationDescription($_POST['description']);
}
} catch (Exception $e) {
$this->getResponse()
->setHttpResponseCode(400)
->appendBody("ERROR: " . $e->getMessage());
Logging::error($e->getMessage());
echo $e->getMessage() . PHP_EOL;
return;
}
$this->getResponse()
->setHttpResponseCode(200)
->appendBody("OK");
}
/** /**
* Delete the Airtime Pro station's files from Amazon S3 * Delete the Airtime Pro station's files from Amazon S3
*/ */
@ -31,12 +65,12 @@ class ProvisioningController extends Zend_Controller_Action
} }
$CC_CONFIG = Config::getConfig(); $CC_CONFIG = Config::getConfig();
foreach ($CC_CONFIG["supportedStorageBackends"] as $storageBackend) { foreach ($CC_CONFIG["supportedStorageBackends"] as $storageBackend) {
$proxyStorageBackend = new ProxyStorageBackend($storageBackend); $proxyStorageBackend = new ProxyStorageBackend($storageBackend);
$proxyStorageBackend->deleteAllCloudFileObjects(); $proxyStorageBackend->deleteAllCloudFileObjects();
} }
$this->getResponse() $this->getResponse()
->setHttpResponseCode(200) ->setHttpResponseCode(200)
->appendBody("OK"); ->appendBody("OK");

View File

@ -28,7 +28,7 @@ class Zend_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract
{ {
$this->_errorPage = array('module' => 'default', $this->_errorPage = array('module' => 'default',
'controller' => 'error', 'controller' => 'error',
'action' => 'denied'); 'action' => 'error');
$this->_roleName = $roleName; $this->_roleName = $roleName;
@ -111,7 +111,16 @@ class Zend_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract
$controller = strtolower($request->getControllerName()); $controller = strtolower($request->getControllerName());
Application_Model_Auth::pinSessionToClient(Zend_Auth::getInstance()); Application_Model_Auth::pinSessionToClient(Zend_Auth::getInstance());
if (in_array($controller, array("api", "auth", "locale", "upgrade", 'whmcs-login', "provisioning"))) { if (in_array($controller, array(
"api",
"auth",
"error",
"locale",
"upgrade",
'whmcs-login',
"provisioning"
)))
{
$this->setRoleName("G"); $this->setRoleName("G");
} elseif (!Zend_Auth::getInstance()->hasIdentity()) { } elseif (!Zend_Auth::getInstance()->hasIdentity()) {

View File

@ -326,6 +326,11 @@ class Application_Model_Preference
return self::getValue("station_name"); return self::getValue("station_name");
} }
public static function SetStationName($station_name)
{
self::setValue("station_name", $station_name);
}
public static function SetAutoUploadRecordedShowToSoundcloud($upload) public static function SetAutoUploadRecordedShowToSoundcloud($upload)
{ {
self::setValue("soundcloud_auto_upload_recorded_show", $upload); self::setValue("soundcloud_auto_upload_recorded_show", $upload);

View File

@ -381,4 +381,7 @@ class AirtimeUpgrader2511 extends AirtimeUpgrader
throw $e; throw $e;
} }
} }
public function downgrade() {
}
} }

View File

@ -0,0 +1,18 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN";
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title><?php echo _("An error has occurred.") ?></title>
<?php echo $this->headLink(); ?>
</head>
<body>
<div class="error-content" id="error-400">
<h2><?php echo _("Bad Request!")?></h2>
<p><?php echo _("The requested action is not supported!")?></p>
<div class="button-bar">
<a class="toggle-button" href="<?php echo $this->baseUrl('dashboard/help'); ?>"><?php echo _("Help") ?></a>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,18 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN";
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title><?php echo _("An error has occurred.") ?></title>
<?php echo $this->headLink(); ?>
</head>
<body>
<div class="error-content" id="error-403">
<h2><?php echo _("Access Denied!")?></h2>
<p><?php echo _("You do not have permission to access this page!")?></p>
<div class="button-bar">
<a class="toggle-button" href="<?php echo $this->baseUrl('dashboard/help'); ?>"><?php echo _("Help") ?></a>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,18 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN";
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title><?php echo _("An error has occurred.") ?></title>
<?php echo $this->headLink(); ?>
</head>
<body>
<div class="error-content" id="error-500">
<h2><?php echo _("Oops!")?></h2>
<p><?php echo _("Something went wrong!")?></p>
<div class="button-bar">
<a class="toggle-button" href="<?php echo $this->baseUrl('dashboard/help'); ?>"><?php echo _("Help") ?></a>
</div>
</div>
</body>
</html>

View File

@ -3,7 +3,8 @@
<html xmlns="http://www.w3.org/1999/xhtml"> <html xmlns="http://www.w3.org/1999/xhtml">
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title><?php echo _("Zend Framework Default Application") ?></title> <title><?php echo _("An error has occurred.") ?></title>
<?php echo $this->headLink(); ?>
</head> </head>
<body> <body>
<div class="error-content"> <div class="error-content">

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -899,20 +899,19 @@ input[type="checkbox"] {
/* Remove any visible csrf form token footprint */ /* Remove any visible csrf form token footprint */
#csrf-label { #csrf-label {
height: 0; display: none;
padding: 0;
margin: 0;
} }
#csrf-element { #csrf-element {
height: 8px;
padding: 0; padding: 0;
margin: 0; margin: 0;
display: inline-block;
} }
/*
#csrf-label .errors li, #csrf-element .errors li { #csrf-label .errors li, #csrf-element .errors li {
margin: 0; margin: 0;
} }*/
.login_box { .login_box {
margin: 0 auto 0 auto; margin: 0 auto 0 auto;
@ -1031,7 +1030,6 @@ input[type="checkbox"] {
#pref_form p.description { #pref_form p.description {
color: #3b3b3b; color: #3b3b3b;
font-size: 12px; font-size: 12px;
float: left;
} }
dt.block-display, dd.block-display { dt.block-display, dd.block-display {
@ -2193,7 +2191,7 @@ dd.radio-inline-list, .preferences dd.radio-inline-list, .stream-config dd.radio
width: 98.5%; width: 98.5%;
} }
.preferences dd#SoundCloudTags-element.block-display .input_text_area { .preferences dd.block-display .input_text_area {
height: 120px; height: 120px;
} }
@ -2202,14 +2200,10 @@ dd.radio-inline-list, .preferences dd.radio-inline-list, .stream-config dd.radio
} }
.preferences #logo-remove-btn { .preferences #logo-remove-btn {
float: right; /*float: left;*/
margin-bottom: 4px; margin-bottom: 4px;
} }
.preferences #Logo-img-container {
margin-top: 30px;
}
#show_time_info { #show_time_info {
font-size:12px; font-size:12px;
height:30px; height:30px;
@ -2570,19 +2564,21 @@ dt.block-display.info-block {
/*---//////////////////// ERROR PAGE ////////////////////---*/ /*---//////////////////// ERROR PAGE ////////////////////---*/
.error-content { .error-content {
background:url(images/404.png) no-repeat 0 0; background:url(images/maintenance.png) no-repeat 0 0;
width:300px; width:360px;
margin: 24px 15px; height:350px;
padding: 0px 10px 0 420px; margin:auto;
margin-top:25px;
padding:auto;
} }
.error-content h2 { .error-content h2 {
margin:0; margin:0;
padding:0 0 10px 0; padding:350px 0 10px 0;
font-size:36px; font-size:36px;
font-weight:bold; font-weight:bold;
color:#3e3e3e; color:#3e3e3e;
text-align:left; text-align:center;
letter-spacing:-.3px; letter-spacing:-.3px;
text-shadow: rgba(248,248,248,.3) 0 1px 0, rgba(0,0,0,.8) 0 -1px 0; text-shadow: rgba(248,248,248,.3) 0 1px 0, rgba(0,0,0,.8) 0 -1px 0;
rgba(51,51,51,.9) rgba(51,51,51,.9)
@ -2590,12 +2586,14 @@ dt.block-display.info-block {
.error-content p { .error-content p {
color: #272727; color: #272727;
font-size: 16px; font-size: 16px;
text-align:center;
margin: 0; margin: 0;
padding:8px 2px; padding:8px 2px;
} }
.error-content .button-bar { .error-content .button-bar {
margin-top:47px; margin-top:47px;
padding-left:2px; padding-left:2px;
text-align:center;
} }
.error-content .toggle-button { .error-content .toggle-button {
border: 1px solid #434343; border: 1px solid #434343;
@ -3142,3 +3140,4 @@ dd .stream-status {
} }
.quota-reached { .quota-reached {
font-size: 14px !important; font-size: 14px !important;
}

View File

@ -3,6 +3,7 @@
import logging import logging
import threading import threading
import multiprocessing import multiprocessing
import Queue
import ConfigParser import ConfigParser
from metadata_analyzer import MetadataAnalyzer from metadata_analyzer import MetadataAnalyzer
from filemover_analyzer import FileMoverAnalyzer from filemover_analyzer import FileMoverAnalyzer
@ -45,8 +46,8 @@ class AnalyzerPipeline:
AnalyzerPipeline.python_logger_deadlock_workaround() AnalyzerPipeline.python_logger_deadlock_workaround()
try: try:
if not isinstance(queue, multiprocessing.queues.Queue): if not isinstance(queue, Queue.Queue):
raise TypeError("queue must be a multiprocessing.Queue()") raise TypeError("queue must be a Queue.Queue()")
if not isinstance(audio_file_path, unicode): if not isinstance(audio_file_path, unicode):
raise TypeError("audio_file_path must be unicode. Was of type " + type(audio_file_path).__name__ + " instead.") raise TypeError("audio_file_path must be unicode. Was of type " + type(audio_file_path).__name__ + " instead.")
if not isinstance(import_directory, unicode): if not isinstance(import_directory, unicode):

View File

@ -6,6 +6,7 @@ import select
import signal import signal
import logging import logging
import multiprocessing import multiprocessing
import Queue
from analyzer_pipeline import AnalyzerPipeline from analyzer_pipeline import AnalyzerPipeline
from status_reporter import StatusReporter from status_reporter import StatusReporter
from cloud_storage_uploader import CloudStorageUploader from cloud_storage_uploader import CloudStorageUploader
@ -212,6 +213,7 @@ class MessageListener:
@staticmethod @staticmethod
def spawn_analyzer_process(audio_file_path, import_directory, original_filename, storage_backend, file_prefix, cloud_storage_config): def spawn_analyzer_process(audio_file_path, import_directory, original_filename, storage_backend, file_prefix, cloud_storage_config):
''' Spawn a child process to analyze and import a new audio file. ''' ''' Spawn a child process to analyze and import a new audio file. '''
'''
q = multiprocessing.Queue() q = multiprocessing.Queue()
p = multiprocessing.Process(target=AnalyzerPipeline.run_analysis, p = multiprocessing.Process(target=AnalyzerPipeline.run_analysis,
args=(q, audio_file_path, import_directory, original_filename, storage_backend, file_prefix, cloud_storage_config)) args=(q, audio_file_path, import_directory, original_filename, storage_backend, file_prefix, cloud_storage_config))
@ -223,7 +225,16 @@ class MessageListener:
logging.info(results) logging.info(results)
else: else:
raise Exception("Analyzer process terminated unexpectedly.") raise Exception("Analyzer process terminated unexpectedly.")
'''
q = Queue.Queue()
try:
AnalyzerPipeline.run_analysis(q, audio_file_path, import_directory, original_filename, storage_backend, file_prefix, cloud_storage_config)
results = q.get()
except Exception as e:
logging.error("Analyzer pipeline exception", e)
pass
# Ensure our queue doesn't fill up and block due to unexpected behaviour. Defensive code. # Ensure our queue doesn't fill up and block due to unexpected behaviour. Defensive code.
while not q.empty(): while not q.empty():
q.get() q.get()

View File

@ -20,10 +20,15 @@ def create_liquidsoap_annotation(media):
# with the metadata we get from Airtime. (You can modify metadata in Airtime's library, # with the metadata we get from Airtime. (You can modify metadata in Airtime's library,
# which doesn't get saved back to the file.) # which doesn't get saved back to the file.)
if 'metadata' in media: if 'metadata' in media:
if 'artist_name' in media['metadata']: if 'artist_name' in media['metadata']:
annotation += ',artist="%s"' % (media['metadata']['artist_name']) artist_name = media['metadata']['artist_name']
if isinstance(artist_name, str):
annotation += ',artist="%s"' % (artist_name.replace('"', '\\"'))
if 'track_title' in media['metadata']: if 'track_title' in media['metadata']:
annotation += ',title="%s"' % (media['metadata']['track_title']) track_title = media['metadata']['track_title']
if isinstance(track_title, str):
annotation += ',title="%s"' % (track_title.replace('"', '\\"'))
annotation += ":" + filename annotation += ":" + filename