subclient

Subsonic ncurses client
git clone https://git.e1e0.net/subclient.git
Log | Files | Refs | README

commit f1ead763fba163407c16d3ee0e2a2a8cd8081fc4
parent e567ef4b528738568334d3db6c6166431c38f768
Author: Paco Esteban <paco@e1e0.net>
Date:   Thu, 10 Jun 2021 12:40:14 +0200

basic interface, no play

Diffstat:
Mrequirements.txt | 1+
Msetup.py | 5++++-
Msubclient/subclient.py | 78+++++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Asubclient/subsonic.py | 56++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asubclient/tests/__init__.py | 0
5 files changed, 110 insertions(+), 30 deletions(-)

diff --git a/requirements.txt b/requirements.txt @@ -1 +1,2 @@ py-sonic==0.7.9 +py-cui==0.1.3 diff --git a/setup.py b/setup.py @@ -5,6 +5,9 @@ here = pathlib.Path(__file__).parent.resolve() long_description = (here / 'README.md').read_text(encoding='utf-8') +with open('requirements.txt', 'r') as req_fp: + required_packages = req_fp.readlines() + setup( name='subclient', version='0.1.0', @@ -27,7 +30,7 @@ setup( keywords='subsonic, client, music', packages=find_packages(where='.'), python_requires='>=3.6, <4', - install_requires=['py-sonic'], + install_requires=required_packages, entry_points={ 'console_scripts': [ 'subclient=subclient.subclient:main', diff --git a/subclient/subclient.py b/subclient/subclient.py @@ -1,43 +1,63 @@ #!/usr/bin/env python3 import configparser -import libsonic -import mpv +from subclient.subsonic import Subsonic +import py_cui -from helpers import format_duration +__version__ = 'v0.0.1' -player = mpv.MPV(input_default_bindings=True, input_vo_keyboard=True, - vo='gpu', ytdl=True) -stream = None +class SubClient: -@player.python_stream('subclient') -def stream_reader(): - while True: - yield stream.read(1024*1024) + def __init__(self, master: py_cui.PyCUI): + + self.config = configparser.ConfigParser() + self.config.read('config.ini') + self.subsonic = Subsonic(self.config['subclient']) + self.master = master + # The scrolled list cells that will contain our tasks in each of the + # three categories + self.artist_scroll_cell = self.master.add_scroll_menu( + 'Artists', 0, 0, row_span=1, column_span=1) + self.album_scroll_cell = self.master.add_scroll_menu( + 'Albums', 0, 1, row_span=1, column_span=1) + self.song_scroll_cell = self.master.add_scroll_menu( + 'Songs', 0, 2, row_span=1, column_span=1) + + self.artist_scroll_cell.add_key_command(py_cui.keys.KEY_ENTER, + self.update_albums) + self.album_scroll_cell.add_key_command(py_cui.keys.KEY_ENTER, + self.update_songs) + # self.song_scroll_cell.add_key_command(py_cui.keys.KEY_ENTER, + # self.play_song) + + self.update_artists() + + def update_artists(self): + artists = self.subsonic.get_artists() + self.artist_scroll_cell.add_item_list(artists) + + def update_albums(self): + self.album_scroll_cell.clear() + artist = self.artist_scroll_cell.get() + albums = self.subsonic.get_albums_from_artist(artist) + self.album_scroll_cell.add_item_list(albums) + + def update_songs(self): + self.song_scroll_cell.clear() + album = self.album_scroll_cell.get() + songs = self.subsonic.get_songs_from_album(album) + self.song_scroll_cell.add_item_list(songs) def main(): - config = configparser.ConfigParser() - config.read('config.ini') - - url = config['subclient']['url'] - user = config['subclient']['username'] - pwd = config['subclient']['password'] - random_list_size = config['subclient']['randomListSize'] - - subsonic = libsonic.Connection(url, user, pwd, port=443) - - # Let's get X completely random songs - songs = subsonic.getRandomSongs(size=random_list_size) - for song in songs['randomSongs']['song']: - print(f"Playing: {song['title']} by {song['artist']}" - f"({format_duration(song['duration'])})") - global stream - stream = subsonic.stream(song['id'], tformat='raw') - player.play('python://subclient') - player.wait_for_playback() + root = py_cui.PyCUI(1, 3) + # enable unicode box chars + root.toggle_unicode_borders() + root.set_title('SubsonicClient') + wrapper = SubClient(root) + root.start() if __name__ == "__main__": diff --git a/subclient/subsonic.py b/subclient/subsonic.py @@ -0,0 +1,56 @@ +import libsonic + + +class Artist: + def __init__(self, id: str, name: str, albumCount: int, **kwargs): + self.id = id + self.name = name + self.album_count = albumCount + + def __str__(self): + return f'{self.name} ({self.album_count})' + + +class Album: + def __init__(self, id: str, title: str, year: int, **kwargs): + self.id = id + self.title = title + self.year = year + + def __str__(self): + return f'{self.title} ({self.year})' + + +class Song: + def __init__(self, id: str, title: str, track: int, duration: int, + **kwargs): + self.id = id + self.title = title + self.track = track + self.duration = duration + + def __str__(self): + return f'{self.title}' + + +class Subsonic: + + def __init__(self, config): + self.s = libsonic.Connection(config['url'], config['username'], + config['password'], port=443) + + def get_artists(self): + artists = [] + artists_idx = self.s.getIndexes()['indexes']['index'] + for i in artists_idx: + for a in i['artist']: + artists.append(Artist(**a)) + return artists + + def get_albums_from_artist(self, artist): + albums = self.s.getArtist(artist.id)['artist']['album'] + return [Album(**a) for a in albums] + + def get_songs_from_album(self, album): + songs = self.s.getAlbum(album.id)['album']['song'] + return [Song(**s) for s in songs] diff --git a/subclient/tests/__init__.py b/subclient/tests/__init__.py