Merge branch 'cc-5709-airtime-analyzer' into cc-5709-airtime-analyzer-cloud-storage
This commit is contained in:
commit
c09457ce7c
22
INSTALL
22
INSTALL
|
@ -1,22 +0,0 @@
|
|||
Airtime is the open radio software for scheduling and remote station management.
|
||||
Home page: http://airtime.sourcefabric.org/
|
||||
|
||||
Installation instructions are here:
|
||||
http://wiki.sourcefabric.org/x/BQBF
|
||||
|
||||
Here is the manual:
|
||||
http://en.flossmanuals.net/airtime/
|
||||
|
||||
To report bugs, visit our bug tracker at:
|
||||
http://dev.sourcefabric.org/browse/CC
|
||||
|
||||
Visit our community support forum here:
|
||||
http://forum.sourcefabric.org/index.php/f/14/
|
||||
|
||||
For commercial support, see:
|
||||
http://sourcefabric.org/en/services/about/347/Support.htm
|
||||
or send an e-mail to contact@sourcefabric.org
|
||||
|
||||
If you are a developer and want to hack on Airtime, go here:
|
||||
http://wiki.sourcefabric.org/display/CC
|
||||
|
|
@ -14,6 +14,7 @@ require_once "DateHelper.php";
|
|||
require_once "OsPath.php";
|
||||
require_once "Database.php";
|
||||
require_once "Timezone.php";
|
||||
require_once "Auth.php";
|
||||
require_once __DIR__.'/forms/helpers/ValidationTypes.php';
|
||||
require_once __DIR__.'/controllers/plugins/RabbitMqPlugin.php';
|
||||
require_once __DIR__.'/controllers/plugins/Maintenance.php';
|
||||
|
@ -26,6 +27,8 @@ require_once __DIR__."/configs/navigation.php";
|
|||
|
||||
Zend_Validate::setDefaultNamespaces("Zend");
|
||||
|
||||
Application_Model_Auth::pinSessionToClient(Zend_Auth::getInstance());
|
||||
|
||||
$front = Zend_Controller_Front::getInstance();
|
||||
$front->registerPlugin(new RabbitMqPlugin());
|
||||
|
||||
|
|
|
@ -14,9 +14,10 @@ class LoginController extends Zend_Controller_Action
|
|||
$request = $this->getRequest();
|
||||
|
||||
Application_Model_Locale::configureLocalization($request->getcookie('airtime_locale', 'en_CA'));
|
||||
if (Zend_Auth::getInstance()->hasIdentity())
|
||||
$auth = Zend_Auth::getInstance();
|
||||
|
||||
if ($auth->hasIdentity())
|
||||
{
|
||||
|
||||
$this->_redirect('Showbuilder');
|
||||
}
|
||||
|
||||
|
@ -52,8 +53,7 @@ class LoginController extends Zend_Controller_Action
|
|||
//pass to the adapter the submitted username and password
|
||||
$authAdapter->setIdentity($username)
|
||||
->setCredential($password);
|
||||
|
||||
$auth = Zend_Auth::getInstance();
|
||||
|
||||
$result = $auth->authenticate($authAdapter);
|
||||
if ($result->isValid()) {
|
||||
//all info about this user from the login table omit only the password
|
||||
|
@ -65,15 +65,13 @@ class LoginController extends Zend_Controller_Action
|
|||
|
||||
Application_Model_LoginAttempts::resetAttempts($_SERVER['REMOTE_ADDR']);
|
||||
Application_Model_Subjects::resetLoginAttempts($username);
|
||||
|
||||
$tempSess = new Zend_Session_Namespace("referrer");
|
||||
$tempSess->referrer = 'login';
|
||||
|
||||
|
||||
//set the user locale in case user changed it in when logging in
|
||||
Application_Model_Preference::SetUserLocale($locale);
|
||||
|
||||
$this->_redirect('Showbuilder');
|
||||
} else {
|
||||
|
||||
$message = _("Wrong username or password provided. Please try again.");
|
||||
Application_Model_Subjects::increaseLoginAttempts($username);
|
||||
Application_Model_LoginAttempts::increaseAttempts($_SERVER['REMOTE_ADDR']);
|
||||
|
@ -96,7 +94,8 @@ class LoginController extends Zend_Controller_Action
|
|||
|
||||
public function logoutAction()
|
||||
{
|
||||
Zend_Auth::getInstance()->clearIdentity();
|
||||
$auth = Zend_Auth::getInstance();
|
||||
$auth->clearIdentity();
|
||||
$this->_redirect('showbuilder/index');
|
||||
}
|
||||
|
||||
|
|
|
@ -109,6 +109,7 @@ class Zend_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract
|
|||
public function preDispatch(Zend_Controller_Request_Abstract $request)
|
||||
{
|
||||
$controller = strtolower($request->getControllerName());
|
||||
Application_Model_Auth::pinSessionToClient(Zend_Auth::getInstance());
|
||||
|
||||
//Ignore authentication for all access to the rest API. We do auth via API keys for this
|
||||
//and/or by OAuth.
|
||||
|
|
|
@ -13,8 +13,8 @@
|
|||
<?php echo $this->layout()->content ?>
|
||||
</div>
|
||||
<div class="footer">
|
||||
<?php echo sprintf(_("Airtime Copyright ©Sourcefabric o.p.s. All rights reserved.%s"
|
||||
."Maintained and distributed under GNU GPL v.3 by %sSourcefabric o.p.s%s"),
|
||||
<?php echo sprintf(_("Airtime copyright © Sourcefabric z.ú. All rights reserved.%s"
|
||||
."Maintained and distributed under the GNU GPL v.3 by %sSourcefabric z.ú.%s"),
|
||||
"<br>", "<a href='http://www.sourcefabric.org'>" ,"</a>");?>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -110,4 +110,18 @@ class Application_Model_Auth
|
|||
|
||||
return $string;
|
||||
}
|
||||
|
||||
/** It is essential to do this before interacting with Zend_Auth otherwise sessions could be shared between
|
||||
* different copies of Airtime on the same webserver. This essentially pins this session to:
|
||||
* - The server hostname - including subdomain so we segment multiple Airtime installs on different subdomains
|
||||
* - The remote IP of the browser - to help prevent session hijacking
|
||||
* - The client ID - same reason as server hostname
|
||||
* @param Zend_Auth $auth Get this with Zend_Auth::getInstance().
|
||||
*/
|
||||
public static function pinSessionToClient($auth)
|
||||
{
|
||||
$serverName = isset($_SERVER['SERVER_NAME']) ? $_SERVER['SERVER_NAME'] : "";
|
||||
$remoteAddr = isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : "";
|
||||
$auth->setStorage(new Zend_Auth_Storage_Session('Airtime' . $serverName . $remoteAddr . Application_Model_Preference::GetClientId()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -545,7 +545,11 @@ class Application_Model_Preference
|
|||
// Returns station default timezone (from preferences)
|
||||
public static function GetDefaultTimezone()
|
||||
{
|
||||
return self::getValue("timezone");
|
||||
$stationTimezone = self::getValue("timezone");
|
||||
if (is_null($stationTimezone) || $stationTimezone == "") {
|
||||
$stationTimezone = "UTC";
|
||||
}
|
||||
return $stationTimezone;
|
||||
}
|
||||
|
||||
public static function SetUserTimezone($timezone = null)
|
||||
|
@ -1313,7 +1317,12 @@ class Application_Model_Preference
|
|||
}
|
||||
|
||||
$ds = unserialize($v);
|
||||
|
||||
|
||||
|
||||
if (is_null($ds) || !is_array($ds)) {
|
||||
return $id;
|
||||
}
|
||||
|
||||
if (!array_key_exists('ColReorder', $ds)) {
|
||||
return $id;
|
||||
}
|
||||
|
|
|
@ -303,10 +303,10 @@ SQL;
|
|||
$p_start_str = $p_start->format("Y-m-d H:i:s");
|
||||
$p_end_str = $p_end->format("Y-m-d H:i:s");
|
||||
|
||||
//We need to search 24 hours before and after the show times so that that we
|
||||
//We need to search 48 hours before and after the show times so that that we
|
||||
//capture all of the show's contents.
|
||||
$p_track_start= $p_start->sub(new DateInterval("PT24H"))->format("Y-m-d H:i:s");
|
||||
$p_track_end = $p_end->add(new DateInterval("PT24H"))->format("Y-m-d H:i:s");
|
||||
$p_track_start= $p_start->sub(new DateInterval("PT48H"))->format("Y-m-d H:i:s");
|
||||
$p_track_end = $p_end->add(new DateInterval("PT48H"))->format("Y-m-d H:i:s");
|
||||
|
||||
$templateSql = <<<SQL
|
||||
SELECT DISTINCT sched.starts AS sched_starts,
|
||||
|
@ -738,13 +738,16 @@ SQL;
|
|||
$replay_gain = is_null($item["replay_gain"]) ? "0": $item["replay_gain"];
|
||||
$replay_gain += Application_Model_Preference::getReplayGainModifier();
|
||||
|
||||
if ( !Application_Model_Preference::GetEnableReplayGain() ) {
|
||||
if (!Application_Model_Preference::GetEnableReplayGain() ) {
|
||||
$replay_gain = 0;
|
||||
}
|
||||
|
||||
$fileMetadata = CcFiles::sanitizeResponse(CcFilesQuery::create()->findPk($media_id));
|
||||
|
||||
$schedule_item = array(
|
||||
'id' => $media_id,
|
||||
'type' => 'file',
|
||||
'metadata' => $fileMetadata,
|
||||
'row_id' => $item["id"],
|
||||
'uri' => $uri,
|
||||
'fade_in' => Application_Model_Schedule::WallTimeToMillisecs($item["fade_in"]),
|
||||
|
|
|
@ -13,6 +13,14 @@
|
|||
*/
|
||||
class CcFiles extends BaseCcFiles {
|
||||
|
||||
//fields we should never expose through our RESTful API
|
||||
private static $privateFields = array(
|
||||
'file_exists',
|
||||
'silan_check',
|
||||
'is_scheduled',
|
||||
'is_playlist'
|
||||
);
|
||||
|
||||
public function getCueLength()
|
||||
{
|
||||
$cuein = $this->getDbCuein();
|
||||
|
@ -46,4 +54,20 @@ class CcFiles extends BaseCcFiles {
|
|||
$this->save();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Strips out the private fields we do not want to send back in API responses
|
||||
* @param $file a CcFiles object
|
||||
*/
|
||||
//TODO: rename this function?
|
||||
public static function sanitizeResponse($file)
|
||||
{
|
||||
$response = $file->toArray(BasePeer::TYPE_FIELDNAME);
|
||||
|
||||
foreach (self::$privateFields as $key) {
|
||||
unset($response[$key]);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
} // CcFiles
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
class Rest_MediaController extends Zend_Rest_Controller
|
||||
{
|
||||
//fields that are not modifiable via our RESTful API
|
||||
private $blackList = array(
|
||||
private static $blackList = array(
|
||||
'id',
|
||||
'directory',
|
||||
'filepath',
|
||||
|
@ -18,14 +18,6 @@ class Rest_MediaController extends Zend_Rest_Controller
|
|||
'is_playlist'
|
||||
);
|
||||
|
||||
//fields we should never expose through our RESTful API
|
||||
private $privateFields = array(
|
||||
'file_exists',
|
||||
'silan_check',
|
||||
'is_scheduled',
|
||||
'is_playlist'
|
||||
);
|
||||
|
||||
public function init()
|
||||
{
|
||||
$this->view->layout()->disableLayout();
|
||||
|
@ -44,7 +36,7 @@ class Rest_MediaController extends Zend_Rest_Controller
|
|||
$files_array = array();
|
||||
foreach (CcFilesQuery::create()->find() as $file)
|
||||
{
|
||||
array_push($files_array, $this->sanitizeResponse($file));
|
||||
array_push($files_array, CcFiles::sanitizeResponse($file));
|
||||
}
|
||||
|
||||
$this->getResponse()
|
||||
|
@ -137,7 +129,7 @@ class Rest_MediaController extends Zend_Rest_Controller
|
|||
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(200)
|
||||
->appendBody(json_encode($this->sanitizeResponse($file)));
|
||||
->appendBody(json_encode(CcFiles::sanitizeResponse($file)));
|
||||
} else {
|
||||
$this->fileNotFoundResponse();
|
||||
}
|
||||
|
@ -204,7 +196,7 @@ class Rest_MediaController extends Zend_Rest_Controller
|
|||
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(201)
|
||||
->appendBody(json_encode($this->sanitizeResponse($file)));
|
||||
->appendBody(json_encode(CcFiles::sanitizeResponse($file)));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -254,7 +246,7 @@ class Rest_MediaController extends Zend_Rest_Controller
|
|||
|
||||
$this->getResponse()
|
||||
->setHttpResponseCode(200)
|
||||
->appendBody(json_encode($this->sanitizeResponse($file)));
|
||||
->appendBody(json_encode(CcFiles::sanitizeResponse($file)));
|
||||
} else {
|
||||
$file->setDbImportStatus(2)->save();
|
||||
$this->fileNotFoundResponse();
|
||||
|
@ -428,7 +420,7 @@ class Rest_MediaController extends Zend_Rest_Controller
|
|||
}
|
||||
|
||||
if (!$fileForm->isValidPartial($whiteList)) {
|
||||
throw Exception("Data validation failed");
|
||||
throw new Exception("Data validation failed");
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$errors = $fileForm->getErrors();
|
||||
|
@ -509,30 +501,15 @@ class Rest_MediaController extends Zend_Rest_Controller
|
|||
* from outside of Airtime
|
||||
* @param array $data
|
||||
*/
|
||||
private function removeBlacklistedFieldsFromRequestData($data)
|
||||
private static function removeBlacklistedFieldsFromRequestData($data)
|
||||
{
|
||||
foreach ($this->blackList as $key) {
|
||||
foreach (self::$blackList as $key) {
|
||||
unset($data[$key]);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Strips out the private fields we do not want to send back in API responses
|
||||
*/
|
||||
//TODO: rename this function?
|
||||
public function sanitizeResponse($file)
|
||||
{
|
||||
$response = $file->toArray(BasePeer::TYPE_FIELDNAME);
|
||||
|
||||
foreach ($this->privateFields as $key) {
|
||||
unset($response[$key]);
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
private function removeEmptySubFolders($path)
|
||||
{
|
||||
|
|
|
@ -85,32 +85,31 @@ class Application_Service_CalendarService
|
|||
$currentShow = Application_Model_Show::getCurrentShow();
|
||||
$currentShowId = count($currentShow) == 1 ? $currentShow[0]["id"] : null;
|
||||
$showIsLinked = $this->ccShow->isLinked();
|
||||
if ($now < $end && ($isAdminOrPM || $isHostOfShow) && !$this->ccShowInstance->isRecorded()) {
|
||||
//if the show is not linked the user can add/remove content
|
||||
if (!$showIsLinked) {
|
||||
|
||||
$menu["schedule"] = array(
|
||||
"name"=> _("Add / Remove Content"),
|
||||
"icon" => "add-remove-content",
|
||||
"url" => $baseUrl."showbuilder/builder-dialog/");
|
||||
//if the show is linked and it's not currently playing the user can add/remove content
|
||||
} elseif ($showIsLinked && $currentShowId != $this->ccShow->getDbId()) {
|
||||
//user can add/remove content if the show has not ended
|
||||
if ($now < $end && ($isAdminOrPM || $isHostOfShow) && !$this->ccShowInstance->isRecorded()) {
|
||||
//if the show is not linked OR if the show is linked AND not the current playing show
|
||||
//the user can add/remove content
|
||||
if (!$showIsLinked || ($showIsLinked && $currentShowId != $this->ccShow->getDbId())) {
|
||||
|
||||
$menu["schedule"] = array(
|
||||
"name"=> _("Add / Remove Content"),
|
||||
"icon" => "add-remove-content",
|
||||
"url" => $baseUrl."showbuilder/builder-dialog/");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($now < $start && ($isAdminOrPM || $isHostOfShow) &&
|
||||
!$this->ccShowInstance->isRecorded() ) {
|
||||
|
||||
$menu["clear"] = array(
|
||||
"name"=> _("Remove All Content"),
|
||||
"icon" => "remove-all-content",
|
||||
"url" => $baseUrl."schedule/clear-show");
|
||||
//user can remove all content if the show has not started
|
||||
if ($now < $start && ($isAdminOrPM || $isHostOfShow) && !$this->ccShowInstance->isRecorded() ) {
|
||||
//if the show is not linked OR if the show is linked AND not the current playing show
|
||||
//the user can remove all content
|
||||
if (!$showIsLinked || ($showIsLinked && $currentShowId != $this->ccShow->getDbId())) {
|
||||
|
||||
$menu["clear"] = array(
|
||||
"name"=> _("Remove All Content"),
|
||||
"icon" => "remove-all-content",
|
||||
"url" => $baseUrl."schedule/clear-show");
|
||||
}
|
||||
}
|
||||
|
||||
//"Show Content" should be a menu item at all times except when
|
||||
|
|
|
@ -289,7 +289,15 @@ class Application_Service_ShowService
|
|||
if ($this->ccShow->isRepeating()) {
|
||||
$ccShowDays = $this->ccShow->getRepeatingCcShowDays();
|
||||
} else {
|
||||
$ccShowDays = $this->ccShow->getCcShowDayss();
|
||||
//$ccShowDays = $this->ccShow->getCcShowDayss();
|
||||
|
||||
/* Cannot use the above statement to get the cc_show_days
|
||||
* object because it's getting the old object before the
|
||||
* show was edited. clearInstancePool() didn't work.
|
||||
*/
|
||||
$ccShowDays = CcShowDaysQuery::create()
|
||||
->filterByDbShowId($this->ccShow->getDbId())
|
||||
->find();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1039,6 +1047,9 @@ SQL;
|
|||
);
|
||||
$origStartDateTime->setTimezone(new DateTimeZone("UTC"));
|
||||
$ccShowInstance = $this->getInstance($origStartDateTime);
|
||||
if (!$ccShowInstance) {
|
||||
throw new Exception("Could not find show instance with start time: ".$origStartDateTime->format("Y-m-d H:i:s"));
|
||||
}
|
||||
}
|
||||
|
||||
$ccShowInstance->setDbShowId($this->ccShow->getDbId());
|
||||
|
|
|
@ -10,7 +10,7 @@ echo sprintf(_("%sAirtime%s %s, the open radio software for scheduling and remot
|
|||
?>
|
||||
<br>© 2013
|
||||
<?php
|
||||
echo sprintf(_("%sSourcefabric%s o.p.s. Airtime is distributed under the %sGNU GPL v.3%s"),
|
||||
echo sprintf(_("%sSourcefabric%s z.ú Airtime is distributed under the %sGNU GPL v.3%s"),
|
||||
"<a href='http://www.sourcefabric.org' target='_blank'>",
|
||||
"</a>",
|
||||
"<a href='http://www.gnu.org/licenses/gpl-3.0-standalone.html' target='_blank'>",
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<div id="login" class="login-content clearfix">
|
||||
<?php if(isset($this->demo) && $this->demo == 1){?>
|
||||
<p style="font-weight:bold">
|
||||
<?php echo _("Welcome to the online Airtime demo! You can log in using the username 'admin' and the password 'admin'.")?>
|
||||
<?php echo _("Welcome to the Airtime demo! You can log in using the username 'admin' and the password 'admin'.")?>
|
||||
</p>
|
||||
<?php }?>
|
||||
<p class="light" style='<?php echo $this->error?"color:#902d2d;font-size:11px;padding:2px 4px;background:#c6b4b4;margin-bottom:2px;border:1px solid #c83f3f;":""?>'><?php echo $this->message; ?></p>
|
||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
@ -109,7 +109,6 @@ class TestHelper
|
|||
//Create all the database tables
|
||||
AirtimeInstall::createDatabaseTables($dbuser, $dbpasswd, $dbname, $dbhost);
|
||||
}
|
||||
AirtimeInstall::SetDefaultTimezone();
|
||||
}
|
||||
|
||||
public static function setupZendBootstrap()
|
||||
|
|
|
@ -178,7 +178,7 @@ class AirtimeInstall
|
|||
|
||||
echo "* Giving Apache permission to access $rp".PHP_EOL;
|
||||
$success = chgrp($rp, $CC_CONFIG["webServerUser"]);
|
||||
$success = chmod($rp, 02775);
|
||||
$success = chmod($rp, 0775);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ def test_double_duplicate_files():
|
|||
@raises(OSError)
|
||||
def test_bad_permissions_destination_dir():
|
||||
filename = os.path.basename(DEFAULT_AUDIO_FILE)
|
||||
dest_dir = u'/var/foobar'
|
||||
dest_dir = u'/sys/foobar' # /sys is using sysfs on Linux, which is unwritable
|
||||
FileMoverAnalyzer.move(DEFAULT_AUDIO_FILE, dest_dir, filename, dict())
|
||||
#Move the file back
|
||||
shutil.move(os.path.join(dest_dir, filename), DEFAULT_AUDIO_FILE)
|
||||
|
|
|
@ -283,11 +283,11 @@ def organized_path(old_path, root_path, orig_md):
|
|||
title_re = re.match(r, normal_md['MDATA_KEY_TITLE'])
|
||||
show_name = title_re.group('show')
|
||||
#date = title_re.group('date')
|
||||
yyyy, mm, _ = normal_md['MDATA_KEY_YEAR'].split('-',2)
|
||||
yyyy, mm, dd = normal_md['MDATA_KEY_YEAR'].split('-',2)
|
||||
fname_base = '%s-%s-%s.%s' % \
|
||||
(title_re.group('time'), show_name,
|
||||
normal_md['MDATA_KEY_BITRATE'], ext)
|
||||
filepath = os.path.join(root_path, yyyy, mm, fname_base)
|
||||
filepath = os.path.join(root_path, yyyy, mm, dd, fname_base)
|
||||
elif len(normal_md['MDATA_KEY_TRACKNUMBER']) == 0:
|
||||
fname = u'%s-%s.%s' % (normal_md['MDATA_KEY_TITLE'],
|
||||
normal_md['MDATA_KEY_BITRATE'], ext)
|
||||
|
|
|
@ -44,5 +44,8 @@ while not successful:
|
|||
logging.error("traceback: %s", traceback.format_exc())
|
||||
sys.exit(1)
|
||||
else:
|
||||
logging.error(str(e))
|
||||
logging.error("traceback: %s", traceback.format_exc())
|
||||
logging.info("Retrying in 3 seconds...")
|
||||
time.sleep(3)
|
||||
attempts += 1
|
||||
|
|
|
@ -3,17 +3,31 @@ from timeout import ls_timeout
|
|||
|
||||
def create_liquidsoap_annotation(media):
|
||||
# We need liq_start_next value in the annotate. That is the value that controls overlap duration of crossfade.
|
||||
return ('annotate:media_id="%s",liq_start_next="0",liq_fade_in="%s",' + \
|
||||
|
||||
filename = media['dst']
|
||||
annotation = ('annotate:media_id="%s",liq_start_next="0",liq_fade_in="%s",' + \
|
||||
'liq_fade_out="%s",liq_cue_in="%s",liq_cue_out="%s",' + \
|
||||
'schedule_table_id="%s",replay_gain="%s dB":%s') % \
|
||||
(media['id'],
|
||||
float(media['fade_in']) / 1000,
|
||||
float(media['fade_out']) / 1000,
|
||||
float(media['cue_in']),
|
||||
float(media['cue_out']),
|
||||
media['row_id'],
|
||||
media['replay_gain'],
|
||||
media['dst'])
|
||||
'schedule_table_id="%s",replay_gain="%s dB"') % \
|
||||
(media['id'],
|
||||
float(media['fade_in']) / 1000,
|
||||
float(media['fade_out']) / 1000,
|
||||
float(media['cue_in']),
|
||||
float(media['cue_out']),
|
||||
media['row_id'],
|
||||
media['replay_gain'])
|
||||
|
||||
# Override the the artist/title that Liquidsoap extracts from a file's metadata
|
||||
# with the metadata we get from Airtime. (You can modify metadata in Airtime's library,
|
||||
# which doesn't get saved back to the file.)
|
||||
if 'metadata' in media:
|
||||
if 'artist_name' in media['metadata']:
|
||||
annotation += ',artist="%s"' % (media['metadata']['artist_name'])
|
||||
if 'track_title' in media['metadata']:
|
||||
annotation += ',title="%s"' % (media['metadata']['track_title'])
|
||||
|
||||
annotation += ":" + filename
|
||||
|
||||
return annotation
|
||||
|
||||
class TelnetLiquidsoap:
|
||||
|
||||
|
|
Loading…
Reference in New Issue