bug fixes with guis and added album songs screen
This commit is contained in:
1 parent
1e8b8ca206
commit
072db9b206
2 files changed
+160
-20
No files matched your search
@@ -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)
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
[STREAMING]
|
[STREAMING]
|
||||||
Cache = true
|
Cache = true
|
||||||
Bitrate = 320kbps
|
Bitrate = 320kbps
|
||||||
|
|
||||||
|
[GENERAL]
|
||||||
|
GUI = true
|
||||||
Reference in new issue
Block a user