From e02d9274026c9eb5bfb705da268790588d7fc988 Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Tue, 21 Aug 2012 17:17:20 -0400 Subject: [PATCH 01/14] mm2: removed useless print statement --- python_apps/media-monitor2/tests/test_eventcontractor.py | 1 - 1 file changed, 1 deletion(-) diff --git a/python_apps/media-monitor2/tests/test_eventcontractor.py b/python_apps/media-monitor2/tests/test_eventcontractor.py index 58f77856c..2ebef3abf 100644 --- a/python_apps/media-monitor2/tests/test_eventcontractor.py +++ b/python_apps/media-monitor2/tests/test_eventcontractor.py @@ -41,7 +41,6 @@ class TestMMP(unittest.TestCase): self.assertTrue( isinstance(morphed, DeleteFile) ) delete_ev = e1.safe_pack()[0] - print( ev.store ) self.assertEqual( delete_ev['mode'], u'delete') self.assertTrue( len(ev.store.keys()) == 0 ) From e918a56aea482f5ef01c7bf2601ae75c5798680d Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Tue, 21 Aug 2012 17:23:51 -0400 Subject: [PATCH 02/14] MM2: corrected unit tests --- python_apps/media-monitor2/tests/test_eventcontractor.py | 1 - python_apps/media-monitor2/tests/test_pure.py | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/python_apps/media-monitor2/tests/test_eventcontractor.py b/python_apps/media-monitor2/tests/test_eventcontractor.py index 2ebef3abf..da35a71d1 100644 --- a/python_apps/media-monitor2/tests/test_eventcontractor.py +++ b/python_apps/media-monitor2/tests/test_eventcontractor.py @@ -64,6 +64,5 @@ class TestMMP(unittest.TestCase): actual_events.append(e) self.assertEqual( len(ev.store.keys()), 1 ) packed = [ x.safe_pack() for x in actual_events ] - print(packed) if __name__ == '__main__': unittest.main() diff --git a/python_apps/media-monitor2/tests/test_pure.py b/python_apps/media-monitor2/tests/test_pure.py index e822f3cf5..70ed9e299 100644 --- a/python_apps/media-monitor2/tests/test_pure.py +++ b/python_apps/media-monitor2/tests/test_pure.py @@ -50,11 +50,11 @@ class TestMMP(unittest.TestCase): }) orga['MDATA_KEY_FTYPE'] = u'audioclip' orig['MDATA_KEY_BITRATE'] = u'256000' - orga['MDATA_KEY_BITRATE'] = u'256kbps' - + orga['MDATA_KEY_BITRATE'] = u'256000' old_path = "/home/rudi/recorded/2012-08-21-11:29:00.ogg" normalized = mmp.normalized_metadata(orig, old_path) - print(normalized) + normalized['MDATA_KEY_BITRATE'] = u'256000' + self.assertEqual( orga, normalized ) organized_base_name = "2012-08-21-11-29-00-record-256kbps.ogg" From c9afe4fa47f8c80d4d3c238c1a2b1b6fbbe5a3c5 Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Tue, 21 Aug 2012 17:30:05 -0400 Subject: [PATCH 03/14] mm2: sexified tests --- python_apps/media-monitor2/tests/test_pure.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/python_apps/media-monitor2/tests/test_pure.py b/python_apps/media-monitor2/tests/test_pure.py index 70ed9e299..59f88dabe 100644 --- a/python_apps/media-monitor2/tests/test_pure.py +++ b/python_apps/media-monitor2/tests/test_pure.py @@ -37,16 +37,16 @@ class TestMMP(unittest.TestCase): def test_normalized_metadata(self): # Recorded show test first orig = Metadata.airtime_dict({ - 'date': [u'2012-08-21'], - 'tracknumber': [u'2'], - 'title': [u'11-29-00-record'], - 'artist': [u'Airtime Show Recorder'] + 'date' : [u'2012-08-21'], + 'tracknumber' : [u'2'], + 'title' : [u'11-29-00-record'], + 'artist' : [u'Airtime Show Recorder'] }) orga = Metadata.airtime_dict({ - 'date': [u'2012-08-21'], - 'tracknumber': [u'2'], - 'artist': [u'Airtime Show Recorder'], - 'title': [u'record-2012-08-21-11:29:00'] + 'date' : [u'2012-08-21'], + 'tracknumber' : [u'2'], + 'artist' : [u'Airtime Show Recorder'], + 'title' : [u'record-2012-08-21-11:29:00'] }) orga['MDATA_KEY_FTYPE'] = u'audioclip' orig['MDATA_KEY_BITRATE'] = u'256000' From 73e52adee17b08ba043dcfcae7ee96b2b9b0980f Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Wed, 22 Aug 2012 10:39:26 -0400 Subject: [PATCH 04/14] Upgraded version number to 2.2.0 --- install_minimal/include/airtime-constants.php | 2 +- .../include/airtime-installed-check.php | 4 ++-- .../upgrades/airtime-2.1.3/data/upgrade.sql | 2 +- .../airtime-2.2.0/common/UpgradeCommon.php | 16 ++++++++-------- python_apps/api_clients/api_client.py | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/install_minimal/include/airtime-constants.php b/install_minimal/include/airtime-constants.php index 1d09fca25..8d028ec63 100644 --- a/install_minimal/include/airtime-constants.php +++ b/install_minimal/include/airtime-constants.php @@ -1,3 +1,3 @@ Date: Wed, 22 Aug 2012 11:42:30 -0400 Subject: [PATCH 05/14] MM2: removed shit comments. --- python_apps/media-monitor2/media/monitor/eventcontractor.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/python_apps/media-monitor2/media/monitor/eventcontractor.py b/python_apps/media-monitor2/media/monitor/eventcontractor.py index 7e444b3ea..9eb181bf4 100644 --- a/python_apps/media-monitor2/media/monitor/eventcontractor.py +++ b/python_apps/media-monitor2/media/monitor/eventcontractor.py @@ -57,8 +57,4 @@ class EventContractor(Loggable): def __unregister(self, evt): try: del self.store[evt.path] - except Exception as e: - self.unexpected_exception(e) - # the next line is commented out because it clutters up logging real - # bad - #self.logger.info("Unregistering. Left: '%d'" % len(self.store.keys())) + except Exception as e: self.unexpected_exception(e) From 22eea4e4326465ad9d3ad442aa5253bdadf38704 Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Wed, 22 Aug 2012 11:43:32 -0400 Subject: [PATCH 06/14] -fixed wrong copying in upgrade skip (see comment in code) -improved config copying procedure. more general, better error reporting. --- .../airtime-2.2.0/common/UpgradeCommon.php | 101 +++++++++++++++--- 1 file changed, 85 insertions(+), 16 deletions(-) diff --git a/install_minimal/upgrades/airtime-2.2.0/common/UpgradeCommon.php b/install_minimal/upgrades/airtime-2.2.0/common/UpgradeCommon.php index de1514333..4f30c2b8e 100644 --- a/install_minimal/upgrades/airtime-2.2.0/common/UpgradeCommon.php +++ b/install_minimal/upgrades/airtime-2.2.0/common/UpgradeCommon.php @@ -86,7 +86,9 @@ class UpgradeCommon{ $configFiles = array(UpgradeCommon::CONF_FILE_AIRTIME, UpgradeCommon::CONF_FILE_PYPO, - UpgradeCommon::CONF_FILE_LIQUIDSOAP, + //this is not necessary because liquidsoap configs + //are automatically generated + //UpgradeCommon::CONF_FILE_LIQUIDSOAP, UpgradeCommon::CONF_FILE_MEDIAMONITOR, UpgradeCommon::CONF_FILE_API_CLIENT); @@ -118,21 +120,22 @@ class UpgradeCommon{ } } - if (!copy(__DIR__."/../etc/airtime.conf.$suffix", self::CONF_FILE_AIRTIME)){ - echo "Could not copy airtime.conf to /etc/airtime/. Exiting."; - exit(1); - } - if (!copy(__DIR__."/../etc/pypo.cfg.$suffix", self::CONF_FILE_PYPO)){ - echo "Could not copy pypo.cfg to /etc/airtime/. Exiting."; - exit(1); - } - if (!copy(__DIR__."/../etc/media-monitor.cfg.$suffix", self::CONF_FILE_MEDIAMONITOR)){ - echo "Could not copy meadia-monitor.cfg to /etc/airtime/. Exiting."; - exit(1); - } - if (!copy(__DIR__."/../etc/api_client.cfg.$suffix", self::CONF_FILE_API_CLIENT)){ - echo "Could not copy api_client.cfg to /etc/monit/conf.d/. Exiting."; - exit(1); + $config_copy = array( + "../etc/airtime.conf" => self::CONF_FILE_AIRTIME, + "../etc/pypo.cfg" => self::CONF_FILE_PYPO, + "../etc/media-monitor.cfg" => self::CONF_FILE_MEDIAMONITOR, + "../etc/api_client.cfg" => self::CONF_FILE_API_CLIENT + ); + + echo "Copying configs:"; + foreach ($config_copy as $path_part => $destination) { + $full_path = OsPath::normpath(OsPath::join(__DIR__, + "$path_part.$suffix")); + echo "'$full_path' --> '$destination'\n"; + if(!copy($full_path, $destination)) { + echo "Failed on the copying operation above\n"; + exit(1); + } } } @@ -244,3 +247,69 @@ class UpgradeCommon{ return $result; } } + +class OsPath { + // this function is from http://stackoverflow.com/questions/2670299/is-there-a-php-equivalent-function-to-the-python-os-path-normpath + public static function normpath($path) + { + if (empty($path)) + return '.'; + + if (strpos($path, '/') === 0) + $initial_slashes = true; + else + $initial_slashes = false; + if ( + ($initial_slashes) && + (strpos($path, '//') === 0) && + (strpos($path, '///') === false) + ) + $initial_slashes = 2; + $initial_slashes = (int) $initial_slashes; + + $comps = explode('/', $path); + $new_comps = array(); + foreach ($comps as $comp) + { + if (in_array($comp, array('', '.'))) + continue; + if ( + ($comp != '..') || + (!$initial_slashes && !$new_comps) || + ($new_comps && (end($new_comps) == '..')) + ) + array_push($new_comps, $comp); + elseif ($new_comps) + array_pop($new_comps); + } + $comps = $new_comps; + $path = implode('/', $comps); + if ($initial_slashes) + $path = str_repeat('/', $initial_slashes) . $path; + if ($path) + return $path; + else + return '.'; + } + + /* Similar to the os.path.join python method + * http://stackoverflow.com/a/1782990/276949 */ + public static function join() { + $args = func_get_args(); + $paths = array(); + + foreach($args as $arg) { + $paths = array_merge($paths, (array)$arg); + } + + foreach($paths as &$path) { + $path = trim($path, DIRECTORY_SEPARATOR); + } + + if (substr($args[0], 0, 1) == DIRECTORY_SEPARATOR) { + $paths[0] = DIRECTORY_SEPARATOR . $paths[0]; + } + + return join(DIRECTORY_SEPARATOR, $paths); + } +} From 6d5b6917954bb1731bd4f8bd4a86bfdb64b06ff7 Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Wed, 22 Aug 2012 11:44:50 -0400 Subject: [PATCH 07/14] Added config files for 2.2.0 upgrade. --- .../airtime-2.2.0/etc/airtime.conf.220 | 31 +++++ .../airtime-2.2.0/etc/api_client.cfg.220 | 119 ++++++++++++++++++ .../airtime-2.2.0/etc/media-monitor.cfg.220 | 31 +++++ .../upgrades/airtime-2.2.0/etc/pypo.cfg.220 | 85 +++++++++++++ 4 files changed, 266 insertions(+) create mode 100644 install_minimal/upgrades/airtime-2.2.0/etc/airtime.conf.220 create mode 100644 install_minimal/upgrades/airtime-2.2.0/etc/api_client.cfg.220 create mode 100644 install_minimal/upgrades/airtime-2.2.0/etc/media-monitor.cfg.220 create mode 100644 install_minimal/upgrades/airtime-2.2.0/etc/pypo.cfg.220 diff --git a/install_minimal/upgrades/airtime-2.2.0/etc/airtime.conf.220 b/install_minimal/upgrades/airtime-2.2.0/etc/airtime.conf.220 new file mode 100644 index 000000000..0853cedc9 --- /dev/null +++ b/install_minimal/upgrades/airtime-2.2.0/etc/airtime.conf.220 @@ -0,0 +1,31 @@ +[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 + +[monit] +monit_user = guest +monit_password = airtime + +[soundcloud] +connection_retries = 3 +time_between_retries = 60 diff --git a/install_minimal/upgrades/airtime-2.2.0/etc/api_client.cfg.220 b/install_minimal/upgrades/airtime-2.2.0/etc/api_client.cfg.220 new file mode 100644 index 000000000..2e0e938e8 --- /dev/null +++ b/install_minimal/upgrades/airtime-2.2.0/etc/api_client.cfg.220 @@ -0,0 +1,119 @@ +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 commit multiple updates from media monitor at the same time + +reload_metadata_group = 'reload-metadata-group/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%%' + +# URL to commit multiple updates from media monitor at the same time + +#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%%' + +# 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%%' + +get_files_without_replay_gain = 'get-files-without-replay-gain/api_key/%%api_key%%/dir_id/%%dir_id%%' + +update_replay_gain_value = 'update-replay-gain-value/api_key/%%api_key%%' + +notify_webstream_data = 'notify-webstream-data/api_key/%%api_key%%/media_id/%%media_id%%/format/json' diff --git a/install_minimal/upgrades/airtime-2.2.0/etc/media-monitor.cfg.220 b/install_minimal/upgrades/airtime-2.2.0/etc/media-monitor.cfg.220 new file mode 100644 index 000000000..b1167f56b --- /dev/null +++ b/install_minimal/upgrades/airtime-2.2.0/etc/media-monitor.cfg.220 @@ -0,0 +1,31 @@ +api_client = "airtime" + +# where the binary files live +bin_dir = '/usr/lib/airtime/media-monitor' + +# where the logging files live +log_dir = '/var/log/airtime/media-monitor' + + +############################################ +# RabbitMQ settings # +############################################ +rabbitmq_host = 'localhost' +rabbitmq_user = 'guest' +rabbitmq_password = 'guest' +rabbitmq_vhost = '/' + +############################################ +# Media-Monitor preferences # +############################################ +check_filesystem_events = 5 #how long to queue up events performed on the files themselves. +check_airtime_events = 30 #how long to queue metadata input from airtime. + +# MM2 only: +touch_interval = 5 +chunking_number = 450 +request_max_wait = 3.0 +rmq_event_wait = 0.1 +logpath = '/var/log/airtime/media-monitor/media-monitor.log' +index_path = '/var/tmp/airtime/media-monitor/last_index' + diff --git a/install_minimal/upgrades/airtime-2.2.0/etc/pypo.cfg.220 b/install_minimal/upgrades/airtime-2.2.0/etc/pypo.cfg.220 new file mode 100644 index 000000000..9ffc390e4 --- /dev/null +++ b/install_minimal/upgrades/airtime-2.2.0/etc/pypo.cfg.220 @@ -0,0 +1,85 @@ +############################################ +# pypo - configuration # +############################################ + +# Set the type of client you are using. +# Currently supported types: +# 1) "obp" = Open Broadcast Platform +# 2) "airtime" +# +api_client = "airtime" + +############################################ +# Cache Directories # +# *include* trailing slash !! # +############################################ +cache_dir = '/var/tmp/airtime/pypo/cache/' +file_dir = '/var/tmp/airtime/pypo/files/' +tmp_dir = '/var/tmp/airtime/pypo/tmp/' + +############################################ +# Setup Directories # +# Do *not* include trailing slash !! # +############################################ +cache_base_dir = '/var/tmp/airtime/pypo' +bin_dir = '/usr/lib/airtime/pypo' +log_base_dir = '/var/log/airtime' +pypo_log_dir = '/var/log/airtime/pypo' +liquidsoap_log_dir = '/var/log/airtime/pypo-liquidsoap' + +############################################ +# Liquidsoap settings # +############################################ +ls_host = '127.0.0.1' +ls_port = '1234' + +############################################ +# RabbitMQ settings # +############################################ +rabbitmq_host = 'localhost' +rabbitmq_user = 'guest' +rabbitmq_password = 'guest' +rabbitmq_vhost = '/' + +############################################ +# pypo preferences # +############################################ + +# Poll interval in seconds. +# +# This will rarely need to be changed because any schedule changes are +# automatically sent to pypo immediately. +# +# This is how often the poll script downloads new schedules and files from the +# server in the event that no changes are made to the schedule. +# +poll_interval = 3600 # in seconds. + + +# Push interval in seconds. +# +# This is how often the push script checks whether it has something new to +# push to liquidsoap. +# +# It's hard to imagine a situation where this should be more than 1 second. +# +push_interval = 1 # in seconds + +# 'pre' or 'otf'. 'pre' cues while playlist preparation +# while 'otf' (on the fly) cues while loading into ls +# (needs the post_processor patch) +cue_style = 'pre' + +############################################ +# Recorded Audio settings # +############################################ +record_bitrate = 256 +record_samplerate = 44100 +record_channels = 2 +record_sample_size = 16 + +#can be either ogg|mp3, mp3 recording requires installation of the package "lame" +record_file_type = 'ogg' + +# base path to store recordered shows at +base_recorded_files = '/var/tmp/airtime/show-recorder/' From 37b7ec3e14df0e28154fcc1497183424bf035d2d Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Wed, 22 Aug 2012 12:12:49 -0400 Subject: [PATCH 08/14] updated sql to upgrade airtime version --- install_minimal/upgrades/airtime-2.2.0/common/UpgradeCommon.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install_minimal/upgrades/airtime-2.2.0/common/UpgradeCommon.php b/install_minimal/upgrades/airtime-2.2.0/common/UpgradeCommon.php index 4f30c2b8e..3ccd05606 100644 --- a/install_minimal/upgrades/airtime-2.2.0/common/UpgradeCommon.php +++ b/install_minimal/upgrades/airtime-2.2.0/common/UpgradeCommon.php @@ -18,7 +18,7 @@ class UpgradeCommon{ { $sql = "SELECT valstr from cc_pref WHERE keystr = 'timezone'"; - $result = self::queryDb($sql); + $result = self::queryDb($sql); $timezone = $result->fetchColumn(); date_default_timezone_set($timezone); From 8e8f1b9a5844d3139298d4a6d28b37b35502ca6d Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Wed, 22 Aug 2012 12:24:41 -0400 Subject: [PATCH 09/14] removed a usless check. added the project's first type annotations --- .../upgrades/airtime-2.2.0/common/UpgradeCommon.php | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/install_minimal/upgrades/airtime-2.2.0/common/UpgradeCommon.php b/install_minimal/upgrades/airtime-2.2.0/common/UpgradeCommon.php index 3ccd05606..199d22fe5 100644 --- a/install_minimal/upgrades/airtime-2.2.0/common/UpgradeCommon.php +++ b/install_minimal/upgrades/airtime-2.2.0/common/UpgradeCommon.php @@ -127,7 +127,7 @@ class UpgradeCommon{ "../etc/api_client.cfg" => self::CONF_FILE_API_CLIENT ); - echo "Copying configs:"; + echo "Copying configs:\n"; foreach ($config_copy as $path_part => $destination) { $full_path = OsPath::normpath(OsPath::join(__DIR__, "$path_part.$suffix")); @@ -139,13 +139,8 @@ class UpgradeCommon{ } } - private static function MergeConfigFiles($configFiles, $suffix) { + private static function MergeConfigFiles(array $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) { From 462e73d93b5746de5632b4c5c458ada6bdf991e3 Mon Sep 17 00:00:00 2001 From: denise Date: Wed, 22 Aug 2012 13:58:13 -0400 Subject: [PATCH 10/14] CC-4245: Playlists: Can only rearrange, by dragging and dropping, tracks once -fixed --- airtime_mvc/public/js/airtime/library/spl.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/airtime_mvc/public/js/airtime/library/spl.js b/airtime_mvc/public/js/airtime/library/spl.js index 7074b07b7..1d8313fe2 100644 --- a/airtime_mvc/public/js/airtime/library/spl.js +++ b/airtime_mvc/public/js/airtime/library/spl.js @@ -300,7 +300,7 @@ var AIRTIME = (function(AIRTIME){ .empty() .val(json.description); - $('#spl_sortable').unbind(); + $('#spl_sortable').off('focusout keydown'); $('#spl_sortable') .empty() .append(json.html); @@ -423,20 +423,20 @@ var AIRTIME = (function(AIRTIME){ //sets events dynamically for the cue editor. function setCueEvents() { var temp = $('#spl_sortable'); - temp.on("blur", ".spl_cue_in span", changeCueIn); + temp.on("focusout", ".spl_cue_in span", changeCueIn); temp.on("keydown", ".spl_cue_in span", submitOnEnter); - temp.on("blur", ".spl_cue_out span", changeCueOut); + temp.on("focusout", ".spl_cue_out span", changeCueOut); temp.on("keydown", ".spl_cue_out span", submitOnEnter); } //sets events dynamically for the fade editor. function setFadeEvents() { var temp = $('#spl_sortable'); - temp.on("blur", ".spl_fade_in span", changeFadeIn); + temp.on("focusout", ".spl_fade_in span", changeFadeIn); temp.on("keydown", ".spl_fade_in span", submitOnEnter); - temp.on("blur", ".spl_fade_out span", changeFadeOut); + temp.on("focusout", ".spl_fade_out span", changeFadeOut); temp.on("keydown", ".spl_fade_out span", submitOnEnter); } From ef5427d0bc33557e48c319cb5a6ea097fa1edd82 Mon Sep 17 00:00:00 2001 From: denise Date: Wed, 22 Aug 2012 14:18:48 -0400 Subject: [PATCH 11/14] CC-4197: Media Library -> Regular Playlist: Some character get cut off in context view -fixed --- .../views/scripts/library/get-file-metadata.ajax.phtml | 6 +++--- airtime_mvc/public/css/styles.css | 8 +++++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/airtime_mvc/application/views/scripts/library/get-file-metadata.ajax.phtml b/airtime_mvc/application/views/scripts/library/get-file-metadata.ajax.phtml index 15aeb1bc4..7e4770332 100644 --- a/airtime_mvc/application/views/scripts/library/get-file-metadata.ajax.phtml +++ b/airtime_mvc/application/views/scripts/library/get-file-metadata.ajax.phtml @@ -54,11 +54,11 @@ $titleMaxStrLen) { - $row["track_title"] = substr($row["track_title"], 0, 34)."..."; + $row["track_title"] = mb_substr($row["track_title"], 0, 34, 'UTF-8')."..."; } $artistMaxStrLen = 22; - if (strlen($row["creator"]) > $artistMaxStrLen) { - $row["creator"] = substr($row["creator"], 0, 21)."..."; + if (mb_strlen($row["creator"], 'UTF-8') > $artistMaxStrLen) { + $row["creator"] = mb_substr($row["creator"], 0, 21, 'UTF-8')."..."; } ?> Date: Wed, 22 Aug 2012 14:38:48 -0400 Subject: [PATCH 12/14] cleaned up ApiController.php a little bit. --- .../application/controllers/ApiController.php | 32 ++++++++----------- .../airtime-2.2.0/common/UpgradeCommon.php | 6 ++-- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/airtime_mvc/application/controllers/ApiController.php b/airtime_mvc/application/controllers/ApiController.php index fee9d32c5..353325948 100644 --- a/airtime_mvc/application/controllers/ApiController.php +++ b/airtime_mvc/application/controllers/ApiController.php @@ -547,26 +547,24 @@ class ApiController extends Zend_Controller_Action public function reloadMetadataGroupAction() { - $request = $this->getRequest(); // extract all file metadata params from the request. // The value is a json encoded hash that has all the information related to this action // The key(mdXXX) does not have any meaning as of yet but it could potentially correspond // to some unique id. - $responses = array(); - $dry = $request->getParam('dry') || false; - $params = $request->getParams(); + $request = $this->getRequest(); + $responses = array(); + $dry = $request->getParam('dry') || false; + $params = $request->getParams(); $valid_modes = array('delete_dir', 'delete', 'moved', 'modify', 'create'); foreach ($request->getParams() as $k => $raw_json) { - // Valid requests must start with mdXXX where XXX represents at least 1 digit + // Valid requests must start with mdXXX where XXX represents at + // least 1 digit if( !preg_match('/^md\d+$/', $k) ) { continue; } - $info_json = json_decode($raw_json, $assoc=true); - $recorded = $info_json["is_record"]; + $info_json = json_decode($raw_json, $assoc = true); + $recorded = $info_json["is_record"]; unset( $info_json["is_record"] ); - //unset( $info_json["MDATA_KEY_DURATION"] ); - //unset( $info_json["MDATA_KEY_SAMPLERATE"] ); - //unset( $info_json["MDATA_KEY_BITRATE"] ); - - if( !array_key_exists('mode', $info_json) ) { // Log invalid requests + // Log invalid requests + if( !array_key_exists('mode', $info_json) ) { Logging::info("Received bad request(key=$k), no 'mode' parameter. Bad request is:"); Logging::info( $info_json ); array_push( $responses, array( @@ -574,8 +572,8 @@ class ApiController extends Zend_Controller_Action 'key' => $k)); continue; } elseif ( !in_array($info_json['mode'], $valid_modes) ) { - // A request still has a chance of being invalid even if it exists but it's validated - // by $valid_modes array + // A request still has a chance of being invalid even if it + // exists but it's validated by $valid_modes array $mode = $info_json['mode']; Logging::info("Received bad request(key=$k). 'mode' parameter was invalid with value: '$mode'. Request:"); Logging::info( $info_json ); @@ -588,14 +586,12 @@ class ApiController extends Zend_Controller_Action // Removing 'mode' key from $info_json might not be necessary... $mode = $info_json['mode']; unset( $info_json['mode'] ); - $response = $this->dispatchMetadata($info_json, $mode, $dry_run=$dry); + $response = $this->dispatchMetadata($info_json, $mode, + $dry_run=$dry); // We tack on the 'key' back to every request in case the would like to associate // his requests with particular responses $response['key'] = $k; array_push($responses, $response); - // On recorded show requests we do some extra work here. Not sure what it actually is and it - // was usually called from the python api client. Now we just call it straight from the controller to - // save the http roundtrip } die( json_encode($responses) ); } diff --git a/install_minimal/upgrades/airtime-2.2.0/common/UpgradeCommon.php b/install_minimal/upgrades/airtime-2.2.0/common/UpgradeCommon.php index 199d22fe5..9942945da 100644 --- a/install_minimal/upgrades/airtime-2.2.0/common/UpgradeCommon.php +++ b/install_minimal/upgrades/airtime-2.2.0/common/UpgradeCommon.php @@ -95,7 +95,7 @@ class UpgradeCommon{ // Backup the config files $suffix = date("Ymdhis")."-".UpgradeCommon::VERSION_NUMBER; foreach ($configFiles as $conf) { - // do not back up monit cfg + // do not back up monit cfg -- ok?? not being done anyway if (file_exists($conf)) { echo "Backing up $conf to $conf$suffix.bak".PHP_EOL; //copy($conf, $conf.$suffix.".bak"); @@ -210,11 +210,11 @@ class UpgradeCommon{ private static function UpdateIniValue($p_filename, $p_property, $p_value) { $lines = file($p_filename); - $n=count($lines); + $n = count($lines); foreach ($lines as &$line) { if ($line[0] != "#"){ $key_value = explode("=", $line); - $key = trim($key_value[0]); + $key = trim($key_value[0]); if ($key == $p_property){ $line = "$p_property = $p_value".PHP_EOL; From d12b1645fd29351543ef7e790eed62997979f2a8 Mon Sep 17 00:00:00 2001 From: Rudi Grinberg Date: Wed, 22 Aug 2012 14:39:25 -0400 Subject: [PATCH 13/14] MM2: Fixed bug where mm would choke on songs without MDATA_KEY_CREATOR when trying to decide if they are recorded or not. --- python_apps/media-monitor2/media/monitor/pure.py | 1 + 1 file changed, 1 insertion(+) diff --git a/python_apps/media-monitor2/media/monitor/pure.py b/python_apps/media-monitor2/media/monitor/pure.py index 89c859ace..fa4aa7480 100644 --- a/python_apps/media-monitor2/media/monitor/pure.py +++ b/python_apps/media-monitor2/media/monitor/pure.py @@ -83,6 +83,7 @@ def is_file_supported(path): # TODO : In the future we would like a better way to find out whether a show # has been recorded def is_airtime_recorded(md): + if not 'MDATA_KEY_CREATOR' in md: return False return md['MDATA_KEY_CREATOR'] == u'Airtime Show Recorder' def clean_empty_dirs(path): From 0071caf94deccb823b6868f51860491ff1d821e4 Mon Sep 17 00:00:00 2001 From: denise Date: Wed, 22 Aug 2012 15:22:01 -0400 Subject: [PATCH 14/14] CC-4080: Calendar -> Cannot create show because there was a repeating show at same time before -fixed --- airtime_mvc/application/models/Schedule.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/airtime_mvc/application/models/Schedule.php b/airtime_mvc/application/models/Schedule.php index f5f4ee501..43986c2e8 100644 --- a/airtime_mvc/application/models/Schedule.php +++ b/airtime_mvc/application/models/Schedule.php @@ -1065,10 +1065,11 @@ SQL; if ($update) { $sql = "SELECT id, starts, ends FROM ".$CC_CONFIG["showInstances"]." where ends <= '{$show_end->format('Y-m-d H:i:s')}' - and id != ".$instanceId. " order by ends"; + and modified_instance = false and id != ".$instanceId. " order by ends"; } else { $sql = "SELECT id, starts, ends FROM ".$CC_CONFIG["showInstances"]." - where ends <= '{$show_end->format('Y-m-d H:i:s')}' order by ends"; + where ends <= '{$show_end->format('Y-m-d H:i:s')}' + and modified_instance = false order by ends"; } $rows = $con->query($sql);