Merge branch 'devel' of dev.sourcefabric.org:airtime into devel

Conflicts:
	utils/airtime-import/airtime-import.py
This commit is contained in:
James 2011-07-18 15:10:57 -04:00
commit e199c118af
11 changed files with 218 additions and 104 deletions

View file

@ -63,12 +63,15 @@ class LibraryController extends Zend_Controller_Action
$paramsPop = str_replace('#id#', $id, $params);
$paramsPop = str_replace('#type#', $type, $paramsPop);
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
$user = new User($userInfo->id);
$pl_sess = $this->pl_sess;
if($type === "au") {
if(isset($pl_sess->id)) {
$menu[] = array('action' => array('type' => 'ajax', 'url' => '/Playlist/add-item'.$params, 'callback' => 'window["setSPLContent"]'),
$menu[] = array('action' => array('type' => 'ajax', 'url' => '/Playlist/add-item'.$params, 'callback' => 'window["setSPLContent"]'),
'title' => 'Add to Playlist');
}
@ -85,9 +88,12 @@ class LibraryController extends Zend_Controller_Action
$menu[] = array('action' => array('type' => 'gourl', 'url' => $url),
'title' => 'Download');
$menu[] = array('action' => array('type' => 'fn',
'callback' => "window['confirmDeleteAudioClip']('$paramsPop')"),
'title' => 'Delete');
if ($user->isAdmin()) {
$menu[] = array('action' => array('type' => 'fn',
'callback' => "window['confirmDeleteAudioClip']('$paramsPop')"),
'title' => 'Delete');
}
}
else if($type === "pl") {
@ -121,32 +127,37 @@ class LibraryController extends Zend_Controller_Action
public function deleteAction()
{
$id = $this->_getParam('id');
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
$user = new User($userInfo->id);
if (!is_null($id)) {
$file = StoredFile::Recall($id);
if ($user->isAdmin()) {
if (PEAR::isError($file)) {
$this->view->message = $file->getMessage();
return;
}
else if(is_null($file)) {
$this->view->message = "file doesn't exist";
return;
if (!is_null($id)) {
$file = StoredFile::Recall($id);
if (PEAR::isError($file)) {
$this->view->message = $file->getMessage();
return;
}
else if(is_null($file)) {
$this->view->message = "file doesn't exist";
return;
}
$res = $file->delete();
if (PEAR::isError($res)) {
$this->view->message = $res->getMessage();
return;
}
else {
$data = array("filepath" => $file->getFilePath(), "delete" => $res);
RabbitMq::SendMessageToMediaMonitor("file_delete", $data);
}
}
$res = $file->delete();
if (PEAR::isError($res)) {
$this->view->message = $res->getMessage();
return;
}
else {
$data = array("filepath" => $file->getFilePath(), "delete" => $res);
RabbitMq::SendMessageToMediaMonitor("file_delete", $data);
}
$this->view->id = $id;
}
$this->view->id = $id;
}
public function contentsAction()

View file

@ -25,9 +25,9 @@ class NowplayingController extends Zend_Controller_Action
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
$user = new User($userInfo->id);
$form = new Application_Form_RegisterAirtime();
if ($request->isPost()) {
$form = new Application_Form_RegisterAirtime();
$values = $request->getPost();
if ($values["Publicise"] != 1){
Application_Model_Preference::SetSupportFeedback($values["SupportFeedback"]);
@ -64,6 +64,10 @@ class NowplayingController extends Zend_Controller_Action
//popup if previous page was login
if($refer_sses->referrer == 'login' && Application_Model_Nowplaying::ShouldShowPopUp()
&& !Application_Model_Preference::GetSupportFeedback() && $user->isAdmin()){
$form = new Application_Form_RegisterAirtime();
$logo = Application_Model_Preference::GetStationLogo();
if($logo){
$this->view->logoImg = $logo;

View file

@ -123,9 +123,10 @@ class PreferenceController extends Zend_Controller_Action
$chosen = $this->getRequest()->getParam("dir");
$element = $this->getRequest()->getParam("element");
$watched_dirs_form = new Application_Form_WatchedDirPreferences();
$watched_dirs_form->populate(array('storageFolder' => $chosen));
$res = MusicDir::setStorDir($chosen);
if($res['code'] != 0){
$watched_dirs_form->populate(array('storageFolder' => $chosen));
$watched_dirs_form->getElement($element)->setErrors(array($res['error']));
}
@ -137,9 +138,10 @@ class PreferenceController extends Zend_Controller_Action
$chosen = $this->getRequest()->getParam("dir");
$element = $this->getRequest()->getParam("element");
$watched_dirs_form = new Application_Form_WatchedDirPreferences();
$watched_dirs_form->populate(array('watchedFolder' => $chosen));
$res = MusicDir::addWatchedDir($chosen);
if($res['code'] != 0){
$watched_dirs_form->populate(array('watchedFolder' => $chosen));
$watched_dirs_form->getElement($element)->setErrors(array($res['error']));
}

View file

@ -40,7 +40,23 @@ class MusicDir {
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();
foreach ($show_instances as $show_instance_row) {
$temp_show = new ShowInstance($show_instance_row["instance_id"]);
$temp_show->updateScheduledTime();
}
RabbitMq::PushSchedule();
}
public static function addDir($p_path, $p_type)

View file

@ -341,18 +341,7 @@ class StoredFile {
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;
}
else {
return false;
}
return true;
}
/**

View file

@ -35,7 +35,7 @@ function deleteAudioClip(json) {
//callbacks called by jjmenu
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;
$.ajax({
url: url,

View file

@ -3,8 +3,9 @@
namespace DoctrineMigrations;
/*
update cc_files table to include to "directory" column as well as add foreign key relation to
cc_music_dirs table.
1) update cc_files table to include to "directory" column
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,
@ -14,21 +15,22 @@ class Version20110711161043 extends AbstractMigration
{
public function up(Schema $schema)
{
//CREATE the default value of "/srv/airtime/stor", this can be updated later in the upgrade script.
/* 1) update cc_files table to include to "directory" column */
$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', '');");
$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->addColumn('directory', 'integer', array('default'=> 2));
$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)

View file

@ -8,7 +8,9 @@
//Pear classes.
set_include_path(__DIR__.'/../../airtime_mvc/library/pear' . PATH_SEPARATOR . get_include_path());
require_once('DB.php');
require_once(__DIR__.'/../../airtime_mvc/application/configs/constants.php');
require_once(dirname(__FILE__).'/AirtimeIni.php');
if(exec("whoami") != "root"){
@ -87,7 +89,9 @@ if (strcmp($version, "1.9.0") < 0){
//set the new version in the database.
$sql = "DELETE FROM cc_pref WHERE keystr = 'system_version'";
$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);

View file

@ -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;
}
}

View file

@ -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.
#Easy Tag creates this when changing metadata of ogg files.
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):
if self.mmc.is_parent_directory(pathname, self.config.organize_directory):
#file was created in /srv/airtime/stor/organize. Need to process and move

View file

@ -47,10 +47,10 @@ def copy_or_move_files_to(paths, dest, flag):
if( 'mp3' in ext or 'ogg' in ext ):
destfile = dest+os.path.basename(path)
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)
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)
else:
print "Cannot find file or path: %s" % path
@ -95,7 +95,7 @@ def printHelp():
========================
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:
%s
@ -103,12 +103,12 @@ There are two ways to import audio files into Airtime:
Files will be automatically organized into the structure
"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
folder will be monitored to automatically detect any changes. Hence any
changes done in the folder(add, delete, edit a file) will trigger
updates in Airtime libarary.
updates in Airtime library.
""" % storage_dir
parser.print_help()
print ""
@ -117,7 +117,7 @@ def CopyAction(option, opt, value, parser):
errorIfMultipleOption(parser.rargs)
stor = helper_get_stor_dir()
if(stor is None):
exit("Unable to connect to the server.")
exit("Unable to connect to the Airtime server.")
dest = stor+"organize/"
copy_or_move_files_to(parser.rargs, dest, 'copy')
@ -125,16 +125,16 @@ def MoveAction(option, opt, value, parser):
errorIfMultipleOption(parser.rargs)
stor = helper_get_stor_dir()
if(stor is None):
exit("Unable to connect to the server.")
exit("Unable to connect to the Airtime server.")
dest = stor+"organize/"
copy_or_move_files_to(parser.rargs, dest, 'move')
def WatchAddAction(option, opt, value, parser):
errorIfMultipleOption(parser.rargs)
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 ):
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]
if(os.path.isdir(path)):
res = api_client.add_watched_dir(path)
@ -144,17 +144,17 @@ def WatchAddAction(option, opt, value, parser):
if(res['msg']['code'] == 0):
print "%s added to watched folder list successfully" % path
else:
print "Adding a watched folder failed. : %s" % res['msg']['error']
print "Adding a watched folder failed: %s" % res['msg']['error']
else:
print "Given path is not a directory: %s" % path
def WatchListAction(option, opt, value, parser):
errorIfMultipleOption(parser.rargs)
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()
if(res is None):
exit("Unable to connect to the server.")
exit("Unable to connect to the Airtime server.")
dirs = res["dirs"].items()
# there will be always 1 which is storage folder
if(len(dirs) == 1):
@ -167,21 +167,21 @@ def WatchListAction(option, opt, value, parser):
def WatchRemoveAction(option, opt, value, parser):
errorIfMultipleOption(parser.rargs)
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 ):
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]
if(os.path.isdir(path)):
res = api_client.remove_watched_dir(path)
if(res is None):
exit("Unable to connect to the server.")
exit("Unable to connect to the Airtime server.")
# sucess
if(res['msg']['code'] == 0):
print "%s removed from watched folder list successfully" % path
print "%s removed from watch folder list successfully." % path
else:
print "Removing a watched folder failed. : %s" % res['msg']['error']
print "Removing the watch folder failed: %s" % res['msg']['error']
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):
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 = confirm or 'N'
while(confirm not in possibleInput):
print "Not an acceptable input: %s" % confirm
confirm = raw_input("Are you sure you want to change the storage direcory? (y/N)")
print "Not an acceptable input: %s\n" % confirm
confirm = raw_input("Are you sure you want to change the storage direcory? (y/N) ")
confirm = confirm or 'N'
if(confirm == 'n' or confirm =='N'):
sys.exit(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 ):
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]
if(os.path.isdir(path)):
res = api_client.set_storage_dir(path)
if(res is None):
exit("Unable to connect to the server.")
exit("Unable to connect to the Airtime server.")
# sucess
if(res['msg']['code'] == 0):
print "Successfully set storage folder to %s" % path
else:
print "Setting storage folder to failed.: %s" % res['msg']['error']
print "Setting storage folder failed: %s" % res['msg']['error']
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):
errorIfMultipleOption(parser.rargs)
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()
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]"""
parser = OptionParser(usage=usage, add_help_option=False)