Commit 5d094c147d5ee0203b5c8a439f896956406d1647 Parent: 8dbf615a323b1de2242c2a6405f3209c4d7bcf5a Author: mcol <mcol@posteo.net> Date: 2020-01-11 13:23:26 +0000 Committer: mcol <mcol@posteo.net> Committed: 2020-01-11 13:23:26 +0000 move package into subfolder within repo
xresources/xresources.py Deleted
@@ -1,54 +0,0 @@ -""" -Qtile helper to get X resources from the root window. -""" - - -import xcffib -import xcffib.xproto - - -def get(DISPLAY, defaults={}): - """ - Get the X resources in an X servers resource manager. - - Parameters - ========== - DISPLAY : str - DISPLAY name to query. - - defaults : dict (optional) - Default values to act as a fallback for missing values or in the event of a - failed connection. - - Returns - ======= - resources: dict - Dictionary containing all (available) X resources. Resources that are specified - in an Xresources/Xdefaults file as wildcards e.g. '*.color1' have the leading - '*.' stripped. - - """ - try: - conn = xcffib.connect(display=DISPLAY) - except xcffib.ConnectionException: - return defaults - - root = conn.get_setup().roots[0].root - atom = conn.core.InternAtom(False, 16, 'RESOURCE_MANAGER').reply().atom - - reply = conn.core.GetProperty( - False, root, atom, - xcffib.xproto.Atom.STRING, - 0, (2 ** 32) - 1 - ).reply() - conn.disconnect() - - resource_string = reply.value.buf().decode("utf-8") - resource_list = filter(None, resource_string.split('\n')) - resources = {} - - for resource in resource_list: - key, value = resource.split(':\t') - resources[key.strip('*.')] = value - - return resources
xresources/__init__.py Deleted
@@ -1 +0,0 @@
-from .xresources import get
qtools/xresources/xresources.py Added
@@ -0,0 +1,54 @@ +""" +Qtile helper to get X resources from the root window. +""" + + +import xcffib +import xcffib.xproto + + +def get(DISPLAY, defaults={}): + """ + Get the X resources in an X servers resource manager. + + Parameters + ========== + DISPLAY : str + DISPLAY name to query. + + defaults : dict (optional) + Default values to act as a fallback for missing values or in the event of a + failed connection. + + Returns + ======= + resources: dict + Dictionary containing all (available) X resources. Resources that are specified + in an Xresources/Xdefaults file as wildcards e.g. '*.color1' have the leading + '*.' stripped. + + """ + try: + conn = xcffib.connect(display=DISPLAY) + except xcffib.ConnectionException: + return defaults + + root = conn.get_setup().roots[0].root + atom = conn.core.InternAtom(False, 16, 'RESOURCE_MANAGER').reply().atom + + reply = conn.core.GetProperty( + False, root, atom, + xcffib.xproto.Atom.STRING, + 0, (2 ** 32) - 1 + ).reply() + conn.disconnect() + + resource_string = reply.value.buf().decode("utf-8") + resource_list = filter(None, resource_string.split('\n')) + resources = {} + + for resource in resource_list: + key, value = resource.split(':\t') + resources[key.strip('*.')] = value + + return resources
qtools/xresources/__init__.py Added
@@ -0,0 +1 @@
+from .xresources import get
qtools/mpc/mpc.py Added
@@ -0,0 +1,83 @@ +""" +Qtile plugin to control Music Player Daemon using musicpd or mpd2 library + +Example usage: + + import qtools.mpc + mpc = qtools.mpc.Client() + keys.extend([EzKey(k, v) for k, v in { + '<XF86AudioPlay>': mpc.lazy_toggle, + '<XF86AudioNext>': mpc.lazy_next, + '<XF86AudioPrev>': mpc.lazy_previous, + '<XF86AudioPlay>': mpc.lazy_stop, + }.items()]) + +""" + +from functools import wraps + +try: + from musicpd import ConnectionError, MPDClient +except ImportError: + from mpd import ConnectionError, MPDClient +from qtools import Notifier + + +def _client_func(func): + @wraps(func) + def _inner(self, qtile): + try: + self.client.connect() + except ConnectionError: + pass + self.show(func(self)) + self.client.disconnect() + return _inner + + +class Client(Notifier): + """ + The host and port are 127.0.0.1 and 6600 by default but can be set by passing these + when initiating the client. + + The notification timeout can be changed by setting Client.timeout to milliseconds + (int) or -1, which then uses the notification server's default timeout. + """ + defaults = [ + ('summary', 'Music', 'Notification summary.'), + ('host', '127.0.0.1', 'IP address of MPD server.'), + ('port', '6600', 'Port of MPD server.'), + ] + def __init__(self, **config): + Notifier.__init__(self, **config) + self.add_defaults(Client.defaults) + + self.client = MPDClient() + self.client.host = self.host + self.client.port = self.port + + @_client_func + def toggle(self): + if self.client.status()['state'] == 'play': + self.client.pause() + return 'Paused' + else: + self.client.play() + return 'Playing' + + @_client_func + def next(self): + self.client.next() + current = self.client.currentsong() + return f"{current['artist']} - {current['title']}" + + @_client_func + def previous(self): + self.client.previous() + current = self.client.currentsong() + return f"{current['artist']} - {current['title']}" + + @_client_func + def stop(self): + self.client.stop() + return 'Stopped'
qtools/mpc/__init__.py Added
@@ -0,0 +1 @@
+from .mpc import Client
qtools/backlight/backlight.py Added
@@ -0,0 +1,63 @@ +""" +Qtile plugin to control the screen backlight. + +Example usage: + + import qtools.backlight + backlight = qtools.backlight.Backlight() + keys.extend([EzKey(k, v) for k, v in { + '<XF86MonBrightnessUp>': backlight.lazy_inc_brightness, + '<XF86MonBrightnessDown>': backlight.lazy_dec_brightness, + }.items()]) + +""" + +import os + +from libqtile.log_utils import logger +from qtools import Notifier + + +class Backlight(Notifier): + + defaults = [ + ('summary', 'Backlight', 'Notification summary.'), + ('interval', 10, 'Percentage interval by which to change backlight'), + ( + 'path', + '/sys/class/backlight/nv_backlight/brightness', + 'Full path to backlight device.' + ), + ] + + def __init__(self, **config): + Notifier.__init__(self, **config) + self.add_defaults(Backlight.defaults) + + if not os.path.isfile(self.path): + logger.error('Path passed to Backlight plugin is invalid') + self.path = '/dev/null' + + @property + def brightness(self): + with open(self.path, 'r') as f: + return int(f.read()) + + @brightness.setter + def brightness(self, value): + if value > 100: + value = 100 + elif value < 0: + value = 0 + elif value % self.interval: + value = self.interval * round(value / self.interval) + + with open(self.path, 'w') as f: + f.write(str(value)) + self.show(value) + + def inc_brightness(self, qtile=None): + self.brightness += self.interval + + def dec_brightness(self, qtile=None): + self.brightness -= self.interval
qtools/backlight/__init__.py Added
@@ -0,0 +1 @@
+from .backlight import Backlight
qtools/amixer/amixer.py Added
@@ -0,0 +1,70 @@ +""" +Qtile plugin to control an ALSA device volume level. + +Example usage: + + import qtools.amixer + vol = qtools.amixer.Volume() + keys.extend([EzKey(k, v) for k, v in { + '<XF86AudioMute>': vol.lazy_mute, + '<XF86AudioRaiseVolume>': vol.lazy_increase, + '<XF86AudioLowerVolume>': vol.lazy_decrease, + }.items()]) + +""" + + +import subprocess + +from libqtile.log_utils import logger +from qtools import Notifier + + +class Volume(Notifier): + defaults = [ + ('summary', 'Volume', 'Notification summary.'), + ('mixer', 'Master', 'ALSA mixer to control.'), + ('interval', 5, 'Percentage interval to change volume by.'), + ] + def __init__(self, **config): + Notifier.__init__(self, **config) + self.add_defaults(Volume.defaults) + + def increase(self, qtile=None): + volume = self._run(f'{self.interval}%+') + self.show(self.interval * round(volume/self.interval)) + + def decrease(self, qtile=None): + volume = self._run(f'{self.interval}%-') + self.show(self.interval * round(volume/self.interval)) + + def toggle(self, qtile=None): + volume = self._run('toggle') + self.show(self.interval * round(volume/self.interval)) + + def mute(self, qtile=None): + self._run('mute') + self.show('Muted') + + def unmute(self, qtile=None): + volume = self._run('unmute') + self.show(volume) + + def _run(self, setting): + try: + output = subprocess.run( + ['amixer', 'set', self.mixer, setting], + stdout=subprocess.PIPE, + ) + stdout = output.stdout.splitlines() + except subprocess.CalledProcessError as err: + logger.error(err.output.decode()) + return + + if len(stdout) == 5: + volume = int(stdout[4].decode().split()[3][1:-2]) + elif len(stdout) == 7: + volume = int(stdout[5].decode().split()[4][1:-2]) + else: + logger.warning('Output from amixer needs decoding') + return volume
qtools/amixer/__init__.py Added
@@ -0,0 +1 @@
+from .amixer import Volume
qtools/__init__.py Added
@@ -0,0 +1,63 @@ +""" +Simple base classes that can be used for multiple plugins. +""" + + +import gi +gi.require_version('Notify', '0.7') +from gi.repository import Notify + +from libqtile.configurable import Configurable +from libqtile.command import lazy + + +class Notifier(Configurable): + """ + This is a base class for classes with methods that are to be executed upon key + presses and that generate pop-up notifications. + """ + _is_initted = False + + defaults = [ + ('summary', 'Notifier', 'Notification summary.'), + ('timeout', -1, 'Timeout for notifications.'), + ] + + def __init__(self, **config): + if not Notifier._is_initted: + Notifier._is_initted = True + Notify.init('Qtile') + + Configurable.__init__(self, **config) + self.add_defaults(Notifier.defaults) + self.notifier = Notify.Notification.new( + config.get('summary', 'Notifier'), '' + ) + self.timeout = config.get('timeout', -1) + + def __getattr__(self, name): + """ + Using this, we can get e.g. Mpc.lazy_toggle which is the equivalent of + lazy.function(Mpc.toggle), which is more convenient for setting keybindings. + """ + if name.startswith('lazy_'): + return lazy.function(getattr(self, name[5:])) + return Configurable.__getattr__(self, name) + + @property + def timeout(self): + return self._timeout + + @timeout.setter + def timeout(self, value): + self.notifier.set_timeout(value) + self._timeout = value + + def show(self, body): + if not isinstance(body, str): + body = str(body) + self.notifier.update(self.summary, body) + self.notifier.show() + + def hide(self): + self.notifier.hide()
mpc/mpc.py Deleted
@@ -1,83 +0,0 @@ -""" -Qtile plugin to control Music Player Daemon using musicpd or mpd2 library - -Example usage: - - import qtools.mpc - mpc = qtools.mpc.Client() - keys.extend([EzKey(k, v) for k, v in { - '<XF86AudioPlay>': mpc.lazy_toggle, - '<XF86AudioNext>': mpc.lazy_next, - '<XF86AudioPrev>': mpc.lazy_previous, - '<XF86AudioPlay>': mpc.lazy_stop, - }.items()]) - -""" - -from functools import wraps - -try: - from musicpd import ConnectionError, MPDClient -except ImportError: - from mpd import ConnectionError, MPDClient -from qtools import Notifier - - -def _client_func(func): - @wraps(func) - def _inner(self, qtile): - try: - self.client.connect() - except ConnectionError: - pass - self.show(func(self)) - self.client.disconnect() - return _inner - - -class Client(Notifier): - """ - The host and port are 127.0.0.1 and 6600 by default but can be set by passing these - when initiating the client. - - The notification timeout can be changed by setting Client.timeout to milliseconds - (int) or -1, which then uses the notification server's default timeout. - """ - defaults = [ - ('summary', 'Music', 'Notification summary.'), - ('host', '127.0.0.1', 'IP address of MPD server.'), - ('port', '6600', 'Port of MPD server.'), - ] - def __init__(self, **config): - Notifier.__init__(self, **config) - self.add_defaults(Client.defaults) - - self.client = MPDClient() - self.client.host = self.host - self.client.port = self.port - - @_client_func - def toggle(self): - if self.client.status()['state'] == 'play': - self.client.pause() - return 'Paused' - else: - self.client.play() - return 'Playing' - - @_client_func - def next(self): - self.client.next() - current = self.client.currentsong() - return f"{current['artist']} - {current['title']}" - - @_client_func - def previous(self): - self.client.previous() - current = self.client.currentsong() - return f"{current['artist']} - {current['title']}" - - @_client_func - def stop(self): - self.client.stop() - return 'Stopped'
mpc/__init__.py Deleted
@@ -1 +0,0 @@
-from .mpc import Client
backlight/backlight.py Deleted
@@ -1,63 +0,0 @@ -""" -Qtile plugin to control the screen backlight. - -Example usage: - - import qtools.backlight - backlight = qtools.backlight.Backlight() - keys.extend([EzKey(k, v) for k, v in { - '<XF86MonBrightnessUp>': backlight.lazy_inc_brightness, - '<XF86MonBrightnessDown>': backlight.lazy_dec_brightness, - }.items()]) - -""" - -import os - -from libqtile.log_utils import logger -from qtools import Notifier - - -class Backlight(Notifier): - - defaults = [ - ('summary', 'Backlight', 'Notification summary.'), - ('interval', 10, 'Percentage interval by which to change backlight'), - ( - 'path', - '/sys/class/backlight/nv_backlight/brightness', - 'Full path to backlight device.' - ), - ] - - def __init__(self, **config): - Notifier.__init__(self, **config) - self.add_defaults(Backlight.defaults) - - if not os.path.isfile(self.path): - logger.error('Path passed to Backlight plugin is invalid') - self.path = '/dev/null' - - @property - def brightness(self): - with open(self.path, 'r') as f: - return int(f.read()) - - @brightness.setter - def brightness(self, value): - if value > 100: - value = 100 - elif value < 0: - value = 0 - elif value % self.interval: - value = self.interval * round(value / self.interval) - - with open(self.path, 'w') as f: - f.write(str(value)) - self.show(value) - - def inc_brightness(self, qtile=None): - self.brightness += self.interval - - def dec_brightness(self, qtile=None): - self.brightness -= self.interval
backlight/__init__.py Deleted
@@ -1 +0,0 @@
-from .backlight import Backlight
amixer/amixer.py Deleted
@@ -1,70 +0,0 @@ -""" -Qtile plugin to control an ALSA device volume level. - -Example usage: - - import qtools.amixer - vol = qtools.amixer.Volume() - keys.extend([EzKey(k, v) for k, v in { - '<XF86AudioMute>': vol.lazy_mute, - '<XF86AudioRaiseVolume>': vol.lazy_increase, - '<XF86AudioLowerVolume>': vol.lazy_decrease, - }.items()]) - -""" - - -import subprocess - -from libqtile.log_utils import logger -from qtools import Notifier - - -class Volume(Notifier): - defaults = [ - ('summary', 'Volume', 'Notification summary.'), - ('mixer', 'Master', 'ALSA mixer to control.'), - ('interval', 5, 'Percentage interval to change volume by.'), - ] - def __init__(self, **config): - Notifier.__init__(self, **config) - self.add_defaults(Volume.defaults) - - def increase(self, qtile=None): - volume = self._run(f'{self.interval}%+') - self.show(self.interval * round(volume/self.interval)) - - def decrease(self, qtile=None): - volume = self._run(f'{self.interval}%-') - self.show(self.interval * round(volume/self.interval)) - - def toggle(self, qtile=None): - volume = self._run('toggle') - self.show(self.interval * round(volume/self.interval)) - - def mute(self, qtile=None): - self._run('mute') - self.show('Muted') - - def unmute(self, qtile=None): - volume = self._run('unmute') - self.show(volume) - - def _run(self, setting): - try: - output = subprocess.run( - ['amixer', 'set', self.mixer, setting], - stdout=subprocess.PIPE, - ) - stdout = output.stdout.splitlines() - except subprocess.CalledProcessError as err: - logger.error(err.output.decode()) - return - - if len(stdout) == 5: - volume = int(stdout[4].decode().split()[3][1:-2]) - elif len(stdout) == 7: - volume = int(stdout[5].decode().split()[4][1:-2]) - else: - logger.warning('Output from amixer needs decoding') - return volume
amixer/__init__.py Deleted
@@ -1 +0,0 @@
-from .amixer import Volume
__init__.py Deleted
@@ -1,63 +0,0 @@ -""" -Simple base classes that can be used for multiple plugins. -""" - - -import gi -gi.require_version('Notify', '0.7') -from gi.repository import Notify - -from libqtile.configurable import Configurable -from libqtile.command import lazy - - -class Notifier(Configurable): - """ - This is a base class for classes with methods that are to be executed upon key - presses and that generate pop-up notifications. - """ - _is_initted = False - - defaults = [ - ('summary', 'Notifier', 'Notification summary.'), - ('timeout', -1, 'Timeout for notifications.'), - ] - - def __init__(self, **config): - if not Notifier._is_initted: - Notifier._is_initted = True - Notify.init('Qtile') - - Configurable.__init__(self, **config) - self.add_defaults(Notifier.defaults) - self.notifier = Notify.Notification.new( - config.get('summary', 'Notifier'), '' - ) - self.timeout = config.get('timeout', -1) - - def __getattr__(self, name): - """ - Using this, we can get e.g. Mpc.lazy_toggle which is the equivalent of - lazy.function(Mpc.toggle), which is more convenient for setting keybindings. - """ - if name.startswith('lazy_'): - return lazy.function(getattr(self, name[5:])) - return Configurable.__getattr__(self, name) - - @property - def timeout(self): - return self._timeout - - @timeout.setter - def timeout(self, value): - self.notifier.set_timeout(value) - self._timeout = value - - def show(self, body): - if not isinstance(body, str): - body = str(body) - self.notifier.update(self.summary, body) - self.notifier.show() - - def hide(self): - self.notifier.hide()