Merge branch 'master' of dev.sourcefabric.org:airtime
Conflicts: install/airtime-install.php
This commit is contained in:
commit
c17ee178d1
|
@ -1,5 +1,5 @@
|
||||||
.*
|
.*
|
||||||
*.pyc
|
*.pyc
|
||||||
files/
|
/files
|
||||||
pypo/liquidsoap/liquidsoap
|
python_apps/pypo/liquidsoap/liquidsoap
|
||||||
build/build.properties
|
build/build.properties
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
require_once (__DIR__."/configs/navigation.php");
|
require_once __DIR__."/configs/navigation.php";
|
||||||
require_once (__DIR__."/configs/ACL.php");
|
require_once __DIR__."/configs/ACL.php";
|
||||||
|
|
||||||
require_once 'propel/runtime/lib/Propel.php';
|
require_once 'propel/runtime/lib/Propel.php';
|
||||||
Propel::init(__DIR__."/configs/airtime-conf.php");
|
Propel::init(__DIR__."/configs/airtime-conf.php");
|
||||||
|
@ -10,17 +10,20 @@ Propel::init(__DIR__."/configs/airtime-conf.php");
|
||||||
$tz = ini_get('date.timezone') ? ini_get('date.timezone') : 'UTC';
|
$tz = ini_get('date.timezone') ? ini_get('date.timezone') : 'UTC';
|
||||||
date_default_timezone_set($tz);
|
date_default_timezone_set($tz);
|
||||||
|
|
||||||
require_once (__DIR__."/configs/constants.php");
|
require_once __DIR__."/configs/constants.php";
|
||||||
require_once (__DIR__."/configs/conf.php");
|
require_once __DIR__."/configs/conf.php";
|
||||||
require_once 'DB.php';
|
require_once 'DB.php';
|
||||||
|
|
||||||
|
require_once 'Soundcloud.php';
|
||||||
require_once 'Playlist.php';
|
require_once 'Playlist.php';
|
||||||
require_once 'StoredFile.php';
|
require_once 'StoredFile.php';
|
||||||
require_once 'Schedule.php';
|
require_once 'Schedule.php';
|
||||||
require_once 'Shows.php';
|
require_once 'Shows.php';
|
||||||
require_once 'Users.php';
|
require_once 'Users.php';
|
||||||
|
require_once 'RabbitMq.php';
|
||||||
|
require_once __DIR__.'/controllers/plugins/RabbitMqPlugin.php';
|
||||||
|
|
||||||
global $CC_CONFIG, $CC_DBC;
|
global $CC_CONFIG, $CC_DBC;
|
||||||
$dsn = $CC_CONFIG['dsn'];
|
$dsn = $CC_CONFIG['dsn'];
|
||||||
|
|
||||||
$CC_DBC = DB::connect($dsn, FALSE);
|
$CC_DBC = DB::connect($dsn, FALSE);
|
||||||
|
@ -33,6 +36,9 @@ $CC_DBC->setFetchMode(DB_FETCHMODE_ASSOC);
|
||||||
//Zend_Session::start();
|
//Zend_Session::start();
|
||||||
Zend_Validate::setDefaultNamespaces("Zend");
|
Zend_Validate::setDefaultNamespaces("Zend");
|
||||||
|
|
||||||
|
$front = Zend_Controller_Front::getInstance();
|
||||||
|
$front->registerPlugin(new RabbitMqPlugin());
|
||||||
|
|
||||||
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
|
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
|
||||||
{
|
{
|
||||||
protected function _initDoctype()
|
protected function _initDoctype()
|
||||||
|
@ -45,9 +51,7 @@ class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
|
||||||
protected function _initHeadLink()
|
protected function _initHeadLink()
|
||||||
{
|
{
|
||||||
$view = $this->getResource('view');
|
$view = $this->getResource('view');
|
||||||
|
|
||||||
$view->headLink()->appendStylesheet('/css/redmond/jquery-ui-1.8.8.custom.css');
|
$view->headLink()->appendStylesheet('/css/redmond/jquery-ui-1.8.8.custom.css');
|
||||||
|
|
||||||
$this->view->headLink()->appendStylesheet('/css/pro_dropdown_3.css');
|
$this->view->headLink()->appendStylesheet('/css/pro_dropdown_3.css');
|
||||||
$this->view->headLink()->appendStylesheet('/css/styles.css');
|
$this->view->headLink()->appendStylesheet('/css/styles.css');
|
||||||
}
|
}
|
||||||
|
@ -64,17 +68,20 @@ class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
|
||||||
$this->view->headScript()->appendFile('/js/playlist/helperfunctions.js','text/javascript');
|
$this->view->headScript()->appendFile('/js/playlist/helperfunctions.js','text/javascript');
|
||||||
$this->view->headScript()->appendFile('/js/playlist/playlist.js','text/javascript');
|
$this->view->headScript()->appendFile('/js/playlist/playlist.js','text/javascript');
|
||||||
|
|
||||||
$view->headScript()->appendFile('/js/airtime/common/common.js','text/javascript');
|
$view->headScript()->appendFile('/js/airtime/common/common.js','text/javascript');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function _initViewHelpers(){
|
protected function _initViewHelpers()
|
||||||
|
{
|
||||||
$view = $this->getResource('view');
|
$view = $this->getResource('view');
|
||||||
$view->addHelperPath('../application/views/helpers', 'Airtime_View_Helper');
|
$view->addHelperPath('../application/views/helpers', 'Airtime_View_Helper');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function _initTitle(){
|
protected function _initTitle()
|
||||||
|
{
|
||||||
$view = $this->getResource('view');
|
$view = $this->getResource('view');
|
||||||
$view->headTitle(Application_Model_Preference::GetHeadTitle());
|
$view->headTitle(Application_Model_Preference::GetHeadTitle());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
<?php
|
<?php
|
||||||
define('AIRTIME_VERSION', '1.7.0 alpha');
|
define('AIRTIME_VERSION', '1.7.0-alpha');
|
||||||
define('AIRTIME_COPYRIGHT_DATE', '2010-2011');
|
define('AIRTIME_COPYRIGHT_DATE', '2010-2011');
|
||||||
|
define('AIRTIME_REST_VERSION', '1.1');
|
||||||
|
|
||||||
// These are the default values for the config.
|
// These are the default values for the config.
|
||||||
global $CC_CONFIG;
|
global $CC_CONFIG;
|
||||||
$values = load_airtime_config();
|
$values = load_airtime_config();
|
||||||
|
|
||||||
// **********************************
|
// **********************************
|
||||||
// ***** START CUSTOMIZING HERE *****
|
// ***** START CUSTOMIZING HERE *****
|
||||||
// **********************************
|
// **********************************
|
||||||
|
|
||||||
// Set the location where you want to store all of your audio files.
|
// Set the location where you want to store all of your audio files.
|
||||||
//
|
//
|
||||||
|
@ -25,10 +26,16 @@ $CC_CONFIG = array(
|
||||||
// Name of the web server user
|
// Name of the web server user
|
||||||
'webServerUser' => 'www-data',
|
'webServerUser' => 'www-data',
|
||||||
|
|
||||||
// ***********************************************************************
|
'rabbitmq' => array("host" => "127.0.0.1",
|
||||||
|
"port" => "5672",
|
||||||
|
"user" => "guest",
|
||||||
|
"password" => "guest",
|
||||||
|
"vhost" => "/"),
|
||||||
|
|
||||||
|
// ***********************************************************************
|
||||||
// STOP CUSTOMIZING HERE
|
// STOP CUSTOMIZING HERE
|
||||||
//
|
//
|
||||||
// You don't need to touch anything below this point.
|
// You don't need to touch anything below this point.
|
||||||
// ***********************************************************************
|
// ***********************************************************************
|
||||||
|
|
||||||
'baseFilesDir' => $baseFilesDir,
|
'baseFilesDir' => $baseFilesDir,
|
||||||
|
@ -46,6 +53,9 @@ $CC_CONFIG = array(
|
||||||
'apiKey' => $values['api_key'],
|
'apiKey' => $values['api_key'],
|
||||||
'apiPath' => '/api/',
|
'apiPath' => '/api/',
|
||||||
|
|
||||||
|
'soundcloud-client-id' => '2CLCxcSXYzx7QhhPVHN4A',
|
||||||
|
'soundcloud-client-secret' => 'pZ7beWmF06epXLHVUP1ufOg2oEnIt9XhE8l8xt0bBs',
|
||||||
|
|
||||||
"rootDir" => __DIR__."/../..",
|
"rootDir" => __DIR__."/../..",
|
||||||
'pearPath' => dirname(__FILE__).'/../../library/pear',
|
'pearPath' => dirname(__FILE__).'/../../library/pear',
|
||||||
'zendPath' => dirname(__FILE__).'/../../library/Zend',
|
'zendPath' => dirname(__FILE__).'/../../library/Zend',
|
||||||
|
@ -55,26 +65,26 @@ $CC_CONFIG = array(
|
||||||
//'AdminsGr' => 'Admins',
|
//'AdminsGr' => 'Admins',
|
||||||
|
|
||||||
// name of station preferences group
|
// name of station preferences group
|
||||||
'StationPrefsGr'=> 'StationPrefs',
|
// 'StationPrefsGr'=> 'StationPrefs',
|
||||||
|
|
||||||
// name of 'all users' group
|
// name of 'all users' group
|
||||||
//'AllGr' => 'All',
|
//'AllGr' => 'All',
|
||||||
|
|
||||||
/* ==================================== application-specific configuration */
|
/* ==================================== application-specific configuration */
|
||||||
'objtypes' => array(
|
// 'objtypes' => array(
|
||||||
'Storage' => array(/*'Folder',*/ 'File' /*, 'Replica'*/),
|
// 'Storage' => array(/*'Folder',*/ 'File' /*, 'Replica'*/),
|
||||||
'File' => array(),
|
// 'File' => array(),
|
||||||
'audioclip' => array(),
|
// 'audioclip' => array(),
|
||||||
'playlist' => array(),
|
// 'playlist' => array(),
|
||||||
),
|
// ),
|
||||||
'allowedActions'=> array(
|
// 'allowedActions'=> array(
|
||||||
'File' => array('editPrivs', 'write', 'read'),
|
// 'File' => array('editPrivs', 'write', 'read'),
|
||||||
'audioclip' => array('editPrivs', 'write', 'read'),
|
// 'audioclip' => array('editPrivs', 'write', 'read'),
|
||||||
'playlist' => array('editPrivs', 'write', 'read'),
|
// 'playlist' => array('editPrivs', 'write', 'read'),
|
||||||
),
|
// ),
|
||||||
'allActions' => array(
|
// 'allActions' => array(
|
||||||
'editPrivs', 'write', 'read', 'subjects'
|
// 'editPrivs', 'write', 'read', 'subjects'
|
||||||
),
|
// ),
|
||||||
|
|
||||||
/* =================================================== cron configuration */
|
/* =================================================== cron configuration */
|
||||||
'cronUserName' => 'www-data',
|
'cronUserName' => 'www-data',
|
||||||
|
@ -82,7 +92,7 @@ $CC_CONFIG = array(
|
||||||
'lockfile' => dirname(__FILE__).'/stor/buffer/cron.lock',
|
'lockfile' => dirname(__FILE__).'/stor/buffer/cron.lock',
|
||||||
'cronfile' => dirname(__FILE__).'/cron/croncall.php',
|
'cronfile' => dirname(__FILE__).'/cron/croncall.php',
|
||||||
'paramdir' => dirname(__FILE__).'/cron/params',
|
'paramdir' => dirname(__FILE__).'/cron/params',
|
||||||
'systemPrefId' => "0", // ID for system prefs in prefs table
|
// 'systemPrefId' => "0", // ID for system prefs in prefs table
|
||||||
);
|
);
|
||||||
|
|
||||||
// Add database table names
|
// Add database table names
|
||||||
|
@ -94,10 +104,8 @@ $CC_CONFIG['permTable'] = $CC_CONFIG['tblNamePrefix'].'perms';
|
||||||
$CC_CONFIG['sessTable'] = $CC_CONFIG['tblNamePrefix'].'sess';
|
$CC_CONFIG['sessTable'] = $CC_CONFIG['tblNamePrefix'].'sess';
|
||||||
$CC_CONFIG['subjTable'] = $CC_CONFIG['tblNamePrefix'].'subjs';
|
$CC_CONFIG['subjTable'] = $CC_CONFIG['tblNamePrefix'].'subjs';
|
||||||
$CC_CONFIG['smembTable'] = $CC_CONFIG['tblNamePrefix'].'smemb';
|
$CC_CONFIG['smembTable'] = $CC_CONFIG['tblNamePrefix'].'smemb';
|
||||||
$CC_CONFIG['transTable'] = $CC_CONFIG['tblNamePrefix'].'trans';
|
|
||||||
$CC_CONFIG['prefTable'] = $CC_CONFIG['tblNamePrefix'].'pref';
|
$CC_CONFIG['prefTable'] = $CC_CONFIG['tblNamePrefix'].'pref';
|
||||||
$CC_CONFIG['scheduleTable'] = $CC_CONFIG['tblNamePrefix'].'schedule';
|
$CC_CONFIG['scheduleTable'] = $CC_CONFIG['tblNamePrefix'].'schedule';
|
||||||
$CC_CONFIG['backupTable'] = $CC_CONFIG['tblNamePrefix'].'backup';
|
|
||||||
$CC_CONFIG['playListTimeView'] = $CC_CONFIG['tblNamePrefix'].'playlisttimes';
|
$CC_CONFIG['playListTimeView'] = $CC_CONFIG['tblNamePrefix'].'playlisttimes';
|
||||||
$CC_CONFIG['showSchedule'] = $CC_CONFIG['tblNamePrefix'].'show_schedule';
|
$CC_CONFIG['showSchedule'] = $CC_CONFIG['tblNamePrefix'].'show_schedule';
|
||||||
$CC_CONFIG['showDays'] = $CC_CONFIG['tblNamePrefix'].'show_days';
|
$CC_CONFIG['showDays'] = $CC_CONFIG['tblNamePrefix'].'show_days';
|
||||||
|
@ -106,16 +114,15 @@ $CC_CONFIG['showInstances'] = $CC_CONFIG['tblNamePrefix'].'show_instances';
|
||||||
|
|
||||||
$CC_CONFIG['playListSequence'] = $CC_CONFIG['playListTable'].'_id';
|
$CC_CONFIG['playListSequence'] = $CC_CONFIG['playListTable'].'_id';
|
||||||
$CC_CONFIG['filesSequence'] = $CC_CONFIG['filesTable'].'_id';
|
$CC_CONFIG['filesSequence'] = $CC_CONFIG['filesTable'].'_id';
|
||||||
$CC_CONFIG['transSequence'] = $CC_CONFIG['transTable'].'_id';
|
|
||||||
$CC_CONFIG['prefSequence'] = $CC_CONFIG['prefTable'].'_id';
|
$CC_CONFIG['prefSequence'] = $CC_CONFIG['prefTable'].'_id';
|
||||||
$CC_CONFIG['permSequence'] = $CC_CONFIG['permTable'].'_id';
|
$CC_CONFIG['permSequence'] = $CC_CONFIG['permTable'].'_id';
|
||||||
$CC_CONFIG['subjSequence'] = $CC_CONFIG['subjTable'].'_id';
|
$CC_CONFIG['subjSequence'] = $CC_CONFIG['subjTable'].'_id';
|
||||||
$CC_CONFIG['smembSequence'] = $CC_CONFIG['smembTable'].'_id';
|
$CC_CONFIG['smembSequence'] = $CC_CONFIG['smembTable'].'_id';
|
||||||
|
|
||||||
// System users/groups - they cannot be deleted
|
// System users/groups - they cannot be deleted
|
||||||
$CC_CONFIG['sysSubjs'] = array(
|
//$CC_CONFIG['sysSubjs'] = array(
|
||||||
'root', /*$CC_CONFIG['AdminsGr'],*/ /*$CC_CONFIG['AllGr'],*/ $CC_CONFIG['StationPrefsGr']
|
// 'root', /*$CC_CONFIG['AdminsGr'],*/ /*$CC_CONFIG['AllGr'],*/ $CC_CONFIG['StationPrefsGr']
|
||||||
);
|
//);
|
||||||
|
|
||||||
// Add libs to the PHP path
|
// Add libs to the PHP path
|
||||||
$old_include_path = get_include_path();
|
$old_include_path = get_include_path();
|
||||||
|
@ -125,9 +132,9 @@ set_include_path('.'.PATH_SEPARATOR.$CC_CONFIG['pearPath']
|
||||||
|
|
||||||
function load_airtime_config(){
|
function load_airtime_config(){
|
||||||
$ini_array = parse_ini_file(dirname(__FILE__).'/../../build/airtime.conf', true);
|
$ini_array = parse_ini_file(dirname(__FILE__).'/../../build/airtime.conf', true);
|
||||||
|
|
||||||
return array(
|
return array(
|
||||||
'database' => array(
|
'database' => array(
|
||||||
'username' => $ini_array['database']['dbuser'],
|
'username' => $ini_array['database']['dbuser'],
|
||||||
'password' => $ini_array['database']['dbpass'],
|
'password' => $ini_array['database']['dbpass'],
|
||||||
'hostspec' => $ini_array['database']['host'],
|
'hostspec' => $ini_array['database']['host'],
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Navigation container (config/array)
|
* Navigation container (config/array)
|
||||||
|
|
||||||
* Each element in the array will be passed to
|
* Each element in the array will be passed to
|
||||||
* Zend_Navigation_Page::factory() when constructing
|
* Zend_Navigation_Page::factory() when constructing
|
||||||
* the navigation container below.
|
* the navigation container below.
|
||||||
|
@ -16,7 +16,7 @@ $pages = array(
|
||||||
'resource' => 'nowplaying'
|
'resource' => 'nowplaying'
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'label' => 'Add Audio',
|
'label' => 'Add Media',
|
||||||
'module' => 'default',
|
'module' => 'default',
|
||||||
'controller' => 'Plupload',
|
'controller' => 'Plupload',
|
||||||
'action' => 'plupload',
|
'action' => 'plupload',
|
||||||
|
@ -51,7 +51,7 @@ $pages = array(
|
||||||
'module' => 'default',
|
'module' => 'default',
|
||||||
'controller' => 'user',
|
'controller' => 'user',
|
||||||
'action' => 'add-user',
|
'action' => 'add-user',
|
||||||
'resource' => 'user'
|
'resource' => 'user'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
@ -64,10 +64,10 @@ $pages = array(
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// Create container from array
|
// Create container from array
|
||||||
$container = new Zend_Navigation($pages);
|
$container = new Zend_Navigation($pages);
|
||||||
$container->id = "nav";
|
$container->id = "nav";
|
||||||
|
|
||||||
//store it in the registry:
|
//store it in the registry:
|
||||||
Zend_Registry::set('Zend_Navigation', $container);
|
Zend_Registry::set('Zend_Navigation', $container);
|
||||||
|
|
|
@ -6,8 +6,10 @@ class ApiController extends Zend_Controller_Action
|
||||||
public function init()
|
public function init()
|
||||||
{
|
{
|
||||||
/* Initialize action controller here */
|
/* Initialize action controller here */
|
||||||
$ajaxContext = $this->_helper->getHelper('AjaxContext');
|
$context = $this->_helper->getHelper('contextSwitch');
|
||||||
$ajaxContext->addActionContext('version', 'json')
|
$context->addActionContext('version', 'json')
|
||||||
|
->addActionContext('recorded-shows', 'json')
|
||||||
|
->addActionContext('upload-recorded', 'json')
|
||||||
->initContext();
|
->initContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +26,7 @@ class ApiController extends Zend_Controller_Action
|
||||||
* in application/conf.php
|
* in application/conf.php
|
||||||
*
|
*
|
||||||
* @return void
|
* @return void
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public function versionAction()
|
public function versionAction()
|
||||||
{
|
{
|
||||||
|
@ -101,6 +103,29 @@ class ApiController extends Zend_Controller_Action
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function liveInfoAction(){
|
||||||
|
global $CC_CONFIG;
|
||||||
|
|
||||||
|
// disable the view and the layout
|
||||||
|
$this->view->layout()->disableLayout();
|
||||||
|
$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).')';
|
||||||
|
}
|
||||||
|
|
||||||
public function scheduleAction()
|
public function scheduleAction()
|
||||||
{
|
{
|
||||||
global $CC_CONFIG;
|
global $CC_CONFIG;
|
||||||
|
@ -110,6 +135,7 @@ class ApiController extends Zend_Controller_Action
|
||||||
$this->_helper->viewRenderer->setNoRender(true);
|
$this->_helper->viewRenderer->setNoRender(true);
|
||||||
|
|
||||||
$api_key = $this->_getParam('api_key');
|
$api_key = $this->_getParam('api_key');
|
||||||
|
|
||||||
if(!in_array($api_key, $CC_CONFIG["apiKey"]))
|
if(!in_array($api_key, $CC_CONFIG["apiKey"]))
|
||||||
{
|
{
|
||||||
header('HTTP/1.0 401 Unauthorized');
|
header('HTTP/1.0 401 Unauthorized');
|
||||||
|
@ -119,18 +145,10 @@ class ApiController extends Zend_Controller_Action
|
||||||
|
|
||||||
PEAR::setErrorHandling(PEAR_ERROR_RETURN);
|
PEAR::setErrorHandling(PEAR_ERROR_RETURN);
|
||||||
|
|
||||||
$from = $this->_getParam("from");
|
$result = Schedule::GetScheduledPlaylists();
|
||||||
$to = $this->_getParam("to");
|
echo json_encode($result);
|
||||||
if (Schedule::ValidPypoTimeFormat($from) && Schedule::ValidPypoTimeFormat($to)) {
|
|
||||||
$result = Schedule::ExportRangeAsJson($from, $to);
|
|
||||||
$result['stream_metadata'] = array();
|
|
||||||
$result['stream_metadata']['format'] = Application_Model_Preference::GetStreamLabelFormat();
|
|
||||||
$result['stream_metadata']['station_name'] = Application_Model_Preference::GetStationName();
|
|
||||||
echo json_encode($result);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function notifyMediaItemStartPlayAction()
|
public function notifyMediaItemStartPlayAction()
|
||||||
{
|
{
|
||||||
global $CC_CONFIG;
|
global $CC_CONFIG;
|
||||||
|
@ -197,5 +215,53 @@ class ApiController extends Zend_Controller_Action
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function recordedShowsAction()
|
||||||
|
{
|
||||||
|
global $CC_CONFIG;
|
||||||
|
|
||||||
|
$api_key = $this->_getParam('api_key');
|
||||||
|
if (!in_array($api_key, $CC_CONFIG["apiKey"]))
|
||||||
|
{
|
||||||
|
header('HTTP/1.0 401 Unauthorized');
|
||||||
|
print 'You are not allowed to access this resource.';
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$today_timestamp = date("Y-m-d H:i:s");
|
||||||
|
$this->view->shows = Show::getShows($today_timestamp, null, $excludeInstance=NULL, $onlyRecord=TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function uploadRecordedAction()
|
||||||
|
{
|
||||||
|
global $CC_CONFIG;
|
||||||
|
|
||||||
|
$api_key = $this->_getParam('api_key');
|
||||||
|
if (!in_array($api_key, $CC_CONFIG["apiKey"]))
|
||||||
|
{
|
||||||
|
header('HTTP/1.0 401 Unauthorized');
|
||||||
|
print 'You are not allowed to access this resource.';
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$upload_dir = ini_get("upload_tmp_dir");
|
||||||
|
$file = StoredFile::uploadFile($upload_dir);
|
||||||
|
|
||||||
|
$show_instance = $this->_getParam('show_instance');
|
||||||
|
|
||||||
|
$show_inst = new ShowInstance($show_instance);
|
||||||
|
$show_inst->setRecordedFile($file->getId());
|
||||||
|
|
||||||
|
if(Application_Model_Preference::GetDoSoundCloudUpload())
|
||||||
|
{
|
||||||
|
$show = new Show($show_inst->getShowId());
|
||||||
|
$description = $show->getDescription();
|
||||||
|
|
||||||
|
$soundcloud = new ATSoundcloud();
|
||||||
|
$soundcloud->uploadTrack($file->getRealFilePath(), $file->getName(), $description);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->view->id = $file->getId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,144 +11,6 @@ class PluploadController extends Zend_Controller_Action
|
||||||
->initContext();
|
->initContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function upload($targetDir)
|
|
||||||
{
|
|
||||||
// HTTP headers for no cache etc
|
|
||||||
header('Content-type: text/plain; charset=UTF-8');
|
|
||||||
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
|
|
||||||
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
|
|
||||||
header("Cache-Control: no-store, no-cache, must-revalidate");
|
|
||||||
header("Cache-Control: post-check=0, pre-check=0", false);
|
|
||||||
header("Pragma: no-cache");
|
|
||||||
|
|
||||||
// Settings
|
|
||||||
//$targetDir = ini_get("upload_tmp_dir"); //. DIRECTORY_SEPARATOR . "plupload";
|
|
||||||
$cleanupTargetDir = false; // Remove old files
|
|
||||||
$maxFileAge = 60 * 60; // Temp file age in seconds
|
|
||||||
|
|
||||||
// 5 minutes execution time
|
|
||||||
@set_time_limit(5 * 60);
|
|
||||||
// usleep(5000);
|
|
||||||
|
|
||||||
// Get parameters
|
|
||||||
$chunk = isset($_REQUEST["chunk"]) ? $_REQUEST["chunk"] : 0;
|
|
||||||
$chunks = isset($_REQUEST["chunks"]) ? $_REQUEST["chunks"] : 0;
|
|
||||||
$fileName = isset($_REQUEST["name"]) ? $_REQUEST["name"] : '';
|
|
||||||
|
|
||||||
// Clean the fileName for security reasons
|
|
||||||
//$fileName = preg_replace('/[^\w\._]+/', '', $fileName);
|
|
||||||
|
|
||||||
// Create target dir
|
|
||||||
if (!file_exists($targetDir))
|
|
||||||
@mkdir($targetDir);
|
|
||||||
|
|
||||||
// Remove old temp files
|
|
||||||
if (is_dir($targetDir) && ($dir = opendir($targetDir))) {
|
|
||||||
while (($file = readdir($dir)) !== false) {
|
|
||||||
$filePath = $targetDir . DIRECTORY_SEPARATOR . $file;
|
|
||||||
|
|
||||||
// Remove temp files if they are older than the max age
|
|
||||||
if (preg_match('/\.tmp$/', $file) && (filemtime($filePath) < time() - $maxFileAge))
|
|
||||||
@unlink($filePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
closedir($dir);
|
|
||||||
} else
|
|
||||||
die('{"jsonrpc" : "2.0", "error" : {"code": 100, "message": "Failed to open temp directory."}, "id" : "id"}');
|
|
||||||
|
|
||||||
// Look for the content type header
|
|
||||||
if (isset($_SERVER["HTTP_CONTENT_TYPE"]))
|
|
||||||
$contentType = $_SERVER["HTTP_CONTENT_TYPE"];
|
|
||||||
|
|
||||||
if (isset($_SERVER["CONTENT_TYPE"]))
|
|
||||||
$contentType = $_SERVER["CONTENT_TYPE"];
|
|
||||||
|
|
||||||
if (strpos($contentType, "multipart") !== false) {
|
|
||||||
if (isset($_FILES['file']['tmp_name']) && is_uploaded_file($_FILES['file']['tmp_name'])) {
|
|
||||||
// Open temp file
|
|
||||||
$out = fopen($targetDir . DIRECTORY_SEPARATOR . $fileName, $chunk == 0 ? "wb" : "ab");
|
|
||||||
if ($out) {
|
|
||||||
// Read binary input stream and append it to temp file
|
|
||||||
$in = fopen($_FILES['file']['tmp_name'], "rb");
|
|
||||||
|
|
||||||
if ($in) {
|
|
||||||
while ($buff = fread($in, 4096))
|
|
||||||
fwrite($out, $buff);
|
|
||||||
} else
|
|
||||||
die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "Failed to open input stream."}, "id" : "id"}');
|
|
||||||
|
|
||||||
fclose($out);
|
|
||||||
unlink($_FILES['file']['tmp_name']);
|
|
||||||
} else
|
|
||||||
die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to open output stream."}, "id" : "id"}');
|
|
||||||
} else
|
|
||||||
die('{"jsonrpc" : "2.0", "error" : {"code": 103, "message": "Failed to move uploaded file."}, "id" : "id"}');
|
|
||||||
} else {
|
|
||||||
// Open temp file
|
|
||||||
$out = fopen($targetDir . DIRECTORY_SEPARATOR . $fileName, $chunk == 0 ? "wb" : "ab");
|
|
||||||
if ($out) {
|
|
||||||
// Read binary input stream and append it to temp file
|
|
||||||
$in = fopen("php://input", "rb");
|
|
||||||
|
|
||||||
if ($in) {
|
|
||||||
while ($buff = fread($in, 4096))
|
|
||||||
fwrite($out, $buff);
|
|
||||||
} else
|
|
||||||
die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "Failed to open input stream."}, "id" : "id"}');
|
|
||||||
|
|
||||||
fclose($out);
|
|
||||||
} else
|
|
||||||
die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to open output stream."}, "id" : "id"}');
|
|
||||||
}
|
|
||||||
|
|
||||||
$audio_file = $targetDir . DIRECTORY_SEPARATOR . $fileName;
|
|
||||||
|
|
||||||
$md5 = md5_file($audio_file);
|
|
||||||
$duplicate = StoredFile::RecallByMd5($md5);
|
|
||||||
if ($duplicate) {
|
|
||||||
if (PEAR::isError($duplicate)) {
|
|
||||||
die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": ' . $duplicate->getMessage() .'}}');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$duplicateName = $duplicate->getMetadataValue(UI_MDATA_KEY_TITLE);
|
|
||||||
die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "An identical audioclip named ' . $duplicateName . ' already exists in the storage server."}}');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$metadata = Metadata::LoadFromFile($audio_file);
|
|
||||||
|
|
||||||
if (PEAR::isError($metadata)) {
|
|
||||||
die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": ' + $metadata->getMessage() + '}}');
|
|
||||||
}
|
|
||||||
|
|
||||||
// #2196 no id tag -> use the original filename
|
|
||||||
if (basename($audio_file) == $metadata[UI_MDATA_KEY_TITLE]) {
|
|
||||||
$metadata[UI_MDATA_KEY_TITLE] = basename($audio_file);
|
|
||||||
$metadata[UI_MDATA_KEY_FILENAME] = basename($audio_file);
|
|
||||||
}
|
|
||||||
|
|
||||||
// setMetadataBatch doesnt like these values
|
|
||||||
unset($metadata['audio']);
|
|
||||||
unset($metadata['playtime_seconds']);
|
|
||||||
|
|
||||||
$values = array(
|
|
||||||
"filename" => basename($audio_file),
|
|
||||||
"filepath" => $audio_file,
|
|
||||||
"filetype" => "audioclip",
|
|
||||||
"mime" => $metadata[UI_MDATA_KEY_FORMAT],
|
|
||||||
"md5" => $md5
|
|
||||||
);
|
|
||||||
$storedFile = StoredFile::Insert($values);
|
|
||||||
|
|
||||||
if (PEAR::isError($storedFile)) {
|
|
||||||
die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": ' + $storedFile->getMessage() + '}}');
|
|
||||||
}
|
|
||||||
|
|
||||||
$storedFile->setMetadataBatch($metadata);
|
|
||||||
|
|
||||||
// Return JSON-RPC response
|
|
||||||
die('{"jsonrpc" : "2.0", "id" : '.$storedFile->getId().' }');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function indexAction()
|
public function indexAction()
|
||||||
{
|
{
|
||||||
|
@ -158,13 +20,9 @@ class PluploadController extends Zend_Controller_Action
|
||||||
public function uploadAction()
|
public function uploadAction()
|
||||||
{
|
{
|
||||||
$upload_dir = ini_get("upload_tmp_dir") . DIRECTORY_SEPARATOR . "plupload";
|
$upload_dir = ini_get("upload_tmp_dir") . DIRECTORY_SEPARATOR . "plupload";
|
||||||
$this->upload($upload_dir);
|
$file = StoredFile::uploadFile($upload_dir);
|
||||||
}
|
|
||||||
|
|
||||||
public function uploadRecordedAction()
|
die('{"jsonrpc" : "2.0", "id" : '.$file->getId().' }');
|
||||||
{
|
|
||||||
$upload_dir = ini_get("upload_tmp_dir");
|
|
||||||
$this->upload($upload_dir);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function pluploadAction()
|
public function pluploadAction()
|
||||||
|
|
|
@ -29,7 +29,11 @@ class PreferenceController extends Zend_Controller_Action
|
||||||
$values = $form->getValues();
|
$values = $form->getValues();
|
||||||
Application_Model_Preference::SetHeadTitle($values["stationName"], $this->view);
|
Application_Model_Preference::SetHeadTitle($values["stationName"], $this->view);
|
||||||
Application_Model_Preference::SetDefaultFade($values["stationDefaultFade"]);
|
Application_Model_Preference::SetDefaultFade($values["stationDefaultFade"]);
|
||||||
Application_Model_Preference::SetStreamLabelFormat($values["streamFormat"]);
|
Application_Model_Preference::SetStreamLabelFormat($values["streamFormat"]);
|
||||||
|
Application_Model_Preference::SetDoSoundCloudUpload($values["UseSoundCloud"]);
|
||||||
|
Application_Model_Preference::SetSoundCloudUser($values["SoundCloudUser"]);
|
||||||
|
Application_Model_Preference::SetSoundCloudPassword($values["SoundCloudPassword"]);
|
||||||
|
Application_Model_Preference::SetSoundCloudTags($values["SoundCloudTags"]);
|
||||||
|
|
||||||
$this->view->statusMsg = "Preferences Updated.";
|
$this->view->statusMsg = "Preferences Updated.";
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
class RecorderController extends Zend_Controller_Action
|
|
||||||
{
|
|
||||||
|
|
||||||
public function init()
|
|
||||||
{
|
|
||||||
$ajaxContext = $this->_helper->getHelper('contextSwitch');
|
|
||||||
$ajaxContext->addActionContext('get-show-schedule', 'json')
|
|
||||||
->addActionContext('get-uploaded-file', 'json')
|
|
||||||
->initContext();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function indexAction()
|
|
||||||
{
|
|
||||||
// action body
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getShowScheduleAction()
|
|
||||||
{
|
|
||||||
$today_timestamp = date("Y-m-d H:i:s");
|
|
||||||
$this->view->shows = Show::getShows($today_timestamp, null, $excludeInstance=NULL, $onlyRecord=TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,9 @@ class ScheduleController extends Zend_Controller_Action
|
||||||
->addActionContext('schedule-show-dialog', 'json')
|
->addActionContext('schedule-show-dialog', 'json')
|
||||||
->addActionContext('show-content-dialog', 'json')
|
->addActionContext('show-content-dialog', 'json')
|
||||||
->addActionContext('clear-show', 'json')
|
->addActionContext('clear-show', 'json')
|
||||||
->addActionContext('get-current-playlist', 'json')
|
->addActionContext('get-current-playlist', 'json')
|
||||||
->addActionContext('find-playlists', 'json')
|
->addActionContext('find-playlists', 'json')
|
||||||
->addActionContext('remove-group', 'json')
|
->addActionContext('remove-group', 'json')
|
||||||
->addActionContext('edit-show', 'json')
|
->addActionContext('edit-show', 'json')
|
||||||
->addActionContext('add-show', 'json')
|
->addActionContext('add-show', 'json')
|
||||||
->addActionContext('cancel-show', 'json')
|
->addActionContext('cancel-show', 'json')
|
||||||
|
@ -64,7 +64,7 @@ class ScheduleController extends Zend_Controller_Action
|
||||||
$formRepeats->removeDecorator('DtDdWrapper');
|
$formRepeats->removeDecorator('DtDdWrapper');
|
||||||
$formStyle->removeDecorator('DtDdWrapper');
|
$formStyle->removeDecorator('DtDdWrapper');
|
||||||
$formRecord->removeDecorator('DtDdWrapper');
|
$formRecord->removeDecorator('DtDdWrapper');
|
||||||
|
|
||||||
|
|
||||||
$this->view->what = $formWhat;
|
$this->view->what = $formWhat;
|
||||||
$this->view->when = $formWhen;
|
$this->view->when = $formWhen;
|
||||||
|
@ -84,7 +84,7 @@ class ScheduleController extends Zend_Controller_Action
|
||||||
{
|
{
|
||||||
$start = $this->_getParam('start', null);
|
$start = $this->_getParam('start', null);
|
||||||
$end = $this->_getParam('end', null);
|
$end = $this->_getParam('end', null);
|
||||||
|
|
||||||
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
||||||
$user = new User($userInfo->id);
|
$user = new User($userInfo->id);
|
||||||
if($user->isAdmin())
|
if($user->isAdmin())
|
||||||
|
@ -111,6 +111,7 @@ class ScheduleController extends Zend_Controller_Action
|
||||||
|
|
||||||
if(isset($error))
|
if(isset($error))
|
||||||
$this->view->error = $error;
|
$this->view->error = $error;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function resizeShowAction()
|
public function resizeShowAction()
|
||||||
|
@ -134,7 +135,7 @@ class ScheduleController extends Zend_Controller_Action
|
||||||
public function deleteShowAction()
|
public function deleteShowAction()
|
||||||
{
|
{
|
||||||
$showInstanceId = $this->_getParam('id');
|
$showInstanceId = $this->_getParam('id');
|
||||||
|
|
||||||
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
||||||
$user = new User($userInfo->id);
|
$user = new User($userInfo->id);
|
||||||
|
|
||||||
|
@ -158,41 +159,41 @@ class ScheduleController extends Zend_Controller_Action
|
||||||
if (strtotime($today_timestamp) < strtotime($show->getShowStart())) {
|
if (strtotime($today_timestamp) < strtotime($show->getShowStart())) {
|
||||||
|
|
||||||
if (($user->isHost($show->getShowId()) || $user->isAdmin()) && !$show->isRecorded() && !$show->isRebroadcast()) {
|
if (($user->isHost($show->getShowId()) || $user->isAdmin()) && !$show->isRecorded() && !$show->isRebroadcast()) {
|
||||||
|
|
||||||
$menu[] = array('action' => array('type' => 'ajax', 'url' => '/Schedule/schedule-show-dialog'.$params,
|
|
||||||
'callback' => 'window["buildScheduleDialog"]'), 'title' => 'Add Content');
|
|
||||||
|
|
||||||
$menu[] = array('action' => array('type' => 'ajax', 'url' => '/Schedule/clear-show'.$params,
|
$menu[] = array('action' => array('type' => 'ajax', 'url' => '/Schedule/schedule-show-dialog'.$params,
|
||||||
|
'callback' => 'window["buildScheduleDialog"]'), 'title' => 'Add / Remove Content');
|
||||||
|
|
||||||
|
$menu[] = array('action' => array('type' => 'ajax', 'url' => '/Schedule/clear-show'.$params,
|
||||||
'callback' => 'window["scheduleRefetchEvents"]'), 'title' => 'Remove All Content');
|
'callback' => 'window["scheduleRefetchEvents"]'), 'title' => 'Remove All Content');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!$show->isRecorded()) {
|
if(!$show->isRecorded()) {
|
||||||
$menu[] = array('action' => array('type' => 'ajax', 'url' => '/Schedule/show-content-dialog'.$params,
|
$menu[] = array('action' => array('type' => 'ajax', 'url' => '/Schedule/show-content-dialog'.$params,
|
||||||
'callback' => 'window["buildContentDialog"]'), 'title' => 'Show Content');
|
'callback' => 'window["buildContentDialog"]'), 'title' => 'Show Content');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (strtotime($show->getShowStart()) <= strtotime($today_timestamp) &&
|
if (strtotime($show->getShowStart()) <= strtotime($today_timestamp) &&
|
||||||
strtotime($today_timestamp) < strtotime($show->getShowEnd())) {
|
strtotime($today_timestamp) < strtotime($show->getShowEnd())) {
|
||||||
$menu[] = array('action' => array('type' => 'fn',
|
$menu[] = array('action' => array('type' => 'fn',
|
||||||
//'url' => '/Schedule/cancel-current-show'.$params,
|
//'url' => '/Schedule/cancel-current-show'.$params,
|
||||||
'callback' => "window['confirmCancelShow']($id)"),
|
'callback' => "window['confirmCancelShow']($id)"),
|
||||||
'title' => 'Cancel Current Show');
|
'title' => 'Cancel Current Show');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strtotime($today_timestamp) < strtotime($show->getShowStart())) {
|
if (strtotime($today_timestamp) < strtotime($show->getShowStart())) {
|
||||||
|
|
||||||
if ($user->isAdmin()) {
|
if ($user->isAdmin()) {
|
||||||
|
|
||||||
$menu[] = array('action' => array('type' => 'ajax', 'url' => '/Schedule/delete-show'.$params,
|
$menu[] = array('action' => array('type' => 'ajax', 'url' => '/Schedule/delete-show'.$params,
|
||||||
'callback' => 'window["scheduleRefetchEvents"]'), 'title' => 'Delete This Instance');
|
'callback' => 'window["scheduleRefetchEvents"]'), 'title' => 'Delete This Instance');
|
||||||
$menu[] = array('action' => array('type' => 'ajax', 'url' => '/Schedule/cancel-show'.$params,
|
$menu[] = array('action' => array('type' => 'ajax', 'url' => '/Schedule/cancel-show'.$params,
|
||||||
'callback' => 'window["scheduleRefetchEvents"]'), 'title' => 'Delete This Instance and All Following');
|
'callback' => 'window["scheduleRefetchEvents"]'), 'title' => 'Delete This Instance and All Following');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//returns format jjmenu is looking for.
|
//returns format jjmenu is looking for.
|
||||||
die(json_encode($menu));
|
die(json_encode($menu));
|
||||||
}
|
}
|
||||||
|
@ -219,7 +220,7 @@ class ScheduleController extends Zend_Controller_Action
|
||||||
$this->view->timeFilled = $show->getTimeScheduled();
|
$this->view->timeFilled = $show->getTimeScheduled();
|
||||||
$this->view->percentFilled = $show->getPercentScheduled();
|
$this->view->percentFilled = $show->getPercentScheduled();
|
||||||
|
|
||||||
$this->view->chosen = $this->view->render('schedule/scheduled-content.phtml');
|
$this->view->chosen = $this->view->render('schedule/scheduled-content.phtml');
|
||||||
unset($this->view->showContent);
|
unset($this->view->showContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,7 +243,7 @@ class ScheduleController extends Zend_Controller_Action
|
||||||
public function findPlaylistsAction()
|
public function findPlaylistsAction()
|
||||||
{
|
{
|
||||||
$post = $this->getRequest()->getPost();
|
$post = $this->getRequest()->getPost();
|
||||||
|
|
||||||
$show = new ShowInstance($this->sched_sess->showInstanceId);
|
$show = new ShowInstance($this->sched_sess->showInstanceId);
|
||||||
$playlists = $show->searchPlaylistsForShow($post);
|
$playlists = $show->searchPlaylistsForShow($post);
|
||||||
|
|
||||||
|
@ -267,7 +268,7 @@ class ScheduleController extends Zend_Controller_Action
|
||||||
$this->view->showContent = $show->getShowContent();
|
$this->view->showContent = $show->getShowContent();
|
||||||
$this->view->timeFilled = $show->getTimeScheduled();
|
$this->view->timeFilled = $show->getTimeScheduled();
|
||||||
$this->view->percentFilled = $show->getPercentScheduled();
|
$this->view->percentFilled = $show->getPercentScheduled();
|
||||||
$this->view->chosen = $this->view->render('schedule/scheduled-content.phtml');
|
$this->view->chosen = $this->view->render('schedule/scheduled-content.phtml');
|
||||||
unset($this->view->showContent);
|
unset($this->view->showContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,7 +276,7 @@ class ScheduleController extends Zend_Controller_Action
|
||||||
{
|
{
|
||||||
$showInstanceId = $this->_getParam('id');
|
$showInstanceId = $this->_getParam('id');
|
||||||
$this->sched_sess->showInstanceId = $showInstanceId;
|
$this->sched_sess->showInstanceId = $showInstanceId;
|
||||||
|
|
||||||
$show = new ShowInstance($showInstanceId);
|
$show = new ShowInstance($showInstanceId);
|
||||||
$start_timestamp = $show->getShowStart();
|
$start_timestamp = $show->getShowStart();
|
||||||
$end_timestamp = $show->getShowEnd();
|
$end_timestamp = $show->getShowEnd();
|
||||||
|
@ -285,14 +286,14 @@ class ScheduleController extends Zend_Controller_Action
|
||||||
$this->view->error = "cannot schedule an overlapping show.";
|
$this->view->error = "cannot schedule an overlapping show.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$start = explode(" ", $start_timestamp);
|
$start = explode(" ", $start_timestamp);
|
||||||
$end = explode(" ", $end_timestamp);
|
$end = explode(" ", $end_timestamp);
|
||||||
$startTime = explode(":", $start[1]);
|
$startTime = explode(":", $start[1]);
|
||||||
$endTime = explode(":", $end[1]);
|
$endTime = explode(":", $end[1]);
|
||||||
$dateInfo_s = getDate(strtotime($start_timestamp));
|
$dateInfo_s = getDate(strtotime($start_timestamp));
|
||||||
$dateInfo_e = getDate(strtotime($end_timestamp));
|
$dateInfo_e = getDate(strtotime($end_timestamp));
|
||||||
|
|
||||||
$this->view->showContent = $show->getShowContent();
|
$this->view->showContent = $show->getShowContent();
|
||||||
$this->view->timeFilled = $show->getTimeScheduled();
|
$this->view->timeFilled = $show->getTimeScheduled();
|
||||||
$this->view->showName = $show->getName();
|
$this->view->showName = $show->getName();
|
||||||
|
@ -308,7 +309,7 @@ class ScheduleController extends Zend_Controller_Action
|
||||||
$this->view->startTime = sprintf("%d:%02d", $startTime[0], $startTime[1]);
|
$this->view->startTime = sprintf("%d:%02d", $startTime[0], $startTime[1]);
|
||||||
$this->view->endTime = sprintf("%d:%02d", $endTime[0], $endTime[1]);
|
$this->view->endTime = sprintf("%d:%02d", $endTime[0], $endTime[1]);
|
||||||
|
|
||||||
$this->view->chosen = $this->view->render('schedule/scheduled-content.phtml');
|
$this->view->chosen = $this->view->render('schedule/scheduled-content.phtml');
|
||||||
$this->view->dialog = $this->view->render('schedule/schedule-show-dialog.phtml');
|
$this->view->dialog = $this->view->render('schedule/schedule-show-dialog.phtml');
|
||||||
unset($this->view->showContent);
|
unset($this->view->showContent);
|
||||||
}
|
}
|
||||||
|
@ -335,7 +336,7 @@ class ScheduleController extends Zend_Controller_Action
|
||||||
{
|
{
|
||||||
$js = $this->_getParam('data');
|
$js = $this->_getParam('data');
|
||||||
$data = array();
|
$data = array();
|
||||||
|
|
||||||
//need to convert from serialized jQuery array.
|
//need to convert from serialized jQuery array.
|
||||||
foreach($js as $j){
|
foreach($js as $j){
|
||||||
$data[$j["name"]] = $j["value"];
|
$data[$j["name"]] = $j["value"];
|
||||||
|
@ -392,8 +393,8 @@ class ScheduleController extends Zend_Controller_Action
|
||||||
$rebroadAb = $formAbsoluteRebroadcast->isValid($data);
|
$rebroadAb = $formAbsoluteRebroadcast->isValid($data);
|
||||||
$rebroad = $formRebroadcast->isValid($data);
|
$rebroad = $formRebroadcast->isValid($data);
|
||||||
|
|
||||||
if ($what && $when && $repeats && $who && $style && $record && $rebroadAb && $rebroad) {
|
if ($what && $when && $repeats && $who && $style && $record && $rebroadAb && $rebroad) {
|
||||||
|
|
||||||
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
||||||
$user = new User($userInfo->id);
|
$user = new User($userInfo->id);
|
||||||
if($user->isAdmin()) {
|
if($user->isAdmin()) {
|
||||||
|
@ -413,7 +414,7 @@ class ScheduleController extends Zend_Controller_Action
|
||||||
$formRecord->reset();
|
$formRecord->reset();
|
||||||
$formAbsoluteRebroadcast->reset();
|
$formAbsoluteRebroadcast->reset();
|
||||||
$formRebroadcast->reset();
|
$formRebroadcast->reset();
|
||||||
|
|
||||||
$this->view->newForm = $this->view->render('schedule/add-show-form.phtml');
|
$this->view->newForm = $this->view->render('schedule/add-show-form.phtml');
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -426,7 +427,7 @@ class ScheduleController extends Zend_Controller_Action
|
||||||
{
|
{
|
||||||
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
||||||
$user = new User($userInfo->id);
|
$user = new User($userInfo->id);
|
||||||
|
|
||||||
if($user->isAdmin()) {
|
if($user->isAdmin()) {
|
||||||
$showInstanceId = $this->_getParam('id');
|
$showInstanceId = $this->_getParam('id');
|
||||||
|
|
||||||
|
@ -434,14 +435,14 @@ class ScheduleController extends Zend_Controller_Action
|
||||||
$show = new Show($showInstance->getShowId());
|
$show = new Show($showInstance->getShowId());
|
||||||
|
|
||||||
$show->cancelShow($showInstance->getShowStart());
|
$show->cancelShow($showInstance->getShowStart());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function cancelCurrentShowAction()
|
public function cancelCurrentShowAction()
|
||||||
{
|
{
|
||||||
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
||||||
$user = new User($userInfo->id);
|
$user = new User($userInfo->id);
|
||||||
|
|
||||||
if($user->isAdmin()) {
|
if($user->isAdmin()) {
|
||||||
$showInstanceId = $this->_getParam('id');
|
$showInstanceId = $this->_getParam('id');
|
||||||
$show = new ShowInstance($showInstanceId);
|
$show = new ShowInstance($showInstanceId);
|
||||||
|
|
|
@ -23,6 +23,8 @@ class UserController extends Zend_Controller_Action
|
||||||
$this->view->headScript()->appendFile('/js/airtime/user/user.js','text/javascript');
|
$this->view->headScript()->appendFile('/js/airtime/user/user.js','text/javascript');
|
||||||
$request = $this->getRequest();
|
$request = $this->getRequest();
|
||||||
$form = new Application_Form_AddUser();
|
$form = new Application_Form_AddUser();
|
||||||
|
|
||||||
|
$this->view->successMessage = "";
|
||||||
|
|
||||||
if ($request->isPost()) {
|
if ($request->isPost()) {
|
||||||
if ($form->isValid($request->getPost())) {
|
if ($form->isValid($request->getPost())) {
|
||||||
|
@ -42,6 +44,12 @@ class UserController extends Zend_Controller_Action
|
||||||
$user->save();
|
$user->save();
|
||||||
|
|
||||||
$form->reset();
|
$form->reset();
|
||||||
|
|
||||||
|
if (strlen($formdata['user_id']) == 0){
|
||||||
|
$this->view->successMessage = "<div class='success'>User added successfully!</div>";
|
||||||
|
} else {
|
||||||
|
$this->view->successMessage = "<div class='success'>User updated successfully!</div>";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -110,7 +110,7 @@ class Zend_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract
|
||||||
{
|
{
|
||||||
$controller = strtolower($request->getControllerName());
|
$controller = strtolower($request->getControllerName());
|
||||||
|
|
||||||
if ($controller == 'api' || $controller == 'recorder' || $controller == 'plupload' && $request->getActionName() == 'upload-recorded'){
|
if ($controller == 'api'){
|
||||||
|
|
||||||
$this->setRoleName("G");
|
$this->setRoleName("G");
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
class RabbitMqPlugin extends Zend_Controller_Plugin_Abstract
|
||||||
|
{
|
||||||
|
public function dispatchLoopShutdown()
|
||||||
|
{
|
||||||
|
RabbitMq::PushScheduleFinal();
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,17 +9,18 @@ class Application_Form_AddShowRebroadcastDates extends Zend_Form_SubForm
|
||||||
array('ViewScript', array('viewScript' => 'form/add-show-rebroadcast.phtml'))
|
array('ViewScript', array('viewScript' => 'form/add-show-rebroadcast.phtml'))
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
||||||
|
$relativeDates = array();
|
||||||
|
$relativeDates[""] = "";
|
||||||
|
for($i=0; $i <=30; $i++) {
|
||||||
|
$relativeDates["$i days"] = "+$i days";
|
||||||
|
}
|
||||||
|
|
||||||
//Add date select
|
//Add date select
|
||||||
$this->addElement('select', 'add_show_rebroadcast_date_1', array(
|
$this->addElement('select', 'add_show_rebroadcast_date_1', array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
'class' => ' input_select',
|
'class' => ' input_select',
|
||||||
'multiOptions' => array(
|
'multiOptions' => $relativeDates,
|
||||||
"" => "",
|
|
||||||
"0 days" => "+0 days",
|
|
||||||
"1 day" => "+1 day",
|
|
||||||
"2 days" => "+2 days",
|
|
||||||
"3 days" => "+3 days"
|
|
||||||
),
|
|
||||||
'decorators' => array(
|
'decorators' => array(
|
||||||
'ViewHelper'
|
'ViewHelper'
|
||||||
)
|
)
|
||||||
|
@ -44,13 +45,7 @@ class Application_Form_AddShowRebroadcastDates extends Zend_Form_SubForm
|
||||||
$this->addElement('select', 'add_show_rebroadcast_date_2', array(
|
$this->addElement('select', 'add_show_rebroadcast_date_2', array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
'class' => ' input_select',
|
'class' => ' input_select',
|
||||||
'multiOptions' => array(
|
'multiOptions' => $relativeDates,
|
||||||
"" => "",
|
|
||||||
"0 days" => "+0 days",
|
|
||||||
"1 day" => "+1 day",
|
|
||||||
"2 days" => "+2 days",
|
|
||||||
"3 days" => "+3 days"
|
|
||||||
),
|
|
||||||
'decorators' => array(
|
'decorators' => array(
|
||||||
'ViewHelper'
|
'ViewHelper'
|
||||||
)
|
)
|
||||||
|
@ -75,13 +70,7 @@ class Application_Form_AddShowRebroadcastDates extends Zend_Form_SubForm
|
||||||
$this->addElement('select', 'add_show_rebroadcast_date_3', array(
|
$this->addElement('select', 'add_show_rebroadcast_date_3', array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
'class' => ' input_select',
|
'class' => ' input_select',
|
||||||
'multiOptions' => array(
|
'multiOptions' => $relativeDates,
|
||||||
"" => "",
|
|
||||||
"0 days" => "+0 days",
|
|
||||||
"1 day" => "+1 day",
|
|
||||||
"2 days" => "+2 days",
|
|
||||||
"3 days" => "+3 days"
|
|
||||||
),
|
|
||||||
'decorators' => array(
|
'decorators' => array(
|
||||||
'ViewHelper'
|
'ViewHelper'
|
||||||
)
|
)
|
||||||
|
@ -106,13 +95,7 @@ class Application_Form_AddShowRebroadcastDates extends Zend_Form_SubForm
|
||||||
$this->addElement('select', 'add_show_rebroadcast_date_4', array(
|
$this->addElement('select', 'add_show_rebroadcast_date_4', array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
'class' => ' input_select',
|
'class' => ' input_select',
|
||||||
'multiOptions' => array(
|
'multiOptions' => $relativeDates,
|
||||||
"" => "",
|
|
||||||
"0 days" => "+0 days",
|
|
||||||
"1 day" => "+1 day",
|
|
||||||
"2 days" => "+2 days",
|
|
||||||
"3 days" => "+3 days"
|
|
||||||
),
|
|
||||||
'decorators' => array(
|
'decorators' => array(
|
||||||
'ViewHelper'
|
'ViewHelper'
|
||||||
)
|
)
|
||||||
|
@ -137,13 +120,7 @@ class Application_Form_AddShowRebroadcastDates extends Zend_Form_SubForm
|
||||||
$this->addElement('select', 'add_show_rebroadcast_date_5', array(
|
$this->addElement('select', 'add_show_rebroadcast_date_5', array(
|
||||||
'required' => false,
|
'required' => false,
|
||||||
'class' => ' input_select',
|
'class' => ' input_select',
|
||||||
'multiOptions' => array(
|
'multiOptions' => $relativeDates,
|
||||||
"" => "",
|
|
||||||
"0 days" => "+0 days",
|
|
||||||
"1 day" => "+1 day",
|
|
||||||
"2 days" => "+2 days",
|
|
||||||
"3 days" => "+3 days"
|
|
||||||
),
|
|
||||||
'decorators' => array(
|
'decorators' => array(
|
||||||
'ViewHelper'
|
'ViewHelper'
|
||||||
)
|
)
|
||||||
|
|
|
@ -16,7 +16,7 @@ class Application_Form_AddShowWhat extends Zend_Form_SubForm
|
||||||
|
|
||||||
// Add URL element
|
// Add URL element
|
||||||
$this->addElement('text', 'add_show_url', array(
|
$this->addElement('text', 'add_show_url', array(
|
||||||
'label' => 'Show URL:',
|
'label' => 'Website:',
|
||||||
'class' => 'input_text',
|
'class' => 'input_text',
|
||||||
'required' => false,
|
'required' => false,
|
||||||
'filters' => array('StringTrim'),
|
'filters' => array('StringTrim'),
|
||||||
|
|
|
@ -68,12 +68,13 @@ class Application_Form_AddUser extends Zend_Form
|
||||||
$this->addElement($jabber);
|
$this->addElement($jabber);
|
||||||
|
|
||||||
$select = new Zend_Form_Element_Select('type');
|
$select = new Zend_Form_Element_Select('type');
|
||||||
|
$select->setLabel('User Type:');
|
||||||
$select->setAttrib('class', 'input_select');
|
$select->setAttrib('class', 'input_select');
|
||||||
$select->setAttrib('style', 'width: 40%');
|
$select->setAttrib('style', 'width: 40%');
|
||||||
$select->setMultiOptions(array(
|
$select->setMultiOptions(array(
|
||||||
"A" => "admin",
|
"G" => "Guest",
|
||||||
"H" => "host",
|
"H" => "Host",
|
||||||
"G" => "guest",
|
"A" => "Admin"
|
||||||
));
|
));
|
||||||
$select->setRequired(true);
|
$select->setRequired(true);
|
||||||
$this->addElement($select);
|
$this->addElement($select);
|
||||||
|
|
|
@ -7,7 +7,7 @@ class Application_Form_Preferences extends Zend_Form
|
||||||
{
|
{
|
||||||
$this->setAction('/Preference/update')->setMethod('post');
|
$this->setAction('/Preference/update')->setMethod('post');
|
||||||
|
|
||||||
// Add login element
|
//Station name
|
||||||
$this->addElement('text', 'stationName', array(
|
$this->addElement('text', 'stationName', array(
|
||||||
'class' => 'input_text',
|
'class' => 'input_text',
|
||||||
'label' => 'Station Name:',
|
'label' => 'Station Name:',
|
||||||
|
@ -17,12 +17,12 @@ class Application_Form_Preferences extends Zend_Form
|
||||||
'value' => Application_Model_Preference::GetValue("station_name")
|
'value' => Application_Model_Preference::GetValue("station_name")
|
||||||
));
|
));
|
||||||
|
|
||||||
$defaultFade = Application_Model_Preference::GetValue("default_fade");
|
$defaultFade = Application_Model_Preference::GetDefaultFade();
|
||||||
if($defaultFade == ""){
|
if($defaultFade == ""){
|
||||||
$defaultFade = '00:00:00.000000';
|
$defaultFade = '00:00:00.000000';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add login element
|
//Default station fade
|
||||||
$this->addElement('text', 'stationDefaultFade', array(
|
$this->addElement('text', 'stationDefaultFade', array(
|
||||||
'class' => 'input_text',
|
'class' => 'input_text',
|
||||||
'label' => 'Default Fade:',
|
'label' => 'Default Fade:',
|
||||||
|
@ -42,11 +42,46 @@ class Application_Form_Preferences extends Zend_Form
|
||||||
$stream_format->setValue(Application_Model_Preference::GetStreamLabelFormat());
|
$stream_format->setValue(Application_Model_Preference::GetStreamLabelFormat());
|
||||||
$this->addElement($stream_format);
|
$this->addElement($stream_format);
|
||||||
|
|
||||||
|
|
||||||
|
$this->addElement('checkbox', 'UseSoundCloud', array(
|
||||||
|
'label' => 'Automatically Upload Recorded Shows To SoundCloud',
|
||||||
|
'required' => false,
|
||||||
|
'value' => Application_Model_Preference::GetDoSoundCloudUpload()
|
||||||
|
));
|
||||||
|
|
||||||
|
//SoundCloud Username
|
||||||
|
$this->addElement('text', 'SoundCloudUser', array(
|
||||||
|
'class' => 'input_text',
|
||||||
|
'label' => 'SoundCloud Email:',
|
||||||
|
'required' => false,
|
||||||
|
'filters' => array('StringTrim'),
|
||||||
|
'value' => Application_Model_Preference::GetSoundCloudUser()
|
||||||
|
));
|
||||||
|
|
||||||
|
//SoundCloud Password
|
||||||
|
$this->addElement('text', 'SoundCloudPassword', array(
|
||||||
|
'class' => 'input_text',
|
||||||
|
'label' => 'SoundCloud Password:',
|
||||||
|
'required' => false,
|
||||||
|
'filters' => array('StringTrim'),
|
||||||
|
'value' => Application_Model_Preference::GetSoundCloudPassword()
|
||||||
|
));
|
||||||
|
|
||||||
|
// Add the description element
|
||||||
|
$this->addElement('textarea', 'SoundCloudTags', array(
|
||||||
|
'label' => 'space separated SoundCloud Tags',
|
||||||
|
'required' => false,
|
||||||
|
'class' => 'input_text_area',
|
||||||
|
'value' => Application_Model_Preference::GetSoundCloudTags()
|
||||||
|
));
|
||||||
|
|
||||||
$this->addElement('submit', 'submit', array(
|
$this->addElement('submit', 'submit', array(
|
||||||
'class' => 'ui-button ui-state-default',
|
'class' => 'ui-button ui-state-default',
|
||||||
'ignore' => true,
|
'ignore' => true,
|
||||||
'label' => 'Submit',
|
'label' => 'Submit',
|
||||||
));
|
));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,61 +2,85 @@
|
||||||
|
|
||||||
class Application_Model_DateHelper
|
class Application_Model_DateHelper
|
||||||
{
|
{
|
||||||
private $_timestamp;
|
private $_timestamp;
|
||||||
|
|
||||||
function __construct() {
|
function __construct()
|
||||||
|
{
|
||||||
$this->_timestamp = date("U");
|
$this->_timestamp = date("U");
|
||||||
}
|
}
|
||||||
|
|
||||||
function getDate(){
|
/**
|
||||||
return date("Y-m-d H:i:s", $this->_timestamp);
|
* Get time of object construction in the format
|
||||||
}
|
* YYYY-MM-DD HH:mm:ss
|
||||||
|
*/
|
||||||
function getTime(){
|
function getDate()
|
||||||
return date("H:i:s", $this->_timestamp);
|
{
|
||||||
}
|
return date("Y-m-d H:i:s", $this->_timestamp);
|
||||||
|
}
|
||||||
function setDate($dateString){
|
|
||||||
|
/**
|
||||||
|
* Get time of object construction in the format
|
||||||
|
* HH:mm:ss
|
||||||
|
*/
|
||||||
|
function getTime()
|
||||||
|
{
|
||||||
|
return date("H:i:s", $this->_timestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the internal timestamp of the object.
|
||||||
|
*/
|
||||||
|
function setDate($dateString)
|
||||||
|
{
|
||||||
$this->_timestamp = strtotime($dateString);
|
$this->_timestamp = strtotime($dateString);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getNowDayStartDiff(){
|
|
||||||
$dayStartTS = strtotime(date("Y-m-d", $this->_timestamp));
|
|
||||||
return $this->_timestamp - $dayStartTS;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getNowDayEndDiff(){
|
/**
|
||||||
$dayEndTS = strtotime(date("Y-m-d", $this->_timestamp+(86400)));
|
*
|
||||||
return $dayEndTS - $this->_timestamp;
|
* Enter description here ...
|
||||||
}
|
*/
|
||||||
|
function getNowDayStartDiff()
|
||||||
|
{
|
||||||
|
$dayStartTS = strtotime(date("Y-m-d", $this->_timestamp));
|
||||||
|
return $this->_timestamp - $dayStartTS;
|
||||||
|
}
|
||||||
|
|
||||||
function getEpochTime(){
|
function getNowDayEndDiff()
|
||||||
|
{
|
||||||
|
$dayEndTS = strtotime(date("Y-m-d", $this->_timestamp+(86400)));
|
||||||
|
return $dayEndTS - $this->_timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getEpochTime()
|
||||||
|
{
|
||||||
return $this->_timestamp;
|
return $this->_timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function TimeDiff($time1, $time2){
|
public static function TimeDiff($time1, $time2)
|
||||||
|
{
|
||||||
return strtotime($time2) - strtotime($time1);
|
return strtotime($time2) - strtotime($time1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function ConvertMSToHHMMSSmm($time){
|
public static function ConvertMSToHHMMSSmm($time)
|
||||||
|
{
|
||||||
$hours = floor($time / 3600000);
|
$hours = floor($time / 3600000);
|
||||||
$time -= 3600000*$hours;
|
$time -= 3600000*$hours;
|
||||||
|
|
||||||
$minutes = floor($time / 60000);
|
$minutes = floor($time / 60000);
|
||||||
$time -= 60000*$minutes;
|
$time -= 60000*$minutes;
|
||||||
|
|
||||||
$seconds = floor($time / 1000);
|
$seconds = floor($time / 1000);
|
||||||
$time -= 1000*$seconds;
|
$time -= 1000*$seconds;
|
||||||
|
|
||||||
$ms = $time;
|
$ms = $time;
|
||||||
|
|
||||||
if (strlen($hours) == 1)
|
if (strlen($hours) == 1)
|
||||||
$hours = "0".$hours;
|
$hours = "0".$hours;
|
||||||
if (strlen($minutes) == 1)
|
if (strlen($minutes) == 1)
|
||||||
$minutes = "0".$minutes;
|
$minutes = "0".$minutes;
|
||||||
if (strlen($seconds) == 1)
|
if (strlen($seconds) == 1)
|
||||||
$seconds = "0".$seconds;
|
$seconds = "0".$seconds;
|
||||||
|
|
||||||
return $hours.":".$minutes.":".$seconds.".".$ms;
|
return $hours.":".$minutes.":".$seconds.".".$ms;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,30 +8,30 @@ class Application_Model_Preference
|
||||||
|
|
||||||
$auth = Zend_Auth::getInstance();
|
$auth = Zend_Auth::getInstance();
|
||||||
$id = $auth->getIdentity()->id;
|
$id = $auth->getIdentity()->id;
|
||||||
|
|
||||||
//Check if key already exists
|
//Check if key already exists
|
||||||
$sql = "SELECT COUNT(*) FROM cc_pref"
|
$sql = "SELECT COUNT(*) FROM cc_pref"
|
||||||
." WHERE keystr = '$key'";
|
." WHERE keystr = '$key'";
|
||||||
$result = $CC_DBC->GetOne($sql);
|
$result = $CC_DBC->GetOne($sql);
|
||||||
|
|
||||||
if ($result == 1){
|
if ($result == 1){
|
||||||
$sql = "UPDATE cc_pref"
|
$sql = "UPDATE cc_pref"
|
||||||
." SET subjid = $id, valstr = '$value'"
|
." SET subjid = $id, valstr = '$value'"
|
||||||
." WHERE keystr = '$key'";
|
." WHERE keystr = '$key'";
|
||||||
} else {
|
} else {
|
||||||
$sql = "INSERT INTO cc_pref (subjid, keystr, valstr)"
|
$sql = "INSERT INTO cc_pref (subjid, keystr, valstr)"
|
||||||
." VALUES ($id, '$key', '$value')";
|
." VALUES ($id, '$key', '$value')";
|
||||||
}
|
}
|
||||||
return $CC_DBC->query($sql);
|
return $CC_DBC->query($sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function GetValue($key){
|
public static function GetValue($key){
|
||||||
global $CC_CONFIG, $CC_DBC;
|
global $CC_CONFIG, $CC_DBC;
|
||||||
//Check if key already exists
|
//Check if key already exists
|
||||||
$sql = "SELECT COUNT(*) FROM cc_pref"
|
$sql = "SELECT COUNT(*) FROM cc_pref"
|
||||||
." WHERE keystr = '$key'";
|
." WHERE keystr = '$key'";
|
||||||
$result = $CC_DBC->GetOne($sql);
|
$result = $CC_DBC->GetOne($sql);
|
||||||
|
|
||||||
if ($result == 0)
|
if ($result == 0)
|
||||||
return "";
|
return "";
|
||||||
else {
|
else {
|
||||||
|
@ -40,9 +40,9 @@ class Application_Model_Preference
|
||||||
$result = $CC_DBC->GetOne($sql);
|
$result = $CC_DBC->GetOne($sql);
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function GetHeadTitle(){
|
public static function GetHeadTitle(){
|
||||||
/* Caches the title name as a session variable so we dont access
|
/* Caches the title name as a session variable so we dont access
|
||||||
* the database on every page load. */
|
* the database on every page load. */
|
||||||
|
@ -55,31 +55,32 @@ class Application_Model_Preference
|
||||||
}
|
}
|
||||||
if (strlen($title) > 0)
|
if (strlen($title) > 0)
|
||||||
$title .= " - ";
|
$title .= " - ";
|
||||||
|
|
||||||
return $title."Airtime";
|
return $title."Airtime";
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function SetHeadTitle($title, $view){
|
public static function SetHeadTitle($title, $view){
|
||||||
Application_Model_Preference::SetValue("station_name", $title);
|
Application_Model_Preference::SetValue("station_name", $title);
|
||||||
$defaultNamespace = new Zend_Session_Namespace('title_name');
|
$defaultNamespace = new Zend_Session_Namespace('title_name');
|
||||||
$defaultNamespace->title = $title;
|
$defaultNamespace->title = $title;
|
||||||
|
RabbitMq::PushSchedule();
|
||||||
|
|
||||||
//set session variable to new station name so that html title is updated.
|
//set session variable to new station name so that html title is updated.
|
||||||
//should probably do this in a view helper to keep this controller as minimal as possible.
|
//should probably do this in a view helper to keep this controller as minimal as possible.
|
||||||
$view->headTitle()->exchangeArray(array()); //clear headTitle ArrayObject
|
$view->headTitle()->exchangeArray(array()); //clear headTitle ArrayObject
|
||||||
$view->headTitle(Application_Model_Preference::GetHeadTitle());
|
$view->headTitle(Application_Model_Preference::GetHeadTitle());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function SetShowsPopulatedUntil($timestamp) {
|
public static function SetShowsPopulatedUntil($timestamp) {
|
||||||
Application_Model_Preference::SetValue("shows_populated_until", $timestamp);
|
Application_Model_Preference::SetValue("shows_populated_until", $timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function GetShowsPopulatedUntil() {
|
public static function GetShowsPopulatedUntil() {
|
||||||
return Application_Model_Preference::GetValue("shows_populated_until");
|
return Application_Model_Preference::GetValue("shows_populated_until");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function SetDefaultFade($fade) {
|
public static function SetDefaultFade($fade) {
|
||||||
Application_Model_Preference::SetValue("default_fade", $fade);
|
Application_Model_Preference::SetValue("default_fade", $fade);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function GetDefaultFade() {
|
public static function GetDefaultFade() {
|
||||||
|
@ -88,6 +89,7 @@ class Application_Model_Preference
|
||||||
|
|
||||||
public static function SetStreamLabelFormat($type){
|
public static function SetStreamLabelFormat($type){
|
||||||
Application_Model_Preference::SetValue("stream_label_format", $type);
|
Application_Model_Preference::SetValue("stream_label_format", $type);
|
||||||
|
RabbitMq::PushSchedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function GetStreamLabelFormat(){
|
public static function GetStreamLabelFormat(){
|
||||||
|
@ -97,5 +99,38 @@ class Application_Model_Preference
|
||||||
public static function GetStationName(){
|
public static function GetStationName(){
|
||||||
return Application_Model_Preference::getValue("station_name");
|
return Application_Model_Preference::getValue("station_name");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function SetDoSoundCloudUpload($upload) {
|
||||||
|
Application_Model_Preference::SetValue("soundcloud_upload", $upload);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function GetDoSoundCloudUpload() {
|
||||||
|
return Application_Model_Preference::GetValue("soundcloud_upload");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function SetSoundCloudUser($user) {
|
||||||
|
Application_Model_Preference::SetValue("soundcloud_user", $user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function GetSoundCloudUser() {
|
||||||
|
return Application_Model_Preference::GetValue("soundcloud_user");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function SetSoundCloudPassword($password) {
|
||||||
|
Application_Model_Preference::SetValue("soundcloud_password", $password);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function GetSoundCloudPassword() {
|
||||||
|
return Application_Model_Preference::GetValue("soundcloud_password");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function SetSoundCloudTags($tags) {
|
||||||
|
Application_Model_Preference::SetValue("soundcloud_tags", $tags);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function GetSoundCloudTags() {
|
||||||
|
return Application_Model_Preference::GetValue("soundcloud_tags");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?php
|
||||||
|
require_once 'php-amqplib/amqp.inc';
|
||||||
|
|
||||||
|
class RabbitMq
|
||||||
|
{
|
||||||
|
static private $doPush = FALSE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a flag to push the schedule at the end of the request.
|
||||||
|
*/
|
||||||
|
public static function PushSchedule() {
|
||||||
|
RabbitMq::$doPush = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Push the current schedule to RabbitMQ, to be picked up by Pypo.
|
||||||
|
* Will push the schedule in the range from 24 hours ago to 24 hours
|
||||||
|
* in the future.
|
||||||
|
*/
|
||||||
|
public static function PushScheduleFinal()
|
||||||
|
{
|
||||||
|
global $CC_CONFIG;
|
||||||
|
if (RabbitMq::$doPush) {
|
||||||
|
$conn = new AMQPConnection($CC_CONFIG["rabbitmq"]["host"],
|
||||||
|
$CC_CONFIG["rabbitmq"]["port"],
|
||||||
|
$CC_CONFIG["rabbitmq"]["user"],
|
||||||
|
$CC_CONFIG["rabbitmq"]["password"]);
|
||||||
|
$channel = $conn->channel();
|
||||||
|
$channel->access_request($CC_CONFIG["rabbitmq"]["vhost"], false, false, true, true);
|
||||||
|
|
||||||
|
$EXCHANGE = 'airtime-schedule';
|
||||||
|
$channel->exchange_declare($EXCHANGE, 'direct', false, true);
|
||||||
|
|
||||||
|
$data = json_encode(Schedule::GetScheduledPlaylists());
|
||||||
|
$msg = new AMQPMessage($data, array('content_type' => 'text/plain'));
|
||||||
|
|
||||||
|
$channel->basic_publish($msg, $EXCHANGE);
|
||||||
|
$channel->close();
|
||||||
|
$conn->close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -24,41 +24,6 @@ class ScheduleGroup {
|
||||||
return $result != "0";
|
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.
|
* 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) {
|
public function add($show_instance, $p_datetime, $p_audioFileId = null, $p_playlistId = null, $p_options = null) {
|
||||||
global $CC_CONFIG, $CC_DBC;
|
global $CC_CONFIG, $CC_DBC;
|
||||||
|
|
||||||
if (!is_null($p_audioFileId)) {
|
if (!is_null($p_audioFileId)) {
|
||||||
// Schedule a single audio track
|
// Schedule a single audio track
|
||||||
|
|
||||||
|
@ -92,27 +58,24 @@ class ScheduleGroup {
|
||||||
if (empty($length)) {
|
if (empty($length)) {
|
||||||
return new PEAR_Error("Length is empty.");
|
return new PEAR_Error("Length is empty.");
|
||||||
}
|
}
|
||||||
if (!Schedule::isScheduleEmptyInRange($p_datetime, $length)) {
|
|
||||||
return new PEAR_Error("Schedule conflict.", 555);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert into the table
|
// Insert into the table
|
||||||
$this->groupId = $CC_DBC->GetOne("SELECT nextval('schedule_group_id_seq')");
|
$this->groupId = $CC_DBC->GetOne("SELECT nextval('schedule_group_id_seq')");
|
||||||
$id = $this->dateToId($p_datetime);
|
|
||||||
$sql = "INSERT INTO ".$CC_CONFIG["scheduleTable"]
|
$sql = "INSERT INTO ".$CC_CONFIG["scheduleTable"]
|
||||||
." (playlist_id, starts, ends, clip_length, group_id, file_id)"
|
." (instance_id, starts, ends, clip_length, group_id, file_id, cue_out)"
|
||||||
." VALUES (0, TIMESTAMP '$p_datetime', "
|
." VALUES ($show_instance, TIMESTAMP '$p_datetime', "
|
||||||
." (TIMESTAMP '$p_datetime' + INTERVAL '$length'),"
|
." (TIMESTAMP '$p_datetime' + INTERVAL '$length'),"
|
||||||
." '$length',"
|
." '$length',"
|
||||||
." {$this->groupId}, $p_audioFileId)";
|
." {$this->groupId}, $p_audioFileId, '$length')";
|
||||||
$result = $CC_DBC->query($sql);
|
$result = $CC_DBC->query($sql);
|
||||||
if (PEAR::isError($result)) {
|
if (PEAR::isError($result)) {
|
||||||
//var_dump($sql);
|
//var_dump($sql);
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
return $this->groupId;
|
|
||||||
|
|
||||||
} elseif (!is_null($p_playlistId)){
|
}
|
||||||
|
elseif (!is_null($p_playlistId)){
|
||||||
// Schedule a whole playlist
|
// Schedule a whole playlist
|
||||||
|
|
||||||
// Load existing playlist
|
// Load existing playlist
|
||||||
|
@ -130,7 +93,6 @@ class ScheduleGroup {
|
||||||
|
|
||||||
// Insert all items into the schedule
|
// Insert all items into the schedule
|
||||||
$this->groupId = $CC_DBC->GetOne("SELECT nextval('schedule_group_id_seq')");
|
$this->groupId = $CC_DBC->GetOne("SELECT nextval('schedule_group_id_seq')");
|
||||||
$id = $this->dateToId($p_datetime);
|
|
||||||
$itemStartTime = $p_datetime;
|
$itemStartTime = $p_datetime;
|
||||||
|
|
||||||
$plItems = $playlist->getContents();
|
$plItems = $playlist->getContents();
|
||||||
|
@ -151,13 +113,13 @@ class ScheduleGroup {
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
$itemStartTime = $CC_DBC->getOne("SELECT TIMESTAMP '$itemStartTime' + INTERVAL '$trackLength'");
|
$itemStartTime = $CC_DBC->getOne("SELECT TIMESTAMP '$itemStartTime' + INTERVAL '$trackLength'");
|
||||||
$id = $this->dateToId($itemStartTime);
|
|
||||||
}
|
}
|
||||||
return $this->groupId;
|
|
||||||
}
|
}
|
||||||
|
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;
|
global $CC_CONFIG, $CC_DBC;
|
||||||
// Get the end time for the given entry
|
// Get the end time for the given entry
|
||||||
$sql = "SELECT MAX(ends) FROM ".$CC_CONFIG["scheduleTable"]
|
$sql = "SELECT MAX(ends) FROM ".$CC_CONFIG["scheduleTable"]
|
||||||
|
@ -176,10 +138,6 @@ class ScheduleGroup {
|
||||||
return $this->add($show_instance, $startTime, null, $p_playlistId);
|
return $this->add($show_instance, $startTime, null, $p_playlistId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove the group from the schedule.
|
* Remove the group from the schedule.
|
||||||
* Note: does not check if it is in the past, you can remove anything.
|
* Note: does not check if it is in the past, you can remove anything.
|
||||||
|
@ -195,7 +153,9 @@ class ScheduleGroup {
|
||||||
$sql = "DELETE FROM ".$CC_CONFIG["scheduleTable"]
|
$sql = "DELETE FROM ".$CC_CONFIG["scheduleTable"]
|
||||||
." WHERE group_id = ".$this->groupId;
|
." WHERE group_id = ".$this->groupId;
|
||||||
//echo $sql;
|
//echo $sql;
|
||||||
return $CC_DBC->query($sql);
|
$retVal = $CC_DBC->query($sql);
|
||||||
|
RabbitMq::PushSchedule();
|
||||||
|
return $retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -231,17 +191,13 @@ class ScheduleGroup {
|
||||||
return $CC_DBC->GetAll($sql);
|
return $CC_DBC->GetAll($sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function reschedule($toDateTime) {
|
|
||||||
global $CC_CONFIG, $CC_DBC;
|
|
||||||
// $sql = "UPDATE ".$CC_CONFIG["scheduleTable"]. " SET id=, starts=,ends="
|
|
||||||
}
|
|
||||||
|
|
||||||
public function notifyGroupStartPlay() {
|
public function notifyGroupStartPlay() {
|
||||||
global $CC_CONFIG, $CC_DBC;
|
global $CC_CONFIG, $CC_DBC;
|
||||||
$sql = "UPDATE ".$CC_CONFIG['scheduleTable']
|
$sql = "UPDATE ".$CC_CONFIG['scheduleTable']
|
||||||
." SET schedule_group_played=TRUE"
|
." SET schedule_group_played=TRUE"
|
||||||
." WHERE group_id=".$this->groupId;
|
." WHERE group_id=".$this->groupId;
|
||||||
return $CC_DBC->query($sql);
|
$retVal = $CC_DBC->query($sql);
|
||||||
|
return $retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function notifyMediaItemStartPlay($p_fileId) {
|
public function notifyMediaItemStartPlay($p_fileId) {
|
||||||
|
@ -250,7 +206,8 @@ class ScheduleGroup {
|
||||||
." SET media_item_played=TRUE"
|
." SET media_item_played=TRUE"
|
||||||
." WHERE group_id=".$this->groupId
|
." WHERE group_id=".$this->groupId
|
||||||
." AND file_id=".pg_escape_string($p_fileId);
|
." AND file_id=".pg_escape_string($p_fileId);
|
||||||
return $CC_DBC->query($sql);
|
$retVal = $CC_DBC->query($sql);
|
||||||
|
return $retVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,9 +291,10 @@ class Schedule {
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function GetPercentScheduled($instance_id, $s_datetime, $e_datetime){
|
public static function GetPercentScheduled($instance_id, $s_datetime, $e_datetime)
|
||||||
|
{
|
||||||
$time = Schedule::GetTotalShowTime($instance_id);
|
$time = Schedule::GetTotalShowTime($instance_id);
|
||||||
|
|
||||||
$s_epoch = strtotime($s_datetime);
|
$s_epoch = strtotime($s_datetime);
|
||||||
$e_epoch = strtotime($e_datetime);
|
$e_epoch = strtotime($e_datetime);
|
||||||
|
|
||||||
|
@ -396,12 +354,14 @@ class Schedule {
|
||||||
* @return array
|
* @return array
|
||||||
* Returns empty array if nothing found
|
* Returns empty array if nothing found
|
||||||
*/
|
*/
|
||||||
public static function GetItems($p_fromDateTime, $p_toDateTime, $p_playlistsOnly = true) {
|
|
||||||
|
public static function GetItems($p_currentDateTime, $p_toDateTime, $p_playlistsOnly = true)
|
||||||
|
{
|
||||||
global $CC_CONFIG, $CC_DBC;
|
global $CC_CONFIG, $CC_DBC;
|
||||||
$rows = array();
|
$rows = array();
|
||||||
if (!$p_playlistsOnly) {
|
if (!$p_playlistsOnly) {
|
||||||
$sql = "SELECT * FROM ".$CC_CONFIG["scheduleTable"]
|
$sql = "SELECT * FROM ".$CC_CONFIG["scheduleTable"]
|
||||||
." WHERE (starts >= TIMESTAMP '$p_fromDateTime') "
|
." WHERE (starts >= TIMESTAMP '$p_currentDateTime') "
|
||||||
." AND (ends <= TIMESTAMP '$p_toDateTime')";
|
." AND (ends <= TIMESTAMP '$p_toDateTime')";
|
||||||
$rows = $CC_DBC->GetAll($sql);
|
$rows = $CC_DBC->GetAll($sql);
|
||||||
foreach ($rows as &$row) {
|
foreach ($rows as &$row) {
|
||||||
|
@ -429,11 +389,11 @@ class Schedule {
|
||||||
." ON st.instance_id = si.id"
|
." ON st.instance_id = si.id"
|
||||||
." LEFT JOIN $CC_CONFIG[showTable] as sh"
|
." LEFT JOIN $CC_CONFIG[showTable] as sh"
|
||||||
." ON si.show_id = sh.id"
|
." ON si.show_id = sh.id"
|
||||||
." WHERE (st.starts >= TIMESTAMP '$p_fromDateTime')"
|
." WHERE (st.ends >= TIMESTAMP '$p_currentDateTime')"
|
||||||
." AND (st.ends <= TIMESTAMP '$p_toDateTime')"
|
." AND (st.ends <= TIMESTAMP '$p_toDateTime')"
|
||||||
//next line makes sure that we aren't returning items that
|
//next line makes sure that we aren't returning items that
|
||||||
//are past the show's scheduled timeslot.
|
//are past the show's scheduled timeslot.
|
||||||
." AND (st.starts < si.ends)"
|
." AND (st.starts < si.ends)"
|
||||||
." GROUP BY st.group_id"
|
." GROUP BY st.group_id"
|
||||||
." ORDER BY starts";
|
." ORDER BY starts";
|
||||||
|
|
||||||
|
@ -457,7 +417,8 @@ class Schedule {
|
||||||
* @param int $next
|
* @param int $next
|
||||||
* @return date
|
* @return date
|
||||||
*/
|
*/
|
||||||
public static function GetPlayOrderRange($prev = 1, $next = 1) {
|
public static function GetPlayOrderRange($prev = 1, $next = 1)
|
||||||
|
{
|
||||||
if (!is_int($prev) || !is_int($next)){
|
if (!is_int($prev) || !is_int($next)){
|
||||||
//must enter integers to specify ranges
|
//must enter integers to specify ranges
|
||||||
return array();
|
return array();
|
||||||
|
@ -469,11 +430,11 @@ class Schedule {
|
||||||
$timeNow = $date->getDate();
|
$timeNow = $date->getDate();
|
||||||
return array("env"=>APPLICATION_ENV,
|
return array("env"=>APPLICATION_ENV,
|
||||||
"schedulerTime"=>gmdate("Y-m-d H:i:s"),
|
"schedulerTime"=>gmdate("Y-m-d H:i:s"),
|
||||||
"previous"=>Schedule::Get_Scheduled_Item_Data($timeNow, -1, $prev, "24 hours"),
|
"previous"=>Schedule::GetScheduledItemData($timeNow, -1, $prev, "24 hours"),
|
||||||
"current"=>Schedule::Get_Scheduled_Item_Data($timeNow, 0),
|
"current"=>Schedule::GetScheduledItemData($timeNow, 0),
|
||||||
"next"=>Schedule::Get_Scheduled_Item_Data($timeNow, 1, $next, "48 hours"),
|
"next"=>Schedule::GetScheduledItemData($timeNow, 1, $next, "48 hours"),
|
||||||
"currentShow"=>Show_DAL::GetCurrentShow($timeNow),
|
"currentShow"=>Show_DAL::GetCurrentShow($timeNow),
|
||||||
"nextShow"=>Show_DAL::GetNextShow($timeNow),
|
"nextShow"=>Show_DAL::GetNextShows($timeNow, 1),
|
||||||
"timezone"=> date("T"),
|
"timezone"=> date("T"),
|
||||||
"timezoneOffset"=> date("Z"),
|
"timezoneOffset"=> date("Z"),
|
||||||
"apiKey"=>$CC_CONFIG['apiKey'][0]);
|
"apiKey"=>$CC_CONFIG['apiKey'][0]);
|
||||||
|
@ -501,7 +462,8 @@ class Schedule {
|
||||||
* want to search the database. For example "5 days", "18 hours", "60 minutes",
|
* want to search the database. For example "5 days", "18 hours", "60 minutes",
|
||||||
* "30 seconds" etc.
|
* "30 seconds" etc.
|
||||||
*/
|
*/
|
||||||
public static function Get_Scheduled_Item_Data($timeStamp, $timePeriod=0, $count = 0, $interval="0 hours"){
|
public static function GetScheduledItemData($timeStamp, $timePeriod=0, $count = 0, $interval="0 hours")
|
||||||
|
{
|
||||||
global $CC_CONFIG, $CC_DBC;
|
global $CC_CONFIG, $CC_DBC;
|
||||||
|
|
||||||
$sql = "SELECT DISTINCT pt.name, ft.track_title, ft.artist_name, ft.album_title, st.starts, st.ends, st.clip_length, st.media_item_played, st.group_id, show.name as show_name, st.instance_id"
|
$sql = "SELECT DISTINCT pt.name, ft.track_title, ft.artist_name, ft.album_title, st.starts, st.ends, st.clip_length, st.media_item_played, st.group_id, show.name as show_name, st.instance_id"
|
||||||
|
@ -531,7 +493,8 @@ class Schedule {
|
||||||
return $rows;
|
return $rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function GetShowInstanceItems($instance_id){
|
public static function GetShowInstanceItems($instance_id)
|
||||||
|
{
|
||||||
global $CC_CONFIG, $CC_DBC;
|
global $CC_CONFIG, $CC_DBC;
|
||||||
|
|
||||||
$sql = "SELECT DISTINCT pt.name, ft.track_title, ft.artist_name, ft.album_title, st.starts, st.ends, st.clip_length, st.media_item_played, st.group_id, show.name as show_name, st.instance_id"
|
$sql = "SELECT DISTINCT pt.name, ft.track_title, ft.artist_name, ft.album_title, st.starts, st.ends, st.clip_length, st.media_item_played, st.group_id, show.name as show_name, st.instance_id"
|
||||||
|
@ -547,12 +510,14 @@ class Schedule {
|
||||||
return $rows;
|
return $rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function UpdateMediaPlayedStatus($id){
|
public static function UpdateMediaPlayedStatus($p_id)
|
||||||
|
{
|
||||||
global $CC_CONFIG, $CC_DBC;
|
global $CC_CONFIG, $CC_DBC;
|
||||||
$sql = "UPDATE ".$CC_CONFIG['scheduleTable']
|
$sql = "UPDATE ".$CC_CONFIG['scheduleTable']
|
||||||
." SET media_item_played=TRUE"
|
." SET media_item_played=TRUE"
|
||||||
." WHERE id=$id";
|
." WHERE id=$p_id";
|
||||||
return $CC_DBC->query($sql);
|
$retVal = $CC_DBC->query($sql);
|
||||||
|
return $retVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -563,7 +528,7 @@ class Schedule {
|
||||||
* @param string $p_time
|
* @param string $p_time
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private static function CcTimeToPypoTime($p_time)
|
private static function AirtimeTimeToPypoTime($p_time)
|
||||||
{
|
{
|
||||||
$p_time = substr($p_time, 0, 19);
|
$p_time = substr($p_time, 0, 19);
|
||||||
$p_time = str_replace(" ", "-", $p_time);
|
$p_time = str_replace(" ", "-", $p_time);
|
||||||
|
@ -578,7 +543,7 @@ class Schedule {
|
||||||
* @param string $p_time
|
* @param string $p_time
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private static function PypoTimeToCcTime($p_time)
|
private static function PypoTimeToAirtimeTime($p_time)
|
||||||
{
|
{
|
||||||
$t = explode("-", $p_time);
|
$t = explode("-", $p_time);
|
||||||
return $t[0]."-".$t[1]."-".$t[2]." ".$t[3].":".$t[4].":00";
|
return $t[0]."-".$t[1]."-".$t[2]." ".$t[3].":".$t[4].":00";
|
||||||
|
@ -658,17 +623,21 @@ class Schedule {
|
||||||
/**
|
/**
|
||||||
* Export the schedule in json formatted for pypo (the liquidsoap scheduler)
|
* Export the schedule in json formatted for pypo (the liquidsoap scheduler)
|
||||||
*
|
*
|
||||||
* @param string $range
|
* @param string $p_fromDateTime
|
||||||
* In the format "YYYY-MM-DD HH:mm:ss"
|
* In the format "YYYY-MM-DD-HH-mm-SS"
|
||||||
* @param string $source
|
* @param string $p_toDateTime
|
||||||
* In the format "YYYY-MM-DD HH:mm:ss"
|
* In the format "YYYY-MM-DD-HH-mm-SS"
|
||||||
*/
|
*/
|
||||||
public static function ExportRangeAsJson($p_fromDateTime, $p_toDateTime)
|
public static function GetScheduledPlaylists()
|
||||||
{
|
{
|
||||||
global $CC_CONFIG, $CC_DBC;
|
global $CC_CONFIG, $CC_DBC;
|
||||||
|
|
||||||
$range_start = Schedule::PypoTimeToCcTime($p_fromDateTime);
|
$t1 = new DateTime();
|
||||||
$range_end = Schedule::PypoTimeToCcTime($p_toDateTime);
|
$range_start = $t1->format("Y-m-d H:i:s");
|
||||||
|
|
||||||
|
$t2 = new DateTime();
|
||||||
|
$t2->add(new DateInterval("PT24H"));
|
||||||
|
$range_end = $t2->format("Y-m-d H:i:s");
|
||||||
|
|
||||||
// Scheduler wants everything in a playlist
|
// Scheduler wants everything in a playlist
|
||||||
$data = Schedule::GetItems($range_start, $range_end, true);
|
$data = Schedule::GetItems($range_start, $range_end, true);
|
||||||
|
@ -684,10 +653,10 @@ class Schedule {
|
||||||
$start = substr($start, 0, 19);
|
$start = substr($start, 0, 19);
|
||||||
|
|
||||||
//Start time is the array key, needs to be in the format "YYYY-MM-DD-HH-mm-ss"
|
//Start time is the array key, needs to be in the format "YYYY-MM-DD-HH-mm-ss"
|
||||||
$pkey = Schedule::CcTimeToPypoTime($start);
|
$pkey = Schedule::AirtimeTimeToPypoTime($start);
|
||||||
$timestamp = strtotime($start);
|
$timestamp = strtotime($start);
|
||||||
$playlists[$pkey]['source'] = "PLAYLIST";
|
$playlists[$pkey]['source'] = "PLAYLIST";
|
||||||
$playlists[$pkey]['x_ident'] = $dx["playlist_id"];
|
$playlists[$pkey]['x_ident'] = $dx['group_id'];
|
||||||
$playlists[$pkey]['subtype'] = '1'; // Just needs to be between 1 and 4 inclusive
|
$playlists[$pkey]['subtype'] = '1'; // Just needs to be between 1 and 4 inclusive
|
||||||
$playlists[$pkey]['timestamp'] = $timestamp;
|
$playlists[$pkey]['timestamp'] = $timestamp;
|
||||||
$playlists[$pkey]['duration'] = $dx['clip_length'];
|
$playlists[$pkey]['duration'] = $dx['clip_length'];
|
||||||
|
@ -695,9 +664,9 @@ class Schedule {
|
||||||
$playlists[$pkey]['schedule_id'] = $dx['group_id'];
|
$playlists[$pkey]['schedule_id'] = $dx['group_id'];
|
||||||
$playlists[$pkey]['show_name'] = $dx['show_name'];
|
$playlists[$pkey]['show_name'] = $dx['show_name'];
|
||||||
$playlists[$pkey]['user_id'] = 0;
|
$playlists[$pkey]['user_id'] = 0;
|
||||||
$playlists[$pkey]['id'] = $dx["playlist_id"];
|
$playlists[$pkey]['id'] = $dx['group_id'];
|
||||||
$playlists[$pkey]['start'] = Schedule::CcTimeToPypoTime($dx["start"]);
|
$playlists[$pkey]['start'] = Schedule::AirtimeTimeToPypoTime($dx["start"]);
|
||||||
$playlists[$pkey]['end'] = Schedule::CcTimeToPypoTime($dx["end"]);
|
$playlists[$pkey]['end'] = Schedule::AirtimeTimeToPypoTime($dx["end"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -734,30 +703,15 @@ class Schedule {
|
||||||
|
|
||||||
$result = array();
|
$result = array();
|
||||||
$result['status'] = array('range' => array('start' => $range_start, 'end' => $range_end),
|
$result['status'] = array('range' => array('start' => $range_start, 'end' => $range_end),
|
||||||
'version' => "1.1");
|
'version' => AIRTIME_REST_VERSION);
|
||||||
$result['playlists'] = $playlists;
|
$result['playlists'] = $playlists;
|
||||||
$result['check'] = 1;
|
$result['check'] = 1;
|
||||||
|
$result['stream_metadata'] = array();
|
||||||
|
$result['stream_metadata']['format'] = Application_Model_Preference::GetStreamLabelFormat();
|
||||||
|
$result['stream_metadata']['station_name'] = Application_Model_Preference::GetStationName();
|
||||||
|
$result['server_timezone'] = date('O');
|
||||||
|
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove all items from the schedule in the given range.
|
|
||||||
*
|
|
||||||
* @param string $p_start
|
|
||||||
* In the format YYYY-MM-DD HH:MM:SS.nnnnnn
|
|
||||||
* @param string $p_end
|
|
||||||
* In the format YYYY-MM-DD HH:MM:SS.nnnnnn
|
|
||||||
*/
|
|
||||||
public static function RemoveItemsInRange($p_start, $p_end)
|
|
||||||
{
|
|
||||||
$items = Schedule::GetItems($p_start, $p_end);
|
|
||||||
foreach ($items as $item) {
|
|
||||||
$scheduleGroup = new ScheduleGroup($item["group_id"]);
|
|
||||||
$scheduleGroup->remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,50 +6,60 @@ class Show {
|
||||||
|
|
||||||
public function __construct($showId=NULL)
|
public function __construct($showId=NULL)
|
||||||
{
|
{
|
||||||
$this->_showId = $showId;
|
$this->_showId = $showId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() {
|
public function getName()
|
||||||
|
{
|
||||||
$show = CcShowQuery::create()->findPK($this->_showId);
|
$show = CcShowQuery::create()->findPK($this->_showId);
|
||||||
return $show->getDbName();
|
return $show->getDbName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setName($name) {
|
public function setName($name)
|
||||||
|
{
|
||||||
$show = CcShowQuery::create()->findPK($this->_showId);
|
$show = CcShowQuery::create()->findPK($this->_showId);
|
||||||
$show->setDbName($name);
|
$show->setDbName($name);
|
||||||
|
RabbitMq::PushSchedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDescription() {
|
public function getDescription()
|
||||||
|
{
|
||||||
$show = CcShowQuery::create()->findPK($this->_showId);
|
$show = CcShowQuery::create()->findPK($this->_showId);
|
||||||
return $show->getDbDescription();
|
return $show->getDbDescription();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setDescription($description) {
|
public function setDescription($description)
|
||||||
|
{
|
||||||
$show = CcShowQuery::create()->findPK($this->_showId);
|
$show = CcShowQuery::create()->findPK($this->_showId);
|
||||||
$show->setDbDescription($description);
|
$show->setDbDescription($description);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getColor() {
|
public function getColor()
|
||||||
|
{
|
||||||
$show = CcShowQuery::create()->findPK($this->_showId);
|
$show = CcShowQuery::create()->findPK($this->_showId);
|
||||||
return $show->getDbColor();
|
return $show->getDbColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setColor($color) {
|
public function setColor($color)
|
||||||
|
{
|
||||||
$show = CcShowQuery::create()->findPK($this->_showId);
|
$show = CcShowQuery::create()->findPK($this->_showId);
|
||||||
$show->setDbColor($color);
|
$show->setDbColor($color);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getBackgroundColor() {
|
public function getBackgroundColor()
|
||||||
|
{
|
||||||
$show = CcShowQuery::create()->findPK($this->_showId);
|
$show = CcShowQuery::create()->findPK($this->_showId);
|
||||||
return $show->getDbBackgroundColor();
|
return $show->getDbBackgroundColor();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setBackgroundColor($backgroundColor) {
|
public function setBackgroundColor($backgroundColor)
|
||||||
|
{
|
||||||
$show = CcShowQuery::create()->findPK($this->_showId);
|
$show = CcShowQuery::create()->findPK($this->_showId);
|
||||||
$show->setDbBackgroundColor($backgroundColor);
|
$show->setDbBackgroundColor($backgroundColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function cancelShow($day_timestamp) {
|
public function cancelShow($day_timestamp)
|
||||||
|
{
|
||||||
global $CC_DBC;
|
global $CC_DBC;
|
||||||
|
|
||||||
$timeinfo = explode(" ", $day_timestamp);
|
$timeinfo = explode(" ", $day_timestamp);
|
||||||
|
@ -62,20 +72,21 @@ class Show {
|
||||||
WHERE starts >= '{$day_timestamp}' AND show_id = {$this->_showId}";
|
WHERE starts >= '{$day_timestamp}' AND show_id = {$this->_showId}";
|
||||||
|
|
||||||
$CC_DBC->query($sql);
|
$CC_DBC->query($sql);
|
||||||
|
RabbitMq::PushSchedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
//end dates are non inclusive.
|
//end dates are non inclusive.
|
||||||
public static function addShow($data) {
|
public static function addShow($data)
|
||||||
|
{
|
||||||
$con = Propel::getConnection(CcShowPeer::DATABASE_NAME);
|
$con = Propel::getConnection(CcShowPeer::DATABASE_NAME);
|
||||||
|
|
||||||
$sql = "SELECT time '{$data['add_show_start_time']}' + INTERVAL '{$data['add_show_duration']} hour' ";
|
$sql = "SELECT time '{$data['add_show_start_time']}' + INTERVAL '{$data['add_show_duration']} hour' ";
|
||||||
$r = $con->query($sql);
|
$r = $con->query($sql);
|
||||||
$endTime = $r->fetchColumn(0);
|
$endTime = $r->fetchColumn(0);
|
||||||
|
|
||||||
$sql = "SELECT EXTRACT(DOW FROM TIMESTAMP '{$data['add_show_start_date']} {$data['add_show_start_time']}')";
|
$sql = "SELECT EXTRACT(DOW FROM TIMESTAMP '{$data['add_show_start_date']} {$data['add_show_start_time']}')";
|
||||||
$r = $con->query($sql);
|
$r = $con->query($sql);
|
||||||
$startDow = $r->fetchColumn(0);
|
$startDow = $r->fetchColumn(0);
|
||||||
|
|
||||||
if($data['add_show_no_end']) {
|
if($data['add_show_no_end']) {
|
||||||
$endDate = NULL;
|
$endDate = NULL;
|
||||||
|
@ -84,13 +95,13 @@ class Show {
|
||||||
else if($data['add_show_repeats']) {
|
else if($data['add_show_repeats']) {
|
||||||
$sql = "SELECT date '{$data['add_show_end_date']}' + INTERVAL '1 day' ";
|
$sql = "SELECT date '{$data['add_show_end_date']}' + INTERVAL '1 day' ";
|
||||||
$r = $con->query($sql);
|
$r = $con->query($sql);
|
||||||
$endDate = $r->fetchColumn(0);
|
$endDate = $r->fetchColumn(0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$sql = "SELECT date '{$data['add_show_start_date']}' + INTERVAL '1 day' ";
|
$sql = "SELECT date '{$data['add_show_start_date']}' + INTERVAL '1 day' ";
|
||||||
$r = $con->query($sql);
|
$r = $con->query($sql);
|
||||||
$endDate = $r->fetchColumn(0);
|
$endDate = $r->fetchColumn(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
//only want the day of the week from the start date.
|
//only want the day of the week from the start date.
|
||||||
if(!$data['add_show_repeats']) {
|
if(!$data['add_show_repeats']) {
|
||||||
|
@ -98,7 +109,7 @@ class Show {
|
||||||
}
|
}
|
||||||
else if($data['add_show_repeats'] && $data['add_show_day_check'] == "") {
|
else if($data['add_show_repeats'] && $data['add_show_day_check'] == "") {
|
||||||
$data['add_show_day_check'] = array($startDow);
|
$data['add_show_day_check'] = array($startDow);
|
||||||
}
|
}
|
||||||
|
|
||||||
//find repeat type or set to a non repeating show.
|
//find repeat type or set to a non repeating show.
|
||||||
if($data['add_show_repeats']) {
|
if($data['add_show_repeats']) {
|
||||||
|
@ -114,7 +125,7 @@ class Show {
|
||||||
$show->setDbUrl($data['add_show_url']);
|
$show->setDbUrl($data['add_show_url']);
|
||||||
$show->setDbColor($data['add_show_color']);
|
$show->setDbColor($data['add_show_color']);
|
||||||
$show->setDbBackgroundColor($data['add_show_background_color']);
|
$show->setDbBackgroundColor($data['add_show_background_color']);
|
||||||
$show->save();
|
$show->save();
|
||||||
|
|
||||||
$showId = $show->getDbId();
|
$showId = $show->getDbId();
|
||||||
|
|
||||||
|
@ -127,7 +138,6 @@ class Show {
|
||||||
|
|
||||||
//don't set day for monthly repeat type, it's invalid.
|
//don't set day for monthly repeat type, it's invalid.
|
||||||
if($data['add_show_repeats'] && $data["add_show_repeat_type"] == 2) {
|
if($data['add_show_repeats'] && $data["add_show_repeat_type"] == 2) {
|
||||||
|
|
||||||
$showDay = new CcShowDays();
|
$showDay = new CcShowDays();
|
||||||
$showDay->setDbFirstShow($data['add_show_start_date']);
|
$showDay->setDbFirstShow($data['add_show_start_date']);
|
||||||
$showDay->setDbLastShow($endDate);
|
$showDay->setDbLastShow($endDate);
|
||||||
|
@ -137,29 +147,25 @@ class Show {
|
||||||
$showDay->setDbShowId($showId);
|
$showDay->setDbShowId($showId);
|
||||||
$showDay->setDbRecord($isRecorded);
|
$showDay->setDbRecord($isRecorded);
|
||||||
$showDay->save();
|
$showDay->save();
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
foreach ($data['add_show_day_check'] as $day) {
|
foreach ($data['add_show_day_check'] as $day) {
|
||||||
|
|
||||||
if($startDow !== $day){
|
if($startDow !== $day){
|
||||||
|
|
||||||
if($startDow > $day)
|
if ($startDow > $day)
|
||||||
$daysAdd = 6 - $startDow + 1 + $day;
|
$daysAdd = 6 - $startDow + 1 + $day;
|
||||||
else
|
else
|
||||||
$daysAdd = $day - $startDow;
|
$daysAdd = $day - $startDow;
|
||||||
|
|
||||||
$sql = "SELECT date '{$data['add_show_start_date']}' + INTERVAL '{$daysAdd} day' ";
|
$sql = "SELECT date '{$data['add_show_start_date']}' + INTERVAL '{$daysAdd} day' ";
|
||||||
$r = $con->query($sql);
|
$r = $con->query($sql);
|
||||||
$start = $r->fetchColumn(0);
|
$start = $r->fetchColumn(0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$start = $data['add_show_start_date'];
|
$start = $data['add_show_start_date'];
|
||||||
}
|
}
|
||||||
|
|
||||||
if(strtotime($start) < strtotime($endDate) || is_null($endDate)) {
|
if(strtotime($start) < strtotime($endDate) || is_null($endDate)) {
|
||||||
|
|
||||||
$showDay = new CcShowDays();
|
$showDay = new CcShowDays();
|
||||||
$showDay->setDbFirstShow($start);
|
$showDay->setDbFirstShow($start);
|
||||||
$showDay->setDbLastShow($endDate);
|
$showDay->setDbLastShow($endDate);
|
||||||
|
@ -180,7 +186,6 @@ class Show {
|
||||||
for($i=1; $i<=5; $i++) {
|
for($i=1; $i<=5; $i++) {
|
||||||
|
|
||||||
if($data['add_show_rebroadcast_date_'.$i]) {
|
if($data['add_show_rebroadcast_date_'.$i]) {
|
||||||
|
|
||||||
$showRebroad = new CcShowRebroadcast();
|
$showRebroad = new CcShowRebroadcast();
|
||||||
$showRebroad->setDbDayOffset($data['add_show_rebroadcast_date_'.$i]);
|
$showRebroad->setDbDayOffset($data['add_show_rebroadcast_date_'.$i]);
|
||||||
$showRebroad->setDbStartTime($data['add_show_rebroadcast_time_'.$i]);
|
$showRebroad->setDbStartTime($data['add_show_rebroadcast_time_'.$i]);
|
||||||
|
@ -190,14 +195,13 @@ class Show {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if($data['add_show_record'] && $data['add_show_rebroadcast'] && $repeat_type == -1){
|
else if($data['add_show_record'] && $data['add_show_rebroadcast'] && $repeat_type == -1){
|
||||||
|
|
||||||
for($i=1; $i<=5; $i++) {
|
for($i=1; $i<=5; $i++) {
|
||||||
|
|
||||||
if($data['add_show_rebroadcast_absolute_date_'.$i]) {
|
if($data['add_show_rebroadcast_absolute_date_'.$i]) {
|
||||||
|
|
||||||
$sql = "SELECT date '{$data['add_show_rebroadcast_absolute_date_'.$i]}' - date '{$data['add_show_start_date']}' ";
|
$sql = "SELECT date '{$data['add_show_rebroadcast_absolute_date_'.$i]}' - date '{$data['add_show_start_date']}' ";
|
||||||
$r = $con->query($sql);
|
$r = $con->query($sql);
|
||||||
$offset_days = $r->fetchColumn(0);
|
$offset_days = $r->fetchColumn(0);
|
||||||
|
|
||||||
$showRebroad = new CcShowRebroadcast();
|
$showRebroad = new CcShowRebroadcast();
|
||||||
$showRebroad->setDbDayOffset($offset_days." days");
|
$showRebroad->setDbDayOffset($offset_days." days");
|
||||||
|
@ -207,7 +211,7 @@ class Show {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(is_array($data['add_show_hosts'])) {
|
if(is_array($data['add_show_hosts'])) {
|
||||||
//add selected hosts to cc_show_hosts table.
|
//add selected hosts to cc_show_hosts table.
|
||||||
foreach ($data['add_show_hosts'] as $host) {
|
foreach ($data['add_show_hosts'] as $host) {
|
||||||
|
@ -219,18 +223,20 @@ class Show {
|
||||||
}
|
}
|
||||||
|
|
||||||
Show::populateShowUntilLastGeneratedDate($showId);
|
Show::populateShowUntilLastGeneratedDate($showId);
|
||||||
|
RabbitMq::PushSchedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getShows($start_timestamp, $end_timestamp, $excludeInstance=NULL, $onlyRecord=FALSE) {
|
public static function getShows($start_timestamp, $end_timestamp, $excludeInstance=NULL, $onlyRecord=FALSE)
|
||||||
|
{
|
||||||
global $CC_DBC;
|
global $CC_DBC;
|
||||||
|
|
||||||
$sql = "SELECT starts, ends, record, rebroadcast, instance_id, show_id, name, description,
|
$sql = "SELECT starts, ends, record, rebroadcast, instance_id, show_id, name, description,
|
||||||
color, background_color, cc_show_instances.id AS instance_id
|
color, background_color, cc_show_instances.id AS instance_id
|
||||||
FROM cc_show_instances
|
FROM cc_show_instances
|
||||||
LEFT JOIN cc_show ON cc_show.id = cc_show_instances.show_id";
|
LEFT JOIN cc_show ON cc_show.id = cc_show_instances.show_id";
|
||||||
|
|
||||||
//only want shows that are starting at the time or later.
|
//only want shows that are starting at the time or later.
|
||||||
if($onlyRecord) {
|
if ($onlyRecord) {
|
||||||
|
|
||||||
$sql = $sql." WHERE (starts >= '{$start_timestamp}' AND starts < timestamp '{$start_timestamp}' + interval '2 hours')";
|
$sql = $sql." WHERE (starts >= '{$start_timestamp}' AND starts < timestamp '{$start_timestamp}' + interval '2 hours')";
|
||||||
$sql = $sql." AND (record = 1)";
|
$sql = $sql." AND (record = 1)";
|
||||||
|
@ -240,10 +246,10 @@ class Show {
|
||||||
$sql = $sql." WHERE ((starts >= '{$start_timestamp}' AND starts < '{$end_timestamp}')
|
$sql = $sql." WHERE ((starts >= '{$start_timestamp}' AND starts < '{$end_timestamp}')
|
||||||
OR (ends > '{$start_timestamp}' AND ends <= '{$end_timestamp}')
|
OR (ends > '{$start_timestamp}' AND ends <= '{$end_timestamp}')
|
||||||
OR (starts <= '{$start_timestamp}' AND ends >= '{$end_timestamp}'))";
|
OR (starts <= '{$start_timestamp}' AND ends >= '{$end_timestamp}'))";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(isset($excludeInstance)) {
|
|
||||||
|
if (isset($excludeInstance)) {
|
||||||
foreach($excludeInstance as $instance) {
|
foreach($excludeInstance as $instance) {
|
||||||
$sql_exclude[] = "cc_show_instances.id != {$instance}";
|
$sql_exclude[] = "cc_show_instances.id != {$instance}";
|
||||||
}
|
}
|
||||||
|
@ -257,8 +263,8 @@ class Show {
|
||||||
return $CC_DBC->GetAll($sql);
|
return $CC_DBC->GetAll($sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function setNextPop($next_date, $show_id, $day) {
|
private static function setNextPop($next_date, $show_id, $day)
|
||||||
|
{
|
||||||
$nextInfo = explode(" ", $next_date);
|
$nextInfo = explode(" ", $next_date);
|
||||||
|
|
||||||
$repeatInfo = CcShowDaysQuery::create()
|
$repeatInfo = CcShowDaysQuery::create()
|
||||||
|
@ -271,15 +277,16 @@ class Show {
|
||||||
}
|
}
|
||||||
|
|
||||||
//for a show with repeat_type == -1
|
//for a show with repeat_type == -1
|
||||||
private static function populateNonRepeatingShow($show_id, $first_show, $start_time, $duration, $day, $record, $end_timestamp) {
|
private static function populateNonRepeatingShow($show_id, $first_show, $start_time, $duration, $day, $record, $end_timestamp)
|
||||||
|
{
|
||||||
global $CC_DBC;
|
global $CC_DBC;
|
||||||
|
|
||||||
$next_date = $first_show." ".$start_time;
|
$next_date = $first_show." ".$start_time;
|
||||||
|
|
||||||
if(strtotime($next_date) < strtotime($end_timestamp)) {
|
if(strtotime($next_date) < strtotime($end_timestamp)) {
|
||||||
|
|
||||||
$start = $next_date;
|
$start = $next_date;
|
||||||
|
|
||||||
$sql = "SELECT timestamp '{$start}' + interval '{$duration}'";
|
$sql = "SELECT timestamp '{$start}' + interval '{$duration}'";
|
||||||
$end = $CC_DBC->GetOne($sql);
|
$end = $CC_DBC->GetOne($sql);
|
||||||
|
|
||||||
|
@ -298,10 +305,10 @@ class Show {
|
||||||
foreach($rebroadcasts as $rebroadcast) {
|
foreach($rebroadcasts as $rebroadcast) {
|
||||||
|
|
||||||
$timeinfo = explode(" ", $start);
|
$timeinfo = explode(" ", $start);
|
||||||
|
|
||||||
$sql = "SELECT timestamp '{$timeinfo[0]}' + interval '{$rebroadcast["day_offset"]}' + interval '{$rebroadcast["start_time"]}'";
|
$sql = "SELECT timestamp '{$timeinfo[0]}' + interval '{$rebroadcast["day_offset"]}' + interval '{$rebroadcast["start_time"]}'";
|
||||||
$rebroadcast_start_time = $CC_DBC->GetOne($sql);
|
$rebroadcast_start_time = $CC_DBC->GetOne($sql);
|
||||||
|
|
||||||
$sql = "SELECT timestamp '{$rebroadcast_start_time}' + interval '{$duration}'";
|
$sql = "SELECT timestamp '{$rebroadcast_start_time}' + interval '{$duration}'";
|
||||||
$rebroadcast_end_time = $CC_DBC->GetOne($sql);
|
$rebroadcast_end_time = $CC_DBC->GetOne($sql);
|
||||||
|
|
||||||
|
@ -315,12 +322,13 @@ class Show {
|
||||||
$newRebroadcastInstance->save();
|
$newRebroadcastInstance->save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
RabbitMq::PushSchedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
//for a show with repeat_type == 0,1,2
|
//for a show with repeat_type == 0,1,2
|
||||||
private static function populateRepeatingShow($show_id, $next_pop_date, $first_show, $last_show,
|
private static function populateRepeatingShow($show_id, $next_pop_date, $first_show, $last_show,
|
||||||
$start_time, $duration, $day, $record, $end_timestamp, $interval) {
|
$start_time, $duration, $day, $record, $end_timestamp, $interval) {
|
||||||
global $CC_DBC;
|
global $CC_DBC;
|
||||||
|
|
||||||
if(isset($next_pop_date)) {
|
if(isset($next_pop_date)) {
|
||||||
$next_date = $next_pop_date." ".$start_time;
|
$next_date = $next_pop_date." ".$start_time;
|
||||||
|
@ -333,9 +341,9 @@ class Show {
|
||||||
$rebroadcasts = $CC_DBC->GetAll($sql);
|
$rebroadcasts = $CC_DBC->GetAll($sql);
|
||||||
|
|
||||||
while(strtotime($next_date) < strtotime($end_timestamp) && (strtotime($last_show) > strtotime($next_date) || is_null($last_show))) {
|
while(strtotime($next_date) < strtotime($end_timestamp) && (strtotime($last_show) > strtotime($next_date) || is_null($last_show))) {
|
||||||
|
|
||||||
$start = $next_date;
|
$start = $next_date;
|
||||||
|
|
||||||
$sql = "SELECT timestamp '{$start}' + interval '{$duration}'";
|
$sql = "SELECT timestamp '{$start}' + interval '{$duration}'";
|
||||||
$end = $CC_DBC->GetOne($sql);
|
$end = $CC_DBC->GetOne($sql);
|
||||||
|
|
||||||
|
@ -351,10 +359,10 @@ class Show {
|
||||||
foreach($rebroadcasts as $rebroadcast) {
|
foreach($rebroadcasts as $rebroadcast) {
|
||||||
|
|
||||||
$timeinfo = explode(" ", $next_date);
|
$timeinfo = explode(" ", $next_date);
|
||||||
|
|
||||||
$sql = "SELECT timestamp '{$timeinfo[0]}' + interval '{$rebroadcast["day_offset"]}' + interval '{$rebroadcast["start_time"]}'";
|
$sql = "SELECT timestamp '{$timeinfo[0]}' + interval '{$rebroadcast["day_offset"]}' + interval '{$rebroadcast["start_time"]}'";
|
||||||
$rebroadcast_start_time = $CC_DBC->GetOne($sql);
|
$rebroadcast_start_time = $CC_DBC->GetOne($sql);
|
||||||
|
|
||||||
$sql = "SELECT timestamp '{$rebroadcast_start_time}' + interval '{$duration}'";
|
$sql = "SELECT timestamp '{$rebroadcast_start_time}' + interval '{$duration}'";
|
||||||
$rebroadcast_end_time = $CC_DBC->GetOne($sql);
|
$rebroadcast_end_time = $CC_DBC->GetOne($sql);
|
||||||
|
|
||||||
|
@ -373,64 +381,65 @@ class Show {
|
||||||
}
|
}
|
||||||
|
|
||||||
Show::setNextPop($next_date, $show_id, $day);
|
Show::setNextPop($next_date, $show_id, $day);
|
||||||
|
RabbitMq::PushSchedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function populateShow($repeat_type, $show_id, $next_pop_date,
|
private static function populateShow($repeat_type, $show_id, $next_pop_date,
|
||||||
$first_show, $last_show, $start_time, $duration, $day, $record, $end_timestamp) {
|
$first_show, $last_show, $start_time, $duration, $day, $record, $end_timestamp) {
|
||||||
|
|
||||||
if($repeat_type == -1) {
|
if($repeat_type == -1) {
|
||||||
Show::populateNonRepeatingShow($show_id, $first_show, $start_time, $duration, $day, $record, $end_timestamp);
|
Show::populateNonRepeatingShow($show_id, $first_show, $start_time, $duration, $day, $record, $end_timestamp);
|
||||||
}
|
}
|
||||||
else if($repeat_type == 0) {
|
else if($repeat_type == 0) {
|
||||||
Show::populateRepeatingShow($show_id, $next_pop_date, $first_show, $last_show,
|
Show::populateRepeatingShow($show_id, $next_pop_date, $first_show, $last_show,
|
||||||
$start_time, $duration, $day, $record, $end_timestamp, '7 days');
|
$start_time, $duration, $day, $record, $end_timestamp, '7 days');
|
||||||
}
|
}
|
||||||
else if($repeat_type == 1) {
|
else if($repeat_type == 1) {
|
||||||
Show::populateRepeatingShow($show_id, $next_pop_date, $first_show, $last_show,
|
Show::populateRepeatingShow($show_id, $next_pop_date, $first_show, $last_show,
|
||||||
$start_time, $duration, $day, $record, $end_timestamp, '14 days');
|
$start_time, $duration, $day, $record, $end_timestamp, '14 days');
|
||||||
}
|
}
|
||||||
else if($repeat_type == 2) {
|
else if($repeat_type == 2) {
|
||||||
Show::populateRepeatingShow($show_id, $next_pop_date, $first_show, $last_show,
|
Show::populateRepeatingShow($show_id, $next_pop_date, $first_show, $last_show,
|
||||||
$start_time, $duration, $day, $record, $end_timestamp, '1 month');
|
$start_time, $duration, $day, $record, $end_timestamp, '1 month');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//used to catch up a newly added show
|
//used to catch up a newly added show
|
||||||
private static function populateShowUntilLastGeneratedDate($show_id) {
|
private static function populateShowUntilLastGeneratedDate($show_id) {
|
||||||
global $CC_DBC;
|
global $CC_DBC;
|
||||||
$showsPopUntil = Application_Model_Preference::GetShowsPopulatedUntil();
|
$showsPopUntil = Application_Model_Preference::GetShowsPopulatedUntil();
|
||||||
|
|
||||||
$sql = "SELECT * FROM cc_show_days WHERE show_id = {$show_id}";
|
$sql = "SELECT * FROM cc_show_days WHERE show_id = {$show_id}";
|
||||||
$res = $CC_DBC->GetAll($sql);
|
$res = $CC_DBC->GetAll($sql);
|
||||||
|
|
||||||
foreach($res as $row) {
|
foreach($res as $row) {
|
||||||
Show::populateShow($row["repeat_type"], $row["show_id"], $row["next_pop_date"], $row["first_show"],
|
Show::populateShow($row["repeat_type"], $row["show_id"], $row["next_pop_date"], $row["first_show"],
|
||||||
$row["last_show"], $row["start_time"], $row["duration"], $row["day"], $row["record"], $showsPopUntil);
|
$row["last_show"], $row["start_time"], $row["duration"], $row["day"], $row["record"], $showsPopUntil);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function populateShowsUntil($pop_timestamp, $end_timestamp) {
|
public static function populateShowsUntil($pop_timestamp, $end_timestamp) {
|
||||||
global $CC_DBC;
|
global $CC_DBC;
|
||||||
|
|
||||||
if($pop_timestamp != "") {
|
if($pop_timestamp != "") {
|
||||||
$sql = "SELECT * FROM cc_show_days
|
$sql = "SELECT * FROM cc_show_days
|
||||||
WHERE last_show IS NULL
|
WHERE last_show IS NULL
|
||||||
OR first_show < '{$end_timestamp}' AND last_show > '{$pop_timestamp}'";
|
OR first_show < '{$end_timestamp}' AND last_show > '{$pop_timestamp}'";
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$today_timestamp = date("Y-m-d");
|
$today_timestamp = date("Y-m-d");
|
||||||
|
|
||||||
$sql = "SELECT * FROM cc_show_days
|
$sql = "SELECT * FROM cc_show_days
|
||||||
WHERE last_show IS NULL
|
WHERE last_show IS NULL
|
||||||
OR first_show < '{$end_timestamp}' AND last_show > '{$today_timestamp}'";
|
OR first_show < '{$end_timestamp}' AND last_show > '{$today_timestamp}'";
|
||||||
}
|
}
|
||||||
|
|
||||||
$res = $CC_DBC->GetAll($sql);
|
$res = $CC_DBC->GetAll($sql);
|
||||||
|
|
||||||
foreach($res as $row) {
|
foreach($res as $row) {
|
||||||
Show::populateShow($row["repeat_type"], $row["show_id"], $row["next_pop_date"], $row["first_show"],
|
Show::populateShow($row["repeat_type"], $row["show_id"], $row["next_pop_date"], $row["first_show"],
|
||||||
$row["last_show"], $row["start_time"], $row["duration"], $row["day"], $row["record"], $end_timestamp);
|
$row["last_show"], $row["start_time"], $row["duration"], $row["day"], $row["record"], $end_timestamp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getFullCalendarEvents($start, $end, $editable=false) {
|
public static function getFullCalendarEvents($start, $end, $editable=false) {
|
||||||
|
@ -460,19 +469,15 @@ class Show {
|
||||||
|
|
||||||
private static function makeFullCalendarEvent($show, $options=array()) {
|
private static function makeFullCalendarEvent($show, $options=array()) {
|
||||||
global $CC_DBC;
|
global $CC_DBC;
|
||||||
|
|
||||||
$event = array();
|
$event = array();
|
||||||
|
|
||||||
if($show["rebroadcast"]) {
|
if($show["rebroadcast"]) {
|
||||||
$title = "REBROADCAST ".$show["name"];
|
|
||||||
$event["disableResizing"] = true;
|
$event["disableResizing"] = true;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
$title = $show["name"];
|
|
||||||
}
|
|
||||||
|
|
||||||
$event["id"] = $show["instance_id"];
|
$event["id"] = $show["instance_id"];
|
||||||
$event["title"] = $title;
|
$event["title"] = $show["name"];
|
||||||
$event["start"] = $show["starts"];
|
$event["start"] = $show["starts"];
|
||||||
$event["end"] = $show["ends"];
|
$event["end"] = $show["ends"];
|
||||||
$event["allDay"] = false;
|
$event["allDay"] = false;
|
||||||
|
@ -500,56 +505,68 @@ class ShowInstance {
|
||||||
|
|
||||||
public function __construct($instanceId)
|
public function __construct($instanceId)
|
||||||
{
|
{
|
||||||
$this->_instanceId = $instanceId;
|
$this->_instanceId = $instanceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getShowId() {
|
public function getShowId()
|
||||||
|
{
|
||||||
$showInstance = CcShowInstancesQuery::create()->findPK($this->_instanceId);
|
$showInstance = CcShowInstancesQuery::create()->findPK($this->_instanceId);
|
||||||
return $showInstance->getDbShowId();
|
return $showInstance->getDbShowId();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getShowInstanceId() {
|
public function getShowInstanceId()
|
||||||
|
{
|
||||||
return $this->_instanceId;
|
return $this->_instanceId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isRebroadcast() {
|
public function isRebroadcast()
|
||||||
|
{
|
||||||
$showInstance = CcShowInstancesQuery::create()->findPK($this->_instanceId);
|
$showInstance = CcShowInstancesQuery::create()->findPK($this->_instanceId);
|
||||||
return $showInstance->getDbOriginalShow();
|
return $showInstance->getDbOriginalShow();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isRecorded() {
|
public function isRecorded()
|
||||||
|
{
|
||||||
$showInstance = CcShowInstancesQuery::create()->findPK($this->_instanceId);
|
$showInstance = CcShowInstancesQuery::create()->findPK($this->_instanceId);
|
||||||
return $showInstance->getDbRecord();
|
return $showInstance->getDbRecord();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName() {
|
public function getName()
|
||||||
|
{
|
||||||
$show = CcShowQuery::create()->findPK($this->getShowId());
|
$show = CcShowQuery::create()->findPK($this->getShowId());
|
||||||
return $show->getDbName();
|
return $show->getDbName();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getShowStart() {
|
public function getShowStart()
|
||||||
|
{
|
||||||
$showInstance = CcShowInstancesQuery::create()->findPK($this->_instanceId);
|
$showInstance = CcShowInstancesQuery::create()->findPK($this->_instanceId);
|
||||||
return $showInstance->getDbStarts();
|
return $showInstance->getDbStarts();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getShowEnd() {
|
public function getShowEnd()
|
||||||
|
{
|
||||||
$showInstance = CcShowInstancesQuery::create()->findPK($this->_instanceId);
|
$showInstance = CcShowInstancesQuery::create()->findPK($this->_instanceId);
|
||||||
return $showInstance->getDbEnds();
|
return $showInstance->getDbEnds();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setShowStart($start) {
|
public function setShowStart($start)
|
||||||
|
{
|
||||||
$showInstance = CcShowInstancesQuery::create()->findPK($this->_instanceId);
|
$showInstance = CcShowInstancesQuery::create()->findPK($this->_instanceId);
|
||||||
$showInstance->setDbStarts($start)
|
$showInstance->setDbStarts($start)
|
||||||
->save();
|
->save();
|
||||||
|
RabbitMq::PushSchedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setShowEnd($end) {
|
public function setShowEnd($end)
|
||||||
|
{
|
||||||
$showInstance = CcShowInstancesQuery::create()->findPK($this->_instanceId);
|
$showInstance = CcShowInstancesQuery::create()->findPK($this->_instanceId);
|
||||||
$showInstance->setDbEnds($end)
|
$showInstance->setDbEnds($end)
|
||||||
->save();
|
->save();
|
||||||
|
RabbitMq::PushSchedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function moveScheduledShowContent($deltaDay, $deltaHours, $deltaMin) {
|
public function moveScheduledShowContent($deltaDay, $deltaHours, $deltaMin)
|
||||||
|
{
|
||||||
global $CC_DBC;
|
global $CC_DBC;
|
||||||
|
|
||||||
$sql = "UPDATE cc_schedule
|
$sql = "UPDATE cc_schedule
|
||||||
|
@ -558,9 +575,11 @@ class ShowInstance {
|
||||||
WHERE instance_id = '{$this->_instanceId}'";
|
WHERE instance_id = '{$this->_instanceId}'";
|
||||||
|
|
||||||
$CC_DBC->query($sql);
|
$CC_DBC->query($sql);
|
||||||
|
RabbitMq::PushSchedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function moveShow($deltaDay, $deltaMin){
|
public function moveShow($deltaDay, $deltaMin)
|
||||||
|
{
|
||||||
global $CC_DBC;
|
global $CC_DBC;
|
||||||
|
|
||||||
$hours = $deltaMin/60;
|
$hours = $deltaMin/60;
|
||||||
|
@ -572,7 +591,7 @@ class ShowInstance {
|
||||||
$mins = abs($deltaMin%60);
|
$mins = abs($deltaMin%60);
|
||||||
|
|
||||||
$starts = $this->getShowStart();
|
$starts = $this->getShowStart();
|
||||||
$ends = $this->getShowEnd();
|
$ends = $this->getShowEnd();
|
||||||
|
|
||||||
$sql = "SELECT timestamp '{$starts}' + interval '{$deltaDay} days' + interval '{$hours}:{$mins}'";
|
$sql = "SELECT timestamp '{$starts}' + interval '{$deltaDay} days' + interval '{$hours}:{$mins}'";
|
||||||
$new_starts = $CC_DBC->GetOne($sql);
|
$new_starts = $CC_DBC->GetOne($sql);
|
||||||
|
@ -595,18 +614,20 @@ class ShowInstance {
|
||||||
if($rebroadcast) {
|
if($rebroadcast) {
|
||||||
$sql = "SELECT timestamp '{$new_starts}' < (SELECT starts FROM cc_show_instances WHERE id = {$rebroadcast})";
|
$sql = "SELECT timestamp '{$new_starts}' < (SELECT starts FROM cc_show_instances WHERE id = {$rebroadcast})";
|
||||||
$isBeforeRecordedOriginal = $CC_DBC->GetOne($sql);
|
$isBeforeRecordedOriginal = $CC_DBC->GetOne($sql);
|
||||||
|
|
||||||
if($isBeforeRecordedOriginal === 't'){
|
if($isBeforeRecordedOriginal === 't'){
|
||||||
return "Cannot move a rebroadcast show before its original";
|
return "Cannot move a rebroadcast show before its original";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->moveScheduledShowContent($deltaDay, $hours, $mins);
|
$this->moveScheduledShowContent($deltaDay, $hours, $mins);
|
||||||
$this->setShowStart($new_starts);
|
$this->setShowStart($new_starts);
|
||||||
$this->setShowEnd($new_ends);
|
$this->setShowEnd($new_ends);
|
||||||
|
RabbitMq::PushSchedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function resizeShow($deltaDay, $deltaMin){
|
public function resizeShow($deltaDay, $deltaMin)
|
||||||
|
{
|
||||||
global $CC_DBC;
|
global $CC_DBC;
|
||||||
|
|
||||||
$hours = $deltaMin/60;
|
$hours = $deltaMin/60;
|
||||||
|
@ -618,7 +639,7 @@ class ShowInstance {
|
||||||
$mins = abs($deltaMin%60);
|
$mins = abs($deltaMin%60);
|
||||||
|
|
||||||
$starts = $this->getShowStart();
|
$starts = $this->getShowStart();
|
||||||
$ends = $this->getShowEnd();
|
$ends = $this->getShowEnd();
|
||||||
|
|
||||||
$sql = "SELECT timestamp '{$ends}' + interval '{$deltaDay} days' + interval '{$hours}:{$mins}'";
|
$sql = "SELECT timestamp '{$ends}' + interval '{$deltaDay} days' + interval '{$hours}:{$mins}'";
|
||||||
$new_ends = $CC_DBC->GetOne($sql);
|
$new_ends = $CC_DBC->GetOne($sql);
|
||||||
|
@ -639,106 +660,142 @@ class ShowInstance {
|
||||||
WHERE rebroadcast = 1 AND instance_id = {$this->_instanceId}";
|
WHERE rebroadcast = 1 AND instance_id = {$this->_instanceId}";
|
||||||
$CC_DBC->query($sql);
|
$CC_DBC->query($sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->setShowEnd($new_ends);
|
$this->setShowEnd($new_ends);
|
||||||
|
RabbitMq::PushSchedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getLastGroupId() {
|
private function getLastGroupId()
|
||||||
|
{
|
||||||
global $CC_DBC;
|
global $CC_DBC;
|
||||||
|
|
||||||
$sql = "SELECT group_id FROM cc_schedule WHERE instance_id = '{$this->_instanceId}' ORDER BY ends DESC LIMIT 1";
|
$sql = "SELECT group_id FROM cc_schedule WHERE instance_id = '{$this->_instanceId}' ORDER BY ends DESC LIMIT 1";
|
||||||
$res = $CC_DBC->GetOne($sql);
|
$res = $CC_DBC->GetOne($sql);
|
||||||
|
|
||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function addPlaylistToShow($plId) {
|
public function addPlaylistToShow($plId)
|
||||||
|
{
|
||||||
$sched = new ScheduleGroup();
|
$sched = new ScheduleGroup();
|
||||||
$lastGroupId = $this->getLastGroupId();
|
$lastGroupId = $this->getLastGroupId();
|
||||||
|
|
||||||
if(is_null($lastGroupId)) {
|
if(is_null($lastGroupId)) {
|
||||||
|
|
||||||
$groupId = $sched->add($this->_instanceId, $this->getShowStart(), null, $plId);
|
$groupId = $sched->add($this->_instanceId, $this->getShowStart(), null, $plId);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$groupId = $sched->addPlaylistAfter($this->_instanceId, $lastGroupId, $plId);
|
$groupId = $sched->addPlaylistAfter($this->_instanceId, $lastGroupId, $plId);
|
||||||
}
|
}
|
||||||
|
RabbitMq::PushSchedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
public function scheduleShow($plIds) {
|
||||||
|
|
||||||
foreach($plIds as $plId) {
|
foreach($plIds as $plId) {
|
||||||
$this->addPlaylistToShow($plId);
|
$this->addPlaylistToShow($plId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function removeGroupFromShow($group_id){
|
public function removeGroupFromShow($group_id)
|
||||||
|
{
|
||||||
global $CC_DBC;
|
global $CC_DBC;
|
||||||
|
|
||||||
$sql = "SELECT MAX(ends) as end_timestamp, (MAX(ends) - MIN(starts)) as length
|
$sql = "SELECT MAX(ends) as end_timestamp, (MAX(ends) - MIN(starts)) as length
|
||||||
FROM cc_schedule
|
FROM cc_schedule
|
||||||
WHERE group_id = '{$group_id}'";
|
WHERE group_id = '{$group_id}'";
|
||||||
|
|
||||||
$groupBoundry = $CC_DBC->GetRow($sql);
|
$groupBoundry = $CC_DBC->GetRow($sql);
|
||||||
|
|
||||||
$group = CcScheduleQuery::create()
|
$group = CcScheduleQuery::create()
|
||||||
->filterByDbGroupId($group_id)
|
->filterByDbGroupId($group_id)
|
||||||
->delete();
|
->delete();
|
||||||
|
|
||||||
$sql = "UPDATE cc_schedule
|
$sql = "UPDATE cc_schedule
|
||||||
SET starts = (starts - INTERVAL '{$groupBoundry["length"]}'), ends = (ends - INTERVAL '{$groupBoundry["length"]}')
|
SET starts = (starts - INTERVAL '{$groupBoundry["length"]}'), ends = (ends - INTERVAL '{$groupBoundry["length"]}')
|
||||||
WHERE starts >= '{$groupBoundry["end_timestamp"]}' AND instance_id = {$this->_instanceId}";
|
WHERE starts >= '{$groupBoundry["end_timestamp"]}' AND instance_id = {$this->_instanceId}";
|
||||||
|
|
||||||
$CC_DBC->query($sql);
|
$CC_DBC->query($sql);
|
||||||
|
RabbitMq::PushSchedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function clearShow() {
|
public function clearShow()
|
||||||
|
{
|
||||||
CcScheduleQuery::create()
|
CcScheduleQuery::create()
|
||||||
->filterByDbInstanceId($this->_instanceId)
|
->filterByDbInstanceId($this->_instanceId)
|
||||||
->delete();
|
->delete();
|
||||||
|
RabbitMq::PushSchedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function deleteShow() {
|
public function deleteShow()
|
||||||
|
{
|
||||||
CcShowInstancesQuery::create()
|
CcShowInstancesQuery::create()
|
||||||
->findPK($this->_instanceId)
|
->findPK($this->_instanceId)
|
||||||
->delete();
|
->delete();
|
||||||
|
RabbitMq::PushSchedule();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTimeScheduled() {
|
public function setRecordedFile($file_id)
|
||||||
|
{
|
||||||
|
$showInstance = CcShowInstancesQuery::create()
|
||||||
|
->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()
|
||||||
|
{
|
||||||
$instance_id = $this->getShowInstanceId();
|
$instance_id = $this->getShowInstanceId();
|
||||||
$time = Schedule::GetTotalShowTime($instance_id);
|
$time = Schedule::GetTotalShowTime($instance_id);
|
||||||
|
|
||||||
return $time;
|
return $time;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getTimeUnScheduled() {
|
public function getTimeUnScheduled()
|
||||||
|
{
|
||||||
$start_timestamp = $this->getShowStart();
|
$start_timestamp = $this->getShowStart();
|
||||||
$end_timestamp = $this->getShowEnd();
|
$end_timestamp = $this->getShowEnd();
|
||||||
$instance_id = $this->getShowInstanceId();
|
$instance_id = $this->getShowInstanceId();
|
||||||
|
|
||||||
$time = Schedule::getTimeUnScheduledInRange($instance_id, $start_timestamp, $end_timestamp);
|
$time = Schedule::getTimeUnScheduledInRange($instance_id, $start_timestamp, $end_timestamp);
|
||||||
|
|
||||||
return $time;
|
return $time;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPercentScheduled() {
|
public function getPercentScheduled()
|
||||||
|
{
|
||||||
$start_timestamp = $this->getShowStart();
|
$start_timestamp = $this->getShowStart();
|
||||||
$end_timestamp = $this->getShowEnd();
|
$end_timestamp = $this->getShowEnd();
|
||||||
$instance_id = $this->getShowInstanceId();
|
$instance_id = $this->getShowInstanceId();
|
||||||
|
|
||||||
return Schedule::GetPercentScheduled($instance_id, $start_timestamp, $end_timestamp);
|
return Schedule::GetPercentScheduled($instance_id, $start_timestamp, $end_timestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getShowLength() {
|
public function getShowLength()
|
||||||
|
{
|
||||||
global $CC_DBC;
|
global $CC_DBC;
|
||||||
|
|
||||||
$start_timestamp = $this->getShowStart();
|
$start_timestamp = $this->getShowStart();
|
||||||
$end_timestamp = $this->getShowEnd();
|
$end_timestamp = $this->getShowEnd();
|
||||||
|
|
||||||
$sql = "SELECT TIMESTAMP '{$end_timestamp}' - TIMESTAMP '{$start_timestamp}' ";
|
$sql = "SELECT TIMESTAMP '{$end_timestamp}' - TIMESTAMP '{$start_timestamp}' ";
|
||||||
|
@ -747,26 +804,27 @@ class ShowInstance {
|
||||||
return $length;
|
return $length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function searchPlaylistsForShow($datatables){
|
public function searchPlaylistsForShow($datatables)
|
||||||
|
{
|
||||||
$time_remaining = $this->getTimeUnScheduled();
|
$time_remaining = $this->getTimeUnScheduled();
|
||||||
|
|
||||||
return StoredFile::searchPlaylistsForSchedule($time_remaining, $datatables);
|
return StoredFile::searchPlaylistsForSchedule($time_remaining, $datatables);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getShowListContent() {
|
public function getShowListContent()
|
||||||
|
{
|
||||||
global $CC_DBC;
|
global $CC_DBC;
|
||||||
|
|
||||||
$sql = "SELECT *
|
$sql = "SELECT *
|
||||||
FROM (cc_schedule AS s LEFT JOIN cc_files AS f ON f.id = s.file_id
|
FROM (cc_schedule AS s LEFT JOIN cc_files AS f ON f.id = s.file_id
|
||||||
LEFT JOIN cc_playlist AS p ON p.id = s.playlist_id )
|
LEFT JOIN cc_playlist AS p ON p.id = s.playlist_id )
|
||||||
|
|
||||||
WHERE s.instance_id = '{$this->_instanceId}' ORDER BY starts";
|
WHERE s.instance_id = '{$this->_instanceId}' ORDER BY starts";
|
||||||
|
|
||||||
return $CC_DBC->GetAll($sql);
|
return $CC_DBC->GetAll($sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getShowContent() {
|
public function getShowContent()
|
||||||
|
{
|
||||||
global $CC_DBC;
|
global $CC_DBC;
|
||||||
|
|
||||||
$res = $this->getShowListContent();
|
$res = $this->getShowListContent();
|
||||||
|
@ -788,7 +846,7 @@ class ShowInstance {
|
||||||
$items[$pl_counter]["pl_name"] = $row["name"];
|
$items[$pl_counter]["pl_name"] = $row["name"];
|
||||||
$items[$pl_counter]["pl_creator"] = $row["creator"];
|
$items[$pl_counter]["pl_creator"] = $row["creator"];
|
||||||
$items[$pl_counter]["pl_description"] = $row["description"];
|
$items[$pl_counter]["pl_description"] = $row["description"];
|
||||||
$items[$pl_counter]["pl_group"] = $row["group_id"];
|
$items[$pl_counter]["pl_group"] = $row["group_id"];
|
||||||
|
|
||||||
$sql = "SELECT SUM(clip_length) FROM cc_schedule WHERE group_id = '{$currGroupId}'";
|
$sql = "SELECT SUM(clip_length) FROM cc_schedule WHERE group_id = '{$currGroupId}'";
|
||||||
$length = $CC_DBC->GetOne($sql);
|
$length = $CC_DBC->GetOne($sql);
|
||||||
|
@ -802,46 +860,49 @@ class ShowInstance {
|
||||||
$items[$pl_counter]["pl_content"][$f_counter]["f_length"] = $row["length"];
|
$items[$pl_counter]["pl_content"][$f_counter]["f_length"] = $row["length"];
|
||||||
}
|
}
|
||||||
|
|
||||||
return $items;
|
return $items;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Show Data Access Layer */
|
/* Show Data Access Layer */
|
||||||
class Show_DAL{
|
class Show_DAL {
|
||||||
|
|
||||||
public static function GetCurrentShow($timeNow) {
|
public static function GetCurrentShow($timeNow)
|
||||||
|
{
|
||||||
global $CC_CONFIG, $CC_DBC;
|
global $CC_CONFIG, $CC_DBC;
|
||||||
|
|
||||||
$timestamp = explode(" ", $timeNow);
|
$timestamp = explode(" ", $timeNow);
|
||||||
$date = $timestamp[0];
|
$date = $timestamp[0];
|
||||||
$time = $timestamp[1];
|
$time = $timestamp[1];
|
||||||
|
|
||||||
$sql = "SELECT si.starts as start_timestamp, si.ends as end_timestamp, s.name, s.id, si.id as instance_id, si.record"
|
$sql = "SELECT si.starts as start_timestamp, si.ends as end_timestamp, s.name, s.id, si.id as instance_id, si.record"
|
||||||
." FROM $CC_CONFIG[showInstances] si, $CC_CONFIG[showTable] s"
|
." FROM $CC_CONFIG[showInstances] si, $CC_CONFIG[showTable] s"
|
||||||
." WHERE si.show_id = s.id"
|
." WHERE si.show_id = s.id"
|
||||||
." AND si.starts <= TIMESTAMP '$timeNow'"
|
." AND si.starts <= TIMESTAMP '$timeNow'"
|
||||||
." AND si.ends > TIMESTAMP '$timeNow'";
|
." AND si.ends > TIMESTAMP '$timeNow'";
|
||||||
|
|
||||||
$rows = $CC_DBC->GetAll($sql);
|
$rows = $CC_DBC->GetAll($sql);
|
||||||
return $rows;
|
return $rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function GetNextShow($timeNow) {
|
public static function GetNextShows($timeNow, $limit)
|
||||||
|
{
|
||||||
global $CC_CONFIG, $CC_DBC;
|
global $CC_CONFIG, $CC_DBC;
|
||||||
|
|
||||||
$sql = "SELECT *, si.starts as start_timestamp, si.ends as end_timestamp FROM "
|
$sql = "SELECT *, si.starts as start_timestamp, si.ends as end_timestamp FROM "
|
||||||
." $CC_CONFIG[showInstances] si, $CC_CONFIG[showTable] s"
|
." $CC_CONFIG[showInstances] si, $CC_CONFIG[showTable] s"
|
||||||
." WHERE si.show_id = s.id"
|
." WHERE si.show_id = s.id"
|
||||||
." AND si.starts >= TIMESTAMP '$timeNow'"
|
." AND si.starts >= TIMESTAMP '$timeNow'"
|
||||||
." AND si.starts < TIMESTAMP '$timeNow' + INTERVAL '48 hours'"
|
." AND si.starts < TIMESTAMP '$timeNow' + INTERVAL '48 hours'"
|
||||||
." ORDER BY si.starts"
|
." ORDER BY si.starts"
|
||||||
." LIMIT 1";
|
." LIMIT $limit";
|
||||||
|
|
||||||
$rows = $CC_DBC->GetAll($sql);
|
$rows = $CC_DBC->GetAll($sql);
|
||||||
return $rows;
|
return $rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function GetShowsInRange($timeNow, $start, $end){
|
public static function GetShowsInRange($timeNow, $start, $end)
|
||||||
|
{
|
||||||
global $CC_CONFIG, $CC_DBC;
|
global $CC_CONFIG, $CC_DBC;
|
||||||
$sql = "SELECT"
|
$sql = "SELECT"
|
||||||
." si.starts as show_starts,"
|
." si.starts as show_starts,"
|
||||||
|
@ -873,5 +934,5 @@ class Show_DAL{
|
||||||
|
|
||||||
return $CC_DBC->GetAll($sql);
|
return $CC_DBC->GetAll($sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
require_once 'soundcloud-api/Services/Soundcloud.php';
|
||||||
|
|
||||||
|
class ATSoundcloud {
|
||||||
|
|
||||||
|
private $_soundcloud;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
global $CC_CONFIG;
|
||||||
|
|
||||||
|
$this->_soundcloud = new Services_Soundcloud($CC_CONFIG['soundcloud-client-id'], $CC_CONFIG['soundcloud-client-secret']);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getToken()
|
||||||
|
{
|
||||||
|
$username = Application_Model_Preference::GetSoundCloudUser();
|
||||||
|
$password = Application_Model_Preference::GetSoundCloudPassword();
|
||||||
|
|
||||||
|
if($username === "" || $password === "")
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$token = $this->_soundcloud->accessTokenResourceOwner($username, $password);
|
||||||
|
|
||||||
|
return $token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function uploadTrack($filepath, $filename, $description, $tags=array())
|
||||||
|
{
|
||||||
|
if($this->getToken())
|
||||||
|
{
|
||||||
|
if(count($tags)) {
|
||||||
|
$tags = join(" ", $tags);
|
||||||
|
$tags = $tags." ".Application_Model_Preference::GetSoundCloudTags();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$tags = Application_Model_Preference::GetSoundCloudTags();
|
||||||
|
}
|
||||||
|
|
||||||
|
$track_data = array(
|
||||||
|
'track[sharing]' => 'private',
|
||||||
|
'track[title]' => $filename,
|
||||||
|
'track[asset_data]' => '@' . $filepath,
|
||||||
|
'track[tag_list]' => $tags,
|
||||||
|
'track[description]' => $description
|
||||||
|
);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$response = json_decode(
|
||||||
|
$this->_soundcloud->post('tracks', $track_data),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
|
echo var_dump($response);
|
||||||
|
}
|
||||||
|
catch (Services_Soundcloud_Invalid_Http_Response_Code_Exception $e) {
|
||||||
|
echo $e->getMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
echo "could not get soundcloud token";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1647,5 +1647,143 @@ class StoredFile {
|
||||||
return array("sEcho" => intval($data["sEcho"]), "iTotalDisplayRecords" => $totalDisplayRows, "iTotalRecords" => $totalRows, "aaData" => $results);
|
return array("sEcho" => intval($data["sEcho"]), "iTotalDisplayRecords" => $totalDisplayRows, "iTotalRecords" => $totalRows, "aaData" => $results);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function uploadFile($targetDir) {
|
||||||
|
|
||||||
|
// HTTP headers for no cache etc
|
||||||
|
header('Content-type: text/plain; charset=UTF-8');
|
||||||
|
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
|
||||||
|
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
|
||||||
|
header("Cache-Control: no-store, no-cache, must-revalidate");
|
||||||
|
header("Cache-Control: post-check=0, pre-check=0", false);
|
||||||
|
header("Pragma: no-cache");
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
//$targetDir = ini_get("upload_tmp_dir"); //. DIRECTORY_SEPARATOR . "plupload";
|
||||||
|
$cleanupTargetDir = false; // Remove old files
|
||||||
|
$maxFileAge = 60 * 60; // Temp file age in seconds
|
||||||
|
|
||||||
|
// 5 minutes execution time
|
||||||
|
@set_time_limit(5 * 60);
|
||||||
|
// usleep(5000);
|
||||||
|
|
||||||
|
// Get parameters
|
||||||
|
$chunk = isset($_REQUEST["chunk"]) ? $_REQUEST["chunk"] : 0;
|
||||||
|
$chunks = isset($_REQUEST["chunks"]) ? $_REQUEST["chunks"] : 0;
|
||||||
|
$fileName = isset($_REQUEST["name"]) ? $_REQUEST["name"] : '';
|
||||||
|
|
||||||
|
// Clean the fileName for security reasons
|
||||||
|
//$fileName = preg_replace('/[^\w\._]+/', '', $fileName);
|
||||||
|
|
||||||
|
// Create target dir
|
||||||
|
if (!file_exists($targetDir))
|
||||||
|
@mkdir($targetDir);
|
||||||
|
|
||||||
|
// Remove old temp files
|
||||||
|
if (is_dir($targetDir) && ($dir = opendir($targetDir))) {
|
||||||
|
while (($file = readdir($dir)) !== false) {
|
||||||
|
$filePath = $targetDir . DIRECTORY_SEPARATOR . $file;
|
||||||
|
|
||||||
|
// Remove temp files if they are older than the max age
|
||||||
|
if (preg_match('/\.tmp$/', $file) && (filemtime($filePath) < time() - $maxFileAge))
|
||||||
|
@unlink($filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
closedir($dir);
|
||||||
|
} else
|
||||||
|
die('{"jsonrpc" : "2.0", "error" : {"code": 100, "message": "Failed to open temp directory."}, "id" : "id"}');
|
||||||
|
|
||||||
|
// Look for the content type header
|
||||||
|
if (isset($_SERVER["HTTP_CONTENT_TYPE"]))
|
||||||
|
$contentType = $_SERVER["HTTP_CONTENT_TYPE"];
|
||||||
|
|
||||||
|
if (isset($_SERVER["CONTENT_TYPE"]))
|
||||||
|
$contentType = $_SERVER["CONTENT_TYPE"];
|
||||||
|
|
||||||
|
if (strpos($contentType, "multipart") !== false) {
|
||||||
|
if (isset($_FILES['file']['tmp_name']) && is_uploaded_file($_FILES['file']['tmp_name'])) {
|
||||||
|
// Open temp file
|
||||||
|
$out = fopen($targetDir . DIRECTORY_SEPARATOR . $fileName, $chunk == 0 ? "wb" : "ab");
|
||||||
|
if ($out) {
|
||||||
|
// Read binary input stream and append it to temp file
|
||||||
|
$in = fopen($_FILES['file']['tmp_name'], "rb");
|
||||||
|
|
||||||
|
if ($in) {
|
||||||
|
while ($buff = fread($in, 4096))
|
||||||
|
fwrite($out, $buff);
|
||||||
|
} else
|
||||||
|
die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "Failed to open input stream."}, "id" : "id"}');
|
||||||
|
|
||||||
|
fclose($out);
|
||||||
|
unlink($_FILES['file']['tmp_name']);
|
||||||
|
} else
|
||||||
|
die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to open output stream."}, "id" : "id"}');
|
||||||
|
} else
|
||||||
|
die('{"jsonrpc" : "2.0", "error" : {"code": 103, "message": "Failed to move uploaded file."}, "id" : "id"}');
|
||||||
|
} else {
|
||||||
|
// Open temp file
|
||||||
|
$out = fopen($targetDir . DIRECTORY_SEPARATOR . $fileName, $chunk == 0 ? "wb" : "ab");
|
||||||
|
if ($out) {
|
||||||
|
// Read binary input stream and append it to temp file
|
||||||
|
$in = fopen("php://input", "rb");
|
||||||
|
|
||||||
|
if ($in) {
|
||||||
|
while ($buff = fread($in, 4096))
|
||||||
|
fwrite($out, $buff);
|
||||||
|
} else
|
||||||
|
die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "Failed to open input stream."}, "id" : "id"}');
|
||||||
|
|
||||||
|
fclose($out);
|
||||||
|
} else
|
||||||
|
die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to open output stream."}, "id" : "id"}');
|
||||||
|
}
|
||||||
|
|
||||||
|
$audio_file = $targetDir . DIRECTORY_SEPARATOR . $fileName;
|
||||||
|
|
||||||
|
$md5 = md5_file($audio_file);
|
||||||
|
$duplicate = StoredFile::RecallByMd5($md5);
|
||||||
|
if ($duplicate) {
|
||||||
|
if (PEAR::isError($duplicate)) {
|
||||||
|
die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": ' . $duplicate->getMessage() .'}}');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$duplicateName = $duplicate->getMetadataValue(UI_MDATA_KEY_TITLE);
|
||||||
|
die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "An identical audioclip named ' . $duplicateName . ' already exists in the storage server."}}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$metadata = Metadata::LoadFromFile($audio_file);
|
||||||
|
|
||||||
|
if (PEAR::isError($metadata)) {
|
||||||
|
die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": ' + $metadata->getMessage() + '}}');
|
||||||
|
}
|
||||||
|
|
||||||
|
// #2196 no id tag -> use the original filename
|
||||||
|
if (basename($audio_file) == $metadata[UI_MDATA_KEY_TITLE]) {
|
||||||
|
$metadata[UI_MDATA_KEY_TITLE] = basename($audio_file);
|
||||||
|
$metadata[UI_MDATA_KEY_FILENAME] = basename($audio_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
// setMetadataBatch doesnt like these values
|
||||||
|
unset($metadata['audio']);
|
||||||
|
unset($metadata['playtime_seconds']);
|
||||||
|
|
||||||
|
$values = array(
|
||||||
|
"filename" => basename($audio_file),
|
||||||
|
"filepath" => $audio_file,
|
||||||
|
"filetype" => "audioclip",
|
||||||
|
"mime" => $metadata[UI_MDATA_KEY_FORMAT],
|
||||||
|
"md5" => $md5
|
||||||
|
);
|
||||||
|
$storedFile = StoredFile::Insert($values);
|
||||||
|
|
||||||
|
if (PEAR::isError($storedFile)) {
|
||||||
|
die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": ' + $storedFile->getMessage() + '}}');
|
||||||
|
}
|
||||||
|
|
||||||
|
$storedFile->setMetadataBatch($metadata);
|
||||||
|
|
||||||
|
return $storedFile;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,7 @@ class CcScheduleTableMap extends TableMap {
|
||||||
$this->setPrimaryKeyMethodInfo('cc_schedule_id_seq');
|
$this->setPrimaryKeyMethodInfo('cc_schedule_id_seq');
|
||||||
// columns
|
// columns
|
||||||
$this->addPrimaryKey('ID', 'DbId', 'INTEGER', true, null, null);
|
$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('STARTS', 'DbStarts', 'TIMESTAMP', true, null, null);
|
||||||
$this->addColumn('ENDS', 'DbEnds', 'TIMESTAMP', true, null, null);
|
$this->addColumn('ENDS', 'DbEnds', 'TIMESTAMP', true, null, null);
|
||||||
$this->addColumn('GROUP_ID', 'DbGroupId', 'INTEGER', false, null, null);
|
$this->addColumn('GROUP_ID', 'DbGroupId', 'INTEGER', false, null, null);
|
||||||
|
|
|
@ -110,6 +110,7 @@ class SchedulerTests extends PHPUnit_TestCase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
function testGetItems() {
|
function testGetItems() {
|
||||||
$i1 = new ScheduleGroup();
|
$i1 = new ScheduleGroup();
|
||||||
$groupId1 = $i1->add('2008-01-01 12:00:00.000', $this->storedFile->getId());
|
$groupId1 = $i1->add('2008-01-01 12:00:00.000', $this->storedFile->getId());
|
||||||
|
@ -123,5 +124,6 @@ class SchedulerTests extends PHPUnit_TestCase {
|
||||||
$i1->remove();
|
$i1->remove();
|
||||||
$i2->remove();
|
$i2->remove();
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
require_once 'soundcloud-api/Services/Soundcloud.php';
|
|
||||||
|
|
||||||
class Airtime_View_Helper_SoundCloudLink extends Zend_View_Helper_Abstract
|
|
||||||
{
|
|
||||||
public function soundCloudLink()
|
|
||||||
{
|
|
||||||
$request = Zend_Controller_Front::getInstance()->getRequest();
|
|
||||||
$host = $request->getHttpHost();
|
|
||||||
$controller = $request->getControllerName();
|
|
||||||
$action = $request->getActionName();
|
|
||||||
|
|
||||||
$redirectUrl = "http://{$host}/{$controller}/{$action}";
|
|
||||||
|
|
||||||
$soundcloud = new Services_Soundcloud('2CLCxcSXYzx7QhhPVHN4A', 'pZ7beWmF06epXLHVUP1ufOg2oEnIt9XhE8l8xt0bBs', $redirectUrl);
|
|
||||||
$authorizeUrl = $soundcloud->getAuthorizeUrl();
|
|
||||||
|
|
||||||
return $authorizeUrl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
<div class="now-playing-info show">
|
<div class="now-playing-info show">
|
||||||
<div class="recording-show" style="display: none;"></div>
|
<div class="recording-show" style="display: none;"></div>
|
||||||
<span id="playlist"></span>
|
<span id="playlist"></span>
|
||||||
<span class="lenght">00:00</span>
|
<span id="show-length" class="show-length"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="progressbar">
|
<div class="progressbar">
|
||||||
<div class="progress-show" id='progress-show' style="width:0%;"></div>
|
<div class="progress-show" id='progress-show' style="width:0%;"></div>
|
||||||
|
@ -43,6 +43,6 @@
|
||||||
<div id="jquery_jplayer_1" class="jp-jplayer" style="width:0px; height:0px;"></div>
|
<div id="jquery_jplayer_1" class="jp-jplayer" style="width:0px; height:0px;"></div>
|
||||||
|
|
||||||
<div id="about-txt" style="display: none;">
|
<div id="about-txt" style="display: none;">
|
||||||
<a href="http://airtime.sourcefabric.org">Airtime</a>, the open radio software for scheduling and remote station management.<br>
|
<a href="http://airtime.sourcefabric.org">Airtime</a> <?php echo AIRTIME_VERSION ?>, the open radio software for scheduling and remote station management.<br>
|
||||||
© 2011 <a href="http://www.sourcefabric.org">Sourcefabric</a> o.p.s 2011. Airtime is distributed under the <a href="http://www.gnu.org/licenses/gpl-3.0-standalone.html">GNU GPL v.3</a>
|
© 2011 <a href="http://www.sourcefabric.org">Sourcefabric</a> o.p.s 2011. Airtime is distributed under the <a href="http://www.gnu.org/licenses/gpl-3.0-standalone.html">GNU GPL v.3</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
<div class="text-row top">
|
<div class="text-row top">
|
||||||
<span class="spl_playlength"><?php echo $item["cliplength"] ?></span>
|
<span class="spl_playlength"><?php echo $item["cliplength"] ?></span>
|
||||||
|
<span class="spl_cue ui-state-default"></span>
|
||||||
<span class="spl_title"><?php echo $item["CcFiles"]['track_title'] ?></span>
|
<span class="spl_title"><?php echo $item["CcFiles"]['track_title'] ?></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-row">
|
<div class="text-row">
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
<div id="schedule-add-show" class="tabs ui-widget ui-widget-content block-shadow alpha-block padded">
|
<div id="schedule-add-show" class="tabs ui-widget ui-widget-content block-shadow alpha-block padded">
|
||||||
<div class="button-bar">
|
<div class="button-bar">
|
||||||
<a href="#" id="add-show-close" class="icon-link"><span class="ui-icon ui-icon-circle-close"></span>Close</a>
|
<a href="#" id="add-show-close" class="icon-link"><span class="ui-icon ui-icon-circle-close"></span>Close</a>
|
||||||
<button id="add-show-submit" class="right-floated">Add this show</button>
|
<button aria-disabled="false" role="button" id="add-show-submit" class="right-floated ui-button ui-widget ui-state-default ui-button-text-icon-primary">
|
||||||
|
<span class="ui-icon ui-icon-plusthick"></span>
|
||||||
|
<span class="ui-button-text">Add this show</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="clear"></div>
|
<div class="clear"></div>
|
||||||
<h3 class="collapsible-header"><span class="arrow-icon"></span>What</h3>
|
<h3 class="collapsible-header"><span class="arrow-icon"></span>What</h3>
|
||||||
|
|
|
@ -7,7 +7,9 @@
|
||||||
<div id="users_wrapper" class="dataTables_wrapper">
|
<div id="users_wrapper" class="dataTables_wrapper">
|
||||||
|
|
||||||
<div class="button-holder">
|
<div class="button-holder">
|
||||||
<button type="button" id="add_user_button" name="search_add_group" class="ui-button ui-widget ui-state-default ui-button-text-icon-primary"><span class="ui-button-text">New User</span></button>
|
<button type="button" id="add_user_button" name="search_add_group" class="ui-button ui-widget ui-state-default ui-button-text-icon-primary">
|
||||||
|
<span class="ui-icon ui-icon-plusthick"></span>
|
||||||
|
<span class="ui-button-text">New User</span></button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table cellspacing="0" cellpadding="0" style="" id="users_datatable" class="datatable">
|
<table cellspacing="0" cellpadding="0" style="" id="users_datatable" class="datatable">
|
||||||
|
@ -26,6 +28,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="user-data simple-formblock" id="user_details">
|
<div class="user-data simple-formblock" id="user_details">
|
||||||
|
<?php echo $this->successMessage ?>
|
||||||
<fieldset class="padded">
|
<fieldset class="padded">
|
||||||
<?php echo $this->form ?>
|
<?php echo $this->form ?>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
|
@ -234,7 +234,7 @@
|
||||||
</table>
|
</table>
|
||||||
<table name="cc_schedule" phpName="CcSchedule">
|
<table name="cc_schedule" phpName="CcSchedule">
|
||||||
<column name="id" phpName="DbId" type="INTEGER" primaryKey="true" autoIncrement="true" required="true"/>
|
<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="starts" phpName="DbStarts" type="TIMESTAMP" required="true"/>
|
||||||
<column name="ends" phpName="DbEnds" type="TIMESTAMP" required="true"/>
|
<column name="ends" phpName="DbEnds" type="TIMESTAMP" required="true"/>
|
||||||
<column name="group_id" phpName="DbGroupId" type="INTEGER" required="false"/>
|
<column name="group_id" phpName="DbGroupId" type="INTEGER" required="false"/>
|
||||||
|
|
|
@ -345,7 +345,7 @@ DROP TABLE "cc_schedule" CASCADE;
|
||||||
CREATE TABLE "cc_schedule"
|
CREATE TABLE "cc_schedule"
|
||||||
(
|
(
|
||||||
"id" serial NOT NULL,
|
"id" serial NOT NULL,
|
||||||
"playlist_id" INTEGER NOT NULL,
|
"playlist_id" INTEGER,
|
||||||
"starts" TIMESTAMP NOT NULL,
|
"starts" TIMESTAMP NOT NULL,
|
||||||
"ends" TIMESTAMP NOT NULL,
|
"ends" TIMESTAMP NOT NULL,
|
||||||
"group_id" INTEGER,
|
"group_id" INTEGER,
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
su -l pypo -c "tail -F /etc/service/pypo-fetch/log/main/current"
|
|
|
@ -1,3 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
su -l pypo -c "tail -F /etc/service/pypo-push/log/main/current"
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
su -l pypo -c "tail -F /etc/service/recorder/log/main/current"
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
su -l pypo -c "less /etc/service/pypo/log/main/current"
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
su -l pypo -c "tail -F /etc/service/pypo/log/main/current"
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
|
use Doctrine\DBAL\Migrations\AbstractMigration,
|
||||||
|
Doctrine\DBAL\Schema\Schema;
|
||||||
|
|
||||||
|
class Version20110312121200 extends AbstractMigration
|
||||||
|
{
|
||||||
|
public function up(Schema $schema)
|
||||||
|
{
|
||||||
|
$schema->dropTable("cc_backup");
|
||||||
|
$schema->dropTable("cc_trans");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
|
@ -39,7 +39,6 @@ AirtimeInstall::InstallPostgresScriptingLanguage();
|
||||||
|
|
||||||
echo "* Creating database tables".PHP_EOL;
|
echo "* Creating database tables".PHP_EOL;
|
||||||
AirtimeInstall::CreateDatabaseTables();
|
AirtimeInstall::CreateDatabaseTables();
|
||||||
AirtimeInstall::MigrateTables(__DIR__);
|
|
||||||
|
|
||||||
echo "* Storage directory setup".PHP_EOL;
|
echo "* Storage directory setup".PHP_EOL;
|
||||||
AirtimeInstall::SetupStorageDirectory($CC_CONFIG);
|
AirtimeInstall::SetupStorageDirectory($CC_CONFIG);
|
||||||
|
@ -47,11 +46,20 @@ AirtimeInstall::SetupStorageDirectory($CC_CONFIG);
|
||||||
echo "* Giving Apache permission to access the storage directory".PHP_EOL;
|
echo "* Giving Apache permission to access the storage directory".PHP_EOL;
|
||||||
AirtimeInstall::ChangeDirOwnerToWebserver($CC_CONFIG["storageDir"]);
|
AirtimeInstall::ChangeDirOwnerToWebserver($CC_CONFIG["storageDir"]);
|
||||||
|
|
||||||
|
echo "* Creating /usr/bin symlinks".PHP_EOL;
|
||||||
|
AirtimeInstall::CreateSymlinks($CC_CONFIG["storageDir"]);
|
||||||
|
|
||||||
echo "* Importing sample audio clips".PHP_EOL;
|
echo "* Importing sample audio clips".PHP_EOL;
|
||||||
system(__DIR__."/../utils/airtime-import --copy ../audio_samples/ > /dev/null");
|
system(__DIR__."/../utils/airtime-import --copy ../audio_samples/ > /dev/null");
|
||||||
|
|
||||||
|
echo "* Python eggs Setup".PHP_EOL;
|
||||||
|
AirtimeInstall::SetUpPythonEggs();
|
||||||
|
|
||||||
echo PHP_EOL."*** Pypo Installation ***".PHP_EOL;
|
echo PHP_EOL."*** Pypo Installation ***".PHP_EOL;
|
||||||
system("python ".__DIR__."/../pypo/install/pypo-install.py");
|
system("python ".__DIR__."/../python_apps/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;
|
echo "******************************* Install Complete *******************************".PHP_EOL;
|
||||||
|
|
|
@ -20,6 +20,7 @@ require_once(dirname(__FILE__).'/installInit.php');
|
||||||
// Need to check that we are superuser before running this.
|
// Need to check that we are superuser before running this.
|
||||||
AirtimeInstall::ExitIfNotRoot();
|
AirtimeInstall::ExitIfNotRoot();
|
||||||
|
|
||||||
|
AirtimeInstall::RemoveSymlinks();
|
||||||
|
|
||||||
echo "******************************* Uninstall Begin ********************************".PHP_EOL;
|
echo "******************************* Uninstall Begin ********************************".PHP_EOL;
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
|
@ -38,7 +39,7 @@ $command = "sudo -u postgres dropdb {$CC_CONFIG['dsn']['database']} 2> /dev/null
|
||||||
//------------------------------------------------------------------------
|
//------------------------------------------------------------------------
|
||||||
if ($dbDeleteFailed) {
|
if ($dbDeleteFailed) {
|
||||||
echo " * Couldn't delete the database, so deleting all the DB tables...".PHP_EOL;
|
echo " * Couldn't delete the database, so deleting all the DB tables...".PHP_EOL;
|
||||||
AirtimeInstall::DbConnect(true);
|
AirtimeInstall::DbConnect(false);
|
||||||
|
|
||||||
if (!PEAR::isError($CC_DBC)) {
|
if (!PEAR::isError($CC_DBC)) {
|
||||||
$sql = "select * from pg_tables where tableowner = 'airtime'";
|
$sql = "select * from pg_tables where tableowner = 'airtime'";
|
||||||
|
@ -81,7 +82,10 @@ if ($results == 0) {
|
||||||
AirtimeInstall::DeleteFilesRecursive($CC_CONFIG['storageDir']);
|
AirtimeInstall::DeleteFilesRecursive($CC_CONFIG['storageDir']);
|
||||||
|
|
||||||
|
|
||||||
$command = "python ".__DIR__."/../pypo/install/pypo-uninstall.py";
|
$command = "python ".__DIR__."/../python_apps/pypo/install/pypo-uninstall.py";
|
||||||
|
system($command);
|
||||||
|
|
||||||
|
$command = "python ".__DIR__."/../python_apps/show-recorder/install/recorder-uninstall.py";
|
||||||
system($command);
|
system($command);
|
||||||
echo "****************************** Uninstall Complete ******************************".PHP_EOL;
|
echo "****************************** Uninstall Complete ******************************".PHP_EOL;
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,8 @@ class AirtimeInstall {
|
||||||
{
|
{
|
||||||
$api_key = AirtimeInstall::GenerateRandomString();
|
$api_key = AirtimeInstall::GenerateRandomString();
|
||||||
AirtimeInstall::UpdateIniValue(__DIR__.'/../build/airtime.conf', 'api_key', $api_key);
|
AirtimeInstall::UpdateIniValue(__DIR__.'/../build/airtime.conf', 'api_key', $api_key);
|
||||||
AirtimeInstall::UpdateIniValue(__DIR__.'/../pypo/config.cfg', 'api_key', "'$api_key'");
|
AirtimeInstall::UpdateIniValue(__DIR__.'/../python_apps/pypo/config.cfg', 'api_key', "'$api_key'");
|
||||||
|
AirtimeInstall::UpdateIniValue(__DIR__.'/../python_apps/show-recorder/config.cfg', 'api_key', "'$api_key'");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function ExitIfNotRoot()
|
public static function ExitIfNotRoot()
|
||||||
|
@ -112,7 +113,7 @@ class AirtimeInstall {
|
||||||
public static function SetupStorageDirectory($CC_CONFIG)
|
public static function SetupStorageDirectory($CC_CONFIG)
|
||||||
{
|
{
|
||||||
global $CC_CONFIG, $CC_DBC;
|
global $CC_CONFIG, $CC_DBC;
|
||||||
|
|
||||||
echo PHP_EOL."*** Directory Setup ***".PHP_EOL;
|
echo PHP_EOL."*** Directory Setup ***".PHP_EOL;
|
||||||
foreach (array('baseFilesDir', 'storageDir') as $d) {
|
foreach (array('baseFilesDir', 'storageDir') as $d) {
|
||||||
if ( !file_exists($CC_CONFIG[$d]) ) {
|
if ( !file_exists($CC_CONFIG[$d]) ) {
|
||||||
|
@ -141,7 +142,7 @@ class AirtimeInstall {
|
||||||
// Create the database user
|
// Create the database user
|
||||||
$command = "sudo -u postgres psql postgres --command \"CREATE USER {$CC_CONFIG['dsn']['username']} "
|
$command = "sudo -u postgres psql postgres --command \"CREATE USER {$CC_CONFIG['dsn']['username']} "
|
||||||
." ENCRYPTED PASSWORD '{$CC_CONFIG['dsn']['password']}' LOGIN CREATEDB NOCREATEUSER;\" 2>/dev/null";
|
." ENCRYPTED PASSWORD '{$CC_CONFIG['dsn']['password']}' LOGIN CREATEDB NOCREATEUSER;\" 2>/dev/null";
|
||||||
|
|
||||||
@exec($command, $output, $results);
|
@exec($command, $output, $results);
|
||||||
if ($results == 0) {
|
if ($results == 0) {
|
||||||
echo "* Database user '{$CC_CONFIG['dsn']['username']}' created.".PHP_EOL;
|
echo "* Database user '{$CC_CONFIG['dsn']['username']}' created.".PHP_EOL;
|
||||||
|
@ -159,7 +160,7 @@ class AirtimeInstall {
|
||||||
public static function CreateDatabase()
|
public static function CreateDatabase()
|
||||||
{
|
{
|
||||||
global $CC_CONFIG;
|
global $CC_CONFIG;
|
||||||
|
|
||||||
$command = "sudo -u postgres createdb {$CC_CONFIG['dsn']['database']} --owner {$CC_CONFIG['dsn']['username']} 2> /dev/null";
|
$command = "sudo -u postgres createdb {$CC_CONFIG['dsn']['database']} --owner {$CC_CONFIG['dsn']['username']} 2> /dev/null";
|
||||||
@exec($command, $output, $results);
|
@exec($command, $output, $results);
|
||||||
if ($results == 0) {
|
if ($results == 0) {
|
||||||
|
@ -202,10 +203,33 @@ class AirtimeInstall {
|
||||||
system($command);
|
system($command);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function SetUpPythonEggs()
|
||||||
|
{
|
||||||
|
//install poster streaming upload
|
||||||
|
$command = "sudo easy_install poster";
|
||||||
|
@exec($command);
|
||||||
|
}
|
||||||
|
|
||||||
public static function DeleteFilesRecursive($p_path)
|
public static function DeleteFilesRecursive($p_path)
|
||||||
{
|
{
|
||||||
$command = "rm -rf $p_path";
|
$command = "rm -rf $p_path";
|
||||||
exec($command);
|
exec($command);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
public static function CreateSymlinks(){
|
||||||
|
AirtimeInstall::RemoveSymlinks();
|
||||||
|
|
||||||
|
$dir = realpath(__DIR__."/../utils/airtime-import");
|
||||||
|
exec("ln -s $dir /usr/bin/airtime-import");
|
||||||
|
|
||||||
|
$dir = realpath(__DIR__."/../utils/airtime-clean-storage");
|
||||||
|
exec("ln -s $dir /usr/bin/airtime-clean-storage");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function RemoveSymlinks(){
|
||||||
|
exec("rm -f /usr/bin/airtime-import");
|
||||||
|
exec("rm -f /usr/bin/airtime-clean-storage");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
#!/usr/bin/php
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Repeatedly receive messages from queue until it receives a message with
|
||||||
|
* 'quit' as the body.
|
||||||
|
*
|
||||||
|
* @author Sean Murphy<sean@iamseanmurphy.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once('../amqp.inc');
|
||||||
|
|
||||||
|
$HOST = 'localhost';
|
||||||
|
$PORT = 5672;
|
||||||
|
$USER = 'guest';
|
||||||
|
$PASS = 'guest';
|
||||||
|
$VHOST = '/';
|
||||||
|
$EXCHANGE = 'airtime-schedule';
|
||||||
|
$QUEUE = 'airtime-schedule-msgs';
|
||||||
|
$CONSUMER_TAG = 'airtime-consumer';
|
||||||
|
|
||||||
|
$conn = new AMQPConnection($HOST, $PORT, $USER, $PASS);
|
||||||
|
$ch = $conn->channel();
|
||||||
|
$ch->access_request($VHOST, false, false, true, true);
|
||||||
|
|
||||||
|
$ch->queue_declare($QUEUE);
|
||||||
|
$ch->exchange_declare($EXCHANGE, 'direct', false, false, false);
|
||||||
|
$ch->queue_bind($QUEUE, $EXCHANGE);
|
||||||
|
|
||||||
|
function process_message($msg) {
|
||||||
|
global $ch, $CONSUMER_TAG;
|
||||||
|
|
||||||
|
echo "\n--------\n";
|
||||||
|
echo $msg->body;
|
||||||
|
echo "\n--------\n";
|
||||||
|
|
||||||
|
$ch->basic_ack($msg->delivery_info['delivery_tag']);
|
||||||
|
|
||||||
|
// Cancel callback
|
||||||
|
if ($msg->body === 'quit') {
|
||||||
|
$ch->basic_cancel($CONSUMER_TAG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$ch->basic_consume($QUEUE, $CONSUMER_TAG, false, false, false, false, 'process_message');
|
||||||
|
|
||||||
|
// Loop as long as the channel has callbacks registered
|
||||||
|
echo "Waiting for messages...\n";
|
||||||
|
while(count($ch->callbacks)) {
|
||||||
|
$ch->wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
$ch->close();
|
||||||
|
$conn->close();
|
||||||
|
?>
|
|
@ -0,0 +1,267 @@
|
||||||
|
(function($){
|
||||||
|
$.fn.airtimeShowSchedule = function(options) {
|
||||||
|
|
||||||
|
var defaults = {
|
||||||
|
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;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
|
||||||
|
(function($){
|
||||||
|
$.fn.airtimeLiveInfo = function(options) {
|
||||||
|
|
||||||
|
var defaults = {
|
||||||
|
updatePeriod: 5, //seconds
|
||||||
|
sourceDomain: "http://localhost/", //where to get show status from
|
||||||
|
audioStreamSource: "" //where to get audio stream from
|
||||||
|
};
|
||||||
|
var options = $.extend(defaults, options);
|
||||||
|
|
||||||
|
return this.each(function() {
|
||||||
|
var obj = $(this);
|
||||||
|
var sd;
|
||||||
|
getServerData();
|
||||||
|
|
||||||
|
function updateWidget(){
|
||||||
|
var currentShow = sd.getCurrentShow();
|
||||||
|
var nextShows = sd.getNextShows();
|
||||||
|
|
||||||
|
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'>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 to update the elapsed/remaining time
|
||||||
|
setTimeout(updateWidget, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* ScheduleData class BEGIN */
|
||||||
|
function ScheduleData(data){
|
||||||
|
this.data = data;
|
||||||
|
this.estimatedSchedulePosixTime;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ScheduleData.prototype.secondsTimer = function(){
|
||||||
|
var date = new Date();
|
||||||
|
this.estimatedSchedulePosixTime = date.getTime() - this.localRemoteTimeOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScheduleData.prototype.getCurrentShow = function(){
|
||||||
|
return this.currentShow;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScheduleData.prototype.getNextShows = function() {
|
||||||
|
return this.nextShows;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScheduleData.prototype.getShowTimeElapsed = function(show) {
|
||||||
|
this.secondsTimer();
|
||||||
|
|
||||||
|
var showStart = convertDateToPosixTime(show.getStartTimestamp());
|
||||||
|
return convertToHHMMSS(this.estimatedSchedulePosixTime - showStart);
|
||||||
|
};
|
||||||
|
|
||||||
|
ScheduleData.prototype.getShowTimeRemaining = function(show) {
|
||||||
|
this.secondsTimer();
|
||||||
|
|
||||||
|
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 */
|
||||||
|
function convertToHHMMSS(timeInMS){
|
||||||
|
var time = parseInt(timeInMS);
|
||||||
|
|
||||||
|
var hours = parseInt(time / 3600000);
|
||||||
|
time -= 3600000*hours;
|
||||||
|
|
||||||
|
var minutes = parseInt(time / 60000);
|
||||||
|
time -= 60000*minutes;
|
||||||
|
|
||||||
|
var seconds = parseInt(time / 1000);
|
||||||
|
|
||||||
|
hours = hours.toString();
|
||||||
|
minutes = minutes.toString();
|
||||||
|
seconds = seconds.toString();
|
||||||
|
|
||||||
|
if (hours.length == 1)
|
||||||
|
hours = "0" + hours;
|
||||||
|
if (minutes.length == 1)
|
||||||
|
minutes = "0" + minutes;
|
||||||
|
if (seconds.length == 1)
|
||||||
|
seconds = "0" + seconds;
|
||||||
|
if (hours == "00")
|
||||||
|
return minutes + ":" + seconds;
|
||||||
|
else
|
||||||
|
return hours + ":" + minutes + ":" + seconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Takes in a string of format similar to 2011-02-07 02:59:57,
|
||||||
|
* and converts this to epoch/posix time. */
|
||||||
|
function convertDateToPosixTime(s){
|
||||||
|
var datetime = s.split(" ");
|
||||||
|
|
||||||
|
var date = datetime[0].split("-");
|
||||||
|
var time = datetime[1].split(":");
|
||||||
|
|
||||||
|
var year = date[0];
|
||||||
|
var month = date[1];
|
||||||
|
var day = date[2];
|
||||||
|
var hour = time[0];
|
||||||
|
var minute = time[1];
|
||||||
|
var sec = 0;
|
||||||
|
var msec = 0;
|
||||||
|
|
||||||
|
if (time[2].indexOf(".") != -1){
|
||||||
|
var temp = time[2].split(".");
|
||||||
|
sec = temp[0];
|
||||||
|
msec = temp[1];
|
||||||
|
} else
|
||||||
|
sec = time[2];
|
||||||
|
|
||||||
|
return Date.UTC(year, month, day, hour, minute, sec, msec);
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 990 B |
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
|
@ -15,7 +15,11 @@
|
||||||
#spl_sortable > li,
|
#spl_sortable > li,
|
||||||
#side_playlist > div,
|
#side_playlist > div,
|
||||||
#spl_editor,
|
#spl_editor,
|
||||||
.spl_artist {
|
.spl_artist,
|
||||||
|
.spl_cue_in,
|
||||||
|
.spl_fade_in,
|
||||||
|
.spl_cue_out,
|
||||||
|
.spl_fade_out {
|
||||||
clear: left;
|
clear: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,8 +39,8 @@
|
||||||
#spl_sortable {
|
#spl_sortable {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
padding:0;
|
padding:0;
|
||||||
height: 400px;
|
height: 300px;
|
||||||
overflow-y: scroll;
|
overflow: auto;
|
||||||
width:100%;
|
width:100%;
|
||||||
margin-top:0;
|
margin-top:0;
|
||||||
}
|
}
|
||||||
|
@ -52,6 +56,10 @@
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#spl_name {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
.ui-icon-closethick {
|
.ui-icon-closethick {
|
||||||
margin-top: 7px;
|
margin-top: 7px;
|
||||||
}
|
}
|
||||||
|
@ -72,10 +80,18 @@
|
||||||
font-size:12px;
|
font-size:12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*#spl_editor {
|
||||||
|
height: 50px;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
#spl_editor > div > span {
|
||||||
|
/* display: inline-block;
|
||||||
|
width: 150px;*/
|
||||||
|
}
|
||||||
|
|
||||||
.ui-icon-closethick,
|
.ui-icon-closethick,
|
||||||
.ui-icon-play,
|
.ui-icon-play,
|
||||||
.spl_fade_control,
|
.spl_fade_control,
|
||||||
.spl_playlength,
|
|
||||||
.spl_text_input {
|
.spl_text_input {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
@ -239,13 +255,12 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
dd.edit-error {
|
.edit-error {
|
||||||
color:#b80000;
|
color:#b80000;
|
||||||
margin:0;
|
margin:0;
|
||||||
padding-bottom:0;
|
padding-bottom:0;
|
||||||
font-size:12px;
|
font-size:12px;
|
||||||
display:none;
|
display:none;
|
||||||
clear: left;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*.edit-error:last-child {
|
/*.edit-error:last-child {
|
||||||
|
@ -276,3 +291,26 @@ dd.edit-error {
|
||||||
top: 3px;
|
top: 3px;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#spl_sortable li .spl_cue {
|
||||||
|
background-color: transparent;
|
||||||
|
float:right;
|
||||||
|
font-size: 9px;
|
||||||
|
height: 15px;
|
||||||
|
right: 35px;
|
||||||
|
width: 33px;
|
||||||
|
margin-top:2px;
|
||||||
|
cursor:pointer;
|
||||||
|
}
|
||||||
|
#spl_sortable li .spl_cue.ui-state-default {
|
||||||
|
background: transparent url(images/cue_playlist.png) no-repeat 0 0;
|
||||||
|
border:none;
|
||||||
|
}
|
||||||
|
#spl_sortable li .spl_cue.ui-state-default:hover {
|
||||||
|
background: transparent url(images/cue_playlist.png) no-repeat 0 -15px;
|
||||||
|
border:none;
|
||||||
|
}
|
||||||
|
#spl_sortable li .spl_cue.ui-state-active, #spl_sortable li .spl_cue.ui-state-active:hover {
|
||||||
|
background: transparent url(images/cue_playlist.png) no-repeat 0 -30px;
|
||||||
|
border:none;
|
||||||
|
}
|
|
@ -184,7 +184,7 @@ select {
|
||||||
.progressbar .progress-show-error {
|
.progressbar .progress-show-error {
|
||||||
background:#d40000 url(images/progressbar_show_error.png) repeat-x 0 0;
|
background:#d40000 url(images/progressbar_show_error.png) repeat-x 0 0;
|
||||||
}
|
}
|
||||||
.now-playing-info .lenght {
|
.now-playing-info .show-length {
|
||||||
color:#c4c4c4;
|
color:#c4c4c4;
|
||||||
padding-left:6px;
|
padding-left:6px;
|
||||||
}
|
}
|
||||||
|
@ -196,6 +196,7 @@ select {
|
||||||
.time-info-block {
|
.time-info-block {
|
||||||
padding:0 14px 0 2px;
|
padding:0 14px 0 2px;
|
||||||
background:url(images/masterpanel_spacer.png) no-repeat right 0;
|
background:url(images/masterpanel_spacer.png) no-repeat right 0;
|
||||||
|
min-width:105px;
|
||||||
}
|
}
|
||||||
.time-info-block ul {
|
.time-info-block ul {
|
||||||
margin:0;
|
margin:0;
|
||||||
|
@ -825,7 +826,6 @@ div.ui-datepicker {
|
||||||
#schedule_playlist_chosen li > h3 > span.ui-icon.ui-icon-triangle-1-e,
|
#schedule_playlist_chosen li > h3 > span.ui-icon.ui-icon-triangle-1-e,
|
||||||
#schedule_playlist_chosen li > h3 > span.ui-icon.ui-icon-triangle-1-s {
|
#schedule_playlist_chosen li > h3 > span.ui-icon.ui-icon-triangle-1-s {
|
||||||
float:left;
|
float:left;
|
||||||
|
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
#schedule_playlist_chosen li > h3 > span.ui-icon.ui-icon-close {
|
#schedule_playlist_chosen li > h3 > span.ui-icon.ui-icon-close {
|
||||||
|
@ -1219,6 +1219,16 @@ ul.errors li {
|
||||||
margin-bottom:2px;
|
margin-bottom:2px;
|
||||||
border:1px solid #c83f3f;
|
border:1px solid #c83f3f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.success{
|
||||||
|
color:#3B5323;
|
||||||
|
font-size:11px;
|
||||||
|
padding:2px 4px;
|
||||||
|
background:#93DB70;
|
||||||
|
margin-bottom:2px;
|
||||||
|
border:1px solid #488214;
|
||||||
|
}
|
||||||
|
|
||||||
.collapsible-header {
|
.collapsible-header {
|
||||||
border: 1px solid #8f8f8f;
|
border: 1px solid #8f8f8f;
|
||||||
background-color: #cccccc;
|
background-color: #cccccc;
|
||||||
|
@ -1474,9 +1484,35 @@ ul.errors li {
|
||||||
margin:-4px 3px -3px 0;
|
margin:-4px 3px -3px 0;
|
||||||
float:right;
|
float:right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.time-flow {
|
.time-flow {
|
||||||
float:right;
|
float:right;
|
||||||
margin-right:4px;
|
margin-right:4px;
|
||||||
|
}
|
||||||
|
.small-icon {
|
||||||
|
display:block;
|
||||||
|
width:20px;
|
||||||
|
height:10px;
|
||||||
|
float:right;
|
||||||
|
margin-left:3px;
|
||||||
|
}
|
||||||
|
.small-icon.recording {
|
||||||
|
background:url(images/icon_record.png) no-repeat 0 0;
|
||||||
|
}
|
||||||
|
.small-icon.rebroadcast {
|
||||||
|
background:url(images/icon_rebroadcast.png) no-repeat 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.medium-icon {
|
||||||
|
display:block;
|
||||||
|
width:25px;
|
||||||
|
height:12px;
|
||||||
|
float:right;
|
||||||
|
margin-left:4px;
|
||||||
|
}
|
||||||
|
.medium-icon.recording {
|
||||||
|
background:url(images/icon_record_m.png) no-repeat 0 0;
|
||||||
|
}
|
||||||
|
.medium-icon.rebroadcast {
|
||||||
|
background:url(images/icon_rebroadcast_m.png) no-repeat 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -205,13 +205,15 @@ function openFadeEditor(event) {
|
||||||
function openCueEditor(event) {
|
function openCueEditor(event) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
var pos, url, li;
|
var pos, url, li, icon;
|
||||||
|
|
||||||
li = $(this).parent().parent().parent();
|
li = $(this).parent().parent().parent();
|
||||||
|
icon = $(this);
|
||||||
pos = li.attr("id").split("_").pop();
|
pos = li.attr("id").split("_").pop();
|
||||||
|
|
||||||
if(li.hasClass("ui-state-active")) {
|
if(li.hasClass("ui-state-active")) {
|
||||||
li.removeClass("ui-state-active");
|
li.removeClass("ui-state-active");
|
||||||
|
icon.attr("class", "spl_cue ui-state-default");
|
||||||
|
|
||||||
$("#cues_"+pos)
|
$("#cues_"+pos)
|
||||||
.empty()
|
.empty()
|
||||||
|
@ -220,6 +222,7 @@ function openCueEditor(event) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
icon.attr("class", "spl_cue ui-state-default ui-state-active");
|
||||||
url = '/Playlist/set-cue';
|
url = '/Playlist/set-cue';
|
||||||
|
|
||||||
highlightActive(li);
|
highlightActive(li);
|
||||||
|
@ -253,7 +256,8 @@ function setSPLContent(json) {
|
||||||
|
|
||||||
$("#spl_sortable .ui-icon-closethick").click(deleteSPLItem);
|
$("#spl_sortable .ui-icon-closethick").click(deleteSPLItem);
|
||||||
$(".spl_fade_control").click(openFadeEditor);
|
$(".spl_fade_control").click(openFadeEditor);
|
||||||
$(".spl_playlength").click(openCueEditor);
|
//$(".spl_playlength").click(openCueEditor);
|
||||||
|
$(".spl_cue").click(openCueEditor);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -487,7 +491,8 @@ function setUpSPL() {
|
||||||
|
|
||||||
$("#spl_sortable .ui-icon-closethick").click(deleteSPLItem);
|
$("#spl_sortable .ui-icon-closethick").click(deleteSPLItem);
|
||||||
$(".spl_fade_control").click(openFadeEditor);
|
$(".spl_fade_control").click(openFadeEditor);
|
||||||
$(".spl_playlength").click(openCueEditor);
|
//$(".spl_playlength").click(openCueEditor);
|
||||||
|
$(".spl_cue").click(openCueEditor);
|
||||||
|
|
||||||
$("#spl_sortable").droppable();
|
$("#spl_sortable").droppable();
|
||||||
$("#spl_sortable" ).bind( "drop", addSPLItem);
|
$("#spl_sortable" ).bind( "drop", addSPLItem);
|
||||||
|
|
|
@ -182,7 +182,6 @@ function setAddShowEvents() {
|
||||||
});
|
});
|
||||||
|
|
||||||
form.find("#add-show-submit")
|
form.find("#add-show-submit")
|
||||||
.button()
|
|
||||||
.click(function(event){
|
.click(function(event){
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
|
|
|
@ -165,6 +165,25 @@ function eventRender(event, element, view) {
|
||||||
}
|
}
|
||||||
|
|
||||||
$(element).find(".fc-event-title").after(div);
|
$(element).find(".fc-event-title").after(div);
|
||||||
|
}
|
||||||
|
|
||||||
|
//add the record/rebroadcast icons if needed.
|
||||||
|
if((view.name === 'agendaDay' || view.name === 'agendaWeek') && event.record === 1) {
|
||||||
|
|
||||||
|
$(element).find(".fc-event-time").after('<span class="small-icon recording"></span>');
|
||||||
|
}
|
||||||
|
if(view.name === 'month' && event.record === 1) {
|
||||||
|
|
||||||
|
$(element).find(".fc-event-title").after('<span class="small-icon recording"></span>');
|
||||||
|
}
|
||||||
|
|
||||||
|
if((view.name === 'agendaDay' || view.name === 'agendaWeek') && event.rebroadcast === 1) {
|
||||||
|
|
||||||
|
$(element).find(".fc-event-time").after('<span class="small-icon rebroadcast"></span>');
|
||||||
|
}
|
||||||
|
if(view.name === 'month' && event.rebroadcast === 1) {
|
||||||
|
|
||||||
|
$(element).find(".fc-event-title").after('<span class="small-icon rebroadcast"></span>');
|
||||||
}
|
}
|
||||||
|
|
||||||
if(event.backgroundColor !== "") {
|
if(event.backgroundColor !== "") {
|
||||||
|
|
|
@ -2,6 +2,7 @@ function populateForm(entries){
|
||||||
//$('#user_details').show();
|
//$('#user_details').show();
|
||||||
|
|
||||||
$('.errors').remove();
|
$('.errors').remove();
|
||||||
|
$('.success').remove();
|
||||||
|
|
||||||
$('#user_id').val(entries.id);
|
$('#user_id').val(entries.id);
|
||||||
$('#login').val(entries.login);
|
$('#login').val(entries.login);
|
||||||
|
|
|
@ -165,11 +165,12 @@ function updatePlaybar(){
|
||||||
|
|
||||||
/* Column 1 update */
|
/* Column 1 update */
|
||||||
$('#playlist').text("Current Show:");
|
$('#playlist').text("Current Show:");
|
||||||
|
var recElem = $('.recording-show');
|
||||||
if (currentShow.length > 0){
|
if (currentShow.length > 0){
|
||||||
$('#playlist').text(currentShow[0].name);
|
$('#playlist').text(currentShow[0].name);
|
||||||
|
(currentShow[0].record == "1") ? recElem.show(): recElem.hide();
|
||||||
var recElem = $('.recording-show');
|
} else {
|
||||||
currentShow[0].record ? recElem.show(): recElem.hide();
|
recElem.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
$('#show-length').empty();
|
$('#show-length').empty();
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
import airtime_api_client
|
|
||||||
import obp_api_client
|
|
||||||
|
|
||||||
def create_api_client(config):
|
|
||||||
if config["api_client"] == "airtime":
|
|
||||||
return campcaster_api_client.AirtimeApiClient(config)
|
|
||||||
elif config["api_client"] == "obp":
|
|
||||||
return obp_api_client.ObpApiClient(config)
|
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
pypo_user="pypo"
|
|
||||||
export HOME="/home/pypo/"
|
|
||||||
# Location of pypo_cli.py Python script
|
|
||||||
pypo_path="/opt/pypo/bin/"
|
|
||||||
pypo_script="pypo-cli.py"
|
|
||||||
echo "*** Daemontools: starting daemon"
|
|
||||||
cd ${pypo_path}
|
|
||||||
exec 2>&1
|
|
||||||
# Note the -u when calling python! we need it to get unbuffered binary stdout and stderr
|
|
||||||
exec setuidgid ${pypo_user} \
|
|
||||||
python -u ${pypo_path}${pypo_script} \
|
|
||||||
-f
|
|
||||||
# EOF
|
|
|
@ -1,23 +0,0 @@
|
||||||
#!/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-fetch"
|
|
||||||
os.system("svc -dx /etc/service/pypo-fetch 2>/dev/null")
|
|
||||||
|
|
||||||
print "Stopping daemontool script pypo-push"
|
|
||||||
os.system("svc -dx /etc/service/pypo-push 2>/dev/null")
|
|
||||||
|
|
||||||
print "Stopping daemontool script pypo-liquidsoap"
|
|
||||||
os.system("svc -dx /etc/service/pypo-liquidsoap 2>/dev/null")
|
|
||||||
os.system("killall liquidsoap")
|
|
||||||
|
|
||||||
except Exception, e:
|
|
||||||
print "exception:" + str(e)
|
|
|
@ -1,60 +0,0 @@
|
||||||
[loggers]
|
|
||||||
keys=root
|
|
||||||
|
|
||||||
[handlers]
|
|
||||||
keys=consoleHandler,fileHandlerERROR,fileHandlerDEBUG,nullHandler
|
|
||||||
|
|
||||||
[formatters]
|
|
||||||
keys=simpleFormatter
|
|
||||||
|
|
||||||
[logger_root]
|
|
||||||
level=DEBUG
|
|
||||||
handlers=consoleHandler,fileHandlerERROR,fileHandlerDEBUG
|
|
||||||
|
|
||||||
[logger_libs]
|
|
||||||
handlers=nullHandler
|
|
||||||
level=DEBUG
|
|
||||||
qualname="process"
|
|
||||||
propagate=0
|
|
||||||
|
|
||||||
|
|
||||||
[handler_consoleHandler]
|
|
||||||
class=StreamHandler
|
|
||||||
level=DEBUG
|
|
||||||
formatter=simpleFormatter
|
|
||||||
args=(sys.stdout,)
|
|
||||||
|
|
||||||
[handler_fileHandlerERROR]
|
|
||||||
class=FileHandler
|
|
||||||
level=WARNING
|
|
||||||
formatter=simpleFormatter
|
|
||||||
args=("./error.log",)
|
|
||||||
|
|
||||||
[handler_fileHandlerDEBUG]
|
|
||||||
class=FileHandler
|
|
||||||
level=DEBUG
|
|
||||||
formatter=simpleFormatter
|
|
||||||
args=("./debug.log",)
|
|
||||||
|
|
||||||
[handler_nullHandler]
|
|
||||||
class=FileHandler
|
|
||||||
level=DEBUG
|
|
||||||
formatter=simpleFormatter
|
|
||||||
args=("/dev/null",)
|
|
||||||
|
|
||||||
|
|
||||||
[formatter_simpleFormatter]
|
|
||||||
format=%(asctime)s %(levelname)s - [%(filename)s : %(funcName)s() : line %(lineno)d] - %(message)s
|
|
||||||
datefmt=
|
|
||||||
|
|
||||||
|
|
||||||
## multitail color sheme
|
|
||||||
## pyml / python
|
|
||||||
# colorscheme:pyml:www.obp.net
|
|
||||||
# cs_re:blue:\[[^ ]*\]
|
|
||||||
# cs_re:red:CRITICAL:*
|
|
||||||
# cs_re:red,black,blink:ERROR:*
|
|
||||||
# cs_re:blue:NOTICE:*
|
|
||||||
# cs_re:cyan:INFO:*
|
|
||||||
# cs_re:green:DEBUG:*
|
|
||||||
|
|
Binary file not shown.
|
@ -13,6 +13,7 @@
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import urllib
|
import urllib
|
||||||
|
import urllib2
|
||||||
import logging
|
import logging
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
@ -90,6 +91,12 @@ class ApiClientInterface:
|
||||||
# You will be able to use this data in update_start_playing
|
# You will be able to use this data in update_start_playing
|
||||||
def get_liquidsoap_data(self, pkey, schedule):
|
def get_liquidsoap_data(self, pkey, schedule):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def get_shows_to_record(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def upload_recorded_show(self):
|
||||||
|
pass
|
||||||
|
|
||||||
# Put here whatever tests you want to run to make sure your API is working
|
# Put here whatever tests you want to run to make sure your API is working
|
||||||
def test(self):
|
def test(self):
|
||||||
|
@ -189,30 +196,10 @@ class AirTimeApiClient(ApiClientInterface):
|
||||||
|
|
||||||
def get_schedule(self, start=None, end=None):
|
def get_schedule(self, start=None, end=None):
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
|
||||||
"""
|
|
||||||
calculate start/end time range (format: YYYY-DD-MM-hh-mm-ss,YYYY-DD-MM-hh-mm-ss)
|
|
||||||
(seconds are ignored, just here for consistency)
|
|
||||||
"""
|
|
||||||
tnow = time.localtime(time.time())
|
|
||||||
if (not start):
|
|
||||||
tstart = time.localtime(time.time() - 3600 * int(self.config["cache_for"]))
|
|
||||||
start = "%04d-%02d-%02d-%02d-%02d" % (tstart[0], tstart[1], tstart[2], tstart[3], tstart[4])
|
|
||||||
|
|
||||||
if (not end):
|
|
||||||
tend = time.localtime(time.time() + 3600 * int(self.config["prepare_ahead"]))
|
|
||||||
end = "%04d-%02d-%02d-%02d-%02d" % (tend[0], tend[1], tend[2], tend[3], tend[4])
|
|
||||||
|
|
||||||
range = {}
|
|
||||||
range['start'] = start
|
|
||||||
range['end'] = end
|
|
||||||
|
|
||||||
# Construct the URL
|
# Construct the URL
|
||||||
export_url = self.config["base_url"] + self.config["api_base"] + self.config["export_url"]
|
export_url = self.config["base_url"] + self.config["api_base"] + self.config["export_url"]
|
||||||
|
|
||||||
# Insert the start and end times into the URL
|
|
||||||
export_url = export_url.replace('%%from%%', range['start'])
|
|
||||||
export_url = export_url.replace('%%to%%', range['end'])
|
|
||||||
logger.info("Fetching schedule from %s", export_url)
|
logger.info("Fetching schedule from %s", export_url)
|
||||||
export_url = export_url.replace('%%api_key%%', self.config["api_key"])
|
export_url = export_url.replace('%%api_key%%', self.config["api_key"])
|
||||||
|
|
||||||
|
@ -225,24 +212,6 @@ class AirTimeApiClient(ApiClientInterface):
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print e
|
print e
|
||||||
|
|
||||||
#schedule = response["playlists"]
|
|
||||||
#scheduleKeys = sorted(schedule.iterkeys())
|
|
||||||
#
|
|
||||||
## Remove all playlists that have passed current time
|
|
||||||
#try:
|
|
||||||
# tnow = time.localtime(time.time())
|
|
||||||
# str_tnow_s = "%04d-%02d-%02d-%02d-%02d-%02d" % (tnow[0], tnow[1], tnow[2], tnow[3], tnow[4], tnow[5])
|
|
||||||
# toRemove = []
|
|
||||||
# for pkey in scheduleKeys:
|
|
||||||
# if (str_tnow_s > schedule[pkey]['end']):
|
|
||||||
# toRemove.append(pkey)
|
|
||||||
# else:
|
|
||||||
# break
|
|
||||||
# for index in toRemove:
|
|
||||||
# del schedule[index]
|
|
||||||
#except Exception, e:
|
|
||||||
#response["playlists"] = schedule
|
|
||||||
|
|
||||||
return status, response
|
return status, response
|
||||||
|
|
||||||
|
|
||||||
|
@ -316,6 +285,41 @@ class AirTimeApiClient(ApiClientInterface):
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
data["schedule_id"] = 0
|
data["schedule_id"] = 0
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
def get_shows_to_record(self):
|
||||||
|
logger = logging.getLogger()
|
||||||
|
response = ''
|
||||||
|
try:
|
||||||
|
url = self.config["base_url"] + self.config["api_base"] + self.config["show_schedule_url"]
|
||||||
|
logger.debug(url)
|
||||||
|
url = url.replace("%%api_key%%", self.config["api_key"])
|
||||||
|
|
||||||
|
response = urllib.urlopen(url)
|
||||||
|
response = json.loads(response.read())
|
||||||
|
logger.info("shows %s", response)
|
||||||
|
|
||||||
|
except Exception, e:
|
||||||
|
logger.error("Exception: %s", e)
|
||||||
|
|
||||||
|
return response[u'shows']
|
||||||
|
|
||||||
|
def upload_recorded_show(self, data, headers):
|
||||||
|
logger = logging.getLogger()
|
||||||
|
response = ''
|
||||||
|
try:
|
||||||
|
url = self.config["base_url"] + self.config["api_base"] + self.config["upload_file_url"]
|
||||||
|
logger.debug(url)
|
||||||
|
url = url.replace("%%api_key%%", self.config["api_key"])
|
||||||
|
|
||||||
|
request = urllib2.Request(url, data, headers)
|
||||||
|
response = urllib2.urlopen(request).read().strip()
|
||||||
|
|
||||||
|
logger.info("uploaded show result %s", response)
|
||||||
|
|
||||||
|
except Exception, e:
|
||||||
|
logger.error("Exception: %s", e)
|
||||||
|
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -26,6 +26,13 @@ base_url = 'http://localhost/'
|
||||||
ls_host = '127.0.0.1'
|
ls_host = '127.0.0.1'
|
||||||
ls_port = '1234'
|
ls_port = '1234'
|
||||||
|
|
||||||
|
############################################
|
||||||
|
# RabbitMQ settings #
|
||||||
|
############################################
|
||||||
|
rabbitmq_host = 'localhost'
|
||||||
|
rabbitmq_user = 'guest'
|
||||||
|
rabbitmq_password = 'guest'
|
||||||
|
|
||||||
############################################
|
############################################
|
||||||
# pypo preferences #
|
# pypo preferences #
|
||||||
############################################
|
############################################
|
||||||
|
@ -34,15 +41,13 @@ cache_for = 24 #how long to hold the cache, in hours
|
||||||
|
|
||||||
# Poll interval in seconds.
|
# Poll interval in seconds.
|
||||||
#
|
#
|
||||||
|
# This will rarely need to be changed because any schedule changes are
|
||||||
|
# automatically sent to pypo immediately.
|
||||||
|
#
|
||||||
# This is how often the poll script downloads new schedules and files from the
|
# This is how often the poll script downloads new schedules and files from the
|
||||||
# server.
|
# server in the event that no changes are made to the schedule.
|
||||||
#
|
#
|
||||||
# For production use, this number depends on whether you plan on making any
|
poll_interval = 3600 # in seconds.
|
||||||
# last-minute changes to your schedule. This number should be set to half of
|
|
||||||
# the time you expect to "lock-in" your schedule. So if your schedule is set
|
|
||||||
# 24 hours in advance, this can be set to poll every 12 hours.
|
|
||||||
#
|
|
||||||
poll_interval = 5 # in seconds.
|
|
||||||
|
|
||||||
|
|
||||||
# Push interval in seconds.
|
# Push interval in seconds.
|
||||||
|
@ -52,7 +57,7 @@ poll_interval = 5 # in seconds.
|
||||||
#
|
#
|
||||||
# It's hard to imagine a situation where this should be more than 1 second.
|
# It's hard to imagine a situation where this should be more than 1 second.
|
||||||
#
|
#
|
||||||
push_interval = 2 # in seconds
|
push_interval = 1 # in seconds
|
||||||
|
|
||||||
# 'pre' or 'otf'. 'pre' cues while playlist preparation
|
# 'pre' or 'otf'. 'pre' cues while playlist preparation
|
||||||
# while 'otf' (on the fly) cues while loading into ls
|
# while 'otf' (on the fly) cues while loading into ls
|
||||||
|
@ -80,7 +85,7 @@ version_url = 'version/api_key/%%api_key%%'
|
||||||
# Schedule export path.
|
# Schedule export path.
|
||||||
# %%from%% - starting date/time in the form YYYY-MM-DD-hh-mm
|
# %%from%% - starting date/time in the form YYYY-MM-DD-hh-mm
|
||||||
# %%to%% - starting date/time in the form YYYY-MM-DD-hh-mm
|
# %%to%% - starting date/time in the form YYYY-MM-DD-hh-mm
|
||||||
export_url = 'schedule/api_key/%%api_key%%/from/%%from%%/to/%%to%%'
|
export_url = 'schedule/api_key/%%api_key%%'
|
||||||
|
|
||||||
# Update whether a schedule group has begun playing.
|
# Update whether a schedule group has begun playing.
|
||||||
update_item_url = 'notify-schedule-group-play/api_key/%%api_key%%/schedule_id/%%schedule_id%%'
|
update_item_url = 'notify-schedule-group-play/api_key/%%api_key%%/schedule_id/%%schedule_id%%'
|
|
@ -1,10 +1,12 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
ls_user="pypo"
|
ls_user="pypo"
|
||||||
export HOME="/home/pypo/"
|
export HOME="/home/pypo/"
|
||||||
|
api_client_path="/opt/pypo/"
|
||||||
ls_path="/opt/pypo/bin/liquidsoap/liquidsoap"
|
ls_path="/opt/pypo/bin/liquidsoap/liquidsoap"
|
||||||
ls_param="/opt/pypo/bin/scripts/ls_script.liq"
|
ls_param="/opt/pypo/bin/scripts/ls_script.liq"
|
||||||
echo "*** Daemontools: starting liquidsoap"
|
echo "*** Daemontools: starting liquidsoap"
|
||||||
exec 2>&1
|
exec 2>&1
|
||||||
echo "exec sudo -u ${ls_user} ${ls_path} ${ls_param} "
|
|
||||||
cd /opt/pypo/bin/scripts && sudo -u ${ls_user} ${ls_path} ${ls_param}
|
cd /opt/pypo/bin/scripts
|
||||||
|
sudo PYTHONPATH=${api_client_path} -u ${ls_user} ${ls_path} ${ls_param}
|
||||||
# EOF
|
# EOF
|
|
@ -3,12 +3,16 @@ pypo_user="pypo"
|
||||||
export HOME="/home/pypo/"
|
export HOME="/home/pypo/"
|
||||||
# Location of pypo_cli.py Python script
|
# Location of pypo_cli.py Python script
|
||||||
pypo_path="/opt/pypo/bin/"
|
pypo_path="/opt/pypo/bin/"
|
||||||
|
api_client_path="/opt/pypo/"
|
||||||
pypo_script="pypo-cli.py"
|
pypo_script="pypo-cli.py"
|
||||||
echo "*** Daemontools: starting daemon"
|
echo "*** Daemontools: starting daemon"
|
||||||
cd ${pypo_path}
|
cd ${pypo_path}
|
||||||
exec 2>&1
|
exec 2>&1
|
||||||
|
|
||||||
|
PYTHONPATH=${api_client_path}:$PYTHONPATH
|
||||||
|
export PYTHONPATH
|
||||||
|
|
||||||
# Note the -u when calling python! we need it to get unbuffered binary stdout and stderr
|
# Note the -u when calling python! we need it to get unbuffered binary stdout and stderr
|
||||||
exec setuidgid ${pypo_user} \
|
exec setuidgid ${pypo_user} \
|
||||||
python -u ${pypo_path}${pypo_script} \
|
python -u ${pypo_path}${pypo_script}
|
||||||
-p
|
|
||||||
# EOF
|
# EOF
|
|
@ -36,14 +36,16 @@ def create_user(username):
|
||||||
os.system("adduser --system --quiet --group --shell /bin/bash "+username)
|
os.system("adduser --system --quiet --group --shell /bin/bash "+username)
|
||||||
|
|
||||||
#set pypo password
|
#set pypo password
|
||||||
p = os.popen('/usr/bin/passwd pypo', 'w')
|
p = os.popen('/usr/bin/passwd pypo 1>/dev/null 2>&1', 'w')
|
||||||
p.write('pypo\n')
|
p.write('pypo\n')
|
||||||
p.write('pypo\n')
|
p.write('pypo\n')
|
||||||
p.close()
|
p.close()
|
||||||
else:
|
else:
|
||||||
print "User already exists."
|
print "User already exists."
|
||||||
#add pypo to audio group
|
#add pypo to audio group
|
||||||
os.system("adduser " + username + " audio 2>&1 1>/dev/null")
|
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):
|
def copy_dir(src_dir, dest_dir):
|
||||||
if (os.path.exists(dest_dir)) and (dest_dir != "/"):
|
if (os.path.exists(dest_dir)) and (dest_dir != "/"):
|
||||||
|
@ -63,7 +65,7 @@ def get_current_script_dir():
|
||||||
try:
|
try:
|
||||||
current_script_dir = get_current_script_dir()
|
current_script_dir = get_current_script_dir()
|
||||||
print "Checking and removing any existing pypo processes"
|
print "Checking and removing any existing pypo processes"
|
||||||
os.system("python %s/pypo-uninstall.py 2>&1 1>/dev/null"% current_script_dir)
|
os.system("python %s/pypo-uninstall.py 1>/dev/null 2>&1"% current_script_dir)
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
|
|
||||||
# Create users
|
# Create users
|
||||||
|
@ -79,14 +81,8 @@ try:
|
||||||
create_path(BASE_PATH+"cache")
|
create_path(BASE_PATH+"cache")
|
||||||
create_path(BASE_PATH+"files")
|
create_path(BASE_PATH+"files")
|
||||||
create_path(BASE_PATH+"tmp")
|
create_path(BASE_PATH+"tmp")
|
||||||
create_path(BASE_PATH+"files/basic")
|
|
||||||
create_path(BASE_PATH+"files/fallback")
|
|
||||||
create_path(BASE_PATH+"files/jingles")
|
|
||||||
create_path(BASE_PATH+"archive")
|
create_path(BASE_PATH+"archive")
|
||||||
|
|
||||||
print "Copying pypo files"
|
|
||||||
shutil.copy("%s/../scripts/silence.mp3"%current_script_dir, BASE_PATH+"files/basic")
|
|
||||||
|
|
||||||
if platform.architecture()[0] == '64bit':
|
if platform.architecture()[0] == '64bit':
|
||||||
print "Installing 64-bit liquidsoap binary"
|
print "Installing 64-bit liquidsoap binary"
|
||||||
shutil.copy("%s/../liquidsoap/liquidsoap64"%current_script_dir, "%s/../liquidsoap/liquidsoap"%current_script_dir)
|
shutil.copy("%s/../liquidsoap/liquidsoap64"%current_script_dir, "%s/../liquidsoap/liquidsoap"%current_script_dir)
|
||||||
|
@ -98,28 +94,21 @@ try:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
copy_dir("%s/.."%current_script_dir, BASE_PATH+"bin/")
|
copy_dir("%s/.."%current_script_dir, BASE_PATH+"bin/")
|
||||||
|
copy_dir("%s/../../api_clients"%current_script_dir, BASE_PATH+"api_clients/")
|
||||||
|
|
||||||
print "Setting permissions"
|
print "Setting permissions"
|
||||||
os.system("chmod -R 755 "+BASE_PATH)
|
os.system("chmod -R 755 "+BASE_PATH)
|
||||||
os.system("chown -R pypo:pypo "+BASE_PATH)
|
os.system("chown -R pypo:pypo "+BASE_PATH)
|
||||||
|
|
||||||
print "Installing daemontool script pypo-fetch"
|
print "Installing pypo daemon"
|
||||||
create_path("/etc/service/pypo-fetch")
|
create_path("/etc/service/pypo")
|
||||||
create_path("/etc/service/pypo-fetch/log")
|
create_path("/etc/service/pypo/log")
|
||||||
shutil.copy("%s/pypo-daemontools-fetch.sh"%current_script_dir, "/etc/service/pypo-fetch/run")
|
shutil.copy("%s/pypo-daemontools.sh"%current_script_dir, "/etc/service/pypo/run")
|
||||||
shutil.copy("%s/pypo-daemontools-logger.sh"%current_script_dir, "/etc/service/pypo-fetch/log/run")
|
shutil.copy("%s/pypo-daemontools-logger.sh"%current_script_dir, "/etc/service/pypo/log/run")
|
||||||
os.system("chmod -R 755 /etc/service/pypo-fetch")
|
os.system("chmod -R 755 /etc/service/pypo")
|
||||||
os.system("chown -R pypo:pypo /etc/service/pypo-fetch")
|
os.system("chown -R pypo:pypo /etc/service/pypo")
|
||||||
|
|
||||||
print "Installing daemontool script pypo-push"
|
print "Installing liquidsoap daemon"
|
||||||
create_path("/etc/service/pypo-push")
|
|
||||||
create_path("/etc/service/pypo-push/log")
|
|
||||||
shutil.copy("%s/pypo-daemontools-push.sh"%current_script_dir, "/etc/service/pypo-push/run")
|
|
||||||
shutil.copy("%s/pypo-daemontools-logger.sh"%current_script_dir, "/etc/service/pypo-push/log/run")
|
|
||||||
os.system("chmod -R 755 /etc/service/pypo-push")
|
|
||||||
os.system("chown -R pypo:pypo /etc/service/pypo-push")
|
|
||||||
|
|
||||||
print "Installing daemontool script pypo-liquidsoap"
|
|
||||||
create_path("/etc/service/pypo-liquidsoap")
|
create_path("/etc/service/pypo-liquidsoap")
|
||||||
create_path("/etc/service/pypo-liquidsoap/log")
|
create_path("/etc/service/pypo-liquidsoap/log")
|
||||||
shutil.copy("%s/pypo-daemontools-liquidsoap.sh"%current_script_dir, "/etc/service/pypo-liquidsoap/run")
|
shutil.copy("%s/pypo-daemontools-liquidsoap.sh"%current_script_dir, "/etc/service/pypo-liquidsoap/run")
|
||||||
|
@ -134,16 +123,12 @@ try:
|
||||||
|
|
||||||
found = True
|
found = True
|
||||||
|
|
||||||
p = Popen('svstat /etc/service/pypo-fetch', shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
|
p = Popen('svstat /etc/service/pypo', shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
|
||||||
output = p.stdout.read()
|
output = p.stdout.read()
|
||||||
if (output.find("unable to open supervise/ok: file does not exist") >= 0):
|
if (output.find("unable to open supervise/ok: file does not exist") >= 0):
|
||||||
found = False
|
found = False
|
||||||
print output
|
print output
|
||||||
|
|
||||||
p = Popen('svstat /etc/service/pypo-push', shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
|
|
||||||
output = p.stdout.read()
|
|
||||||
print output
|
|
||||||
|
|
||||||
p = Popen('svstat /etc/service/pypo-liquidsoap', shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
|
p = Popen('svstat /etc/service/pypo-liquidsoap', shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
|
||||||
output = p.stdout.read()
|
output = p.stdout.read()
|
||||||
print output
|
print output
|
||||||
|
@ -152,6 +137,7 @@ try:
|
||||||
print "Pypo install has completed, but daemontools is not running, please make sure you have it installed and then reboot."
|
print "Pypo install has completed, but daemontools is not running, please make sure you have it installed and then reboot."
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print "exception:" + str(e)
|
print "exception:" + str(e)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,9 @@ if os.geteuid() != 0:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
print "Starting daemontool script pypo-fetch"
|
print "Starting daemontool script pypo"
|
||||||
os.system("svc -u /etc/service/pypo-fetch")
|
os.system("svc -u /etc/service/pypo")
|
||||||
|
|
||||||
print "Starting daemontool script pypo-push"
|
|
||||||
os.system("svc -u /etc/service/pypo-push")
|
|
||||||
|
|
||||||
print "Starting daemontool script pypo-liquidsoap"
|
print "Starting daemontool script pypo-liquidsoap"
|
||||||
os.system("svc -u /etc/service/pypo-liquidsoap")
|
os.system("svc -u /etc/service/pypo-liquidsoap")
|
||||||
|
|
|
@ -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)
|
|
@ -15,13 +15,13 @@ def remove_path(path):
|
||||||
os.system("rm -rf " + path)
|
os.system("rm -rf " + path)
|
||||||
|
|
||||||
def remove_user(username):
|
def remove_user(username):
|
||||||
os.system("killall -u %s 2>&1 1>/dev/null" % 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
|
#allow all process to be completely closed before we attempt to delete user
|
||||||
print "Waiting for processes to close..."
|
print "Waiting for processes to close..."
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
|
|
||||||
os.system("deluser --remove-home " + username + " 1>/dev/null")
|
os.system("deluser --remove-home " + username + " 1>/dev/null 2>&1")
|
||||||
|
|
||||||
def get_current_script_dir():
|
def get_current_script_dir():
|
||||||
current_script_dir = os.path.realpath(__file__)
|
current_script_dir = os.path.realpath(__file__)
|
||||||
|
@ -37,16 +37,19 @@ try:
|
||||||
print "Removing pypo files"
|
print "Removing pypo files"
|
||||||
remove_path(BASE_PATH)
|
remove_path(BASE_PATH)
|
||||||
|
|
||||||
print "Removing daemontool script pypo-fetch"
|
print "Removing daemontool script pypo"
|
||||||
remove_path("rm -rf /etc/service/pypo-fetch")
|
remove_path("/etc/service/pypo")
|
||||||
|
|
||||||
print "Removing daemontool script pypo-push"
|
if os.path.exists("/etc/service/pypo-fetch"):
|
||||||
remove_path("rm -rf /etc/service/pypo-push")
|
remove_path("/etc/service/pypo-fetch")
|
||||||
|
|
||||||
|
if os.path.exists("/etc/service/pypo-push"):
|
||||||
|
remove_path("/etc/service/pypo-push")
|
||||||
|
|
||||||
print "Removing daemontool script pypo-liquidsoap"
|
print "Removing daemontool script pypo-liquidsoap"
|
||||||
remove_path("rm -rf /etc/service/pypo-liquidsoap")
|
remove_path("/etc/service/pypo-liquidsoap")
|
||||||
|
|
||||||
remove_user("pypo")
|
remove_user("pypo")
|
||||||
print "Uninstall complete."
|
print "Pypo uninstall complete."
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print "exception:" + str(e)
|
print "exception:" + str(e)
|
|
@ -0,0 +1,34 @@
|
||||||
|
[loggers]
|
||||||
|
keys=root,fetch,push
|
||||||
|
|
||||||
|
[handlers]
|
||||||
|
keys=consoleHandler
|
||||||
|
|
||||||
|
[formatters]
|
||||||
|
keys=simpleFormatter
|
||||||
|
|
||||||
|
[logger_root]
|
||||||
|
level=DEBUG
|
||||||
|
handlers=consoleHandler
|
||||||
|
|
||||||
|
[logger_fetch]
|
||||||
|
level=DEBUG
|
||||||
|
handlers=consoleHandler
|
||||||
|
qualname=fetch
|
||||||
|
propagate=0
|
||||||
|
|
||||||
|
[logger_push]
|
||||||
|
level=DEBUG
|
||||||
|
handlers=consoleHandler
|
||||||
|
qualname=push
|
||||||
|
propagate=0
|
||||||
|
|
||||||
|
[handler_consoleHandler]
|
||||||
|
class=StreamHandler
|
||||||
|
level=DEBUG
|
||||||
|
formatter=simpleFormatter
|
||||||
|
args=(sys.stdout,)
|
||||||
|
|
||||||
|
[formatter_simpleFormatter]
|
||||||
|
format=%(asctime)s %(levelname)s - [%(filename)s : %(funcName)s() : line %(lineno)d] - %(message)s
|
||||||
|
datefmt=
|
|
@ -7,14 +7,13 @@ Python part of radio playout (pypo)
|
||||||
The main functions are "fetch" (./pypo_cli.py -f) and "push" (./pypo_cli.py -p)
|
The main functions are "fetch" (./pypo_cli.py -f) and "push" (./pypo_cli.py -p)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# python defaults (debian default)
|
|
||||||
import time
|
import time
|
||||||
#import calendar
|
#import calendar
|
||||||
|
|
||||||
|
|
||||||
#import traceback
|
#import traceback
|
||||||
from optparse import *
|
from optparse import *
|
||||||
import sys
|
import sys
|
||||||
|
import os
|
||||||
|
import signal
|
||||||
#import datetime
|
#import datetime
|
||||||
import logging
|
import logging
|
||||||
import logging.config
|
import logging.config
|
||||||
|
@ -27,11 +26,11 @@ import logging.config
|
||||||
#import string
|
#import string
|
||||||
#import operator
|
#import operator
|
||||||
#import inspect
|
#import inspect
|
||||||
|
from Queue import Queue
|
||||||
|
|
||||||
from pypopush import PypoPush
|
from pypopush import PypoPush
|
||||||
from pypofetch import PypoFetch
|
from pypofetch import PypoFetch
|
||||||
|
|
||||||
# additional modules (should be checked)
|
|
||||||
from configobj import ConfigObj
|
from configobj import ConfigObj
|
||||||
|
|
||||||
# custom imports
|
# custom imports
|
||||||
|
@ -53,7 +52,6 @@ parser.add_option("-v", "--compat", help="Check compatibility with server API ve
|
||||||
parser.add_option("-t", "--test", help="Do a test to make sure everything is working properly.", default=False, action="store_true", dest="test")
|
parser.add_option("-t", "--test", help="Do a test to make sure everything is working properly.", default=False, action="store_true", dest="test")
|
||||||
parser.add_option("-f", "--fetch-scheduler", help="Fetch the schedule from server. This is a polling process that runs forever.", default=False, action="store_true", dest="fetch_scheduler")
|
parser.add_option("-f", "--fetch-scheduler", help="Fetch the schedule from server. This is a polling process that runs forever.", default=False, action="store_true", dest="fetch_scheduler")
|
||||||
parser.add_option("-p", "--push-scheduler", help="Push the schedule to Liquidsoap. This is a polling process that runs forever.", default=False, action="store_true", dest="push_scheduler")
|
parser.add_option("-p", "--push-scheduler", help="Push the schedule to Liquidsoap. This is a polling process that runs forever.", default=False, action="store_true", dest="push_scheduler")
|
||||||
|
|
||||||
parser.add_option("-b", "--cleanup", help="Cleanup", default=False, action="store_true", dest="cleanup")
|
parser.add_option("-b", "--cleanup", help="Cleanup", default=False, action="store_true", dest="cleanup")
|
||||||
parser.add_option("-c", "--check", help="Check the cached schedule and exit", default=False, action="store_true", dest="check")
|
parser.add_option("-c", "--check", help="Check the cached schedule and exit", default=False, action="store_true", dest="check")
|
||||||
|
|
||||||
|
@ -66,10 +64,6 @@ logging.config.fileConfig("logging.cfg")
|
||||||
# loading config file
|
# loading config file
|
||||||
try:
|
try:
|
||||||
config = ConfigObj('config.cfg')
|
config = ConfigObj('config.cfg')
|
||||||
POLL_INTERVAL = float(config['poll_interval'])
|
|
||||||
PUSH_INTERVAL = float(config['push_interval'])
|
|
||||||
LS_HOST = config['ls_host']
|
|
||||||
LS_PORT = config['ls_port']
|
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print 'Error loading config file: ', e
|
print 'Error loading config file: ', e
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
@ -121,55 +115,44 @@ class Global:
|
||||||
for media in playlist['medias']:
|
for media in playlist['medias']:
|
||||||
print media
|
print media
|
||||||
|
|
||||||
|
def keyboardInterruptHandler(signum, frame):
|
||||||
|
print "\nKeyboard Interrupt\n"
|
||||||
|
sys.exit();
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print '###########################################'
|
print '###########################################'
|
||||||
print '# *** pypo *** #'
|
print '# *** pypo *** #'
|
||||||
print '# Liquidsoap + External Scheduler #'
|
print '# Liquidsoap Scheduled Playout System #'
|
||||||
print '# Playout System #'
|
|
||||||
print '###########################################'
|
print '###########################################'
|
||||||
|
|
||||||
|
signal.signal(signal.SIGINT, keyboardInterruptHandler)
|
||||||
|
|
||||||
# initialize
|
# initialize
|
||||||
g = Global()
|
g = Global()
|
||||||
g.selfcheck()
|
g.selfcheck()
|
||||||
|
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
loops = 0
|
|
||||||
|
|
||||||
if options.test:
|
if options.test:
|
||||||
g.test_api()
|
g.test_api()
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
q = Queue()
|
||||||
if options.fetch_scheduler:
|
|
||||||
pf = PypoFetch()
|
|
||||||
while True:
|
|
||||||
try: pf.fetch('scheduler')
|
|
||||||
except Exception, e:
|
|
||||||
print e
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
if (loops%2 == 0):
|
pp = PypoPush(q)
|
||||||
logger.info("heartbeat")
|
pp.daemon = True
|
||||||
loops += 1
|
pp.start()
|
||||||
time.sleep(POLL_INTERVAL)
|
|
||||||
|
|
||||||
if options.push_scheduler:
|
pf = PypoFetch(q)
|
||||||
pp = PypoPush()
|
pf.daemon = True
|
||||||
while True:
|
pf.start()
|
||||||
try: pp.push('scheduler')
|
|
||||||
except Exception, e:
|
|
||||||
print 'PUSH ERROR!! WILL EXIT NOW:('
|
|
||||||
print e
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
if (loops%60 == 0):
|
while True: time.sleep(3600)
|
||||||
logger.info("heartbeat")
|
|
||||||
|
|
||||||
loops += 1
|
|
||||||
time.sleep(PUSH_INTERVAL)
|
|
||||||
|
|
||||||
|
#pp.join()
|
||||||
|
#pf.join()
|
||||||
|
"""
|
||||||
if options.check:
|
if options.check:
|
||||||
try: g.check_schedule()
|
try: g.check_schedule()
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
|
@ -179,4 +162,4 @@ if __name__ == '__main__':
|
||||||
try: pf.cleanup('scheduler')
|
try: pf.cleanup('scheduler')
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print e
|
print e
|
||||||
sys.exit()
|
"""
|
|
@ -9,146 +9,151 @@ import random
|
||||||
import string
|
import string
|
||||||
import json
|
import json
|
||||||
import telnetlib
|
import telnetlib
|
||||||
|
import math
|
||||||
|
from threading import Thread
|
||||||
|
from subprocess import Popen, PIPE
|
||||||
|
|
||||||
|
# For RabbitMQ
|
||||||
|
from kombu.connection import BrokerConnection
|
||||||
|
from kombu.messaging import Exchange, Queue, Consumer, Producer
|
||||||
|
|
||||||
from api_clients import api_client
|
from api_clients import api_client
|
||||||
from util import CueFile
|
from util import CueFile
|
||||||
|
|
||||||
from configobj import ConfigObj
|
from configobj import ConfigObj
|
||||||
|
|
||||||
|
# configure logging
|
||||||
|
logging.config.fileConfig("logging.cfg")
|
||||||
|
|
||||||
# loading config file
|
# loading config file
|
||||||
try:
|
try:
|
||||||
config = ConfigObj('config.cfg')
|
config = ConfigObj('config.cfg')
|
||||||
POLL_INTERVAL = float(config['poll_interval'])
|
|
||||||
PUSH_INTERVAL = 0.5
|
|
||||||
#PUSH_INTERVAL = float(config['push_interval'])
|
|
||||||
LS_HOST = config['ls_host']
|
LS_HOST = config['ls_host']
|
||||||
LS_PORT = config['ls_port']
|
LS_PORT = config['ls_port']
|
||||||
|
POLL_INTERVAL = int(config['poll_interval'])
|
||||||
|
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print 'Error loading config file: ', e
|
print 'Error loading config file: ', e
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
class PypoFetch:
|
# Yuk - using a global, i know!
|
||||||
def __init__(self):
|
SCHEDULE_PUSH_MSG = []
|
||||||
|
|
||||||
|
"""
|
||||||
|
Handle a message from RabbitMQ, put it into our yucky global var.
|
||||||
|
Hopefully there is a better way to do this.
|
||||||
|
"""
|
||||||
|
def handle_message(body, message):
|
||||||
|
logger = logging.getLogger('fetch')
|
||||||
|
global SCHEDULE_PUSH_MSG
|
||||||
|
logger.info("Received schedule from RabbitMQ: " + message.body)
|
||||||
|
SCHEDULE_PUSH_MSG = json.loads(message.body)
|
||||||
|
# ACK the message to take it off the queue
|
||||||
|
message.ack()
|
||||||
|
|
||||||
|
|
||||||
|
class PypoFetch(Thread):
|
||||||
|
def __init__(self, q):
|
||||||
|
Thread.__init__(self)
|
||||||
|
logger = logging.getLogger('fetch')
|
||||||
self.api_client = api_client.api_client_factory(config)
|
self.api_client = api_client.api_client_factory(config)
|
||||||
self.cue_file = CueFile()
|
self.cue_file = CueFile()
|
||||||
self.set_export_source('scheduler')
|
self.set_export_source('scheduler')
|
||||||
|
self.queue = q
|
||||||
|
|
||||||
|
logger.info("Initializing RabbitMQ stuff")
|
||||||
|
schedule_exchange = Exchange("airtime-schedule", "direct", durable=True, auto_delete=True)
|
||||||
|
schedule_queue = Queue("pypo-fetch", exchange=schedule_exchange, key="foo")
|
||||||
|
self.connection = BrokerConnection(config["rabbitmq_host"], config["rabbitmq_user"], config["rabbitmq_password"], "/")
|
||||||
|
channel = self.connection.channel()
|
||||||
|
consumer = Consumer(channel, schedule_queue)
|
||||||
|
consumer.register_callback(handle_message)
|
||||||
|
consumer.consume()
|
||||||
|
|
||||||
|
logger.info("PypoFetch: init complete")
|
||||||
|
|
||||||
|
|
||||||
def set_export_source(self, export_source):
|
def set_export_source(self, export_source):
|
||||||
self.export_source = export_source
|
self.export_source = export_source
|
||||||
self.cache_dir = config["cache_dir"] + self.export_source + '/'
|
self.cache_dir = config["cache_dir"] + self.export_source + '/'
|
||||||
self.schedule_file = self.cache_dir + 'schedule.pickle'
|
|
||||||
self.schedule_tracker_file = self.cache_dir + "schedule_tracker.pickle"
|
def check_matching_timezones(self, server_timezone):
|
||||||
|
logger = logging.getLogger('fetch')
|
||||||
|
|
||||||
|
process = Popen(["date", "+%z"], stdout=PIPE)
|
||||||
|
pypo_timezone = (process.communicate()[0]).strip(' \r\n\t')
|
||||||
|
|
||||||
|
if server_timezone != pypo_timezone:
|
||||||
|
logger.error("Server and pypo timezone offsets do not match. Audio playback may not start when expected!")
|
||||||
|
logger.error("Server timezone offset: %s", server_timezone)
|
||||||
|
logger.error("Pypo timezone offset: %s", pypo_timezone)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Fetching part of pypo
|
Process the schedule
|
||||||
- Reads the scheduled entries of a given range (actual time +/- "prepare_ahead" / "cache_for")
|
- Reads the scheduled entries of a given range (actual time +/- "prepare_ahead" / "cache_for")
|
||||||
- Saves a serialized file of the schedule
|
- Saves a serialized file of the schedule
|
||||||
- playlists are prepared. (brought to liquidsoap format) and, if not mounted via nsf, files are copied
|
- playlists are prepared. (brought to liquidsoap format) and, if not mounted via nsf, files are copied
|
||||||
to the cache dir (Folder-structure: cache/YYYY-MM-DD-hh-mm-ss)
|
to the cache dir (Folder-structure: cache/YYYY-MM-DD-hh-mm-ss)
|
||||||
- runs the cleanup routine, to get rid of unused cashed files
|
- runs the cleanup routine, to get rid of unused cashed files
|
||||||
"""
|
"""
|
||||||
def fetch(self, export_source):
|
def process_schedule(self, schedule_data, export_source):
|
||||||
"""
|
logger = logging.getLogger('fetch')
|
||||||
wrapper script for fetching the whole schedule (in json)
|
self.schedule = schedule_data["playlists"]
|
||||||
"""
|
|
||||||
logger = logging.getLogger()
|
|
||||||
|
|
||||||
try: os.mkdir(self.cache_dir)
|
self.check_matching_timezones(schedule_data["server_timezone"])
|
||||||
except Exception, e: pass
|
|
||||||
|
# Push stream metadata to liquidsoap
|
||||||
# get schedule
|
# TODO: THIS LIQUIDSOAP STUFF NEEDS TO BE MOVED TO PYPO-PUSH!!!
|
||||||
|
stream_metadata = schedule_data['stream_metadata']
|
||||||
try:
|
try:
|
||||||
while self.get_schedule() != 1:
|
tn = telnetlib.Telnet(LS_HOST, LS_PORT)
|
||||||
logger.warning("failed to read from export url")
|
#encode in latin-1 due to telnet protocol not supporting utf-8
|
||||||
time.sleep(1)
|
tn.write(('vars.stream_metadata_type %s\n' % stream_metadata['format']).encode('latin-1'))
|
||||||
|
tn.write(('vars.station_name %s\n' % stream_metadata['station_name']).encode('latin-1'))
|
||||||
|
tn.write('exit\n')
|
||||||
|
tn.read_all()
|
||||||
|
except Exception, e:
|
||||||
|
logger.error("Exception %s", e)
|
||||||
|
status = 0
|
||||||
|
|
||||||
|
# Download all the media and put playlists in liquidsoap format
|
||||||
|
try:
|
||||||
|
playlists = self.prepare_playlists()
|
||||||
except Exception, e: logger.error("%s", e)
|
except Exception, e: logger.error("%s", e)
|
||||||
|
|
||||||
# prepare the playlists
|
# Send the data to pypo-push
|
||||||
if config["cue_style"] == 'pre':
|
scheduled_data = dict()
|
||||||
try: self.prepare_playlists_cue()
|
scheduled_data['playlists'] = playlists
|
||||||
except Exception, e: logger.error("%s", e)
|
scheduled_data['schedule'] = self.schedule
|
||||||
elif config["cue_style"] == 'otf':
|
scheduled_data['stream_metadata'] = schedule_data["stream_metadata"]
|
||||||
try: self.prepare_playlists(self.export_source)
|
self.queue.put(scheduled_data)
|
||||||
except Exception, e: logger.error("%s", e)
|
|
||||||
|
|
||||||
# cleanup
|
# cleanup
|
||||||
try: self.cleanup(self.export_source)
|
try: self.cleanup(self.export_source)
|
||||||
except Exception, e: logger.error("%s", e)
|
except Exception, e: logger.error("%s", e)
|
||||||
|
|
||||||
def get_schedule(self):
|
|
||||||
logger = logging.getLogger()
|
|
||||||
status, response = self.api_client.get_schedule()
|
|
||||||
|
|
||||||
if status == 1:
|
|
||||||
logger.info("dump serialized schedule to %s", self.schedule_file)
|
|
||||||
schedule = response['playlists']
|
|
||||||
stream_metadata = response['stream_metadata']
|
|
||||||
try:
|
|
||||||
schedule_file = open(self.schedule_file, "w")
|
|
||||||
pickle.dump(schedule, schedule_file)
|
|
||||||
schedule_file.close()
|
|
||||||
|
|
||||||
tn = telnetlib.Telnet(LS_HOST, LS_PORT)
|
|
||||||
|
|
||||||
#encode in latin-1 due to telnet protocol not supporting utf-8
|
|
||||||
tn.write(('vars.stream_metadata_type %s\n' % stream_metadata['format']).encode('latin-1'))
|
|
||||||
tn.write(('vars.station_name %s\n' % stream_metadata['station_name']).encode('latin-1'))
|
|
||||||
|
|
||||||
tn.write('exit\n')
|
|
||||||
logger.debug(tn.read_all())
|
|
||||||
|
|
||||||
except Exception, e:
|
|
||||||
logger.error("Exception %s", e)
|
|
||||||
status = 0
|
|
||||||
|
|
||||||
return status
|
|
||||||
|
|
||||||
#TODO this is a duplicate function!!!
|
|
||||||
def load_schedule(self):
|
|
||||||
logger = logging.getLogger()
|
|
||||||
schedule = None
|
|
||||||
|
|
||||||
# create the file if it doesnt exist
|
|
||||||
if (not os.path.exists(self.schedule_file)):
|
|
||||||
logger.debug('creating file ' + self.schedule_file)
|
|
||||||
open(self.schedule_file, 'w').close()
|
|
||||||
else:
|
|
||||||
# load the schedule from cache
|
|
||||||
#logger.debug('loading schedule file '+self.schedule_file)
|
|
||||||
try:
|
|
||||||
schedule_file = open(self.schedule_file, "r")
|
|
||||||
schedule = pickle.load(schedule_file)
|
|
||||||
schedule_file.close()
|
|
||||||
|
|
||||||
except Exception, e:
|
|
||||||
logger.error('%s', e)
|
|
||||||
|
|
||||||
return schedule
|
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Alternative version of playout preparation. Every playlist entry is
|
In this function every audio file is cut as necessary (cue_in/cue_out != 0)
|
||||||
pre-cued if neccessary (cue_in/cue_out != 0) and stored in the
|
and stored in a playlist folder.
|
||||||
playlist folder.
|
file is e.g. 2010-06-23-15-00-00/17_cue_10.132-123.321.mp3
|
||||||
file is eg 2010-06-23-15-00-00/17_cue_10.132-123.321.mp3
|
|
||||||
"""
|
"""
|
||||||
def prepare_playlists_cue(self):
|
def prepare_playlists(self):
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger('fetch')
|
||||||
|
|
||||||
# Load schedule from disk
|
schedule = self.schedule
|
||||||
schedule = self.load_schedule()
|
playlists = dict()
|
||||||
|
|
||||||
# Dont do anything if schedule is empty
|
# Dont do anything if schedule is empty
|
||||||
if (not schedule):
|
if not schedule:
|
||||||
logger.debug("Schedule is empty.")
|
logger.debug("Schedule is empty.")
|
||||||
return
|
return playlists
|
||||||
|
|
||||||
scheduleKeys = sorted(schedule.iterkeys())
|
scheduleKeys = sorted(schedule.iterkeys())
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for pkey in scheduleKeys:
|
for pkey in scheduleKeys:
|
||||||
logger.info("found playlist at %s", pkey)
|
logger.info("Playlist starting at %s", pkey)
|
||||||
playlist = schedule[pkey]
|
playlist = schedule[pkey]
|
||||||
|
|
||||||
# create playlist directory
|
# create playlist directory
|
||||||
|
@ -157,15 +162,15 @@ class PypoFetch:
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
logger.debug('*****************************************')
|
#logger.debug('*****************************************')
|
||||||
logger.debug('pkey: ' + str(pkey))
|
#logger.debug('pkey: ' + str(pkey))
|
||||||
logger.debug('cached at : ' + self.cache_dir + str(pkey))
|
#logger.debug('cached at : ' + self.cache_dir + str(pkey))
|
||||||
logger.debug('subtype: ' + str(playlist['subtype']))
|
#logger.debug('subtype: ' + str(playlist['subtype']))
|
||||||
logger.debug('played: ' + str(playlist['played']))
|
#logger.debug('played: ' + str(playlist['played']))
|
||||||
logger.debug('schedule id: ' + str(playlist['schedule_id']))
|
#logger.debug('schedule id: ' + str(playlist['schedule_id']))
|
||||||
logger.debug('duration: ' + str(playlist['duration']))
|
#logger.debug('duration: ' + str(playlist['duration']))
|
||||||
logger.debug('source id: ' + str(playlist['x_ident']))
|
#logger.debug('source id: ' + str(playlist['x_ident']))
|
||||||
logger.debug('*****************************************')
|
#logger.debug('*****************************************')
|
||||||
|
|
||||||
if int(playlist['played']) == 1:
|
if int(playlist['played']) == 1:
|
||||||
logger.info("playlist %s already played / sent to liquidsoap, so will ignore it", pkey)
|
logger.info("playlist %s already played / sent to liquidsoap, so will ignore it", pkey)
|
||||||
|
@ -173,34 +178,32 @@ class PypoFetch:
|
||||||
elif int(playlist['subtype']) > 0 and int(playlist['subtype']) < 5:
|
elif int(playlist['subtype']) > 0 and int(playlist['subtype']) < 5:
|
||||||
ls_playlist = self.handle_media_file(playlist, pkey)
|
ls_playlist = self.handle_media_file(playlist, pkey)
|
||||||
|
|
||||||
# write playlist file
|
playlists[pkey] = ls_playlist
|
||||||
plfile = open(self.cache_dir + str(pkey) + '/list.lsp', "w")
|
|
||||||
plfile.write(json.dumps(ls_playlist))
|
|
||||||
plfile.close()
|
|
||||||
logger.info('ls playlist file written to %s', self.cache_dir + str(pkey) + '/list.lsp')
|
|
||||||
|
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
logger.info("%s", e)
|
logger.info("%s", e)
|
||||||
|
return playlists
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
Download and cache the media files.
|
||||||
|
This handles both remote and local files.
|
||||||
|
Returns an updated ls_playlist string.
|
||||||
|
"""
|
||||||
def handle_media_file(self, playlist, pkey):
|
def handle_media_file(self, playlist, pkey):
|
||||||
"""
|
|
||||||
This handles both remote and local files.
|
|
||||||
Returns an updated ls_playlist string.
|
|
||||||
"""
|
|
||||||
ls_playlist = []
|
ls_playlist = []
|
||||||
|
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger('fetch')
|
||||||
for media in playlist['medias']:
|
for media in playlist['medias']:
|
||||||
logger.debug("Processing track %s", media['uri'])
|
logger.debug("Processing track %s", media['uri'])
|
||||||
|
|
||||||
fileExt = os.path.splitext(media['uri'])[1]
|
fileExt = os.path.splitext(media['uri'])[1]
|
||||||
try:
|
try:
|
||||||
if str(media['cue_in']) == '0' and str(media['cue_out']) == '0':
|
if str(media['cue_in']) == '0' and str(media['cue_out']) == '0':
|
||||||
logger.debug('No cue in/out detected for this file')
|
#logger.debug('No cue in/out detected for this file')
|
||||||
dst = "%s%s/%s%s" % (self.cache_dir, str(pkey), str(media['id']), str(fileExt))
|
dst = "%s%s/%s%s" % (self.cache_dir, str(pkey), str(media['id']), str(fileExt))
|
||||||
do_cue = False
|
do_cue = False
|
||||||
else:
|
else:
|
||||||
logger.debug('Cue in/out detected')
|
#logger.debug('Cue in/out detected')
|
||||||
dst = "%s%s/%s_cue_%s-%s%s" % \
|
dst = "%s%s/%s_cue_%s-%s%s" % \
|
||||||
(self.cache_dir, str(pkey), str(media['id']), str(float(media['cue_in']) / 1000), str(float(media['cue_out']) / 1000), str(fileExt))
|
(self.cache_dir, str(pkey), str(media['id']), str(float(media['cue_in']) / 1000), str(float(media['cue_out']) / 1000), str(fileExt))
|
||||||
do_cue = True
|
do_cue = True
|
||||||
|
@ -225,7 +228,7 @@ class PypoFetch:
|
||||||
% (str(media['export_source']), media['id'], 0, str(float(media['fade_in']) / 1000), \
|
% (str(media['export_source']), media['id'], 0, str(float(media['fade_in']) / 1000), \
|
||||||
str(float(media['fade_out']) / 1000), media['row_id'],dst)
|
str(float(media['fade_out']) / 1000), media['row_id'],dst)
|
||||||
|
|
||||||
logger.debug(pl_entry)
|
#logger.debug(pl_entry)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Tracks are only added to the playlist if they are accessible
|
Tracks are only added to the playlist if they are accessible
|
||||||
|
@ -239,7 +242,7 @@ class PypoFetch:
|
||||||
entry['show_name'] = playlist['show_name']
|
entry['show_name'] = playlist['show_name']
|
||||||
ls_playlist.append(entry)
|
ls_playlist.append(entry)
|
||||||
|
|
||||||
logger.debug("everything ok, adding %s to playlist", pl_entry)
|
#logger.debug("everything ok, adding %s to playlist", pl_entry)
|
||||||
else:
|
else:
|
||||||
print 'zero-file: ' + dst + ' from ' + media['uri']
|
print 'zero-file: ' + dst + ' from ' + media['uri']
|
||||||
logger.warning("zero-size file - skipping %s. will not add it to playlist", dst)
|
logger.warning("zero-size file - skipping %s. will not add it to playlist", dst)
|
||||||
|
@ -251,11 +254,15 @@ class PypoFetch:
|
||||||
return ls_playlist
|
return ls_playlist
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
Download a file from a remote server and store it in the cache.
|
||||||
|
"""
|
||||||
def handle_remote_file(self, media, dst, do_cue):
|
def handle_remote_file(self, media, dst, do_cue):
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger('fetch')
|
||||||
if do_cue == False:
|
if do_cue == False:
|
||||||
if os.path.isfile(dst):
|
if os.path.isfile(dst):
|
||||||
logger.debug("file already in cache: %s", dst)
|
pass
|
||||||
|
#logger.debug("file already in cache: %s", dst)
|
||||||
else:
|
else:
|
||||||
logger.debug("try to download %s", media['uri'])
|
logger.debug("try to download %s", media['uri'])
|
||||||
self.api_client.get_media(media['uri'], dst)
|
self.api_client.get_media(media['uri'], dst)
|
||||||
|
@ -296,12 +303,12 @@ class PypoFetch:
|
||||||
logger.error("%s", e)
|
logger.error("%s", e)
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
Cleans up folders in cache_dir. Look for modification date older than "now - CACHE_FOR"
|
||||||
|
and deletes them.
|
||||||
|
"""
|
||||||
def cleanup(self, export_source):
|
def cleanup(self, export_source):
|
||||||
"""
|
logger = logging.getLogger('fetch')
|
||||||
Cleans up folders in cache_dir. Look for modification date older than "now - CACHE_FOR"
|
|
||||||
and deletes them.
|
|
||||||
"""
|
|
||||||
logger = logging.getLogger()
|
|
||||||
|
|
||||||
offset = 3600 * int(config["cache_for"])
|
offset = 3600 * int(config["cache_for"])
|
||||||
now = time.time()
|
now = time.time()
|
||||||
|
@ -323,3 +330,41 @@ class PypoFetch:
|
||||||
print e
|
print e
|
||||||
logger.error("%s", e)
|
logger.error("%s", e)
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
Main loop of the thread:
|
||||||
|
Wait for schedule updates from RabbitMQ, but in case there arent any,
|
||||||
|
poll the server to get the upcoming schedule.
|
||||||
|
"""
|
||||||
|
def run(self):
|
||||||
|
logger = logging.getLogger('fetch')
|
||||||
|
|
||||||
|
try: os.mkdir(self.cache_dir)
|
||||||
|
except Exception, e: pass
|
||||||
|
|
||||||
|
# Bootstrap: since we are just starting up, we need to grab the
|
||||||
|
# most recent schedule. After that we can just wait for updates.
|
||||||
|
status, schedule_data = self.api_client.get_schedule()
|
||||||
|
if status == 1:
|
||||||
|
self.process_schedule(schedule_data, "scheduler")
|
||||||
|
logger.info("Bootstrap complete: got initial copy of the schedule")
|
||||||
|
|
||||||
|
loops = 1
|
||||||
|
while True:
|
||||||
|
logger.info("Loop #"+str(loops))
|
||||||
|
try:
|
||||||
|
# Wait for messages from RabbitMQ. Timeout if we
|
||||||
|
# dont get any after POLL_INTERVAL.
|
||||||
|
self.connection.drain_events(timeout=POLL_INTERVAL)
|
||||||
|
# Hooray for globals!
|
||||||
|
schedule_data = SCHEDULE_PUSH_MSG
|
||||||
|
status = 1
|
||||||
|
except:
|
||||||
|
# We didnt get a message for a while, so poll the server
|
||||||
|
# to get an updated schedule.
|
||||||
|
status, schedule_data = self.api_client.get_schedule()
|
||||||
|
|
||||||
|
if status == 1:
|
||||||
|
self.process_schedule(schedule_data, "scheduler")
|
||||||
|
loops += 1
|
||||||
|
|
|
@ -7,29 +7,38 @@ import pickle
|
||||||
import telnetlib
|
import telnetlib
|
||||||
import calendar
|
import calendar
|
||||||
import json
|
import json
|
||||||
|
import math
|
||||||
|
from threading import Thread
|
||||||
|
|
||||||
from api_clients import api_client
|
from api_clients import api_client
|
||||||
from util import CueFile
|
from util import CueFile
|
||||||
|
|
||||||
from configobj import ConfigObj
|
from configobj import ConfigObj
|
||||||
|
|
||||||
|
# configure logging
|
||||||
|
logging.config.fileConfig("logging.cfg")
|
||||||
|
|
||||||
# loading config file
|
# loading config file
|
||||||
try:
|
try:
|
||||||
config = ConfigObj('config.cfg')
|
config = ConfigObj('config.cfg')
|
||||||
POLL_INTERVAL = float(config['poll_interval'])
|
|
||||||
PUSH_INTERVAL = 0.5
|
|
||||||
#PUSH_INTERVAL = float(config['push_interval'])
|
|
||||||
LS_HOST = config['ls_host']
|
LS_HOST = config['ls_host']
|
||||||
LS_PORT = config['ls_port']
|
LS_PORT = config['ls_port']
|
||||||
|
PUSH_INTERVAL = 2
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
print 'Error loading config file: ', e
|
logger.error('Error loading config file %s', e)
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
class PypoPush:
|
class PypoPush(Thread):
|
||||||
def __init__(self):
|
def __init__(self, q):
|
||||||
|
Thread.__init__(self)
|
||||||
self.api_client = api_client.api_client_factory(config)
|
self.api_client = api_client.api_client_factory(config)
|
||||||
self.cue_file = CueFile()
|
self.cue_file = CueFile()
|
||||||
self.set_export_source('scheduler')
|
self.set_export_source('scheduler')
|
||||||
|
self.queue = q
|
||||||
|
|
||||||
|
self.schedule = dict()
|
||||||
|
self.playlists = dict()
|
||||||
|
self.stream_metadata = dict()
|
||||||
|
|
||||||
"""
|
"""
|
||||||
push_ahead2 MUST be < push_ahead. The difference in these two values
|
push_ahead2 MUST be < push_ahead. The difference in these two values
|
||||||
|
@ -42,51 +51,58 @@ class PypoPush:
|
||||||
def set_export_source(self, export_source):
|
def set_export_source(self, export_source):
|
||||||
self.export_source = export_source
|
self.export_source = export_source
|
||||||
self.cache_dir = config["cache_dir"] + self.export_source + '/'
|
self.cache_dir = config["cache_dir"] + self.export_source + '/'
|
||||||
self.schedule_file = self.cache_dir + 'schedule.pickle'
|
|
||||||
self.schedule_tracker_file = self.cache_dir + "schedule_tracker.pickle"
|
self.schedule_tracker_file = self.cache_dir + "schedule_tracker.pickle"
|
||||||
|
|
||||||
"""
|
"""
|
||||||
The Push Loop - the push loop periodically (minimal 1/2 of the playlist-grid)
|
The Push Loop - the push loop periodically checks if there is a playlist
|
||||||
checks if there is a playlist that should be scheduled at the current time.
|
that should be scheduled at the current time.
|
||||||
If yes, the temporary liquidsoap playlist gets replaced with the corresponding one,
|
If yes, the current liquidsoap playlist gets replaced with the corresponding one,
|
||||||
then liquidsoap is asked (via telnet) to reload and immediately play it.
|
then liquidsoap is asked (via telnet) to reload and immediately play it.
|
||||||
"""
|
"""
|
||||||
def push(self, export_source):
|
def push(self, export_source):
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger('push')
|
||||||
|
|
||||||
self.schedule = self.load_schedule()
|
# get a new schedule from pypo-fetch
|
||||||
playedItems = self.load_schedule_tracker()
|
if not self.queue.empty():
|
||||||
|
scheduled_data = self.queue.get()
|
||||||
|
logger.debug("Received data from pypo-fetch")
|
||||||
|
self.schedule = scheduled_data['schedule']
|
||||||
|
self.playlists = scheduled_data['playlists']
|
||||||
|
self.stream_metadata = scheduled_data['stream_metadata']
|
||||||
|
|
||||||
tcoming = time.localtime(time.time() + self.push_ahead)
|
schedule = self.schedule
|
||||||
tcoming2 = time.localtime(time.time() + self.push_ahead2)
|
playlists = self.playlists
|
||||||
|
|
||||||
|
|
||||||
str_tcoming_s = "%04d-%02d-%02d-%02d-%02d-%02d" % (tcoming[0], tcoming[1], tcoming[2], tcoming[3], tcoming[4], tcoming[5])
|
|
||||||
str_tcoming2_s = "%04d-%02d-%02d-%02d-%02d-%02d" % (tcoming2[0], tcoming2[1], tcoming2[2], tcoming2[3], tcoming2[4], tcoming2[5])
|
|
||||||
|
|
||||||
currently_on_air = False
|
currently_on_air = False
|
||||||
if self.schedule == None:
|
if schedule:
|
||||||
logger.warn('Unable to loop schedule - maybe write in progress?')
|
playedItems = self.load_schedule_tracker()
|
||||||
logger.warn('Will try again in next loop.')
|
|
||||||
|
|
||||||
else:
|
timenow = time.time()
|
||||||
for pkey in self.schedule:
|
tcoming = time.localtime(timenow + self.push_ahead)
|
||||||
|
str_tcoming_s = "%04d-%02d-%02d-%02d-%02d-%02d" % (tcoming[0], tcoming[1], tcoming[2], tcoming[3], tcoming[4], tcoming[5])
|
||||||
|
|
||||||
|
tcoming2 = time.localtime(timenow + self.push_ahead2)
|
||||||
|
str_tcoming2_s = "%04d-%02d-%02d-%02d-%02d-%02d" % (tcoming2[0], tcoming2[1], tcoming2[2], tcoming2[3], tcoming2[4], tcoming2[5])
|
||||||
|
|
||||||
|
tnow = time.localtime(timenow)
|
||||||
|
str_tnow_s = "%04d-%02d-%02d-%02d-%02d-%02d" % (tnow[0], tnow[1], tnow[2], tnow[3], tnow[4], tnow[5])
|
||||||
|
|
||||||
|
for pkey in schedule:
|
||||||
plstart = pkey[0:19]
|
plstart = pkey[0:19]
|
||||||
start = self.schedule[pkey]['start']
|
start = schedule[pkey]['start']
|
||||||
end = self.schedule[pkey]['end']
|
end = schedule[pkey]['end']
|
||||||
|
|
||||||
playedFlag = (pkey in playedItems) and playedItems[pkey].get("played", 0)
|
playedFlag = (pkey in playedItems) and playedItems[pkey].get("played", 0)
|
||||||
|
|
||||||
if plstart == str_tcoming_s or (plstart < str_tcoming_s and plstart > str_tcoming2_s and not playedFlag):
|
if plstart == str_tcoming_s or (plstart < str_tcoming_s and plstart > str_tcoming2_s and not playedFlag):
|
||||||
logger.debug('Preparing to push playlist scheduled at: %s', pkey)
|
logger.debug('Preparing to push playlist scheduled at: %s', pkey)
|
||||||
playlist = self.schedule[pkey]
|
playlist = schedule[pkey]
|
||||||
|
|
||||||
ptype = playlist['subtype']
|
|
||||||
currently_on_air = True
|
currently_on_air = True
|
||||||
|
|
||||||
# We have a match, replace the current playlist and
|
# We have a match, replace the current playlist and
|
||||||
# force liquidsoap to refresh.
|
# force liquidsoap to refresh.
|
||||||
if (self.push_liquidsoap(pkey, self.schedule, ptype) == 1):
|
if (self.push_liquidsoap(pkey, schedule, playlists) == 1):
|
||||||
logger.debug("Pushed to liquidsoap, updating 'played' status.")
|
logger.debug("Pushed to liquidsoap, updating 'played' status.")
|
||||||
# Marked the current playlist as 'played' in the schedule tracker
|
# Marked the current playlist as 'played' in the schedule tracker
|
||||||
# so it is not called again in the next push loop.
|
# so it is not called again in the next push loop.
|
||||||
|
@ -100,39 +116,28 @@ class PypoPush:
|
||||||
|
|
||||||
# Call API to update schedule states
|
# Call API to update schedule states
|
||||||
logger.debug("Doing callback to server to update 'played' status.")
|
logger.debug("Doing callback to server to update 'played' status.")
|
||||||
self.api_client.notify_scheduled_item_start_playing(pkey, self.schedule)
|
self.api_client.notify_scheduled_item_start_playing(pkey, schedule)
|
||||||
|
|
||||||
if self.schedule != None:
|
start = schedule[pkey]['start']
|
||||||
tnow = time.localtime(time.time())
|
end = schedule[pkey]['end']
|
||||||
str_tnow_s = "%04d-%02d-%02d-%02d-%02d-%02d" % (tnow[0], tnow[1], tnow[2], tnow[3], tnow[4], tnow[5])
|
|
||||||
for pkey in self.schedule:
|
|
||||||
start = self.schedule[pkey]['start']
|
|
||||||
end = self.schedule[pkey]['end']
|
|
||||||
|
|
||||||
if start <= str_tnow_s and str_tnow_s < end:
|
if start <= str_tnow_s and str_tnow_s < end:
|
||||||
currently_on_air = True
|
currently_on_air = True
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
#logger.debug('Empty schedule')
|
||||||
|
|
||||||
if not currently_on_air:
|
if not currently_on_air:
|
||||||
tn = telnetlib.Telnet(LS_HOST, LS_PORT)
|
tn = telnetlib.Telnet(LS_HOST, LS_PORT)
|
||||||
tn.write('source.skip\n'.encode('latin-1'))
|
tn.write('source.skip\n')
|
||||||
tn.write('exit\n')
|
tn.write('exit\n')
|
||||||
tn.read_all()
|
tn.read_all()
|
||||||
#logger.info('source.skip')
|
|
||||||
#logger.debug(tn.read_all())
|
|
||||||
|
|
||||||
def push_liquidsoap(self, pkey, schedule, ptype):
|
def push_liquidsoap(self, pkey, schedule, playlists):
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger('push')
|
||||||
src = self.cache_dir + str(pkey) + '/list.lsp'
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if True == os.access(src, os.R_OK):
|
playlist = playlists[pkey]
|
||||||
logger.debug('OK - Can read playlist file')
|
|
||||||
|
|
||||||
pl_file = open(src, "r")
|
|
||||||
file_content = pl_file.read()
|
|
||||||
pl_file.close()
|
|
||||||
logger.debug('file content: %s' % (file_content))
|
|
||||||
playlist = json.loads(file_content)
|
|
||||||
|
|
||||||
#strptime returns struct_time in local time
|
#strptime returns struct_time in local time
|
||||||
#mktime takes a time_struct and returns a floating point
|
#mktime takes a time_struct and returns a floating point
|
||||||
|
@ -180,43 +185,24 @@ class PypoPush:
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
logger.error('%s', e)
|
logger.error('%s', e)
|
||||||
status = 0
|
status = 0
|
||||||
|
|
||||||
return status
|
return status
|
||||||
|
|
||||||
|
|
||||||
def load_schedule(self):
|
|
||||||
logger = logging.getLogger()
|
|
||||||
schedule = None
|
|
||||||
|
|
||||||
# create the file if it doesnt exist
|
|
||||||
if (not os.path.exists(self.schedule_file)):
|
|
||||||
logger.debug('creating file ' + self.schedule_file)
|
|
||||||
open(self.schedule_file, 'w').close()
|
|
||||||
else:
|
|
||||||
# load the schedule from cache
|
|
||||||
#logger.debug('loading schedule file '+self.schedule_file)
|
|
||||||
try:
|
|
||||||
schedule_file = open(self.schedule_file, "r")
|
|
||||||
schedule = pickle.load(schedule_file)
|
|
||||||
schedule_file.close()
|
|
||||||
|
|
||||||
except Exception, e:
|
|
||||||
logger.error('%s', e)
|
|
||||||
|
|
||||||
return schedule
|
|
||||||
|
|
||||||
|
|
||||||
def load_schedule_tracker(self):
|
def load_schedule_tracker(self):
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger('push')
|
||||||
|
#logger.debug('load_schedule_tracker')
|
||||||
playedItems = dict()
|
playedItems = dict()
|
||||||
|
|
||||||
# create the file if it doesnt exist
|
# create the file if it doesnt exist
|
||||||
if (not os.path.exists(self.schedule_tracker_file)):
|
if (not os.path.exists(self.schedule_tracker_file)):
|
||||||
logger.debug('creating file ' + self.schedule_tracker_file)
|
try:
|
||||||
schedule_tracker = open(self.schedule_tracker_file, 'w')
|
logger.debug('creating file ' + self.schedule_tracker_file)
|
||||||
pickle.dump(playedItems, schedule_tracker)
|
schedule_tracker = open(self.schedule_tracker_file, 'w')
|
||||||
schedule_tracker.close()
|
pickle.dump(playedItems, schedule_tracker)
|
||||||
|
schedule_tracker.close()
|
||||||
|
except Exception, e:
|
||||||
|
logger.error('Error creating schedule tracker file: %s', e)
|
||||||
else:
|
else:
|
||||||
|
#logger.debug('schedule tracker file exists, opening: ' + self.schedule_tracker_file)
|
||||||
try:
|
try:
|
||||||
schedule_tracker = open(self.schedule_tracker_file, "r")
|
schedule_tracker = open(self.schedule_tracker_file, "r")
|
||||||
playedItems = pickle.load(schedule_tracker)
|
playedItems = pickle.load(schedule_tracker)
|
||||||
|
@ -226,3 +212,18 @@ class PypoPush:
|
||||||
|
|
||||||
return playedItems
|
return playedItems
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
loops = 0
|
||||||
|
heartbeat_period = math.floor(30/PUSH_INTERVAL)
|
||||||
|
logger = logging.getLogger('push')
|
||||||
|
|
||||||
|
while True:
|
||||||
|
if loops % heartbeat_period == 0:
|
||||||
|
logger.info("heartbeat")
|
||||||
|
loops = 0
|
||||||
|
try: self.push('scheduler')
|
||||||
|
except Exception, e:
|
||||||
|
logger.error('Pypo Push Error, exiting: %s', e)
|
||||||
|
sys.exit()
|
||||||
|
time.sleep(PUSH_INTERVAL)
|
||||||
|
loops += 1
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue