Commit 6f1cb8d4 authored by Carlos Garnacho's avatar Carlos Garnacho

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.
parent 5723795c
......@@ -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)
......
......@@ -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)
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment