diff --git a/README.md b/README.md index c01428f..839b1d8 100644 --- a/README.md +++ b/README.md @@ -194,6 +194,12 @@ You *should* get the sound working. Also docker will reuse the Clay config file - `` or ` /` or _ - close most recent notification or popup - ` x` - exit app +## X keybinds +**NOTE:** you need to pass the `--with-x-keybinds` flag for these to work +- `` - play/pause the song +- `` - play the next song +- `` - play previous song + # Troubleshooting At some point, the app may fail. Possible reasons are app bugs, diff --git a/clay/app.py b/clay/app.py index 5b12864..e273833 100755 --- a/clay/app.py +++ b/clay/app.py @@ -9,8 +9,12 @@ Main app entrypoint. import sys sys.path.insert(0, '.') # noqa + +import argparse +import os import urwid +from clay import meta from clay.player import Player from clay.playbar import PlayBar from clay.pages.debug import DebugPage @@ -23,6 +27,7 @@ from clay.settings import Settings from clay.notifications import NotificationArea from clay.gp import GP + BG = '#222' PALETTE = [ @@ -133,8 +138,8 @@ class AppWidget(urwid.Frame): for page in self.pages ] - self.current_page = None + self.current_page = None self.loop = None NotificationArea.set_app(self) @@ -373,16 +378,50 @@ class AppWidget(urwid.Frame): action() -def main(): +class MultilineVersionAction(argparse.Action): """ - Application entrypoint. + An argparser action for multiple lines so we can display the copyright notice + Based on: https://stackoverflow.com/a/41147122 """ + version = "0.6.2" + author = "Andrew Dunai" + + def __init__(self, option_strings, dest, nargs=None, **kwargs): + if nargs is not None: + raise ValueError("nargs not allowed") + + self.prog = os.path.basename(sys.argv[0]) + super(MultilineVersionAction, self).__init__(option_strings, dest, nargs=0, **kwargs) + + def __call__(self, parser, namespace, values, option_string=None): + parser.exit(message=meta.COPYRIGHT_MESSAGE) + + +if __name__ == '__main__': + # pylint: disable-all + parser = argparse.ArgumentParser( + prog=meta.APP_NAME, + description=meta.DESCRIPTION, + epilog="This project is neither affiliated nor endorsed by Google.") + + parser.add_argument("-v", "--version", action=MultilineVersionAction) + + parser.add_argument( + "--with-x-keybinds", + help="define global X keybinds (requires Keybinder and PyGObject)", + action='store_true') + + args = parser.parse_args() + + if args.version: + exit(0) + + if args.with_x_keybinds: + Player.get().enable_xorg_bindings() + + # Run the actual program app_widget = AppWidget() loop = urwid.MainLoop(app_widget, PALETTE) app_widget.set_loop(loop) loop.screen.set_terminal_properties(256) loop.run() - - -if __name__ == '__main__': - main() diff --git a/clay/meta.py b/clay/meta.py index 17eb2db..c250ce0 100644 --- a/clay/meta.py +++ b/clay/meta.py @@ -1,17 +1,27 @@ """ Predefined values. """ +APP_NAME = 'Clay Player' +VERSION = '0.6.2' +AUTHOR = "Andrew Dunai" +DESCRIPTION = "Awesome standalone command line player for Google Play Music" + try: from codename import codename except ImportError: - codename = None - -APP_NAME = 'Clay Player' -VERSION = '0.6.2' -if codename is not None: - VERSION_WITH_CODENAME = VERSION + '-' + codename(separator='-', id=VERSION) -else: VERSION_WITH_CODENAME = VERSION +else: + VERSION_WITH_CODENAME = VERSION + ' (' + codename(separator=' ', id=VERSION) + ')' + +COPYRIGHT_MESSAGE = """{app_name} {version} + +Copyright 2017 - {year} (C) {author} and {app_name} contributors. +License GPLv3+: GNU GPL version 3 or later +This is free software; you are free to change it and redistribute it. +There is NO WARRANTY, to the extent permitted by law +""".format(app_name=APP_NAME, year=2018, + version=VERSION_WITH_CODENAME, author=AUTHOR) + USER_AGENT = ' '.join([ 'Mozilla/5.0 (X11; Linux x86_64)' 'AppleWebKit/537.36 (KHTML, like Gecko)' diff --git a/clay/player.py b/clay/player.py index 4688e33..36a9b4d 100644 --- a/clay/player.py +++ b/clay/player.py @@ -161,16 +161,6 @@ class Player(object): self.media_player.set_equalizer(self.equalizer) - # Check whether xorg is running - if os.environ.get("DISPLAY") is not None: - from clay.hotkeys import HotkeyManager - hotkey_manager = HotkeyManager.get() - hotkey_manager.play_pause += self.play_pause - hotkey_manager.next += self.next - hotkey_manager.prev += lambda: self.seek_absolute(0) - else: - self.logger.debug("X11 isn't running so we can't load the global keybinds") - self._create_station_notification = None self._is_loading = False self.queue = Queue() @@ -185,6 +175,18 @@ class Player(object): return cls.instance + def enable_xorg_bindings(self): + """Enable the global X bindings using keybinder""" + if os.environ.get("DISPLAY") is None: + self.logger.debug("X11 isn't running so we can't load the global keybinds") + return + + from clay.hotkeys import HotkeyManager + hotkey_manager = HotkeyManager.get() + hotkey_manager.play_pause += self.play_pause + hotkey_manager.next += self.next + hotkey_manager.prev += lambda: self.seek_absolute(0) + def broadcast_state(self): """ Write current playback state into a ``/tmp/clay.json`` file.