Commit d83b7de3 authored by Jean Felder's avatar Jean Felder Committed by Jean Felder

player: Refactor player playlist

Separate player logic from the playlist logic.
Rename discovery logic to validation as this is more accurate of the
underlying logic.
PlayerPlaylist object handles the playlist and songs validation
logic. Player object acts as a glue for the ui and the underlying
logic (playlist and validation).
Use Gobject Properties.

There are 4 ways to launch a song:
1. Click on a song in the current view. The set_playlist method is
called.
2. At the end of the current song. The next method is automatically called.
3. click on the next buttom from the PlayerToolbar. The next method is called.
4. click on the previous buttom from the PlayerToolbar. The previous
method is called.

Validation is a very expensive operation, so only do it when it's
needed. See commit message from 6f1cb8d4.

The Validation logic brings 3 features:
- display an error icon if a song cannot be played
- do not load a song that cannot be played
- when the song changes, try to load the next possible one: if the
next song cannot be loaded, try the one after, etc.

In "set_playlist" method, if the song has already been played the
validation information is already known, nothing to add. If the song
has never been played, there is no information yet. In that case,
validate_current_song and validate_next_song need to be called to
trigger the validation mechanism.

In "next" method, call validate_next_song to continue the validation
mechanism if there is a next song.

In "previous" method, call validate_previous_song to continue the validation
mechanism if there is a previous song.

Closes: #60, #154
parent 1ea45617
......@@ -86,12 +86,12 @@ class InhibitSuspend(GObject.GObject):
if self._player.get_playback_status() == Playback.PLAYING:
self._inhibit_suspend()
# TODO: The additional check for has_next() is necessary
# TODO: The additional check for has_next property is necessary
# since after a track is done, the player
# goes into STOPPED state before it goes back to PLAYING.
# To be simplified when the player's behavior is corrected.
if (self._player.get_playback_status() == Playback.PAUSED
or (self._player.get_playback_status() == Playback.STOPPED
and not self._player.has_next())):
and not self._player.props.has_next)):
self._uninhibit_suspend()
......@@ -26,7 +26,7 @@
import codecs
from gnomemusic.gstplayer import Playback
from gnomemusic.player import RepeatMode
from gnomemusic.player import PlayerField, PlayerPlaylist, RepeatMode
from gnomemusic.grilo import grilo
from gnomemusic.playlists import Playlists
from gnomemusic.utils import View
......@@ -238,9 +238,6 @@ class MediaPlayer2Service(Server):
playlists.connect('playlist-deleted', self._on_playlists_count_changed)
grilo.connect('ready', self._on_grilo_ready)
self.playlists = []
self.playlist = None
self.playlist_insert_handler = 0
self.playlist_delete_handler = 0
self.first_song_handler = 0
@log
......@@ -255,9 +252,9 @@ class MediaPlayer2Service(Server):
@log
def _get_loop_status(self):
if self.player.repeat == RepeatMode.NONE:
if self.player.props.repeat_mode == RepeatMode.NONE:
return 'None'
elif self.player.repeat == RepeatMode.SONG:
elif self.player.props.repeat_mode == RepeatMode.SONG:
return 'Track'
else:
return 'Playlist'
......@@ -265,7 +262,7 @@ class MediaPlayer2Service(Server):
@log
def _get_metadata(self, media=None):
if not media:
media = self.player.get_current_media()
media = self.player.props.current_song
if not media:
return {}
......@@ -353,17 +350,17 @@ class MediaPlayer2Service(Server):
@log
def _get_media_from_id(self, track_id):
for track in self.player.playlist:
media = track[self.player.Field.SONG]
for track in self.player.get_songs():
media = track[PlayerField.SONG]
if track_id == self._get_media_id(media):
return media
return None
@log
def _get_track_list(self):
if self.player.playlist:
return [self._get_media_id(track[self.player.Field.SONG])
for track in self.player.playlist]
if self.player.props.playing:
return [self._get_media_id(song[PlayerField.SONG])
for song in self.player.get_songs()]
else:
return []
......@@ -400,16 +397,19 @@ class MediaPlayer2Service(Server):
@log
def _get_active_playlist(self):
playlist = self._get_playlist_from_id(self.player.playlist_id) \
if self.player.playlist_type == 'Playlist' else None
playlistName = utils.get_media_title(playlist) \
if playlist else ''
return (playlist is not None,
(self._get_playlist_path(playlist), playlistName, ''))
playlist = None
playlist_name = ''
if self.player.get_playlist_type() == PlayerPlaylist.Type.PLAYLIST:
playlist = self._get_playlist_from_id(
self.player.get_playlist_id())
playlist_name = utils.get_media_title(playlist)
path = self._get_playlist_path(playlist)
return (playlist is not None, (path, playlist_name, ''))
@log
def _on_current_song_changed(self, player, current_iter, data=None):
if self.player.repeat == RepeatMode.SONG:
def _on_current_song_changed(self, player, position):
if self.player.props.repeat_mode == RepeatMode.SONG:
self.Seeked(0)
self.PropertiesChanged(MediaPlayer2Service.MEDIA_PLAYER2_PLAYER_IFACE,
......@@ -441,7 +441,7 @@ class MediaPlayer2Service(Server):
self.PropertiesChanged(MediaPlayer2Service.MEDIA_PLAYER2_PLAYER_IFACE,
{
'LoopStatus': GLib.Variant('s', self._get_loop_status()),
'Shuffle': GLib.Variant('b', self.player.repeat == RepeatMode.SHUFFLE),
'Shuffle': GLib.Variant('b', self.player.props.repeat_mode == RepeatMode.SHUFFLE),
},
[])
......@@ -457,8 +457,8 @@ class MediaPlayer2Service(Server):
def _on_prev_next_invalidated(self, player, data=None):
self.PropertiesChanged(MediaPlayer2Service.MEDIA_PLAYER2_PLAYER_IFACE,
{
'CanGoNext': GLib.Variant('b', self.player.has_next()),
'CanGoPrevious': GLib.Variant('b', self.player.has_previous()),
'CanGoNext': GLib.Variant('b', self.player.props.has_next),
'CanGoPrevious': GLib.Variant('b', self.player.props.has_previous),
},
[])
......@@ -467,7 +467,7 @@ class MediaPlayer2Service(Server):
if self.first_song_handler:
model.disconnect(self.first_song_handler)
self.first_song_handler = 0
self.player.set_playlist('Songs', None, model, iter_)
self.player.set_playlist(PlayerPlaylist.Type.SONG, None, model, iter_)
self.player.play()
@log
......@@ -476,13 +476,6 @@ class MediaPlayer2Service(Server):
@log
def _on_playlist_changed(self, player, data=None):
if self.playlist:
if self.playlist_insert_handler:
self.playlist.disconnect(self.playlist_insert_handler)
if self.playlist_delete_handler:
self.playlist.disconnect(self.playlist_delete_handler)
self.playlist = self.player.playlist
self._on_playlist_modified()
self.PropertiesChanged(MediaPlayer2Service.MEDIA_PLAYER2_PLAYLISTS_IFACE,
......@@ -491,18 +484,12 @@ class MediaPlayer2Service(Server):
},
[])
self.playlist_insert_handler = \
self.playlist.connect('row-inserted', self._on_playlist_modified)
self.playlist_delete_handler = \
self.playlist.connect('row-deleted', self._on_playlist_modified)
@log
def _on_playlist_modified(self, path=None, _iter=None, data=None):
if self.player.current_song and self.player.current_song.valid():
path = self.player.current_song.get_path()
current_song = self.player.playlist[path][self.player.Field.SONG]
if self.player.props.current_song:
track_list = self._get_track_list()
self.TrackListReplaced(track_list, self._get_media_id(current_song))
self.TrackListReplaced(
track_list, self._get_media_id(self.player.props.current_song))
self.PropertiesChanged(MediaPlayer2Service.MEDIA_PLAYER2_TRACKLIST_IFACE,
{
'Tracks': GLib.Variant('ao', track_list),
......@@ -551,7 +538,7 @@ class MediaPlayer2Service(Server):
self.player.stop()
def Play(self):
if self.player.playlist is not None:
if self.player.get_songs():
self.player.play()
elif self.first_song_handler == 0:
window = self.app.get_active_window()
......@@ -594,13 +581,9 @@ class MediaPlayer2Service(Server):
pass
def GoTo(self, track_id):
for track in self.player.playlist:
media = track[self.player.Field.SONG]
if track_id == self._get_media_id(media):
self.player.set_playlist(
self.player.playlist_type, self.player.playlist_id,
self.player.playlist, track.iter)
self.player.play()
for index, song in enumerate(self.player.get_songs()):
if track_id == self._get_media_id(song[PlayerField.SONG]):
self.player_play(index)
return
def TrackListReplaced(self, tracks, current_song):
......@@ -682,16 +665,16 @@ class MediaPlayer2Service(Server):
'PlaybackStatus': GLib.Variant('s', self._get_playback_status()),
'LoopStatus': GLib.Variant('s', self._get_loop_status()),
'Rate': GLib.Variant('d', 1.0),
'Shuffle': GLib.Variant('b', self.player.repeat == RepeatMode.SHUFFLE),
'Shuffle': GLib.Variant('b', self.player.props.repeat_mode == RepeatMode.SHUFFLE),
'Metadata': GLib.Variant('a{sv}', self._get_metadata()),
'Volume': GLib.Variant('d', self.player.get_volume()),
'Position': GLib.Variant('x', self.player.get_position()),
'MinimumRate': GLib.Variant('d', 1.0),
'MaximumRate': GLib.Variant('d', 1.0),
'CanGoNext': GLib.Variant('b', self.player.has_next()),
'CanGoPrevious': GLib.Variant('b', self.player.has_previous()),
'CanPlay': GLib.Variant('b', self.player.current_song is not None),
'CanPause': GLib.Variant('b', self.player.current_song is not None),
'CanGoNext': GLib.Variant('b', self.player.props.has_next),
'CanGoPrevious': GLib.Variant('b', self.player.props.has_previous),
'CanPlay': GLib.Variant('b', self.player.props.current_song is not None),
'CanPause': GLib.Variant('b', self.player.props.current_song is not None),
'CanSeek': GLib.Variant('b', True),
'CanControl': GLib.Variant('b', True),
}
......@@ -727,16 +710,16 @@ class MediaPlayer2Service(Server):
self.player.set_volume(new_value)
elif property_name == 'LoopStatus':
if new_value == 'None':
self.player.set_repeat_mode(RepeatMode.NONE)
self.player.props.repeat_mode = RepeatMode.NONE
elif new_value == 'Track':
self.player.set_repeat_mode(RepeatMode.SONG)
self.player.props.repeat_mode = RepeatMode.SONG
elif new_value == 'Playlist':
self.player.set_repeat_mode(RepeatMode.ALL)
self.player.props.repeat_mode = RepeatMode.ALL
elif property_name == 'Shuffle':
if new_value:
self.player.set_repeat_mode(RepeatMode.SHUFFLE)
self.player.props.repeat_mode = RepeatMode.SHUFFLE
else:
self.player.set_repeat_mode(RepeatMode.NONE)
self.player.props.repeat_mode = RepeatMode.NONE
else:
raise Exception(
'org.mpris.MediaPlayer2.GnomeMusic',
......
This diff is collapsed.
......@@ -28,6 +28,7 @@ from gi.repository import Gdk, GLib, Gtk
from gnomemusic import log
from gnomemusic.grilo import grilo
from gnomemusic.player import PlayerPlaylist
from gnomemusic.views.baseview import BaseView
from gnomemusic.widgets.artistalbumswidget import ArtistAlbumsWidget
from gnomemusic.widgets.sidebarrow import SidebarRow
......@@ -108,7 +109,8 @@ class ArtistsView(BaseView):
widget = self._artists[artist.casefold()]['widget']
if widget:
if self.player.playing_playlist('Artist', widget.props.artist):
if self.player.playing_playlist(
PlayerPlaylist.Type.ARTIST, widget.artist):
self._artist_albums_widget = widget.get_parent()
GLib.idle_add(
self._view.set_visible_child, self._artist_albums_widget)
......
......@@ -28,7 +28,7 @@ from gi.repository import Gio, GLib, GObject, Gtk, Pango
from gnomemusic import log
from gnomemusic.grilo import grilo
from gnomemusic.player import DiscoveryStatus
from gnomemusic.player import ValidationStatus, PlayerPlaylist
from gnomemusic.playlists import Playlists, StaticPlaylists
from gnomemusic.views.baseview import BaseView
from gnomemusic.widgets.notificationspopup import PlaylistNotification
......@@ -131,6 +131,7 @@ class PlaylistView(BaseView):
self.model.connect('row-deleted', self._on_song_deleted)
self.player.connect('song-changed', self._update_model)
self.player.connect('song-validated', self._on_song_validated)
playlists.connect('playlist-created', self._on_playlist_created)
playlists.connect('playlist-updated', self._on_playlist_update)
playlists.connect(
......@@ -226,14 +227,14 @@ class PlaylistView(BaseView):
def _on_list_widget_icon_render(self, col, cell, model, _iter, data):
if not self.player.playing_playlist(
'Playlist', self._current_playlist.get_id()):
PlayerPlaylist.Type.PLAYLIST, self._current_playlist.get_id()):
cell.set_visible(False)
return
if not model.iter_is_valid(_iter):
return
if model[_iter][11] == DiscoveryStatus.FAILED:
if model[_iter][11] == ValidationStatus.FAILED:
cell.set_property('icon-name', self._error_icon_name)
cell.set_visible(True)
elif model[_iter][5].get_url() == self.player.url:
......@@ -243,15 +244,19 @@ class PlaylistView(BaseView):
cell.set_visible(False)
@log
def _update_model(self, player, playlist, current_iter):
def _update_model(self, player, position):
"""Updates model when the song changes
:param Player player: The main player object
:param int position: current song position
"""
if self._iter_to_clean:
self._iter_to_clean_model[self._iter_to_clean][10] = False
if not player.playing_playlist(
'Playlist', self._current_playlist.get_id()):
PlayerPlaylist.Type.PLAYLIST, self._current_playlist.get_id()):
return False
pos_str = playlist.get_path(current_iter).to_string()
iter_ = self.model.get_iter_from_string(pos_str)
iter_ = self.model.get_iter_from_string(str(position))
self.model[iter_][10] = True
if self.model[iter_][8] != self._error_icon_name:
self._iter_to_clean = iter_.copy()
......@@ -304,6 +309,15 @@ class PlaylistView(BaseView):
self._sidebar.select_row(row)
self._sidebar.emit('row-activated', row)
@log
def _on_song_validated(self, player, index, status):
if not self.player.playing_playlist(
PlayerPlaylist.Type.PLAYLIST, self._current_playlist.get_id()):
return
iter_ = self.model.get_iter_from_string(str(index))
self.model[iter_][11] = status
@log
def _on_song_activated(self, widget, path, column):
"""Action performed when clicking on a song
......@@ -327,8 +341,8 @@ class PlaylistView(BaseView):
_iter = self.model.get_iter(path)
if self.model[_iter][8] != self._error_icon_name:
self.player.set_playlist(
'Playlist', self._current_playlist.get_id(), self.model,
_iter)
PlayerPlaylist.Type.PLAYLIST,
self._current_playlist.get_id(), self.model, _iter)
self.player.play()
# 'row-activated' signal is emitted before 'drag-begin' signal.
......@@ -376,7 +390,7 @@ class PlaylistView(BaseView):
def _on_song_deleted(self, model, path):
"""Save new playlist order after drag and drop operation.
Update player's playlist if necessary.
Update player's playlist if the playlist is being played.
"""
if not self._song_drag['active']:
return
......@@ -390,24 +404,21 @@ class PlaylistView(BaseView):
first_pos = min(new_pos, prev_pos)
last_pos = max(new_pos, prev_pos)
# update player's playlist.
# update player's playlist if necessary
if self.player.playing_playlist(
'Playlist', self._current_playlist.get_id()):
playing_old_path = self.player.current_song.get_path().to_string()
playing_old_pos = int(playing_old_path)
iter_ = model.get_iter_from_string(playing_old_path)
# if playing song position has changed
if playing_old_pos >= first_pos and playing_old_pos < last_pos:
current_player_song = self.player.get_current_media()
for row in model:
if row[5].get_id() == current_player_song.get_id():
iter_ = row.iter
self._iter_to_clean = iter_
self._iter_to_clean_model = model
break
self.player.set_playlist(
'Playlist', self._current_playlist.get_id(), model, iter_)
PlayerPlaylist.Type.PLAYLIST, self._current_playlist.get_id()):
if new_pos < prev_pos:
prev_pos -= 1
else:
new_pos -= 1
current_index = self.player.playlist_change_position(
prev_pos, new_pos)
if current_index >= 0:
current_iter = model.get_iter_from_string(str(current_index))
self._iter_to_clean = current_iter
self._iter_to_clean_model = model
# update playlist's storage
positions = []
songs = []
for pos in range(first_pos, last_pos):
......@@ -658,7 +669,8 @@ class PlaylistView(BaseView):
or self._sidebar.get_row_at_index(index - 1))
self._sidebar.remove(selection)
if self.player.playing_playlist('Playlist', playlist_id):
if self.player.playing_playlist(
PlayerPlaylist.Type.PLAYLIST, playlist_id):
self.player.stop()
self.set_player_visible(False)
......@@ -688,10 +700,12 @@ class PlaylistView(BaseView):
and playlist.get_id() == self._current_playlist.get_id()):
iter_ = self._add_song_to_model(
song_todelete['song'], self.model, song_todelete['index'])
playlist_id = self._current_playlist.get_id()
if self.player.playing_playlist(
'Playlist', self._current_playlist.get_id()):
PlayerPlaylist.Type.PLAYLIST, playlist_id):
song = self.model[iter_][5]
path = self.model.get_path(iter_)
self.player.add_song(self.model, path, iter_)
self.player.add_song(song, int(path.to_string()))
self._songs_todelete.pop(media_id)
@log
......@@ -739,23 +753,23 @@ class PlaylistView(BaseView):
def _on_song_added_to_playlist(self, playlists, playlist, item):
if self._is_current_playlist(playlist):
iter_ = self._add_song_to_model(item, self.model)
playlist_id = self._current_playlist.get_id()
if self.player.playing_playlist(
'Playlist', self._current_playlist.get_id()):
PlayerPlaylist.Type.PLAYLIST, playlist_id):
path = self.model.get_path(iter_)
self.player.add_song(self.model, path, iter_)
self.player.add_song(item, int(path.to_string()))
@log
def _remove_song_from_playlist(self, playlist, item, index):
if not self._is_current_playlist(playlist):
return
model = self.model
iter_ = model.get_iter_from_string(str(index))
if self.player.playing_playlist(
'Playlist', self._current_playlist.get_id()):
self.player.remove_song(model, model.get_path(iter_))
model.remove(iter_)
PlayerPlaylist.Type.PLAYLIST, self._current_playlist.get_id()):
self.player.remove_song(index)
iter_ = self.model.get_iter_from_string(str(index))
self.model.remove(iter_)
self._update_songs_count(self._songs_count - 1)
......
......@@ -28,7 +28,7 @@ from gi.repository import Gd, Gdk, GdkPixbuf, GObject, Grl, Gtk, Pango
from gnomemusic.albumartcache import Art
from gnomemusic.grilo import grilo
from gnomemusic import log
from gnomemusic.player import DiscoveryStatus
from gnomemusic.player import ValidationStatus, PlayerPlaylist
from gnomemusic.playlists import Playlists
from gnomemusic.query import Query
from gnomemusic.utils import View
......@@ -157,10 +157,11 @@ class SearchView(BaseView):
self.set_visible_child(self._artist_albums_widget)
self._header_bar.searchbar.reveal(False)
elif self.model[_iter][12] == 'song':
if self.model[_iter][11] != DiscoveryStatus.FAILED:
if self.model[_iter][11] != ValidationStatus.FAILED:
c_iter = self._songs_model.convert_child_iter_to_iter(_iter)[1]
self.player.set_playlist(
'Search Results', None, self._songs_model, c_iter)
PlayerPlaylist.Type.SEARCH_RESULT, None, self._songs_model,
c_iter)
self.player.play()
else: # Headers
if self._view.row_expanded(path):
......@@ -554,7 +555,7 @@ class SearchView(BaseView):
GObject.TYPE_STRING,
GObject.TYPE_INT,
GObject.TYPE_BOOLEAN,
GObject.TYPE_INT, # discovery status
GObject.TYPE_INT, # validation status
GObject.TYPE_STRING, # type
object # album art surface
)
......
......@@ -28,7 +28,7 @@ from gi.repository import Gdk, GLib, Gtk, Pango
from gnomemusic import log
from gnomemusic.grilo import grilo
from gnomemusic.player import DiscoveryStatus
from gnomemusic.player import ValidationStatus, PlayerPlaylist
from gnomemusic.views.baseview import BaseView
import gnomemusic.utils as utils
......@@ -63,6 +63,7 @@ class SongsView(BaseView):
self.player = player
self.player.connect('song-changed', self._update_model)
self.player.connect('song-validated', self._on_song_validated)
@log
def _setup_view(self):
......@@ -154,7 +155,7 @@ class SongsView(BaseView):
cell.props.visible = False
return
if model[itr][11] == DiscoveryStatus.FAILED:
if model[itr][11] == ValidationStatus.FAILED:
cell.props.icon_name = self._error_icon_name
cell.props.visible = True
elif model[itr][5].get_url() == track_uri:
......@@ -202,9 +203,9 @@ class SongsView(BaseView):
return
itr = self.model.get_iter(path)
if self.model[itr][8] != self._error_icon_name:
self.player.set_playlist('Songs', None, self.model, itr)
self.player.play()
self.player.set_playlist(
PlayerPlaylist.Type.SONGS, None, self.model, itr)
self.player.play()
@log
def _on_view_clicked(self, treeview, event):
......@@ -227,20 +228,18 @@ class SongsView(BaseView):
self._update_header_from_selection(len(self.get_selected_songs()))
@log
def _update_model(self, player, playlist, current_iter):
"""Updates model when the track changes
def _update_model(self, player, position):
"""Updates model when the song changes
:param player: The main player object
:param playlist: The current playlist object
:param current_iter: Iter of the current displayed song
:param Player player: The main player object
:param int position: current song position
"""
if self._iter_to_clean:
self.model[self._iter_to_clean][10] = False
if not player.playing_playlist('Songs', None):
if not player.playing_playlist(PlayerPlaylist.Type.SONGS, None):
return False
pos_str = playlist.get_path(current_iter).to_string()
iter_ = self.model.get_iter_from_string(pos_str)
iter_ = self.model.get_iter_from_string(str(position))
self.model[iter_][10] = True
path = self.model.get_path(iter_)
self._view.scroll_to_cell(path, None, False, 0., 0.)
......@@ -248,6 +247,14 @@ class SongsView(BaseView):
self._iter_to_clean = iter_.copy()
return False
@log
def _on_song_validated(self, player, index, status):
if not player.playing_playlist(PlayerPlaylist.Type.SONGS, None):
return
iter_ = self.model.get_iter_from_string(str(index))
self.model[iter_][11] = status
def _add_item(self, source, param, item, remaining=0, data=None):
"""Adds track item to the model"""
if not item and not remaining:
......
......@@ -28,6 +28,7 @@ from gi.repository import GdkPixbuf, GLib, GObject, Gtk
from gnomemusic import log
from gnomemusic.albumartcache import Art, ArtImage
from gnomemusic.grilo import grilo
from gnomemusic.player import PlayerPlaylist
from gnomemusic.widgets.disclistboxwidget import DiscBox
from gnomemusic.widgets.disclistboxwidget import DiscListBox # noqa: F401
from gnomemusic.widgets.songwidget import SongWidget
......@@ -186,9 +187,9 @@ class AlbumWidget(Gtk.EventBox):
song_widget.props.selected = not song_widget.props.selected
return
self._player.stop()
self._player.set_playlist(
'Album', self._album, song_widget.model, song_widget.itr)
PlayerPlaylist.Type.ALBUM, self._album, song_widget.model,
song_widget.itr)
self._player.play()
return True
......@@ -227,29 +228,24 @@ class AlbumWidget(Gtk.EventBox):
self.show_all()
@log
def _update_model(self, player, playlist, current_iter):
"""Player changed callback.
def _update_model(self, player, position):
"""Updates model when the song changes
:param player: The player object
:param playlist: The current playlist
:param current_iter: The current iter of the playlist model
:param Player player: The main player object
:param int position: current song position
"""
if not player.playing_playlist('Album', self._album):
if not player.playing_playlist(PlayerPlaylist.Type.ALBUM, self._album):
return True
current_song = playlist[current_iter][player.Field.SONG]
current_song = player.props.current_song
self._duration = 0
song_passed = False
_iter = playlist.get_iter_first()
while _iter:
song = playlist[_iter][player.Field.SONG]
for song in self._songs:
song_widget = song.song_widget
self._duration += song.get_duration()
if (song == current_song):
if (song.get_id() == current_song.get_id()):
song_widget.props.state = SongWidget.State.PLAYING
song_passed = True
elif (song_passed):
......@@ -258,8 +254,6 @@ class AlbumWidget(Gtk.EventBox):
else:
song_widget.props.state = SongWidget.State.PLAYED
_iter = playlist.iter_next(_iter)
self._set_duration_label()
return True
......
......@@ -27,6 +27,7 @@ import logging
from gi.repository import GObject, Gtk
from gnomemusic import log
from gnomemusic.player import PlayerPlaylist
from gnomemusic.widgets.artistalbumwidget import ArtistAlbumWidget
from gnomemusic.widgets.songwidget import SongWidget
......@@ -143,20 +144,26 @@ class ArtistAlbumsWidget(Gtk.Box):
widget.connect('songs-loaded', self._on_album_displayed)
@log
def _update_model(self, player, playlist, current_iter):
if not player.playing_playlist('Artist', self.props.artist):
def _update_model(self, player, position):
"""Updates model when the song changes
:param Player player: The main player object
:param int position: current song position
"""
if not player.playing_playlist(
PlayerPlaylist.Type.ARTIST, self._artist):
self._clean_model()
return False
current_song = playlist[current_iter][player.Field.SONG]
current_song = player.props.current_song
song_passed = False
itr = playlist.get_iter_first()
itr = self._model.get_iter_first()
while itr:
song = playlist[itr][player.Field.SONG]
song = self._model[itr][5]
song_widget = song.song_widget
if (song == current_song):
if (song.get_id() == current_song.get_id()):
song_widget.props.state = SongWidget.State.PLAYING
song_passed = True
elif (song_passed):
......@@ -165,7 +172,7 @@ class ArtistAlbumsWidget(Gtk.Box):
else:
song_widget.props.state = SongWidget.State.PLAYED
itr = playlist.iter_next(itr)
itr = self._model.iter_next(itr)
return False
......
......@@ -27,6 +27,7 @@ from gi.repository import GObject, Gtk
from gnomemusic import log
from gnomemusic.albumartcache import Art
from gnomemusic.grilo import grilo
from gnomemusic.player import PlayerPlaylist
from gnomemusic.widgets.disclistboxwidget import DiscBox
import gnomemusic.utils as utils
......@@ -137,9 +138,9 @@ class ArtistAlbumWidget(Gtk.Box):
if self.props.selection_mode:
return
self._player.stop()
self._player.set_playlist(
'Artist', self._artist, song_widget.model, song_widget.itr)
PlayerPlaylist.Type.ARTIST, self._artist, song_widget.model,
song_widget.itr)
self._player.play()
return True
......
......@@ -127,13 +127,13 @@ class PlayerToolbar(Gtk.ActionBar):
@log
def _sync_repeat_image(self, player=None):
icon = None
if self._player.repeat == RepeatMode.NONE:
if self._player.props.repeat_mode == RepeatMode.NONE:
icon = 'media-playlist-consecutive-symbolic'
elif self._player.repeat == RepeatMode.SHUFFLE:
elif self._player.props.repeat_mode == RepeatMode.SHUFFLE:
icon = 'media-playlist-shuffle-symbolic'
elif self._player.repeat == RepeatMode.ALL:
elif self._player.props.repeat_mode == RepeatMode.ALL:
icon = 'media-playlist-repeat-symbolic'
elif self._player.repeat == RepeatMode.SONG: