Merge branch '2.5.x-installer' of https://github.com/sourcefabric/Airtime into 2.5.x-installer

This commit is contained in:
Duncan Sommerville 2015-03-18 10:12:58 -04:00
commit 0a3d8ea515
10 changed files with 469 additions and 844 deletions

View File

@ -466,7 +466,10 @@ for i in /etc/init/airtime*.template; do
mv $i ${i%.template}
done
#loudCmd "initctl reload-configuration"
set +e
loudCmd "initctl reload-configuration"
loudCmd "systemctl daemon-reload" #systemd hipsters
set -e
if [ ! -d /var/log/airtime ]; then
loud "\n-----------------------------------------------------"
@ -504,6 +507,9 @@ loud "\n-----------------------------------------------------"
loud " * Configuring PostgreSQL * "
loud "-----------------------------------------------------"
# Ensure postgres is running - It isn't after you install the postgres package on Ubuntu 15.04
loudCmd "service postgresql start"
setupAirtimePostgresUser() {
# here-doc to execute this block as postgres user
su postgres <<'EOF'

View File

@ -0,0 +1,69 @@
apache2
libapache2-mod-php5
php5
libzend-framework-php
php-pear
php5-gd
lsb-release
rabbitmq-server
postgresql
postgresql-client
php5-pgsql
python
python-virtualenv
python-pip
libsoundtouch-ocaml
libtaglib-ocaml
libao-ocaml
libmad-ocaml
ecasound
libportaudio2
libsamplerate0
patch
php5-curl
mpg123
icecast2
libcamomile-ocaml-data
libpulse0
vorbis-tools
lsb-release
lsof
vorbisgain
flac
vorbis-tools
pwgen
libfaad2
php-apc
lame
coreutils
liquidsoap
liquidsoap-plugin-alsa
liquidsoap-plugin-ao
liquidsoap-plugin-faad
liquidsoap-plugin-flac
liquidsoap-plugin-icecast
liquidsoap-plugin-lame
liquidsoap-plugin-mad
liquidsoap-plugin-ogg
liquidsoap-plugin-portaudio
liquidsoap-plugin-pulseaudio
liquidsoap-plugin-taglib
liquidsoap-plugin-voaacenc
liquidsoap-plugin-vorbis
silan
libopus0
sysvinit-utils

View File

@ -1,13 +0,0 @@
#!/bin/bash
#-------------------------------------------------------------------------------
# This script for a correct system environment for Airtime.
#
# Absolute path to this script
SCRIPT=`readlink -f $0`
# Absolute directory this script is in
SCRIPTPATH=`dirname $SCRIPT`
invokePwd=$PWD
cd $SCRIPTPATH
php -q airtime-check-system.php "$@" || exit 1

View File

@ -1,270 +0,0 @@
<?php
AirtimeCheck::ExitIfNotRoot();
date_default_timezone_set("UTC");
$sapi_type = php_sapi_name();
$showColor = !in_array("--no-color", $argv);
//detect if we are running via the command line
if (substr($sapi_type, 0, 3) == 'cli') {
//we are running from the command-line
$airtimeIni = AirtimeCheck::GetAirtimeConf();
$apiKey = $airtimeIni['general']['api_key'];
$baseUrl = $airtimeIni['general']['base_url'];
$base_port = $airtimeIni['general']['base_port'];
$base_dir = $airtimeIni['general']['base_dir'];
$status = AirtimeCheck::GetStatus($baseUrl, $base_port, $base_dir, $apiKey);
AirtimeCheck::PrintStatus($baseUrl, $base_port, $status);
//AirtimeCheck::PrintStatus($baseUrl, $status);
}
class AirtimeCheck {
private static $AIRTIME_STATUS_OK = true;
CONST UNKNOWN = "UNKNOWN";
/**
* Ensures that the user is running this PHP script with root
* permissions. If not running with root permissions, causes the
* script to exit.
*/
public static function ExitIfNotRoot()
{
// Need to check that we are superuser before running this.
$euid = posix_geteuid();
$user = exec('whoami');
if($euid != 0 && $user != "www-data"){
echo "Must be root user.\n";
exit(1);
}
}
public static function GetCpuInfo()
{
$command = "cat /proc/cpuinfo |grep -m 1 'model name' ";
exec($command, $output, $rv);
if ($rv != 0 || !isset($output[0]))
return self::UNKNOWN;
$choppedStr = explode(":", $output[0]);
if (!isset($choppedStr[1]))
return self::UNKNOWN;
$status = trim($choppedStr[1]);
return $status;
}
public static function GetAirtimeConf()
{
$ini = parse_ini_file("/etc/airtime/airtime.conf", true);
if ($ini === false){
echo "Error reading /etc/airtime/airtime.conf.".PHP_EOL;
exit;
}
return $ini;
}
public static function CheckOsTypeVersion(){
exec("lsb_release -ds", $output, $rv);
if ($rv != 0 || !isset($output[0])){
$os_string = self::UNKNOWN;
} else {
$os_string = $output[0];
}
unset($output);
// Figure out if 32 or 64 bit
exec("uname -m", $output, $rv);
if ($rv != 0 || !isset($output[0])){
$machine = self::UNKNOWN;
} else {
$machine = $output[0];
}
return $os_string." ".$machine;
}
public static function GetServerType($p_baseUrl, $p_basePort)
{
$headerInfo = get_headers("http://$p_baseUrl:$p_basePort",1);
if (!isset($headerInfo['Server'][0])) {
return self::UNKNOWN;
} else if (is_array($headerInfo['Server'])) {
return $headerInfo['Server'][0];
} else {
return $headerInfo['Server'];
}
}
public static function GetStatus($p_baseUrl, $p_basePort, $p_baseDir, $p_apiKey){
if ($p_baseDir == '/') {
$url = "http://$p_baseUrl:$p_basePort/api/status/format/json/api_key/%%api_key%%";
} else {
$url = "http://$p_baseUrl:$p_basePort/$p_baseDir"."api/status/format/json/api_key/%%api_key%%";
}
self::output_status("AIRTIME_STATUS_URL", $url);
$url = str_replace("%%api_key%%", $p_apiKey, $url);
$ch = curl_init($url);
curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
$data = curl_exec($ch);
//$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return $data;
}
public static function PrintStatus($p_baseUrl, $p_basePort, $p_status){
if ($p_status === false){
self::output_status("AIRTIME_SERVER_RESPONDING", "FAILED");
} else {
self::output_status("AIRTIME_SERVER_RESPONDING", "OK");
$p_status = json_decode($p_status);
if (isset($p_status->status)) {
$data = $p_status->status;
} else {
$data = array();
}
if (isset($data->platform)) {
self::output_status("KERNEL_VERSION", $data->platform->release);
self::output_status("MACHINE_ARCHITECTURE", $data->platform->machine);
self::output_status("TOTAL_MEMORY_MBYTES", $data->platform->memory);
self::output_status("TOTAL_SWAP_MBYTES", $data->platform->swap);
self::output_status("AIRTIME_VERSION", $data->airtime_version);
} else {
self::output_status("KERNEL_VERSION", "UNKNOWN");
self::output_status("MACHINE_ARCHITECTURE", "UNKNOWN");
self::output_status("TOTAL_MEMORY_MBYTES", "UNKNOWN");
self::output_status("TOTAL_SWAP_MBYTES", "UNKNOWN");
self::output_status("AIRTIME_VERSION", "UNKNOWN");
}
self::output_status("OS", self::CheckOsTypeVersion());
self::output_status("CPU", self::GetCpuInfo());
self::output_status("WEB_SERVER", self::GetServerType($p_baseUrl, $p_basePort));
if (isset($data->services)) {
$services = $data->services;
} else {
$services = array();
}
if (isset($services->pypo) && $services->pypo->process_id != "FAILED") {
self::output_status("PLAYOUT_ENGINE_PROCESS_ID", $data->services->pypo->process_id);
self::output_status("PLAYOUT_ENGINE_RUNNING_SECONDS", $data->services->pypo->uptime_seconds);
self::output_status("PLAYOUT_ENGINE_MEM_PERC", $data->services->pypo->memory_perc);
self::output_status("PLAYOUT_ENGINE_CPU_PERC", $data->services->pypo->cpu_perc);
} else {
self::output_status("PLAYOUT_ENGINE_PROCESS_ID", "FAILED");
self::output_status("PLAYOUT_ENGINE_RUNNING_SECONDS", "0");
self::output_status("PLAYOUT_ENGINE_MEM_PERC", "0%");
self::output_status("PLAYOUT_ENGINE_CPU_PERC", "0%");
$log = "/var/log/airtime/pypo/pypo.log";
self::show_log_file($log);
}
if (isset($services->liquidsoap) && $services->liquidsoap->process_id != "FAILED") {
self::output_status("LIQUIDSOAP_PROCESS_ID", $data->services->liquidsoap->process_id);
self::output_status("LIQUIDSOAP_RUNNING_SECONDS", $data->services->liquidsoap->uptime_seconds);
self::output_status("LIQUIDSOAP_MEM_PERC", $data->services->liquidsoap->memory_perc);
self::output_status("LIQUIDSOAP_CPU_PERC", $data->services->liquidsoap->cpu_perc);
} else {
self::output_status("LIQUIDSOAP_PROCESS_ID", "FAILED");
self::output_status("LIQUIDSOAP_RUNNING_SECONDS", "0");
self::output_status("LIQUIDSOAP_MEM_PERC", "0%");
self::output_status("LIQUIDSOAP_CPU_PERC", "0%");
$log = "/var/log/airtime/pypo-liquidsoap/ls_script.log";
self::show_log_file($log);
}
if (isset($services->media_monitor) && $services->media_monitor->process_id != "FAILED") {
self::output_status("MEDIA_MONITOR_PROCESS_ID", $data->services->media_monitor->process_id);
self::output_status("MEDIA_MONITOR_RUNNING_SECONDS", $data->services->media_monitor->uptime_seconds);
self::output_status("MEDIA_MONITOR_MEM_PERC", $data->services->media_monitor->memory_perc);
self::output_status("MEDIA_MONITOR_CPU_PERC", $data->services->media_monitor->cpu_perc);
} else {
self::output_status("MEDIA_MONITOR_PROCESS_ID", "FAILED");
self::output_status("MEDIA_MONITOR_RUNNING_SECONDS", "0");
self::output_status("MEDIA_MONITOR_MEM_PERC", "0%");
self::output_status("MEDIA_MONITOR_CPU_PERC", "0%");
$log = "/var/log/airtime/media-monitor/media-monitor.log";
self::show_log_file($log);
}
}
if (self::$AIRTIME_STATUS_OK){
self::output_comment("Your installation of Airtime looks OK!");
exit(0);
} else {
self::output_comment("There appears to be a problem with your Airtime installation.");
self::output_comment("Please visit http://wiki.sourcefabric.org/x/HABQ");
exit(1);
}
}
public static function show_log_file($log) {
self::output_comment("Check the log file $log");
self::output_comment("");
}
public static function output_comment($comment){
if (!is_array($comment)) {
$comment = array($comment);
}
foreach ($comment as $c) {
echo "-- $c".PHP_EOL;
}
}
public static function output_status($key, $value){
global $showColor;
$RED = "[0;31m";
$ORANGE = "[0;33m";
$GREEN = "[1;32m";
$color = $GREEN;
if ($value == "FAILED"){
$color = $RED;
self::$AIRTIME_STATUS_OK = false;
} else if ($value == "NOT MONITORED"){
$color = $ORANGE;
self::$AIRTIME_STATUS_OK = false;
}
if ($showColor)
echo sprintf("%-31s= %s", $key, self::term_color($value, $color)).PHP_EOL;
else
echo sprintf("%-31s= %s", $key, $value).PHP_EOL;
}
public static function term_color($text, $color){
if($color == ""){
$color = "[0m";
}
return chr(27)."$color$text".chr(27)."[0m";
}
}

View File

@ -1,21 +1,326 @@
#!/bin/bash
#!/usr/bin/python2 import sys
import os
import logging
from configobj import ConfigObj
from optparse import OptionParser, OptionValueError
from api_clients import api_client as apc
import json
import shutil
import commands
virtualenv_bin="/usr/lib/airtime/airtime_virtualenv/bin/"
. ${virtualenv_bin}activate
#sys.path.append('/usr/lib/airtime/media-monitor/mm2/')
from mm2.media.monitor.pure import is_file_supported
invokePwd=$PWD
# create logger
logger = logging.getLogger()
airtime_import_path="/usr/lib/airtime/utils/airtime-import/"
airtime_import_script="airtime-import.py"
# no logging
ch = logging.StreamHandler()
logging.disable(50)
api_client_path="/usr/lib/airtime/"
cd ${airtime_import_path}
# add ch to logger
logger.addHandler(ch)
if (os.geteuid() != 0):
print 'Must be a root user.'
sys.exit()
# loading config file
try:
config = ConfigObj('/etc/airtime/airtime.conf')
except Exception, e:
print('Error loading config file: %s', e)
sys.exit()
api_client = apc.AirtimeApiClient(config)
#helper functions
# copy or move files
# flag should be 'copy' or 'move'
def copy_or_move_files_to(paths, dest, flag):
try:
for path in paths:
if (path[0] == "/" or path[0] == "~"):
path = os.path.realpath(path)
else:
path = currentDir+path
path = apc.encode_to(path, 'utf-8')
dest = apc.encode_to(dest, 'utf-8')
if(os.path.exists(path)):
if(os.path.isdir(path)):
path = format_dir_string(path)
#construct full path
sub_path = []
for temp in os.listdir(path):
sub_path.append(path+temp)
copy_or_move_files_to(sub_path, dest, flag)
elif(os.path.isfile(path)):
#copy file to dest
if(is_file_supported(path)):
destfile = dest+os.path.basename(path)
if(flag == 'copy'):
print "Copying %(src)s to %(dest)s..." % {'src':path, 'dest':destfile}
shutil.copyfile(path, destfile)
elif(flag == 'move'):
print "Moving %(src)s to %(dest)s..." % {'src':path, 'dest':destfile}
shutil.move(path, destfile)
else:
print "Cannot find file or path: %s" % path
except Exception as e:
print "Error: ", e
def format_dir_string(path):
if(path[-1] != '/'):
path = path+'/'
return path
def helper_get_stor_dir():
try:
res = api_client.list_all_watched_dirs()
except Exception, e:
return res
if(res['dirs']['1'][-1] != '/'):
out = res['dirs']['1']+'/'
return out
else:
return res['dirs']['1']
def checkOtherOption(args):
for i in args:
if(i[0] == '-'):
return True
def errorIfMultipleOption(args, msg=''):
if(checkOtherOption(args)):
if(msg != ''):
raise OptionValueError(msg)
else:
raise OptionValueError("This option cannot be combined with other options")
def printHelp():
storage_dir = helper_get_stor_dir()
if(storage_dir is None):
storage_dir = "Unknown"
else:
storage_dir += "imported/"
print """
========================
Airtime Import Script
========================
There are two ways to import audio files into Airtime:
1) Use airtime-import to copy or move files into the storage folder.
Copied or moved files will be placed into the folder:
%s
Files will be automatically organized into the structure
"Artist/Album/TrackNumber-TrackName-Bitrate.file_extension".
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 library.
""" % storage_dir
parser.print_help()
print ""
def CopyAction(option, opt, value, parser):
errorIfMultipleOption(parser.rargs)
if(len(parser.rargs) == 0 ):
raise OptionValueError("No argument found. This option requires at least one argument.")
stor = helper_get_stor_dir()
if(stor is None):
print "Unable to connect to the Airtime server."
return
dest = stor+"organize/"
copy_or_move_files_to(parser.rargs, dest, 'copy')
def MoveAction(option, opt, value, parser):
errorIfMultipleOption(parser.rargs)
if(len(parser.rargs) == 0 ):
raise OptionValueError("No argument found. This option requires at least one argument.")
stor = helper_get_stor_dir()
if(stor is None):
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 requires exactly one argument.")
elif(len(parser.rargs) == 0 ):
raise OptionValueError("No argument found. This option requires exactly one argument.")
path = parser.rargs[0]
if (path[0] == "/" or path[0] == "~"):
path = os.path.realpath(path)
else:
path = currentDir+path
path = apc.encode_to(path, 'utf-8')
if(os.path.isdir(path)):
#os.chmod(path, 0765)
try:
res = api_client.add_watched_dir(path)
except Exception, e:
exit("Unable to connect to the server.")
# sucess
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 "This error most likely caused by wrong permissions"
print "Try fixing this error by chmodding the parent directory(ies)"
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 arguments.")
try:
res = api_client.list_all_watched_dirs()
except Exception, e:
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):
print "No watch folders found"
else:
for key, v in dirs:
if(key != '1'):
print v
def WatchRemoveAction(option, opt, value, parser):
errorIfMultipleOption(parser.rargs)
if(len(parser.rargs) > 1):
raise OptionValueError("Too many arguments. This option requires exactly one argument.")
elif(len(parser.rargs) == 0 ):
raise OptionValueError("No argument found. This option requires exactly one argument.")
path = parser.rargs[0]
if (path[0] == "/" or path[0] == "~"):
path = os.path.realpath(path)
else:
path = currentDir+path
path = apc.encode_to(path, 'utf-8')
if(os.path.isdir(path)):
try:
res = api_client.remove_watched_dir(path)
except Exception, e:
exit("Unable to connect to the Airtime server.")
# sucess
if(res['msg']['code'] == 0):
print "%s removed from watch folder list successfully." % path
else:
print "Removing the watch folder failed: %s" % res['msg']['error']
else:
print "The given path is not a directory: %s" % path
def StorageSetAction(option, opt, value, parser):
bypass = False
isF = '-f' in parser.rargs
isForce = '--force' in parser.rargs
if(isF or isForce ):
bypass = True
if(isF):
parser.rargs.remove('-f')
if(isForce):
parser.rargs.remove('--force')
if(not bypass):
errorIfMultipleOption(parser.rargs, "Only [-f] and [--force] option is allowed with this option.")
possibleInput = ['y','Y','n','N']
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\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 requires exactly one argument.")
elif(len(parser.rargs) == 0 ):
raise OptionValueError("No argument found. This option requires exactly one argument.")
path = parser.rargs[0]
if (path[0] == "/" or path[0] == "~"):
path = os.path.realpath(path)
else:
path = currentDir+path
path = apc.encode_to(path, 'utf-8')
if(os.path.isdir(path)):
try:
res = api_client.set_storage_dir(path)
except Exception, e:
exit("Unable to connect to the Airtime server.")
# success
if(res['msg']['code'] == 0):
print "Successfully set storage folder to %s" % path
else:
print "Setting storage folder failed: %s" % res['msg']['error']
else:
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 does not take any arguments.")
print helper_get_stor_dir()
class OptionValueError(RuntimeError):
def __init__(self, msg):
self.msg = msg
usage = """[-c|--copy FILE/DIR [FILE/DIR...]] [-m|--move FILE/DIR [FILE/DIR...]]
[--watch-add DIR] [--watch-list] [--watch-remove DIR]
[--storage-dir-set DIR] [--storage-dir-get]"""
parser = OptionParser(usage=usage, add_help_option=False)
parser.add_option('-c','--copy', action='callback', callback=CopyAction, metavar='FILE', help='Copy FILE(s) into the storage directory.\nYou can specify multiple files or directories.')
parser.add_option('-m','--move', action='callback', callback=MoveAction, metavar='FILE', help='Move FILE(s) into the storage directory.\nYou can specify multiple files or directories.')
parser.add_option('--watch-add', action='callback', callback=WatchAddAction, help='Add DIR to the watched folders list.')
parser.add_option('--watch-list', action='callback', callback=WatchListAction, help='Show the list of folders that are watched.')
parser.add_option('--watch-remove', action='callback', callback=WatchRemoveAction, help='Remove DIR from the watched folders list.')
parser.add_option('--storage-dir-set', action='callback', callback=StorageSetAction, help='Set storage dir to DIR.')
parser.add_option('--storage-dir-get', action='callback', callback=StorageGetAction, help='Show the current storage dir.')
parser.add_option('-h', '--help', dest='help', action='store_true', help='show this help message and exit')
# pop "--dir"
#sys.argv.pop(1)
# pop "invoked pwd"
currentDir = os.getcwd() #sys.argv.pop(1)+'/'
if('-l' in sys.argv or '--link' in sys.argv):
print "\nThe [-l][--link] option is deprecated. Please use the --watch-add option.\nTry 'airtime-import -h' for more detail.\n"
sys.exit()
if('-h' in sys.argv):
printHelp()
sys.exit()
if(len(sys.argv) == 1 or '-' not in sys.argv[1]):
printHelp()
sys.exit()
try:
(option, args) = parser.parse_args()
except Exception, e:
printHelp()
if hasattr(e, 'msg'):
print "Error: "+e.msg
else:
print "Error: ",e
sys.exit()
except SystemExit:
printHelp()
sys.exit()
if option.help:
printHelp()
sys.exit()
exec 2>&1
export PYTHONPATH=${api_client_path}
# Note the -u when calling python! we need it to get unbuffered binary stdout and stderr
exec python -u ${airtime_import_path}${airtime_import_script} --dir "$invokePwd" "$@"
# EOF

View File

@ -1,326 +0,0 @@
import sys
import os
import logging
from configobj import ConfigObj
from optparse import OptionParser, OptionValueError
from api_clients import api_client as apc
import json
import shutil
import commands
sys.path.append('/usr/lib/airtime/media-monitor/mm2/')
from media.monitor.pure import is_file_supported
# create logger
logger = logging.getLogger()
# no logging
ch = logging.StreamHandler()
logging.disable(50)
# add ch to logger
logger.addHandler(ch)
if (os.geteuid() != 0):
print 'Must be a root user.'
sys.exit()
# loading config file
try:
config = ConfigObj('/etc/airtime/airtime.conf')
except Exception, e:
print('Error loading config file: %s', e)
sys.exit()
api_client = apc.AirtimeApiClient(config)
#helper functions
# copy or move files
# flag should be 'copy' or 'move'
def copy_or_move_files_to(paths, dest, flag):
try:
for path in paths:
if (path[0] == "/" or path[0] == "~"):
path = os.path.realpath(path)
else:
path = currentDir+path
path = apc.encode_to(path, 'utf-8')
dest = apc.encode_to(dest, 'utf-8')
if(os.path.exists(path)):
if(os.path.isdir(path)):
path = format_dir_string(path)
#construct full path
sub_path = []
for temp in os.listdir(path):
sub_path.append(path+temp)
copy_or_move_files_to(sub_path, dest, flag)
elif(os.path.isfile(path)):
#copy file to dest
if(is_file_supported(path)):
destfile = dest+os.path.basename(path)
if(flag == 'copy'):
print "Copying %(src)s to %(dest)s..." % {'src':path, 'dest':destfile}
shutil.copyfile(path, destfile)
elif(flag == 'move'):
print "Moving %(src)s to %(dest)s..." % {'src':path, 'dest':destfile}
shutil.move(path, destfile)
else:
print "Cannot find file or path: %s" % path
except Exception as e:
print "Error: ", e
def format_dir_string(path):
if(path[-1] != '/'):
path = path+'/'
return path
def helper_get_stor_dir():
try:
res = api_client.list_all_watched_dirs()
except Exception, e:
return res
if(res['dirs']['1'][-1] != '/'):
out = res['dirs']['1']+'/'
return out
else:
return res['dirs']['1']
def checkOtherOption(args):
for i in args:
if(i[0] == '-'):
return True
def errorIfMultipleOption(args, msg=''):
if(checkOtherOption(args)):
if(msg != ''):
raise OptionValueError(msg)
else:
raise OptionValueError("This option cannot be combined with other options")
def printHelp():
storage_dir = helper_get_stor_dir()
if(storage_dir is None):
storage_dir = "Unknown"
else:
storage_dir += "imported/"
print """
========================
Airtime Import Script
========================
There are two ways to import audio files into Airtime:
1) Use airtime-import to copy or move files into the storage folder.
Copied or moved files will be placed into the folder:
%s
Files will be automatically organized into the structure
"Artist/Album/TrackNumber-TrackName-Bitrate.file_extension".
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 library.
""" % storage_dir
parser.print_help()
print ""
def CopyAction(option, opt, value, parser):
errorIfMultipleOption(parser.rargs)
if(len(parser.rargs) == 0 ):
raise OptionValueError("No argument found. This option requires at least one argument.")
stor = helper_get_stor_dir()
if(stor is None):
print "Unable to connect to the Airtime server."
return
dest = stor+"organize/"
copy_or_move_files_to(parser.rargs, dest, 'copy')
def MoveAction(option, opt, value, parser):
errorIfMultipleOption(parser.rargs)
if(len(parser.rargs) == 0 ):
raise OptionValueError("No argument found. This option requires at least one argument.")
stor = helper_get_stor_dir()
if(stor is None):
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 requires exactly one argument.")
elif(len(parser.rargs) == 0 ):
raise OptionValueError("No argument found. This option requires exactly one argument.")
path = parser.rargs[0]
if (path[0] == "/" or path[0] == "~"):
path = os.path.realpath(path)
else:
path = currentDir+path
path = apc.encode_to(path, 'utf-8')
if(os.path.isdir(path)):
#os.chmod(path, 0765)
try:
res = api_client.add_watched_dir(path)
except Exception, e:
exit("Unable to connect to the server.")
# sucess
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 "This error most likely caused by wrong permissions"
print "Try fixing this error by chmodding the parent directory(ies)"
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 arguments.")
try:
res = api_client.list_all_watched_dirs()
except Exception, e:
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):
print "No watch folders found"
else:
for key, v in dirs:
if(key != '1'):
print v
def WatchRemoveAction(option, opt, value, parser):
errorIfMultipleOption(parser.rargs)
if(len(parser.rargs) > 1):
raise OptionValueError("Too many arguments. This option requires exactly one argument.")
elif(len(parser.rargs) == 0 ):
raise OptionValueError("No argument found. This option requires exactly one argument.")
path = parser.rargs[0]
if (path[0] == "/" or path[0] == "~"):
path = os.path.realpath(path)
else:
path = currentDir+path
path = apc.encode_to(path, 'utf-8')
if(os.path.isdir(path)):
try:
res = api_client.remove_watched_dir(path)
except Exception, e:
exit("Unable to connect to the Airtime server.")
# sucess
if(res['msg']['code'] == 0):
print "%s removed from watch folder list successfully." % path
else:
print "Removing the watch folder failed: %s" % res['msg']['error']
else:
print "The given path is not a directory: %s" % path
def StorageSetAction(option, opt, value, parser):
bypass = False
isF = '-f' in parser.rargs
isForce = '--force' in parser.rargs
if(isF or isForce ):
bypass = True
if(isF):
parser.rargs.remove('-f')
if(isForce):
parser.rargs.remove('--force')
if(not bypass):
errorIfMultipleOption(parser.rargs, "Only [-f] and [--force] option is allowed with this option.")
possibleInput = ['y','Y','n','N']
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\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 requires exactly one argument.")
elif(len(parser.rargs) == 0 ):
raise OptionValueError("No argument found. This option requires exactly one argument.")
path = parser.rargs[0]
if (path[0] == "/" or path[0] == "~"):
path = os.path.realpath(path)
else:
path = currentDir+path
path = apc.encode_to(path, 'utf-8')
if(os.path.isdir(path)):
try:
res = api_client.set_storage_dir(path)
except Exception, e:
exit("Unable to connect to the Airtime server.")
# success
if(res['msg']['code'] == 0):
print "Successfully set storage folder to %s" % path
else:
print "Setting storage folder failed: %s" % res['msg']['error']
else:
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 does not take any arguments.")
print helper_get_stor_dir()
class OptionValueError(RuntimeError):
def __init__(self, msg):
self.msg = msg
usage = """[-c|--copy FILE/DIR [FILE/DIR...]] [-m|--move FILE/DIR [FILE/DIR...]]
[--watch-add DIR] [--watch-list] [--watch-remove DIR]
[--storage-dir-set DIR] [--storage-dir-get]"""
parser = OptionParser(usage=usage, add_help_option=False)
parser.add_option('-c','--copy', action='callback', callback=CopyAction, metavar='FILE', help='Copy FILE(s) into the storage directory.\nYou can specify multiple files or directories.')
parser.add_option('-m','--move', action='callback', callback=MoveAction, metavar='FILE', help='Move FILE(s) into the storage directory.\nYou can specify multiple files or directories.')
parser.add_option('--watch-add', action='callback', callback=WatchAddAction, help='Add DIR to the watched folders list.')
parser.add_option('--watch-list', action='callback', callback=WatchListAction, help='Show the list of folders that are watched.')
parser.add_option('--watch-remove', action='callback', callback=WatchRemoveAction, help='Remove DIR from the watched folders list.')
parser.add_option('--storage-dir-set', action='callback', callback=StorageSetAction, help='Set storage dir to DIR.')
parser.add_option('--storage-dir-get', action='callback', callback=StorageGetAction, help='Show the current storage dir.')
parser.add_option('-h', '--help', dest='help', action='store_true', help='show this help message and exit')
# pop "--dir"
sys.argv.pop(1)
# pop "invoked pwd"
currentDir = sys.argv.pop(1)+'/'
if('-l' in sys.argv or '--link' in sys.argv):
print "\nThe [-l][--link] option is deprecated. Please use the --watch-add option.\nTry 'airtime-import -h' for more detail.\n"
sys.exit()
if('-h' in sys.argv):
printHelp()
sys.exit()
if(len(sys.argv) == 1 or '-' not in sys.argv[1]):
printHelp()
sys.exit()
try:
(option, args) = parser.parse_args()
except Exception, e:
printHelp()
if hasattr(e, 'msg'):
print "Error: "+e.msg
else:
print "Error: ",e
sys.exit()
except SystemExit:
printHelp()
sys.exit()
if option.help:
printHelp()
sys.exit()

View File

@ -1,42 +1,79 @@
#!/bin/bash
#-------------------------------------------------------------------------------
# Copyright (c) 2011 Sourcefabric O.P.S.
#
# This file is part of the Airtime project.
# http://airtime.sourcefabric.org/
#
# Airtime is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# Airtime is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Airtime; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
# This script handles update cue-in/cue-out points for files that already exist
# in Airtime's library.
#
exec 2>&1
airtime_silan_script="airtime-silan.py"
api_client_path="/usr/lib/airtime/"
#!/usr/bin/python
from configobj import ConfigObj
from api_clients import api_client as apc
virtualenv_bin="/usr/lib/airtime/airtime_virtualenv/bin/"
. ${virtualenv_bin}activate
import logging
import json
import os
import sys
import subprocess
import traceback
export PYTHONPATH=${api_client_path}
# create logger
logger = logging.getLogger()
# Absolute path to this script
SCRIPT=`readlink -f $0`
# Absolute directory this script is in
SCRIPTPATH=`dirname $SCRIPT`
# no logging
ch = logging.StreamHandler()
logging.disable(50)
cd $SCRIPTPATH
python ${airtime_silan_script}
# add ch to logger
logger.addHandler(ch)
if os.geteuid() != 0:
print 'Must be a root user.'
sys.exit(1)
# loading config file
try:
config = ConfigObj('/etc/airtime/airtime.conf')
except Exception, e:
print('Error loading config file: %s', e)
sys.exit(1)
api_client = apc.AirtimeApiClient(config)
try:
# keep getting few rows at a time for current music_dir (stor
# or watched folder).
subtotal = 0
while True:
# return a list of pairs where the first value is the
# file's database row id and the second value is the
# filepath
files = api_client.get_files_without_silan_value()
total_files = len(files)
if total_files == 0: break
processed_data = []
total = 0
for f in files:
full_path = f['fp']
# silence detect(set default queue in and out)
try:
command = ['silan', '-b' '-f', 'JSON', full_path]
proc = subprocess.Popen(command, stdout=subprocess.PIPE)
out = proc.communicate()[0].strip('\r\n')
info = json.loads(out)
data = {}
data['cuein'] = str('{0:f}'.format(info['sound'][0][0]))
data['cueout'] = str('{0:f}'.format(info['sound'][-1][1]))
data['length'] = str('{0:f}'.format(info['file duration']))
processed_data.append((f['id'], data))
total += 1
if total % 5 == 0:
print "Total %s / %s files has been processed.." % (total, total_files)
except Exception, e:
print e
print traceback.format_exc()
print "Processed: %d songs" % total
subtotal += total
try:
print api_client.update_cue_values_by_silan(processed_data)
except Exception ,e:
print e
print traceback.format_exc()
print "Total %d songs Processed" % subtotal
except Exception, e:
print e
print traceback.format_exc()

View File

@ -1,78 +0,0 @@
from configobj import ConfigObj
from api_clients import api_client as apc
import logging
import json
import os
import sys
import subprocess
import traceback
# create logger
logger = logging.getLogger()
# no logging
ch = logging.StreamHandler()
logging.disable(50)
# add ch to logger
logger.addHandler(ch)
if os.geteuid() != 0:
print 'Must be a root user.'
sys.exit(1)
# loading config file
try:
config = ConfigObj('/etc/airtime/airtime.conf')
except Exception, e:
print('Error loading config file: %s', e)
sys.exit(1)
api_client = apc.AirtimeApiClient(config)
try:
# keep getting few rows at a time for current music_dir (stor
# or watched folder).
subtotal = 0
while True:
# return a list of pairs where the first value is the
# file's database row id and the second value is the
# filepath
files = api_client.get_files_without_silan_value()
total_files = len(files)
if total_files == 0: break
processed_data = []
total = 0
for f in files:
full_path = f['fp']
# silence detect(set default queue in and out)
try:
command = ['silan', '-b' '-f', 'JSON', full_path]
proc = subprocess.Popen(command, stdout=subprocess.PIPE)
out = proc.communicate()[0].strip('\r\n')
info = json.loads(out)
data = {}
data['cuein'] = str('{0:f}'.format(info['sound'][0][0]))
data['cueout'] = str('{0:f}'.format(info['sound'][-1][1]))
data['length'] = str('{0:f}'.format(info['file duration']))
processed_data.append((f['id'], data))
total += 1
if total % 5 == 0:
print "Total %s / %s files has been processed.." % (total, total_files)
except Exception, e:
print e
print traceback.format_exc()
print "Processed: %d songs" % total
subtotal += total
try:
print api_client.update_cue_values_by_silan(processed_data)
except Exception ,e:
print e
print traceback.format_exc()
print "Total %d songs Processed" % subtotal
except Exception, e:
print e
print traceback.format_exc()

View File

@ -1,18 +0,0 @@
#!/bin/bash
#-------------------------------------------------------------------------------
# Determine directories, files
#-------------------------------------------------------------------------------
virtualenv_bin="/usr/lib/airtime/airtime_virtualenv/bin/"
. ${virtualenv_bin}activate
# Absolute path to this script
SCRIPT=`readlink -f $0`
# Absolute directory this script is in
SCRIPTPATH=`dirname $SCRIPT`
#-------------------------------------------------------------------------------
# Do import
#-------------------------------------------------------------------------------
invokePwd=$PWD
cd $SCRIPTPATH && python airtime-update-db-settings.py

View File

@ -1,87 +0,0 @@
"""
The purpose of this script is to consolidate into one location where
we need to update database host, dbname, username and password.
This script reads from /etc/airtime/airtime.conf.
"""
import os
import sys
import ConfigParser
import xml.dom.minidom
from xml.dom.minidom import Node
if os.geteuid() != 0:
print "Please run this as root."
sys.exit(1)
airtime_conf = '/etc/airtime/airtime.conf'
#Read the universal values
parser = ConfigParser.SafeConfigParser()
parser.read(airtime_conf)
host = 'resources.db.params.host'
dbname = 'resources.db.params.dbname'
username = 'resources.db.params.username'
password = 'resources.db.params.password'
airtime_dir = parser.get('general', 'airtime_dir')
if os.path.exists(airtime_dir):
print 'Airtime root folder found at %s' % airtime_dir
else:
print 'Could not find Airtime root folder specified by "airtime_dir" in %s' % airtime_conf
sys.exit(1)
print ("Updating %s/application/configs/application.ini" % airtime_dir)
f = file('%s/application/configs/application.ini' % airtime_dir,'r')
file_lines = []
for line in f:
if line[0:len(host)] == host:
line= '%s = "%s"\n' % (host, parser.get('database', 'host'))
elif line[0:len(dbname)] == dbname:
line= '%s = "%s"\n' % (dbname, parser.get('database', 'dbname'))
elif line[0:len(username)] == username:
line= '%s = "%s"\n' % (username, parser.get('database', 'dbuser'))
elif line[0:len(password)] == password:
line= '%s = "%s"\n' % (password, parser.get('database', 'dbpass'))
file_lines.append(line)
f.close()
f = file('%s/application/configs/application.ini' % airtime_dir, 'w')
f.writelines(file_lines)
f.close()
print ("Updating %s/build/build.properties" % airtime_dir)
f = file('%s/build/build.properties' % airtime_dir, 'r')
file_lines = []
db_url = 'propel.database.url'
for line in f:
if line[0:len(db_url)] == db_url:
line = '%s = pgsql:host=%s dbname=%s user=%s password=%s\n' % \
(db_url, parser.get('database', 'host'), parser.get('database', 'dbname'), parser.get('database', 'dbuser'), \
parser.get('database', 'dbpass'))
file_lines.append(line)
f.close()
f = file('%s/build/build.properties' % airtime_dir, 'w')
f.writelines(file_lines)
f.close()
print ("Updating %s/build/runtime-conf.xml" % airtime_dir)
doc = xml.dom.minidom.parse('%s/build/runtime-conf.xml' % airtime_dir)
node = doc.getElementsByTagName("dsn")[0]
node.firstChild.nodeValue = 'pgsql:host=%s;port=5432;dbname=%s;user=%s;password=%s' % (parser.get('database', 'host'), \
parser.get('database', 'dbname'), parser.get('database', 'dbuser'), parser.get('database', 'dbpass'))
xml_file = open('%s/build/runtime-conf.xml' % airtime_dir, "w")
xml_file.writelines(doc.toxml('utf-8'))
xml_file.close()
print "Success!"