Sfoglia il codice sorgente

Initial UI implementation

Caleb Fangmeier 7 anni fa
commit
1b16901b9e
2 ha cambiato i file con 194 aggiunte e 0 eliminazioni
  1. 192 0
      app/ui.py
  2. 2 0
      requirements.txt

+ 192 - 0
app/ui.py

@@ -0,0 +1,192 @@
+import urwid
+
+songs = ['one', 'another on bites the dust', 'enter sandman', 'piano man', 'dance of death']
+artists = ['metallica', 'iron maiden', 'judas priest', 'haken']
+albums = ['some kind of bird egg', 'electric boogaloo', 'another time', '13']
+
+log = []
+
+
+class Song:
+    def __init__(self, title, artist, album):
+        self.title = title
+        self.album = album
+        self.artist = artist
+
+    def __repr__(self):
+        return f'<Song title:{self.title}, album:{self.album}, artist:{self.artist}>'
+
+
+class Album:
+    def __init__(self, title, artist):
+        self.title = title
+        self.artist = artist
+
+    def __repr__(self):
+        return f'<Album title:{self.title}, artist:{self.artist}>'
+
+
+class Artist:
+    def __init__(self, name):
+        self.name = name
+
+    def __repr__(self):
+        return f'<Artist name:{self.name}>'
+
+
+def build_search_collection(N):
+    from random import choice
+    types = (Song, Artist, Album)
+    collection = []
+    for _ in range(N):
+        type_ = choice(types)
+        if type_ == Song:
+            collection.append(Song(choice(songs), choice(artists), choice(albums)))
+        elif type_ == Artist:
+            collection.append(Artist(choice(artists)))
+        else:
+            collection.append(Album(choice(albums), choice(artists)))
+    return (list(filter(lambda o: type(o) == Song, collection)),
+            list(filter(lambda o: type(o) == Album, collection)),
+            list(filter(lambda o: type(o) == Artist, collection)))
+
+
+class UI(urwid.Pile):
+
+    palette = [
+        ('header', 'white,underline', 'black'),
+        ('header_bg', 'white', 'black'),
+        ('line', 'white', ''),
+        ('search normal', 'white', ''),
+        ('search select', 'white', 'dark red'),
+
+        ('region_bg normal', '', ''),
+        ('region_bg select', '', 'black'),
+    ]
+
+    def click(self, *args, **kwargs):
+        print(args, kwargs)
+
+    def __init__(self):
+        self.search_results = urwid.SimpleFocusListWalker([])
+        search_results_box = urwid.ListBox(self.search_results)
+        search_results_box = urwid.LineBox(search_results_box, title='Search Results')
+        search_results_box = urwid.AttrMap(search_results_box, 'region_bg normal', 'region_bg select')
+
+        self.now_playing = urwid.Text('Now Playing')
+
+        # urwid.connect_signal(search_results_box.base_widget, 'click', self.click)
+
+        self.queue = urwid.SimpleFocusListWalker([])
+        queue_box = urwid.ListBox(self.queue)
+        queue_box = urwid.LineBox(queue_box, title='Queue')
+        queue_box = urwid.AttrMap(queue_box, 'region_bg normal', 'region_bg select')
+
+        self.command_input = urwid.Edit('> ', multiline=False, allow_tab=False)
+
+        urwid.Pile.__init__(self, [('weight', 12, search_results_box),
+                                   ('pack', self.now_playing),
+                                   ('weight', 7, queue_box),
+                                   ('pack', self.command_input)
+                                   ])
+
+    def header(self, txts):
+        header = urwid.Columns([('weight', 1, urwid.Text(('header', txt)))
+                                for txt in txts])
+        return urwid.AttrMap(header, 'header_bg')
+
+    def line(self, txts):
+        first, *rest = txts
+        items = [urwid.SelectableIcon(first, 0)]
+        for line in rest:
+            items.append(urwid.Text(line))
+        line = urwid.Columns(items)
+        line = urwid.AttrMap(line, 'search normal', 'search select')
+        return line
+
+    def selected_search_obj(self):
+        focus_id = self.search_results.get_focus()[1]
+        songs, albums, artists = self.search_list
+
+        focus_id -= 1
+        if focus_id < len(songs):
+            return songs[focus_id]
+        focus_id -= (1 + len(songs))
+        if focus_id < len(albums):
+            return albums[focus_id]
+        focus_id -= (1 + len(albums))
+        return artists[focus_id]
+
+    def enqueue(self, obj):
+        pass
+
+    def expand(self, obj):
+        pass
+
+    def radio(self, obj):
+        pass
+
+    def keypress(self, size, key):
+        if key in ('q', 'e', 'r'):
+            focus_obj = self.selected_search_obj()
+            self.now_playing.set_text(repr(focus_obj))
+            if key == 'q' and type(focus_obj) in (Song, Album):
+                self.enqueue(focus_obj)
+            elif key == 'e':
+                self.expand(focus_obj)
+            else:
+                self.radio(focus_obj)
+
+        else:
+            return self.focus.keypress(size, key)
+
+    def display_search_results(self, search_list=None):
+        if search_list is None:
+            self.search_list = build_search_collection(40)
+        songs, albums, artists = self.search_list
+
+        self.search_results.clear()
+        if songs:
+            self.search_results.append(self.header(['Title', 'Album', 'Artist']))
+        for song in songs:
+            self.search_results.append(self.line([song.title, song.album, song.artist]))
+
+        if albums:
+            self.search_results.append(self.header(['Album', 'Artist']))
+        for album in albums:
+            self.search_results.append(self.line([album.title, album.artist]))
+
+        if artists:
+            self.search_results.append(self.header(['Artist']))
+        for artist in artists:
+            self.search_results.append(self.line([artist.name]))
+
+
+ui = UI()
+
+
+def show_or_exit(key):
+    if key == 'esc':
+        raise urwid.ExitMainLoop()
+    elif key == 'enter':
+        ui.display_search_results()
+    else:
+        # ui.now_playing.set_text(repr(key))
+        # try:
+        #     ui.now_playing.set_text(repr(ui.search_results.get_focus()[0].base_widget))
+        # except AttributeError:
+        ui.now_playing.set_text(repr(ui.search_results.get_focus()))
+        # current = ui.search_results.get_focus()[1]
+        # try:
+        #     ui.search_results.set_focus(current+1)
+        # except IndexError:
+        #     pass
+
+
+loop = urwid.MainLoop(ui, ui.palette, unhandled_input=show_or_exit)
+loop.screen.set_terminal_properties(colors=256)
+try:
+    loop.run()
+except Exception as e:
+    print(log)
+    raise e

+ 2 - 0
requirements.txt

@@ -0,0 +1,2 @@
+gmusicapi==10.1.2
+urwid==1.3.1