From 92f19139b9eae853a6bd9b8d22c7cfd50504e4dd Mon Sep 17 00:00:00 2001
From: Martin Konecny <martin.konecny@gmail.com>
Date: Wed, 29 Feb 2012 21:27:42 -0500
Subject: [PATCH] CC-3336: Refactor schedule API used by pypo

-done
---
 .../application/controllers/ApiController.php | 24 ++++++++++++
 python_apps/api_clients/api_client.py         | 34 -----------------
 python_apps/pypo/pypo-notify.py               |  2 +-
 python_apps/pypo/pypofetch.py                 | 13 +------
 python_apps/pypo/pypopush.py                  | 38 +++++++++----------
 5 files changed, 46 insertions(+), 65 deletions(-)

diff --git a/airtime_mvc/application/controllers/ApiController.php b/airtime_mvc/application/controllers/ApiController.php
index 20e9a0f0d..fbed8005d 100644
--- a/airtime_mvc/application/controllers/ApiController.php
+++ b/airtime_mvc/application/controllers/ApiController.php
@@ -27,6 +27,7 @@ class ApiController extends Zend_Controller_Action
                 ->addActionContext('live-chat', 'json')
                 ->addActionContext('update-file-system-mount', 'json')
                 ->addActionContext('handle-watched-dir-missing', 'json')
+                ->addActionContext('rabbitmq-do-push', 'json')
                 ->initContext();
     }
 
@@ -318,6 +319,7 @@ class ApiController extends Zend_Controller_Action
         }
     }
 
+/*
     public function notifyScheduleGroupPlayAction()
     {
         global $CC_CONFIG;
@@ -357,6 +359,7 @@ class ApiController extends Zend_Controller_Action
             exit;
         }
     }
+    */
 
     public function recordedShowsAction()
     {
@@ -903,5 +906,26 @@ class ApiController extends Zend_Controller_Action
         $dir = base64_decode($request->getParam('dir'));
         Application_Model_MusicDir::removeWatchedDir($dir, false);
     }
+    
+    
+    /* This action is for use by our dev scripts, that make
+     * a change to the database and we want rabbitmq to send
+     * out a message to pypo that a potential change has been made. */
+    public function rabbitmqDoPushAction(){
+        global $CC_CONFIG;
+        
+        $request = $this->getRequest();
+        $api_key = $request->getParam('api_key');
+        if (!in_array($api_key, $CC_CONFIG["apiKey"]))
+        {
+            header('HTTP/1.0 401 Unauthorized');
+            print 'You are not allowed to access this resource.';
+            exit;
+        }
+        
+        Logging::log("Notifying RabbitMQ to send message to pypo");
+        
+        Application_Model_RabbitMq::PushSchedule();
+    }
 }
 
diff --git a/python_apps/api_clients/api_client.py b/python_apps/api_clients/api_client.py
index df5b9cd1f..1148dcdc1 100755
--- a/python_apps/api_clients/api_client.py
+++ b/python_apps/api_clients/api_client.py
@@ -81,14 +81,6 @@ class ApiClientInterface:
     def get_media(self, src, dst):
         pass
 
-    # Implementation: optional
-    #
-    # Called from: push loop
-    #
-    # Tell server that the scheduled *playlist* has started.
-    def notify_scheduled_item_start_playing(self, pkey, schedule):
-        pass
-
     # Implementation: optional
     # You dont actually have to implement this function for the liquidsoap playout to work.
     #
@@ -285,32 +277,6 @@ class AirTimeApiClient(ApiClientInterface):
         except Exception, e:
             logger.error("%s", e)
 
-
-    """
-    Tell server that the scheduled *playlist* has started.
-    """
-    def notify_scheduled_item_start_playing(self, pkey, schedule):
-        logger = self.logger
-        playlist = schedule[pkey]
-        schedule_id = playlist["schedule_id"]
-        url = "http://%s:%s/%s/%s" % (self.config["base_url"], str(self.config["base_port"]), self.config["api_base"], self.config["update_item_url"])
-
-        url = url.replace("%%schedule_id%%", str(schedule_id))
-        logger.debug(url)
-        url = url.replace("%%api_key%%", self.config["api_key"])
-
-        try:
-            response = urllib.urlopen(url)
-            response = json.loads(response.read())
-            logger.info("API-Status %s", response['status'])
-            logger.info("API-Message %s", response['message'])
-
-        except Exception, e:
-            logger.error("Unable to connect - %s", e)
-
-        return response
-
-
     """
     This is a callback from liquidsoap, we use this to notify about the
     currently playing *song*.  We get passed a JSON string which we handed to
diff --git a/python_apps/pypo/pypo-notify.py b/python_apps/pypo/pypo-notify.py
index 42fb523fc..ef480691f 100644
--- a/python_apps/pypo/pypo-notify.py
+++ b/python_apps/pypo/pypo-notify.py
@@ -34,7 +34,7 @@ import json
 from configobj import ConfigObj
 
 # custom imports
-from util import *
+#from util import *
 from api_clients import *
 
 # Set up command-line options
diff --git a/python_apps/pypo/pypofetch.py b/python_apps/pypo/pypofetch.py
index 99a06d6d5..fbdf1ea2a 100644
--- a/python_apps/pypo/pypofetch.py
+++ b/python_apps/pypo/pypofetch.py
@@ -336,7 +336,7 @@ class PypoFetch(Thread):
                 
                 if self.handle_media_file(media_item, dst):
                     entry = self.create_liquidsoap_annotation(media_item, dst)
-                    entry['show_name'] = "TODO"
+                    media_item['show_name'] = "TODO"
                     media_item["annotation"] = entry
                 
         except Exception, e:
@@ -346,7 +346,7 @@ class PypoFetch(Thread):
     
 
     def create_liquidsoap_annotation(self, media, dst):
-        pl_entry = \
+        entry = \
             'annotate:media_id="%s",liq_start_next="%s",liq_fade_in="%s",liq_fade_out="%s",liq_cue_in="%s",liq_cue_out="%s",schedule_table_id="%s":%s' \
             % (media['id'], 0, \
             float(media['fade_in']) / 1000, \
@@ -355,15 +355,6 @@ class PypoFetch(Thread):
             float(media['cue_out']), \
             media['row_id'], dst)
 
-        """
-        Tracks are only added to the playlist if they are accessible
-        on the file system and larger than 0 bytes.
-        So this can lead to playlists shorter than expectet.
-        (there is a hardware silence detector for this cases...)
-        """
-        entry = dict()
-        entry['type'] = 'file'
-        entry['annotate'] = pl_entry        
         return entry
         
     def check_for_previous_crash(self, media_item):
diff --git a/python_apps/pypo/pypopush.py b/python_apps/pypo/pypopush.py
index aaddb69da..db153cd36 100644
--- a/python_apps/pypo/pypopush.py
+++ b/python_apps/pypo/pypopush.py
@@ -39,9 +39,11 @@ class PypoPush(Thread):
         self.media = dict()
 
         self.liquidsoap_state_play = True
-        self.push_ahead = 30
+        self.push_ahead = 10
         self.last_end_time = 0
         
+        self.logger = logging.getLogger('push')
+        
     def push(self):
         """
         The Push Loop - the push loop periodically checks if there is a playlist 
@@ -49,7 +51,6 @@ class PypoPush(Thread):
         If yes, the current liquidsoap playlist gets replaced with the corresponding one,
         then liquidsoap is asked (via telnet) to reload and immediately play it.
         """
-        logger = logging.getLogger('push')
 
         timenow = time.time()
         # get a new schedule from pypo-fetch
@@ -57,8 +58,8 @@ class PypoPush(Thread):
             # make sure we get the latest schedule
             while not self.queue.empty():
                 self.media = self.queue.get()
-            logger.debug("Received data from pypo-fetch")          
-            logger.debug('media %s' % json.dumps(self.media))
+            self.logger.debug("Received data from pypo-fetch")          
+            self.logger.debug('media %s' % json.dumps(self.media))
 
         media = self.media
         
@@ -77,17 +78,13 @@ class PypoPush(Thread):
                     """
                     If the media item starts in the next 30 seconds, push it to the queue.
                     """
-                    logger.debug('Preparing to push media item scheduled at: %s', key)
+                    self.logger.debug('Preparing to push media item scheduled at: %s', key)
                               
                     if self.push_to_liquidsoap(media_item):
-                        logger.debug("Pushed to liquidsoap, updating 'played' status.")
+                        self.logger.debug("Pushed to liquidsoap, updating 'played' status.")
                         
                         currently_on_air = True
                         self.liquidsoap_state_play = True
-
-                        # Call API to update schedule states
-                        logger.debug("Doing callback to server to update 'played' status.")
-                        self.api_client.notify_scheduled_item_start_playing(key, schedule)
                         
     def push_to_liquidsoap(self, media_item):
         """
@@ -133,15 +130,15 @@ class PypoPush(Thread):
         #Return the time as a floating point number expressed in seconds since the epoch, in UTC.
         epoch_now = time.time()
         
-        logger.debug("Epoch start: %s" % epoch_start)
-        logger.debug("Epoch now: %s" % epoch_now)
+        self.logger.debug("Epoch start: %s" % epoch_start)
+        self.logger.debug("Epoch now: %s" % epoch_now)
 
         sleep_time = epoch_start - epoch_now
 
         if sleep_time < 0:
             sleep_time = 0
 
-        logger.debug('sleeping for %s s' % (sleep_time))
+        self.logger.debug('sleeping for %s s' % (sleep_time))
         time.sleep(sleep_time)
 
     def telnet_to_liquidsoap(self, media_item):
@@ -156,25 +153,28 @@ class PypoPush(Thread):
         #tn.write(("vars.pypo_data %s\n"%liquidsoap_data["schedule_id"]).encode('utf-8'))
         
         annotation = media_item['annotation']
-        tn.write('queue.push %s\n' % annotation.encode('utf-8'))
+        msg = 'queue.push %s\n' % annotation.encode('utf-8')
+        tn.write(msg)
+        self.logger.debug(msg)
         
         show_name = media_item['show_name']
-        tn.write('vars.show_name %s\n' % show_name.encode('utf-8'))
+        msg = 'vars.show_name %s\n' % show_name.encode('utf-8')
+        tn.write(msg)
+        self.logger.debug(msg)
         
         tn.write("exit\n")
-        logger.debug(tn.read_all())
+        self.logger.debug(tn.read_all())
                      
     def run(self):
         loops = 0
         heartbeat_period = math.floor(30/PUSH_INTERVAL)
-        logger = logging.getLogger('push')
         
         while True:
             if loops % heartbeat_period == 0:
-                logger.info("heartbeat")
+                self.logger.info("heartbeat")
                 loops = 0
             try: self.push()
             except Exception, e:
-                logger.error('Pypo Push Exception: %s', e)
+                self.logger.error('Pypo Push Exception: %s', e)
             time.sleep(PUSH_INTERVAL)
             loops += 1