hmm, asynchronous api is nontrivial
authorKristoffer Grönlund <kristoffer.gronlund@purplescout.se>
Fri, 1 Jan 2010 04:16:35 +0000 (05:16 +0100)
committerKristoffer Grönlund <kristoffer.gronlund@purplescout.se>
Sat, 2 Jan 2010 23:37:45 +0000 (00:37 +0100)
jamaendo/api.py
jamaui/playerwindow.py
jamaui/showalbum.py

index 1e052a8..d026770 100644 (file)
@@ -226,6 +226,45 @@ class Query(object):
     def execute(self):
         raise NotImplemented
 
+import threading
+
+class CoverFetcher(threading.Thread):
+    def __init__(self):
+        threading.Thread.__init__(self)
+        self.setDaemon(True)
+        self.cond = threading.Condition()
+        self.work = []
+
+    def _fetch_cover(self, albumid, size):
+        coverdir = _COVERDIR if _COVERDIR else '/tmp'
+        to = os.path.join(coverdir, '%d-%d.jpg'%(albumid, size))
+        if not os.path.isfile(to):
+            url = _GET2+'image/album/redirect/?id=%d&imagesize=%d'%(albumid, size)
+            urllib.urlretrieve(url, to)
+        return to
+
+    def request_cover(self, albumid, size, cb):
+        self.cond.acquire()
+        self.work.insert(0, (albumid, size, cb))
+        self.cond.notify()
+        self.cond.release()
+
+    def run(self):
+        while True:
+            work = []
+            self.cond.acquire()
+            while True:
+                work = self.work
+                if work:
+                    self.work = []
+                    break
+                self.cond.wait()
+            self.cond.release()
+
+            for albumid, size, cb in work:
+                cover = self._fetch_cover(albumid, size)
+                cb(albumid, size, cover)
+
 class CoverCache(object):
     """
     cache and fetch covers
@@ -243,6 +282,8 @@ class CoverCache(object):
                 m = covermatch.match(fil)
                 if m and os.path.isfile(fl):
                     self._covers[(int(m.group(1)), int(m.group(2)))] = fl
+        self._fetcher = CoverFetcher()
+        self._fetcher.start()
 
     def fetch_cover(self, albumid, size):
         coverdir = _COVERDIR if _COVERDIR else '/tmp'
@@ -264,9 +305,7 @@ class CoverCache(object):
         if cover:
             cb(cover)
         else:
-            # TODO
-            cover = self.fetch_cover(albumid, size)
-            cb(cover)
+            self._fetcher.request_cover(albumid, size, cb)
 
 _cover_cache = CoverCache()
 
index 1c2316d..65fe075 100644 (file)
@@ -27,11 +27,22 @@ import jamaendo
 from settings import settings
 from player import Playlist, the_player
 
+_player_window = None
+
+def album_cover_receiver(albumid, size, cover):
+    if _player_window:
+        playing = _player_window.get_album_id()
+        if int(playing) == int(albumid):
+            _player_window.set_album_cover(cover)
+
 class PlayerWindow(hildon.StackableWindow):
     def __init__(self, playlist=None):
         hildon.StackableWindow.__init__(self)
         self.set_title("jamaendo")
 
+        global _player_window
+        _player_window = self
+
         self.connect('hide', self.on_hide)
         self.connect('destroy', self.on_destroy)
 
@@ -94,11 +105,18 @@ class PlayerWindow(hildon.StackableWindow):
 
         print "Created player window, playlist: %s" % (self.playlist)
 
+    def get_album_id(self):
+        if self.playlist and self.playlist.current_index() > -1:
+            return self.playlist.current().album_id
+        return None
+
     def on_hide(self, wnd):
         print "Hiding player window"
 
     def on_destroy(self, wnd):
         print "Destroying player window"
+        global _player_window
+        _player_window = None
         if self.player:
             self.player.stop()
 
@@ -133,9 +151,13 @@ class PlayerWindow(hildon.StackableWindow):
             print "current:", item
             self.set_labels(item.name, item.artist_name, item.album_name,
                             self.playlist.current_index(), self.playlist.size())
-            coverfile = jamaendo.get_album_cover(int(item.album_id), size=200)
-            print "coverfile:", coverfile
-            self.cover.set_from_file(coverfile)
+            jamaendo.get_album_cover_async(album_cover_receiver, int(item.album_id), size=200)
+            #coverfile = jamaendo.get_album_cover(int(item.album_id), size=200)
+            #print "coverfile:", coverfile
+            #self.cover.set_from_file(coverfile)
+
+    def set_album_cover(self, cover):
+        self.cover.set_from_file(cover)
 
     def play_tracks(self, tracks):
         self.playlist = Playlist(tracks)
index ad31439..c95974e 100644 (file)
@@ -28,12 +28,24 @@ from playerwindow import open_playerwindow
 from settings import settings
 import util
 
+_instance = None
+
+def album_cover_receiver(albumid, size, cover):
+    if _instance:
+        playing = _instance.get_album_id()
+        if int(playing) == int(albumid):
+            _instance.set_album_cover(cover)
+
 class ShowAlbum(hildon.StackableWindow):
     def __init__(self, album):
         hildon.StackableWindow.__init__(self)
         self.set_title("Album")
         self.album = album
 
+        global _instance
+        _instance = self
+        self.connect('destroy', self.on_destroy)
+
         top_vbox = gtk.VBox()
         top_hbox = gtk.HBox()
         vbox1 = gtk.VBox()
@@ -92,11 +104,16 @@ class ShowAlbum(hildon.StackableWindow):
 
         self.add(top_vbox)
 
+        # here it's probably ok to get the cover synchronously..
         coverfile = jamaendo.get_album_cover(self.album.ID, size=200)
         self.cover.set_from_file(coverfile)
 
         self.show_all()
 
+    def on_destroy(self, wnd):
+        global _instance
+        _instance = None
+
     def make_imagebutton(self, name, cb):
         btn = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
         btn.set_relief(gtk.RELIEF_NONE)