the queue now actually works

This commit is contained in:
JISAUAY committed 2025-01-24 17:04:06 -06:00
1 parent 2d97c921af
commit c1c640f837
5 files changed
+96 -27

No files matched your search

+2 -1
View File
@@ -1 +1,2 @@
__pycache__
__pycache__
art/*
+3 -1
View File
@@ -1,3 +1,5 @@
requests==2.31.0
textual==1.0.0
pygame==2.6.0
pygame==2.6.0
Pillow==10.0.0
rich-pixels==3.0.1
+3 -1
View File
@@ -4,7 +4,9 @@ from PIL import Image
console = Console()
size = 70
with Image.open("cover.png") as image:
pixels = Pixels.from_image(image, resize=(60, 60))
pixels = Pixels.from_image(image, resize=(size, size))
console.print(pixels)
+77 -15
View File
@@ -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()
+11 -9
View File
@@ -1,9 +1,11 @@
[2025-01-24 14:38:51,125] DEBUG in selector_events: Using selector: EpollSelector
[2025-01-24 14:38:51,902] DEBUG in screens-test: sus
[2025-01-24 14:38:51,930] DEBUG in connectionpool: Starting new HTTPS connection (1): music.0x01fe.net:443
[2025-01-24 14:38:52,091] DEBUG in connectionpool: https://music.0x01fe.net:443 "GET /rest/getPlaylists?u=pseudo&t=3b3e07bd0a56711c9db81acfb74b5560&s=2Q2MV419&v=1.16.1&c=testing&f=json HTTP/1.1" 200 705
[2025-01-24 14:38:52,947] DEBUG in connectionpool: Starting new HTTPS connection (1): music.0x01fe.net:443
[2025-01-24 14:38:53,121] DEBUG in connectionpool: https://music.0x01fe.net:443 "GET /rest/getPlaylist?u=pseudo&t=174305d05353398cf608a65562db736f&s=GQLIDGEJ&v=1.16.1&c=testing&f=json&id=e6e8ff27-2a60-4e33-8aa1-09586191166a HTTP/1.1" 200 None
[2025-01-24 14:38:54,045] DEBUG in screens-test: Playing song Theia by King Gizzard & The Lizard Wizard.
[2025-01-24 14:38:54,046] DEBUG in connectionpool: Starting new HTTPS connection (1): music.0x01fe.net:443
[2025-01-24 14:38:54,249] DEBUG in connectionpool: https://music.0x01fe.net:443 "GET /rest/stream?u=pseudo&t=61c596042c3be872619f0f39ddcc645d&s=LAPQRCLD&v=1.16.1&c=testing&id=9e28af41e8bfcf423a5a958cd7aca5cc HTTP/1.1" 200 8314893
[2025-01-24 17:00:13,155] DEBUG in selector_events: Using selector: EpollSelector
[2025-01-24 17:00:15,224] DEBUG in connectionpool: Starting new HTTPS connection (1): music.0x01fe.net:443
[2025-01-24 17:00:15,621] DEBUG in connectionpool: https://music.0x01fe.net:443 "GET /rest/getStarred?u=pseudo&t=df47a647004f9967d54a717354d758bd&s=OEYQY6IP&v=1.16.1&c=testing&f=json HTTP/1.1" 200 None
[2025-01-24 17:00:18,614] DEBUG in screens-test: Playing song rap music by Lil Darkie.
[2025-01-24 17:00:18,615] DEBUG in connectionpool: Starting new HTTPS connection (1): music.0x01fe.net:443
[2025-01-24 17:00:18,843] DEBUG in connectionpool: https://music.0x01fe.net:443 "GET /rest/stream?u=pseudo&t=17ea6e0ce1111a102699f10662381805&s=UUJ177KV&v=1.16.1&c=testing&id=62196e9d0d531adff738bf47349cbfc6 HTTP/1.1" 200 8464191
[2025-01-24 17:00:20,392] DEBUG in connectionpool: Starting new HTTPS connection (1): music.0x01fe.net:443
[2025-01-24 17:00:20,628] DEBUG in connectionpool: https://music.0x01fe.net:443 "GET /rest/getCoverArt?u=pseudo&t=36a4b74c419b83821131781619811886&s=I4SC818D&v=1.16.1&c=testing&id=62196e9d0d531adff738bf47349cbfc6 HTTP/1.1" 200 None
[2025-01-24 17:03:36,276] DEBUG in screens-test: Playing song Pegasus Pro Ultra Fusion by Dan Terminus.
[2025-01-24 17:03:36,278] DEBUG in connectionpool: Starting new HTTPS connection (1): music.0x01fe.net:443
[2025-01-24 17:03:36,763] DEBUG in connectionpool: https://music.0x01fe.net:443 "GET /rest/stream?u=pseudo&t=3b4bd01e32919d4f7868d0f89e702b93&s=94XX1BQN&v=1.16.1&c=testing&id=49f56133cf2f7bc6462be7620113ee79 HTTP/1.1" 200 None