More screens updated to do background fetching
authorKristoffer Grönlund <kristoffer.gronlund@purplescout.se>
Fri, 8 Jan 2010 01:27:34 +0000 (02:27 +0100)
committerKristoffer Grönlund <kristoffer.gronlund@purplescout.se>
Fri, 8 Jan 2010 01:27:34 +0000 (02:27 +0100)
jamaui/featured.py
jamaui/fetcher.py
jamaui/player.py
jamaui/playerwindow.py
jamaui/radios.py
jamaui/search.py

index 16ec929..b85ec5a 100644 (file)
@@ -32,6 +32,7 @@ from showartist import ShowArtist
 from showalbum import ShowAlbum
 from albumlist import MusicList
 from player import Playlist
 from showalbum import ShowAlbum
 from albumlist import MusicList
 from player import Playlist
+from fetcher import Fetcher
 import logging
 
 log = logging.getLogger(__name__)
 import logging
 
 log = logging.getLogger(__name__)
@@ -59,6 +60,8 @@ class FeaturedWindow(hildon.StackableWindow):
         hildon.StackableWindow.__init__(self)
         self.set_title(feature)
 
         hildon.StackableWindow.__init__(self)
         self.set_title(feature)
 
+        self.fetcher = None
+        self.connect('destroy', self.on_destroy)
         self.featurefn = _alist(self.features, feature)
 
         # Results list
         self.featurefn = _alist(self.features, feature)
 
         # Results list
@@ -68,19 +71,35 @@ class FeaturedWindow(hildon.StackableWindow):
         self.panarea.add(self.musiclist)
 
         self.idmap = {}
         self.panarea.add(self.musiclist)
 
         self.idmap = {}
-        try:
-            self.items = self.featurefn()
-            for item in self.items:
-                self.idmap[item.ID] = item
-            self.musiclist.add_items(self.items)
-        except jamaendo.JamendoAPIException:
-            log.exception('failed to get %s' % (feature))
-            self.items = []
+        self.items = []
 
         self.add(self.panarea)
 
         self.create_menu()
 
 
         self.add(self.panarea)
 
         self.create_menu()
 
+        self.start_feature_fetcher()
+
+    def start_feature_fetcher(self):
+        if self.fetcher:
+            self.fetcher.stop()
+            self.fetcher = None
+        self.fetcher = Fetcher(self.featurefn, self,
+                               on_item = self.on_feature_result,
+                               on_ok = self.on_feature_complete,
+                               on_fail = self.on_feature_complete)
+        self.fetcher.start()
+
+    def on_feature_result(self, wnd, item):
+        if wnd is self:
+            self.musiclist.add_items([item])
+            self.idmap[item.ID] = item
+            self.items.append(item)
+
+    def on_feature_complete(self, wnd, error=None):
+        if wnd is self:
+            self.fetcher.stop()
+            self.fetcher = None
+
     def create_menu(self):
         def on_player(*args):
             from playerwindow import open_playerwindow
     def create_menu(self):
         def on_player(*args):
             from playerwindow import open_playerwindow
@@ -93,6 +112,11 @@ class FeaturedWindow(hildon.StackableWindow):
         self.menu.show_all()
         self.set_app_menu(self.menu)
 
         self.menu.show_all()
         self.set_app_menu(self.menu)
 
+    def on_destroy(self, wnd):
+        if self.fetcher:
+            self.fetcher.stop()
+            self.fetcher = None
+
     def row_activated(self, treeview, path, view_column):
         _id = self.musiclist.get_item_id(path)
         item = self.idmap[_id]
     def row_activated(self, treeview, path, view_column):
         _id = self.musiclist.get_item_id(path)
         item = self.idmap[_id]
@@ -111,9 +135,29 @@ class FeaturedWindow(hildon.StackableWindow):
             wnd = open_playerwindow()
             wnd.play_tracks(playlist)
         elif isinstance(item, jamaendo.Tag):
             wnd = open_playerwindow()
             wnd.play_tracks(playlist)
         elif isinstance(item, jamaendo.Tag):
-            try:
+            self.start_tag_fetcher(item.ID)
+
+    def start_tag_fetcher(self, item_id):
+        if self.fetcher:
+            self.fetcher.stop()
+            self.fetcher = None
+        self.fetcher = Fetcher(lambda: jamaendo.get_tag_tracks(item_id),
+                               self,
+                               on_item = self.on_tag_result,
+                               on_ok = self.on_tag_complete,
+                               on_fail = self.on_tag_complete)
+        self.fetcher.taglist = []
+        self.fetcher.start()
+
+    def on_tag_result(self, wnd, item):
+        if wnd is self and hasattr(self.fetcher, 'taglist'):
+            self.fetcher.taglist.append(item)
+
+    def on_tag_complete(self, wnd, error=None):
+        if wnd is self:
+            self.fetcher.stop()
+            if error is not None and hasattr(self.fetcher, 'taglist'):
                 wnd = open_playerwindow()
                 wnd = open_playerwindow()
-                wnd.play_tracks(jamaendo.get_tag_tracks(item.ID))
-            except jamaendo.JamendoAPIException:
-                log.exception('Failed to get tracks for %s' % (item.ID))
+                wnd.play_tracks(self.fetcher.taglist)
+            self.fetcher = None
 
 
index d6f5ff0..e4fa3e0 100644 (file)
@@ -9,6 +9,7 @@ from postoffice import postoffice
 import jamaendo
 import logging
 
 import jamaendo
 import logging
 
+import gtk
 import hildon
 
 log = logging.getLogger(__name__)
 import hildon
 
 log = logging.getLogger(__name__)
@@ -34,7 +35,7 @@ class _Worker(threading.Thread):
             for item in self.generator():
                 self._post(item)
             self._post_ok()
             for item in self.generator():
                 self._post(item)
             self._post_ok()
-        except jamaendo.JamendoAPIError, e:
+        except jamaendo.JamendoAPIException, e:
             log.exception("Failed to fetch, id %s" % (self.owner))
             self._post_fail(e)
 
             log.exception("Failed to fetch, id %s" % (self.owner))
             self._post_fail(e)
 
@@ -53,17 +54,20 @@ class Fetcher(object):
 
     def _on_ok_cb(self, i):
         self.on_ok(i)
 
     def _on_ok_cb(self, i):
         self.on_ok(i)
-        hildon.hildon_gtk_window_set_progress_indicator(self.owner, 0)
+        if isinstance(self.owner, gtk.Window):
+            hildon.hildon_gtk_window_set_progress_indicator(self.owner, 0)
 
     def _on_fail_cb(self, i, e):
         self.on_fail(i, e)
 
     def _on_fail_cb(self, i, e):
         self.on_fail(i, e)
-        hildon.hildon_gtk_window_set_progress_indicator(self.owner, 0)
+        if isinstance(self.owner, gtk.Window):
+            hildon.hildon_gtk_window_set_progress_indicator(self.owner, 0)
 
     def start(self):
         postoffice.connect('fetch', self, self._on_item_cb)
         postoffice.connect('fetch-ok', self, self._on_ok_cb)
         postoffice.connect('fetch-fail', self, self._on_fail_cb)
 
     def start(self):
         postoffice.connect('fetch', self, self._on_item_cb)
         postoffice.connect('fetch-ok', self, self._on_ok_cb)
         postoffice.connect('fetch-fail', self, self._on_fail_cb)
-        hildon.hildon_gtk_window_set_progress_indicator(self.owner, 1)
+        if isinstance(self.owner, gtk.Window):
+            hildon.hildon_gtk_window_set_progress_indicator(self.owner, 1)
         self.worker = _Worker(self.generator, self.owner)
         self.worker.start()
 
         self.worker = _Worker(self.generator, self.owner)
         self.worker.start()
 
index 7908dea..31211eb 100644 (file)
@@ -28,6 +28,7 @@ import dbus
 import jamaendo
 from settings import settings
 from postoffice import postoffice
 import jamaendo
 from settings import settings
 from postoffice import postoffice
+from fetcher import Fetcher
 
 log = logging.getLogger(__name__)
 
 
 log = logging.getLogger(__name__)
 
@@ -349,51 +350,76 @@ class Player(object):
         self.backend = PlayerBackend()
         self.backend.set_eos_callback(self._on_eos)
         self.playlist = Playlist()
         self.backend = PlayerBackend()
         self.backend.set_eos_callback(self._on_eos)
         self.playlist = Playlist()
+        self.fetcher = None # for refilling the radio
 
     def get_position_duration(self):
         return self.backend.get_position_duration()
 
 
     def get_position_duration(self):
         return self.backend.get_position_duration()
 
+    def _play_track(self, track, notify='play'):
+        self.backend.play_url('mp3', track.mp3_url())
+        log.debug("playing %s", track)
+        postoffice.notify(notify, track)
+
+    def _refill_radio(self):
+        log.debug("Refilling radio %s", self.playlist)
+        #self.playlist.add(jamaendo.get_radio_tracks(self.playlist.radio_id))
+        self._start_radio_fetcher()
+
+    def _start_radio_fetcher(self):
+        if self.fetcher:
+            self.fetcher.stop()
+            self.fetcher = None
+        self.fetcher = Fetcher(lambda: jamaendo.get_radio_tracks(self.playlist.radio_id),
+                               self,
+                               on_item = self._on_radio_result,
+                               on_ok = self._on_radio_complete,
+                               on_fail = self._on_radio_complete)
+        self.fetcher.has_no_results = True
+        self.fetcher.start()
+
+    def _on_radio_result(self, wnd, item):
+        if wnd is self:
+            self.playlist.add(item)
+            if not self.playing():
+                if self.fetcher.has_no_results:
+                    self.fetcher.has_no_results = False
+                    entry = self.playlist.next()
+                    self._play_track(entry)
+
+    def _on_radio_complete(self, wnd, error=None):
+        if wnd is self:
+            if error:
+                self.stop()
+            self.fetcher.stop()
+            self.fetcher = None
+
     def play(self, playlist = None):
         if playlist:
             self.playlist = playlist
         elif self.playlist is None:
             self.playlist = Playlist()
     def play(self, playlist = None):
         if playlist:
             self.playlist = playlist
         elif self.playlist is None:
             self.playlist = Playlist()
-        if self.playlist.size():
-            if self.playlist.current():
-                entry = self.playlist.current()
-                self.backend.play_url('mp3', entry.mp3_url())
-                log.debug("playing %s", entry)
-            elif self.playlist.has_next():
-                entry = self.playlist.next()
-                self.backend.play_url('mp3', entry.mp3_url())
-                log.debug("playing %s", entry)
-            postoffice.notify('play', entry)
-
-    def pause(self):
-        self.backend.pause()
-        postoffice.notify('pause', self.playlist.current())
-
-    def stop(self):
-        self.backend.stop()
-        postoffice.notify('stop', self.playlist.current())
 
 
-    def playing(self):
-        return self.backend.playing()
+        if self.playlist.current():
+            entry = self.playlist.current()
+            self._play_track(entry)
+        elif self.playlist.has_next():
+            entry = self.playlist.next()
+            self._play_track(entry)
+        elif self.playlist.radio_mode:
+            self._refill_radio()
+            #self.play()
 
     def next(self):
         if self.playlist.has_next():
             self.backend.stop(reset=False)
             entry = self.playlist.next()
 
     def next(self):
         if self.playlist.has_next():
             self.backend.stop(reset=False)
             entry = self.playlist.next()
-            self.backend.play_url('mp3', entry.mp3_url())
-            log.debug("playing %s:%s", entry.ID, entry.name)
-            postoffice.notify('next', entry)
+            self._play_track(entry, notify='next')
         elif self.playlist.radio_mode:
         elif self.playlist.radio_mode:
-            log.debug("Refilling radio %s", self.playlist)
-            self.playlist.add(jamaendo.get_radio_tracks(self.playlist.radio_id))
-            if self.playlist.has_next():
-                self.next()
-            else:
-                self.stop()
+            self._refill_radio()
+            #if self.playlist.has_next():
+            #    self.next()
+            #else:
+            #    self.stop()
         else:
             self.stop()
 
         else:
             self.stop()
 
@@ -401,9 +427,18 @@ class Player(object):
         if self.playlist.has_prev():
             self.backend.stop(reset=False)
             entry = self.playlist.prev()
         if self.playlist.has_prev():
             self.backend.stop(reset=False)
             entry = self.playlist.prev()
-            self.backend.play_url('mp3', entry.mp3_url())
-            log.debug("playing %s", entry)
-            postoffice.notify('prev', entry)
+            self._play_track(entry, 'prev')
+
+    def pause(self):
+        self.backend.pause()
+        postoffice.notify('pause', self.playlist.current())
+
+    def stop(self):
+        self.backend.stop()
+        postoffice.notify('stop', self.playlist.current())
+
+    def playing(self):
+        return self.backend.playing()
 
     def _on_eos(self):
         self.next()
 
     def _on_eos(self):
         self.next()
index ae6e803..ea7f76c 100644 (file)
@@ -108,6 +108,8 @@ class PlayerWindow(hildon.StackableWindow):
         self.add_stock_button(btns, gtk.STOCK_MEDIA_STOP, self.on_stop)
         self.add_stock_button(btns, gtk.STOCK_MEDIA_NEXT, self.on_next)
 
         self.add_stock_button(btns, gtk.STOCK_MEDIA_STOP, self.on_stop)
         self.add_stock_button(btns, gtk.STOCK_MEDIA_NEXT, self.on_next)
 
+        self.controls = btns
+
         self.add(vbox)
 
         postoffice.connect('album-cover', self, self.set_album_cover)
         self.add(vbox)
 
         postoffice.connect('album-cover', self, self.set_album_cover)
@@ -222,6 +224,14 @@ class PlayerWindow(hildon.StackableWindow):
         self.artist.set_markup('%s'%(cgi.escape(artist)))
         self.album.set_markup('<span foreground="%s">%s</span>'%(colors.SecondaryTextColor(), cgi.escape(album)))
 
         self.artist.set_markup('%s'%(cgi.escape(artist)))
         self.album.set_markup('<span foreground="%s">%s</span>'%(colors.SecondaryTextColor(), cgi.escape(album)))
 
+        if not track:
+            txt = '<span font_desc="%s" foreground="%s">%s</span>' % \
+                (colors.XXLargeSystemFont(),
+                 colors.SecondaryTextColor(),
+                 '00:00'
+                 )
+            self.playtime.set_markup(txt)
+
     def show_banner(self, message, timeout = 2000):
         banner = hildon.hildon_banner_show_information(self, '', message)
         banner.set_timeout(2000)
     def show_banner(self, message, timeout = 2000):
         banner = hildon.hildon_banner_show_information(self, '', message)
         banner.set_timeout(2000)
@@ -294,6 +304,7 @@ class PlayerWindow(hildon.StackableWindow):
     def update_state(self):
         item = self.playlist.current()
         if item:
     def update_state(self):
         item = self.playlist.current()
         if item:
+            hildon.hildon_gtk_window_set_progress_indicator(self, 0)
             if not item.name:
                 item.load()
             self.set_labels(item.name, item.artist_name, item.album_name,
             if not item.name:
                 item.load()
             self.set_labels(item.name, item.artist_name, item.album_name,
@@ -303,6 +314,10 @@ class PlayerWindow(hildon.StackableWindow):
         else:
             self.set_labels('', '', '', 0, 0)
             self.set_default_cover()
         else:
             self.set_labels('', '', '', 0, 0)
             self.set_default_cover()
+        state = bool(item)
+        for btn in self.controls:
+            if isinstance(btn, hildon.GtkButton):
+                btn.set_sensitive(state)
 
     def set_album_cover(self, albumid, size, cover):
         if size == 300:
 
     def set_album_cover(self, albumid, size, cover):
         if size == 300:
@@ -316,12 +331,11 @@ class PlayerWindow(hildon.StackableWindow):
         playlist.radio_mode = True
         playlist.radio_name = radio_name
         playlist.radio_id = radio_id
         playlist.radio_mode = True
         playlist.radio_name = radio_name
         playlist.radio_id = radio_id
-        playlist.add(jamaendo.get_radio_tracks(playlist.radio_id))
-        log.debug("Playing radio: %s", playlist)
+        hildon.hildon_gtk_window_set_progress_indicator(self, 1)
         self.__play_tracks(playlist)
         self.__play_tracks(playlist)
-        log.debug("Playlist current: %s, playing? %s",
-                  playlist.current_index(),
-                  self.player.playing())
+        #log.debug("Playlist current: %s, playing? %s",
+        #          playlist.current_index(),
+        #          self.player.playing())
 
     def play_tracks(self, tracks):
         self.__play_tracks(tracks)
 
     def play_tracks(self, tracks):
         self.__play_tracks(tracks)
index 44d92f3..ac3e2ed 100644 (file)
@@ -29,40 +29,52 @@ except:
 import jamaendo
 from playerwindow import open_playerwindow
 from albumlist import RadioList
 import jamaendo
 from playerwindow import open_playerwindow
 from albumlist import RadioList
+from fetcher import Fetcher
 
 class RadiosWindow(hildon.StackableWindow):
     def __init__(self):
         hildon.StackableWindow.__init__(self)
 
 class RadiosWindow(hildon.StackableWindow):
     def __init__(self):
         hildon.StackableWindow.__init__(self)
+        self.fetcher = None
+        self.radios = {}
+
         self.set_title("Radios")
         self.set_title("Radios")
+        self.connect('destroy', self.on_destroy)
 
         # Results list
         self.panarea = hildon.PannableArea()
         self.radiolist = RadioList()
         self.radiolist.connect('row-activated', self.row_activated)
 
         # Results list
         self.panarea = hildon.PannableArea()
         self.radiolist = RadioList()
         self.radiolist.connect('row-activated', self.row_activated)
-
         self.panarea.add(self.radiolist)
         self.panarea.add(self.radiolist)
-
-        self.radios = {}
-        hildon.hildon_gtk_window_set_progress_indicator(self, 1)
-        radios = jamaendo.starred_radios()
-        for item in radios:
-            self.radios[item.ID] = item
-        self.radiolist.add_radios(radios)
-        hildon.hildon_gtk_window_set_progress_indicator(self, 0)
-
         self.add(self.panarea)
 
         self.add(self.panarea)
 
-    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)
+        self.start_radio_fetcher()
 
 
-        return button
+    def on_destroy(self, wnd):
+        if self.fetcher:
+            self.fetcher.stop()
+            self.fetcher = None
 
     def row_activated(self, treeview, path, view_column):
         name, _id = self.radiolist.get_radio_id(path)
         wnd = open_playerwindow()
         wnd.play_radio(name, _id)
 
     def row_activated(self, treeview, path, view_column):
         name, _id = self.radiolist.get_radio_id(path)
         wnd = open_playerwindow()
         wnd.play_radio(name, _id)
+
+    def start_radio_fetcher(self):
+        if self.fetcher:
+            self.fetcher.stop()
+            self.fetcher = None
+        self.fetcher = Fetcher(jamaendo.starred_radios, self,
+                               on_item = self.on_radio_result,
+                               on_ok = self.on_radio_complete,
+                               on_fail = self.on_radio_complete)
+        self.fetcher.start()
+
+    def on_radio_result(self, wnd, item):
+        if wnd is self:
+            self.radios[item.ID] = item
+            self.radiolist.add_radios([item])
+
+    def on_radio_complete(self, wnd, error=None):
+        if wnd is self:
+            self.fetcher.stop()
+            self.fetcher = None
index ec3f366..c05794c 100644 (file)
@@ -110,6 +110,7 @@ class SearchWindow(hildon.StackableWindow):
         mode = self.mode.get_active()
         txt = self.entry.get_text()
         self.musiclist.set_loading(False)
         mode = self.mode.get_active()
         txt = self.entry.get_text()
         self.musiclist.set_loading(False)
+        self.musiclist.empty_message = "Searching..."
         self.musiclist.get_model().clear()
 
         if self.fetcher:
         self.musiclist.get_model().clear()
 
         if self.fetcher:
@@ -128,8 +129,8 @@ class SearchWindow(hildon.StackableWindow):
 
         self.fetcher = Fetcher(itemgen, self,
                                on_item = self.on_add_result,
 
         self.fetcher = Fetcher(itemgen, self,
                                on_item = self.on_add_result,
-                               on_ok = self.on_add_ok,
-                               on_fail = self.on_add_fail)
+                               on_ok = self.on_add_complete,
+                               on_fail = self.on_add_complete)
         self.fetcher.start()
         '''
         try:
         self.fetcher.start()
         '''
         try:
@@ -154,13 +155,9 @@ class SearchWindow(hildon.StackableWindow):
             self.musiclist.add_items([item])
             self.idmap[item.ID] = item
 
             self.musiclist.add_items([item])
             self.idmap[item.ID] = item
 
-    def on_add_ok(self, wnd):
-        if wnd is self:
-            self.fetcher.stop()
-            self.fetcher = None
-
-    def on_add_fail(self, wnd, error):
+    def on_add_complete(self, wnd, error=None):
         if wnd is self:
         if wnd is self:
+            self.musiclist.empty_message = "No matching results"
             self.musiclist.queue_draw()
             self.fetcher.stop()
             self.fetcher = None
             self.musiclist.queue_draw()
             self.fetcher.stop()
             self.fetcher = None