From 25b5ad43a16fbca596628f8c25707f2b2c97eff3 Mon Sep 17 00:00:00 2001
From: Rudi Grinberg <rudi.grinberg@sourcefabric.org>
Date: Thu, 16 Aug 2012 13:01:39 -0400
Subject: [PATCH 1/6] cc-4235: added todo to fix this shit

---
 python_apps/media-monitor2/media/monitor/manager.py | 1 +
 1 file changed, 1 insertion(+)

diff --git a/python_apps/media-monitor2/media/monitor/manager.py b/python_apps/media-monitor2/media/monitor/manager.py
index 283511dbd..fb4bc58df 100644
--- a/python_apps/media-monitor2/media/monitor/manager.py
+++ b/python_apps/media-monitor2/media/monitor/manager.py
@@ -37,6 +37,7 @@ class Manager(Loggable):
         self.organize_channel = 'organize'
         self.watch_listener   = StoreWatchListener(signal = self.watch_channel)
         # TODO : change this to  a weak ref
+        # TODO : get rid of this hack once cc-4235 is fixed
         self.__timeout_thread = ManagerTimeout(self)
         self.__timeout_thread.daemon = True
         self.__timeout_thread.start()

From 974858c8f50bdad9122d66109891d81602cd222d Mon Sep 17 00:00:00 2001
From: Rudi Grinberg <rudi.grinberg@sourcefabric.org>
Date: Thu, 16 Aug 2012 14:34:40 -0400
Subject: [PATCH 2/6] MM2: fixed bug where index file wans't being created

---
 python_apps/media-monitor2/media/monitor/listeners.py | 4 ++--
 python_apps/media-monitor2/mm2.py                     | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/python_apps/media-monitor2/media/monitor/listeners.py b/python_apps/media-monitor2/media/monitor/listeners.py
index 48a4cd5bf..6858527b9 100644
--- a/python_apps/media-monitor2/media/monitor/listeners.py
+++ b/python_apps/media-monitor2/media/monitor/listeners.py
@@ -133,8 +133,8 @@ class StoreWatchListener(BaseListener, Loggable, pyinotify.ProcessEvent):
     @IncludeOnly(mmp.supported_extensions)
     def process_delete(self, event):
         evt = None
-        if event.dir: evt = DeleteDir(event)
-        else: evt = DeleteFile(event)
+        if event.dir : evt = DeleteDir(event)
+        else         : evt = DeleteFile(event)
         dispatcher.send(signal=self.signal, sender=self, event=evt)
         return evt
 
diff --git a/python_apps/media-monitor2/mm2.py b/python_apps/media-monitor2/mm2.py
index 849d7ae6b..752076da2 100644
--- a/python_apps/media-monitor2/mm2.py
+++ b/python_apps/media-monitor2/mm2.py
@@ -57,7 +57,7 @@ def main(global_config, api_client_config, log_config,
         if not os.path.exists(config['index_path']):
             log.info("Attempting to create index file:...")
             try:
-                with open(config['index_path']) as f: f.write(" ")
+                with open(config['index_path'], 'w') as f: f.write(" ")
             except Exception as e:
                 log.info("Failed to create index file with exception: %s" % str(e))
             else:

From 062e7bbe8b229a02ccd906d25247f609f281dda4 Mon Sep 17 00:00:00 2001
From: Rudi Grinberg <rudi.grinberg@sourcefabric.org>
Date: Thu, 16 Aug 2012 15:24:36 -0400
Subject: [PATCH 3/6] MM2: added listener test

---
 .../media-monitor2/tests/test_listeners.py    | 77 +++++++++++++++++++
 1 file changed, 77 insertions(+)
 create mode 100644 python_apps/media-monitor2/tests/test_listeners.py

diff --git a/python_apps/media-monitor2/tests/test_listeners.py b/python_apps/media-monitor2/tests/test_listeners.py
new file mode 100644
index 000000000..0d99c46bf
--- /dev/null
+++ b/python_apps/media-monitor2/tests/test_listeners.py
@@ -0,0 +1,77 @@
+import os, shutil
+import time
+import pyinotify
+import unittest
+from pydispatch import dispatcher
+
+from media.monitor.listeners import OrganizeListener
+from media.monitor.events import OrganizeFile
+
+from os.path import join, normpath, abspath
+
+def create_file(p):
+    with open(p, 'w') as f: f.write(" ")
+
+class TestOrganizeListener(unittest.TestCase):
+    def setUp(self):
+        self.organize_path = 'test_o'
+        self.sig = 'org'
+        def my_abs_path(x):
+            return normpath(join(os.getcwd(), x))
+        self.sample_files = [ my_abs_path(join(self.organize_path, f))
+                for f in [ "gogi.mp3",
+                           "gio.mp3",
+                           "mimino.ogg" ] ]
+        os.mkdir(self.organize_path)
+
+    def test_flush_events(self):
+        org = self.create_org()
+        self.create_sample_files()
+        received = [0]
+        def pass_event(sender, event):
+            if isinstance(event, OrganizeFile):
+                received[0] += 1
+                self.assertTrue( abspath(event.path) in self.sample_files )
+        dispatcher.connect(pass_event, signal=self.sig, sender=dispatcher.Any,
+                weak=True)
+        org.flush_events( self.organize_path )
+        self.assertEqual( received[0], len(self.sample_files) )
+        self.delete_sample_files()
+
+    def test_process(self):
+        org = self.create_org()
+        received = [0]
+        def pass_event(sender, event):
+            if isinstance(event, OrganizeFile):
+                self.assertTrue( event.path in self.sample_files )
+                received[0] += 1
+        dispatcher.connect(pass_event, signal=self.sig, sender=dispatcher.Any,
+                weak=True)
+        wm = pyinotify.WatchManager()
+        def stopper(notifier):
+            return received[0] == len(self.sample_files)
+        tn = pyinotify.ThreadedNotifier(wm, default_proc_fun=org)
+        tn.daemon = True
+        tn.start()
+        wm.add_watch(self.organize_path, pyinotify.ALL_EVENTS, rec=True,
+                auto_add=True)
+        time.sleep(0.5)
+        self.create_sample_files()
+        time.sleep(1)
+        self.assertEqual( len(self.sample_files), received[0] )
+        self.delete_sample_files()
+
+    def tearDown(self):
+        shutil.rmtree(self.organize_path)
+
+    def create_sample_files(self):
+        for f in self.sample_files: create_file(f)
+
+    def delete_sample_files(self):
+        for f in self.sample_files: os.remove(f)
+
+    def create_org(self):
+        return OrganizeListener( signal=self.sig )
+
+if __name__ == '__main__': unittest.main()
+

From 6b841a0fc448098940f83dac14d5a8c8f5e1f358 Mon Sep 17 00:00:00 2001
From: denise <denise@denise-DX4860.(none)>
Date: Thu, 16 Aug 2012 17:11:48 -0400
Subject: [PATCH 4/6] CC-4239: Playlist: need to improve error msg "Something
 went wrong"

-fixed
---
 airtime_mvc/public/js/airtime/library/spl.js | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/airtime_mvc/public/js/airtime/library/spl.js b/airtime_mvc/public/js/airtime/library/spl.js
index 7c38352ef..fc6bc7210 100644
--- a/airtime_mvc/public/js/airtime/library/spl.js
+++ b/airtime_mvc/public/js/airtime/library/spl.js
@@ -17,7 +17,8 @@ var AIRTIME = (function(AIRTIME){
 		width;
 	
 	function isTimeValid(time) {
-		var regExpr = new RegExp("^\\d{2}[:]\\d{2}[:]\\d{2}([.]\\d{1,6})?$");
+		//var regExpr = new RegExp("^\\d{2}[:]\\d{2}[:]\\d{2}([.]\\d{1,6})?$");
+	    var regExpr = new RegExp("^\\d{2}[:]([0-5]){1}([0-9]){1}[:]([0-5]){1}([0-9]){1}([.]\\d{1,6})?$");
 		
 		return regExpr.test(time);
 	}

From 33f38190e9d64f490b72a31364956fdda7e6c197 Mon Sep 17 00:00:00 2001
From: Rudi Grinberg <rudi.grinberg@sourcefabric.org>
Date: Thu, 16 Aug 2012 17:27:43 -0400
Subject: [PATCH 5/6] MM2: removed bad comments and possible bug

---
 python_apps/media-monitor2/media/monitor/pure.py | 11 ++---------
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/python_apps/media-monitor2/media/monitor/pure.py b/python_apps/media-monitor2/media/monitor/pure.py
index 8bc1639c0..30742c236 100644
--- a/python_apps/media-monitor2/media/monitor/pure.py
+++ b/python_apps/media-monitor2/media/monitor/pure.py
@@ -229,20 +229,13 @@ def normalized_metadata(md, original_path):
     for k,v in new_md.iteritems(): new_md[k] = unicode(v).replace('/','-')
     # Specific rules that are applied in a per attribute basis
     format_rules = {
-        # It's very likely that the following isn't strictly necessary. But the
-        # old code would cast MDATA_KEY_TRACKNUMBER to an integer as a
-        # byproduct of formatting the track number to 2 digits.
         'MDATA_KEY_TRACKNUMBER' : parse_int,
         'MDATA_KEY_BITRATE'     : lambda x: str(int(x) / 1000) + "kbps",
         'MDATA_KEY_FILEPATH'    : lambda x: os.path.normpath(x),
         'MDATA_KEY_MIME'        : lambda x: x.replace('-','/'),
         'MDATA_KEY_BPM'         : lambda x: x[0:8],
     }
-    # note that we could have saved a bit of code by rewriting new_md using
-    # defaultdict(lambda x: "unknown"). But it seems to be too implicit and
-    # could possibly lead to subtle bugs down the road. Plus the following
-    # approach gives us the flexibility to use different defaults for different
-    # attributes
+
     new_md = remove_whitespace(new_md)
     new_md = apply_rules_dict(new_md, format_rules)
     new_md = default_to(dictionary=new_md, keys=['MDATA_KEY_TITLE'],
@@ -287,7 +280,7 @@ def organized_path(old_path, root_path, orig_md):
         yyyy, mm, _ = normal_md['MDATA_KEY_YEAR'].split('-',3)
         path = os.path.join(root_path, yyyy, mm)
         filepath = os.path.join(path,fname)
-    elif normal_md['MDATA_KEY_TRACKNUMBER'] == unicode_unknown:
+    elif len(normal_md['MDATA_KEY_TRACKNUMBER']) == 0:
         fname = u'%s-%s.%s' % (normal_md['MDATA_KEY_TITLE'],
                 normal_md['MDATA_KEY_BITRATE'], ext)
         path = os.path.join(root_path, normal_md['MDATA_KEY_CREATOR'],

From 7ceb9bd84a7d5965e12b606359721faa47a5fb01 Mon Sep 17 00:00:00 2001
From: Rudi Grinberg <rudi.grinberg@sourcefabric.org>
Date: Thu, 16 Aug 2012 17:32:54 -0400
Subject: [PATCH 6/6] MM2: removed distracting logging

---
 python_apps/media-monitor2/media/monitor/listeners.py | 7 ++++---
 python_apps/media-monitor2/mm1.99.sh                  | 2 +-
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/python_apps/media-monitor2/media/monitor/listeners.py b/python_apps/media-monitor2/media/monitor/listeners.py
index 6858527b9..18a1925c5 100644
--- a/python_apps/media-monitor2/media/monitor/listeners.py
+++ b/python_apps/media-monitor2/media/monitor/listeners.py
@@ -65,15 +65,16 @@ class BaseListener(object):
 
 class OrganizeListener(BaseListener, pyinotify.ProcessEvent, Loggable):
     def process_IN_CLOSE_WRITE(self, event):
-        self.logger.info("===> handling: '%s'" % str(event))
+        #self.logger.info("===> handling: '%s'" % str(event))
         self.process_to_organize(event)
     # got cookie
     def process_IN_MOVED_TO(self, event):
-        self.logger.info("===> handling: '%s'" % str(event))
+        #self.logger.info("===> handling: '%s'" % str(event))
         self.process_to_organize(event)
 
     def process_default(self, event):
-        self.logger.info("===> Not handling: '%s'" % str(event))
+        pass
+        #self.logger.info("===> Not handling: '%s'" % str(event))
 
     def flush_events(self, path):
         """
diff --git a/python_apps/media-monitor2/mm1.99.sh b/python_apps/media-monitor2/mm1.99.sh
index b3f9621e6..aeae5a3ca 100755
--- a/python_apps/media-monitor2/mm1.99.sh
+++ b/python_apps/media-monitor2/mm1.99.sh
@@ -1,4 +1,4 @@
 #export PYTHONPATH="/home/rudi/Airtime/python_apps/:/home/rudi/Airtime/python_apps/media-monitor2/"
 PYTHONPATH='/home/rudi/Airtime/python_apps/:/home/rudi/Airtime/python_apps/media-monitor2/'
 export PYTHONPATH
-python ./mm2.py --config="/home/rudi/Airtime/python_apps/media-monitor2/tests/live_client.cfg" --apiclient="/home/rudi/Airtime/python_apps/media-monitor2/tests/live_client.cfg" --log="/home/rudi/Airtime/python_apps/media-monitor/logging.cfg"
+python ./mm2.py --config="/etc/airtime/media-monitor.cfg" --apiclient="/etc/airtime/api_client.cfg" --log="/home/rudi/Airtime/python_apps/media-monitor/logging.cfg"