From 0286aa364ea4a12801979ee04803714fb3c7951c Mon Sep 17 00:00:00 2001 From: Martin Konecny Date: Tue, 3 Jul 2012 16:43:10 -0400 Subject: [PATCH 1/5] 2.1.3 preparation --- CREDITS | 7 +++++++ VERSION | 2 +- changelog | 12 ++++++++++++ install_minimal/airtime-install | 4 ---- install_minimal/include/airtime-constants.php | 2 +- install_minimal/include/airtime-upgrade.php | 6 +++++- python_apps/api_clients/api_client.py | 2 +- 7 files changed, 27 insertions(+), 8 deletions(-) diff --git a/CREDITS b/CREDITS index 3a15126a2..d303519ef 100644 --- a/CREDITS +++ b/CREDITS @@ -1,3 +1,10 @@ +======= +CREDITS +======= +Version 2.1.3 +------------- +Same as previous version. + ======= CREDITS ======= diff --git a/VERSION b/VERSION index 0b9f4ef5f..682777c6f 100644 --- a/VERSION +++ b/VERSION @@ -1,2 +1,2 @@ PRODUCT_ID=Airtime -PRODUCT_RELEASE=2.1.2 +PRODUCT_RELEASE=2.1.3 diff --git a/changelog b/changelog index 579c4db28..96eb74af9 100644 --- a/changelog +++ b/changelog @@ -1,3 +1,15 @@ +2.1.3 - July 4th, 2012 + * Changes + * Clarify inputs and output labels under stream settings + * Bug Fixes + * Fix playout engine crashing in rare cases after the system is restarted + * Fix entries in the Calendar unable to have multiple icons (recorded icon, soundcloud icon etc.) + * Fixed unwatching a watched folder with a large number of files (50,000+) can take a long time + * Fixed files deleted in the Web UI would delete files from the disk in watched folders + * Fixed jQuery widgets not showing the incorrectly showing the past Sunday on Sunday + * Fixed dragging and dropping tracks into a live show could cause to web UI to become unsynchronized from what is actually playing + * Fixed unable to receive mono streams for Master or Show source rebroadcasts + 2.1.2 - June 18th, 2012 * Bug Fixes * Fixed problem where playout engine may not retrieve program schedule after extended periods of user inactivity. diff --git a/install_minimal/airtime-install b/install_minimal/airtime-install index 43302b604..86691c427 100755 --- a/install_minimal/airtime-install +++ b/install_minimal/airtime-install @@ -152,10 +152,6 @@ fi if [ -e /etc/init.d/airtime-playout ]; then invoke-rc.d airtime-playout stop > /dev/null 2>&1 fi -if [ -e /etc/init.d/airtime-show-recorder ]; then - invoke-rc.d airtime-show-recorder stop > /dev/null 2>&1 -fi - #export these variables to make them available in sub bash scripts export DO_UPGRADE diff --git a/install_minimal/include/airtime-constants.php b/install_minimal/include/airtime-constants.php index c33d25441..1d09fca25 100644 --- a/install_minimal/include/airtime-constants.php +++ b/install_minimal/include/airtime-constants.php @@ -1,3 +1,3 @@ Date: Tue, 3 Jul 2012 16:43:24 -0400 Subject: [PATCH 2/5] fix indentation --- .../airtimefilemonitor/mediamonitorcommon.py | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/python_apps/media-monitor/airtimefilemonitor/mediamonitorcommon.py b/python_apps/media-monitor/airtimefilemonitor/mediamonitorcommon.py index 9ca0fcf88..92d0d4ceb 100644 --- a/python_apps/media-monitor/airtimefilemonitor/mediamonitorcommon.py +++ b/python_apps/media-monitor/airtimefilemonitor/mediamonitorcommon.py @@ -31,7 +31,7 @@ class MediaMonitorCommon: def is_temp_file(self, filename): info = filename.split(".") - + # if file doesn't have any extension, info[-2] throws exception # Hence, checking length of info before we do anything if(len(info) >= 2): @@ -56,7 +56,7 @@ class MediaMonitorCommon: try: uid = pwd.getpwnam(euid)[2] gid = grp.getgrnam(egid)[2] - + #drop root permissions and become "nobody" os.setegid(gid) os.seteuid(uid) @@ -85,15 +85,15 @@ class MediaMonitorCommon: except Exception, e: self.logger.warn(u"Failed to check owner/group/permissions for %s", item) return False - + def make_file_readable(self, pathname, is_dir): if is_dir: #set to 755 - os.chmod(pathname, stat.S_IRUSR|stat.S_IWUSR|stat.S_IXUSR | stat.S_IRGRP|stat.S_IXGRP | stat.S_IROTH|stat.S_IXOTH) + os.chmod(pathname, stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH) else: #set to 644 - os.chmod(pathname, stat.S_IRUSR|stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH) - + os.chmod(pathname, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH) + def make_readable(self, pathname): """ Should only call this function if is_readable() returns False. This function @@ -120,7 +120,7 @@ class MediaMonitorCommon: except Exception, e: #something went wrong while we were trying to make world readable. return False - + return True #checks if path is a directory, and if it doesnt exist, then creates it. @@ -165,7 +165,7 @@ class MediaMonitorCommon: #non-critical exception because we probably tried to delete a non-empty dir. #Don't need to log this, let's just "return" pass - + #checks if path exists already in stor. If the path exists and the md5s are the @@ -195,7 +195,7 @@ class MediaMonitorCommon: self.logger.error("Trying %s", new_filepath) if(os.path.exists(new_filepath)): - i = i+1; + i = i + 1; else: filepath = new_filepath break @@ -231,7 +231,7 @@ class MediaMonitorCommon: md['MDATA_KEY_TRACKNUMBER'] = "%02d" % (int(md['MDATA_KEY_TRACKNUMBER'])) #format bitrate as 128kbps - md['MDATA_KEY_BITRATE'] = str(md['MDATA_KEY_BITRATE']/1000)+"kbps" + md['MDATA_KEY_BITRATE'] = str(md['MDATA_KEY_BITRATE'] / 1000) + "kbps" filepath = None #file is recorded by Airtime @@ -274,7 +274,7 @@ class MediaMonitorCommon: if p.returncode != 0: self.logger.warn("command \n%s\n return with a non-zero return value", command) self.logger.error(stderr) - + try: """ File name charset encoding is UTF-8. @@ -283,14 +283,14 @@ class MediaMonitorCommon: except Exception, e: stdout = None self.logger.error("Could not decode %s using UTF-8" % stdout) - + return stdout def scan_dir_for_new_files(self, dir): command = 'find "%s" -iname "*.ogg" -o -iname "*.mp3" -type f -readable' % dir.replace('"', '\\"') self.logger.debug(command) stdout = self.exec_command(command) - + return stdout.splitlines() def touch_index_file(self): @@ -312,7 +312,7 @@ class MediaMonitorCommon: self.move_file(pathname, filepath) self.make_readable(filepath) return filepath - + def test_file_playability(self, pathname): #when there is an single apostrophe inside of a string quoted by apostrophes, we can only escape it by replace that apostrophe #with '\''. This breaks the string into two, and inserts an escaped single quote in between them. @@ -323,13 +323,13 @@ class MediaMonitorCommon: if return_code != 0: #print pathname for py-interpreter.log print pathname - + return (return_code == 0) - + def move_to_problem_dir(self, source): - + dest = os.path.join(self.config.problem_directory, os.path.basename(source)) - + try: omask = os.umask(0) os.rename(source, dest) @@ -338,4 +338,4 @@ class MediaMonitorCommon: self.logger.error("traceback: %s", traceback.format_exc()) finally: os.umask(omask) - + From 7f66d735a15241123e26cdc9d17cc6c8392a3772 Mon Sep 17 00:00:00 2001 From: Martin Konecny Date: Tue, 3 Jul 2012 16:43:33 -0400 Subject: [PATCH 3/5] fix spelling --- python_apps/pypo/pypofile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python_apps/pypo/pypofile.py b/python_apps/pypo/pypofile.py index cf8e199e9..a3d21af6a 100644 --- a/python_apps/pypo/pypofile.py +++ b/python_apps/pypo/pypofile.py @@ -66,7 +66,7 @@ class PypoFile(Thread): if src_size != dst_size: do_copy = True else: - self.logger.debug("file %s already exists in local cache as %s, skipping cpoying..." % (src, dst)) + self.logger.debug("file %s already exists in local cache as %s, skipping copying..." % (src, dst)) media_item['already_exist'] = True else: do_copy = True From 00745d372db8dc4a1b6e514f52ce679f7403a1f6 Mon Sep 17 00:00:00 2001 From: Martin Konecny Date: Tue, 3 Jul 2012 17:06:35 -0400 Subject: [PATCH 4/5] CC-4058: Timeline -> Cannot add song twice if last cursor is selected -fixed --- python_apps/pypo/pypofetch.py | 2 +- python_apps/pypo/pypofile.py | 12 +++++++++--- python_apps/pypo/pypopush.py | 4 ++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/python_apps/pypo/pypofetch.py b/python_apps/pypo/pypofetch.py index 4e2cfaf29..4e350d59c 100644 --- a/python_apps/pypo/pypofetch.py +++ b/python_apps/pypo/pypofetch.py @@ -429,7 +429,7 @@ class PypoFetch(Thread): fileExt = os.path.splitext(media_item['uri'])[1] dst = os.path.join(download_dir, media_item['id'] + fileExt) media_item['dst'] = dst - media_item['started_copying'] = False + media_item['file_ready'] = False media_filtered[key] = media_item self.media_prepare_queue.put(copy.copy(media_filtered)) diff --git a/python_apps/pypo/pypofile.py b/python_apps/pypo/pypofile.py index a3d21af6a..67e829464 100644 --- a/python_apps/pypo/pypofile.py +++ b/python_apps/pypo/pypofile.py @@ -60,22 +60,28 @@ class PypoFile(Thread): except Exception, e: dst_exists = False - media_item['already_exist'] = False do_copy = False if dst_exists: if src_size != dst_size: do_copy = True else: self.logger.debug("file %s already exists in local cache as %s, skipping copying..." % (src, dst)) - media_item['already_exist'] = True else: do_copy = True + media_item['file_ready'] = not do_copy + if do_copy: self.logger.debug("copying from %s to local cache %s" % (src, dst)) try: - media_item['started_copying'] = True + """ + List file as "ready" before it starts copying because by the time + Liquidsoap is ready to play this file, it should have at least started + copying (and can continue copying while Liquidsoap reads from the beginning + of the file) + """ + media_item['file_ready'] = True """ copy will overwrite dst if it already exists diff --git a/python_apps/pypo/pypopush.py b/python_apps/pypo/pypopush.py index cb71937a3..67191f81f 100644 --- a/python_apps/pypo/pypopush.py +++ b/python_apps/pypo/pypopush.py @@ -340,11 +340,11 @@ class PypoPush(Thread): give up on it. """ iter_num = 0 - while not media_item['started_copying'] and iter_num < 50: + while not media_item['file_ready'] and iter_num < 50: time.sleep(0.1) iter_num += 1 - if media_item['started_copying'] or media_item['already_exist']: + if media_item['file_ready']: self.telnet_to_liquidsoap(media_item) else: self.logger.warn("File %s did not become ready in less than 5 seconds. Skipping...", media_item['dst']) From 87afea63bf976cbfb358f6aa62e98b5892de27fd Mon Sep 17 00:00:00 2001 From: denise Date: Tue, 3 Jul 2012 18:22:48 -0400 Subject: [PATCH 5/5] CC-4065: Timeline -> Cursor will disappear after a track is finished sometimes -fixed --- airtime_mvc/public/js/airtime/showbuilder/builder.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/airtime_mvc/public/js/airtime/showbuilder/builder.js b/airtime_mvc/public/js/airtime/showbuilder/builder.js index 055588eeb..b1834ec4f 100644 --- a/airtime_mvc/public/js/airtime/showbuilder/builder.js +++ b/airtime_mvc/public/js/airtime/showbuilder/builder.js @@ -213,6 +213,13 @@ var AIRTIME = (function(AIRTIME){ mod.fnItemCallback = function(json) { checkError(json); + mod.getSelectedCursors(); + oSchedTable.fnDraw(); + + mod.enableUI(); + }; + + mod.getSelectedCursors = function() { cursorIds = []; /* We need to keep record of which show the cursor belongs to @@ -237,9 +244,6 @@ var AIRTIME = (function(AIRTIME){ headerFooter.push("n"); } } - oSchedTable.fnDraw(); - - mod.enableUI(); }; mod.fnAdd = function(aMediaIds, aSchedIds) { @@ -315,6 +319,7 @@ var AIRTIME = (function(AIRTIME){ "success": function(json) { mod.setTimestamp(json.timestamp); mod.setShowInstances(json.instances); + mod.getSelectedCursors(); fnCallback(json); } });