New Buttons (#5)
Added two new buttons to the player: - Favorite song button - Queue mode button Reviewed-on: #5
This commit is contained in:
1 parent
4c6976b2df
commit
0ca2547b54
4 files changed
+102
-2
No files matched your search
Binary file not shown.
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 33 KiB |
@@ -80,3 +80,18 @@ class NavidromeAPI:
|
||||
|
||||
return [SubSonic.Album(album_d) for album_d in response.json()]
|
||||
|
||||
def getSong(self, id: str):
|
||||
url = self.base_url + '/api/song?'
|
||||
|
||||
payload = {
|
||||
"id" : id
|
||||
}
|
||||
|
||||
response = requests.get(url + self._encodePayload(payload), headers=self.auth_header)
|
||||
|
||||
return response.json()
|
||||
|
||||
def isSongStarred(self, id: str) -> bool:
|
||||
info = self.getSong(id)
|
||||
|
||||
return info[0]['starred']
|
||||
+4
-1
@@ -306,7 +306,7 @@ class SubpyConn:
|
||||
return starred
|
||||
|
||||
# Returns a requests Response object, the data stream can be found in Response.content
|
||||
def stream(self, song_id: str, maxBitRate: int | None = None) -> requests.Response:
|
||||
def stream(self, song_id: str, maxBitRate: int | None = None, format: str | None = None) -> requests.Response:
|
||||
url = self.base_url + '/rest/stream?'
|
||||
|
||||
payload = self._getBasePayload()
|
||||
@@ -314,6 +314,9 @@ class SubpyConn:
|
||||
if maxBitRate:
|
||||
payload['maxBitRate'] = maxBitRate
|
||||
|
||||
if format:
|
||||
payload['format'] = format
|
||||
|
||||
payload['id'] = song_id
|
||||
|
||||
return requests.get(url + self._encodePayload(payload), stream=True)
|
||||
|
||||
@@ -56,6 +56,12 @@ conn = SubSonic.SubpyConn(user, passw, MUSIC_SERVER_URL)
|
||||
|
||||
pygame.mixer.init()
|
||||
|
||||
SONG_LIKED_CHAR = '♥'
|
||||
SONG_NOT_LIKED_CHAR = '♡'
|
||||
LOOP_CHAR = '⮔'
|
||||
INFINITY_CHAR = '∞'
|
||||
THREE_BARS_CHAR = '≡'
|
||||
|
||||
class AlbumSongs(Screen):
|
||||
BINDINGS = [
|
||||
('escape', 'die()', "Back"),
|
||||
@@ -1080,6 +1086,9 @@ class Player(Screen):
|
||||
def on_mount(self) -> None:
|
||||
app.sub_title = "Player"
|
||||
|
||||
pause_play: Button = self.query_one("#play_pause_track", Button)
|
||||
pause_play.focus()
|
||||
|
||||
def update_song(self, song: SubSonic.Song) -> None:
|
||||
if song.album and song.title and song.artist:
|
||||
|
||||
@@ -1098,6 +1107,11 @@ class Player(Screen):
|
||||
if cover_id:
|
||||
cover_art.get_cover_art(cover_id)
|
||||
|
||||
if song.id:
|
||||
is_song_starred: bool = app.navidrome.isSongStarred(song.id)
|
||||
like_song_button: Button = self.query_one('#like_track', Button)
|
||||
like_song_button.label = SONG_LIKED_CHAR if is_song_starred else SONG_NOT_LIKED_CHAR
|
||||
|
||||
def compose(self) -> ComposeResult:
|
||||
yield Header(icon="")
|
||||
with Horizontal(id="headerbs"):
|
||||
@@ -1121,9 +1135,11 @@ class Player(Screen):
|
||||
yield TotalDuration(classes='playerProgressBarTotalTime')
|
||||
|
||||
with Horizontal(id='playerButtons'):
|
||||
yield Button(SONG_NOT_LIKED_CHAR, id='like_track', classes='playerButton')
|
||||
yield Button('|<', id='prev_track', classes='playerButton')
|
||||
yield Button('|>/||', id='play_pause_track', classes='playerButton')
|
||||
yield Button('>|', id='next_track', classes='playerButton')
|
||||
yield Button(THREE_BARS_CHAR, id='loop_queue', classes='playerButton')
|
||||
|
||||
yield Footer()
|
||||
|
||||
@@ -1132,6 +1148,9 @@ class Player(Screen):
|
||||
app.sub_title = "Player"
|
||||
app.update_now_playing()
|
||||
|
||||
pause_play: Button = self.query_one("#play_pause_track", Button)
|
||||
pause_play.focus()
|
||||
|
||||
@on(Button.Pressed, "#prev_track")
|
||||
def prev_track_pressed(self) -> None:
|
||||
app.action_rewind()
|
||||
@@ -1148,6 +1167,40 @@ class Player(Screen):
|
||||
# app.install_screen(QueueScreen, 'queue')
|
||||
app.push_screen(QueueScreen())
|
||||
|
||||
@on(Button.Pressed, '#like_track')
|
||||
def like_track(self) -> None:
|
||||
song = app.currently_playing
|
||||
if song:
|
||||
|
||||
is_song_starred: bool = app.navidrome.isSongStarred(song.id)
|
||||
like_song_button: Button = self.query_one('#like_track', Button)
|
||||
|
||||
if not is_song_starred:
|
||||
conn.star(song.id)
|
||||
app.notify(f'Starred song "{song.title}"')
|
||||
like_song_button.label = SONG_LIKED_CHAR
|
||||
else:
|
||||
conn.unstar(song.id)
|
||||
app.notify(f'Unstarred song "{song.title}"')
|
||||
like_song_button.label = SONG_NOT_LIKED_CHAR
|
||||
|
||||
@on(Button.Pressed, '#loop_queue')
|
||||
def loop_queue(self) -> None:
|
||||
queue_button: Button = self.query_one('#loop_queue', Button)
|
||||
|
||||
if app.queue_mode == 0:
|
||||
app.queue_mode = 1
|
||||
queue_button.label = LOOP_CHAR
|
||||
app.notify('Queue mode set to "Loop Queue"')
|
||||
elif app.queue_mode == 1:
|
||||
app.queue_mode = 2
|
||||
queue_button.label = INFINITY_CHAR
|
||||
app.notify('Queue mode set to "Loop Song"')
|
||||
elif app.queue_mode == 2:
|
||||
app.queue_mode = 0
|
||||
queue_button.label = THREE_BARS_CHAR
|
||||
app.notify('Queue mode set to "Queue"')
|
||||
|
||||
# Startup keyboard listener for media keys
|
||||
def listen_media_keys(queue: multiprocessing.Queue):
|
||||
|
||||
@@ -1225,6 +1278,14 @@ class SubPy(App):
|
||||
check_playing_timer: Timer | None = None
|
||||
check_music_commands: Timer
|
||||
|
||||
"""
|
||||
Modes:
|
||||
0: standard queue, is done when queue is done
|
||||
1: loop, loops queue after queue is done
|
||||
2: loop song, loops song
|
||||
"""
|
||||
queue_mode: int = 0
|
||||
|
||||
def on_mount(self) -> None:
|
||||
self.title = "SubPy"
|
||||
self.switch_mode('main')
|
||||
@@ -1298,9 +1359,16 @@ class SubPy(App):
|
||||
|
||||
def check_done_playing(self) -> None:
|
||||
if not pygame.mixer.music.get_busy() and not self.is_paused and self.currently_playing:
|
||||
if self.queue_mode == 2:
|
||||
self.play_song(app.currently_playing)
|
||||
|
||||
if self.check_playing_timer:
|
||||
self.check_playing_timer.stop()
|
||||
return
|
||||
|
||||
self.play_history.append(self.currently_playing)
|
||||
|
||||
self.is_played = False
|
||||
self.is_playing = False
|
||||
|
||||
next_song: SubSonic.Song | None = None
|
||||
if self.user_queue:
|
||||
@@ -1308,6 +1376,13 @@ class SubPy(App):
|
||||
elif self.song_queue:
|
||||
next_song = self.song_queue.pop(0)
|
||||
|
||||
if not next_song and self.queue_mode == 1:
|
||||
self.song_queue = self.play_history.copy()
|
||||
if self.user_queue:
|
||||
next_song = self.user_queue.pop(0)
|
||||
elif self.song_queue:
|
||||
next_song = self.song_queue.pop(0)
|
||||
|
||||
if next_song:
|
||||
self.play_song(next_song)
|
||||
|
||||
@@ -1328,6 +1403,13 @@ class SubPy(App):
|
||||
elif self.song_queue:
|
||||
next_song = self.song_queue.pop(0)
|
||||
|
||||
if not next_song and self.queue_mode == 1:
|
||||
self.song_queue = self.play_history.copy()
|
||||
if self.user_queue:
|
||||
next_song = self.user_queue.pop(0)
|
||||
elif self.song_queue:
|
||||
next_song = self.song_queue.pop(0)
|
||||
|
||||
if next_song:
|
||||
self.play_song(next_song)
|
||||
|
||||
|
||||
Reference in new issue
Block a user