Merge branch 'devel' of dev.sourcefabric.org:airtime into devel
This commit is contained in:
commit
322d4ba7dc
|
@ -20,6 +20,9 @@ Highlights:
|
||||||
- Fixed various editing show problems
|
- Fixed various editing show problems
|
||||||
- Fixed airtime-pypo-stop/start causing playback problems
|
- Fixed airtime-pypo-stop/start causing playback problems
|
||||||
- Fixed incorrect information being occasionally shown in the top panel
|
- Fixed incorrect information being occasionally shown in the top panel
|
||||||
|
- Fixed problem with Record Check box occasionally being greyed-out when creating new show
|
||||||
|
- Fixed a problem with default genre not being applied to recorded shows
|
||||||
|
- Fixed a problem where shows repeating bi-weekly or monthly did not update properly when edited.
|
||||||
|
|
||||||
|
|
||||||
1.8.1 - May 2, 2011
|
1.8.1 - May 2, 2011
|
||||||
|
|
2
VERSION
2
VERSION
|
@ -1,2 +1,2 @@
|
||||||
PRODUCT_ID=Airtime
|
PRODUCT_ID=Airtime
|
||||||
PRODUCT_RELEASE=1.8.2
|
PRODUCT_RELEASE=1.9.0
|
||||||
|
|
|
@ -6,7 +6,8 @@ $ccAcl = new Zend_Acl();
|
||||||
|
|
||||||
$ccAcl->addRole(new Zend_Acl_Role('G'))
|
$ccAcl->addRole(new Zend_Acl_Role('G'))
|
||||||
->addRole(new Zend_Acl_Role('H'), 'G')
|
->addRole(new Zend_Acl_Role('H'), 'G')
|
||||||
->addRole(new Zend_Acl_Role('A'), 'H');
|
->addRole(new Zend_Acl_Role('P'), 'H')
|
||||||
|
->addRole(new Zend_Acl_Role('A'), 'P');
|
||||||
|
|
||||||
$ccAcl->add(new Zend_Acl_Resource('library'))
|
$ccAcl->add(new Zend_Acl_Resource('library'))
|
||||||
->add(new Zend_Acl_Resource('index'))
|
->add(new Zend_Acl_Resource('index'))
|
||||||
|
|
|
@ -63,7 +63,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');
|
||||||
$download = $this->_getParam('download');
|
$downlaod = $this->_getParam('download');
|
||||||
|
|
||||||
if(!in_array($api_key, $CC_CONFIG["apiKey"]))
|
if(!in_array($api_key, $CC_CONFIG["apiKey"]))
|
||||||
{
|
{
|
||||||
|
@ -100,15 +100,15 @@ class ApiController extends Zend_Controller_Action
|
||||||
|
|
||||||
// !! binary mode !!
|
// !! binary mode !!
|
||||||
$fp = fopen($filepath, 'rb');
|
$fp = fopen($filepath, 'rb');
|
||||||
|
|
||||||
//We can have multiple levels of output buffering. Need to
|
//We can have multiple levels of output buffering. Need to
|
||||||
//keep looping until all have been disabled!!!
|
//keep looping until all have been disabled!!!
|
||||||
//http://www.php.net/manual/en/function.ob-end-flush.php
|
//http://www.php.net/manual/en/function.ob-end-flush.php
|
||||||
while (@ob_end_flush());
|
while (@ob_end_flush());
|
||||||
|
|
||||||
fpassthru($fp);
|
fpassthru($fp);
|
||||||
fclose($fp);
|
fclose($fp);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -293,52 +293,61 @@ class ApiController extends Zend_Controller_Action
|
||||||
print 'You are not allowed to access this resource.';
|
print 'You are not allowed to access this resource.';
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$showCanceled = false;
|
||||||
|
$show_instance = $this->_getParam('show_instance');
|
||||||
|
|
||||||
$upload_dir = ini_get("upload_tmp_dir");
|
$upload_dir = ini_get("upload_tmp_dir");
|
||||||
$file = StoredFile::uploadFile($upload_dir);
|
$file = StoredFile::uploadFile($upload_dir);
|
||||||
|
|
||||||
$show_instance = $this->_getParam('show_instance');
|
$show_name = "";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$show_inst = new ShowInstance($show_instance);
|
$show_inst = new ShowInstance($show_instance);
|
||||||
|
|
||||||
$show_inst->setRecordedFile($file->getId());
|
$show_inst->setRecordedFile($file->getId());
|
||||||
$show_name = $show_inst->getName();
|
$show_name = $show_inst->getName();
|
||||||
$show_genre = $show_inst->getGenre();
|
$show_genre = $show_inst->getGenre();
|
||||||
$show_start_time = $show_inst->getShowStart();
|
$show_start_time = $show_inst->getShowStart();
|
||||||
|
|
||||||
if(Application_Model_Preference::GetDoSoundCloudUpload())
|
} catch (Exception $e){
|
||||||
{
|
|
||||||
for($i=0; $i<$CC_CONFIG['soundcloud-connection-retries']; $i++) {
|
|
||||||
|
|
||||||
$show = new Show($show_inst->getShowId());
|
|
||||||
$description = $show->getDescription();
|
|
||||||
$hosts = $show->getHosts();
|
|
||||||
|
|
||||||
$tags = array_merge($hosts, array($show_name));
|
|
||||||
|
|
||||||
try {
|
|
||||||
$soundcloud = new ATSoundcloud();
|
|
||||||
$soundcloud_id = $soundcloud->uploadTrack($file->getRealFilePath(), $file->getName(), $description, $tags, $show_start_time, $show_genre);
|
|
||||||
$show_inst->setSoundCloudFileId($soundcloud_id);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
catch (Services_Soundcloud_Invalid_Http_Response_Code_Exception $e) {
|
|
||||||
$code = $e->getHttpCode();
|
|
||||||
if(!in_array($code, array(0, 100))) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sleep($CC_CONFIG['soundcloud-connection-wait']);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception $e){
|
|
||||||
//we've reached here probably because the show was
|
//we've reached here probably because the show was
|
||||||
//cancelled, and therefore the show instance does not
|
//cancelled, and therefore the show instance does not
|
||||||
//exist anymore (ShowInstance constructor threw this error).
|
//exist anymore (ShowInstance constructor threw this error).
|
||||||
//We've done all we can do (upload the file and put it in
|
//We've done all we can do (upload the file and put it in
|
||||||
//the library), now lets just return.
|
//the library), now lets just return.
|
||||||
|
$showCanceled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
$tmpTitle = !(empty($show_name))?$show_name."-":"";
|
||||||
|
$tmpTitle .= $file->getName();
|
||||||
|
|
||||||
|
$file->setMetadataValue(UI_MDATA_KEY_TITLE, $tmpTitle);
|
||||||
|
|
||||||
|
if (!$showCanceled && Application_Model_Preference::GetDoSoundCloudUpload())
|
||||||
|
{
|
||||||
|
for ($i=0; $i<$CC_CONFIG['soundcloud-connection-retries']; $i++) {
|
||||||
|
|
||||||
|
$show = new Show($show_inst->getShowId());
|
||||||
|
$description = $show->getDescription();
|
||||||
|
$hosts = $show->getHosts();
|
||||||
|
|
||||||
|
$tags = array_merge($hosts, array($show_name));
|
||||||
|
|
||||||
|
try {
|
||||||
|
$soundcloud = new ATSoundcloud();
|
||||||
|
$soundcloud_id = $soundcloud->uploadTrack($file->getRealFilePath(), $tmpTitle, $description, $tags, $show_start_time, $show_genre);
|
||||||
|
$show_inst->setSoundCloudFileId($soundcloud_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (Services_Soundcloud_Invalid_Http_Response_Code_Exception $e) {
|
||||||
|
$code = $e->getHttpCode();
|
||||||
|
if(!in_array($code, array(0, 100))) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sleep($CC_CONFIG['soundcloud-connection-wait']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->view->id = $file->getId();
|
$this->view->id = $file->getId();
|
||||||
|
@ -357,8 +366,9 @@ class ApiController extends Zend_Controller_Action
|
||||||
}
|
}
|
||||||
|
|
||||||
$md = $this->_getParam('md');
|
$md = $this->_getParam('md');
|
||||||
|
$filepath = $md['filepath'];
|
||||||
$file = StoredFile::Recall(null, $md['gunid']);
|
$filepath = str_replace("\\", "", $filepath);
|
||||||
|
$file = StoredFile::Recall(null, null, null, $filepath);
|
||||||
if (PEAR::isError($file) || is_null($file)) {
|
if (PEAR::isError($file) || is_null($file)) {
|
||||||
$this->view->response = "File not in Airtime's Database";
|
$this->view->response = "File not in Airtime's Database";
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -59,6 +59,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);
|
||||||
$this->view->isAdmin = $user->isAdmin();
|
$this->view->isAdmin = $user->isAdmin();
|
||||||
|
$this->view->isProgramManager = $user->isUserType('P');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function eventFeedAction()
|
public function eventFeedAction()
|
||||||
|
@ -68,7 +69,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->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER)))
|
||||||
$editable = true;
|
$editable = true;
|
||||||
else
|
else
|
||||||
$editable = false;
|
$editable = false;
|
||||||
|
@ -85,7 +86,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->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
|
||||||
$show = new ShowInstance($showInstanceId);
|
$show = new ShowInstance($showInstanceId);
|
||||||
$error = $show->moveShow($deltaDay, $deltaMin);
|
$error = $show->moveShow($deltaDay, $deltaMin);
|
||||||
}
|
}
|
||||||
|
@ -104,7 +105,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->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
|
||||||
$show = new ShowInstance($showInstanceId);
|
$show = new ShowInstance($showInstanceId);
|
||||||
$error = $show->resizeShow($deltaDay, $deltaMin);
|
$error = $show->resizeShow($deltaDay, $deltaMin);
|
||||||
}
|
}
|
||||||
|
@ -120,7 +121,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->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
|
||||||
$show = new ShowInstance($showInstanceId);
|
$show = new ShowInstance($showInstanceId);
|
||||||
$show->deleteShow();
|
$show->deleteShow();
|
||||||
}
|
}
|
||||||
|
@ -182,10 +183,10 @@ class ScheduleController extends Zend_Controller_Action
|
||||||
$show = new ShowInstance($id);
|
$show = new ShowInstance($id);
|
||||||
|
|
||||||
$params = '/format/json/id/#id#';
|
$params = '/format/json/id/#id#';
|
||||||
|
|
||||||
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->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER, UTYPE_HOST),$show->getShowId()) && !$show->isRecorded() && !$show->isRebroadcast()) {
|
||||||
|
|
||||||
$menu[] = array('action' => array('type' => 'ajax', 'url' => '/Schedule/schedule-show-dialog'.$params,
|
$menu[] = array('action' => array('type' => 'ajax', 'url' => '/Schedule/schedule-show-dialog'.$params,
|
||||||
'callback' => 'window["buildScheduleDialog"]'), 'title' => 'Add / Remove Content');
|
'callback' => 'window["buildScheduleDialog"]'), 'title' => 'Add / Remove Content');
|
||||||
|
@ -203,6 +204,7 @@ class ScheduleController extends Zend_Controller_Action
|
||||||
|
|
||||||
if (strtotime($show->getShowEnd()) <= strtotime($today_timestamp)
|
if (strtotime($show->getShowEnd()) <= strtotime($today_timestamp)
|
||||||
&& is_null($show->getSoundCloudFileId())
|
&& is_null($show->getSoundCloudFileId())
|
||||||
|
&& $show->isRecorded()
|
||||||
&& Application_Model_Preference::GetDoSoundCloudUpload()) {
|
&& Application_Model_Preference::GetDoSoundCloudUpload()) {
|
||||||
$menu[] = array('action' => array('type' => 'fn',
|
$menu[] = array('action' => array('type' => 'fn',
|
||||||
'callback' => "window['uploadToSoundCloud']($id)"),
|
'callback' => "window['uploadToSoundCloud']($id)"),
|
||||||
|
@ -212,7 +214,7 @@ class ScheduleController extends Zend_Controller_Action
|
||||||
|
|
||||||
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()) &&
|
||||||
$user->isAdmin()) {
|
$user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
|
||||||
$menu[] = array('action' => array('type' => 'fn',
|
$menu[] = array('action' => array('type' => 'fn',
|
||||||
'callback' => "window['confirmCancelShow']($id)"),
|
'callback' => "window['confirmCancelShow']($id)"),
|
||||||
'title' => 'Cancel Current Show');
|
'title' => 'Cancel Current Show');
|
||||||
|
@ -220,7 +222,7 @@ class ScheduleController extends Zend_Controller_Action
|
||||||
|
|
||||||
if (strtotime($today_timestamp) < strtotime($show->getShowStart())) {
|
if (strtotime($today_timestamp) < strtotime($show->getShowStart())) {
|
||||||
|
|
||||||
if ($user->isAdmin()) {
|
if ($user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
|
||||||
|
|
||||||
$menu[] = array('action' => array('type' => 'ajax', 'url' => '/Schedule/edit-show/format/json/id/'.$id,
|
$menu[] = array('action' => array('type' => 'ajax', 'url' => '/Schedule/edit-show/format/json/id/'.$id,
|
||||||
'callback' => 'window["beginEditShow"]'), 'title' => 'Edit Show');
|
'callback' => 'window["beginEditShow"]'), 'title' => 'Edit Show');
|
||||||
|
@ -230,7 +232,7 @@ class ScheduleController extends Zend_Controller_Action
|
||||||
'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));
|
||||||
}
|
}
|
||||||
|
@ -249,7 +251,7 @@ class ScheduleController extends Zend_Controller_Action
|
||||||
$user = new User($userInfo->id);
|
$user = new User($userInfo->id);
|
||||||
$show = new ShowInstance($showInstanceId);
|
$show = new ShowInstance($showInstanceId);
|
||||||
|
|
||||||
if($user->isHost($show->getShowId()) || $user->isAdmin()) {
|
if($user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER, UTYPE_HOST),$show->getShowId())) {
|
||||||
$show->scheduleShow(array($plId));
|
$show->scheduleShow(array($plId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,7 +270,7 @@ class ScheduleController extends Zend_Controller_Action
|
||||||
$user = new User($userInfo->id);
|
$user = new User($userInfo->id);
|
||||||
$show = new ShowInstance($showInstanceId);
|
$show = new ShowInstance($showInstanceId);
|
||||||
|
|
||||||
if($user->isHost($show->getShowId()) || $user->isAdmin())
|
if($user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER, UTYPE_HOST),$show->getShowId()))
|
||||||
$show->clearShow();
|
$show->clearShow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,7 +300,7 @@ class ScheduleController extends Zend_Controller_Action
|
||||||
$user = new User($userInfo->id);
|
$user = new User($userInfo->id);
|
||||||
$show = new ShowInstance($showInstanceId);
|
$show = new ShowInstance($showInstanceId);
|
||||||
|
|
||||||
if($user->isHost($show->getShowId()) || $user->isAdmin()) {
|
if($user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER, UTYPE_HOST),$show->getShowId())) {
|
||||||
$show->removeGroupFromShow($group_id);
|
$show->removeGroupFromShow($group_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,7 +378,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->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -596,7 +598,7 @@ class ScheduleController extends Zend_Controller_Action
|
||||||
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->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
|
||||||
Show::create($data);
|
Show::create($data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -634,7 +636,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->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
|
||||||
$showInstanceId = $this->_getParam('id');
|
$showInstanceId = $this->_getParam('id');
|
||||||
|
|
||||||
$showInstance = new ShowInstance($showInstanceId);
|
$showInstance = new ShowInstance($showInstanceId);
|
||||||
|
@ -649,7 +651,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->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) {
|
||||||
$showInstanceId = $this->_getParam('id');
|
$showInstanceId = $this->_getParam('id');
|
||||||
$show = new ShowInstance($showInstanceId);
|
$show = new ShowInstance($showInstanceId);
|
||||||
$show->clearShow();
|
$show->clearShow();
|
||||||
|
|
|
@ -73,7 +73,8 @@ class Application_Form_AddUser extends Zend_Form
|
||||||
$select->setAttrib('style', 'width: 40%');
|
$select->setAttrib('style', 'width: 40%');
|
||||||
$select->setMultiOptions(array(
|
$select->setMultiOptions(array(
|
||||||
"G" => "Guest",
|
"G" => "Guest",
|
||||||
"H" => "Host",
|
"H" => "DJ",
|
||||||
|
"P" => "Program Manager",
|
||||||
"A" => "Admin"
|
"A" => "Admin"
|
||||||
));
|
));
|
||||||
$select->setRequired(true);
|
$select->setRequired(true);
|
||||||
|
|
|
@ -313,6 +313,26 @@ class Show {
|
||||||
$CC_DBC->query($sql);
|
$CC_DBC->query($sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes all future rebroadcast instances of the current
|
||||||
|
* show object from the show_instances table.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function deleteAllRebroadcasts(){
|
||||||
|
global $CC_DBC;
|
||||||
|
|
||||||
|
$date = new DateHelper;
|
||||||
|
$timestamp = $date->getTimestamp();
|
||||||
|
|
||||||
|
$showId = $this->getId();
|
||||||
|
$sql = "DELETE FROM cc_show_instances"
|
||||||
|
." WHERE starts > TIMESTAMP '$timestamp'"
|
||||||
|
." AND show_id = $showId"
|
||||||
|
." AND rebroadcast = 1";
|
||||||
|
|
||||||
|
$CC_DBC->query($sql);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes all show instances of current show after a
|
* Deletes all show instances of current show after a
|
||||||
* certain date.
|
* certain date.
|
||||||
|
@ -556,52 +576,57 @@ class Show {
|
||||||
return CcShowInstancesQuery::create()->findPk($row);
|
return CcShowInstancesQuery::create()->findPk($row);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function deletePossiblyInvalidInstances($p_data, $p_show, $p_endDate, $isRecorded, $repeatType)
|
public function deletePossiblyInvalidInstances($p_data, $p_endDate, $isRecorded, $repeatType)
|
||||||
{
|
{
|
||||||
if (($p_data['add_show_repeats'] != $p_show->isRepeating()) || ($isRecorded && !$p_data['add_show_repeats'])){
|
if ($p_data['add_show_repeats'] != $this->isRepeating()){
|
||||||
//repeat option was toggled.
|
//repeat option was toggled
|
||||||
$p_show->deleteAllInstances();
|
$this->deleteAllInstances();
|
||||||
}
|
|
||||||
if($isRecorded && $p_data['add_show_repeats']) {
|
|
||||||
$p_show->removeAllInstancesFromDate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($p_data['add_show_duration'] != $p_show->getDuration()){
|
if ($p_data['add_show_duration'] != $this->getDuration()){
|
||||||
//duration has changed
|
//duration has changed
|
||||||
$p_show->updateDurationTime($p_data);
|
$this->updateDurationTime($p_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($isRecorded){
|
||||||
|
//delete all rebroadcasts. They will simply be recreated later
|
||||||
|
//in the execution of this PHP script. This simplifies having to
|
||||||
|
//reason about whether we should keep individual rebroadcasts or
|
||||||
|
//delete them or move them around etc.
|
||||||
|
$this->deleteAllRebroadcasts();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($p_data['add_show_repeats']){
|
if ($p_data['add_show_repeats']){
|
||||||
if (($repeatType == 1 || $repeatType == 2) &&
|
if (($repeatType == 1 || $repeatType == 2) &&
|
||||||
$p_data['add_show_start_date'] != $p_show->getStartDate()){
|
$p_data['add_show_start_date'] != $this->getStartDate()){
|
||||||
|
|
||||||
//start date has changed when repeat type is bi-weekly or monthly.
|
//start date has changed when repeat type is bi-weekly or monthly.
|
||||||
//This screws up the repeating positions of show instances, so lets
|
//This screws up the repeating positions of show instances, so lets
|
||||||
//just delete them for now.
|
//just delete them for now. (CC-2351)
|
||||||
|
|
||||||
$p_show->deleteAllInstances();
|
$this->deleteAllInstances();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($p_data['add_show_start_date'] != $p_show->getStartDate()
|
if ($p_data['add_show_start_date'] != $this->getStartDate()
|
||||||
|| $p_data['add_show_start_time'] != $p_show->getStartTime()){
|
|| $p_data['add_show_start_time'] != $this->getStartTime()){
|
||||||
//start date/time has changed
|
//start date/time has changed
|
||||||
|
|
||||||
$newDate = strtotime($p_data['add_show_start_date']);
|
$newDate = strtotime($p_data['add_show_start_date']);
|
||||||
$oldDate = strtotime($p_show->getStartDate());
|
$oldDate = strtotime($this->getStartDate());
|
||||||
if ($newDate > $oldDate){
|
if ($newDate > $oldDate){
|
||||||
$p_show->removeAllInstancesBeforeDate($p_data['add_show_start_date']);
|
$this->removeAllInstancesBeforeDate($p_data['add_show_start_date']);
|
||||||
}
|
}
|
||||||
|
|
||||||
$p_show->updateStartDateTime($p_data, $p_endDate);
|
$this->updateStartDateTime($p_data, $p_endDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($repeatType != $p_show->getRepeatType()){
|
if ($repeatType != $this->getRepeatType()){
|
||||||
//repeat type changed.
|
//repeat type changed.
|
||||||
$p_show->deleteAllInstances();
|
$this->deleteAllInstances();
|
||||||
} else {
|
} else {
|
||||||
//repeat type is the same, check if the days of the week are the same
|
//repeat type is the same, check if the days of the week are the same
|
||||||
$repeatingDaysChanged = false;
|
$repeatingDaysChanged = false;
|
||||||
$showDaysArray = $p_show->getShowDays();
|
$showDaysArray = $this->getShowDays();
|
||||||
if (count($p_data['add_show_day_check']) == count($showDaysArray)){
|
if (count($p_data['add_show_day_check']) == count($showDaysArray)){
|
||||||
//same number of days checked, lets see if they are the same numbers
|
//same number of days checked, lets see if they are the same numbers
|
||||||
$intersect = array_intersect($p_data['add_show_day_check'], $showDaysArray);
|
$intersect = array_intersect($p_data['add_show_day_check'], $showDaysArray);
|
||||||
|
@ -617,28 +642,28 @@ class Show {
|
||||||
$daysRemoved = array_diff($showDaysArray, $p_data['add_show_day_check']);
|
$daysRemoved = array_diff($showDaysArray, $p_data['add_show_day_check']);
|
||||||
|
|
||||||
if (count($daysRemoved) > 0){
|
if (count($daysRemoved) > 0){
|
||||||
$p_show->removeUncheckedDaysInstances($daysRemoved);
|
$this->removeUncheckedDaysInstances($daysRemoved);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Check if end date for the repeat option has changed. If so, need to take care
|
//Check if end date for the repeat option has changed. If so, need to take care
|
||||||
//of deleting possible invalid Show Instances.
|
//of deleting possible invalid Show Instances.
|
||||||
if ((strlen($p_show->getRepeatingEndDate()) == 0) == $p_data['add_show_no_end']){
|
if ((strlen($this->getRepeatingEndDate()) == 0) == $p_data['add_show_no_end']){
|
||||||
//show "Never Ends" option was toggled.
|
//show "Never Ends" option was toggled.
|
||||||
if ($p_data['add_show_no_end']){
|
if ($p_data['add_show_no_end']){
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$p_show->removeAllInstancesFromDate($p_endDate);
|
$this->removeAllInstancesFromDate($p_endDate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($p_show->getRepeatingEndDate() != $p_data['add_show_end_date']){
|
if ($this->getRepeatingEndDate() != $p_data['add_show_end_date']){
|
||||||
//end date was changed.
|
//end date was changed.
|
||||||
|
|
||||||
$newDate = strtotime($p_data['add_show_end_date']);
|
$newDate = strtotime($p_data['add_show_end_date']);
|
||||||
$oldDate = strtotime($p_show->getRepeatingEndDate());
|
$oldDate = strtotime($this->getRepeatingEndDate());
|
||||||
if ($newDate < $oldDate){
|
if ($newDate < $oldDate){
|
||||||
$p_show->removeAllInstancesFromDate($p_endDate);
|
$this->removeAllInstancesFromDate($p_endDate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -704,7 +729,7 @@ class Show {
|
||||||
$isRecorded = ($data['add_show_record']) ? 1 : 0;
|
$isRecorded = ($data['add_show_record']) ? 1 : 0;
|
||||||
|
|
||||||
if ($data['add_show_id'] != -1){
|
if ($data['add_show_id'] != -1){
|
||||||
Show::deletePossiblyInvalidInstances($data, $show, $endDate, $isRecorded, $repeatType);
|
$show->deletePossiblyInvalidInstances($data, $endDate, $isRecorded, $repeatType);
|
||||||
}
|
}
|
||||||
|
|
||||||
//check if we are adding or updating a show, and if updating
|
//check if we are adding or updating a show, and if updating
|
||||||
|
@ -908,7 +933,7 @@ class Show {
|
||||||
$ccShowInstance = new CcShowInstances();
|
$ccShowInstance = new CcShowInstances();
|
||||||
$newInstance = true;
|
$newInstance = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($newInstance || $ccShowInstance->getDbStarts() > $currentTimestamp){
|
if ($newInstance || $ccShowInstance->getDbStarts() > $currentTimestamp){
|
||||||
$ccShowInstance->setDbShowId($show_id);
|
$ccShowInstance->setDbShowId($show_id);
|
||||||
$ccShowInstance->setDbStarts($start);
|
$ccShowInstance->setDbStarts($start);
|
||||||
|
@ -986,10 +1011,10 @@ class Show {
|
||||||
$ccShowInstance = new CcShowInstances();
|
$ccShowInstance = new CcShowInstances();
|
||||||
$newInstance = true;
|
$newInstance = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When editing the start/end time of a repeating show, we don't want to
|
/* When editing the start/end time of a repeating show, we don't want to
|
||||||
* change shows that started in the past. So check the start time.
|
* change shows that started in the past. So check the start time.
|
||||||
*/
|
*/
|
||||||
if ($newInstance || $ccShowInstance->getDbStarts() > $currentTimestamp){
|
if ($newInstance || $ccShowInstance->getDbStarts() > $currentTimestamp){
|
||||||
$ccShowInstance->setDbShowId($show_id);
|
$ccShowInstance->setDbShowId($show_id);
|
||||||
$ccShowInstance->setDbStarts($start);
|
$ccShowInstance->setDbStarts($start);
|
||||||
|
@ -1130,7 +1155,6 @@ class Show {
|
||||||
public static function getFullCalendarEvents($start, $end, $editable=false)
|
public static function getFullCalendarEvents($start, $end, $editable=false)
|
||||||
{
|
{
|
||||||
$events = array();
|
$events = array();
|
||||||
$options = array();
|
|
||||||
|
|
||||||
$start_range = new DateTime($start);
|
$start_range = new DateTime($start);
|
||||||
$end_range = new DateTime($end);
|
$end_range = new DateTime($end);
|
||||||
|
@ -1141,13 +1165,15 @@ class Show {
|
||||||
|
|
||||||
$today_timestamp = date("Y-m-d H:i:s");
|
$today_timestamp = date("Y-m-d H:i:s");
|
||||||
foreach ($shows as $show) {
|
foreach ($shows as $show) {
|
||||||
|
$options = array();
|
||||||
|
|
||||||
//only bother calculating percent for week or day view.
|
//only bother calculating percent for week or day view.
|
||||||
if(intval($days) <= 7) {
|
if(intval($days) <= 7) {
|
||||||
$show_instance = new ShowInstance($show["instance_id"]);
|
$show_instance = new ShowInstance($show["instance_id"]);
|
||||||
$options["percent"] = $show_instance->getPercentScheduled();
|
$options["percent"] = $show_instance->getPercentScheduled();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($editable && strtotime($today_timestamp) < strtotime($show["starts"])) {
|
if ($editable && (strtotime($today_timestamp) < strtotime($show["starts"]))) {
|
||||||
$options["editable"] = true;
|
$options["editable"] = true;
|
||||||
$events[] = Show::makeFullCalendarEvent($show, $options);
|
$events[] = Show::makeFullCalendarEvent($show, $options);
|
||||||
}
|
}
|
||||||
|
@ -1357,16 +1383,20 @@ class ShowInstance {
|
||||||
|
|
||||||
$mins = abs($deltaMin%60);
|
$mins = abs($deltaMin%60);
|
||||||
|
|
||||||
|
$today_timestamp = date("Y-m-d H:i:s");
|
||||||
$starts = $this->getShowStart();
|
$starts = $this->getShowStart();
|
||||||
$ends = $this->getShowEnd();
|
$ends = $this->getShowEnd();
|
||||||
|
|
||||||
|
if(strtotime($today_timestamp) > strtotime($starts)) {
|
||||||
|
return "can't move a past show";
|
||||||
|
}
|
||||||
|
|
||||||
$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);
|
||||||
|
|
||||||
$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);
|
||||||
|
|
||||||
$today_timestamp = date("Y-m-d H:i:s");
|
|
||||||
if(strtotime($today_timestamp) > strtotime($new_starts)) {
|
if(strtotime($today_timestamp) > strtotime($new_starts)) {
|
||||||
return "can't move show into past";
|
return "can't move show into past";
|
||||||
}
|
}
|
||||||
|
@ -1405,9 +1435,14 @@ class ShowInstance {
|
||||||
|
|
||||||
$mins = abs($deltaMin%60);
|
$mins = abs($deltaMin%60);
|
||||||
|
|
||||||
|
$today_timestamp = date("Y-m-d H:i:s");
|
||||||
$starts = $this->getShowStart();
|
$starts = $this->getShowStart();
|
||||||
$ends = $this->getShowEnd();
|
$ends = $this->getShowEnd();
|
||||||
|
|
||||||
|
if(strtotime($today_timestamp) > strtotime($starts)) {
|
||||||
|
return "can't resize a past show";
|
||||||
|
}
|
||||||
|
|
||||||
$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);
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ class ATSoundcloud {
|
||||||
return $token;
|
return $token;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function uploadTrack($filepath, $filename, $description, $tags=array(), $release=null, $genre=null)
|
public function uploadTrack($filepath, $filename, $description, $tags=array(), $release=null, $genre=null)
|
||||||
{
|
{
|
||||||
if($this->getToken())
|
if($this->getToken())
|
||||||
{
|
{
|
||||||
|
@ -47,7 +47,7 @@ class ATSoundcloud {
|
||||||
'track[tag_list]' => $tags,
|
'track[tag_list]' => $tags,
|
||||||
'track[description]' => $description,
|
'track[description]' => $description,
|
||||||
'track[downloadable]' => true,
|
'track[downloadable]' => true,
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if(isset($release)) {
|
if(isset($release)) {
|
||||||
|
@ -61,13 +61,13 @@ class ATSoundcloud {
|
||||||
$track_data['track[release_month]'] = $release[1];
|
$track_data['track[release_month]'] = $release[1];
|
||||||
$track_data['track[release_day]'] = $release[2];
|
$track_data['track[release_day]'] = $release[2];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($genre) && $genre != "") {
|
if (isset($genre) && $genre != "") {
|
||||||
$track_data['track[genre]'] = $genre;
|
$track_data['track[genre]'] = $genre;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$default_genre = Application_Model_Preference::GetSoundCloudTrackType();
|
$default_genre = Application_Model_Preference::GetSoundCloudGenre();
|
||||||
if ($genre != "") {
|
if ($default_genre != "") {
|
||||||
$track_data['track[genre]'] = $default_genre;
|
$track_data['track[genre]'] = $default_genre;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ class ATSoundcloud {
|
||||||
);
|
);
|
||||||
|
|
||||||
return $response["id"];
|
return $response["id"];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -703,7 +703,7 @@ class StoredFile {
|
||||||
* @return StoredFile|Playlist|NULL
|
* @return StoredFile|Playlist|NULL
|
||||||
* Return NULL if the object doesnt exist in the DB.
|
* Return NULL if the object doesnt exist in the DB.
|
||||||
*/
|
*/
|
||||||
public static function Recall($p_id=null, $p_gunid=null, $p_md5sum=null)
|
public static function Recall($p_id=null, $p_gunid=null, $p_md5sum=null, $p_filepath=null)
|
||||||
{
|
{
|
||||||
global $CC_DBC;
|
global $CC_DBC;
|
||||||
global $CC_CONFIG;
|
global $CC_CONFIG;
|
||||||
|
@ -713,6 +713,8 @@ class StoredFile {
|
||||||
$cond = "gunid='$p_gunid'";
|
$cond = "gunid='$p_gunid'";
|
||||||
} elseif (!is_null($p_md5sum)) {
|
} elseif (!is_null($p_md5sum)) {
|
||||||
$cond = "md5='$p_md5sum'";
|
$cond = "md5='$p_md5sum'";
|
||||||
|
} elseif (!is_null($p_filepath)) {
|
||||||
|
$cond = "filepath='$p_filepath'";
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -782,6 +784,31 @@ class StoredFile {
|
||||||
return $rows;
|
return $rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function ensureDir($dir)
|
||||||
|
{
|
||||||
|
if (!is_dir($dir)) {
|
||||||
|
mkdir($dir, 02775);
|
||||||
|
chmod($dir, 02775);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function createUniqueFilename($base, $ext)
|
||||||
|
{
|
||||||
|
if(file_exists("$base.$ext")) {
|
||||||
|
$i = 1;
|
||||||
|
while(true) {
|
||||||
|
if(file_exists("$base($i).$ext")) {
|
||||||
|
$i = $i+1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "$base($i).$ext";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "$base.$ext";
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate the location to store the file.
|
* Generate the location to store the file.
|
||||||
* It creates the subdirectory if needed.
|
* It creates the subdirectory if needed.
|
||||||
|
@ -789,14 +816,48 @@ class StoredFile {
|
||||||
private function generateFilePath()
|
private function generateFilePath()
|
||||||
{
|
{
|
||||||
global $CC_CONFIG, $CC_DBC;
|
global $CC_CONFIG, $CC_DBC;
|
||||||
$resDir = $CC_CONFIG['storageDir']."/".substr($this->gunid, 0, 3);
|
|
||||||
if (!is_dir($resDir)) {
|
$storageDir = $CC_CONFIG['storageDir'];
|
||||||
mkdir($resDir, 02775);
|
|
||||||
chmod($resDir, 02775);
|
|
||||||
}
|
|
||||||
$info = pathinfo($this->name);
|
$info = pathinfo($this->name);
|
||||||
|
$origName = $info['filename'];
|
||||||
$fileExt = strtolower($info["extension"]);
|
$fileExt = strtolower($info["extension"]);
|
||||||
return "{$resDir}/{$this->gunid}.{$fileExt}";
|
|
||||||
|
$this->loadMetadata();
|
||||||
|
|
||||||
|
$artist = $this->md["dc:creator"];
|
||||||
|
$album = $this->md["dc:source"];
|
||||||
|
$title = $this->md["dc:title"];
|
||||||
|
$track_num = $this->md["ls:track_num"];
|
||||||
|
|
||||||
|
if(isset($artist) && $artist != "") {
|
||||||
|
$base = "$storageDir/$artist";
|
||||||
|
$this->ensureDir($base);
|
||||||
|
|
||||||
|
if(isset($album) && $album != "") {
|
||||||
|
$base = "$base/$album";
|
||||||
|
$this->ensureDir($base);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isset($title) && $title != "") {
|
||||||
|
if(isset($track_num) && $track_num != "") {
|
||||||
|
if($track_num < 10 && strlen($track_num) == 1) {
|
||||||
|
$track_num = "0$track_num";
|
||||||
|
}
|
||||||
|
$base = "$base/$track_num - $title";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$base = "$base/$title";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$base = "$base/$origName";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$base = "$storageDir/$origName";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->createUniqueFilename($base, $fileExt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1693,8 +1754,8 @@ 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) {
|
public static function uploadFile($p_targetDir)
|
||||||
|
{
|
||||||
// HTTP headers for no cache etc
|
// HTTP headers for no cache etc
|
||||||
header('Content-type: text/plain; charset=UTF-8');
|
header('Content-type: text/plain; charset=UTF-8');
|
||||||
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
|
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
|
||||||
|
@ -1704,7 +1765,7 @@ class StoredFile {
|
||||||
header("Pragma: no-cache");
|
header("Pragma: no-cache");
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
//$targetDir = ini_get("upload_tmp_dir"); //. DIRECTORY_SEPARATOR . "plupload";
|
//$p_targetDir = ini_get("upload_tmp_dir"); //. DIRECTORY_SEPARATOR . "plupload";
|
||||||
$cleanupTargetDir = false; // Remove old files
|
$cleanupTargetDir = false; // Remove old files
|
||||||
$maxFileAge = 60 * 60; // Temp file age in seconds
|
$maxFileAge = 60 * 60; // Temp file age in seconds
|
||||||
|
|
||||||
|
@ -1721,13 +1782,13 @@ class StoredFile {
|
||||||
//$fileName = preg_replace('/[^\w\._]+/', '', $fileName);
|
//$fileName = preg_replace('/[^\w\._]+/', '', $fileName);
|
||||||
|
|
||||||
// Create target dir
|
// Create target dir
|
||||||
if (!file_exists($targetDir))
|
if (!file_exists($p_targetDir))
|
||||||
@mkdir($targetDir);
|
@mkdir($p_targetDir);
|
||||||
|
|
||||||
// Remove old temp files
|
// Remove old temp files
|
||||||
if (is_dir($targetDir) && ($dir = opendir($targetDir))) {
|
if (is_dir($p_targetDir) && ($dir = opendir($p_targetDir))) {
|
||||||
while (($file = readdir($dir)) !== false) {
|
while (($file = readdir($dir)) !== false) {
|
||||||
$filePath = $targetDir . DIRECTORY_SEPARATOR . $file;
|
$filePath = $p_targetDir . DIRECTORY_SEPARATOR . $file;
|
||||||
|
|
||||||
// Remove temp files if they are older than the max age
|
// Remove temp files if they are older than the max age
|
||||||
if (preg_match('/\.tmp$/', $file) && (filemtime($filePath) < time() - $maxFileAge))
|
if (preg_match('/\.tmp$/', $file) && (filemtime($filePath) < time() - $maxFileAge))
|
||||||
|
@ -1748,7 +1809,7 @@ class StoredFile {
|
||||||
if (strpos($contentType, "multipart") !== false) {
|
if (strpos($contentType, "multipart") !== false) {
|
||||||
if (isset($_FILES['file']['tmp_name']) && is_uploaded_file($_FILES['file']['tmp_name'])) {
|
if (isset($_FILES['file']['tmp_name']) && is_uploaded_file($_FILES['file']['tmp_name'])) {
|
||||||
// Open temp file
|
// Open temp file
|
||||||
$out = fopen($targetDir . DIRECTORY_SEPARATOR . $fileName, $chunk == 0 ? "wb" : "ab");
|
$out = fopen($p_targetDir . DIRECTORY_SEPARATOR . $fileName, $chunk == 0 ? "wb" : "ab");
|
||||||
if ($out) {
|
if ($out) {
|
||||||
// Read binary input stream and append it to temp file
|
// Read binary input stream and append it to temp file
|
||||||
$in = fopen($_FILES['file']['tmp_name'], "rb");
|
$in = fopen($_FILES['file']['tmp_name'], "rb");
|
||||||
|
@ -1767,7 +1828,7 @@ class StoredFile {
|
||||||
die('{"jsonrpc" : "2.0", "error" : {"code": 103, "message": "Failed to move uploaded file."}, "id" : "id"}');
|
die('{"jsonrpc" : "2.0", "error" : {"code": 103, "message": "Failed to move uploaded file."}, "id" : "id"}');
|
||||||
} else {
|
} else {
|
||||||
// Open temp file
|
// Open temp file
|
||||||
$out = fopen($targetDir . DIRECTORY_SEPARATOR . $fileName, $chunk == 0 ? "wb" : "ab");
|
$out = fopen($p_targetDir . DIRECTORY_SEPARATOR . $fileName, $chunk == 0 ? "wb" : "ab");
|
||||||
if ($out) {
|
if ($out) {
|
||||||
// Read binary input stream and append it to temp file
|
// Read binary input stream and append it to temp file
|
||||||
$in = fopen("php://input", "rb");
|
$in = fopen("php://input", "rb");
|
||||||
|
@ -1783,7 +1844,7 @@ class StoredFile {
|
||||||
die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to open output stream."}, "id" : "id"}');
|
die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to open output stream."}, "id" : "id"}');
|
||||||
}
|
}
|
||||||
|
|
||||||
$audio_file = $targetDir . DIRECTORY_SEPARATOR . $fileName;
|
$audio_file = $p_targetDir . DIRECTORY_SEPARATOR . $fileName;
|
||||||
|
|
||||||
$md5 = md5_file($audio_file);
|
$md5 = md5_file($audio_file);
|
||||||
$duplicate = StoredFile::RecallByMd5($md5);
|
$duplicate = StoredFile::RecallByMd5($md5);
|
||||||
|
@ -1812,18 +1873,14 @@ class StoredFile {
|
||||||
die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": ' + $metadata->getMessage() + '}}');
|
die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": ' + $metadata->getMessage() + '}}');
|
||||||
}
|
}
|
||||||
|
|
||||||
// #2196 no id tag -> use the original filename
|
// no id3 title tag -> use the original filename for title
|
||||||
if (basename($audio_file) == $metadata[UI_MDATA_KEY_TITLE]) {
|
if (empty($metadata[UI_MDATA_KEY_TITLE])) {
|
||||||
$metadata[UI_MDATA_KEY_TITLE] = basename($audio_file);
|
$metadata[UI_MDATA_KEY_TITLE] = basename($audio_file);
|
||||||
$metadata[UI_MDATA_KEY_FILENAME] = 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(
|
$values = array(
|
||||||
"filename" => basename($audio_file),
|
"filename" => basename($audio_file),
|
||||||
"filepath" => $audio_file,
|
"filepath" => $audio_file,
|
||||||
"filetype" => "audioclip",
|
"filetype" => "audioclip",
|
||||||
"mime" => $metadata[UI_MDATA_KEY_FORMAT],
|
"mime" => $metadata[UI_MDATA_KEY_FORMAT],
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
define('UTYPE_HOST', 'H');
|
||||||
|
define('UTYPE_ADMIN', 'A');
|
||||||
|
define('UTYPE_GUEST', 'G');
|
||||||
|
define('UTYPE_PROGRAM_MANAGER', 'P');
|
||||||
|
|
||||||
class User {
|
class User {
|
||||||
|
|
||||||
private $_userInstance;
|
private $_userInstance;
|
||||||
|
@ -18,12 +23,44 @@ class User {
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isHost($showId) {
|
public function isHost($showId) {
|
||||||
$userId = $this->_userInstance->getDbId();
|
return $this->isUserType(UTYPE_HOST, $showId);
|
||||||
return CcShowHostsQuery::create()->filterByDbShow($showId)->filterByDbHost($userId)->count() > 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isAdmin() {
|
public function isAdmin() {
|
||||||
return $this->_userInstance->getDbType() === 'A';
|
return $this->isUserType(UTYPE_ADMIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isUserType($type, $showId=''){
|
||||||
|
if(is_array($type)){
|
||||||
|
$result = false;
|
||||||
|
foreach($type as $t){
|
||||||
|
switch($t){
|
||||||
|
case UTYPE_ADMIN:
|
||||||
|
$result = $this->_userInstance->getDbType() === 'A';
|
||||||
|
break;
|
||||||
|
case UTYPE_HOST:
|
||||||
|
$userId = $this->_userInstance->getDbId();
|
||||||
|
$result = CcShowHostsQuery::create()->filterByDbShow($showId)->filterByDbHost($userId)->count() > 0;
|
||||||
|
break;
|
||||||
|
case UTYPE_PROGRAM_MANAGER:
|
||||||
|
$result = $this->_userInstance->getDbType() === 'P';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if($result){
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
switch($type){
|
||||||
|
case UTYPE_ADMIN:
|
||||||
|
return $this->_userInstance->getDbType() === 'A';
|
||||||
|
case UTYPE_HOST:
|
||||||
|
$userId = $this->_userInstance->getDbId();
|
||||||
|
return CcShowHostsQuery::create()->filterByDbShow($showId)->filterByDbHost($userId)->count() > 0;
|
||||||
|
case UTYPE_PROGRAM_MANAGER:
|
||||||
|
return $this->_userInstance->getDbType() === 'P';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setLogin($login){
|
public function setLogin($login){
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<?php if($this->isAdmin) : ?>
|
<?php if($this->isAdmin || $this->isProgramManager) : ?>
|
||||||
<form id="add-show-form" method="post" action="" style="display:none;">
|
<form id="add-show-form" method="post" action="" style="display:none;">
|
||||||
<?php echo $this->render('schedule/add-show-form.phtml') ?>
|
<?php echo $this->render('schedule/add-show-form.phtml') ?>
|
||||||
</form>
|
</form>
|
||||||
|
|
|
@ -51,6 +51,9 @@ function rowCallback( nRow, aData, iDisplayIndex ){
|
||||||
} else if ( aData[4] == "G" )
|
} else if ( aData[4] == "G" )
|
||||||
{
|
{
|
||||||
$('td:eq(3)', nRow).html( 'Guest' );
|
$('td:eq(3)', nRow).html( 'Guest' );
|
||||||
|
} else if ( aData[4] == "P" )
|
||||||
|
{
|
||||||
|
$('td:eq(3)', nRow).html( 'Program Manager' );
|
||||||
}
|
}
|
||||||
|
|
||||||
return nRow;
|
return nRow;
|
||||||
|
|
|
@ -12,12 +12,12 @@ php ${SCRIPTPATH}/airtime-uninstall.php
|
||||||
echo -e "\n*** Uninstalling Pypo ***"
|
echo -e "\n*** Uninstalling Pypo ***"
|
||||||
python ${SCRIPTPATH}/../python_apps/pypo/install/pypo-uninstall.py
|
python ${SCRIPTPATH}/../python_apps/pypo/install/pypo-uninstall.py
|
||||||
|
|
||||||
#echo -e "\n*** Uninstalling Media Monitor ***"
|
|
||||||
#python ${SCRIPTPATH}/../python_apps/pytag-fs/install/media-monitor-uninstall.py
|
|
||||||
|
|
||||||
echo -e "\n*** Uninstalling Show Recorder ***"
|
echo -e "\n*** Uninstalling Show Recorder ***"
|
||||||
python ${SCRIPTPATH}/../python_apps/show-recorder/install/recorder-uninstall.py
|
python ${SCRIPTPATH}/../python_apps/show-recorder/install/recorder-uninstall.py
|
||||||
|
|
||||||
|
echo -e "\n*** Uninstalling Media Monitor ***"
|
||||||
|
python ${SCRIPTPATH}/../python_apps/media-monitor/install/media-monitor-uninstall.py
|
||||||
|
|
||||||
echo -e "\n*** Removing Pypo User ***"
|
echo -e "\n*** Removing Pypo User ***"
|
||||||
python ${SCRIPTPATH}/../python_apps/remove-pypo-user.py
|
python ${SCRIPTPATH}/../python_apps/remove-pypo-user.py
|
||||||
|
|
||||||
|
|
|
@ -96,7 +96,8 @@ passthru("python ".__DIR__."/../python_apps/pypo/install/pypo-install.py");
|
||||||
echo PHP_EOL."*** Updating Recorder ***".PHP_EOL;
|
echo PHP_EOL."*** Updating Recorder ***".PHP_EOL;
|
||||||
passthru("python ".__DIR__."/../python_apps/show-recorder/install/recorder-install.py");
|
passthru("python ".__DIR__."/../python_apps/show-recorder/install/recorder-install.py");
|
||||||
|
|
||||||
|
echo PHP_EOL."*** Starting Media Monitor ***".PHP_EOL;
|
||||||
|
passthru("python ".__DIR__."/../python_apps/media-monitor/install/media-monitor-install.py");
|
||||||
|
|
||||||
|
|
||||||
echo "******************************* Update Complete *******************************".PHP_EOL;
|
echo "******************************* Update Complete *******************************".PHP_EOL;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,8 @@ class AirtimeIni
|
||||||
$configFiles = array(AirtimeIni::CONF_FILE_AIRTIME,
|
$configFiles = array(AirtimeIni::CONF_FILE_AIRTIME,
|
||||||
AirtimeIni::CONF_FILE_PYPO,
|
AirtimeIni::CONF_FILE_PYPO,
|
||||||
AirtimeIni::CONF_FILE_RECORDER,
|
AirtimeIni::CONF_FILE_RECORDER,
|
||||||
AirtimeIni::CONF_FILE_LIQUIDSOAP);
|
AirtimeIni::CONF_FILE_LIQUIDSOAP,
|
||||||
|
AirtimeIni::CONF_FILE_MEDIAMONITOR);
|
||||||
$exist = false;
|
$exist = false;
|
||||||
foreach ($configFiles as $conf) {
|
foreach ($configFiles as $conf) {
|
||||||
if (file_exists($conf)) {
|
if (file_exists($conf)) {
|
||||||
|
@ -102,9 +103,9 @@ class AirtimeIni
|
||||||
}
|
}
|
||||||
|
|
||||||
//wait until Airtime 1.9.0
|
//wait until Airtime 1.9.0
|
||||||
//if (file_exists(AirtimeIni::CONF_FILE_MEDIAMONITOR)){
|
if (file_exists(AirtimeIni::CONF_FILE_MEDIAMONITOR)){
|
||||||
// unlink(AirtimeIni::CONF_FILE_MEDIAMONITOR);
|
unlink(AirtimeIni::CONF_FILE_MEDIAMONITOR);
|
||||||
//}
|
}
|
||||||
|
|
||||||
if (file_exists("etc/airtime")){
|
if (file_exists("etc/airtime")){
|
||||||
rmdir("/etc/airtime/");
|
rmdir("/etc/airtime/");
|
||||||
|
@ -156,9 +157,9 @@ class AirtimeIni
|
||||||
$n=count($lines);
|
$n=count($lines);
|
||||||
foreach ($lines as &$line) {
|
foreach ($lines as &$line) {
|
||||||
if ($line[0] != "#"){
|
if ($line[0] != "#"){
|
||||||
$key_value = split("=", $line);
|
$key_value = explode("=", $line);
|
||||||
$key = trim($key_value[0]);
|
$key = trim($key_value[0]);
|
||||||
|
|
||||||
if ($key == $p_property){
|
if ($key == $p_property){
|
||||||
$line = "$p_property = $p_value".PHP_EOL;
|
$line = "$p_property = $p_value".PHP_EOL;
|
||||||
}
|
}
|
||||||
|
@ -185,7 +186,7 @@ class AirtimeIni
|
||||||
AirtimeIni::UpdateIniValue(AirtimeIni::CONF_FILE_AIRTIME, 'airtime_dir', AirtimeInstall::CONF_DIR_WWW);
|
AirtimeIni::UpdateIniValue(AirtimeIni::CONF_FILE_AIRTIME, 'airtime_dir', AirtimeInstall::CONF_DIR_WWW);
|
||||||
AirtimeIni::UpdateIniValue(AirtimeIni::CONF_FILE_PYPO, 'api_key', "'$api_key'");
|
AirtimeIni::UpdateIniValue(AirtimeIni::CONF_FILE_PYPO, 'api_key', "'$api_key'");
|
||||||
AirtimeIni::UpdateIniValue(AirtimeIni::CONF_FILE_RECORDER, 'api_key', "'$api_key'");
|
AirtimeIni::UpdateIniValue(AirtimeIni::CONF_FILE_RECORDER, 'api_key', "'$api_key'");
|
||||||
//AirtimeIni::UpdateIniValue(AirtimeIni::CONF_FILE_MEDIAMONITOR, 'api_key', "'$api_key'");
|
AirtimeIni::UpdateIniValue(AirtimeIni::CONF_FILE_MEDIAMONITOR, 'api_key', "'$api_key'");
|
||||||
AirtimeIni::UpdateIniValue(AirtimeInstall::CONF_DIR_WWW.'/build/build.properties', 'project.home', AirtimeInstall::CONF_DIR_WWW);
|
AirtimeIni::UpdateIniValue(AirtimeInstall::CONF_DIR_WWW.'/build/build.properties', 'project.home', AirtimeInstall::CONF_DIR_WWW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,6 @@ function UninstallBinaries()
|
||||||
|
|
||||||
exec("/usr/bin/airtime-pypo-stop");
|
exec("/usr/bin/airtime-pypo-stop");
|
||||||
exec("/usr/bin/airtime-show-recorder-stop");
|
exec("/usr/bin/airtime-show-recorder-stop");
|
||||||
exec("/usr/bin/airtime-media-monitor-stop");
|
|
||||||
|
|
||||||
exec("svc -d /etc/service/pypo");
|
exec("svc -d /etc/service/pypo");
|
||||||
exec("svc -d /etc/service/pypo/log");
|
exec("svc -d /etc/service/pypo/log");
|
||||||
|
@ -69,6 +68,7 @@ $pathnames = array("/usr/bin/airtime-pypo-start",
|
||||||
"/etc/service/media-monitor",
|
"/etc/service/media-monitor",
|
||||||
"/etc/service/recorder",
|
"/etc/service/recorder",
|
||||||
"/var/log/airtime/pypo/main",
|
"/var/log/airtime/pypo/main",
|
||||||
|
"/var/log/airtime/pypo-liquidsoap/main",
|
||||||
"/var/log/airtime/show-recorder/main"
|
"/var/log/airtime/show-recorder/main"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import os
|
||||||
import sys
|
import sys
|
||||||
import hashlib
|
import hashlib
|
||||||
import json
|
import json
|
||||||
|
import shutil
|
||||||
|
|
||||||
from subprocess import Popen, PIPE, STDOUT
|
from subprocess import Popen, PIPE, STDOUT
|
||||||
|
|
||||||
|
@ -22,6 +23,9 @@ from kombu.connection import BrokerConnection
|
||||||
from kombu.messaging import Exchange, Queue, Consumer, Producer
|
from kombu.messaging import Exchange, Queue, Consumer, Producer
|
||||||
from api_clients import api_client
|
from api_clients import api_client
|
||||||
|
|
||||||
|
global storage_directory
|
||||||
|
storage_directory = "/srv/airtime/stor"
|
||||||
|
|
||||||
# configure logging
|
# configure logging
|
||||||
try:
|
try:
|
||||||
logging.config.fileConfig("logging.cfg")
|
logging.config.fileConfig("logging.cfg")
|
||||||
|
@ -42,6 +46,7 @@ list of supported easy tags in mutagen version 1.20
|
||||||
['albumartistsort', 'musicbrainz_albumstatus', 'lyricist', 'releasecountry', 'date', 'performer', 'musicbrainz_albumartistid', 'composer', 'encodedby', 'tracknumber', 'musicbrainz_albumid', 'album', 'asin', 'musicbrainz_artistid', 'mood', 'copyright', 'author', 'media', 'length', 'version', 'artistsort', 'titlesort', 'discsubtitle', 'website', 'musicip_fingerprint', 'conductor', 'compilation', 'barcode', 'performer:*', 'composersort', 'musicbrainz_discid', 'musicbrainz_albumtype', 'genre', 'isrc', 'discnumber', 'musicbrainz_trmid', 'replaygain_*_gain', 'musicip_puid', 'artist', 'title', 'bpm', 'musicbrainz_trackid', 'arranger', 'albumsort', 'replaygain_*_peak', 'organization']
|
['albumartistsort', 'musicbrainz_albumstatus', 'lyricist', 'releasecountry', 'date', 'performer', 'musicbrainz_albumartistid', 'composer', 'encodedby', 'tracknumber', 'musicbrainz_albumid', 'album', 'asin', 'musicbrainz_artistid', 'mood', 'copyright', 'author', 'media', 'length', 'version', 'artistsort', 'titlesort', 'discsubtitle', 'website', 'musicip_fingerprint', 'conductor', 'compilation', 'barcode', 'performer:*', 'composersort', 'musicbrainz_discid', 'musicbrainz_albumtype', 'genre', 'isrc', 'discnumber', 'musicbrainz_trmid', 'replaygain_*_gain', 'musicip_puid', 'artist', 'title', 'bpm', 'musicbrainz_trackid', 'arranger', 'albumsort', 'replaygain_*_peak', 'organization']
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
def checkRabbitMQ(notifier):
|
def checkRabbitMQ(notifier):
|
||||||
try:
|
try:
|
||||||
notifier.connection.drain_events(timeout=int(config["check_airtime_events"]))
|
notifier.connection.drain_events(timeout=int(config["check_airtime_events"]))
|
||||||
|
@ -71,7 +76,7 @@ class AirtimeNotifier(Notifier):
|
||||||
"isrc_number": "isrc",\
|
"isrc_number": "isrc",\
|
||||||
"copyright": "copyright",\
|
"copyright": "copyright",\
|
||||||
}
|
}
|
||||||
|
|
||||||
schedule_exchange = Exchange("airtime-media-monitor", "direct", durable=True, auto_delete=True)
|
schedule_exchange = Exchange("airtime-media-monitor", "direct", durable=True, auto_delete=True)
|
||||||
schedule_queue = Queue("media-monitor", exchange=schedule_exchange, key="filesystem")
|
schedule_queue = Queue("media-monitor", exchange=schedule_exchange, key="filesystem")
|
||||||
self.connection = BrokerConnection(config["rabbitmq_host"], config["rabbitmq_user"], config["rabbitmq_password"], "/")
|
self.connection = BrokerConnection(config["rabbitmq_host"], config["rabbitmq_user"], config["rabbitmq_password"], "/")
|
||||||
|
@ -87,7 +92,7 @@ class AirtimeNotifier(Notifier):
|
||||||
logger = logging.getLogger('root')
|
logger = logging.getLogger('root')
|
||||||
logger.info("Received md from RabbitMQ: " + body)
|
logger.info("Received md from RabbitMQ: " + body)
|
||||||
|
|
||||||
m = json.loads(message.body)
|
m = json.loads(message.body)
|
||||||
airtime_file = mutagen.File(m['filepath'], easy=True)
|
airtime_file = mutagen.File(m['filepath'], easy=True)
|
||||||
del m['filepath']
|
del m['filepath']
|
||||||
for key in m.keys() :
|
for key in m.keys() :
|
||||||
|
@ -124,21 +129,89 @@ class MediaMonitor(ProcessEvent):
|
||||||
"copyright": "copyright",\
|
"copyright": "copyright",\
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.supported_file_formats = ['mp3', 'ogg']
|
||||||
self.logger = logging.getLogger('root')
|
self.logger = logging.getLogger('root')
|
||||||
|
|
||||||
self.temp_files = {}
|
self.temp_files = {}
|
||||||
|
self.imported_renamed_files = {}
|
||||||
|
|
||||||
|
def get_md5(self, filepath):
|
||||||
|
f = open(filepath, 'rb')
|
||||||
|
m = hashlib.md5()
|
||||||
|
m.update(f.read())
|
||||||
|
md5 = m.hexdigest()
|
||||||
|
|
||||||
|
return md5
|
||||||
|
|
||||||
|
def ensure_dir(self, filepath):
|
||||||
|
|
||||||
|
directory = os.path.dirname(filepath)
|
||||||
|
|
||||||
|
if ((not os.path.exists(directory)) or ((os.path.exists(directory) and not os.path.isdir(directory)))):
|
||||||
|
os.makedirs(directory, 02775)
|
||||||
|
|
||||||
|
def create_unique_filename(self, filepath):
|
||||||
|
|
||||||
|
file_dir = os.path.dirname(filepath)
|
||||||
|
filename = os.path.basename(filepath).split(".")[0]
|
||||||
|
file_ext = os.path.splitext(filepath)[1]
|
||||||
|
|
||||||
|
if(os.path.exists(filepath)):
|
||||||
|
i = 1;
|
||||||
|
while(True):
|
||||||
|
new_filepath = "%s/%s(%s).%s" % (file_dir, filename, i, file_ext)
|
||||||
|
|
||||||
|
if(os.path.exists(new_filepath)):
|
||||||
|
i = i+1;
|
||||||
|
else:
|
||||||
|
filepath = new_filepath
|
||||||
|
|
||||||
|
self.imported_renamed_files[filepath] = 0
|
||||||
|
|
||||||
|
return filepath
|
||||||
|
|
||||||
|
def create_file_path(self, imported_filepath):
|
||||||
|
|
||||||
|
global storage_directory
|
||||||
|
|
||||||
|
original_name = os.path.basename(imported_filepath)
|
||||||
|
file_ext = os.path.splitext(imported_filepath)[1]
|
||||||
|
file_info = mutagen.File(imported_filepath, easy=True)
|
||||||
|
|
||||||
|
metadata = {'artist':None,
|
||||||
|
'album':None,
|
||||||
|
'title':None,
|
||||||
|
'tracknumber':None}
|
||||||
|
|
||||||
|
for key in metadata.keys():
|
||||||
|
if key in file_info:
|
||||||
|
metadata[key] = file_info[key][0]
|
||||||
|
|
||||||
|
if metadata['artist'] is not None:
|
||||||
|
base = "%s/%s" % (storage_directory, metadata['artist'])
|
||||||
|
if metadata['album'] is not None:
|
||||||
|
base = "%s/%s" % (base, metadata['album'])
|
||||||
|
if metadata['title'] is not None:
|
||||||
|
if metadata['tracknumber'] is not None:
|
||||||
|
metadata['tracknumber'] = "%02d" % (int(metadata['tracknumber']))
|
||||||
|
base = "%s/%s - %s" % (base, metadata['tracknumber'], metadata['title'])
|
||||||
|
else:
|
||||||
|
base = "%s/%s" % (base, metadata['title'])
|
||||||
|
else:
|
||||||
|
base = "%s/%s" % (base, original_name)
|
||||||
|
else:
|
||||||
|
base = "%s/%s" % (storage_directory, original_name)
|
||||||
|
|
||||||
|
base = "%s%s" % (base, file_ext)
|
||||||
|
|
||||||
|
filepath = self.create_unique_filename(base)
|
||||||
|
self.ensure_dir(filepath)
|
||||||
|
shutil.move(imported_filepath, filepath)
|
||||||
|
|
||||||
def update_airtime(self, event):
|
def update_airtime(self, event):
|
||||||
self.logger.info("Updating Change to Airtime")
|
self.logger.info("Updating Change to Airtime")
|
||||||
try:
|
try:
|
||||||
f = open(event.pathname, 'rb')
|
md5 = self.get_md5(event.pathname)
|
||||||
m = hashlib.md5()
|
md = {'filepath':event.pathname, 'md5':md5}
|
||||||
m.update(f.read())
|
|
||||||
|
|
||||||
md5 = m.hexdigest()
|
|
||||||
gunid = event.name.split('.')[0]
|
|
||||||
|
|
||||||
md = {'gunid':gunid, 'md5':md5}
|
|
||||||
|
|
||||||
file_info = mutagen.File(event.pathname, easy=True)
|
file_info = mutagen.File(event.pathname, easy=True)
|
||||||
attrs = self.mutagen2airtime
|
attrs = self.mutagen2airtime
|
||||||
|
@ -147,37 +220,55 @@ class MediaMonitor(ProcessEvent):
|
||||||
md[attrs[key]] = file_info[key][0]
|
md[attrs[key]] = file_info[key][0]
|
||||||
|
|
||||||
data = {'md': md}
|
data = {'md': md}
|
||||||
|
|
||||||
response = self.api_client.update_media_metadata(data)
|
response = self.api_client.update_media_metadata(data)
|
||||||
|
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
self.logger.info("%s", e)
|
self.logger.info("%s", e)
|
||||||
|
|
||||||
|
def is_renamed_file(self, filename):
|
||||||
|
if filename in self.imported_renamed_files:
|
||||||
|
del self.imported_renamed_files[filename]
|
||||||
|
return True
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
def is_temp_file(self, filename):
|
||||||
|
info = filename.split(".")
|
||||||
|
|
||||||
|
if(info[-2] in self.supported_file_formats):
|
||||||
|
return True
|
||||||
|
else :
|
||||||
|
return False
|
||||||
|
|
||||||
|
def is_audio_file(self, filename):
|
||||||
|
info = filename.split(".")
|
||||||
|
|
||||||
|
if(info[-1] in self.supported_file_formats):
|
||||||
|
return True
|
||||||
|
else :
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def process_IN_CREATE(self, event):
|
def process_IN_CREATE(self, event):
|
||||||
if not event.dir :
|
if not event.dir:
|
||||||
filename_info = event.name.split(".")
|
|
||||||
|
|
||||||
#file created is a tmp file which will be modified and then moved back to the original filename.
|
#file created is a tmp file which will be modified and then moved back to the original filename.
|
||||||
if len(filename_info) > 2 :
|
if self.is_temp_file(event.name) :
|
||||||
self.temp_files[event.pathname] = None
|
self.temp_files[event.pathname] = None
|
||||||
#This is a newly imported file.
|
#This is a newly imported file.
|
||||||
else :
|
else :
|
||||||
pass
|
#if not is_renamed_file(event.pathname):
|
||||||
|
self.create_file_path(event.pathname)
|
||||||
|
|
||||||
self.logger.info("%s: %s", event.maskname, event.pathname)
|
self.logger.info("%s: %s", event.maskname, event.pathname)
|
||||||
|
|
||||||
#event.path : /srv/airtime/stor/bd2
|
|
||||||
#event.name : bd2aa73b58d9c8abcced989621846e99.mp3
|
|
||||||
#event.pathname : /srv/airtime/stor/bd2/bd2aa73b58d9c8abcced989621846e99.mp3
|
|
||||||
def process_IN_MODIFY(self, event):
|
def process_IN_MODIFY(self, event):
|
||||||
if not event.dir :
|
if not event.dir :
|
||||||
filename_info = event.name.split(".")
|
|
||||||
|
|
||||||
#file modified is not a tmp file.
|
if self.is_audio_file(event.name) :
|
||||||
if len(filename_info) == 2 :
|
self.update_airtime(event)
|
||||||
self.update_airtime(event)
|
|
||||||
|
|
||||||
self.logger.info("%s: path: %s name: %s", event.maskname, event.path, event.name)
|
self.logger.info("%s: %s", event.maskname, event.pathname)
|
||||||
|
|
||||||
def process_IN_MOVED_FROM(self, event):
|
def process_IN_MOVED_FROM(self, event):
|
||||||
if event.pathname in self.temp_files :
|
if event.pathname in self.temp_files :
|
||||||
|
@ -190,7 +281,7 @@ class MediaMonitor(ProcessEvent):
|
||||||
if event.cookie in self.temp_files :
|
if event.cookie in self.temp_files :
|
||||||
del self.temp_files[event.cookie]
|
del self.temp_files[event.cookie]
|
||||||
self.update_airtime(event)
|
self.update_airtime(event)
|
||||||
|
|
||||||
self.logger.info("%s: %s", event.maskname, event.pathname)
|
self.logger.info("%s: %s", event.maskname, event.pathname)
|
||||||
|
|
||||||
def process_default(self, event):
|
def process_default(self, event):
|
||||||
|
@ -204,12 +295,13 @@ if __name__ == '__main__':
|
||||||
#mask = pyinotify.ALL_EVENTS
|
#mask = pyinotify.ALL_EVENTS
|
||||||
|
|
||||||
wm = WatchManager()
|
wm = WatchManager()
|
||||||
wdd = wm.add_watch('/srv/airtime/stor', mask, rec=True, auto_add=True)
|
wdd = wm.add_watch(storage_directory, mask, rec=True, auto_add=True)
|
||||||
|
|
||||||
|
logger = logging.getLogger('root')
|
||||||
|
logger.info("Added watch to %s", storage_directory)
|
||||||
|
|
||||||
notifier = AirtimeNotifier(wm, MediaMonitor(), read_freq=int(config["check_filesystem_events"]), timeout=1)
|
notifier = AirtimeNotifier(wm, MediaMonitor(), read_freq=int(config["check_filesystem_events"]), timeout=1)
|
||||||
notifier.coalesce_events()
|
notifier.coalesce_events()
|
||||||
notifier.loop(callback=checkRabbitMQ)
|
notifier.loop(callback=checkRabbitMQ)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
notifier.stop()
|
notifier.stop()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,6 @@ exec 2>&1
|
||||||
export PYTHONPATH=${api_client_path}
|
export PYTHONPATH=${api_client_path}
|
||||||
|
|
||||||
# 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 python -u ${media_monitor_path}${media_monitor_script}
|
exec python -u ${media_monitor_path}${media_monitor_script} > /var/log/airtime/media-monitor/py-interpreter.log 2>&1
|
||||||
|
|
||||||
# EOF
|
# EOF
|
||||||
|
|
|
@ -32,5 +32,5 @@ rabbitmq_password = 'guest'
|
||||||
############################################
|
############################################
|
||||||
# Media-Monitor preferences #
|
# Media-Monitor preferences #
|
||||||
############################################
|
############################################
|
||||||
check_filesystem_events = 30 #how long to queue up events performed on the files themselves.
|
check_filesystem_events = 5 #how long to queue up events performed on the files themselves.
|
||||||
check_airtime_events = 30 #how long to queue metadata input from airtime.
|
check_airtime_events = 30 #how long to queue metadata input from airtime.
|
||||||
|
|
|
@ -13,6 +13,6 @@ export HOME="/var/tmp/airtime/pypo/"
|
||||||
export PYTHONPATH=${api_client_path}:$PYTHONPATH
|
export PYTHONPATH=${api_client_path}:$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 python -u ${pypo_path}${pypo_script}
|
exec python -u ${pypo_path}${pypo_script} > /var/log/airtime/pypo/py-interpreter.log 2>&1
|
||||||
|
|
||||||
# EOF
|
# EOF
|
||||||
|
|
|
@ -61,18 +61,25 @@ class PypoFetch(Thread):
|
||||||
self.cue_file = CueFile()
|
self.cue_file = CueFile()
|
||||||
self.set_export_source('scheduler')
|
self.set_export_source('scheduler')
|
||||||
self.queue = q
|
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")
|
logger.info("PypoFetch: init complete")
|
||||||
|
|
||||||
|
def init_rabbit_mq(self):
|
||||||
|
logger = logging.getLogger('fetch')
|
||||||
|
logger.info("Initializing RabbitMQ stuff")
|
||||||
|
try:
|
||||||
|
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()
|
||||||
|
except Exception, e:
|
||||||
|
logger.error(e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def set_export_source(self, export_source):
|
def set_export_source(self, export_source):
|
||||||
self.export_source = export_source
|
self.export_source = export_source
|
||||||
|
@ -336,6 +343,10 @@ class PypoFetch(Thread):
|
||||||
def run(self):
|
def run(self):
|
||||||
logger = logging.getLogger('fetch')
|
logger = logging.getLogger('fetch')
|
||||||
|
|
||||||
|
while not self.init_rabbit_mq():
|
||||||
|
logger.error("Error connecting to RabbitMQ Server. Trying again in few seconds")
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
try: os.mkdir(self.cache_dir)
|
try: os.mkdir(self.cache_dir)
|
||||||
except Exception, e: pass
|
except Exception, e: pass
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,6 @@ export PYTHONPATH=${api_client_path}
|
||||||
|
|
||||||
#this line works: su ${recorder_user} -c "python -u ${recorder_path}${recorder_script}"
|
#this line works: su ${recorder_user} -c "python -u ${recorder_path}${recorder_script}"
|
||||||
# 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 python -u ${recorder_path}${recorder_script}
|
exec python -u ${recorder_path}${recorder_script} > /var/log/airtime/show-recorder/py-interpreter.log 2>&1
|
||||||
|
|
||||||
# EOF
|
# EOF
|
||||||
|
|
|
@ -48,11 +48,10 @@ def getDateTimeObj(time):
|
||||||
|
|
||||||
class ShowRecorder(Thread):
|
class ShowRecorder(Thread):
|
||||||
|
|
||||||
def __init__ (self, show_instance, filelength, show_name, start_time, filetype):
|
def __init__ (self, show_instance, filelength, start_time, filetype):
|
||||||
Thread.__init__(self)
|
Thread.__init__(self)
|
||||||
self.api_client = api_client.api_client_factory(config)
|
self.api_client = api_client.api_client_factory(config)
|
||||||
self.filelength = filelength
|
self.filelength = filelength
|
||||||
self.show_name = show_name
|
|
||||||
self.start_time = start_time
|
self.start_time = start_time
|
||||||
self.filetype = filetype
|
self.filetype = filetype
|
||||||
self.show_instance = show_instance
|
self.show_instance = show_instance
|
||||||
|
@ -61,7 +60,7 @@ class ShowRecorder(Thread):
|
||||||
|
|
||||||
def record_show(self):
|
def record_show(self):
|
||||||
length = str(self.filelength)+".0"
|
length = str(self.filelength)+".0"
|
||||||
filename = self.show_name+" "+self.start_time
|
filename = self.start_time
|
||||||
filename = filename.replace(" ", "-")
|
filename = filename.replace(" ", "-")
|
||||||
filepath = "%s%s.%s" % (config["base_recorded_files"], filename, self.filetype)
|
filepath = "%s%s.%s" % (config["base_recorded_files"], filename, self.filetype)
|
||||||
|
|
||||||
|
@ -155,9 +154,8 @@ class Record():
|
||||||
|
|
||||||
show_length = self.shows_to_record[start_time][0]
|
show_length = self.shows_to_record[start_time][0]
|
||||||
show_instance = self.shows_to_record[start_time][1]
|
show_instance = self.shows_to_record[start_time][1]
|
||||||
show_name = self.shows_to_record[start_time][2]
|
|
||||||
|
|
||||||
self.sr = ShowRecorder(show_instance, show_length.seconds, show_name, start_time, filetype="mp3")
|
self.sr = ShowRecorder(show_instance, show_length.seconds, start_time, filetype="mp3")
|
||||||
self.sr.start()
|
self.sr.start()
|
||||||
|
|
||||||
#remove show from shows to record.
|
#remove show from shows to record.
|
||||||
|
|
Loading…
Reference in New Issue