added a shuffle play feature + fixed some bugs with duplicate songs on a playlist

This commit is contained in:
JISAUAY committed 2025-09-10 13:14:48 -05:00
1 parent 0856fbfbbf
commit ab94a8a9ee
1 file changed
+44 -9
+44 -9
View File
@@ -1,4 +1,5 @@
import logging import logging
import random
import os import os
import io import io
import asyncio import asyncio
@@ -48,11 +49,12 @@ class AlbumSongs(Screen):
BINDINGS = [ BINDINGS = [
('escape', 'die()', "Back"), ('escape', 'die()', "Back"),
('p', 'play()', 'Play Song'), ('p', 'play()', 'Play Song'),
('q' 'queue()', 'Queue Song') ('q' 'queue()', 'Queue Song'),
('m', 'shuffle_mix()', 'Shuffle Play')
] ]
selected_song_id: str | None = None selected_song_id: str | None = None
songs = None songs: list[SubSonic.Song]
def __init__(self, album_id: str): def __init__(self, album_id: str):
self.album_id = album_id self.album_id = album_id
@@ -96,6 +98,13 @@ class AlbumSongs(Screen):
app.pop_screen() app.pop_screen()
app.uninstall_screen("albumSongs") app.uninstall_screen("albumSongs")
def action_shuffle_mix(self) -> None:
q = self.songs.copy()
random.shuffle(q)
app.play_song(q.pop(0))
app.song_queue = q
app.update_queue_table()
class ArtistAlbums(Screen): class ArtistAlbums(Screen):
BINDINGS = [ BINDINGS = [
('escape', 'die()', "Back") ('escape', 'die()', "Back")
@@ -207,10 +216,12 @@ class PlaylistSongs(Screen):
BINDINGS = [ BINDINGS = [
('escape', 'die()', "Back"), ('escape', 'die()', "Back"),
('p', 'play()', 'Play Song'), ('p', 'play()', 'Play Song'),
('q', 'queue()', 'Queue Song') ('q', 'queue()', 'Queue Song'),
('m', 'shuffle_mix()', 'Shuffle Play')
] ]
selected_song_id: str | None = None selected_song_id: str | None = None
songs: list[SubSonic.Song]
def __init__(self, playlist: SubSonic.Playlist): def __init__(self, playlist: SubSonic.Playlist):
self.playlist = playlist self.playlist = playlist
@@ -229,8 +240,8 @@ class PlaylistSongs(Screen):
songTable.cursor_type = "row" songTable.cursor_type = "row"
songTable.add_columns("Title", "Album", "Artist", "Plays", "Duration", "Bitrate") songTable.add_columns("Title", "Album", "Artist", "Plays", "Duration", "Bitrate")
for song in self.songs: for i, song in enumerate(self.songs):
songTable.add_row(song.title, song.album, song.artist, song.playCount, song.duration, song.bitRate, key=song.id) songTable.add_row(song.title, song.album, song.artist, song.playCount, song.duration, song.bitRate, key=str(i))
# Pops and uninstalls self # Pops and uninstalls self
def action_die(self) -> None: def action_die(self) -> None:
@@ -239,7 +250,7 @@ class PlaylistSongs(Screen):
@on(DataTable.RowHighlighted) @on(DataTable.RowHighlighted)
def row_highlighted(self, event: DataTable.RowHighlighted) -> None: def row_highlighted(self, event: DataTable.RowHighlighted) -> None:
self.selected_song_id = event.row_key.value self.selected_song_id = self.songs[int(event.row_key.value)].id
def action_play(self) -> None: def action_play(self) -> None:
song_index = self._find_selected_song() song_index = self._find_selected_song()
@@ -257,13 +268,21 @@ class PlaylistSongs(Screen):
if song.id == self.selected_song_id: if song.id == self.selected_song_id:
return i return i
def action_shuffle_mix(self) -> None:
q = self.songs.copy()
random.shuffle(q)
app.play_song(q.pop(0))
app.song_queue = q
app.update_queue_table()
class Favourites(Screen): class Favourites(Screen):
BINDINGS = [ BINDINGS = [
('p', 'play()', 'Play Song'), ('p', 'play()', 'Play Song'),
('q', 'queue()', 'Queue Song') ('q', 'queue()', 'Queue Song'),
('m', 'shuffle_mix()', 'Shuffle Play')
] ]
songs: list[SubSonic.Song] | None = None songs: list[SubSonic.Song]
selected_song_id: str | None = None selected_song_id: str | None = None
def compose(self) -> ComposeResult: def compose(self) -> ComposeResult:
@@ -293,7 +312,8 @@ class Favourites(Screen):
app.update_queue_table() app.update_queue_table()
def action_queue(self) -> None: def action_queue(self) -> None:
app.queue_song(self._find_selected_song()) song_index = self._find_selected_song()
app.queue_song(self.songs[song_index])
# Returns index of selected song # Returns index of selected song
def _find_selected_song(self) -> int: def _find_selected_song(self) -> int:
@@ -301,6 +321,13 @@ class Favourites(Screen):
if song.id == self.selected_song_id: if song.id == self.selected_song_id:
return i return i
def action_shuffle_mix(self) -> None:
q = self.songs.copy()
random.shuffle(q)
app.play_song(q.pop(0))
app.song_queue = q
app.update_queue_table()
# TODO fix coverart # TODO fix coverart
class CoverArtPixels(Container): class CoverArtPixels(Container):
@@ -491,6 +518,8 @@ class TextualSubpyPlayer(App):
("r", "rewind()", "⏪"), ("r", "rewind()", "⏪"),
("space", "play_pause_song()", "⏯"), ("space", "play_pause_song()", "⏯"),
("s", "skip()", "⏭"), ("s", "skip()", "⏭"),
("d", "volume_down()", "🕩"),
("u", "volume_up()", "🕪"),
("f1", "switch_mode('main')", "Overview"), ("f1", "switch_mode('main')", "Overview"),
("f2", "switch_mode('artists')", "Artists"), ("f2", "switch_mode('artists')", "Artists"),
("f3", "switch_mode('albums')", "Albums"), ("f3", "switch_mode('albums')", "Albums"),
@@ -627,6 +656,12 @@ class TextualSubpyPlayer(App):
def action_play_pause_song(self) -> None: def action_play_pause_song(self) -> None:
self.play_pause_song() self.play_pause_song()
def action_volume_down(self) -> None:
pygame.mixer.music.set_volume(max(pygame.mixer.music.get_volume() - 0.05, 0.0))
def action_volume_up(self) -> None:
pygame.mixer.music.set_volume(min(pygame.mixer.music.get_volume() + 0.05, 1.0))
def play_pause_song(self) -> None: def play_pause_song(self) -> None:
if not self.currently_playing: if not self.currently_playing:
return None return None