[gnome-music] view: don't discover URIs synchronously



commit 5fdc33208d700f4e7e3e3d2b3046a51d723e23f8
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Sun Aug 18 17:57:47 2013 +0200

    view: don't discover URIs synchronously
    
    Doing IO in the main loop is always a bad idea. But we don't need
    to, because GStreamer can be made to do all the processing in a
    background thread and only report the final result.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=706019

 gnomemusic/player.py  |   32 +++++++++++++++++++
 gnomemusic/view.py    |   54 +++++++++++++-------------------
 gnomemusic/widgets.py |   82 +++++++++++++++++++++++-------------------------
 3 files changed, 93 insertions(+), 75 deletions(-)
---
diff --git a/gnomemusic/player.py b/gnomemusic/player.py
index 52b7256..c8834d6 100644
--- a/gnomemusic/player.py
+++ b/gnomemusic/player.py
@@ -81,7 +81,12 @@ class Player(GObject.GObject):
         self._symbolicIcon = self.cache.make_default_icon(ART_SIZE, ART_SIZE)
 
         Gst.init(None)
+
         self.discoverer = GstPbutils.Discoverer()
+        self.discoverer.connect('discovered', self._on_discovered)
+        self.discoverer.start()
+        self._discovering_urls = {}
+
         self.player = Gst.ElementFactory.make('playbin', 'player')
         self.bus = self.player.get_bus()
         self.bus.add_signal_watch()
@@ -95,6 +100,33 @@ class Player(GObject.GObject):
         self.bus.connect('message::eos', self._on_bus_eos)
         self._setup_view()
 
+    def discover_item(self, item, callback, data=None):
+        url = item.get_url()
+        if not url:
+            return
+
+        obj = (callback, data)
+
+        if url in self._discovering_urls:
+            self._discovering_urls[url] += [obj]
+        else:
+            self._discovering_urls[url] = [obj]
+            self.discoverer.discover_uri_async(url)
+
+    def _on_discovered(self, discoverer, info, error):
+        try:
+            cbs = self._discovering_urls[info.get_uri()]
+            del(self._discovering_urls[info.get_uri()])
+
+            for callback, data in cbs:
+                if data is not None:
+                    callback(info, error, data)
+                else:
+                    callback(info, error)
+        except KeyError:
+            # Not something we're interested in
+            return
+
     def _on_settings_changed(self, settings, value):
         self.repeat = settings.get_enum('repeat')
         self._sync_prev_next()
diff --git a/gnomemusic/view.py b/gnomemusic/view.py
index 3fb5978..a7104ed 100644
--- a/gnomemusic/view.py
+++ b/gnomemusic/view.py
@@ -135,6 +135,8 @@ class ViewContainer(Stack):
         self.view.connect('view-selection-changed',
                           self._on_view_selection_changed)
 
+        self._discovering_urls = {};
+
     def _get_remaining_item_count(self):
         if self._cached_count < 0:
             self._cached_count = Widgets.get_count(self.countQuery)
@@ -209,6 +211,10 @@ class ViewContainer(Stack):
     def populate(self):
         print('populate')
 
+    def _on_discovered(self, info, error, _iter):
+        if error:
+            self._model.set(_iter, [8, 10], [self.errorIconName, True])
+
     def _add_item(self, source, param, item):
         if not item:
             return
@@ -219,23 +225,15 @@ class ViewContainer(Stack):
         title = albumArtCache.get_media_title(item)
         item.set_title(title)
 
-        def add_new_item():
-            _iter = self._model.append()
-            icon_name = self.nowPlayingIconName
-            if item.get_url():
-                try:
-                    self.player.discoverer.discover_uri(item.get_url())
-                except:
-                    print('failed to discover url ' + item.get_url())
-                    icon_name = self.errorIconName
-            self._model.set(_iter,
-                            [0, 1, 2, 3, 4, 5, 7, 8, 9, 10],
-                            [str(item.get_id()), '', title,
-                             artist, self._symbolicIcon, item,
-                             -1, icon_name, False, icon_name == self.errorIconName])
-            GLib.idle_add(self._update_album_art, item, _iter)
-
-        GLib.idle_add(add_new_item)
+        _iter = self._model.append()
+        icon_name = self.nowPlayingIconName
+        self.player.discover_item(item, self._on_discovered, _iter)
+        self._model.set(_iter,
+                        [0, 1, 2, 3, 4, 5, 7, 8, 9, 10],
+                        [str(item.get_id()), '', title,
+                         artist, self._symbolicIcon, item,
+                         -1, icon_name, False, False])
+        GLib.idle_add(self._update_album_art, item, _iter)
 
     def _insert_album_art(self, item, cb_item, itr, x=False):
         if item and cb_item and not item.get_thumbnail():
@@ -289,6 +287,7 @@ class Albums(ViewContainer):
         self.view.set_view_type(Gd.MainViewType.ICON)
         self.countQuery = Query.ALBUMS_COUNT
         self._albumWidget = Widgets.AlbumWidget(player)
+        self.player = player
         self.add(self._albumWidget)
 
     def _back_button_clicked(self, widget, data=None):
@@ -354,21 +353,12 @@ class Songs(ViewContainer):
         self._offset += 1
         _iter = self._model.append()
         item.set_title(albumArtCache.get_media_title(item))
-        try:
-            if item.get_url():
-                self.player.discoverer.discover_uri(item.get_url())
-            self._model.set(_iter,
-                            [2, 3, 5, 8, 9, 10],
-                            [albumArtCache.get_media_title(item),
-                             item.get_string(Grl.METADATA_KEY_ARTIST),
-                             item, self.nowPlayingIconName, False, False])
-        except:
-            print('failed to discover url ' + item.get_url())
-            self._model.set(_iter,
-                            [2, 3, 5, 8, 9, 10],
-                            [albumArtCache.get_media_title(item),
-                             item.get_string(Grl.METADATA_KEY_ARTIST),
-                             item, self.errorIconName, False, True])
+        self.player.discover_item(item, self._on_discovered, _iter)
+        self._model.set(_iter,
+                        [2, 3, 5, 8, 9, 10],
+                        [albumArtCache.get_media_title(item),
+                         item.get_string(Grl.METADATA_KEY_ARTIST),
+                         item, self.nowPlayingIconName, False, False])
 
     def _add_list_renderers(self):
         list_widget = self.view.get_generic_view()
diff --git a/gnomemusic/widgets.py b/gnomemusic/widgets.py
index 8668ec2..6c10e16 100644
--- a/gnomemusic/widgets.py
+++ b/gnomemusic/widgets.py
@@ -273,28 +273,24 @@ class AlbumWidget(Gtk.EventBox):
             if(self.player.get_playback_status() != 2):
                 self.player.eventBox.set_visible(True)
 
+    def _on_discovered(self, info, error, _iter):
+        if error:
+            self.model.set(_iter, [7, 9], [ERROR_ICON_NAME, True])
+
     def _on_populate_album_songs(self, source, prefs, track):
         if track:
             self.tracks.append(track)
             self.duration = self.duration + track.get_duration()
             _iter = self.model.append()
             escapedTitle = AlbumArtCache.get_media_title(track, True)
-            try:
-                self.player.discoverer.discover_uri(track.get_url())
-                self.model.set(_iter,
-                               [0, 1, 2, 3, 4, 5, 7, 9],
-                               [escapedTitle,
-                                self.player.seconds_to_string(
-                                    track.get_duration()),
-                                '', '', None, track, NOW_PLAYING_ICON_NAME,
-                                False])
-            except Exception as err:
-                logging.debug(err.message)
-                logging.debug('failed to discover url ' + track.get_url())
-                self.model.set(_iter,
-                               [0, 1, 2, 3, 4, 5, 7, 9],
-                               [escapedTitle, '', '', '', None,
-                                track, ERROR_ICON_NAME, True])
+            self.player.discover_item(track, self._on_discovered, _iter)
+            self.model.set(_iter,
+                           [0, 1, 2, 3, 4, 5, 7, 9],
+                           [escapedTitle,
+                            self.player.seconds_to_string(
+                                track.get_duration()),
+                            '', '', None, track, NOW_PLAYING_ICON_NAME,
+                            False])
             self.ui.get_object('running_length_label_info').set_text(
                 '%d min' % (int(self.duration / 60) + 1))
 
@@ -521,6 +517,15 @@ class ArtistAlbumWidget(Gtk.HBox):
         self.pack_start(self.ui.get_object('ArtistAlbumWidget'), True, True, 0)
         self.show_all()
 
+    def _on_discovered(self, info, error, song_widget):
+        if error:
+            self.model.set(song_widget._iter, [4], [ERROR_ICON_NAME])
+            song_widget.now_playing_sign.set_from_icon_name(
+                ERROR_ICON_NAME,
+                Gtk.IconSize.SMALL_TOOLBAR)
+            song_widget.now_playing_sign.show()
+            song_widget.can_be_played = False
+
     def get_songs(self, source, prefs, track):
         if track:
             self.tracks.append(track)
@@ -547,33 +552,21 @@ class ArtistAlbumWidget(Gtk.HBox):
                 song_widget.model = self.model
                 song_widget.title = ui.get_object('title')
 
-                try:
-                    self.player.discoverer.discover_uri(str(track.get_url()))
-                    self.model.set(itr,
-                                   [0, 1, 2, 3, 4, 5],
-                                   [title, '', '', False,
-                                    NOW_PLAYING_ICON_NAME, track])
-                    song_widget.now_playing_sign = ui.get_object('image1')
-                    song_widget.now_playing_sign.set_from_icon_name(
-                        NOW_PLAYING_ICON_NAME,
-                        Gtk.IconSize.SMALL_TOOLBAR)
-                    song_widget.now_playing_sign.set_no_show_all('True')
-                    song_widget.now_playing_sign.set_alignment(1, 0.6)
-                    song_widget.can_be_played = True
-                    song_widget.connect('button-release-event',
-                                        self.track_selected)
-
-                except:
-                    print('failed to discover url ' + str(track.get_url()))
-                    self.model.set(itr, [0, 1, 2, 3, 4, 5],
-                                   [title, '', '', True,
-                                    ERROR_ICON_NAME, track])
-                    song_widget.now_playing_sign = ui.get_object('image1')
-                    song_widget.now_playing_sign.set_from_icon_name(
-                        ERROR_ICON_NAME,
-                        Gtk.IconSize.SMALL_TOOLBAR)
-                    song_widget.now_playing_sign.set_alignment(1, 0.6)
-                    song_widget.can_be_played = False
+                self.player.discover_item(track, self._on_discovered, song_widget)
+                self.model.set(itr,
+                               [0, 1, 2, 3, 4, 5],
+                               [title, '', '', False,
+                                NOW_PLAYING_ICON_NAME, track])
+                song_widget.now_playing_sign = ui.get_object('image1')
+                song_widget.now_playing_sign.set_from_icon_name(
+                    NOW_PLAYING_ICON_NAME,
+                    Gtk.IconSize.SMALL_TOOLBAR)
+                song_widget.now_playing_sign.set_no_show_all('True')
+                song_widget.now_playing_sign.set_alignment(1, 0.6)
+                song_widget.can_be_played = True
+                song_widget.connect('button-release-event',
+                                    self.track_selected)
+
             self.ui.get_object('grid1').show_all()
 
     def _update_album_art(self):
@@ -584,6 +577,9 @@ class ArtistAlbumWidget(Gtk.HBox):
             self.ui.get_object('cover').set_from_pixbuf(pixbuf)
 
     def track_selected(self, widget, _iter):
+        if not widget.can_be_played:
+            return
+
         self.player.stop()
         self.player.set_playlist('Artist', self.album,
                                  widget.model, widget._iter, 5)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]