bug fixes with guis and added album songs screen

This commit is contained in:
JISAUAY committed 2025-09-24 14:20:34 -05:00
1 parent 1e8b8ca206
commit 072db9b206
2 files changed
+160 -20

No files matched your search

+157 -20
View File
@@ -23,6 +23,7 @@ CACHE = config.getboolean('STREAMING', 'Cache')
BITRATE = config.get('STREAMING', 'Bitrate') BITRATE = config.get('STREAMING', 'Bitrate')
BITRATE = re.findall(r'[0-9]+', BITRATE)[0] BITRATE = re.findall(r'[0-9]+', BITRATE)[0]
BITRATE = int(BITRATE) if BITRATE else BITRATE BITRATE = int(BITRATE) if BITRATE else BITRATE
IMAGE_MODE = config.getboolean('GENERAL', 'GUI')
os.makedirs(".cache/art/", exist_ok=True) os.makedirs(".cache/art/", exist_ok=True)
os.makedirs(".cache/audio/", exist_ok=True) os.makedirs(".cache/audio/", exist_ok=True)
@@ -170,13 +171,32 @@ class AlbumPanel(Widget, can_focus=True, can_focus_children=True):
label = self.query_one(Label) label = self.query_one(Label)
label.update(self.album.album) label.update(self.album.album)
class ArtistAlbums2(Screen): @on(events.Click)
def clicked(self, event: events.Click) -> None:
app.install_screen(AlbumSongs(self.album.id), 'albumSongs')
app.push_screen('albumSongs')
def clear(self) -> None:
self.album = None
coverArt = self.query_one(CoverArtPixels)
coverArt.cover = None
label = self.query_one(Label)
label.update('')
class ArtistAlbumsGUI(Screen):
BINDINGS = [ BINDINGS = [
('escape', 'die()', "Back") ('escape', 'die()', "Back"),
Binding('a', 'page_backward()', 'Prev. Page'),
Binding('d', 'page_forward()', 'Next Page')
] ]
artist: SubSonic.Artist artist: SubSonic.Artist
albums: list[SubSonic.Album] albums: list[SubSonic.Album]
page: int = 1
pages: int = 1
albums_displayed: int
def __init__(self, artist: SubSonic.Artist): def __init__(self, artist: SubSonic.Artist):
self.artist = artist self.artist = artist
@@ -201,27 +221,82 @@ class ArtistAlbums2(Screen):
yield AlbumPanel(classes="albumPanel") yield AlbumPanel(classes="albumPanel")
yield AlbumPanel(classes="albumPanel") yield AlbumPanel(classes="albumPanel")
yield AlbumPanel(classes="albumPanel") yield AlbumPanel(classes="albumPanel")
yield Label(id='page-counter')
yield Footer() yield Footer()
def on_mount(self) -> None: def on_mount(self) -> None:
self.albums = conn.getArtistAlbums(self.artist.id) self.albums = conn.getArtistAlbums(self.artist.id)
album_panels = self.query(AlbumPanel)
artist_header = self.query_one(Label) artist_header = self.query_one(Label)
artist_header.update(self.artist.name) artist_header.update(self.artist.name)
albums_displayed = 0 self.pages = math.ceil(len(self.albums) / len(album_panels))
album_panels = self.query(AlbumPanel) self.update_pager()
for album_panel in album_panels:
album_panel.set_album(self.albums[albums_displayed])
albums_displayed += 1
if albums_displayed >= len(self.albums) - 1: self.albums_displayed = 0
for album_panel in album_panels:
album_panel.set_album(self.albums[self.albums_displayed])
self.albums_displayed += 1
if self.albums_displayed >= len(self.albums):
return return
def update_pager(self) -> None:
pager = self.query_one('#page-counter', Label)
pager.update(f'{self.page} ... {self.pages}')
def _clear_panels(self) -> None:
album_panels = self.query(AlbumPanel)
for panel in album_panels:
panel.clear()
def action_die(self) -> None: def action_die(self) -> None:
app.pop_screen() app.pop_screen()
app.uninstall_screen("artistAlbums") app.uninstall_screen("artistAlbums")
def action_page_forward(self) -> None:
album_panels = self.query(AlbumPanel)
if self.page + 1 > self.pages:
return
self.page += 1
self.update_pager()
self._clear_panels()
for album_panel in album_panels:
if self.albums_displayed >= len(self.albums):
return
album_panel.set_album(self.albums[self.albums_displayed])
self.albums_displayed += 1
def action_page_backward(self) -> None:
album_panels = self.query(AlbumPanel)
if self.page - 1 <= 0:
return
# count how many panels actually are displaying an album
real_displayed = 0
for album_panel in album_panels:
if album_panel.album:
real_displayed += 1
self.page -= 1
self.update_pager()
self._clear_panels()
self.albums_displayed -= len(album_panels) + real_displayed
for album_panel in album_panels:
if self.albums_displayed >= len(self.albums):
return
album_panel.set_album(self.albums[self.albums_displayed])
self.albums_displayed += 1
class Artists(Screen): class Artists(Screen):
artists: list[SubSonic.Artist] artists: list[SubSonic.Artist]
@@ -322,7 +397,7 @@ class ArtistArt(Static):
class ArtistPanel(Widget, can_focus=True, can_focus_children=True): class ArtistPanel(Widget, can_focus=True, can_focus_children=True):
artist: SubSonic.Artist artist: SubSonic.Artist | None
def compose(self) -> ComposeResult: def compose(self) -> ComposeResult:
yield ArtistArt(classes="artistArt") yield ArtistArt(classes="artistArt")
@@ -339,20 +414,33 @@ class ArtistPanel(Widget, can_focus=True, can_focus_children=True):
@on(events.Click) @on(events.Click)
def clicked(self, event: events.Click) -> None: def clicked(self, event: events.Click) -> None:
if not self.artist:
return
logging.debug(f'ArtistPanel {self.artist.name} was clicked.') logging.debug(f'ArtistPanel {self.artist.name} was clicked.')
app.install_screen(ArtistAlbums2(self.artist), 'artistAlbums') app.install_screen(ArtistAlbumsGUI(self.artist), 'artistAlbums')
app.push_screen('artistAlbums') app.push_screen('artistAlbums')
class Artists2(Screen): def clear(self) -> None:
self.artist = None
art: ArtistArt = self.query_one(ArtistArt)
art.art = None
label = self.query_one(Label)
label.update('')
class ArtistsGUI(Screen):
BINDINGS = [ BINDINGS = [
Binding('d', "page_forward()", "Next Page"), Binding('a', "page_backward()", "Prev. Page"),
Binding('a', "page_backward()", "Prev. Page") Binding('d', "page_forward()", "Next Page")
] ]
artists: list[SubSonic.Artist] artists: list[SubSonic.Artist]
artists_displayed: int = 0 artists_displayed: int = 0
page: int = 1 page: int = 1
pages: int = 1
def compose(self) -> ComposeResult: def compose(self) -> ComposeResult:
yield Header(icon='') yield Header(icon='')
@@ -362,6 +450,7 @@ class Artists2(Screen):
yield Label(Text("F3 ", style="bold orange").append_text(Text("Albums", style="white")), classes="headerb") yield Label(Text("F3 ", style="bold orange").append_text(Text("Albums", style="white")), classes="headerb")
yield Label(Text("F4 ", style="bold orange").append_text(Text("Favourites", style="white")), classes="headerb") yield Label(Text("F4 ", style="bold orange").append_text(Text("Favourites", style="white")), classes="headerb")
yield Label(Text("F5 ", style="bold orange").append_text(Text("Playlists", style="white")), classes="headerb") yield Label(Text("F5 ", style="bold orange").append_text(Text("Playlists", style="white")), classes="headerb")
yield Input(placeholder="Search", id="artistSearchBar")
with Horizontal(): with Horizontal():
yield ArtistPanel(classes="artistPanel") yield ArtistPanel(classes="artistPanel")
yield ArtistPanel(classes="artistPanel") yield ArtistPanel(classes="artistPanel")
@@ -384,14 +473,15 @@ class Artists2(Screen):
yield Footer() yield Footer()
def on_mount(self) -> None: def on_mount(self) -> None:
app.sub_title = 'Artists2' app.sub_title = 'Artists'
self.artists = conn.getArtists() self.artists = conn.getArtists()
artist_panels = self.query(ArtistPanel)
self.artists_displayed = 0 self.artists_displayed = 0
self.pages = math.ceil(len(self.artists)/len(artist_panels))
self.update_pager() self.update_pager()
artist_panels = self.query(ArtistPanel)
for artist_panel in artist_panels: for artist_panel in artist_panels:
if self.artists_displayed >= len(self.artists) - 1: if self.artists_displayed >= len(self.artists) - 1:
return return
@@ -401,13 +491,17 @@ class Artists2(Screen):
def update_pager(self) -> None: def update_pager(self) -> None:
pager = self.query_one("#page-counter", Label) pager = self.query_one("#page-counter", Label)
pager.update(f"{self.page} ... {math.ceil(len(self.artists)/15)}") pager.update(f"{self.page} ... {self.pages}")
def action_page_forward(self) -> None: def action_page_forward(self) -> None:
artist_panels = self.query(ArtistPanel) artist_panels = self.query(ArtistPanel)
if self.page + 1 > self.pages:
return
self.page += 1 self.page += 1
self.update_pager() self.update_pager()
self._clear_panels()
for artist_panel in artist_panels: for artist_panel in artist_panels:
if self.artists_displayed >= len(self.artists) - 1: if self.artists_displayed >= len(self.artists) - 1:
@@ -419,14 +513,52 @@ class Artists2(Screen):
def action_page_backward(self) -> None: def action_page_backward(self) -> None:
artist_panels = self.query(ArtistPanel) artist_panels = self.query(ArtistPanel)
if self.page - 1 <= 0:
return
self.page -= 1 self.page -= 1
self.update_pager() self.update_pager()
self._clear_panels()
self.artists_displayed -= 30 self.artists_displayed -= len(artist_panels) * 2
for artist_panel in artist_panels: for artist_panel in artist_panels:
artist_panel.set_artist(self.artists[self.artists_displayed]) artist_panel.set_artist(self.artists[self.artists_displayed])
self.artists_displayed += 1 self.artists_displayed += 1
def _clear_panels(self) -> None:
artist_panels = self.query(ArtistPanel)
for artist_panel in artist_panels:
artist_panel.clear()
@on(Input.Submitted)
def search_submit(self, event: Input.Submitted) -> None:
search_value = event.value.lower()
logging.debug(search_value)
artist_panels = self.query(ArtistPanel)
self.artists_displayed = 0
filtered_artists = []
for artist in self.artists:
if search_value in artist.name.lower():
filtered_artists.append(artist)
self.page = 1
self.pages = math.ceil(len(filtered_artists) / len(artist_panels))
self.update_pager()
self._clear_panels()
for artist_panel in artist_panels:
if self.artists_displayed >= len(filtered_artists):
return
artist_panel.set_artist(filtered_artists[self.artists_displayed])
self.artists_displayed += 1
class Albums(Screen): class Albums(Screen):
albums: list[SubSonic.Album] albums: list[SubSonic.Album]
@@ -846,13 +978,14 @@ class TextualSubpyPlayer(App):
MODES = { MODES = {
"main" : MainView, "main" : MainView,
"artists" : Artists2, "artists" : ArtistsGUI,
"albums" : Albums, "albums" : Albums,
"favourites" : Favourites, "favourites" : Favourites,
"playlists" : Playlists "playlists" : Playlists
} }
currently_playing: SubSonic.Song | None = reactive(SubSonic.Song()) currently_playing: SubSonic.Song | None = reactive(SubSonic.Song())
is_playing: bool = False
song_queue: list[SubSonic.Song] = reactive([]) song_queue: list[SubSonic.Song] = reactive([])
user_queue: list[SubSonic.Song] = reactive([]) user_queue: list[SubSonic.Song] = reactive([])
play_history: list[SubSonic.Song] = [] play_history: list[SubSonic.Song] = []
@@ -869,6 +1002,7 @@ class TextualSubpyPlayer(App):
async def play_song(self, song: SubSonic.Song) -> None: async def play_song(self, song: SubSonic.Song) -> None:
self.currently_playing = song self.currently_playing = song
self.is_paused = False self.is_paused = False
self.is_playing = True
logging.debug(f"Playing song {song.title} by {song.artist}.") logging.debug(f"Playing song {song.title} by {song.artist}.")
self.notify(f"Playing \"{song.title}\" by {song.artist}.") self.notify(f"Playing \"{song.title}\" by {song.artist}.")
@@ -920,6 +1054,8 @@ class TextualSubpyPlayer(App):
if not pygame.mixer.music.get_busy() and not self.is_paused and self.currently_playing: if not pygame.mixer.music.get_busy() and not self.is_paused and self.currently_playing:
self.play_history.append(self.currently_playing) self.play_history.append(self.currently_playing)
self.is_played = False
next_song: SubSonic.Song | None = None next_song: SubSonic.Song | None = None
if self.user_queue: if self.user_queue:
next_song = self.user_queue.pop(0) next_song = self.user_queue.pop(0)
@@ -983,7 +1119,7 @@ class TextualSubpyPlayer(App):
pygame.mixer.music.set_volume(min(pygame.mixer.music.get_volume() + 0.05, 1.0)) 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 or not self.is_playing:
return None return None
if not self.is_paused: if not self.is_paused:
@@ -1019,7 +1155,8 @@ class TextualSubpyPlayer(App):
async def action_star_c_song(self) -> None: async def action_star_c_song(self) -> None:
if self.currently_playing: if self.currently_playing:
asyncio.create_task(asyncio.to_thread(conn.star, self.currently_playing.id)) await asyncio.create_task(asyncio.to_thread(conn.star, self.currently_playing.id))
self.notify(f'Favourite song "{self.currently_playing.title}".')
def on_key(self, event: events.Key) -> None: def on_key(self, event: events.Key) -> None:
logging.debug(event.key) logging.debug(event.key)
+3
View File
@@ -1,3 +1,6 @@
[STREAMING] [STREAMING]
Cache = true Cache = true
Bitrate = 320kbps Bitrate = 320kbps
[GENERAL]
GUI = true