[gnome-music/wip/jfelder/playlists-core-rewrite-prep-work: 7/20] playlists: Dynamically instantiate the smart playlists
- From: Jean Felder <jfelder src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-music/wip/jfelder/playlists-core-rewrite-prep-work: 7/20] playlists: Dynamically instantiate the smart playlists
- Date: Mon, 1 Jul 2019 22:31:03 +0000 (UTC)
commit 2eb68eae84c01a93972598bcda4860b8326d0da0
Author: Jean Felder <jfelder src gnome org>
Date: Mon Jul 1 21:28:26 2019 +0200
playlists: Dynamically instantiate the smart playlists
This commit makes the smart playlists be allocated when the
Playlists class is instantiated. This allows to correctly emit the
smart playlists only once.
It is based on some work done by Georges Basile Stavracas Neto.
gnomemusic/playlists.py | 153 ++++++++++++++++++--------------
gnomemusic/widgets/songwidget.py | 5 +-
gnomemusic/widgets/starhandlerwidget.py | 5 +-
3 files changed, 92 insertions(+), 71 deletions(-)
---
diff --git a/gnomemusic/playlists.py b/gnomemusic/playlists.py
index d8f89e48..496476e4 100644
--- a/gnomemusic/playlists.py
+++ b/gnomemusic/playlists.py
@@ -32,7 +32,6 @@ from gi.repository import Grl, GLib, GObject
from gnomemusic.grilo import grilo
from gnomemusic.query import Query
from gettext import gettext as _
-import inspect
from gnomemusic import log
import logging
@@ -59,62 +58,64 @@ class Playlist(GObject.Object):
self.props.title = title
-class SmartPlaylists:
+class MostPlayed(Playlist):
+ """Most Played smart playlist"""
- def __repr__(self):
- return '<SmartPlaylists>'
+ def __init__(self):
+ super().__init__()
- class MostPlayed(Playlist):
- TAG_TEXT = "MOST_PLAYED"
+ self.props.tag_text = "MOST_PLAYED"
# TRANSLATORS: this is a playlist name
- TITLE = _("Most Played")
+ self.props.title = _("Most Played")
+ self.props.query = Query.get_never_played_songs()
- class NeverPlayed(Playlist):
- TAG_TEXT = "NEVER_PLAYED"
- # TRANSLATORS: this is a playlist name
- TITLE = _("Never Played")
- class RecentlyPlayed(Playlist):
- TAG_TEXT = "RECENTLY_PLAYED"
- # TRANSLATORS: this is a playlist name
- TITLE = _("Recently Played")
+class NeverPlayed(Playlist):
+ """Never Played smart playlist"""
- class RecentlyAdded(Playlist):
- TAG_TEXT = "RECENTLY_ADDED"
+ def __init__(self):
+ super().__init__()
+
+ self.props.tag_text = "NEVER_PLAYED"
# TRANSLATORS: this is a playlist name
- TITLE = _("Recently Added")
+ self.props.title = _("Never Played")
+ self.props.query = Query.get_never_played_songs()
+
- class Favorites(Playlist):
- TAG_TEXT = "FAVORITES"
+class RecentlyPlayed(Playlist):
+ """Recently Played smart playlist"""
+
+ def __init__(self):
+ super().__init__()
+
+ self.props.tag_text = "RECENTLY_PLAYED"
# TRANSLATORS: this is a playlist name
- TITLE = _("Favorite Songs")
+ self.props.title = _("Recently Played")
+ self.props.query = Query.get_recently_played_songs()
+
+
+class RecentlyAdded(Playlist):
+ """Recently Added smart playlist"""
def __init__(self):
- Query()
- self.MostPlayed.QUERY = Query.get_most_played_songs()
- self.NeverPlayed.QUERY = Query.get_never_played_songs()
- self.RecentlyPlayed.QUERY = Query.get_recently_played_songs()
- self.RecentlyAdded.QUERY = Query.get_recently_added_songs()
- self.Favorites.QUERY = Query.get_favorite_songs()
-
- @staticmethod
- def get_ids():
- """Get all smart playlist IDs
-
- :return: A list of tracker.id's
- :rtype: A list of integers
- """
- return [str(playlist.ID) for playlist in SmartPlaylists.get_all()]
+ super().__init__()
- @staticmethod
- def get_all():
- """Get all smart playlist classes
+ self.props.tag_text = "RECENTLY_ADDED"
+ # TRANSLATORS: this is a playlist name
+ self.props.title = _("Recently Added")
+ self.props.query = Query.get_recently_added_songs()
- :return: All SmartPlaylists innerclasses
- :rtype: A list of classes
- """
- return [cls for name, cls in inspect.getmembers(SmartPlaylists)
- if inspect.isclass(cls) and not name == "__class__"]
+
+class Favorites(Playlist):
+ """Favorites smart playlist"""
+
+ def __init__(self):
+ super().__init__()
+
+ self.props.tag_text = "FAVORITES"
+ # TRANSLATORS: this is a playlist name
+ self.props.title = _("Favorite Songs")
+ self.props.query = Query.get_favorite_songs()
class Playlists(GObject.GObject):
@@ -127,9 +128,7 @@ class Playlists(GObject.GObject):
'playlist-deleted': (
GObject.SignalFlags.RUN_FIRST, None, (str,)
),
- 'playlist-updated': (
- GObject.SignalFlags.RUN_FIRST, None, (int,)
- ),
+ 'playlist-updated': (GObject.SignalFlags.RUN_FIRST, None, (str,)),
'playlist-renamed': (
GObject.SignalFlags.RUN_FIRST, None, (Grl.Media,)
),
@@ -156,15 +155,23 @@ class Playlists(GObject.GObject):
def __init__(self):
super().__init__()
- self._smart_playlists = SmartPlaylists()
+ Query()
+ self._smart_playlists = {
+ "MostPlayed": MostPlayed(),
+ "NeverPlayed": NeverPlayed(),
+ "RecentlyPlayed": RecentlyPlayed(),
+ "RecentlyAdded": RecentlyAdded(),
+ "Favorites": Favorites()
+ }
+
self._pls_todelete = {}
grilo.connect('ready', self._on_grilo_ready)
@log
def _on_grilo_ready(self, data=None):
- """For all smart playlists: get ID, if exists; if not, create
- the playlist and get ID."""
+ """For all smart playlists: get id, if exists; if not, create
+ the playlist and get id."""
def playlist_id_fetched_cb(cursor, res, playlist):
""" Called after the playlist id is fetched """
@@ -174,9 +181,9 @@ class Playlists(GObject.GObject):
logger.warning("Error: {}, {}".format(err.__class__, err))
return
- playlist.ID = cursor.get_integer(1)
+ playlist.props.id_ = cursor.get_integer(1)
- if not playlist.ID:
+ if not playlist.props.id_:
# Create the smart playlist
self._create_smart_playlist(playlist)
else:
@@ -191,14 +198,14 @@ class Playlists(GObject.GObject):
logger.warning("Error: {}, {}".format(err.__class__, err))
return
- # Search for the playlist ID
+ # Search for the playlist id
cursor.next_async(None, playlist_id_fetched_cb, playlist)
self._tracker = grilo.tracker_sparql
# Start fetching all the smart playlists
- for playlist in self._smart_playlists.get_all():
+ for playlist in self._smart_playlists.values():
self._tracker.query_async(
- Query.get_playlist_with_tag(playlist.TAG_TEXT), None,
+ Query.get_playlist_with_tag(playlist.props.tag_text), None,
callback, playlist)
@log
@@ -206,26 +213,26 @@ class Playlists(GObject.GObject):
""" Create the tag and the smart playlist, and fetch the newly created
playlist's songs.
"""
- title = playlist.TITLE
- tag_text = playlist.TAG_TEXT
+ title = playlist.props.title
+ tag_text = playlist.props.tag_text
def playlist_next_async_cb(cursor, res, playlist):
""" Called after we finished moving the Tracker cursor, and ready
to retrieve the playlist id"""
- # Update the playlist ID
+ # Update the playlist id
try:
cursor.next_finish(res)
except GLib.Error as err:
logger.warning("Error: {}, {}".format(err.__class__, err))
return
- playlist.ID = cursor.get_integer(0)
+ playlist.props.id_ = cursor.get_integer(0)
# Fetch the playlist contents
self.update_smart_playlist(playlist)
def playlist_queried_cb(obj, res, playlist):
- """ Called after the playlist is created and the ID is fetched """
+ """ Called after the playlist is created and the id is fetched """
try:
cursor = obj.query_finish(res)
except GLib.Error as err:
@@ -270,7 +277,7 @@ class Playlists(GObject.GObject):
@log
def clear_playlist(self, playlist):
"""Starts cleaning the playlist"""
- query = Query.clear_playlist_with_id(playlist.ID)
+ query = Query.clear_playlist_with_id(playlist.props.id_)
self._tracker.update_async(
query, GLib.PRIORITY_LOW, None, self._smart_playlist_cleared_cb,
playlist)
@@ -280,7 +287,8 @@ class Playlists(GObject.GObject):
"""After clearing the playlist, start querying the playlist's songs"""
# Get a list of matching songs
self._tracker.query_async(
- playlist.QUERY, None, self._smart_playlist_query_cb, playlist)
+ playlist.props.query, None, self._smart_playlist_query_cb,
+ playlist)
@log
def _smart_playlist_query_cb(self, connection, res, playlist):
@@ -304,7 +312,8 @@ class Playlists(GObject.GObject):
# Only perform the update when the cursor reached the end
if has_next:
uri = cursor.get_string(0)[0]
- final_query += Query.add_song_to_playlist(playlist.ID, uri)
+ final_query += Query.add_song_to_playlist(
+ playlist.props.id_, uri)
cursor.next_async(None, callback, final_query)
else:
@@ -317,11 +326,11 @@ class Playlists(GObject.GObject):
@log
def _smart_playlist_update_finished(self, source, res, smart_playlist):
- self.emit('playlist-updated', smart_playlist.ID)
+ self.emit('playlist-updated', smart_playlist.props.id_)
@log
def update_all_smart_playlists(self):
- for playlist in self._smart_playlists.get_all():
+ for playlist in self._smart_playlists.values():
self.update_smart_playlist(playlist)
@log
@@ -455,6 +464,16 @@ class Playlists(GObject.GObject):
Query.change_song_position(playlist_id, item_id, new_position),
GLib.PRIORITY_LOW, None, update_callback, item)
+ @log
+ def get_smart_playlist(self, name):
+ """SmartPlaylist getter
+
+ :param str name: smart playlist name
+ :returns: Smart Playlist
+ :rtype: Playlist
+ """
+ return self._smart_playlists[name]
+
@log
def is_smart_playlist(self, playlist):
"""Checks whether the given playlist is smart or not
@@ -462,8 +481,8 @@ class Playlists(GObject.GObject):
:return: True if the playlist is smart
:rtype: bool
"""
- for smart_playlist_id in self._smart_playlists.get_ids():
- if playlist.get_id() == smart_playlist_id:
+ for smart_playlist in self._smart_playlists.values():
+ if playlist.get_id() == smart_playlist.props.id_:
return True
return False
diff --git a/gnomemusic/widgets/songwidget.py b/gnomemusic/widgets/songwidget.py
index 78c87181..f3310d94 100644
--- a/gnomemusic/widgets/songwidget.py
+++ b/gnomemusic/widgets/songwidget.py
@@ -32,7 +32,7 @@ from gi.repository.Dazzle import BoldingLabel # noqa: F401
from gnomemusic import log
from gnomemusic import utils
from gnomemusic.grilo import grilo
-from gnomemusic.playlists import Playlists, SmartPlaylists
+from gnomemusic.playlists import Playlists
from gnomemusic.widgets.starimage import StarImage # noqa: F401
@@ -143,7 +143,8 @@ class SongWidget(Gtk.EventBox):
# TODO: Rework and stop updating widgets from here directly.
grilo.set_favorite(self._media, favorite)
- self._playlists.update_smart_playlist(SmartPlaylists.Favorites)
+ favorite_playlist = self._playlists.get_smart_playlist("Favorites")
+ self._playlists.update_smart_playlist(favorite_playlist)
return True
diff --git a/gnomemusic/widgets/starhandlerwidget.py b/gnomemusic/widgets/starhandlerwidget.py
index f9698598..e1745602 100644
--- a/gnomemusic/widgets/starhandlerwidget.py
+++ b/gnomemusic/widgets/starhandlerwidget.py
@@ -26,7 +26,7 @@ from gi.repository import GObject, Gtk
from gnomemusic import log
from gnomemusic.grilo import grilo
-from gnomemusic.playlists import Playlists, SmartPlaylists
+from gnomemusic.playlists import Playlists
playlists = Playlists.get_default()
@@ -152,7 +152,8 @@ class StarHandlerWidget(object):
self._parent.model[_iter][self._star_index] = new_value
song_item = self._parent.model[_iter][5]
grilo.toggle_favorite(song_item)
- playlists.update_smart_playlist(SmartPlaylists.Favorites)
+ favorite_playlist = playlists.get_smart_playlist("Favorites")
+ playlists.update_smart_playlist(favorite_playlist)
# Use this flag to ignore the upcoming _on_item_activated call
self.star_renderer_click = True
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]