[gnome-music/wip/garnacho/performance-improvements: 1/5] player: Take care of media item discovery
- From: Carlos Garnacho <carlosg src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-music/wip/garnacho/performance-improvements: 1/5] player: Take care of media item discovery
- Date: Sun, 15 Feb 2015 16:59:00 +0000 (UTC)
commit 6f1cb8d448d8a1a5e04e86b7bf292ee1ddaa9798
Author: Carlos Garnacho <carlosg gnome org>
Date: Sun Feb 15 14:25:56 2015 +0100
player: Take care of media item discovery
All models have been added a column to store the DiscoveryStatus for the
song, and this column is passed on set_playlist(), so the Player object
does take care of updating the status after the song failed playing, or
discovery failed on it.
This makes sure we react properly to player/discovery failures for the
current and next songs, and only when it's needed so. Discovery is a
very expensive operation, and this allows us to stop doing it for every
song at the time of adding these to a model/view, which means lots of
I/O and CPU time just to know whether songs can be played, even it they
might not eventually.
gnomemusic/player.py | 46 ++++++++++++++++++++++++++++++++++++++++++----
gnomemusic/view.py | 23 ++++++++++++++---------
gnomemusic/widgets.py | 11 +++++++----
3 files changed, 63 insertions(+), 17 deletions(-)
---
diff --git a/gnomemusic/player.py b/gnomemusic/player.py
index 684aef6..20c05fe 100644
--- a/gnomemusic/player.py
+++ b/gnomemusic/player.py
@@ -61,6 +61,10 @@ class PlaybackStatus:
PAUSED = 1
STOPPED = 2
+class DiscoveryStatus:
+ PENDING = 0
+ FAILED = 1
+ SUCCEEDED = 2
class Player(GObject.GObject):
nextTrack = None
@@ -210,6 +214,8 @@ class Player(GObject.GObject):
def _onBusError(self, bus, message):
media = self.get_current_media()
if media is not None:
+ currentTrack = self.playlist.get_iter(self.currentTrack.get_path())
+ self.playlist.set_value(currentTrack, self.discovery_status_field, DiscoveryStatus.FAILED)
uri = media.get_url()
else:
uri = 'none'
@@ -225,8 +231,6 @@ class Player(GObject.GObject):
@log
def _on_bus_eos(self, bus, message):
- self.nextTrack = self._get_next_track()
-
if self.nextTrack:
GLib.idle_add(self._on_glib_idle)
elif (self.repeat == RepeatType.NONE):
@@ -468,6 +472,37 @@ class Player(GObject.GObject):
self.emit('playlist-item-changed', self.playlist, currentTrack)
self.emit('current-changed')
+ self._validate_next_track();
+
+ def _on_next_item_validated(self, info, error, _iter):
+ if error:
+ print("Info %s: error: %s" % (info, error))
+ self.playlist.set_value(_iter, self.discovery_status_field, DiscoveryStatus.FAILED);
+ nextTrack = self.playlist.iter_next(_iter)
+
+ if nextTrack:
+ self._validate_next_track(Gtk.TreeRowReference.new(self.playlist,
self.playlist.get_path(nextTrack)))
+
+ def _validate_next_track(self, track=None):
+ if track is None:
+ track = self._get_next_track()
+
+ if track is None:
+ return
+
+ self.nextTrack = track
+
+ _iter = self.playlist.get_iter(self.nextTrack.get_path())
+ status = self.playlist.get_value(_iter, self.discovery_status_field)
+ nextSong = self.playlist.get_value(_iter, self.playlistField)
+
+ if status == DiscoveryStatus.PENDING:
+ self.discover_item(nextSong, self._on_next_item_validated, _iter)
+ elif status == DiscoveryStatus.FAILED:
+ GLib.idle_add(self._validate_next_track())
+
+ return False;
+
@log
def _on_cache_lookup(self, pixbuf, path, data=None):
if pixbuf is not None:
@@ -524,7 +559,7 @@ class Player(GObject.GObject):
return True
self.stop()
- self.currentTrack = self._get_next_track()
+ self.currentTrack = self.nextTrack
if self.currentTrack:
self.play()
@@ -557,7 +592,7 @@ class Player(GObject.GObject):
self.set_playing(True)
@log
- def set_playlist(self, type, id, model, iter, field):
+ def set_playlist(self, type, id, model, iter, field, discovery_status_field):
self.stop()
old_playlist = self.playlist
@@ -572,6 +607,7 @@ class Player(GObject.GObject):
self.playlistId = id
self.currentTrack = Gtk.TreeRowReference.new(model, model.get_path(iter))
self.playlistField = field
+ self.discovery_status_field = discovery_status_field
if old_playlist != model:
self.playlist_insert_handler = model.connect('row-inserted', self._on_playlist_size_changed)
@@ -798,6 +834,8 @@ class Player(GObject.GObject):
if not self.currentTrack or not self.currentTrack.valid():
return None
currentTrack = self.playlist.get_iter(self.currentTrack.get_path())
+ if self.playlist.get_value(currentTrack, self.discovery_status_field) == DiscoveryStatus.FAILED:
+ return None
return self.playlist.get_value(currentTrack, self.playlistField)
diff --git a/gnomemusic/view.py b/gnomemusic/view.py
index 801a06e..f759575 100644
--- a/gnomemusic/view.py
+++ b/gnomemusic/view.py
@@ -44,6 +44,7 @@ from gnomemusic.grilo import grilo
from gnomemusic.query import Query
from gnomemusic.toolbar import ToolbarState
import gnomemusic.widgets as Widgets
+from gnomemusic.player import DiscoveryStatus
from gnomemusic.playlists import Playlists, StaticPlaylists
from gnomemusic.albumArtCache import AlbumArtCache as albumArtCache
from gnomemusic import log
@@ -80,7 +81,8 @@ class ViewContainer(Gtk.Stack):
GObject.TYPE_INT,
GObject.TYPE_STRING,
GObject.TYPE_BOOLEAN,
- GObject.TYPE_BOOLEAN
+ GObject.TYPE_BOOLEAN,
+ GObject.TYPE_INT
)
self.view = Gd.MainView(
shadow_type=Gtk.ShadowType.NONE
@@ -429,7 +431,7 @@ class Songs(ViewContainer):
except TypeError:
return
if self._model.get_value(_iter, 8) != self.errorIconName:
- self.player.set_playlist('Songs', None, self._model, _iter, 5)
+ self.player.set_playlist('Songs', None, self._model, _iter, 5, 11)
self.player.set_playing(True)
@log
@@ -815,7 +817,8 @@ class Playlist(ViewContainer):
GObject.TYPE_INT,
GObject.TYPE_STRING,
GObject.TYPE_BOOLEAN,
- GObject.TYPE_BOOLEAN
+ GObject.TYPE_BOOLEAN,
+ GObject.TYPE_INT
)
self.playlists_sidebar.set_view_type(Gd.MainViewType.LIST)
@@ -1009,7 +1012,7 @@ class Playlist(ViewContainer):
if self._model.get_value(_iter, 8) != self.errorIconName:
self.player.set_playlist(
'Playlist', self.current_playlist.get_id(),
- self._model, _iter, 5
+ self._model, _iter, 5, 11
)
self.player.set_playing(True)
@@ -1104,7 +1107,8 @@ class Playlist(ViewContainer):
GObject.TYPE_INT,
GObject.TYPE_STRING,
GObject.TYPE_BOOLEAN,
- GObject.TYPE_BOOLEAN
+ GObject.TYPE_BOOLEAN,
+ GObject.TYPE_INT
)
self.view.set_model(self._model)
GLib.idle_add(grilo.populate_playlist_songs, playlist, self._add_item)
@@ -1246,7 +1250,7 @@ class Playlist(ViewContainer):
self.iter_to_clean = None
self.update_model(self.player, model, nextIter)
- self.player.set_playlist('Playlist', playlist.get_id(), model, nextIter, 5)
+ self.player.set_playlist('Playlist', playlist.get_id(), model, nextIter, 5, 11)
self.player.set_playing(True)
# Update songs count
@@ -1343,9 +1347,9 @@ class Search(ViewContainer):
self.set_visible_child(self._artistAlbumsWidget)
self.header_bar.searchbar.show_bar(False)
elif self._model[_iter][11] == 'song':
- if self._model.get_value(_iter, 8) != self.errorIconName:
+ if self._model.get_value(_iter, 12) != DiscoveryStatus.FAILED:
child_iter = self.songs_model.convert_child_iter_to_iter(_iter)[1]
- self.player.set_playlist('Search Results', None, self.songs_model, child_iter, 5)
+ self.player.set_playlist('Search Results', None, self.songs_model, child_iter, 5, 12)
self.player.set_playing(True)
else: # Headers
if self.view.get_generic_view().row_expanded(path):
@@ -1612,7 +1616,8 @@ class Search(ViewContainer):
GObject.TYPE_STRING,
GObject.TYPE_BOOLEAN,
GObject.TYPE_BOOLEAN,
- GObject.TYPE_STRING # type
+ GObject.TYPE_STRING, # type
+ GObject.TYPE_INT
)
self.filter_model = self._model.filter_new(None)
self.filter_model.set_visible_func(self._filter_visible_func)
diff --git a/gnomemusic/widgets.py b/gnomemusic/widgets.py
index 6c58502..34dbdf0 100644
--- a/gnomemusic/widgets.py
+++ b/gnomemusic/widgets.py
@@ -36,6 +36,7 @@ from gi.repository import GdkPixbuf, Grl
from gettext import gettext as _, ngettext
from gnomemusic.grilo import grilo
from gnomemusic.albumArtCache import AlbumArtCache
+from gnomemusic.player import DiscoveryStatus
from gnomemusic.playlists import Playlists, StaticPlaylists
from gnomemusic import log
import logging
@@ -107,14 +108,14 @@ class AlbumWidget(Gtk.EventBox):
_iter = self.model.get_iter(path)
- if(self.model.get_value(_iter, 7) != ERROR_ICON_NAME):
+ if self.model.get_value(_iter, 10) != DiscoveryStatus.FAILED:
if (self.iterToClean and self.player.playlistId == self.album):
item = self.model.get_value(self.iterToClean, 5)
title = AlbumArtCache.get_media_title(item)
self.model.set_value(self.iterToClean, 0, title)
# Hide now playing icon
self.model.set_value(self.iterToClean, 6, False)
- self.player.set_playlist('Album', self.album, self.model, _iter, 5)
+ self.player.set_playlist('Album', self.album, self.model, _iter, 5, 11)
self.player.set_playing(True)
@log
@@ -180,6 +181,7 @@ class AlbumWidget(Gtk.EventBox):
GObject.TYPE_BOOLEAN,
GObject.TYPE_BOOLEAN, # icon shown
GObject.TYPE_BOOLEAN,
+ GObject.TYPE_INT
)
@log
@@ -362,7 +364,8 @@ class ArtistAlbums(Gtk.Box):
GObject.TYPE_BOOLEAN, # icon shown
GObject.TYPE_STRING, # icon
GObject.TYPE_OBJECT, # song object
- GObject.TYPE_BOOLEAN
+ GObject.TYPE_BOOLEAN,
+ GObject.TYPE_INT
)
self.model.connect('row-changed', self._model_row_changed)
@@ -642,7 +645,7 @@ class ArtistAlbumWidget(Gtk.Box):
self.player.stop()
self.player.set_playlist('Artist', self.artist,
- widget.model, widget._iter, 5)
+ widget.model, widget._iter, 5, 6)
self.player.set_playing(True)
@log
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]