From 63b89043b605219363de07067cbd0b3206437ad7 Mon Sep 17 00:00:00 2001 From: Martin Konecny Date: Wed, 1 Aug 2012 14:51:56 -0400 Subject: [PATCH 1/2] CC-1665: Scheduled stream rebroadcasting and recording on-air light works with streams now --- airtime_mvc/application/models/Schedule.php | 6 +++++ .../pypo/liquidsoap_scripts/ls_lib.liq | 27 ++++++++++++------- .../pypo/liquidsoap_scripts/ls_script.liq | 6 +++++ python_apps/pypo/pypopush.py | 4 +++ 4 files changed, 33 insertions(+), 10 deletions(-) diff --git a/airtime_mvc/application/models/Schedule.php b/airtime_mvc/application/models/Schedule.php index 88b3c49b3..abdf9591e 100644 --- a/airtime_mvc/application/models/Schedule.php +++ b/airtime_mvc/application/models/Schedule.php @@ -665,6 +665,12 @@ class Application_Model_Schedule //time of this event is the "end" time of the stream minus 1 second. $dt = new DateTime($item["end"], new DateTimeZone('UTC')); $dt->sub(new DateInterval("PT1S")); + + //make sure the webstream doesn't play past the end time of the show + if ($dt->getTimestamp() > $showEndDateTime->getTimestamp()) { + $dt = $showEndDateTime; + } + $stream_end = Application_Model_Schedule::AirtimeTimeToPypoTime($dt->format("Y-m-d H:i:s")); $data["media"][$stream_end] = array( diff --git a/python_apps/pypo/liquidsoap_scripts/ls_lib.liq b/python_apps/pypo/liquidsoap_scripts/ls_lib.liq index 9fe471108..18e2290e6 100644 --- a/python_apps/pypo/liquidsoap_scripts/ls_lib.liq +++ b/python_apps/pypo/liquidsoap_scripts/ls_lib.liq @@ -235,20 +235,27 @@ dyn_out = output.icecast(%wav, mount="test-harbor", fallible=true) +def set_dynamic_source_id(id) = + current_dyn_id := id + #"Done!" + string_of(!current_dyn_id) +end + # Function to create a playlist source and output it. def create_dynamic_source(uri) = - # The playlist source - s = input.http(uri) + # The playlist source + s = input.http(uri) - # The output - active_dyn_out = dyn_out(s) + # The output + active_dyn_out = dyn_out(s) - # We register both source and output - # in the list of sources - dyn_sources := - list.append( [(uri,s),(uri,active_dyn_out)], - !dyn_sources ) - "Done!" + # We register both source and output + # in the list of sources + dyn_sources := + list.append([(uri,s),(uri,active_dyn_out)], !dyn_sources) + + notify([("schedule_table_id", !current_dyn_id)]) + "Done!" end # A function to destroy a dynamic source diff --git a/python_apps/pypo/liquidsoap_scripts/ls_script.liq b/python_apps/pypo/liquidsoap_scripts/ls_script.liq index 83d4605fd..b7c2c4460 100644 --- a/python_apps/pypo/liquidsoap_scripts/ls_script.liq +++ b/python_apps/pypo/liquidsoap_scripts/ls_script.liq @@ -21,6 +21,7 @@ set("harbor.bind_addr", "0.0.0.0") #TODO: Need to create a randomized password for every instance web_stream = input.harbor("test-harbor",port=8999,password="hackme") +current_dyn_id = ref '' pypo_data = ref '0' stream_metadata_type = ref 0 @@ -53,6 +54,11 @@ server.register(namespace="vars", "station_name", fun (s) -> begin station_name server.register(namespace="vars", "bootup_time", fun (s) -> begin time := s s end) server.register(namespace="streams", "connection_status", fun (s) -> begin "1:#{!s1_connected},2:#{!s2_connected},3:#{!s3_connected}" end) server.register(namespace="vars", "default_dj_fade", fun (s) -> begin default_dj_fade := float_of_string(s) s end) +server.register(namespace="dynamic_source", + description="Set the cc_schedule row id", + usage="id ", + "id", + set_dynamic_source_id) server.register(namespace="dynamic_source", description="Start a new dynamic source.", usage="start ", diff --git a/python_apps/pypo/pypopush.py b/python_apps/pypo/pypopush.py index 628133f59..93d527d40 100644 --- a/python_apps/pypo/pypopush.py +++ b/python_apps/pypo/pypopush.py @@ -374,6 +374,10 @@ class PypoPush(Thread): tn = telnetlib.Telnet(LS_HOST, LS_PORT) #dynamic_source.start http://87.230.101.24:80/top100station.mp3 + msg = 'dynamic_source.id %s\n' % media_item['row_id'] + tn.write(msg) + + #TODO: DO we need this? msg = 'streams.scheduled_play_start\n' tn.write(msg) msg = 'dynamic_source.start %s\n' % media_item['uri'].encode('latin-1') From 5f8a5a618d71bd1ff9dad5b79608b46a58754d23 Mon Sep 17 00:00:00 2001 From: Martin Konecny Date: Wed, 1 Aug 2012 14:52:21 -0400 Subject: [PATCH 2/2] Remove unecessary trailing whitespace --- python_apps/pypo/pypopush.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/python_apps/pypo/pypopush.py b/python_apps/pypo/pypopush.py index 93d527d40..a6ebef2a6 100644 --- a/python_apps/pypo/pypopush.py +++ b/python_apps/pypo/pypopush.py @@ -157,7 +157,7 @@ class PypoPush(Thread): else: """ We should only reach here if Pypo crashed and restarted (because self.pushed_objects was reset). In this case - let's clear the entire Liquidsoap queue. + let's clear the entire Liquidsoap queue. """ self.logger.error("ID exists in liquidsoap queue that does not exist in our pushed_objects queue: " + item) self.clear_liquidsoap_queue() @@ -169,7 +169,7 @@ class PypoPush(Thread): def handle_new_media_schedule(self, media_schedule, liquidsoap_queue_approx, media_chain): """ This function's purpose is to gracefully handle situations where - Liquidsoap already has a track in its queue, but the schedule + Liquidsoap already has a track in its queue, but the schedule has changed. If the schedule has changed, this function's job is to call other functions that will connect to Liquidsoap and alter its queue. @@ -198,11 +198,11 @@ class PypoPush(Thread): """ Compare whats in the liquidsoap_queue to the new schedule we just received in media_schedule. This function only iterates over liquidsoap_queue_approx - and finds if every item in that list is still scheduled in "media_schedule". It doesn't + and finds if every item in that list is still scheduled in "media_schedule". It doesn't take care of the case where media_schedule has more items than liquidsoap_queue_approx """ def find_removed_items(self, media_schedule, liquidsoap_queue_approx): - #iterate through the items we got from the liquidsoap queue and + #iterate through the items we got from the liquidsoap queue and #see if they are the same as the newly received schedule iteration = 0 problem_at_iteration = None @@ -219,12 +219,12 @@ class PypoPush(Thread): else: #A different item has been scheduled at the same time! Need to remove #all tracks from the Liquidsoap queue starting at this point, and re-add - #them. + #them. problem_at_iteration = iteration break else: #There are no more items scheduled for this time! The user has shortened - #the playlist, so we simply need to remove tracks from the queue. + #the playlist, so we simply need to remove tracks from the queue. problem_at_iteration = iteration break iteration += 1 @@ -278,16 +278,16 @@ class PypoPush(Thread): """ Returns two chains, original chain and current_chain. current_chain is a subset of original_chain but can also be equal to original chain. - + We return original chain because the user of this function may want to clean up the input 'chains' list - + chain, original = get_current_chain(chains) - - and + + and chains.remove(chain) can throw a ValueError exception - - but + + but chains.remove(original) won't """ def get_current_chain(self, chains, tnow): @@ -311,7 +311,7 @@ class PypoPush(Thread): """ The purpose of this function is to take a look at the last received schedule from - pypo-fetch and return the next chain of media_items. A chain is defined as a sequence + pypo-fetch and return the next chain of media_items. A chain is defined as a sequence of media_items where the end time of media_item 'n' is the start time of media_item 'n+1' """ @@ -380,6 +380,7 @@ class PypoPush(Thread): #TODO: DO we need this? msg = 'streams.scheduled_play_start\n' tn.write(msg) + msg = 'dynamic_source.start %s\n' % media_item['uri'].encode('latin-1') self.logger.debug(msg) tn.write(msg)