From 60fc4eb917c7d0af64401e2a695d0ac1ec0d8f24 Mon Sep 17 00:00:00 2001 From: Andrew Dunai Date: Thu, 4 Jan 2018 11:35:57 +0200 Subject: [PATCH] Hotkeys --- clay/app.py | 1 - clay/hotkeys.py | 71 ++++++++++++++++++++++++++++++++++++++++--- clay/notifications.py | 16 +++++++--- clay/player.py | 5 +++ clay/settings.py | 2 +- 5 files changed, 83 insertions(+), 12 deletions(-) diff --git a/clay/app.py b/clay/app.py index 038eef9..bcd9aac 100755 --- a/clay/app.py +++ b/clay/app.py @@ -19,7 +19,6 @@ from clay.myplaylists import MyPlaylists from clay.playerqueue import Queue from clay.settings import Settings from clay.notifications import NotificationArea -# from clay import hotkeys PALETTE = [ ('logo', '', '', '', '#F54', ''), diff --git a/clay/hotkeys.py b/clay/hotkeys.py index 277730d..2c14c67 100644 --- a/clay/hotkeys.py +++ b/clay/hotkeys.py @@ -1,7 +1,68 @@ -# import gi -# gi.require_version('Keybinder', '3.0') -# from gi.repository import Keybinder +import sys +import threading -# Keybinder.init() -# # Keybinder.bind() +try: + import gi + gi.require_version('Keybinder', '3.0') # noqa + gi.require_version('Gtk', '3.0') # noqa + from gi.repository import Keybinder, Gtk +except Exception as e: + sys.stderr.write('Could not import Keybinder and Gtk. Error was: "{}"\n'.format(e)) + sys.stderr.write('Global shortcuts will not work.\n') + IS_INIT = False + ERROR = str(e) +else: + IS_INIT = True + +from clay.settings import Settings +from clay.eventhook import EventHook +from clay.notifications import NotificationArea + + +class HotkeyManager(object): + DEFAULT_HOTKEYS = { + 'play_pause': 'XF86AudioPlay', + 'next': 'XF86AudioNext', + 'prev': 'XF86AudioPrev' + } + + def __init__(self): + self.hotkeys = {} + self.config = None + + self.play_pause = EventHook() + self.next = EventHook() + self.prev = EventHook() + + if IS_INIT: + Keybinder.init() + self.initialize() + + threading.Thread(target=Gtk.main).start() + else: + NotificationArea.notify( + 'Could not import Keybinder and Gtk. Error was: "{}"\n' + 'Global shortcuts will not work.'.format(ERROR) + ) + + def load_keys(self): + config = Settings.get_config() + hotkeys = config.get('hotkeys', {}) + for op, default_key in HotkeyManager.DEFAULT_HOTKEYS.items(): + if op not in hotkeys or not hotkeys[op]: + hotkeys[op] = default_key + return hotkeys + + def initialize(self): + for op, key in self.hotkeys.items(): + Keybinder.unbind(key) + self.hotkeys = self.load_keys() + for op, key in self.hotkeys.items(): + Keybinder.bind(key, self.fire_hook, op) + + def fire_hook(self, key, op): + getattr(self, op).fire() + + +hotkey_manager = HotkeyManager() diff --git a/clay/notifications.py b/clay/notifications.py index 564bb0e..1d230e8 100644 --- a/clay/notifications.py +++ b/clay/notifications.py @@ -7,7 +7,8 @@ class Notification(urwid.Columns): def __init__(self, area, id, message): self.area = area self.id = id - self.text = urwid.Text(Notification.TEMPLATE.format(message)) + self.text = urwid.Text('') + self.update(message) super(Notification, self).__init__([ urwid.AttrWrap( urwid.Columns([ @@ -19,6 +20,10 @@ class Notification(urwid.Columns): ]) def update(self, message): + message = message.split('\n') + message = '\n'.join([ + message[0] + ] + [' {}'.format(line) for line in message[1:]]) self.text.set_text(Notification.TEMPLATE.format(message)) def close(self): @@ -49,15 +54,15 @@ class NotificationArea(urwid.Pile): @classmethod def notify(cls, message): - return cls.instance._notify(message) + return cls.get()._notify(message) @classmethod def close_all(cls): - cls.instance._close_all() + cls.get()._close_all() @classmethod def close_newest(cls): - cls.instance._close_newest() + cls.get()._close_newest() def _notify(self, message): self.last_id += 1 @@ -68,7 +73,8 @@ class NotificationArea(urwid.Pile): ('weight', 1) ) ) - self.__class__.app.redraw() + if self.__class__.app is not None: + self.__class__.app.redraw() return notification def _close_all(self): diff --git a/clay/player.py b/clay/player.py index c4d8a0c..b38ba04 100644 --- a/clay/player.py +++ b/clay/player.py @@ -5,6 +5,7 @@ import json from clay import vlc from clay.eventhook import EventHook from clay.notifications import NotificationArea +from clay.hotkeys import hotkey_manager class Queue(object): @@ -90,6 +91,10 @@ class Player(object): self._media_position_changed ) + hotkey_manager.play_pause += self.play_pause + hotkey_manager.next += self.next + hotkey_manager.prev += lambda: self.seek_absolute(0) + self.queue = Queue() def broadcast_state(self): diff --git a/clay/settings.py b/clay/settings.py index 12df6ba..25e2de3 100644 --- a/clay/settings.py +++ b/clay/settings.py @@ -59,7 +59,7 @@ class Settings(urwid.Columns): if e.errno != errno.EEXIST: raise - path = os.path.join(filedir, 'config.json') + path = os.path.join(filedir, 'config.yaml') if not os.path.exists(path): with open(path, 'w') as f: f.write('{}')