diff --git a/LICENSE_3RD_PARTY b/LICENSE_3RD_PARTY index 515b95951..1b6aebdc7 100644 --- a/LICENSE_3RD_PARTY +++ b/LICENSE_3RD_PARTY @@ -58,10 +58,11 @@ Linked code: Non-linked code: * Apache Web Server 2.2 - Web site: http://httpd.apache.org/ + - License: Apache 2.0. See http://httpd.apache.org/docs/2.2/license.html * PostgreSQL 8.4 - Web site: http://www.postgresql.org/ - - License: The PostgreSQL License. See http://www.opensource.org/licenses/postgresql + - License: The PostgreSQL License. See http://www.postgresql.org/about/licence * PHP 5.3 - Web site: http://www.php.net/ @@ -106,7 +107,7 @@ Non-linked code: * Server Browse - Web site: http://code.google.com/p/jq-serverbrowse/ - - License: BSD 2-Clause + - License: BSD 2-Clause ------------- Media-Monitor diff --git a/VERSION b/VERSION index 1f3a63c2c..8e07f99cf 100644 --- a/VERSION +++ b/VERSION @@ -1,2 +1,2 @@ PRODUCT_ID=Airtime -PRODUCT_RELEASE=1.9.0-RC2 +PRODUCT_RELEASE=1.9.0-RC3 diff --git a/airtime_mvc/application/configs/constants.php b/airtime_mvc/application/configs/constants.php index 71a62ef8a..270e78b1d 100644 --- a/airtime_mvc/application/configs/constants.php +++ b/airtime_mvc/application/configs/constants.php @@ -28,6 +28,7 @@ define('MDATA_KEY_YEAR', 'year'); define('MDATA_KEY_BPM', 'bpm'); define('MDATA_KEY_TRACKNUMBER', 'track_number'); define('MDATA_KEY_CONDUCTOR', 'conductor'); +define('MDATA_KEY_LANGUAGE', 'language'); define('UI_MDATA_VALUE_FORMAT_FILE', 'File'); define('UI_MDATA_VALUE_FORMAT_STREAM', 'live stream'); diff --git a/airtime_mvc/application/controllers/ApiController.php b/airtime_mvc/application/controllers/ApiController.php index e81469fa9..d54f292ac 100644 --- a/airtime_mvc/application/controllers/ApiController.php +++ b/airtime_mvc/application/controllers/ApiController.php @@ -103,8 +103,14 @@ class ApiController extends Zend_Controller_Action //We just want the basename which is the file name with the path //information stripped away. We are using Content-Disposition to specify //to the browser what name the file should be saved as. - $path_parts = pathinfo($media->getPropelOrm()->getDbFilepath()); - header('Content-Disposition: attachment; filename="'.$path_parts['basename'].'"'); + // + // By james.moon: + // I'm removing pathinfo() since it strips away UTF-8 characters. + // Using manualy parsing + $full_path = $media->getPropelOrm()->getDbFilepath(); + $file_base_name = strrchr($full_path, '/'); + $file_base_name = substr($file_base_name, 1); + header('Content-Disposition: attachment; filename="'.$file_base_name.'"'); } header("Content-Length: " . filesize($filepath)); diff --git a/airtime_mvc/application/controllers/ScheduleController.php b/airtime_mvc/application/controllers/ScheduleController.php index f9316b20e..953cfee52 100644 --- a/airtime_mvc/application/controllers/ScheduleController.php +++ b/airtime_mvc/application/controllers/ScheduleController.php @@ -285,6 +285,11 @@ class ScheduleController extends Zend_Controller_Action $show = new ShowInstance($this->sched_sess->showInstanceId); $playlists = $show->searchPlaylistsForShow($post); + foreach( $playlists['aaData'] as &$data){ + // calling two functions to format time to 1 decimal place + $sec = Playlist::playlistTimeToSeconds($data[4]); + $data[4] = Playlist::secondsToPlaylistTime($sec); + } //for datatables die(json_encode($playlists)); diff --git a/airtime_mvc/application/forms/EditAudioMD.php b/airtime_mvc/application/forms/EditAudioMD.php index 14ff80484..5e9b5969b 100644 --- a/airtime_mvc/application/forms/EditAudioMD.php +++ b/airtime_mvc/application/forms/EditAudioMD.php @@ -101,34 +101,41 @@ class Application_Form_EditAudioMD extends Zend_Form 'filters' => array('StringTrim') )); - // Add mood field + // Add bmp field $this->addElement('text', 'bpm', array( 'label' => 'BPM:', 'class' => 'input_text', 'filters' => array('StringTrim') )); - // Add mood field + // Add copyright field $this->addElement('text', 'copyright', array( 'label' => 'Copyright:', 'class' => 'input_text', 'filters' => array('StringTrim') )); - // Add mood field + // Add isrc number field $this->addElement('text', 'isrc_number', array( 'label' => 'ISRC Number:', 'class' => 'input_text', 'filters' => array('StringTrim') )); - // Add mood field + // Add website field $this->addElement('text', 'info_url', array( 'label' => 'Website:', 'class' => 'input_text', 'filters' => array('StringTrim') )); + // Add language field + $this->addElement('text', 'language', array( + 'label' => 'Language:', + 'class' => 'input_text', + 'filters' => array('StringTrim') + )); + // Add the submit button $this->addElement('submit', 'submit', array( 'ignore' => true, diff --git a/airtime_mvc/application/models/StoredFile.php b/airtime_mvc/application/models/StoredFile.php index 156439f19..922856feb 100644 --- a/airtime_mvc/application/models/StoredFile.php +++ b/airtime_mvc/application/models/StoredFile.php @@ -40,7 +40,8 @@ class StoredFile { "sample_rate" => "DbSampleRate", "mime" => "DbMime", "md5" => "DbMd5", - "ftype" => "DbFtype" + "ftype" => "DbFtype", + "language" => "DbLanguage" ); public function __construct() @@ -819,7 +820,7 @@ class StoredFile { $r = @copy($audio_file, $audio_stor);*/ } - + public static function copyFileToStor($p_targetDir, $fileName){ $audio_file = $p_targetDir . DIRECTORY_SEPARATOR . $fileName; @@ -834,7 +835,7 @@ class StoredFile { die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "An identical audioclip named ' . $duplicateName . ' already exists in the storage server."}}'); } } - + $storDir = MusicDir::getStorDir(); $stor = $storDir->getDirectory(); diff --git a/install_full/ubuntu/airtime-full-install b/install_full/ubuntu/airtime-full-install index b27cb5fb6..9c6800ac1 100755 --- a/install_full/ubuntu/airtime-full-install +++ b/install_full/ubuntu/airtime-full-install @@ -28,7 +28,7 @@ sudo apt-get -y install tar gzip curl apache2 php5-pgsql libapache2-mod-php5 \ php-pear php5-gd postgresql odbc-postgresql python2.6 lame libsoundtouch-ocaml \ libvorbis-ocaml-dev libmp3lame-dev libtaglib-ocaml libao-ocaml libmad-ocaml \ libesd0 icecast2 sudo libportaudio2 libsamplerate0 libcamomile-ocaml-dev \ -ecasound php5-curl mpg123 rabbitmq-server monit +ecasound php5-curl mpg123 rabbitmq-server monit python-virtualenv if [ "$?" -ne "0" ]; then echo "" diff --git a/install_minimal/include/AirtimeInstall.php b/install_minimal/include/AirtimeInstall.php index 60438e200..149741a90 100644 --- a/install_minimal/include/AirtimeInstall.php +++ b/install_minimal/include/AirtimeInstall.php @@ -65,13 +65,18 @@ class AirtimeInstall $sql = "SELECT valstr FROM cc_pref WHERE keystr = 'system_version'"; $version = $CC_DBC->GetOne($sql); - if (PEAR::isError($version)) { - return null; - } - // no version string detected - if($version == ''){ - $version = false; + if ($version == '') { + $sql = "SELECT * FROM cc_show_rebroadcast LIMIT 1"; + $result = $CC_DBC->GetOne($sql); + if (!PEAR::isError($result)) { + $version = "1.7.0"; + //echo "Airtime Version: ".$version." ".PHP_EOL; + } + else { + $version = false; + } } + return $version; } } diff --git a/install_minimal/include/airtime-install.php b/install_minimal/include/airtime-install.php index faaad8d0e..ff4f8d731 100644 --- a/install_minimal/include/airtime-install.php +++ b/install_minimal/include/airtime-install.php @@ -72,7 +72,7 @@ if (isset($version) && ($version != false) && ($version < AIRTIME_VERSION) && !i } if($version === false){ - echo "A version of Airtime older than 1.8.0 detected, please upgrade to 1.8.0 first.\n"; + echo "A version of Airtime older than 1.7.0 detected, please upgrade to 1.7.0 first.\n"; echo "You will then be able to upgrade to 1.9.0 using this installer.\n"; exit(3); } diff --git a/install_minimal/include/airtime-upgrade.php b/install_minimal/include/airtime-upgrade.php index 856a1a57f..32c68ad33 100644 --- a/install_minimal/include/airtime-upgrade.php +++ b/install_minimal/include/airtime-upgrade.php @@ -12,6 +12,7 @@ set_include_path(__DIR__.'/../../airtime_mvc/library/pear' . PATH_SEPARATOR . ge require_once('DB.php'); require_once(__DIR__.'/../../airtime_mvc/application/configs/constants.php'); require_once(dirname(__FILE__).'/AirtimeIni.php'); +require_once(dirname(__FILE__).'/AirtimeInstall.php'); if(exec("whoami") != "root"){ echo "Must be root user.\n"; @@ -43,6 +44,7 @@ if (PEAR::isError($CC_DBC)) { $CC_DBC->setFetchMode(DB_FETCHMODE_ASSOC); } +/* $sql = "SELECT valstr FROM cc_pref WHERE keystr = 'system_version'"; $version = $CC_DBC->GetOne($sql); @@ -52,7 +54,7 @@ if (PEAR::isError($version)) { if (!$version){ - $sql = "SELECT * FROM ".$p_name; + $sql = "SELECT * FROM cc_show_rebroadcast LIMIT 1"; $result = $CC_DBC->GetOne($sql); if (!PEAR::isError($result)) { $version = "1.7.0"; @@ -63,6 +65,9 @@ if (!$version){ echo "Airtime Version: ".$version." ".PHP_EOL; } } +*/ + +$version = AirtimeInstall::GetVersionInstalled(); echo "******************************** Update Begin *********************************".PHP_EOL; diff --git a/install_minimal/upgrades/airtime-1.8.0/airtime-upgrade.php b/install_minimal/upgrades/airtime-1.8.0/airtime-upgrade.php index 897555da6..dabbf0b22 100644 --- a/install_minimal/upgrades/airtime-1.8.0/airtime-upgrade.php +++ b/install_minimal/upgrades/airtime-1.8.0/airtime-upgrade.php @@ -7,9 +7,56 @@ */ set_include_path(__DIR__.'/../../../airtime_mvc/library' . PATH_SEPARATOR . get_include_path()); -require_once __DIR__.'/../../../airtime_mvc/application/configs/conf.php'; require_once(dirname(__FILE__).'/../../include/AirtimeInstall.php'); -require_once(dirname(__FILE__).'/../../include/AirtimeIni.php'); + +global $CC_CONFIG; + +function load_airtime_config(){ + $ini_array = parse_ini_file('/etc/airtime/airtime.conf', true); + return $ini_array; +} + +$values = load_airtime_config(); + +$CC_CONFIG = array( + + // Name of the web server user + 'webServerUser' => $values['general']['web_server_user'], + + 'rabbitmq' => $values['rabbitmq'], + + 'baseFilesDir' => $values['general']['base_files_dir'], + // main directory for storing binary media files + 'storageDir' => $values['general']['base_files_dir']."/stor", + + // Database config + 'dsn' => array( + 'username' => $values['database']['dbuser'], + 'password' => $values['database']['dbpass'], + 'hostspec' => $values['database']['host'], + 'phptype' => 'pgsql', + 'database' => $values['database']['dbname']), + + // prefix for table names in the database + 'tblNamePrefix' => 'cc_', + + /* ================================================ storage configuration */ + + 'apiKey' => array($values['general']['api_key']), + 'apiPath' => '/api/', + + 'soundcloud-client-id' => '2CLCxcSXYzx7QhhPVHN4A', + 'soundcloud-client-secret' => 'pZ7beWmF06epXLHVUP1ufOg2oEnIt9XhE8l8xt0bBs', + + 'soundcloud-connection-retries' => $values['soundcloud']['connection_retries'], + 'soundcloud-connection-wait' => $values['soundcloud']['time_between_retries'], + + "rootDir" => __DIR__."/../..", + 'pearPath' => dirname(__FILE__).'/../../library/pear', + 'zendPath' => dirname(__FILE__).'/../../library/Zend', + 'phingPath' => dirname(__FILE__).'/../../library/phing', + +); AirtimeInstall::DbConnect(true); @@ -41,26 +88,18 @@ const CONF_FILE_PYPO = "/etc/airtime/pypo.cfg"; const CONF_FILE_RECORDER = "/etc/airtime/recorder.cfg"; const CONF_FILE_LIQUIDSOAP = "/etc/airtime/liquidsoap.cfg"; -$configFiles = array(AirtimeIni::CONF_FILE_AIRTIME, - AirtimeIni::CONF_FILE_PYPO, - AirtimeIni::CONF_FILE_RECORDER, - AirtimeIni::CONF_FILE_LIQUIDSOAP); +$configFiles = array(CONF_FILE_AIRTIME, + CONF_FILE_PYPO, + CONF_FILE_RECORDER, + CONF_FILE_LIQUIDSOAP); -foreach ($configFiles as $conf) { - if (file_exists($conf)) { - echo "Backing up $conf to $conf.bak".PHP_EOL; - exec("cp $conf $conf.bak"); - } -} /** * This function creates the /etc/airtime configuration folder * and copies the default config files to it. */ -function CreateIniFiles() +function CreateIniFiles($suffix) { - global $AIRTIME_PYTHON_APPS; - if (!file_exists("/etc/airtime/")){ if (!mkdir("/etc/airtime/", 0755, true)){ echo "Could not create /etc/airtime/ directory. Exiting."; @@ -68,40 +107,149 @@ function CreateIniFiles() } } - if (!copy("airtime.conf.180", CONF_FILE_AIRTIME)){ - echo "Could not copy airtime.conf to /etc/airtime/. Exiting."; + if (!copy(__DIR__."/airtime.conf.$suffix", CONF_FILE_AIRTIME)){ + echo "Could not copy airtime.conf.$suffix to /etc/airtime/. Exiting."; exit(1); } - if (!copy($AIRTIME_PYTHON_APPS."/pypo/pypo.cfg", CONF_FILE_PYPO)){ - echo "Could not copy pypo.cfg to /etc/airtime/. Exiting."; + if (!copy(__DIR__."/pypo.cfg.$suffix", CONF_FILE_PYPO)){ + echo "Could not copy pypo.cfg.$suffix to /etc/airtime/. Exiting."; exit(1); } - if (!copy($AIRTIME_PYTHON_APPS."/show-recorder/recorder.cfg", CONF_FILE_RECORDER)){ - echo "Could not copy recorder.cfg to /etc/airtime/. Exiting."; + if (!copy(__DIR__."/recorder.cfg.$suffix", CONF_FILE_RECORDER)){ + echo "Could not copy recorder.cfg.$suffix to /etc/airtime/. Exiting."; exit(1); } - if (!copy($AIRTIME_PYTHON_APPS."/pypo/liquidsoap_scripts/liquidsoap.cfg", CONF_FILE_LIQUIDSOAP)){ - echo "Could not copy liquidsoap.cfg to /etc/airtime/. Exiting."; + if (!copy(__DIR__."/liquidsoap.cfg.$suffix", CONF_FILE_LIQUIDSOAP)){ + echo "Could not copy liquidsoap.cfg.$suffix to /etc/airtime/. Exiting."; exit(1); } } -echo "* Creating INI files".PHP_EOL; -CreateIniFiles(); +function ReadPythonConfig($p_filename) +{ + $values = array(); -AirtimeInstall::InstallPhpCode(); -AirtimeInstall::InstallBinaries(); + $lines = file($p_filename); + $n=count($lines); + for ($i=0; $i<$n; $i++) { + if (strlen($lines[$i]) && !in_array(substr($lines[$i], 0, 1), array('#', PHP_EOL))){ + $info = explode("=", $lines[$i]); + $values[trim($info[0])] = trim($info[1]); + } + } + return $values; +} + +function UpdateIniValue($p_filename, $p_property, $p_value) +{ + $lines = file($p_filename); + $n=count($lines); + foreach ($lines as &$line) { + if ($line[0] != "#"){ + $key_value = split("=", $line); + $key = trim($key_value[0]); + + if ($key == $p_property){ + $line = "$p_property = $p_value".PHP_EOL; + } + } + } + + $fp=fopen($p_filename, 'w'); + for($i=0; $i<$n; $i++){ + fwrite($fp, $lines[$i]); + } + fclose($fp); +} + +function MergeConfigFiles($configFiles, $suffix) +{ + foreach ($configFiles as $conf) { + if (file_exists("$conf$suffix.bak")) { + + if($conf === CONF_FILE_AIRTIME) { + // Parse with sections + $newSettings = parse_ini_file($conf, true); + $oldSettings = parse_ini_file("$conf$suffix.bak", true); + } + else { + $newSettings = ReadPythonConfig($conf); + $oldSettings = ReadPythonConfig("$conf$suffix.bak"); + } + + //override some values needed for 1.8.0. + if($conf === CONF_FILE_PYPO) { + + $oldSettings['cache_dir'] = '/var/tmp/airtime/pypo/cache/'; + $oldSettings['file_dir'] = '/var/tmp/airtime/pypo/files/'; + $oldSettings['tmp_dir'] = '/var/tmp/airtime/pypo/tmp/'; + } + else if($conf === CONF_FILE_RECORDER) { + + $oldSettings['base_recorded_files'] = '/var/tmp/airtime/show-recorder/'; + } + + $settings = array_keys($newSettings); + + foreach($settings as $section) { + if(isset($oldSettings[$section])) { + if(is_array($oldSettings[$section])) { + $sectionKeys = array_keys($newSettings[$section]); + foreach($sectionKeys as $sectionKey) { + if(isset($oldSettings[$section][$sectionKey])) { + UpdateIniValue($conf, $sectionKey, $oldSettings[$section][$sectionKey]); + } + } + } + else { + UpdateIniValue($conf, $section, $oldSettings[$section]); + } + } + } + } + } +} + +function LoadConfig($CC_CONFIG) { + $values = parse_ini_file(CONF_FILE_AIRTIME, true); + + // Name of the web server user + $CC_CONFIG['webServerUser'] = $values['general']['web_server_user']; + $CC_CONFIG['phpDir'] = $values['general']['airtime_dir']; + $CC_CONFIG['rabbitmq'] = $values['rabbitmq']; + + $CC_CONFIG['baseFilesDir'] = $values['general']['base_files_dir']; + // main directory for storing binary media files + $CC_CONFIG['storageDir'] = $values['general']['base_files_dir']."/stor"; + + // 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; +} + +// Backup the config files +$suffix = date("Ymdhis")."-1.8.0"; +foreach ($configFiles as $conf) { + if (file_exists($conf)) { + echo "Backing up $conf to $conf$suffix.bak".PHP_EOL; + exec("cp $conf $conf$suffix.bak"); + } +} + +$default_suffix = "180"; +CreateIniFiles($default_suffix); echo "* Initializing INI files".PHP_EOL; -AirtimeIni::UpdateIniFiles(); -global $CC_CONFIG; -$CC_CONFIG = Config::loadConfig($CC_CONFIG); +MergeConfigFiles($configFiles, $suffix); -echo "* Creating default storage directory".PHP_EOL; -AirtimeInstall::InstallStorageDirectory(); - -$ini = parse_ini_file(__DIR__."/../../include/airtime-install.ini"); -$stor_dir = $ini["storage_dir"]; - -AirtimeInstall::ChangeDirOwnerToWebserver($stor_dir); -AirtimeInstall::CreateSymlinksToUtils(); +$CC_CONFIG = LoadConfig($CC_CONFIG); diff --git a/install_minimal/upgrades/airtime-1.8.0/liquidsoap.cfg.180 b/install_minimal/upgrades/airtime-1.8.0/liquidsoap.cfg.180 new file mode 100644 index 000000000..360ee107f --- /dev/null +++ b/install_minimal/upgrades/airtime-1.8.0/liquidsoap.cfg.180 @@ -0,0 +1,38 @@ +########################################### +# liquidsoap config file # +########################################### + + +########################################### +# general settings # +########################################### + +log_file = "/var/log/airtime/pypo-liquidsoap/