143 lines
3.8 KiB
Python
143 lines
3.8 KiB
Python
import logging
|
|
import os
|
|
|
|
from enum import Enum
|
|
|
|
LOG_FILE = 'textual.log'
|
|
LOGGING_LEVEL = logging.DEBUG
|
|
LOG_FORMAT = '[%(asctime)s] %(levelname)s in %(module)s: %(message)s'
|
|
|
|
# Clear Log File
|
|
os.remove(LOG_FILE)
|
|
|
|
logging.basicConfig(filename=LOG_FILE, level=LOGGING_LEVEL, format=LOG_FORMAT)
|
|
|
|
import SubSonic
|
|
|
|
|
|
from textual import on, events
|
|
from textual.app import App, ComposeResult
|
|
from textual.widgets import Footer, Header, OptionList, DataTable, Tabs, Tab, TabbedContent, TabPane
|
|
from textual.screen import Screen
|
|
from textual.widgets.option_list import Option
|
|
|
|
u = 'pseudo'
|
|
p = 'telegram9dock-MICHEL'
|
|
|
|
conn = SubSonic.SubpyConn(u, p, "https://music.0x01fe.net")
|
|
|
|
class AlbumSongs(Screen):
|
|
BINDINGS = [
|
|
('escape', 'die()', "Back")
|
|
]
|
|
|
|
def __init__(self, album_id: str):
|
|
self.album_id = album_id
|
|
super().__init__()
|
|
|
|
def compose(self) -> ComposeResult:
|
|
yield DataTable(id="albumSongs")
|
|
yield Footer()
|
|
|
|
def on_mount(self) -> None:
|
|
songs = conn.getAlbumSongs(self.album_id)
|
|
songsTable: DataTable = self.query_one(DataTable)
|
|
|
|
songsTable.cursor_type = 'row'
|
|
songsTable.add_columns("#", "Title", "Artist", "Duration", "Bitrate")
|
|
|
|
for song in songs:
|
|
songsTable.add_row(song.trackNumber, song.title, song.artist, song.duration, song.bitRate, key=song.id)
|
|
|
|
|
|
# Pops and uninstalls self
|
|
def action_die(self) -> None:
|
|
app.pop_screen()
|
|
app.uninstall_screen("albumSongs")
|
|
|
|
class ArtistAlbums(Screen):
|
|
BINDINGS = [
|
|
('escape', 'die()', "Back")
|
|
]
|
|
|
|
def __init__(self, artist_id: str):
|
|
self.artist_id = artist_id
|
|
super().__init__()
|
|
|
|
def compose(self) -> ComposeResult:
|
|
yield DataTable(id="Albums")
|
|
yield Footer()
|
|
|
|
def on_mount(self) -> None:
|
|
albums = conn.getArtistAlbums(self.artist_id)
|
|
albumTable: DataTable = self.query_one(DataTable)
|
|
|
|
albumTable.cursor_type = 'row'
|
|
|
|
albumTable.add_columns("Title", "Songs")
|
|
|
|
for album in albums:
|
|
albumTable.add_row(album.title, album.songCount, key=album.id)
|
|
|
|
@on(DataTable.RowSelected)
|
|
async def album_selected(self, event: DataTable.RowSelected) -> None:
|
|
app.install_screen(AlbumSongs(event.row_key.value), "albumSongs")
|
|
app.push_screen("albumSongs")
|
|
|
|
# Pops and uninstalls self
|
|
def action_die(self) -> None:
|
|
app.pop_screen()
|
|
app.uninstall_screen("artistAlbums")
|
|
|
|
class Artists(Screen):
|
|
BINDINGS = [
|
|
('escape', 'app.pop_screen', "Back")
|
|
]
|
|
|
|
def compose(self) -> ComposeResult:
|
|
yield OptionList(id="Artists")
|
|
yield Footer()
|
|
|
|
def on_mount(self) -> None:
|
|
artists = conn.getArtists()
|
|
artistList = self.query_one(OptionList)
|
|
|
|
for artist in artists:
|
|
artistList.add_option(Option(artist.name, artist.id))
|
|
|
|
@on(OptionList.OptionSelected)
|
|
def artist_selected(self, event: OptionList.OptionSelected) -> None:
|
|
app.install_screen(ArtistAlbums(event.option_id), 'artistAlbums')
|
|
app.push_screen('artistAlbums')
|
|
|
|
class Albums(Screen):
|
|
BINDINGS = [
|
|
('escape', 'app.pop_screen', "Back")
|
|
]
|
|
|
|
def compose(self) -> ComposeResult:
|
|
yield DataTable()
|
|
yield Footer()
|
|
|
|
def on_mount(self) -> None:
|
|
albums = conn.getAlbums()
|
|
|
|
class TextualSubpyPlayer(App):
|
|
BINDINGS = [
|
|
("f1", "push_screen('artists')", "Artists"),
|
|
("f2", "push_screen('albums')", "Albums")
|
|
]
|
|
|
|
def compose(self) -> ComposeResult:
|
|
yield Footer()
|
|
|
|
def on_mount(self) -> None:
|
|
self.install_screen(Artists(), name="artists")
|
|
|
|
def on_key(self, event: events.Key) -> None:
|
|
logging.debug(f'Key Pressed {event.name}')
|
|
|
|
if __name__ == '__main__':
|
|
app = TextualSubpyPlayer()
|
|
app.run()
|