Big threading update, most things are asynchronous now
authorKristoffer Grönlund <kristoffer.gronlund@purplescout.se>
Sat, 9 Jan 2010 01:47:22 +0000 (02:47 +0100)
committerKristoffer Grönlund <kristoffer.gronlund@purplescout.se>
Sat, 9 Jan 2010 01:47:22 +0000 (02:47 +0100)
jamaendo/api.py
jamaui/favorites.py
jamaui/fetcher.py
jamaui/showalbum.py
jamaui/showartist.py
jamaui/ui.py

index ca4e51f..8bc2353 100644 (file)
@@ -694,9 +694,9 @@ def get_albums(artist_id):
     """Returns: [Album]
     Parameter can either be an artist_id or a list of album ids.
     """
+    if isinstance(artist_id, list):
+        return get_album_list(artist_id)
     with _APILOCK:
-        if isinstance(artist_id, list):
-            return get_album_list(artist_id)
         a = _artists.get(artist_id, None)
         if a and a.albums:
             return a.albums
@@ -747,9 +747,9 @@ def get_tracks(album_id):
     """Returns: [Track]
     Parameter can either be an album_id or a list of track ids.
     """
+    if isinstance(album_id, list):
+        return get_track_list(album_id)
     with _APILOCK:
-        if isinstance(album_id, list):
-            return get_track_list(album_id)
         a = _albums.get(album_id, None)
         if a and a.tracks:
             return a.tracks
index 6e829ac..ef58143 100644 (file)
@@ -21,7 +21,6 @@
 #  Copyright (c) 2008-05-26 Thomas Perl <thpinfo.com>
 #  (based on http://pygstdocs.berlios.de/pygst-tutorial/seeking.html)
 #
-import gtk
 try:
     import hildon
 except:
@@ -32,8 +31,10 @@ from showartist import ShowArtist
 from showalbum import ShowAlbum
 from settings import settings
 import logging
+from fetcher import Fetcher
+import itertools
 
-from albumlist import AlbumList
+from albumlist import MusicList
 
 log = logging.getLogger(__name__)
 
@@ -47,51 +48,66 @@ class FavoritesWindow(hildon.StackableWindow):
     def __init__(self):
         hildon.StackableWindow.__init__(self)
         self.set_title("Favorites")
-
-        if settings.user:
-            # Results list
-            self.panarea = hildon.PannableArea()
-            self.results = AlbumList()
-            self.results.connect('row-activated', self.row_activated)
-            self.panarea.add(self.results)
-
-            self.idmap = {}
-
-            def add_album(ID, album_factory):
-                if ID not in self.idmap:
-                    album = album_factory()
-                    self.idmap[ID] = album
-                    self.results.add_album(album)
-
-            try:
-                for item in jamaendo.favorite_albums(settings.user):
-                    add_album(item.ID, lambda: item)
-            except jamaendo.JamendoAPIException, e:
-                msg = "Query failed, is the user name '%s' correct?" % (settings.user)
-                banner = hildon.hildon_banner_show_information(self, '',
-                                                               msg)
-                banner.set_timeout(3000)
-
-            favorite_albums = [f[1] for f in settings.favorites if isinstance(f, tuple) and len(f) == 2 and f[0] == 'album' and f[1] not in self.idmap]
-            try:
-                for album in jamaendo.get_albums(favorite_albums):
-                    add_album(album.ID, lambda: album)
-
-            except jamaendo.JamendoAPIException, e:
-                log.exception("jamaendo.get_albums(%s)"%(favorite_albums))
-
-            self.add(self.panarea)
-
+        self.connect('destroy', self.on_destroy)
+        self.fetcher = None
+        self.idmap = {}
+
+        self.panarea = hildon.PannableArea()
+        self.favorites = MusicList()
+        self.favorites.connect('row-activated', self.row_activated)
+        self.panarea.add(self.favorites)
+        self.add(self.panarea)
+
+        if not settings.user:
+            self.favorites.loading_message = """give your username
+to the settings dialog
+favorites appear
+"""
         else:
-            vbox = gtk.VBox()
-            lbl = gtk.Label()
-            lbl.set_markup("""<span size="xx-large">jamendo.com
-in the settings dialog
-enter your username</span>
-""")
-            lbl.set_single_line_mode(False)
-            vbox.pack_start(lbl, True, False)
-            self.add(vbox)
+            self.favorites.loading_message = """Loading favorites"""
+
+        self.start_favorites_fetcher()
+
+    def on_destroy(self, wnd):
+        if self.fetcher:
+            self.fetcher.stop()
+            self.fetcher = None
+
+    def start_favorites_fetcher(self):
+        if self.fetcher:
+            self.fetcher.stop()
+            self.fetcher = None
+
+        def gen():
+            generated = []
+            for item in jamaendo.favorite_albums(settings.user):
+                generated.append(item.ID)
+                yield item
+            fav = [f[1] for f in settings.favorites \
+                       if isinstance(f, tuple) and \
+                       len(f) == 2 and \
+                       f[0] == 'album' and \
+                       f[1] not in generated]
+            for item in jamaendo.get_albums(fav):
+                yield item
+
+        self.fetcher = Fetcher(gen,
+                               self,
+                               on_item = self.on_favorites_result,
+                               on_ok = self.on_favorites_complete,
+                               on_fail = self.on_favorites_complete)
+        self.fetcher.start()
+
+    def on_favorites_result(self, wnd, item):
+        if wnd is self:
+            if item.ID not in self.idmap:
+                self.idmap[item.ID] = item
+                self.favorites.add_items([item])
+
+    def on_favorites_complete(self, wnd, error=None):
+        if wnd is self:
+            self.fetcher.stop()
+            self.fetcher = None
 
     def get_item_text(self, item):
         if isinstance(item, jamaendo.Album):
@@ -101,25 +117,11 @@ enter your username</span>
         else:
             return item.name
 
-    def make_button(self, text, subtext, callback):
-        button = hildon.Button(gtk.HILDON_SIZE_FINGER_HEIGHT,
-                               hildon.BUTTON_ARRANGEMENT_VERTICAL)
-        button.set_text(text, subtext)
-
-        if callback:
-            button.connect('clicked', callback)
-
-        #image = gtk.image_new_from_stock(gtk.STOCK_INFO, gtk.ICON_SIZE_BUTTON)
-        #button.set_image(image)
-        #button.set_image_position(gtk.POS_RIGHT)
-
-        return button
-
     def row_activated(self, treeview, path, view_column):
-        _id = self.results.get_album_id(path)
-        item = self.idmap[_id]
-        #print _id, item
-        self.open_item(item)
+        _id = self.favorites.get_item_id(path)
+        item = self.idmap.get(_id)
+        if item:
+            self.open_item(item)
 
     def open_item(self, item):
         if isinstance(item, jamaendo.Album):
index e4fa3e0..eb1d08d 100644 (file)
@@ -9,6 +9,7 @@ from postoffice import postoffice
 import jamaendo
 import logging
 
+import gobject
 import gtk
 import hildon
 
@@ -22,13 +23,19 @@ class _Worker(threading.Thread):
         self.owner = owner
 
     def _post(self, item):
-        postoffice.notify("fetch", self.owner, item)
+        def idle_fetch(owner, item):
+            postoffice.notify("fetch", owner, item)
+        gobject.idle_add(idle_fetch, self.owner, item)
 
     def _post_ok(self):
-        postoffice.notify("fetch-ok", self.owner)
+        def idle_fetch_ok(owner):
+            postoffice.notify("fetch-ok", owner)
+        gobject.idle_add(idle_fetch_ok, self.owner)
 
     def _post_fail(self, e):
-        postoffice.notify("fetch-fail", self.owner, e)
+        def idle_fetch_fail(owner, e):
+            postoffice.notify("fetch-fail", owner, e)
+        gobject.idle_add(idle_fetch_fail, self.owner, e)
 
     def run(self):
         try:
index f1933d2..a1aec5c 100644 (file)
@@ -34,6 +34,8 @@ from settings import settings
 from postoffice import postoffice
 import util
 import logging
+import thread
+import gobject
 from albumlist import TrackList
 from playlists import add_to_playlist
 from fetcher import Fetcher
@@ -160,8 +162,19 @@ class ShowAlbum(hildon.StackableWindow):
         return btn
 
     def on_goto_artist(self, btn):
-        artist = jamaendo.get_artist(int(self.album.artist_id))
-        self.open_item(artist)
+        def threadfun(wnd, artist_id):
+            try:
+                artist = jamaendo.get_artist(artist_id)
+                def oncomplete(wnd, artist):
+                    wnd.open_item(artist)
+                    hildon.hildon_gtk_window_set_progress_indicator(wnd, 0)
+                gobject.idle_add(oncomplete, wnd, artist)
+            except:
+                def onfail(wnd):
+                    hildon.hildon_gtk_window_set_progress_indicator(wnd, 0)
+                gobject.idle_add(onfail, wnd)
+        hildon.hildon_gtk_window_set_progress_indicator(self, 1)
+        thread.start_new_thread(threadfun, (self, int(self.album.artist_id)))
 
     def on_download(self, btn):
         banner = hildon.hildon_banner_show_information(self, '', "Opening in web browser")
index 1a6557f..9b49b4e 100644 (file)
@@ -91,6 +91,7 @@ class ShowArtist(hildon.StackableWindow):
         self.start_album_fetcher()
 
     def on_destroy(self, wnd):
+        postoffice.disconnect('images', self)
         if self.fetcher:
             self.fetcher.stop()
             self.fetcher = None
@@ -131,15 +132,45 @@ class ShowArtist(hildon.StackableWindow):
         self.menu.show_all()
         self.set_app_menu(self.menu)
 
+    def start_addpl_fetcher(self):
+        if self.fetcher:
+            self.fetcher.stop()
+            self.fetcher = None
+        def fetchgen():
+            for album in self.albumlist:
+                yield jamaendo.get_tracks(album.ID)
+            raise StopIteration
+        self.fetcher = Fetcher(fetchgen, self,
+                               on_item = self.on_addpl_result,
+                               on_ok = self.on_addpl_complete,
+                               on_fail = self.on_addpl_complete)
+        self.fetcher.tracklist = []
+        self.fetcher.pdlg = gtk.Dialog("Fetching album tracks", self)
+        self.fetcher.pbar = gtk.ProgressBar()
+        self.fetcher.pbar.set_fraction(0)
+        self.fetcher.pdlg.vbox.add(self.fetcher.pbar)
+        self.fetcher.pdlg.show_all()
+        self.fetcher.ppos = 1
+        self.fetcher.start()
+
+    def on_addpl_result(self, wnd, items):
+        if wnd is self:
+            self.fetcher.tracklist.extend(items)
+            self.fetcher.ppos += 1
+            self.fetcher.pbar.set_fraction(float(self.fetcher.ppos)/float(len(self.albumlist)+1))
+
+    def on_addpl_complete(self, wnd, error=None):
+        if wnd is self:
+            self.fetcher.stop()
+            self.fetcher.pdlg.destroy()
+            if self.fetcher.tracklist:
+                add_to_playlist(self, self.fetcher.tracklist)
+            self.fetcher = None
+
+
     def on_add_to_playlist(self, button, user_data=None):
         if self.albumlist:
-            try:
-                tracklist = []
-                for album in self.albumlist:
-                    tracklist.extend(jamaendo.get_tracks(album.ID))
-                add_to_playlist(self, tracklist)
-            except jamaendo.JamendoAPIException:
-                log.exception("Failed to get track list for artist %s", self.artist.ID)
+            self.start_addpl_fetcher()
         else:
             show_banner(self, "Error when opening track list")
 
@@ -170,15 +201,37 @@ class ShowArtist(hildon.StackableWindow):
                 if pb:
                     self.image.set_from_pixbuf(pb)
 
-    def on_destroy(self, wnd):
-        postoffice.disconnect('images', self)
+    def start_albumplay_fetcher(self, ID):
+        if self.fetcher:
+            self.fetcher.stop()
+            self.fetcher = None
+        def albumgen():
+            yield jamaendo.get_album(ID)
+            raise StopIteration
+        self.fetcher = Fetcher(albumgen, self,
+                               on_item = self.on_albumplay_result,
+                               on_ok = self.on_albumplay_complete,
+                               on_fail = self.on_albumplay_complete)
+        self.fetcher.album = None
+        self.fetcher.start()
+
+    def on_albumplay_result(self, wnd, item):
+        if wnd is self:
+            if isinstance(item, list):
+                self.fetcher.album = item[0]
+            else:
+                self.fetcher.album = item
+
+    def on_albumplay_complete(self, wnd, error=None):
+        if wnd is self:
+            self.fetcher.stop()
+            if self.fetcher.album:
+                self.open_item(self.fetcher.album)
+            self.fetcher = None
 
     def row_activated(self, treeview, path, view_column):
         _id = self.albums.get_album_id(path)
-        album = jamaendo.get_album(_id)
-        if isinstance(album, list):
-            album = album[0]
-        self.open_item(album)
+        self.start_albumplay_fetcher(_id)
 
     def open_item(self, item):
         if isinstance(item, jamaendo.Album):
index 100be8d..ac1c6a8 100644 (file)
@@ -286,7 +286,9 @@ JAMENDO is an online platform that distributes musical works under Creative Comm
         self.create_menu()
         self.setup_widgets()
         self.window.show_all()
+        gtk.gdk.threads_enter()
         gtk.main()
+        gtk.gdk.threads_leave()
         ossohelper.application_exit()
 
 if __name__=="__main__":