the queue now actually works
This commit is contained in:
1 parent
2d97c921af
commit
c1c640f837
5 files changed
+96
-27
No files matched your search
+77
-15
@@ -16,12 +16,15 @@ import SubSonic
|
||||
os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = "hide"
|
||||
import pygame
|
||||
|
||||
from textual import on, events
|
||||
from textual.app import App, ComposeResult
|
||||
from textual import on, events, work
|
||||
from textual.app import App, ComposeResult, RenderResult
|
||||
from textual.widgets import Footer, Header, OptionList, DataTable, ProgressBar, Label
|
||||
from textual.containers import Horizontal, Vertical
|
||||
from textual.containers import Horizontal, Vertical, Container
|
||||
from textual.screen import Screen
|
||||
from textual.widgets.option_list import Option
|
||||
from textual.timer import Timer
|
||||
|
||||
from rich_pixels import Pixels
|
||||
|
||||
u = 'pseudo'
|
||||
p = 'telegram9dock-MICHEL'
|
||||
@@ -241,7 +244,13 @@ class PlaylistSongs(Screen):
|
||||
return i
|
||||
|
||||
class Favourites(Screen):
|
||||
BINDINGS = [
|
||||
('p', 'play()', 'Play Song'),
|
||||
('q', 'queue()', 'Queue Song')
|
||||
]
|
||||
|
||||
songs: list[SubSonic.Song] | None = None
|
||||
selected_song_id: str | None = None
|
||||
|
||||
def compose(self) -> ComposeResult:
|
||||
yield Header(icon="")
|
||||
@@ -259,13 +268,52 @@ class Favourites(Screen):
|
||||
for song in self.songs:
|
||||
songTable.add_row(song.title, song.album, song.artist, song.playCount, song.duration, song.bitRate, key=song.id)
|
||||
|
||||
@on(DataTable.RowHighlighted)
|
||||
def row_highlighted(self, event: DataTable.RowHighlighted) -> None:
|
||||
self.selected_song_id = event.row_key.value
|
||||
|
||||
def action_play(self) -> None:
|
||||
song_index = self._find_selected_song()
|
||||
app.play_song(self.songs[song_index])
|
||||
app.song_queue = self.songs[song_index + 1:]
|
||||
|
||||
def action_queue(self) -> None:
|
||||
app.queue_song(self._find_selected_song())
|
||||
|
||||
# Returns index of selected song
|
||||
def _find_selected_song(self) -> int:
|
||||
for i, song in enumerate(self.songs):
|
||||
if song.id == self.selected_song_id:
|
||||
return i
|
||||
|
||||
# TODO : Maybe should just take bytes instead of saving it as a file
|
||||
class CoverArtPixels(Container):
|
||||
|
||||
def __init__(self, cover_art_id: str):
|
||||
super().__init__()
|
||||
|
||||
self.cover_art_id = cover_art_id
|
||||
conn.getCoverArt(cover_art_id, path=f'art/{cover_art_id}.png')
|
||||
|
||||
def render(self) -> RenderResult:
|
||||
|
||||
# Make the size square
|
||||
width, height = self.size
|
||||
|
||||
if width > height:
|
||||
width = height
|
||||
elif height > width:
|
||||
height = width
|
||||
|
||||
return Pixels().from_image_path(f'art/{self.cover_art_id}.png', resize=(width, height))
|
||||
|
||||
class MainView(Screen):
|
||||
CSS_PATH = 'main.tcss'
|
||||
|
||||
def compose(self) -> ComposeResult:
|
||||
yield Header(icon="")
|
||||
with Horizontal():
|
||||
with Vertical(classes="info"):
|
||||
with Vertical(classes="info", id='info'):
|
||||
yield Label("Playing")
|
||||
yield DataTable(id="currently_playing")
|
||||
yield ProgressBar()
|
||||
@@ -284,12 +332,8 @@ class MainView(Screen):
|
||||
currentlyPlaying.cursor_type = "row"
|
||||
currentlyPlaying.add_columns("", "")
|
||||
|
||||
@on(events.ScreenSuspend)
|
||||
def sus(self, event: events.ScreenSuspend) -> None:
|
||||
logging.debug('sus')
|
||||
|
||||
@on(events.ScreenResume)
|
||||
def screen_resumed(self, event: events.ScreenResume) -> None:
|
||||
async def screen_resumed(self, event: events.ScreenResume) -> None:
|
||||
app.sub_title = "Overview"
|
||||
|
||||
# Update Queue Table
|
||||
@@ -315,6 +359,8 @@ class MainView(Screen):
|
||||
currentlyPlaying.add_row("Track Number", song.trackNumber)
|
||||
currentlyPlaying.add_row("Bit Rate", song.bitRate)
|
||||
|
||||
await self.query_one('#info').mount(CoverArtPixels(app.currently_playing.id))
|
||||
|
||||
def _clear_table(self, table_id: str) -> None:
|
||||
table: DataTable = self.query_one(table_id)
|
||||
|
||||
@@ -347,9 +393,10 @@ class TextualSubpyPlayer(App):
|
||||
currently_playing: SubSonic.Song | None = None
|
||||
song_queue: list[SubSonic.Song] = []
|
||||
user_queue: list[SubSonic.Song] = []
|
||||
isPlaying: bool = False
|
||||
is_paused: bool = False
|
||||
place: int = 0
|
||||
|
||||
check_playing_timer: Timer | None = None
|
||||
|
||||
def on_mount(self) -> None:
|
||||
self.title = "SubPy"
|
||||
@@ -359,9 +406,10 @@ class TextualSubpyPlayer(App):
|
||||
# logging.debug(f'Key Pressed {event.name}')
|
||||
pass
|
||||
|
||||
def play_song(self, song: SubSonic.Song) -> None:
|
||||
@work(exclusive=True)
|
||||
async def play_song(self, song: SubSonic.Song) -> None:
|
||||
self.currently_playing = song
|
||||
self.isPlaying = True
|
||||
self.is_paused = False
|
||||
logging.debug(f"Playing song {song.title} by {song.artist}.")
|
||||
|
||||
self.notify(f"Playing \"{song.title}\" by {song.artist}.")
|
||||
@@ -372,17 +420,31 @@ class TextualSubpyPlayer(App):
|
||||
pygame.mixer.music.load(audio_data)
|
||||
pygame.mixer.music.play()
|
||||
|
||||
self.check_playing_timer = self.set_interval(1 / 5, self.check_done_playing, pause=False)
|
||||
|
||||
# playingLabel: Label = self.query_one(Label)
|
||||
# playingLabel.
|
||||
|
||||
# Set callback loop for progress bar
|
||||
# self.progress_timer = self.set_interval(1 / 10, self.update_progress, pause=False)
|
||||
|
||||
def check_done_playing(self) -> None:
|
||||
if not pygame.mixer.music.get_busy() and not self.is_paused:
|
||||
queue = self.user_queue
|
||||
queue.extend(self.song_queue)
|
||||
|
||||
next_song = queue.pop(0)
|
||||
|
||||
self.play_song(next_song)
|
||||
|
||||
self.check_playing_timer.stop()
|
||||
|
||||
# def update_progress(self) -> None:
|
||||
# self.query_one(ProgressBar).advance(1)
|
||||
|
||||
def queue_song(self, song: SubSonic.Song) -> None:
|
||||
logging.debug(f'Queue\'d song "{song.title}" by {song.artist}.')
|
||||
self.notify(f'Queue\'d song "{song.title}" by {song.artist}.')
|
||||
self.user_queue.append(song)
|
||||
|
||||
def action_play_pause_song(self) -> None:
|
||||
@@ -392,13 +454,13 @@ class TextualSubpyPlayer(App):
|
||||
if not self.currently_playing:
|
||||
return None
|
||||
|
||||
if self.isPlaying:
|
||||
if not self.is_paused:
|
||||
self.place = pygame.mixer.music.get_pos()
|
||||
pygame.mixer.music.pause()
|
||||
self.isPlaying = False
|
||||
self.is_paused = True
|
||||
else:
|
||||
pygame.mixer.music.unpause()
|
||||
self.isPlaying = True
|
||||
self.is_paused = False
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = TextualSubpyPlayer()
|
||||
|
||||
Reference in new issue
Block a user