Fixed airtime-import to work without the virtualenv
This commit is contained in:
parent
0eebd182dd
commit
19de887efb
|
@ -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
|
|
|
@ -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";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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/"
|
#sys.path.append('/usr/lib/airtime/media-monitor/mm2/')
|
||||||
. ${virtualenv_bin}activate
|
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/"
|
# no logging
|
||||||
airtime_import_script="airtime-import.py"
|
ch = logging.StreamHandler()
|
||||||
|
logging.disable(50)
|
||||||
|
|
||||||
api_client_path="/usr/lib/airtime/"
|
# add ch to logger
|
||||||
cd ${airtime_import_path}
|
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
|
|
||||||
|
|
|
@ -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()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue