From d83267e6dca1edd253f2251c34a9e128d670ebc6 Mon Sep 17 00:00:00 2001 From: Martin Konecny Date: Tue, 27 Mar 2012 15:16:58 -0400 Subject: [PATCH 1/5] -remove crossfade function from ls scripts since it wasn't doing anything. --- python_apps/pypo/liquidsoap_scripts/ls_lib.liq | 9 --------- python_apps/pypo/liquidsoap_scripts/ls_script.liq | 2 -- 2 files changed, 11 deletions(-) diff --git a/python_apps/pypo/liquidsoap_scripts/ls_lib.liq b/python_apps/pypo/liquidsoap_scripts/ls_lib.liq index 873997c7e..e35614625 100644 --- a/python_apps/pypo/liquidsoap_scripts/ls_lib.liq +++ b/python_apps/pypo/liquidsoap_scripts/ls_lib.liq @@ -23,15 +23,6 @@ def transition(a,b) = fade.final(duration=!default_dj_fade, a) ]) end -def crossfade(s) - #duration is automatically overwritten by metadata fields passed in - #with audio - s = fade.in(type="log", duration=0., s) - s = fade.out(type="log", duration=0., s) - fader = fun (a,b) -> add(normalize=false,[b,a]) - cross(fader,s) -end - # Define a transition that fades out the # old source, adds a single, and then # plays the new source diff --git a/python_apps/pypo/liquidsoap_scripts/ls_script.liq b/python_apps/pypo/liquidsoap_scripts/ls_script.liq index 4a7f129cb..f1b08588a 100644 --- a/python_apps/pypo/liquidsoap_scripts/ls_script.liq +++ b/python_apps/pypo/liquidsoap_scripts/ls_script.liq @@ -151,8 +151,6 @@ end s = switch(id="default_switch", track_sensitive=false, transitions=[transition, transition], [({!scheduled_play_enabled},queue),({true},default)]) s = append_dj_inputs(master_live_stream_port, master_live_stream_mp, dj_live_stream_port, dj_live_stream_mp, s) -s = crossfade(s) - # Attach a skip command to the source s: #web_stream_source = input.http(id="web_stream", autostart = false, buffer=0.5, max=20., "") From 654ff76ea4eb53ab17a7da139187f6d932981d1c Mon Sep 17 00:00:00 2001 From: Martin Konecny Date: Tue, 27 Mar 2012 15:24:25 -0400 Subject: [PATCH 2/5] CC-3399: Use VBR instead of CBR for Vorbis (OGG) audio streams -Done --- .../pypo/liquidsoap_scripts/ls_lib.liq | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/python_apps/pypo/liquidsoap_scripts/ls_lib.liq b/python_apps/pypo/liquidsoap_scripts/ls_lib.liq index e35614625..da34c5ab4 100644 --- a/python_apps/pypo/liquidsoap_scripts/ls_lib.liq +++ b/python_apps/pypo/liquidsoap_scripts/ls_lib.liq @@ -93,27 +93,27 @@ def output_to(output_type, type, bitrate, host, port, pass, mount_point, url, de source := add(normalize=false, [amplify(0.00001, noise()),s]) end if bitrate == 24 then - ignore(output(%vorbis.cbr(bitrate = 24),!source)) + ignore(output(%vorbis(quality=-0.1),!source)) elsif bitrate == 32 then - ignore(output(%vorbis.cbr(bitrate = 32),!source)) + ignore(output(%vorbis(quality=-0.1),!source)) elsif bitrate == 48 then - ignore(output(%vorbis.cbr(bitrate = 48),!source)) + ignore(output(%vorbis(quality=-0.1),!source)) elsif bitrate == 64 then - ignore(output(%vorbis.cbr(bitrate = 64),!source)) + ignore(output(%vorbis(quality=0),!source)) elsif bitrate == 96 then - ignore(output(%vorbis.cbr(bitrate = 96),!source)) + ignore(output(%vorbis(quality=0.2),!source)) elsif bitrate == 128 then - ignore(output(%vorbis.cbr(bitrate = 128),!source)) + ignore(output(%vorbis(quality=0.4),!source)) elsif bitrate == 160 then - ignore(output(%vorbis.cbr(bitrate = 160),!source)) + ignore(output(%vorbis(quality=0.5),!source)) elsif bitrate == 192 then - ignore(output(%vorbis.cbr(bitrate = 192),!source)) + ignore(output(%vorbis(quality=0.6),!source)) elsif bitrate == 224 then - ignore(output(%vorbis.cbr(bitrate = 224),!source)) + ignore(output(%vorbis(quality=0.7),!source)) elsif bitrate == 256 then - ignore(output(%vorbis.cbr(bitrate = 256),!source)) + ignore(output(%vorbis(quality=0.8),!source)) elsif bitrate == 320 then - ignore(output(%vorbis.cbr(bitrate = 320),!source)) + ignore(output(%vorbis(quality=0.9),!source)) end end else From 24262d5ed5a66d910151e6f9d37aa3c232a87992 Mon Sep 17 00:00:00 2001 From: Martin Konecny Date: Tue, 27 Mar 2012 15:34:56 -0400 Subject: [PATCH 3/5] cc-3521: remove 2 second delay --- python_apps/pypo/liquidsoap_scripts/ls_lib.liq | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python_apps/pypo/liquidsoap_scripts/ls_lib.liq b/python_apps/pypo/liquidsoap_scripts/ls_lib.liq index da34c5ab4..aad687a53 100644 --- a/python_apps/pypo/liquidsoap_scripts/ls_lib.liq +++ b/python_apps/pypo/liquidsoap_scripts/ls_lib.liq @@ -18,7 +18,7 @@ end def transition(a,b) = log("transition called...") add(normalize=false, - [ sequence([ blank(duration=0.1), + [ sequence([ blank(duration=0.01), fade.initial(duration=!default_dj_fade, b) ]), fade.final(duration=!default_dj_fade, a) ]) end From 45fcedfbd36d8803c2f36b5875a6c528f81c0d87 Mon Sep 17 00:00:00 2001 From: Martin Konecny Date: Tue, 27 Mar 2012 15:49:54 -0400 Subject: [PATCH 4/5] CC-3528: SaaS compatible upgrade script template -Done --- .../airtime-2.1.0/ConfFileUpgrade.php | 15 ++ .../upgrades/airtime-2.1.0/DbUpgrade.php | 17 ++ .../upgrades/airtime-2.1.0/MiscUpgrade.php | 8 + .../airtime-2.1.0/airtime-upgrade.php | 36 +++ .../airtime-2.1.0/common/UpgradeCommon.php | 252 ++++++++++++++++++ .../airtime-2.1.0/etc/airtime.conf.210 | 27 ++ .../airtime-2.1.0/etc/api_client.cfg.210 | 111 ++++++++ .../airtime-2.1.0/etc/liquidsoap.cfg.210 | 69 +++++ .../airtime-2.1.0/etc/media-monitor.cfg.210 | 22 ++ .../upgrades/airtime-2.1.0/etc/pypo.cfg.210 | 87 ++++++ 10 files changed, 644 insertions(+) create mode 100644 install_minimal/upgrades/airtime-2.1.0/ConfFileUpgrade.php create mode 100644 install_minimal/upgrades/airtime-2.1.0/DbUpgrade.php create mode 100644 install_minimal/upgrades/airtime-2.1.0/MiscUpgrade.php create mode 100644 install_minimal/upgrades/airtime-2.1.0/airtime-upgrade.php create mode 100644 install_minimal/upgrades/airtime-2.1.0/common/UpgradeCommon.php create mode 100644 install_minimal/upgrades/airtime-2.1.0/etc/airtime.conf.210 create mode 100644 install_minimal/upgrades/airtime-2.1.0/etc/api_client.cfg.210 create mode 100644 install_minimal/upgrades/airtime-2.1.0/etc/liquidsoap.cfg.210 create mode 100644 install_minimal/upgrades/airtime-2.1.0/etc/media-monitor.cfg.210 create mode 100644 install_minimal/upgrades/airtime-2.1.0/etc/pypo.cfg.210 diff --git a/install_minimal/upgrades/airtime-2.1.0/ConfFileUpgrade.php b/install_minimal/upgrades/airtime-2.1.0/ConfFileUpgrade.php new file mode 100644 index 000000000..f7aea03c3 --- /dev/null +++ b/install_minimal/upgrades/airtime-2.1.0/ConfFileUpgrade.php @@ -0,0 +1,15 @@ +getMessage().PHP_EOL; + echo $CC_DBC->getUserInfo().PHP_EOL; + echo "Database connection problem.".PHP_EOL; + echo "Check if database '{$CC_CONFIG['dsn']['database']}' exists". + " with corresponding permissions.".PHP_EOL; + if ($p_exitOnError) { + exit(1); + } + } else { + $CC_DBC->setFetchMode(DB_FETCHMODE_ASSOC); + } + } + + + public static function DbTableExists($p_name) + { + global $CC_DBC; + $sql = "SELECT * FROM ".$p_name; + $result = $CC_DBC->GetOne($sql); + if (PEAR::isError($result)) { + return false; + } + return true; + } + + private static function GetAirtimeSrcDir() + { + return __DIR__."/../../../airtime_mvc"; + } + + public static function MigrateTablesToVersion($dir, $version) + { + echo "Upgrading database, may take several minutes, please wait".PHP_EOL; + + $appDir = self::GetAirtimeSrcDir(); + $command = "php --php-ini $dir/../../airtime-php.ini ". + "$appDir/library/doctrine/migrations/doctrine-migrations.phar ". + "--configuration=$dir/../../DoctrineMigrations/migrations.xml ". + "--db-configuration=$appDir/library/doctrine/migrations/migrations-db.php ". + "--no-interaction migrations:migrate $version"; + system($command); + } + + public static function BypassMigrations($dir, $version) + { + $appDir = self::GetAirtimeSrcDir(); + $command = "php --php-ini $dir/../../airtime-php.ini ". + "$appDir/library/doctrine/migrations/doctrine-migrations.phar ". + "--configuration=$dir/../../DoctrineMigrations/migrations.xml ". + "--db-configuration=$appDir/library/doctrine/migrations/migrations-db.php ". + "--no-interaction --add migrations:version $version"; + system($command); + } + + public static function upgradeConfigFiles(){ + + $configFiles = array(UpgradeCommon::CONF_FILE_AIRTIME, + UpgradeCommon::CONF_FILE_PYPO, + UpgradeCommon::CONF_FILE_LIQUIDSOAP, + UpgradeCommon::CONF_FILE_MEDIAMONITOR, + UpgradeCommon::CONF_FILE_API_CLIENT); + + // Backup the config files + $suffix = date("Ymdhis")."-".UpgradeCommon::VERSION_NUMBER; + foreach ($configFiles as $conf) { + // do not back up monit cfg + if (file_exists($conf)) { + echo "Backing up $conf to $conf$suffix.bak".PHP_EOL; + //copy($conf, $conf.$suffix.".bak"); + exec("cp -p $conf $conf$suffix.bak"); //use cli version to preserve file attributes + } + } + + self::CreateIniFiles(UpgradeCommon::CONF_BACKUP_SUFFIX); + self::MergeConfigFiles($configFiles, $suffix); + } + + /** + * This function creates the /etc/airtime configuration folder + * and copies the default config files to it. + */ + public static function CreateIniFiles($suffix) + { + if (!file_exists("/etc/airtime/")){ + if (!mkdir("/etc/airtime/", 0755, true)){ + echo "Could not create /etc/airtime/ directory. Exiting."; + exit(1); + } + } + + if (!copy(__DIR__."/airtime.conf.$suffix", self::CONF_FILE_AIRTIME)){ + echo "Could not copy airtime.conf to /etc/airtime/. Exiting."; + exit(1); + } + if (!copy(__DIR__."/pypo.cfg.$suffix", self::CONF_FILE_PYPO)){ + echo "Could not copy pypo.cfg to /etc/airtime/. Exiting."; + exit(1); + } + if (!copy(__DIR__."/media-monitor.cfg.$suffix", self::CONF_FILE_MEDIAMONITOR)){ + echo "Could not copy meadia-monitor.cfg to /etc/airtime/. Exiting."; + exit(1); + } + if (!copy(__DIR__."/api_client.cfg.$suffix", self::CONF_FILE_API_CLIENT)){ + echo "Could not copy api_client.cfg to /etc/monit/conf.d/. Exiting."; + exit(1); + } + } + + private static function MergeConfigFiles($configFiles, $suffix) { + foreach ($configFiles as $conf) { + // we want to use new liquidsoap.cfg so don't merge + // also for monit + if( $conf == self::CONF_FILE_LIQUIDSOAP){ + continue; + } + if (file_exists("$conf$suffix.bak")) { + + if($conf === self::CONF_FILE_AIRTIME) { + // Parse with sections + $newSettings = parse_ini_file($conf, true); + $oldSettings = parse_ini_file("$conf$suffix.bak", true); + } + else { + $newSettings = self::ReadPythonConfig($conf); + $oldSettings = self::ReadPythonConfig("$conf$suffix.bak"); + } + + $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) { + // skip airtim_dir as we want to use new value + if($sectionKey != "airtime_dir"){ + if(isset($oldSettings[$section][$sectionKey])) { + self::UpdateIniValue($conf, $sectionKey, $oldSettings[$section][$sectionKey]); + } + } + } + } + else { + self::UpdateIniValue($conf, $section, $oldSettings[$section]); + } + } + } + } + } + } + + private static function ReadPythonConfig($p_filename) + { + $values = array(); + + $fh = fopen($p_filename, 'r'); + + while(!feof($fh)){ + $line = fgets($fh); + if(substr(trim($line), 0, 1) == '#' || trim($line) == ""){ + continue; + }else{ + $info = explode('=', $line, 2); + $values[trim($info[0])] = trim($info[1]); + } + } + + return $values; + } + + /** + * This function updates an INI style config file. + * + * A property and the value the property should be changed to are + * supplied. If the property is not found, then no changes are made. + * + * @param string $p_filename + * The path the to the file. + * @param string $p_property + * The property to look for in order to change its value. + * @param string $p_value + * The value the property should be changed to. + * + */ + private static function UpdateIniValue($p_filename, $p_property, $p_value) + { + $lines = file($p_filename); + $n=count($lines); + foreach ($lines as &$line) { + if ($line[0] != "#"){ + $key_value = explode("=", $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); + } + + public static function queryDb($p_sql){ + global $CC_DBC; + + $result = $CC_DBC->getRow($p_sql, $fetchmode=DB_FETCHMODE_ASSOC); + if (PEAR::isError($result)) { + echo "Error executing $sql. Exiting."; + exit(1); + } + + return $result; + } +} diff --git a/install_minimal/upgrades/airtime-2.1.0/etc/airtime.conf.210 b/install_minimal/upgrades/airtime-2.1.0/etc/airtime.conf.210 new file mode 100644 index 000000000..578c50828 --- /dev/null +++ b/install_minimal/upgrades/airtime-2.1.0/etc/airtime.conf.210 @@ -0,0 +1,27 @@ +[database] +host = localhost +dbname = airtime +dbuser = airtime +dbpass = airtime + +[rabbitmq] +host = 127.0.0.1 +port = 5672 +user = guest +password = guest +vhost = / + +[general] +api_key = AAA +web_server_user = www-data +airtime_dir = x +base_url = localhost +base_port = 80 + +;How many hours ahead of time should Airtime playout engine (PYPO) +;cache scheduled media files. +cache_ahead_hours = 1 + +[soundcloud] +connection_retries = 3 +time_between_retries = 60 diff --git a/install_minimal/upgrades/airtime-2.1.0/etc/api_client.cfg.210 b/install_minimal/upgrades/airtime-2.1.0/etc/api_client.cfg.210 new file mode 100644 index 000000000..2ff113b9c --- /dev/null +++ b/install_minimal/upgrades/airtime-2.1.0/etc/api_client.cfg.210 @@ -0,0 +1,111 @@ +bin_dir = "/usr/lib/airtime/api_clients" + +############################# +## Common +############################# + +# Value needed to access the API +api_key = 'AAA' + +# Path to the base of the API +api_base = 'api' + +# URL to get the version number of the server API +version_url = 'version/api_key/%%api_key%%' + +#URL to register a components IP Address with the central web server +register_component = 'register-component/format/json/api_key/%%api_key%%/component/%%component%%' + +# Hostname +base_url = 'localhost' +base_port = 80 + +############################# +## Config for Media Monitor +############################# + +# URL to setup the media monitor +media_setup_url = 'media-monitor-setup/format/json/api_key/%%api_key%%' + +# Tell Airtime the file id associated with a show instance. +upload_recorded = 'upload-recorded/format/json/api_key/%%api_key%%/fileid/%%fileid%%/showinstanceid/%%showinstanceid%%' + +# URL to tell Airtime to update file's meta data +update_media_url = 'reload-metadata/format/json/api_key/%%api_key%%/mode/%%mode%%' + +# URL to tell Airtime we want a listing of all files it knows about +list_all_db_files = 'list-all-files/format/json/api_key/%%api_key%%/dir_id/%%dir_id%%' + +# URL to tell Airtime we want a listing of all dirs its watching (including the stor dir) +list_all_watched_dirs = 'list-all-watched-dirs/format/json/api_key/%%api_key%%' + +# URL to tell Airtime we want to add watched directory +add_watched_dir = 'add-watched-dir/format/json/api_key/%%api_key%%/path/%%path%%' + +# URL to tell Airtime we want to add watched directory +remove_watched_dir = 'remove-watched-dir/format/json/api_key/%%api_key%%/path/%%path%%' + +# URL to tell Airtime we want to add watched directory +set_storage_dir = 'set-storage-dir/format/json/api_key/%%api_key%%/path/%%path%%' + +# URL to tell Airtime about file system mount change +update_fs_mount = 'update-file-system-mount/format/json/api_key/%%api_key%%' + +# URL to tell Airtime about file system mount change +handle_watched_dir_missing = 'handle-watched-dir-missing/format/json/api_key/%%api_key%%/dir/%%dir%%' + +############################# +## Config for Recorder +############################# + +# URL to get the schedule of shows set to record +show_schedule_url = 'recorded-shows/format/json/api_key/%%api_key%%' + +# URL to upload the recorded show's file to Airtime +upload_file_url = 'upload-file/format/json/api_key/%%api_key%%' + +#number of retries to upload file if connection problem +upload_retries = 3 + +#time to wait between attempts to upload file if connection problem (in seconds) +upload_wait = 60 + +################################################################################ +# Uncomment *one of the sets* of values from the API clients below, and comment +# out all the others. +################################################################################ + +############################# +## Config for Pypo +############################# + +# Schedule export path. +# %%from%% - starting date/time in the form YYYY-MM-DD-hh-mm +# %%to%% - starting date/time in the form YYYY-MM-DD-hh-mm +export_url = 'schedule/api_key/%%api_key%%' + +get_media_url = 'get-media/file/%%file%%/api_key/%%api_key%%' + +# Update whether a schedule group has begun playing. +update_item_url = 'notify-schedule-group-play/api_key/%%api_key%%/schedule_id/%%schedule_id%%' + +# Update whether an audio clip is currently playing. +update_start_playing_url = 'notify-media-item-start-play/api_key/%%api_key%%/media_id/%%media_id%%/schedule_id/%%schedule_id%%' + +# ??? +generate_range_url = 'generate_range_dp.php' + +# URL to tell Airtime we want to get stream setting +get_stream_setting = 'get-stream-setting/format/json/api_key/%%api_key%%/' + +#URL to update liquidsoap status +update_liquidsoap_status = 'update-liquidsoap-status/format/json/api_key/%%api_key%%/msg/%%msg%%/stream_id/%%stream_id%%/boot_time/%%boot_time%%' + +#URL to check live stream auth +check_live_stream_auth = 'check-live-stream-auth/format/json/api_key/%%api_key%%/username/%%username%%/password/%%password%%/djtype/%%djtype%%' + +#URL to update source status +update_source_status = 'update-source-status/format/json/api_key/%%api_key%%/sourcename/%%sourcename%%/status/%%status%%' + +get_bootstrap_info = 'get-bootstrap-info/format/json/api_key/%%api_key%%' + diff --git a/install_minimal/upgrades/airtime-2.1.0/etc/liquidsoap.cfg.210 b/install_minimal/upgrades/airtime-2.1.0/etc/liquidsoap.cfg.210 new file mode 100644 index 000000000..d76e3af3d --- /dev/null +++ b/install_minimal/upgrades/airtime-2.1.0/etc/liquidsoap.cfg.210 @@ -0,0 +1,69 @@ +########################################### +# Liquidsoap config file # +########################################### + +########################################### +# Output settings # +########################################### +output_sound_device = false +output_sound_device_type = "ALSA" +s1_output = "icecast" +s2_output = "icecast" +s3_output = "icecast" + +s1_enable = true +s2_enable = false +s3_enable = false + +s1_type = "ogg" +s2_type = "ogg" +s3_type = "mp3" + +s1_bitrate = 128 +s2_bitrate = 128 +s3_bitrate = 160 + +########################################### +# Logging settings # +########################################### +log_file = "/var/log/airtime/pypo-liquidsoap/