Merge branch 'devel' of dev.sourcefabric.org:airtime into cc-2528-use-virtualenv-for-installing
Conflicts: python_apps/media-monitor/airtime-media-monitor
This commit is contained in:
commit
107c100cc4
2
VERSION
2
VERSION
|
@ -1,2 +1,2 @@
|
||||||
PRODUCT_ID=Airtime
|
PRODUCT_ID=Airtime
|
||||||
PRODUCT_RELEASE=1.9.0-beta4
|
PRODUCT_RELEASE=1.9.0-RC1
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
define('AIRTIME_VERSION', '1.9.0-beta4');
|
define('AIRTIME_VERSION', '1.9.0-RC1');
|
||||||
define('AIRTIME_COPYRIGHT_DATE', '2010-2011');
|
define('AIRTIME_COPYRIGHT_DATE', '2010-2011');
|
||||||
define('AIRTIME_REST_VERSION', '1.1');
|
define('AIRTIME_REST_VERSION', '1.1');
|
||||||
|
|
||||||
|
|
|
@ -341,7 +341,7 @@ class ApiController extends Zend_Controller_Action
|
||||||
$file = StoredFile::Recall($file_id);
|
$file = StoredFile::Recall($file_id);
|
||||||
//$show_instance = $this->_getParam('show_instance');
|
//$show_instance = $this->_getParam('show_instance');
|
||||||
|
|
||||||
$show_name = "";
|
$show_name = null;
|
||||||
try {
|
try {
|
||||||
$show_inst = new ShowInstance($show_instance_id);
|
$show_inst = new ShowInstance($show_instance_id);
|
||||||
|
|
||||||
|
@ -359,10 +359,17 @@ class ApiController extends Zend_Controller_Action
|
||||||
$showCanceled = true;
|
$showCanceled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$tmpTitle = !(empty($show_name))?$show_name."-":"";
|
if (isset($show_name)) {
|
||||||
$tmpTitle .= $file->getName();
|
$tmpTitle = "$show_name-$show_start_time";
|
||||||
|
$tmpTitle = str_replace(" ", "-", $tmpTitle);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$tmpTitle = $file->getName();
|
||||||
|
}
|
||||||
|
|
||||||
$file->setMetadataValue('MDATA_KEY_TITLE', $tmpTitle);
|
$file->setMetadataValue('MDATA_KEY_TITLE', $tmpTitle);
|
||||||
|
$file->setMetadataValue('MDATA_KEY_CREATOR', "Airtime Show Recorder");
|
||||||
|
$file->setMetadataValue('MDATA_KEY_TRACKNUMBER', null);
|
||||||
|
|
||||||
if (!$showCanceled && Application_Model_Preference::GetDoSoundCloudUpload())
|
if (!$showCanceled && Application_Model_Preference::GetDoSoundCloudUpload())
|
||||||
{
|
{
|
||||||
|
|
|
@ -63,6 +63,9 @@ class LibraryController extends Zend_Controller_Action
|
||||||
$paramsPop = str_replace('#id#', $id, $params);
|
$paramsPop = str_replace('#id#', $id, $params);
|
||||||
$paramsPop = str_replace('#type#', $type, $paramsPop);
|
$paramsPop = str_replace('#type#', $type, $paramsPop);
|
||||||
|
|
||||||
|
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
||||||
|
$user = new User($userInfo->id);
|
||||||
|
|
||||||
$pl_sess = $this->pl_sess;
|
$pl_sess = $this->pl_sess;
|
||||||
|
|
||||||
if($type === "au") {
|
if($type === "au") {
|
||||||
|
@ -85,10 +88,13 @@ class LibraryController extends Zend_Controller_Action
|
||||||
$menu[] = array('action' => array('type' => 'gourl', 'url' => $url),
|
$menu[] = array('action' => array('type' => 'gourl', 'url' => $url),
|
||||||
'title' => 'Download');
|
'title' => 'Download');
|
||||||
|
|
||||||
|
|
||||||
|
if ($user->isAdmin()) {
|
||||||
$menu[] = array('action' => array('type' => 'fn',
|
$menu[] = array('action' => array('type' => 'fn',
|
||||||
'callback' => "window['confirmDeleteAudioClip']('$paramsPop')"),
|
'callback' => "window['confirmDeleteAudioClip']('$paramsPop')"),
|
||||||
'title' => 'Delete');
|
'title' => 'Delete');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else if($type === "pl") {
|
else if($type === "pl") {
|
||||||
|
|
||||||
if(!isset($pl_sess->id) || $pl_sess->id !== $id) {
|
if(!isset($pl_sess->id) || $pl_sess->id !== $id) {
|
||||||
|
@ -121,6 +127,10 @@ class LibraryController extends Zend_Controller_Action
|
||||||
public function deleteAction()
|
public function deleteAction()
|
||||||
{
|
{
|
||||||
$id = $this->_getParam('id');
|
$id = $this->_getParam('id');
|
||||||
|
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
||||||
|
$user = new User($userInfo->id);
|
||||||
|
|
||||||
|
if ($user->isAdmin()) {
|
||||||
|
|
||||||
if (!is_null($id)) {
|
if (!is_null($id)) {
|
||||||
$file = StoredFile::Recall($id);
|
$file = StoredFile::Recall($id);
|
||||||
|
@ -141,6 +151,7 @@ class LibraryController extends Zend_Controller_Action
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
$res = settype($res, "integer");
|
||||||
$data = array("filepath" => $file->getFilePath(), "delete" => $res);
|
$data = array("filepath" => $file->getFilePath(), "delete" => $res);
|
||||||
RabbitMq::SendMessageToMediaMonitor("file_delete", $data);
|
RabbitMq::SendMessageToMediaMonitor("file_delete", $data);
|
||||||
}
|
}
|
||||||
|
@ -148,6 +159,7 @@ class LibraryController extends Zend_Controller_Action
|
||||||
|
|
||||||
$this->view->id = $id;
|
$this->view->id = $id;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function contentsAction()
|
public function contentsAction()
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,9 +25,9 @@ class NowplayingController 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 ($request->isPost()) {
|
||||||
$form = new Application_Form_RegisterAirtime();
|
$form = new Application_Form_RegisterAirtime();
|
||||||
|
|
||||||
if ($request->isPost()) {
|
|
||||||
$values = $request->getPost();
|
$values = $request->getPost();
|
||||||
if ($values["Publicise"] != 1){
|
if ($values["Publicise"] != 1){
|
||||||
Application_Model_Preference::SetSupportFeedback($values["SupportFeedback"]);
|
Application_Model_Preference::SetSupportFeedback($values["SupportFeedback"]);
|
||||||
|
@ -64,6 +64,10 @@ class NowplayingController extends Zend_Controller_Action
|
||||||
//popup if previous page was login
|
//popup if previous page was login
|
||||||
if($refer_sses->referrer == 'login' && Application_Model_Nowplaying::ShouldShowPopUp()
|
if($refer_sses->referrer == 'login' && Application_Model_Nowplaying::ShouldShowPopUp()
|
||||||
&& !Application_Model_Preference::GetSupportFeedback() && $user->isAdmin()){
|
&& !Application_Model_Preference::GetSupportFeedback() && $user->isAdmin()){
|
||||||
|
|
||||||
|
$form = new Application_Form_RegisterAirtime();
|
||||||
|
|
||||||
|
|
||||||
$logo = Application_Model_Preference::GetStationLogo();
|
$logo = Application_Model_Preference::GetStationLogo();
|
||||||
if($logo){
|
if($logo){
|
||||||
$this->view->logoImg = $logo;
|
$this->view->logoImg = $logo;
|
||||||
|
|
|
@ -123,9 +123,10 @@ class PreferenceController extends Zend_Controller_Action
|
||||||
$chosen = $this->getRequest()->getParam("dir");
|
$chosen = $this->getRequest()->getParam("dir");
|
||||||
$element = $this->getRequest()->getParam("element");
|
$element = $this->getRequest()->getParam("element");
|
||||||
$watched_dirs_form = new Application_Form_WatchedDirPreferences();
|
$watched_dirs_form = new Application_Form_WatchedDirPreferences();
|
||||||
$watched_dirs_form->populate(array('storageFolder' => $chosen));
|
|
||||||
$res = MusicDir::setStorDir($chosen);
|
$res = MusicDir::setStorDir($chosen);
|
||||||
if($res['code'] != 0){
|
if($res['code'] != 0){
|
||||||
|
$watched_dirs_form->populate(array('storageFolder' => $chosen));
|
||||||
$watched_dirs_form->getElement($element)->setErrors(array($res['error']));
|
$watched_dirs_form->getElement($element)->setErrors(array($res['error']));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,9 +138,10 @@ class PreferenceController extends Zend_Controller_Action
|
||||||
$chosen = $this->getRequest()->getParam("dir");
|
$chosen = $this->getRequest()->getParam("dir");
|
||||||
$element = $this->getRequest()->getParam("element");
|
$element = $this->getRequest()->getParam("element");
|
||||||
$watched_dirs_form = new Application_Form_WatchedDirPreferences();
|
$watched_dirs_form = new Application_Form_WatchedDirPreferences();
|
||||||
$watched_dirs_form->populate(array('watchedFolder' => $chosen));
|
|
||||||
$res = MusicDir::addWatchedDir($chosen);
|
$res = MusicDir::addWatchedDir($chosen);
|
||||||
if($res['code'] != 0){
|
if($res['code'] != 0){
|
||||||
|
$watched_dirs_form->populate(array('watchedFolder' => $chosen));
|
||||||
$watched_dirs_form->getElement($element)->setErrors(array($res['error']));
|
$watched_dirs_form->getElement($element)->setErrors(array($res['error']));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
class NestedDirectoryException extends Exception { }
|
||||||
|
|
||||||
class MusicDir {
|
class MusicDir {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,7 +42,75 @@ class MusicDir {
|
||||||
|
|
||||||
public function remove()
|
public function remove()
|
||||||
{
|
{
|
||||||
|
global $CC_DBC;
|
||||||
|
|
||||||
|
$music_dir_id = $this->getId();
|
||||||
|
|
||||||
|
$sql = "SELECT DISTINCT s.instance_id from cc_music_dirs as md LEFT JOIN cc_files as f on f.directory = md.id
|
||||||
|
RIGHT JOIN cc_schedule as s on s.file_id = f.id WHERE md.id = $music_dir_id";
|
||||||
|
|
||||||
|
$show_instances = $CC_DBC->GetAll($sql);
|
||||||
|
|
||||||
$this->_dir->delete();
|
$this->_dir->delete();
|
||||||
|
|
||||||
|
foreach ($show_instances as $show_instance_row) {
|
||||||
|
$temp_show = new ShowInstance($show_instance_row["instance_id"]);
|
||||||
|
$temp_show->updateScheduledTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
RabbitMq::PushSchedule();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if p_dir1 is the ancestor of p_dir2. Returns
|
||||||
|
* true if it is the ancestor, false otherwise. Note that
|
||||||
|
* /home/user is considered the ancestor of /home/user
|
||||||
|
*
|
||||||
|
* @param string $p_dir1
|
||||||
|
* The potential ancestor directory.
|
||||||
|
* @param string $p_dir2
|
||||||
|
* The potential descendent directory.
|
||||||
|
* @return boolean
|
||||||
|
* Returns true if it is the ancestor, false otherwise.
|
||||||
|
*/
|
||||||
|
private static function isAncestorDir($p_dir1, $p_dir2){
|
||||||
|
if (strlen($p_dir1) > strlen($p_dir2)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return substr($p_dir2, 0, strlen($p_dir1)) == $p_dir1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the path provided is a valid path. A valid path
|
||||||
|
* is defined as not being nested within an existing watched directory,
|
||||||
|
* or vice-versa. Throws a NestedDirectoryException if invalid.
|
||||||
|
*
|
||||||
|
* @param string $p_path
|
||||||
|
* The path we want to validate
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public static function isPathValid($p_path){
|
||||||
|
$dirs = self::getWatchedDirs();
|
||||||
|
$dirs[] = self::getStorDir();
|
||||||
|
|
||||||
|
foreach ($dirs as $dirObj){
|
||||||
|
$dir = $dirObj->getDirectory();
|
||||||
|
$diff = strlen($dir) - strlen($p_path);
|
||||||
|
if ($diff == 0){
|
||||||
|
if ($dir == $p_path){
|
||||||
|
throw new NestedDirectoryException("'$p_path' is already watched.");
|
||||||
|
}
|
||||||
|
} else if ($diff > 0){
|
||||||
|
if (self::isAncestorDir($p_path, $dir)){
|
||||||
|
throw new NestedDirectoryException("'$p_path' contains nested watched directory: '$dir'");
|
||||||
|
}
|
||||||
|
} else { /* diff < 0*/
|
||||||
|
if (self::isAncestorDir($dir, $p_path)){
|
||||||
|
throw new NestedDirectoryException("'$p_path' is nested within existing watched directory: '$dir'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function addDir($p_path, $p_type)
|
public static function addDir($p_path, $p_type)
|
||||||
|
@ -51,13 +121,20 @@ class MusicDir {
|
||||||
$dir = new CcMusicDirs();
|
$dir = new CcMusicDirs();
|
||||||
$dir->setType($p_type);
|
$dir->setType($p_type);
|
||||||
$p_path = realpath($p_path)."/";
|
$p_path = realpath($p_path)."/";
|
||||||
$temp = $dir->setDirectory($p_path);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
/* isPathValid() checks if path is a substring or a superstring of an
|
||||||
|
* existing dir and if not, throws NestedDirectoryException */
|
||||||
|
self::isPathValid($p_path);
|
||||||
|
$dir->setDirectory($p_path);
|
||||||
|
|
||||||
$dir->save();
|
$dir->save();
|
||||||
return array("code"=>0);
|
return array("code"=>0);
|
||||||
}
|
} catch (NestedDirectoryException $nde){
|
||||||
catch(Exception $e){
|
$msg = $nde->getMessage();
|
||||||
//echo $e->getMessage();
|
return array("code"=>1, "error"=>"$msg");
|
||||||
|
} catch(Exception $e){
|
||||||
return array("code"=>1, "error"=>"'$p_path' is already set as the current storage dir or in the watched folders list");
|
return array("code"=>1, "error"=>"'$p_path' is already set as the current storage dir or in the watched folders list");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,7 +56,7 @@ class ScheduleGroup {
|
||||||
|
|
||||||
// Check if there are any conflicts with existing entries
|
// Check if there are any conflicts with existing entries
|
||||||
$metadata = $track->getMetadata();
|
$metadata = $track->getMetadata();
|
||||||
$length = trim($metadata["length"]);
|
$length = $metadata['MDATA_KEY_DURATION'];
|
||||||
if (empty($length)) {
|
if (empty($length)) {
|
||||||
return new PEAR_Error("Length is empty.");
|
return new PEAR_Error("Length is empty.");
|
||||||
}
|
}
|
||||||
|
|
|
@ -318,6 +318,13 @@ class StoredFile {
|
||||||
|
|
||||||
Playlist::DeleteFileFromAllPlaylists($this->getId());
|
Playlist::DeleteFileFromAllPlaylists($this->getId());
|
||||||
$this->_file->delete();
|
$this->_file->delete();
|
||||||
|
|
||||||
|
if (isset($res)) {
|
||||||
|
return $res;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -341,19 +348,8 @@ class StoredFile {
|
||||||
return PEAR::raiseError('Cannot delete a file that is scheduled in the future.');
|
return PEAR::raiseError('Cannot delete a file that is scheduled in the future.');
|
||||||
}
|
}
|
||||||
|
|
||||||
$storageDir = MusicDir::getStorDir()->getDirectory();
|
|
||||||
$dirCompare = substr($this->getFilePath(), 0, strlen($storageDir));
|
|
||||||
|
|
||||||
//return PEAR::raiseError("({$storageDir} , {$dirCompare})");
|
|
||||||
|
|
||||||
// Only delete the file from filesystem if it has been copied to the storage directory
|
|
||||||
if ($dirCompare === $storageDir) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if media file exists
|
* Returns true if media file exists
|
||||||
|
|
|
@ -35,7 +35,7 @@ function deleteAudioClip(json) {
|
||||||
|
|
||||||
//callbacks called by jjmenu
|
//callbacks called by jjmenu
|
||||||
function confirmDeleteAudioClip(params){
|
function confirmDeleteAudioClip(params){
|
||||||
if(confirm('Are you sure you want to delete?')){
|
if(confirm('The file will be deleted from disk, are you sure you want to delete?')){
|
||||||
var url = '/Library/delete' + params;
|
var url = '/Library/delete' + params;
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: url,
|
url: url,
|
||||||
|
|
|
@ -33,7 +33,7 @@ function setWatchedDirEvents() {
|
||||||
//knownPaths: [{text:'Desktop', image:'desktop.png', path:'/home'}],
|
//knownPaths: [{text:'Desktop', image:'desktop.png', path:'/home'}],
|
||||||
knownPaths: [],
|
knownPaths: [],
|
||||||
imageUrl: 'img/icons/',
|
imageUrl: 'img/icons/',
|
||||||
systemImageUrl: 'img/browser/',
|
systemImageUrl: '/css/img/',
|
||||||
handlerUrl: '/Preference/server-browse/format/json',
|
handlerUrl: '/Preference/server-browse/format/json',
|
||||||
title: 'Choose Folder to Watch',
|
title: 'Choose Folder to Watch',
|
||||||
basePath: '',
|
basePath: '',
|
||||||
|
|
|
@ -3,8 +3,9 @@
|
||||||
namespace DoctrineMigrations;
|
namespace DoctrineMigrations;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
update cc_files table to include to "directory" column as well as add foreign key relation to
|
1) update cc_files table to include to "directory" column
|
||||||
cc_music_dirs table.
|
2) create a foreign key relationship from cc_files to cc_music_dirs
|
||||||
|
3) create a foreign key relationship from cc_schedule to cc_files
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use Doctrine\DBAL\Migrations\AbstractMigration,
|
use Doctrine\DBAL\Migrations\AbstractMigration,
|
||||||
|
@ -14,21 +15,22 @@ class Version20110711161043 extends AbstractMigration
|
||||||
{
|
{
|
||||||
public function up(Schema $schema)
|
public function up(Schema $schema)
|
||||||
{
|
{
|
||||||
|
/* 1) update cc_files table to include to "directory" column */
|
||||||
//CREATE the default value of "/srv/airtime/stor", this can be updated later in the upgrade script.
|
|
||||||
$this->_addSql("INSERT INTO cc_music_dirs (type, directory) VALUES ('stor', '/srv/airtime/stor');");
|
$this->_addSql("INSERT INTO cc_music_dirs (type, directory) VALUES ('stor', '/srv/airtime/stor');");
|
||||||
|
|
||||||
$this->_addSql("INSERT INTO cc_music_dirs (type, directory) VALUES ('upgrade', '');");
|
$this->_addSql("INSERT INTO cc_music_dirs (type, directory) VALUES ('upgrade', '');");
|
||||||
|
|
||||||
$cc_music_dirs = $schema->getTable('cc_music_dirs');
|
$cc_music_dirs = $schema->getTable('cc_music_dirs');
|
||||||
|
|
||||||
//start cc_files modifications
|
/* 2) create a foreign key relationship from cc_files to cc_music_dirs */
|
||||||
$cc_files = $schema->getTable('cc_files');
|
$cc_files = $schema->getTable('cc_files');
|
||||||
$cc_files->addColumn('directory', 'integer', array('default'=> 2));
|
$cc_files->addColumn('directory', 'integer', array('default'=> 2));
|
||||||
|
|
||||||
$cc_files->addNamedForeignKeyConstraint('cc_music_dirs_folder_fkey', $cc_music_dirs, array('directory'), array('id'), array('onDelete' => 'CASCADE'));
|
$cc_files->addNamedForeignKeyConstraint('cc_music_dirs_folder_fkey', $cc_music_dirs, array('directory'), array('id'), array('onDelete' => 'CASCADE'));
|
||||||
//end cc_files modifications
|
|
||||||
|
|
||||||
|
/* 3) create a foreign key relationship from cc_schedule to cc_files */
|
||||||
|
$cc_schedule = $schema->getTable('cc_schedule');
|
||||||
|
$cc_schedule->addNamedForeignKeyConstraint('cc_files_folder_fkey', $cc_files, array('file_id'), array('id'), array('onDelete' => 'CASCADE'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function down(Schema $schema)
|
public function down(Schema $schema)
|
||||||
|
|
|
@ -19,6 +19,9 @@ python ${SCRIPTPATH}/../python_apps/create-pypo-user.py
|
||||||
|
|
||||||
php ${SCRIPTPATH}/include/airtime-install.php $@
|
php ${SCRIPTPATH}/include/airtime-install.php $@
|
||||||
|
|
||||||
|
echo -e "\n*** API Client Installation ***"
|
||||||
|
python ${SCRIPTPATH}/../python_apps/api_clients/install/api_client_install.py
|
||||||
|
|
||||||
echo -e "\n*** Pypo Installation ***"
|
echo -e "\n*** Pypo Installation ***"
|
||||||
python ${SCRIPTPATH}/../python_apps/pypo/install/pypo-install.py
|
python ${SCRIPTPATH}/../python_apps/pypo/install/pypo-install.py
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,10 @@ python ${SCRIPTPATH}/../python_apps/show-recorder/install/recorder-uninstall.py
|
||||||
echo -e "\n*** Uninstalling Media Monitor ***"
|
echo -e "\n*** Uninstalling Media Monitor ***"
|
||||||
python ${SCRIPTPATH}/../python_apps/media-monitor/install/media-monitor-uninstall.py
|
python ${SCRIPTPATH}/../python_apps/media-monitor/install/media-monitor-uninstall.py
|
||||||
|
|
||||||
|
echo -e "\n*** Uninstalling API Client ***"
|
||||||
|
python ${SCRIPTPATH}/../python_apps/api_clients/install/api_client_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
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ class AirtimeIni
|
||||||
const CONF_FILE_AIRTIME = "/etc/airtime/airtime.conf";
|
const CONF_FILE_AIRTIME = "/etc/airtime/airtime.conf";
|
||||||
const CONF_FILE_PYPO = "/etc/airtime/pypo.cfg";
|
const CONF_FILE_PYPO = "/etc/airtime/pypo.cfg";
|
||||||
const CONF_FILE_RECORDER = "/etc/airtime/recorder.cfg";
|
const CONF_FILE_RECORDER = "/etc/airtime/recorder.cfg";
|
||||||
|
const CONF_FILE_API_CLIENT = "/etc/airtime/api_client.cfg";
|
||||||
const CONF_FILE_LIQUIDSOAP = "/etc/airtime/liquidsoap.cfg";
|
const CONF_FILE_LIQUIDSOAP = "/etc/airtime/liquidsoap.cfg";
|
||||||
const CONF_FILE_MEDIAMONITOR = "/etc/airtime/media-monitor.cfg";
|
const CONF_FILE_MEDIAMONITOR = "/etc/airtime/media-monitor.cfg";
|
||||||
const CONF_FILE_MONIT = "/etc/monit/conf.d/airtime-monit.cfg";
|
const CONF_FILE_MONIT = "/etc/monit/conf.d/airtime-monit.cfg";
|
||||||
|
@ -65,6 +66,10 @@ class AirtimeIni
|
||||||
echo "Could not copy airtime.conf to /etc/airtime/. Exiting.";
|
echo "Could not copy airtime.conf to /etc/airtime/. Exiting.";
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
if (!copy(__DIR__."/../../python_apps/api_clients/api_client.cfg", AirtimeIni::CONF_FILE_API_CLIENT)){
|
||||||
|
echo "Could not copy api_client.cfg to /etc/airtime/. Exiting.";
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
if (!copy(__DIR__."/../../python_apps/pypo/pypo.cfg", AirtimeIni::CONF_FILE_PYPO)){
|
if (!copy(__DIR__."/../../python_apps/pypo/pypo.cfg", AirtimeIni::CONF_FILE_PYPO)){
|
||||||
echo "Could not copy pypo.cfg to /etc/airtime/. Exiting.";
|
echo "Could not copy pypo.cfg to /etc/airtime/. Exiting.";
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
|
@ -8,7 +8,9 @@
|
||||||
|
|
||||||
//Pear classes.
|
//Pear classes.
|
||||||
set_include_path(__DIR__.'/../../airtime_mvc/library/pear' . PATH_SEPARATOR . get_include_path());
|
set_include_path(__DIR__.'/../../airtime_mvc/library/pear' . PATH_SEPARATOR . get_include_path());
|
||||||
|
|
||||||
require_once('DB.php');
|
require_once('DB.php');
|
||||||
|
require_once(__DIR__.'/../../airtime_mvc/application/configs/constants.php');
|
||||||
require_once(dirname(__FILE__).'/AirtimeIni.php');
|
require_once(dirname(__FILE__).'/AirtimeIni.php');
|
||||||
|
|
||||||
if(exec("whoami") != "root"){
|
if(exec("whoami") != "root"){
|
||||||
|
@ -87,9 +89,13 @@ if (strcmp($version, "1.9.0") < 0){
|
||||||
//set the new version in the database.
|
//set the new version in the database.
|
||||||
$sql = "DELETE FROM cc_pref WHERE keystr = 'system_version'";
|
$sql = "DELETE FROM cc_pref WHERE keystr = 'system_version'";
|
||||||
$CC_DBC->query($sql);
|
$CC_DBC->query($sql);
|
||||||
$sql = "INSERT INTO cc_pref (keystr, valstr) VALUES ('system_version', '1.9.0-devel')";
|
|
||||||
|
$newVersion = AIRTIME_VERSION;
|
||||||
|
$sql = "INSERT INTO cc_pref (keystr, valstr) VALUES ('system_version', '$newVersion')";
|
||||||
$CC_DBC->query($sql);
|
$CC_DBC->query($sql);
|
||||||
|
|
||||||
|
echo PHP_EOL."*** Updating Api Client ***".PHP_EOL;
|
||||||
|
passthru("python ".__DIR__."/../../python_apps/api_clients/install/api_client_install.py");
|
||||||
|
|
||||||
echo PHP_EOL."*** Updating Pypo ***".PHP_EOL;
|
echo PHP_EOL."*** Updating Pypo ***".PHP_EOL;
|
||||||
passthru("python ".__DIR__."/../../python_apps/pypo/install/pypo-install.py");
|
passthru("python ".__DIR__."/../../python_apps/pypo/install/pypo-install.py");
|
||||||
|
|
|
@ -321,7 +321,7 @@ class AirtimeInstall{
|
||||||
INSERT INTO cc_country (isocode, name) VALUES ('ZWE', 'Zimbabwe ');";
|
INSERT INTO cc_country (isocode, name) VALUES ('ZWE', 'Zimbabwe ');";
|
||||||
|
|
||||||
echo "* Inserting data into country table".PHP_EOL;
|
echo "* Inserting data into country table".PHP_EOL;
|
||||||
execSqlQuery($sql);
|
Airtime190Upgrade::execSqlQuery($sql);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,7 +420,7 @@ class AirtimeIni{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function upgradeConfigFiles(){
|
public static function upgradeConfigFiles(){
|
||||||
|
|
||||||
$configFiles = array(AirtimeIni::CONF_FILE_AIRTIME,
|
$configFiles = array(AirtimeIni::CONF_FILE_AIRTIME,
|
||||||
AirtimeIni::CONF_FILE_PYPO,
|
AirtimeIni::CONF_FILE_PYPO,
|
||||||
|
@ -443,7 +443,7 @@ class AirtimeIni{
|
||||||
* This function creates the /etc/airtime configuration folder
|
* This function creates the /etc/airtime configuration folder
|
||||||
* and copies the default config files to it.
|
* and copies the default config files to it.
|
||||||
*/
|
*/
|
||||||
function CreateIniFiles()
|
public static function CreateIniFiles()
|
||||||
{
|
{
|
||||||
if (!file_exists("/etc/airtime/")){
|
if (!file_exists("/etc/airtime/")){
|
||||||
if (!mkdir("/etc/airtime/", 0755, true)){
|
if (!mkdir("/etc/airtime/", 0755, true)){
|
||||||
|
@ -474,7 +474,9 @@ class AirtimeIni{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function InstallAirtimePhpServerCode($phpDir)
|
class Airtime190Upgrade{
|
||||||
|
|
||||||
|
public static function InstallAirtimePhpServerCode($phpDir)
|
||||||
{
|
{
|
||||||
|
|
||||||
$AIRTIME_SRC = realpath(__DIR__.'/../../../airtime_mvc');
|
$AIRTIME_SRC = realpath(__DIR__.'/../../../airtime_mvc');
|
||||||
|
@ -484,7 +486,7 @@ function InstallAirtimePhpServerCode($phpDir)
|
||||||
exec("cp -R ".$AIRTIME_SRC."/* ".$phpDir);
|
exec("cp -R ".$AIRTIME_SRC."/* ".$phpDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
function CopyUtils()
|
public static function CopyUtils()
|
||||||
{
|
{
|
||||||
$utilsSrc = __DIR__."/../../../utils";
|
$utilsSrc = __DIR__."/../../../utils";
|
||||||
|
|
||||||
|
@ -496,25 +498,25 @@ function CopyUtils()
|
||||||
/* Removes pypo, media-monitor, show-recorder and utils from system. These will
|
/* Removes pypo, media-monitor, show-recorder and utils from system. These will
|
||||||
* be reinstalled by the main airtime-upgrade script.
|
* be reinstalled by the main airtime-upgrade script.
|
||||||
*/
|
*/
|
||||||
function UninstallBinaries()
|
public static function UninstallBinaries()
|
||||||
{
|
{
|
||||||
echo "* Removing Airtime binaries from ".CONF_DIR_BINARIES.PHP_EOL;
|
echo "* Removing Airtime binaries from ".CONF_DIR_BINARIES.PHP_EOL;
|
||||||
exec('rm -rf "'.CONF_DIR_BINARIES.'"');
|
exec('rm -rf "'.CONF_DIR_BINARIES.'"');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function removeOldAirtimeImport(){
|
public static function removeOldAirtimeImport(){
|
||||||
exec('rm -f "/usr/bin/airtime-import"');
|
exec('rm -f "/usr/bin/airtime-import"');
|
||||||
exec('rm -f "/usr/lib/airtime/utils/airtime-import.php"');
|
exec('rm -f "/usr/lib/airtime/utils/airtime-import.php"');
|
||||||
exec('rm -rf "/usr/lib/airtime/utils/airtime-import"');
|
exec('rm -rf "/usr/lib/airtime/utils/airtime-import"');
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateAirtimeImportSymLink(){
|
public static function updateAirtimeImportSymLink(){
|
||||||
$dir = "/usr/lib/airtime/utils/airtime-import/airtime-import";
|
$dir = "/usr/lib/airtime/utils/airtime-import/airtime-import";
|
||||||
exec("ln -s $dir /usr/bin/airtime-import");
|
exec("ln -s $dir /usr/bin/airtime-import");
|
||||||
}
|
}
|
||||||
|
|
||||||
function execSqlQuery($sql){
|
public static function execSqlQuery($sql){
|
||||||
global $CC_DBC;
|
global $CC_DBC;
|
||||||
|
|
||||||
$result = $CC_DBC->query($sql);
|
$result = $CC_DBC->query($sql);
|
||||||
|
@ -526,7 +528,7 @@ function execSqlQuery($sql){
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function connectToDatabase(){
|
public static function connectToDatabase(){
|
||||||
global $CC_DBC, $CC_CONFIG;
|
global $CC_DBC, $CC_CONFIG;
|
||||||
|
|
||||||
$values = parse_ini_file('/etc/airtime/airtime.conf', true);
|
$values = parse_ini_file('/etc/airtime/airtime.conf', true);
|
||||||
|
@ -544,18 +546,18 @@ function connectToDatabase(){
|
||||||
/* Old database had a "fullpath" column that stored the absolute path of each track. We have to
|
/* Old database had a "fullpath" column that stored the absolute path of each track. We have to
|
||||||
* change it so that the "fullpath" column has path relative to the "directory" column.
|
* change it so that the "fullpath" column has path relative to the "directory" column.
|
||||||
*/
|
*/
|
||||||
function installMediaMonitor($values){
|
public static function installMediaMonitor($values){
|
||||||
|
|
||||||
/* Handle Database Changes. */
|
/* Handle Database Changes. */
|
||||||
$stor_dir = realpath($values['general']['base_files_dir']."/stor")."/";
|
$stor_dir = realpath($values['general']['base_files_dir']."/stor")."/";
|
||||||
echo "* Inserting stor directory location $stor_dir into music_dirs table".PHP_EOL;
|
echo "* Inserting stor directory location $stor_dir into music_dirs table".PHP_EOL;
|
||||||
$sql = "UPDATE cc_music_dirs SET directory='$stor_dir' WHERE type='stor'";
|
$sql = "UPDATE cc_music_dirs SET directory='$stor_dir' WHERE type='stor'";
|
||||||
echo $sql.PHP_EOL;
|
echo $sql.PHP_EOL;
|
||||||
execSqlQuery($sql);
|
Airtime190Upgrade::execSqlQuery($sql);
|
||||||
|
|
||||||
$sql = "SELECT id FROM cc_music_dirs WHERE type='stor'";
|
$sql = "SELECT id FROM cc_music_dirs WHERE type='stor'";
|
||||||
echo $sql.PHP_EOL;
|
echo $sql.PHP_EOL;
|
||||||
$rows = execSqlQuery($sql);
|
$rows = Airtime190Upgrade::execSqlQuery($sql);
|
||||||
|
|
||||||
echo "Creating media-monitor log file";
|
echo "Creating media-monitor log file";
|
||||||
mkdir("/var/log/airtime/media-monitor/", 755, true);
|
mkdir("/var/log/airtime/media-monitor/", 755, true);
|
||||||
|
@ -566,6 +568,8 @@ function installMediaMonitor($values){
|
||||||
echo "Could not copy media-monitor.cfg to /etc/airtime/. Exiting.";
|
echo "Could not copy media-monitor.cfg to /etc/airtime/. Exiting.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AirtimeIni::UpdateIniValue(AirtimeIni::CONF_FILE_MEDIAMONITOR, "api_key", $values["general"]["api_key"]);
|
||||||
|
|
||||||
echo "Reorganizing files in stor directory";
|
echo "Reorganizing files in stor directory";
|
||||||
$mediaMonitorUpgradePath = realpath(__DIR__."/../../../python_apps/media-monitor/media-monitor-upgrade.py");
|
$mediaMonitorUpgradePath = realpath(__DIR__."/../../../python_apps/media-monitor/media-monitor-upgrade.py");
|
||||||
exec("su -c \"python $mediaMonitorUpgradePath\"", $output);
|
exec("su -c \"python $mediaMonitorUpgradePath\"", $output);
|
||||||
|
@ -578,9 +582,12 @@ function installMediaMonitor($values){
|
||||||
$absPathOld = pg_escape_string($pair[0]);
|
$absPathOld = pg_escape_string($pair[0]);
|
||||||
$sql = "UPDATE cc_files SET filepath = '$relPathNew', directory=1 WHERE filepath = '$absPathOld'";
|
$sql = "UPDATE cc_files SET filepath = '$relPathNew', directory=1 WHERE filepath = '$absPathOld'";
|
||||||
echo $sql.PHP_EOL;
|
echo $sql.PHP_EOL;
|
||||||
execSqlQuery($sql);
|
Airtime190Upgrade::execSqlQuery($sql);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
AirtimeInstall::CreateZendPhpLogFile();
|
AirtimeInstall::CreateZendPhpLogFile();
|
||||||
|
@ -622,19 +629,19 @@ foreach ($pathnames as $pn){
|
||||||
/* update Airtime Server PHP files */
|
/* update Airtime Server PHP files */
|
||||||
$values = parse_ini_file(AirtimeIni::CONF_FILE_AIRTIME, true);
|
$values = parse_ini_file(AirtimeIni::CONF_FILE_AIRTIME, true);
|
||||||
$phpDir = $values['general']['airtime_dir'];
|
$phpDir = $values['general']['airtime_dir'];
|
||||||
InstallAirtimePhpServerCode($phpDir);
|
Airtime190Upgrade::InstallAirtimePhpServerCode($phpDir);
|
||||||
|
|
||||||
/* update utils (/usr/lib/airtime) folder */
|
/* update utils (/usr/lib/airtime) folder */
|
||||||
UninstallBinaries();
|
Airtime190Upgrade::UninstallBinaries();
|
||||||
CopyUtils();
|
Airtime190Upgrade::CopyUtils();
|
||||||
|
|
||||||
/* James made a new airtime-import script, lets remove the old airtime-import php script,
|
/* James made a new airtime-import script, lets remove the old airtime-import php script,
|
||||||
*install the new airtime-import.py script and update the /usr/bin/symlink.
|
*install the new airtime-import.py script and update the /usr/bin/symlink.
|
||||||
*/
|
*/
|
||||||
removeOldAirtimeImport();
|
Airtime190Upgrade::removeOldAirtimeImport();
|
||||||
updateAirtimeImportSymLink();
|
Airtime190Upgrade::updateAirtimeImportSymLink();
|
||||||
|
|
||||||
connectToDatabase();
|
Airtime190Upgrade::connectToDatabase();
|
||||||
|
|
||||||
if(AirtimeInstall::DbTableExists('doctrine_migration_versions') === false) {
|
if(AirtimeInstall::DbTableExists('doctrine_migration_versions') === false) {
|
||||||
$migrations = array('20110312121200', '20110331111708', '20110402164819', '20110406182005');
|
$migrations = array('20110312121200', '20110331111708', '20110402164819', '20110406182005');
|
||||||
|
@ -652,7 +659,7 @@ AirtimeInstall::InsertCountryDataIntoDatabase();
|
||||||
/* create cron file for phone home stat */
|
/* create cron file for phone home stat */
|
||||||
AirtimeInstall::CreateCronFile();
|
AirtimeInstall::CreateCronFile();
|
||||||
|
|
||||||
installMediaMonitor($values);
|
Airtime190Upgrade::installMediaMonitor($values);
|
||||||
|
|
||||||
AirtimeIni::upgradeConfigFiles();
|
AirtimeIni::upgradeConfigFiles();
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from configobj import ConfigObj
|
||||||
|
|
||||||
|
class AirtimeMediaConfig:
|
||||||
|
|
||||||
|
MODE_CREATE = "create"
|
||||||
|
MODE_MODIFY = "modify"
|
||||||
|
MODE_MOVED = "moved"
|
||||||
|
MODE_DELETE = "delete"
|
||||||
|
|
||||||
|
def __init__(self, logger):
|
||||||
|
|
||||||
|
# loading config file
|
||||||
|
try:
|
||||||
|
config = ConfigObj('/etc/airtime/media-monitor.cfg')
|
||||||
|
self.cfg = config
|
||||||
|
except Exception, e:
|
||||||
|
logger.info('Error loading config: ', e)
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
|
self.storage_directory = None
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,243 @@
|
||||||
|
import os
|
||||||
|
import grp
|
||||||
|
import pwd
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from subprocess import Popen, PIPE
|
||||||
|
from airtimemetadata import AirtimeMetadata
|
||||||
|
|
||||||
|
class MediaMonitorCommon:
|
||||||
|
|
||||||
|
timestamp_file = "/var/tmp/airtime/last_index"
|
||||||
|
|
||||||
|
def __init__(self, airtime_config):
|
||||||
|
self.supported_file_formats = ['mp3', 'ogg']
|
||||||
|
self.logger = logging.getLogger()
|
||||||
|
self.config = airtime_config
|
||||||
|
self.md_manager = AirtimeMetadata()
|
||||||
|
|
||||||
|
def is_parent_directory(self, filepath, directory):
|
||||||
|
filepath = os.path.normpath(filepath)
|
||||||
|
directory = os.path.normpath(directory)
|
||||||
|
return (directory == filepath[0:len(directory)])
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
#check if file is readable by "nobody"
|
||||||
|
def has_correct_permissions(self, filepath):
|
||||||
|
#drop root permissions and become "nobody"
|
||||||
|
os.seteuid(65534)
|
||||||
|
|
||||||
|
try:
|
||||||
|
open(filepath)
|
||||||
|
readable = True
|
||||||
|
except IOError:
|
||||||
|
self.logger.warn("File does not have correct permissions: '%s'", filepath)
|
||||||
|
readable = False
|
||||||
|
except Exception, e:
|
||||||
|
self.logger.error("Unexpected exception thrown: %s", e)
|
||||||
|
readable = False
|
||||||
|
finally:
|
||||||
|
#reset effective user to root
|
||||||
|
os.seteuid(0)
|
||||||
|
|
||||||
|
return readable
|
||||||
|
|
||||||
|
def set_needed_file_permissions(self, item, is_dir):
|
||||||
|
try:
|
||||||
|
omask = os.umask(0)
|
||||||
|
|
||||||
|
uid = pwd.getpwnam('www-data')[2]
|
||||||
|
gid = grp.getgrnam('www-data')[2]
|
||||||
|
|
||||||
|
os.chown(item, uid, gid)
|
||||||
|
|
||||||
|
if is_dir is True:
|
||||||
|
os.chmod(item, 02777)
|
||||||
|
else:
|
||||||
|
os.chmod(item, 0666)
|
||||||
|
|
||||||
|
except Exception, e:
|
||||||
|
self.logger.error("Failed to change file's owner/group/permissions. %s", e)
|
||||||
|
finally:
|
||||||
|
os.umask(omask)
|
||||||
|
|
||||||
|
|
||||||
|
#checks if path is a directory, and if it doesnt exist, then creates it.
|
||||||
|
#Otherwise prints error to log file.
|
||||||
|
def ensure_is_dir(self, directory):
|
||||||
|
try:
|
||||||
|
omask = os.umask(0)
|
||||||
|
if not os.path.exists(directory):
|
||||||
|
os.makedirs(directory, 02777)
|
||||||
|
elif not os.path.isdir(directory):
|
||||||
|
#path exists but it is a file not a directory!
|
||||||
|
self.logger.error("path %s exists, but it is not a directory!!!")
|
||||||
|
finally:
|
||||||
|
os.umask(omask)
|
||||||
|
|
||||||
|
#moves file from source to dest but also recursively removes the
|
||||||
|
#the source file's parent directories if they are now empty.
|
||||||
|
def move_file(self, source, dest):
|
||||||
|
|
||||||
|
try:
|
||||||
|
omask = os.umask(0)
|
||||||
|
os.rename(source, dest)
|
||||||
|
except Exception, e:
|
||||||
|
self.logger.error("failed to move file. %s", e)
|
||||||
|
finally:
|
||||||
|
os.umask(omask)
|
||||||
|
|
||||||
|
dir = os.path.dirname(source)
|
||||||
|
self.cleanup_empty_dirs(dir)
|
||||||
|
|
||||||
|
#keep moving up the file hierarchy and deleting parent
|
||||||
|
#directories until we hit a non-empty directory, or we
|
||||||
|
#hit the organize dir.
|
||||||
|
def cleanup_empty_dirs(self, dir):
|
||||||
|
if os.path.normpath(dir) != self.config.organize_directory:
|
||||||
|
if len(os.listdir(dir)) == 0:
|
||||||
|
os.rmdir(dir)
|
||||||
|
|
||||||
|
pdir = os.path.dirname(dir)
|
||||||
|
self.cleanup_empty_dirs(pdir)
|
||||||
|
|
||||||
|
|
||||||
|
#checks if path exists already in stor. If the path exists and the md5s are the
|
||||||
|
#same just overwrite.
|
||||||
|
def create_unique_filename(self, filepath, old_filepath):
|
||||||
|
|
||||||
|
try:
|
||||||
|
if(os.path.exists(filepath)):
|
||||||
|
self.logger.info("Path %s exists", filepath)
|
||||||
|
|
||||||
|
self.logger.info("Checking if md5s are the same.")
|
||||||
|
md5_fp = self.md_manager.get_md5(filepath)
|
||||||
|
md5_ofp = self.md_manager.get_md5(old_filepath)
|
||||||
|
|
||||||
|
if(md5_fp == md5_ofp):
|
||||||
|
self.logger.info("Md5s are the same, moving to same filepath.")
|
||||||
|
return filepath
|
||||||
|
|
||||||
|
self.logger.info("Md5s aren't the same, appending to filepath.")
|
||||||
|
file_dir = os.path.dirname(filepath)
|
||||||
|
filename = os.path.basename(filepath).split(".")[0]
|
||||||
|
#will be in the format .ext
|
||||||
|
file_ext = os.path.splitext(filepath)[1]
|
||||||
|
i = 1;
|
||||||
|
while(True):
|
||||||
|
new_filepath = '%s/%s(%s)%s' % (file_dir, filename, i, file_ext)
|
||||||
|
self.logger.error("Trying %s", new_filepath)
|
||||||
|
|
||||||
|
if(os.path.exists(new_filepath)):
|
||||||
|
i = i+1;
|
||||||
|
else:
|
||||||
|
filepath = new_filepath
|
||||||
|
break
|
||||||
|
|
||||||
|
except Exception, e:
|
||||||
|
self.logger.error("Exception %s", e)
|
||||||
|
|
||||||
|
return filepath
|
||||||
|
|
||||||
|
#create path in /srv/airtime/stor/imported/[song-metadata]
|
||||||
|
def create_file_path(self, original_path, orig_md):
|
||||||
|
|
||||||
|
storage_directory = self.config.storage_directory
|
||||||
|
|
||||||
|
is_recorded_show = False
|
||||||
|
|
||||||
|
try:
|
||||||
|
#will be in the format .ext
|
||||||
|
file_ext = os.path.splitext(original_path)[1]
|
||||||
|
file_ext = file_ext.encode('utf-8')
|
||||||
|
|
||||||
|
path_md = ['MDATA_KEY_TITLE', 'MDATA_KEY_CREATOR', 'MDATA_KEY_SOURCE', 'MDATA_KEY_TRACKNUMBER', 'MDATA_KEY_BITRATE']
|
||||||
|
|
||||||
|
md = {}
|
||||||
|
for m in path_md:
|
||||||
|
if m not in orig_md:
|
||||||
|
md[m] = u'unknown'.encode('utf-8')
|
||||||
|
else:
|
||||||
|
#get rid of any "/" which will interfere with the filepath.
|
||||||
|
if isinstance(orig_md[m], basestring):
|
||||||
|
md[m] = orig_md[m].replace("/", "-")
|
||||||
|
else:
|
||||||
|
md[m] = orig_md[m]
|
||||||
|
|
||||||
|
if 'MDATA_KEY_TRACKNUMBER' in orig_md:
|
||||||
|
#make sure all track numbers are at least 2 digits long in the filepath.
|
||||||
|
md['MDATA_KEY_TRACKNUMBER'] = "%02d" % (int(md['MDATA_KEY_TRACKNUMBER']))
|
||||||
|
|
||||||
|
#format bitrate as 128kbps
|
||||||
|
md['MDATA_KEY_BITRATE'] = str(md['MDATA_KEY_BITRATE']/1000)+"kbps"
|
||||||
|
|
||||||
|
filepath = None
|
||||||
|
#file is recorded by Airtime
|
||||||
|
#/srv/airtime/stor/recorded/year/month/year-month-day-time-showname-bitrate.ext
|
||||||
|
if(md['MDATA_KEY_CREATOR'] == "AIRTIMERECORDERSOURCEFABRIC".encode('utf-8')):
|
||||||
|
#yyyy-mm-dd-hh-MM-ss
|
||||||
|
y = orig_md['MDATA_KEY_YEAR'].split("-")
|
||||||
|
filepath = '%s/%s/%s/%s/%s-%s-%s%s' % (storage_directory, "recorded".encode('utf-8'), y[0], y[1], orig_md['MDATA_KEY_YEAR'], md['MDATA_KEY_TITLE'], md['MDATA_KEY_BITRATE'], file_ext)
|
||||||
|
elif(md['MDATA_KEY_TRACKNUMBER'] == u'unknown'.encode('utf-8')):
|
||||||
|
filepath = '%s/%s/%s/%s/%s-%s%s' % (storage_directory, "imported".encode('utf-8'), md['MDATA_KEY_CREATOR'], md['MDATA_KEY_SOURCE'], md['MDATA_KEY_TITLE'], md['MDATA_KEY_BITRATE'], file_ext)
|
||||||
|
else:
|
||||||
|
filepath = '%s/%s/%s/%s/%s-%s-%s%s' % (storage_directory, "imported".encode('utf-8'), md['MDATA_KEY_CREATOR'], md['MDATA_KEY_SOURCE'], md['MDATA_KEY_TRACKNUMBER'], md['MDATA_KEY_TITLE'], md['MDATA_KEY_BITRATE'], file_ext)
|
||||||
|
|
||||||
|
filepath = self.create_unique_filename(filepath, original_path)
|
||||||
|
self.logger.info('Unique filepath: %s', filepath)
|
||||||
|
self.ensure_is_dir(os.path.dirname(filepath))
|
||||||
|
|
||||||
|
except Exception, e:
|
||||||
|
self.logger.error('Exception: %s', e)
|
||||||
|
|
||||||
|
return filepath
|
||||||
|
|
||||||
|
def execCommandAndReturnStdOut(self, command):
|
||||||
|
p = Popen(command, shell=True, stdout=PIPE)
|
||||||
|
stdout = p.communicate()[0]
|
||||||
|
if p.returncode != 0:
|
||||||
|
self.logger.warn("command \n%s\n return with a non-zero return value", command)
|
||||||
|
return stdout
|
||||||
|
|
||||||
|
def scan_dir_for_new_files(self, dir):
|
||||||
|
command = 'find "%s" -type f -iname "*.ogg" -o -iname "*.mp3" -readable' % dir.replace('"', '\\"')
|
||||||
|
self.logger.debug(command)
|
||||||
|
stdout = self.execCommandAndReturnStdOut(command)
|
||||||
|
stdout = unicode(stdout, "utf_8")
|
||||||
|
|
||||||
|
return stdout.splitlines()
|
||||||
|
|
||||||
|
def touch_index_file(self):
|
||||||
|
open(self.timestamp_file, "w")
|
||||||
|
|
||||||
|
def organize_new_file(self, pathname):
|
||||||
|
self.logger.info("Organizing new file: %s", pathname)
|
||||||
|
file_md = self.md_manager.get_md_from_file(pathname)
|
||||||
|
|
||||||
|
if file_md is not None:
|
||||||
|
#is_recorded_show = 'MDATA_KEY_CREATOR' in file_md and \
|
||||||
|
# file_md['MDATA_KEY_CREATOR'] == "AIRTIMERECORDERSOURCEFABRIC".encode('utf-8')
|
||||||
|
filepath = self.create_file_path(pathname, file_md)
|
||||||
|
|
||||||
|
self.logger.debug("Moving from %s to %s", pathname, filepath)
|
||||||
|
self.move_file(pathname, filepath)
|
||||||
|
else:
|
||||||
|
filepath = None
|
||||||
|
self.logger.warn("File %s, has invalid metadata", pathname)
|
||||||
|
|
||||||
|
return filepath
|
|
@ -0,0 +1,83 @@
|
||||||
|
<?php
|
||||||
|
/* THIS FILE IS NOT MEANT FOR CUSTOMIZING.
|
||||||
|
* PLEASE EDIT THE FOLLOWING TO CHANGE YOUR CONFIG:
|
||||||
|
* /etc/airtime/airtime.conf
|
||||||
|
* /etc/airtime/pypo.cfg
|
||||||
|
* /etc/airtime/recorder.cfg
|
||||||
|
*/
|
||||||
|
|
||||||
|
global $CC_CONFIG;
|
||||||
|
|
||||||
|
$CC_CONFIG = array(
|
||||||
|
// prefix for table names in the database
|
||||||
|
'tblNamePrefix' => 'cc_',
|
||||||
|
|
||||||
|
/* ================================================ storage configuration */
|
||||||
|
|
||||||
|
'soundcloud-client-id' => '2CLCxcSXYzx7QhhPVHN4A',
|
||||||
|
'soundcloud-client-secret' => 'pZ7beWmF06epXLHVUP1ufOg2oEnIt9XhE8l8xt0bBs',
|
||||||
|
|
||||||
|
"rootDir" => __DIR__."/../..",
|
||||||
|
'pearPath' => dirname(__FILE__).'/../../../airtime_mvc/library/pear',
|
||||||
|
'zendPath' => dirname(__FILE__).'/../../../airtime_mvc/library/Zend',
|
||||||
|
'phingPath' => dirname(__FILE__).'/../../../airtime_mvc/library/phing'
|
||||||
|
);
|
||||||
|
|
||||||
|
$CC_CONFIG = Config::loadConfig($CC_CONFIG);
|
||||||
|
|
||||||
|
// Add database table names
|
||||||
|
$CC_CONFIG['playListTable'] = $CC_CONFIG['tblNamePrefix'].'playlist';
|
||||||
|
$CC_CONFIG['playListContentsTable'] = $CC_CONFIG['tblNamePrefix'].'playlistcontents';
|
||||||
|
$CC_CONFIG['filesTable'] = $CC_CONFIG['tblNamePrefix'].'files';
|
||||||
|
$CC_CONFIG['accessTable'] = $CC_CONFIG['tblNamePrefix'].'access';
|
||||||
|
$CC_CONFIG['permTable'] = $CC_CONFIG['tblNamePrefix'].'perms';
|
||||||
|
$CC_CONFIG['sessTable'] = $CC_CONFIG['tblNamePrefix'].'sess';
|
||||||
|
$CC_CONFIG['subjTable'] = $CC_CONFIG['tblNamePrefix'].'subjs';
|
||||||
|
$CC_CONFIG['smembTable'] = $CC_CONFIG['tblNamePrefix'].'smemb';
|
||||||
|
$CC_CONFIG['prefTable'] = $CC_CONFIG['tblNamePrefix'].'pref';
|
||||||
|
$CC_CONFIG['scheduleTable'] = $CC_CONFIG['tblNamePrefix'].'schedule';
|
||||||
|
$CC_CONFIG['playListTimeView'] = $CC_CONFIG['tblNamePrefix'].'playlisttimes';
|
||||||
|
$CC_CONFIG['showSchedule'] = $CC_CONFIG['tblNamePrefix'].'show_schedule';
|
||||||
|
$CC_CONFIG['showDays'] = $CC_CONFIG['tblNamePrefix'].'show_days';
|
||||||
|
$CC_CONFIG['showTable'] = $CC_CONFIG['tblNamePrefix'].'show';
|
||||||
|
$CC_CONFIG['showInstances'] = $CC_CONFIG['tblNamePrefix'].'show_instances';
|
||||||
|
|
||||||
|
$CC_CONFIG['playListSequence'] = $CC_CONFIG['playListTable'].'_id';
|
||||||
|
$CC_CONFIG['filesSequence'] = $CC_CONFIG['filesTable'].'_id';
|
||||||
|
$CC_CONFIG['prefSequence'] = $CC_CONFIG['prefTable'].'_id';
|
||||||
|
$CC_CONFIG['permSequence'] = $CC_CONFIG['permTable'].'_id';
|
||||||
|
$CC_CONFIG['subjSequence'] = $CC_CONFIG['subjTable'].'_id';
|
||||||
|
$CC_CONFIG['smembSequence'] = $CC_CONFIG['smembTable'].'_id';
|
||||||
|
|
||||||
|
// Add libs to the PHP path
|
||||||
|
$old_include_path = get_include_path();
|
||||||
|
set_include_path('.'.PATH_SEPARATOR.$CC_CONFIG['pearPath']
|
||||||
|
.PATH_SEPARATOR.$CC_CONFIG['zendPath']
|
||||||
|
.PATH_SEPARATOR.$old_include_path);
|
||||||
|
|
||||||
|
class Config {
|
||||||
|
public static function loadConfig($CC_CONFIG) {
|
||||||
|
$values = parse_ini_file('/etc/airtime/airtime.conf', true);
|
||||||
|
|
||||||
|
// Name of the web server user
|
||||||
|
$CC_CONFIG['webServerUser'] = $values['general']['web_server_user'];
|
||||||
|
$CC_CONFIG['rabbitmq'] = $values['rabbitmq'];
|
||||||
|
|
||||||
|
$CC_CONFIG['baseUrl'] = $values['general']['base_url'];
|
||||||
|
$CC_CONFIG['basePort'] = $values['general']['base_port'];
|
||||||
|
|
||||||
|
// Database config
|
||||||
|
$CC_CONFIG['dsn']['username'] = $values['database']['dbuser'];
|
||||||
|
$CC_CONFIG['dsn']['password'] = $values['database']['dbpass'];
|
||||||
|
$CC_CONFIG['dsn']['hostspec'] = $values['database']['host'];
|
||||||
|
$CC_CONFIG['dsn']['phptype'] = 'pgsql';
|
||||||
|
$CC_CONFIG['dsn']['database'] = $values['database']['dbname'];
|
||||||
|
|
||||||
|
$CC_CONFIG['apiKey'] = array($values['general']['api_key']);
|
||||||
|
|
||||||
|
$CC_CONFIG['soundcloud-connection-retries'] = $values['soundcloud']['connection_retries'];
|
||||||
|
$CC_CONFIG['soundcloud-connection-wait'] = $values['soundcloud']['time_between_retries'];
|
||||||
|
|
||||||
|
return $CC_CONFIG;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
[loggers]
|
||||||
|
keys=root
|
||||||
|
|
||||||
|
[handlers]
|
||||||
|
keys=fileOutHandler
|
||||||
|
|
||||||
|
[formatters]
|
||||||
|
keys=simpleFormatter
|
||||||
|
|
||||||
|
[logger_root]
|
||||||
|
level=DEBUG
|
||||||
|
handlers=fileOutHandler
|
||||||
|
|
||||||
|
[handler_fileOutHandler]
|
||||||
|
class=logging.handlers.RotatingFileHandler
|
||||||
|
level=DEBUG
|
||||||
|
formatter=simpleFormatter
|
||||||
|
args=("/var/log/airtime/media-monitor/media-monitor.log", 'a', 1000000, 5,)
|
||||||
|
|
||||||
|
[formatter_simpleFormatter]
|
||||||
|
format=%(asctime)s %(levelname)s - [%(filename)s : %(funcName)s() : line %(lineno)d] - %(message)s
|
||||||
|
datefmt=
|
|
@ -0,0 +1 @@
|
||||||
|
bin_dir = "/usr/lib/airtime/api_clients"
|
|
@ -0,0 +1,25 @@
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import sys
|
||||||
|
from configobj import ConfigObj
|
||||||
|
|
||||||
|
def get_current_script_dir():
|
||||||
|
return os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
||||||
|
def copy_dir(src_dir, dest_dir):
|
||||||
|
if (os.path.exists(dest_dir)) and (dest_dir != "/"):
|
||||||
|
shutil.rmtree(dest_dir)
|
||||||
|
if not (os.path.exists(dest_dir)):
|
||||||
|
print "Copying directory "+os.path.realpath(src_dir)+" to "+os.path.realpath(dest_dir)
|
||||||
|
shutil.copytree(src_dir, dest_dir)
|
||||||
|
|
||||||
|
current_script_dir = get_current_script_dir()
|
||||||
|
|
||||||
|
"""load config file"""
|
||||||
|
try:
|
||||||
|
config = ConfigObj("%s/../api_client.cfg" % current_script_dir)
|
||||||
|
except Exception, e:
|
||||||
|
print 'Error loading config file: ', e
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
copy_dir("%s/../../api_clients"%current_script_dir, config["bin_dir"])
|
|
@ -0,0 +1,21 @@
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from configobj import ConfigObj
|
||||||
|
|
||||||
|
def remove_path(path):
|
||||||
|
os.system('rm -rf "%s"' % path)
|
||||||
|
|
||||||
|
def get_current_script_dir():
|
||||||
|
return os.path.dirname(os.path.realpath(__file__))
|
||||||
|
|
||||||
|
current_script_dir = get_current_script_dir()
|
||||||
|
|
||||||
|
"""load config file"""
|
||||||
|
try:
|
||||||
|
config = ConfigObj("%s/../api_client.cfg" % current_script_dir)
|
||||||
|
except Exception, e:
|
||||||
|
print 'Error loading config file: ', e
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
print "Removing API Client files"
|
||||||
|
remove_path(config["bin_dir"])
|
|
@ -30,6 +30,8 @@ except Exception, e:
|
||||||
|
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
logger.info("\n\n*** Media Monitor bootup ***\n\n")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
config = AirtimeMediaConfig(logger)
|
config = AirtimeMediaConfig(logger)
|
||||||
api_client = api_client.api_client_factory(config.cfg)
|
api_client = api_client.api_client_factory(config.cfg)
|
||||||
|
|
|
@ -8,7 +8,7 @@ virtualenv_bin="/usr/lib/airtime/airtime_virtualenv/bin/"
|
||||||
media_monitor_path="/usr/lib/airtime/media-monitor/"
|
media_monitor_path="/usr/lib/airtime/media-monitor/"
|
||||||
media_monitor_script="MediaMonitor.py"
|
media_monitor_script="MediaMonitor.py"
|
||||||
|
|
||||||
api_client_path="/usr/lib/airtime/pypo/"
|
api_client_path="/usr/lib/airtime/"
|
||||||
|
|
||||||
cd ${media_monitor_path}
|
cd ${media_monitor_path}
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@ class AirtimeMediaMonitorBootstrap():
|
||||||
|
|
||||||
for file_path in new_files:
|
for file_path in new_files:
|
||||||
if len(file_path.strip(" \n")) > 0:
|
if len(file_path.strip(" \n")) > 0:
|
||||||
new_and_modified_files.add(file_path[len(dir)+1:])
|
new_and_modified_files.add(file_path[len(dir):])
|
||||||
|
|
||||||
"""
|
"""
|
||||||
new_and_modified_files gives us a set of files that were either copied or modified
|
new_and_modified_files gives us a set of files that were either copied or modified
|
||||||
|
@ -114,15 +114,19 @@ class AirtimeMediaMonitorBootstrap():
|
||||||
self.mmc.touch_index_file()
|
self.mmc.touch_index_file()
|
||||||
|
|
||||||
for file_path in deleted_files_set:
|
for file_path in deleted_files_set:
|
||||||
self.pe.handle_removed_file(False, "%s/%s" % (dir, file_path))
|
self.pe.handle_removed_file(False, "%s%s" % (dir, file_path))
|
||||||
|
deleted_files_set.clear()
|
||||||
|
|
||||||
for file_path in new_files_set:
|
for file_path in new_files_set:
|
||||||
file_path = "%s/%s" % (dir, file_path)
|
file_path = "%s%s" % (dir, file_path)
|
||||||
if os.path.exists(file_path):
|
if os.path.exists(file_path):
|
||||||
self.pe.handle_created_file(False, os.path.basename(file_path), file_path)
|
self.pe.handle_created_file(False, os.path.basename(file_path), file_path)
|
||||||
|
|
||||||
|
new_files_set.clear()
|
||||||
|
|
||||||
for file_path in modified_files_set:
|
for file_path in modified_files_set:
|
||||||
file_path = "%s/%s" % (dir, file_path)
|
file_path = "%s%s" % (dir, file_path)
|
||||||
if os.path.exists(file_path):
|
if os.path.exists(file_path):
|
||||||
self.pe.handle_modified_file(False, os.path.basename(file_path), file_path)
|
self.pe.handle_modified_file(False, os.path.basename(file_path), file_path)
|
||||||
|
modified_files_set.clear()
|
||||||
|
|
||||||
|
|
|
@ -112,7 +112,7 @@ class AirtimeNotifier(Notifier):
|
||||||
self.logger.info("Adding file to ignore: %s ", filepath)
|
self.logger.info("Adding file to ignore: %s ", filepath)
|
||||||
mm.add_filepath_to_ignore(filepath)
|
mm.add_filepath_to_ignore(filepath)
|
||||||
|
|
||||||
if m['delete'] == "true":
|
if m['delete']:
|
||||||
self.logger.info("Deleting file: %s ", filepath)
|
self.logger.info("Deleting file: %s ", filepath)
|
||||||
os.unlink(filepath)
|
os.unlink(filepath)
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,9 @@ class AirtimeProcessEvent(ProcessEvent):
|
||||||
#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.
|
||||||
#Easy Tag creates this when changing metadata of ogg files.
|
#Easy Tag creates this when changing metadata of ogg files.
|
||||||
self.temp_files[pathname] = None
|
self.temp_files[pathname] = None
|
||||||
|
#file is being overwritten/replaced in GUI.
|
||||||
|
elif "goutputstream" in pathname:
|
||||||
|
self.temp_files[pathname] = None
|
||||||
elif self.mmc.is_audio_file(pathname):
|
elif self.mmc.is_audio_file(pathname):
|
||||||
if self.mmc.is_parent_directory(pathname, self.config.organize_directory):
|
if self.mmc.is_parent_directory(pathname, self.config.organize_directory):
|
||||||
#file was created in /srv/airtime/stor/organize. Need to process and move
|
#file was created in /srv/airtime/stor/organize. Need to process and move
|
||||||
|
|
|
@ -5,7 +5,7 @@ virtualenv_bin="/usr/lib/airtime/airtime_virtualenv/bin/"
|
||||||
|
|
||||||
ls_user="pypo"
|
ls_user="pypo"
|
||||||
export HOME="/var/tmp/airtime/pypo/"
|
export HOME="/var/tmp/airtime/pypo/"
|
||||||
api_client_path="/usr/lib/airtime/pypo/"
|
api_client_path="/usr/lib/airtime/"
|
||||||
ls_path="/usr/lib/airtime/pypo/bin/liquidsoap_bin/liquidsoap"
|
ls_path="/usr/lib/airtime/pypo/bin/liquidsoap_bin/liquidsoap"
|
||||||
ls_param="/usr/lib/airtime/pypo/bin/liquidsoap_scripts/ls_script.liq"
|
ls_param="/usr/lib/airtime/pypo/bin/liquidsoap_scripts/ls_script.liq"
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ pypo_user="pypo"
|
||||||
|
|
||||||
# Location of pypo_cli.py Python script
|
# Location of pypo_cli.py Python script
|
||||||
pypo_path="/usr/lib/airtime/pypo/bin/"
|
pypo_path="/usr/lib/airtime/pypo/bin/"
|
||||||
api_client_path="/usr/lib/airtime/pypo/"
|
api_client_path="/usr/lib/airtime/"
|
||||||
pypo_script="pypo-cli.py"
|
pypo_script="pypo-cli.py"
|
||||||
cd ${pypo_path}
|
cd ${pypo_path}
|
||||||
exec 2>&1
|
exec 2>&1
|
||||||
|
|
|
@ -96,7 +96,6 @@ try:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
copy_dir("%s/.."%current_script_dir, config["bin_dir"]+"/bin/")
|
copy_dir("%s/.."%current_script_dir, config["bin_dir"]+"/bin/")
|
||||||
copy_dir("%s/../../api_clients"%current_script_dir, config["bin_dir"]+"/api_clients/")
|
|
||||||
|
|
||||||
print "Setting permissions"
|
print "Setting permissions"
|
||||||
os.system("chmod -R 755 "+config["bin_dir"])
|
os.system("chmod -R 755 "+config["bin_dir"])
|
||||||
|
|
|
@ -10,7 +10,7 @@ recorder_user="pypo"
|
||||||
recorder_path="/usr/lib/airtime/show-recorder/"
|
recorder_path="/usr/lib/airtime/show-recorder/"
|
||||||
recorder_script="recorder.py"
|
recorder_script="recorder.py"
|
||||||
|
|
||||||
api_client_path="/usr/lib/airtime/pypo/"
|
api_client_path="/usr/lib/airtime/"
|
||||||
cd ${recorder_path}
|
cd ${recorder_path}
|
||||||
|
|
||||||
exec 2>&1
|
exec 2>&1
|
||||||
|
|
|
@ -47,10 +47,10 @@ def copy_or_move_files_to(paths, dest, flag):
|
||||||
if( 'mp3' in ext or 'ogg' in ext ):
|
if( 'mp3' in ext or 'ogg' in ext ):
|
||||||
destfile = dest+os.path.basename(path)
|
destfile = dest+os.path.basename(path)
|
||||||
if(flag == 'copy'):
|
if(flag == 'copy'):
|
||||||
print "Copying %(src)s to %(dest)s....." % {'src':path, 'dest':destfile}
|
print "Copying %(src)s to %(dest)s..." % {'src':path, 'dest':destfile}
|
||||||
shutil.copy2(path, destfile)
|
shutil.copy2(path, destfile)
|
||||||
elif(flag == 'move'):
|
elif(flag == 'move'):
|
||||||
print "Moving %(src)s to %(dest)s....." % {'src':path, 'dest':destfile}
|
print "Moving %(src)s to %(dest)s..." % {'src':path, 'dest':destfile}
|
||||||
shutil.move(path, destfile)
|
shutil.move(path, destfile)
|
||||||
else:
|
else:
|
||||||
print "Cannot find file or path: %s" % path
|
print "Cannot find file or path: %s" % path
|
||||||
|
@ -95,7 +95,7 @@ def printHelp():
|
||||||
========================
|
========================
|
||||||
There are two ways to import audio files into Airtime:
|
There are two ways to import audio files into Airtime:
|
||||||
|
|
||||||
1) Copy or move files into the storage folder
|
1) Use airtime-import to copy or move files into the storage folder.
|
||||||
|
|
||||||
Copied or moved files will be placed into the folder:
|
Copied or moved files will be placed into the folder:
|
||||||
%s
|
%s
|
||||||
|
@ -103,12 +103,12 @@ There are two ways to import audio files into Airtime:
|
||||||
Files will be automatically organized into the structure
|
Files will be automatically organized into the structure
|
||||||
"Artist/Album/TrackNumber-TrackName-Bitrate.file_extension".
|
"Artist/Album/TrackNumber-TrackName-Bitrate.file_extension".
|
||||||
|
|
||||||
2) Add a folder to the Airtime library("watch" a folder)
|
2) Use airtime-import to add a folder to the Airtime library ("watch" a folder).
|
||||||
|
|
||||||
All the files in the watched folder will be imported to Airtime and the
|
All the files in the watched folder will be imported to Airtime and the
|
||||||
folder will be monitored to automatically detect any changes. Hence any
|
folder will be monitored to automatically detect any changes. Hence any
|
||||||
changes done in the folder(add, delete, edit a file) will trigger
|
changes done in the folder(add, delete, edit a file) will trigger
|
||||||
updates in Airtime libarary.
|
updates in Airtime library.
|
||||||
""" % storage_dir
|
""" % storage_dir
|
||||||
parser.print_help()
|
parser.print_help()
|
||||||
print ""
|
print ""
|
||||||
|
@ -117,7 +117,7 @@ def CopyAction(option, opt, value, parser):
|
||||||
errorIfMultipleOption(parser.rargs)
|
errorIfMultipleOption(parser.rargs)
|
||||||
stor = helper_get_stor_dir()
|
stor = helper_get_stor_dir()
|
||||||
if(stor is None):
|
if(stor is None):
|
||||||
exit("Unable to connect to the server.")
|
exit("Unable to connect to the Airtime server.")
|
||||||
dest = stor+"organize/"
|
dest = stor+"organize/"
|
||||||
copy_or_move_files_to(parser.rargs, dest, 'copy')
|
copy_or_move_files_to(parser.rargs, dest, 'copy')
|
||||||
|
|
||||||
|
@ -125,16 +125,16 @@ def MoveAction(option, opt, value, parser):
|
||||||
errorIfMultipleOption(parser.rargs)
|
errorIfMultipleOption(parser.rargs)
|
||||||
stor = helper_get_stor_dir()
|
stor = helper_get_stor_dir()
|
||||||
if(stor is None):
|
if(stor is None):
|
||||||
exit("Unable to connect to the server.")
|
exit("Unable to connect to the Airtime server.")
|
||||||
dest = stor+"organize/"
|
dest = stor+"organize/"
|
||||||
copy_or_move_files_to(parser.rargs, dest, 'move')
|
copy_or_move_files_to(parser.rargs, dest, 'move')
|
||||||
|
|
||||||
def WatchAddAction(option, opt, value, parser):
|
def WatchAddAction(option, opt, value, parser):
|
||||||
errorIfMultipleOption(parser.rargs)
|
errorIfMultipleOption(parser.rargs)
|
||||||
if(len(parser.rargs) > 1):
|
if(len(parser.rargs) > 1):
|
||||||
raise OptionValueError("Too many arguments. This option need exactly one argument.")
|
raise OptionValueError("Too many arguments. This option requires exactly one argument.")
|
||||||
elif(len(parser.rargs) == 0 ):
|
elif(len(parser.rargs) == 0 ):
|
||||||
raise OptionValueError("No argument found. This option need exactly one argument.")
|
raise OptionValueError("No argument found. This option requires exactly one argument.")
|
||||||
path = parser.rargs[0]
|
path = parser.rargs[0]
|
||||||
if(os.path.isdir(path)):
|
if(os.path.isdir(path)):
|
||||||
res = api_client.add_watched_dir(path)
|
res = api_client.add_watched_dir(path)
|
||||||
|
@ -144,17 +144,17 @@ def WatchAddAction(option, opt, value, parser):
|
||||||
if(res['msg']['code'] == 0):
|
if(res['msg']['code'] == 0):
|
||||||
print "%s added to watched folder list successfully" % path
|
print "%s added to watched folder list successfully" % path
|
||||||
else:
|
else:
|
||||||
print "Adding a watched folder failed. : %s" % res['msg']['error']
|
print "Adding a watched folder failed: %s" % res['msg']['error']
|
||||||
else:
|
else:
|
||||||
print "Given path is not a directory: %s" % path
|
print "Given path is not a directory: %s" % path
|
||||||
|
|
||||||
def WatchListAction(option, opt, value, parser):
|
def WatchListAction(option, opt, value, parser):
|
||||||
errorIfMultipleOption(parser.rargs)
|
errorIfMultipleOption(parser.rargs)
|
||||||
if(len(parser.rargs) > 0):
|
if(len(parser.rargs) > 0):
|
||||||
raise OptionValueError("This option doesn't take any argument.")
|
raise OptionValueError("This option doesn't take any arguments.")
|
||||||
res = api_client.list_all_watched_dirs()
|
res = api_client.list_all_watched_dirs()
|
||||||
if(res is None):
|
if(res is None):
|
||||||
exit("Unable to connect to the server.")
|
exit("Unable to connect to the Airtime server.")
|
||||||
dirs = res["dirs"].items()
|
dirs = res["dirs"].items()
|
||||||
# there will be always 1 which is storage folder
|
# there will be always 1 which is storage folder
|
||||||
if(len(dirs) == 1):
|
if(len(dirs) == 1):
|
||||||
|
@ -167,21 +167,21 @@ def WatchListAction(option, opt, value, parser):
|
||||||
def WatchRemoveAction(option, opt, value, parser):
|
def WatchRemoveAction(option, opt, value, parser):
|
||||||
errorIfMultipleOption(parser.rargs)
|
errorIfMultipleOption(parser.rargs)
|
||||||
if(len(parser.rargs) > 1):
|
if(len(parser.rargs) > 1):
|
||||||
raise OptionValueError("Too many arguments. This option need exactly one argument.")
|
raise OptionValueError("Too many arguments. This option requires exactly one argument.")
|
||||||
elif(len(parser.rargs) == 0 ):
|
elif(len(parser.rargs) == 0 ):
|
||||||
raise OptionValueError("No argument found. This option need exactly one argument.")
|
raise OptionValueError("No argument found. This option requires exactly one argument.")
|
||||||
path = parser.rargs[0]
|
path = parser.rargs[0]
|
||||||
if(os.path.isdir(path)):
|
if(os.path.isdir(path)):
|
||||||
res = api_client.remove_watched_dir(path)
|
res = api_client.remove_watched_dir(path)
|
||||||
if(res is None):
|
if(res is None):
|
||||||
exit("Unable to connect to the server.")
|
exit("Unable to connect to the Airtime server.")
|
||||||
# sucess
|
# sucess
|
||||||
if(res['msg']['code'] == 0):
|
if(res['msg']['code'] == 0):
|
||||||
print "%s removed from watched folder list successfully" % path
|
print "%s removed from watch folder list successfully." % path
|
||||||
else:
|
else:
|
||||||
print "Removing a watched folder failed. : %s" % res['msg']['error']
|
print "Removing the watch folder failed: %s" % res['msg']['error']
|
||||||
else:
|
else:
|
||||||
print "Given path is not a directory: %s" % path
|
print "The given path is not a directory: %s" % path
|
||||||
|
|
||||||
def StorageSetAction(option, opt, value, parser):
|
def StorageSetAction(option, opt, value, parser):
|
||||||
bypass = False
|
bypass = False
|
||||||
|
@ -199,38 +199,38 @@ def StorageSetAction(option, opt, value, parser):
|
||||||
confirm = raw_input("Are you sure you want to change the storage direcory? (y/N)")
|
confirm = raw_input("Are you sure you want to change the storage direcory? (y/N)")
|
||||||
confirm = confirm or 'N'
|
confirm = confirm or 'N'
|
||||||
while(confirm not in possibleInput):
|
while(confirm not in possibleInput):
|
||||||
print "Not an acceptable input: %s" % confirm
|
print "Not an acceptable input: %s\n" % confirm
|
||||||
confirm = raw_input("Are you sure you want to change the storage direcory? (y/N) ")
|
confirm = raw_input("Are you sure you want to change the storage direcory? (y/N) ")
|
||||||
confirm = confirm or 'N'
|
confirm = confirm or 'N'
|
||||||
if(confirm == 'n' or confirm =='N'):
|
if(confirm == 'n' or confirm =='N'):
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if(len(parser.rargs) > 1):
|
if(len(parser.rargs) > 1):
|
||||||
raise OptionValueError("Too many arguments. This option need exactly one argument.")
|
raise OptionValueError("Too many arguments. This option requires exactly one argument.")
|
||||||
elif(len(parser.rargs) == 0 ):
|
elif(len(parser.rargs) == 0 ):
|
||||||
raise OptionValueError("No argument found. This option need exactly one argument.")
|
raise OptionValueError("No argument found. This option requires exactly one argument.")
|
||||||
|
|
||||||
path = parser.rargs[0]
|
path = parser.rargs[0]
|
||||||
if(os.path.isdir(path)):
|
if(os.path.isdir(path)):
|
||||||
res = api_client.set_storage_dir(path)
|
res = api_client.set_storage_dir(path)
|
||||||
if(res is None):
|
if(res is None):
|
||||||
exit("Unable to connect to the server.")
|
exit("Unable to connect to the Airtime server.")
|
||||||
# sucess
|
# sucess
|
||||||
if(res['msg']['code'] == 0):
|
if(res['msg']['code'] == 0):
|
||||||
print "Successfully set storage folder to %s" % path
|
print "Successfully set storage folder to %s" % path
|
||||||
else:
|
else:
|
||||||
print "Setting storage folder to failed.: %s" % res['msg']['error']
|
print "Setting storage folder failed: %s" % res['msg']['error']
|
||||||
else:
|
else:
|
||||||
print "Given path is not a directory: %s" % path
|
print "The given path is not a directory: %s" % path
|
||||||
|
|
||||||
def StorageGetAction(option, opt, value, parser):
|
def StorageGetAction(option, opt, value, parser):
|
||||||
errorIfMultipleOption(parser.rargs)
|
errorIfMultipleOption(parser.rargs)
|
||||||
if(len(parser.rargs) > 0):
|
if(len(parser.rargs) > 0):
|
||||||
raise OptionValueError("This option doesn't take any argument.")
|
raise OptionValueError("This option does not take any arguments.")
|
||||||
print helper_get_stor_dir()
|
print helper_get_stor_dir()
|
||||||
|
|
||||||
usage = """[-c|--copy FILE/DIR [FILE/DIR...]] [-m|--move FILE/DIR [FILE/DIR...]]
|
usage = """[-c|--copy FILE/DIR [FILE/DIR...]] [-m|--move FILE/DIR [FILE/DIR...]]
|
||||||
[--watch-add DIR] [--watch-list] [--watch-remve DIR]
|
[--watch-add DIR] [--watch-list] [--watch-remove DIR]
|
||||||
[--storage-dir-set DIR] [--storage-dir-get]"""
|
[--storage-dir-set DIR] [--storage-dir-get]"""
|
||||||
|
|
||||||
parser = OptionParser(usage=usage, add_help_option=False)
|
parser = OptionParser(usage=usage, add_help_option=False)
|
||||||
|
|
Loading…
Reference in New Issue