playlist: Create a Playlist Factory object
The playlist factory has properties for the currently selected, currently active, and previous playlists. It will eventually create Gio.ListModel instances representing the tracks in each of these playlists, in sorted order. Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
parent
7d26d89405
commit
fdfc12fbd2
|
@ -9,6 +9,7 @@ from . import header
|
|||
from . import mpris2
|
||||
from . import nowplaying
|
||||
from . import options
|
||||
from . import playlist
|
||||
from . import sidebar
|
||||
from . import window
|
||||
from gi.repository import GObject
|
||||
|
@ -25,6 +26,7 @@ class Application(Adw.Application):
|
|||
"""Our custom Adw.Application."""
|
||||
|
||||
db = GObject.Property(type=db.Connection)
|
||||
factory = GObject.Property(type=playlist.Factory)
|
||||
mpris = GObject.Property(type=mpris2.Connection)
|
||||
player = GObject.Property(type=audio.Player)
|
||||
win = GObject.Property(type=window.Window)
|
||||
|
@ -162,6 +164,13 @@ class Application(Adw.Application):
|
|||
self.mpris.player.connect("SetPosition", self.__set_position)
|
||||
self.mpris.player.connect("Stop", self.player.stop)
|
||||
|
||||
def connect_playlist_factory(self) -> None:
|
||||
"""Connect the playlist factory properties."""
|
||||
self.db.playlists.bind_property("previous",
|
||||
self.factory, "db-previous")
|
||||
self.win.sidebar.bind_property("selected-playlist",
|
||||
self.factory, "db-visible")
|
||||
|
||||
def do_handle_local_options(self, opts: GLib.VariantDict) -> int:
|
||||
"""Handle any command line options."""
|
||||
if opts.contains("version"):
|
||||
|
@ -175,6 +184,7 @@ class Application(Adw.Application):
|
|||
Adw.Application.do_startup(self)
|
||||
self.db = db.Connection()
|
||||
self.mpris = mpris2.Connection()
|
||||
self.factory = playlist.Factory(self.db)
|
||||
self.player = audio.Player()
|
||||
|
||||
gsetup.add_style()
|
||||
|
@ -186,6 +196,7 @@ class Application(Adw.Application):
|
|||
self.win = self.build_window()
|
||||
self.add_window(self.win)
|
||||
self.connect_mpris2()
|
||||
self.connect_playlist_factory()
|
||||
|
||||
def do_activate(self) -> None:
|
||||
"""Handle the Adw.Application::activate signal."""
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
# Copyright 2023 (c) Anna Schumaker.
|
||||
"""An object for managing the visible and active playlists."""
|
||||
from gi.repository import GObject
|
||||
from .. import db
|
||||
|
||||
|
||||
class Factory(GObject.GObject):
|
||||
"""Our playlist model factory."""
|
||||
|
||||
sql = GObject.Property(type=db.Connection)
|
||||
|
||||
db_active = GObject.Property(type=db.playlist.Playlist)
|
||||
db_previous = GObject.Property(type=db.playlist.Playlist)
|
||||
db_visible = GObject.Property(type=db.playlist.Playlist)
|
||||
|
||||
def __init__(self, sql: db.Connection):
|
||||
"""Initialize the Playlist Factory."""
|
||||
super().__init__(sql=sql)
|
||||
self.sql.bind_property("active-playlist", self, "db-active")
|
||||
self.connect("notify", self.__notify_db_playlists)
|
||||
|
||||
def __notify_db_playlists(self, factory: GObject.GObject, param) -> None:
|
||||
match param.name:
|
||||
case "db-active" | "db-previous" | "db-visible":
|
||||
plist = self.get_property(param.name)
|
||||
name = "<None>" if plist is None else plist.name
|
||||
print(f"factory: {param.name[3:]} playlist is:", name)
|
|
@ -0,0 +1,2 @@
|
|||
# Copyright 2023 (c) Anna Schumaker.
|
||||
"""Needed to fix the unique basename problem with pytest."""
|
|
@ -0,0 +1,63 @@
|
|||
# Copyright 2023 (c) Anna Schumaker.
|
||||
"""Test our Playlist Manager object."""
|
||||
import io
|
||||
import unittest.mock
|
||||
import emmental.playlist
|
||||
import tests.util
|
||||
from gi.repository import GObject
|
||||
|
||||
|
||||
@unittest.mock.patch("sys.stdout", new_callable=io.StringIO)
|
||||
class TestFactory(tests.util.TestCase):
|
||||
"""Test the Playlist Factory class."""
|
||||
|
||||
def setUp(self):
|
||||
"""Set up common variables."""
|
||||
super().setUp()
|
||||
self.sql.playlists.load(now=True)
|
||||
self.user_plist = self.sql.playlists.create("User Playlist")
|
||||
self.factory = emmental.playlist.Factory(self.sql)
|
||||
|
||||
def test_init(self, mock_stdout: io.StringIO):
|
||||
"""Check that the Playlist Factory is set up properly."""
|
||||
self.assertIsInstance(self.factory, GObject.GObject)
|
||||
self.assertEqual(self.factory.sql, self.sql)
|
||||
|
||||
def test_active(self, mock_stdout: io.StringIO):
|
||||
"""Test the active playlist property."""
|
||||
self.assertIsNone(self.factory.db_active)
|
||||
|
||||
self.sql.set_active_playlist(self.user_plist)
|
||||
self.assertEqual(self.factory.db_active, self.user_plist)
|
||||
self.assertRegex(mock_stdout.getvalue(),
|
||||
"factory: active playlist is: User Playlist")
|
||||
|
||||
self.sql.set_active_playlist(None)
|
||||
self.assertIsNone(self.factory.db_active)
|
||||
self.assertRegex(mock_stdout.getvalue(), "active playlist is: <None>")
|
||||
|
||||
def test_previous(self, mock_stdout: io.StringIO):
|
||||
"""Test the previous playlist property."""
|
||||
self.assertIsNone(self.factory.db_previous)
|
||||
|
||||
self.factory.db_previous = self.sql.playlists.previous
|
||||
self.assertEqual(self.factory.db_previous, self.sql.playlists.previous)
|
||||
self.assertRegex(mock_stdout.getvalue(),
|
||||
r"factory: previous playlist is: Previous Tracks")
|
||||
|
||||
self.factory.db_previous = None
|
||||
self.assertRegex(mock_stdout.getvalue(),
|
||||
"factory: previous playlist is: <None>")
|
||||
|
||||
def test_visible(self, mock_stdout: io.StringIO):
|
||||
"""Test the visible playlist property."""
|
||||
self.assertIsNone(self.factory.db_visible)
|
||||
|
||||
self.factory.db_visible = self.user_plist
|
||||
self.assertEqual(self.factory.db_visible, self.user_plist)
|
||||
self.assertRegex(mock_stdout.getvalue(),
|
||||
"factory: visible playlist is: User Playlist")
|
||||
|
||||
self.factory.db_visible = None
|
||||
self.assertRegex(mock_stdout.getvalue(),
|
||||
"factory: visible playlist is: <None>")
|
|
@ -45,6 +45,7 @@ class TestEmmental(unittest.TestCase):
|
|||
"""Test that the startup signal works as expected."""
|
||||
self.assertIsNone(self.application.db)
|
||||
self.assertIsNone(self.application.mpris)
|
||||
self.assertIsNone(self.application.factory)
|
||||
self.assertIsNone(self.application.player)
|
||||
self.assertIsNone(self.application.win)
|
||||
|
||||
|
@ -53,6 +54,8 @@ class TestEmmental(unittest.TestCase):
|
|||
self.assertIsInstance(self.application.mpris,
|
||||
emmental.mpris2.Connection)
|
||||
self.assertIsInstance(self.application.player, emmental.audio.Player)
|
||||
self.assertIsInstance(self.application.factory,
|
||||
emmental.playlist.Factory)
|
||||
self.assertIsInstance(self.application.win, emmental.window.Window)
|
||||
|
||||
mock_startup.assert_called()
|
||||
|
@ -154,6 +157,25 @@ class TestEmmental(unittest.TestCase):
|
|||
|
||||
self.assertEqual(win.sidebar.sql, self.application.db)
|
||||
|
||||
@unittest.mock.patch("sys.stdout", new_callable=io.StringIO)
|
||||
def test_playlist_factory(self, mock_stdout: io.StringIO):
|
||||
"""Test that the Playlist Factory is wired up properly."""
|
||||
self.application.db = emmental.db.Connection()
|
||||
self.application.player = emmental.audio.Player()
|
||||
self.application.factory = emmental.playlist.Factory(
|
||||
self.application.db)
|
||||
self.application.win = self.application.build_window()
|
||||
self.application.connect_playlist_factory()
|
||||
|
||||
self.application.db.playlists.load(now=True)
|
||||
playlist = self.application.db.playlists.create("Test Playlist")
|
||||
|
||||
self.application.win.sidebar.selected_playlist = playlist
|
||||
self.assertEqual(self.application.factory.db_visible, playlist)
|
||||
|
||||
self.assertEqual(self.application.factory.db_previous,
|
||||
self.application.db.playlists.previous)
|
||||
|
||||
@unittest.mock.patch("sys.stdout", new_callable=io.StringIO)
|
||||
def test_replaygain(self, mock_stdout: io.StringIO):
|
||||
"""Test setting replaygain modes."""
|
||||
|
|
Loading…
Reference in New Issue