you can now play and pause songs
This commit is contained in:
1 parent
f8815964b5
commit
2fe525d0d6
5 files changed
+1817
-311
No files matched your search
+96
-4
@@ -1,7 +1,6 @@
|
||||
import logging
|
||||
import os
|
||||
|
||||
from enum import Enum
|
||||
import io
|
||||
|
||||
LOG_FILE = 'textual.log'
|
||||
LOGGING_LEVEL = logging.DEBUG
|
||||
@@ -14,10 +13,12 @@ logging.basicConfig(filename=LOG_FILE, level=LOGGING_LEVEL, format=LOG_FORMAT)
|
||||
|
||||
import SubSonic
|
||||
|
||||
os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = "hide"
|
||||
import pygame
|
||||
|
||||
from textual import on, events
|
||||
from textual.app import App, ComposeResult
|
||||
from textual.widgets import Footer, Header, OptionList, DataTable, Tabs, Tab, TabbedContent, TabPane, ProgressBar, Label
|
||||
from textual.widgets import Footer, Header, OptionList, DataTable, ProgressBar, Label
|
||||
from textual.screen import Screen
|
||||
from textual.widgets.option_list import Option
|
||||
|
||||
@@ -26,6 +27,8 @@ p = 'telegram9dock-MICHEL'
|
||||
|
||||
conn = SubSonic.SubpyConn(u, p, "https://music.0x01fe.net")
|
||||
|
||||
pygame.mixer.init()
|
||||
|
||||
class AlbumSongs(Screen):
|
||||
BINDINGS = [
|
||||
('escape', 'die()', "Back"),
|
||||
@@ -161,6 +164,7 @@ class Playlists(Screen):
|
||||
]
|
||||
|
||||
playlists: list[SubSonic.Playlist] | None = None
|
||||
selected_playlist_id: str = None
|
||||
|
||||
def compose(self) -> ComposeResult:
|
||||
yield Header(icon="")
|
||||
@@ -178,6 +182,71 @@ class Playlists(Screen):
|
||||
for playlist in self.playlists:
|
||||
playlistTable.add_row(playlist.name, playlist.songCount, playlist.duration, playlist.owner, key=playlist.id)
|
||||
|
||||
@on(DataTable.RowHighlighted)
|
||||
def row_highlighted(self, event: DataTable.RowHighlighted) -> None:
|
||||
self.selected_playlist_id = event.row_key.value
|
||||
|
||||
@on(DataTable.RowSelected)
|
||||
def playlist_selected(self, event: DataTable.RowSelected) -> None:
|
||||
app.install_screen(PlaylistSongs(self._find_selected_playlist()), "playlistSongs")
|
||||
app.push_screen('playlistSongs')
|
||||
|
||||
def _find_selected_playlist(self) -> SubSonic.Playlist:
|
||||
for playlist in self.playlists:
|
||||
if playlist.id == self.selected_playlist_id:
|
||||
return playlist
|
||||
|
||||
|
||||
class PlaylistSongs(Screen):
|
||||
BINDINGS = [
|
||||
('escape', 'die()', "Back"),
|
||||
('p', 'play()', 'Play Song'),
|
||||
('q' 'queue()', 'Queue Song')
|
||||
]
|
||||
|
||||
selected_song_id: str | None = None
|
||||
|
||||
def __init__(self, playlist: SubSonic.Playlist):
|
||||
self.playlist = playlist
|
||||
self.songs = conn.getPlaylist(playlist.id)
|
||||
super().__init__()
|
||||
|
||||
def compose(self) -> ComposeResult:
|
||||
self.sub_title = self.playlist.name
|
||||
yield Header(icon="")
|
||||
yield DataTable()
|
||||
yield Footer()
|
||||
|
||||
def on_mount(self) -> None:
|
||||
songTable: DataTable = self.query_one(DataTable)
|
||||
|
||||
songTable.cursor_type = "row"
|
||||
songTable.add_columns("Title", "Album", "Artist", "Plays", "Duration", "Bitrate")
|
||||
|
||||
for song in self.songs:
|
||||
songTable.add_row(song.title, song.album, song.artist, song.playCount, song.duration, song.bitRate, key=song.id)
|
||||
|
||||
# Pops and uninstalls self
|
||||
def action_die(self) -> None:
|
||||
app.pop_screen()
|
||||
app.uninstall_screen("playlistSongs")
|
||||
|
||||
@on(DataTable.RowHighlighted)
|
||||
def row_highlighted(self, event: DataTable.RowHighlighted) -> None:
|
||||
self.selected_song_id = event.row_key.value
|
||||
|
||||
def action_play(self) -> None:
|
||||
app.play_song(self._find_selected_song())
|
||||
|
||||
def action_queue(self) -> None:
|
||||
app.queue_song(self._find_selected_song())
|
||||
|
||||
# Find the song that was selected
|
||||
def _find_selected_song(self) -> SubSonic.Song:
|
||||
for song in self.songs:
|
||||
if song.id == self.selected_song_id:
|
||||
return song
|
||||
|
||||
class Favourites(Screen):
|
||||
BINDINGS = [
|
||||
('escape', 'app.pop_screen', "Back")
|
||||
@@ -203,6 +272,7 @@ class Favourites(Screen):
|
||||
|
||||
class TextualSubpyPlayer(App):
|
||||
BINDINGS = [
|
||||
("space", "play_pause_song()", "⏯️"),
|
||||
("f1", "push_screen('artists')", "Artists"),
|
||||
("f2", "push_screen('albums')", "Albums"),
|
||||
("f3", "push_screen('favourites')", "Favourites"),
|
||||
@@ -211,6 +281,8 @@ class TextualSubpyPlayer(App):
|
||||
|
||||
currently_playing: SubSonic.Song | None = None
|
||||
song_queue: list[SubSonic.Song] = []
|
||||
playing: bool = False
|
||||
place: int = 0
|
||||
|
||||
def compose(self) -> ComposeResult:
|
||||
yield Label()
|
||||
@@ -226,12 +298,20 @@ class TextualSubpyPlayer(App):
|
||||
self.install_screen(Playlists(), name="playlists")
|
||||
|
||||
def on_key(self, event: events.Key) -> None:
|
||||
logging.debug(f'Key Pressed {event.name}')
|
||||
# logging.debug(f'Key Pressed {event.name}')
|
||||
pass
|
||||
|
||||
def play_song(self, song: SubSonic.Song) -> None:
|
||||
self.currently_playing = song
|
||||
self.playing = True
|
||||
logging.debug(f"Playing song {song.title} by {song.artist}.")
|
||||
|
||||
r = conn.stream(song.id)
|
||||
audio_data = io.BytesIO(r.content)
|
||||
|
||||
pygame.mixer.music.load(audio_data)
|
||||
pygame.mixer.music.play()
|
||||
|
||||
# Set callback loop for progress bar
|
||||
# self.progress_timer = self.set_interval(1 / 10, self.update_progress, pause=False)
|
||||
|
||||
@@ -242,6 +322,18 @@ class TextualSubpyPlayer(App):
|
||||
logging.debug(f'Queue\'d song "{song.title}" by {song.artist}.')
|
||||
self.song_queue.append(song)
|
||||
|
||||
def action_play_pause_song(self) -> None:
|
||||
self.play_pause_song()
|
||||
|
||||
def play_pause_song(self) -> None:
|
||||
if self.playing:
|
||||
self.place = pygame.mixer.music.get_pos()
|
||||
pygame.mixer.music.pause()
|
||||
self.playing = False
|
||||
else:
|
||||
pygame.mixer.music.play(start=self.place)
|
||||
self.playing = True
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = TextualSubpyPlayer()
|
||||
app.run()
|
||||
Reference in new issue
Block a user