playlist: Create a Previous Playlist type

This Playlist implements some special handling for the Previous
Playlist. This includes adding a previous_tracks() function and
properties to indicate if the Playlist has a previous or next track.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
Anna Schumaker 2023-04-19 15:58:01 -04:00
parent 55486c20c3
commit f5ef144419
2 changed files with 131 additions and 0 deletions

View File

@ -0,0 +1,39 @@
# Copyright 2023 (c) Anna Schumaker.
"""A Playlist model configured for the Previous Tracks playlist."""
from gi.repository import GObject
from . import playlist
from .. import db
class Previous(playlist.Playlist):
"""A Playlist configured for Previous Tracks."""
can_go_forward = GObject.Property(type=bool, default=False)
def __init__(self, sql: db.Connection, playlist: db.playlist.Playlist):
"""Initialize the Previous Playlist object."""
super().__init__(sql=sql, playlist=playlist)
self.connect("notify::current-track", self.__notify_current_track)
def __notify_current_track(self, plist: playlist.Playlist, param) -> None:
current = self.current_track
self.can_go_forward = current and current != self[0]
def do_get_sort_key(self, trackid: int) -> float:
"""Get the sort key for a given trackid."""
track = self.sql.tracks.rows.get(trackid)
return 0 if track is None else -track.laststarted.timestamp()
def on_trackid_added(self, set: db.tracks.TrackidSet,
trackid: int) -> None:
"""Handle the TrackidSet::trackid-added signal."""
super().on_trackid_added(set, trackid)
self.playlist.current_trackid = self.trackids[0]
self.notify("current-track")
def previous_track(self) -> db.tracks.Track | None:
"""Go backwards one Track."""
if self.playlist is not None and len(self.trackids) > 0:
if (index := self.index(self.current_track)) > 0:
self.current_track = self[index - 1]
return self.current_track

View File

@ -0,0 +1,92 @@
# Copyright 2023 (c) Anna Schumaker.
"""Tests our Previous Tracks Playlist model."""
import pathlib
import tests.util
import emmental.playlist.previous
class TestPrevious(tests.util.TestCase):
"""Tests the Previous Playlist Gio.ListModel."""
def setUp(self):
"""Set up common variables."""
super().setUp()
self.sql.playlists.load(now=True)
self.previous = emmental.playlist.previous.Previous(
self.sql, self.sql.playlists.previous)
self.library = self.sql.libraries.create(pathlib.Path("/a/b"))
self.album = self.sql.albums.create("Test Album", "Artist", "2023")
self.medium = self.sql.media.create(self.album, "", number=1)
self.year = self.sql.years.create(2023)
self.tracks = [self.sql.tracks.create(self.library,
pathlib.Path(f"/a/b/{i}.ogg"),
self.medium, self.year, number=i)
for i in range(1, 6)]
def test_init(self):
"""Test that the Previous Playlist was set up correctly."""
self.assertIsInstance(self.previous,
emmental.playlist.playlist.Playlist)
self.assertEqual(self.previous.playlist, self.sql.playlists.previous)
def test_can_go_forward(self):
"""Test the can-go-forward property."""
self.assertFalse(self.previous.can_go_forward)
self.tracks[0].start()
self.assertFalse(self.previous.can_go_forward)
self.tracks[1].start()
self.assertFalse(self.previous.can_go_forward)
self.previous.next_track()
self.assertTrue(self.previous.can_go_forward)
def test_start_tracks(self):
"""Test that tracks added to the playlist are sorted correctly."""
self.tracks[0].start()
self.assertEqual(self.previous[0], self.tracks[0])
self.assertEqual(self.previous.current_track, self.tracks[0])
self.tracks[1].start()
self.assertEqual(self.previous[0], self.tracks[1])
self.assertEqual(self.previous[1], self.tracks[0])
self.tracks[2].start()
self.assertEqual(self.previous[0], self.tracks[2])
self.assertEqual(self.previous[1], self.tracks[1])
self.assertEqual(self.previous[2], self.tracks[0])
def test_previous_track(self):
"""Test the previous_track() function."""
self.assertIsNone(self.previous.previous_track())
for track in self.tracks:
track.start()
self.previous.current_track = self.tracks[0]
self.assertEqual(self.previous.previous_track(), self.tracks[1])
self.assertEqual(self.previous.previous_track(), self.tracks[2])
self.assertEqual(self.previous.previous_track(), self.tracks[3])
self.assertEqual(self.previous.previous_track(), self.tracks[4])
self.assertIsNone(self.previous.previous_track())
self.previous.playlist = None
self.assertIsNone(self.previous.previous_track())
def test_next_previous_track(self):
"""Test mixing the next_track() and previous_track() functions."""
for track in self.tracks:
track.start()
self.assertEqual(self.previous.next_track(), self.tracks[3])
self.assertEqual(self.previous.next_track(), self.tracks[2])
self.assertEqual(self.previous.next_track(), self.tracks[1])
self.assertEqual(self.previous.next_track(), self.tracks[0])
self.assertIsNone(self.previous.next_track())
self.assertEqual(self.previous.previous_track(), self.tracks[1])
self.assertEqual(self.previous.previous_track(), self.tracks[2])
self.assertEqual(self.previous.previous_track(), self.tracks[3])