From 683ff9f917c26feadf4ab05708609ea6db96d6e4 Mon Sep 17 00:00:00 2001 From: Ryan Kes Date: Sun, 8 Mar 2020 15:48:20 +0100 Subject: [PATCH] put polybar-scripts in its proper place --- install | 10 +- .../polybar}/bin/dockerstatus | 0 .../{.local => .config/polybar}/bin/mailcount | 0 .../polybar/bin/player-mpris-tail/README.md | 164 ------ .../player-mpris-tail/player-mpris-tail.py | 532 ------------------ .../bin/player-mpris-tail/screenshots/1.png | Bin 9199 -> 0 bytes .../bin/player-mpris-tail/screenshots/2.png | Bin 6192 -> 0 bytes .../bin/updates-arch-combined/README.md | 24 - .../updates-arch-combined/screenshots/1.png | Bin 3039 -> 0 bytes .../updates-arch-combined.sh | 16 - polybar/.config/polybar/config | 21 +- 11 files changed, 20 insertions(+), 747 deletions(-) rename polybar/{.local => .config/polybar}/bin/dockerstatus (100%) rename polybar/{.local => .config/polybar}/bin/mailcount (100%) delete mode 100644 polybar/.config/polybar/bin/player-mpris-tail/README.md delete mode 100755 polybar/.config/polybar/bin/player-mpris-tail/player-mpris-tail.py delete mode 100644 polybar/.config/polybar/bin/player-mpris-tail/screenshots/1.png delete mode 100644 polybar/.config/polybar/bin/player-mpris-tail/screenshots/2.png delete mode 100644 polybar/.config/polybar/bin/updates-arch-combined/README.md delete mode 100644 polybar/.config/polybar/bin/updates-arch-combined/screenshots/1.png delete mode 100755 polybar/.config/polybar/bin/updates-arch-combined/updates-arch-combined.sh diff --git a/install b/install index 9f1e5d1..cf35b43 100755 --- a/install +++ b/install @@ -61,8 +61,7 @@ if [ ! -d ~/.config/nvim/plugged ] https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim end -# Install Neovim plugins -nvim +PlugInstall +qall +# Install Neovim plugins nvim +PlugInstall +qall # Install vifm dependencies curl https://raw.githubusercontent.com/cirala/vifmimg/master/vifmimg --output vifm/.local/bin/vifmimg @@ -76,6 +75,13 @@ if [ ! -d ~/.local/share/broot ] broot --install end +# Polybar scripts if not installed already +if [ ! -d ~/.local/share/polybar-scripts ] + git clone https://github.com/polybar/polybar-scripts ~/.local/share/polybar-scripts +else + git --work-tree=$HOME/.local/share/polybar-scripts pull +end + # Update fish completions (auto generated from man pages) fish_update_completions diff --git a/polybar/.local/bin/dockerstatus b/polybar/.config/polybar/bin/dockerstatus similarity index 100% rename from polybar/.local/bin/dockerstatus rename to polybar/.config/polybar/bin/dockerstatus diff --git a/polybar/.local/bin/mailcount b/polybar/.config/polybar/bin/mailcount similarity index 100% rename from polybar/.local/bin/mailcount rename to polybar/.config/polybar/bin/mailcount diff --git a/polybar/.config/polybar/bin/player-mpris-tail/README.md b/polybar/.config/polybar/bin/player-mpris-tail/README.md deleted file mode 100644 index dc1fe25..0000000 --- a/polybar/.config/polybar/bin/player-mpris-tail/README.md +++ /dev/null @@ -1,164 +0,0 @@ -# Script: player-mpris-tail - -This script displays the current track and the play-pause status without polling. Information is obtained by listening to MPRIS events, so it is updated instantaneously on change. - -![player-mpris-tail](screenshots/1.png) ![player-mpris-tail](screenshots/2.png) - - -## Dependencies - -* `python-dbus` -* `python-gobject` -* `python-gi` - - -## Configuration - -The format of the output can be defined by passing an `-f` or `--format` argument. This argument supports metadata replacement using `{tag}` (e.g. `{title}`) as well as more advanced formatting, described below. - -Players can be blacklisted by passing a `-b` or `--blacklist` argument. As an example, VLC can be blacklisted by passing `-b vlc`. To get a list of the current running players (and their status), run the script as `player-mpris-tail.py list`. - - -### Commands - -The current player can be controlled by passing one of the following commands: - -Command | Description ----|--- -play | Play the current track -pause | Pause the currently playing track -play-pause | Play the current track or unpause it if currently paused -stop | Stop playback -previous | Move to the previous track -next | Move to the next track -raise | Tell the current player to focus its window - -General information about the current state can be printed using the following commands: - -Command | Description ----|--- -status | Print the normal output and exit immediately -current | Print the currently detected player and its status -list | List the detected players and their status -metadata | Print the metadata object for the current track - - -### Arguments - -The following arguments are supported: - -Argument | Description | Default ----|---|--- --b, --blacklist | Blacklist / Ignore the given player --f, --format | Use the given `format` string | `{icon} {artist} - {title}` ---truncate-text | Use the given string as the end of truncated text | `…` ---icon-playing | Use the given text as the playing icon | `⏵` ---icon-paused | Use the given text as the paused icon | `⏸` ---icon-stopped | Use the given text as the stopped icon | `⏹` ---icon-none | Use the given text as the icon for when no player is active | `` - - -### Formatting - -Tags can be printed by surrounding them with `{` and `}`. Polybar formatting can also be given and will be passed through, including substituted tags and formatters. - - -### Tags - -The supported tags are: - -Tag | Description ----|--- -artist | The artist of the current track -album | The album of the current track -title | The title of the current track -track | The track number of the current track -length | The length of the current track -genre | The genre of the current track -disc | The disc number of the current track -date | The date of the current track -year | The year of the current track -cover | The URL of the cover of the current track -icon | The icon for the current status (playing / paused / stopped / none) -icon-reversed | The pause icon when playing, else the play icon - - -### String formatters - -Parts of the `format` string can be manipulated by surrounding them with `{:` and `:}` and prepending a formatter followed by a `:` (e.g. `{:t20:by {artist}:}`) - -The following formatters are supported: - -Formatter | Argument | Description | Example | Output ----|---|---|---|--- -`tag` | | Only print the string if `tag` exists | `{:album: on {album}:}` | ` on Album Name` -w | Number | Limit the width of the string to `number` | `{:w3:Hello:}` | `Hel` -t | Number | Truncate width of the string to `number`. If the string is shorter than or equal to `number` it is printed as given, else the string is truncated and appended a truncator text | `{:t3:Hello:}` | `He…` - - -## Module - -### Basic output - -```ini -[module/player-mpris-tail] -type = custom/script -exec = ~/polybar-scripts/player-mpris-tail.py -f '{icon} {artist} - {title}' -tail = true -``` - -Example: `⏵ Artist - Title` - - -### Basic output and mouse controls - -```ini -[module/player-mpris-tail] -type = custom/script -exec = ~/polybar-scripts/player-mpris-tail.py -f '{icon} {artist} - {title}' -tail = true -click-left = ~/polybar-scripts/player-mpris-tail.py previous & -click-right = ~/polybar-scripts/player-mpris-tail.py next & -click-middle = ~/polybar-scripts/player-mpris-tail.py play-pause & -``` - -Example: `⏵ Artist - Title` - - -### Output using formatters - -```ini -[module/player-mpris-tail] -type = custom/script -exec = ~/polybar-scripts/player-mpris-tail.py -f '{icon} {:artist:t5:{artist}:}{:artist: - :}{:t4:{title}:}' -tail = true -click-left = ~/polybar-scripts/player-mpris-tail.py previous & -click-right = ~/polybar-scripts/player-mpris-tail.py next & -click-middle = ~/polybar-scripts/player-mpris-tail.py play-pause & -``` - -Example: `⏵ Artis… - Titl…` or `⏵ Titl…` - - -### Output using formatters and Polybar action handlers - -```ini -[module/player-mpris-tail] -type = custom/script -exec = ~/polybar-scripts/player-mpris-tail.py -f '{icon} {:artist:t18:{artist}:}{:artist: - :}{:t20:{title}:} %{A1:~/polybar-scripts/player-mpris-tail.py previous:} ⏮ %{A} %{A1:~/polybar-scripts/player-mpris-tail.py play-pause:} {icon-reversed} %{A} %{A1:~/polybar-scripts/player-mpris-tail.py next:} ⏭ %{A}' -tail = true -``` - -Example: `⏵ Artis… - Titl… ⏮ ⏸ ⏭ ` or `⏵ Titl… ⏮ ⏸ ⏭ ` or `⏸ Titl… ⏮ ⏵ ⏭ ` - - -### Output using formatters, Polybar action handlers and blacklisting - -```ini -[module/player-mpris-tail] -type = custom/script -exec = ~/polybar-scripts/player-mpris-tail.py -f '{icon} {:artist:t18:{artist}:}{:artist: - :}{:t20:{title}:} %{A1:~/polybar-scripts/player-mpris-tail.py previous -b vlc -b plasma-browser-integration:} ⏮ %{A} %{A1:~/polybar-scripts/player-mpris-tail.py play-pause -b vlc -b plasma-browser-integration:} {icon-reversed} %{A} %{A1:~/polybar-scripts/player-mpris-tail.py next -b vlc -b plasma-browser-integration:} ⏭ %{A}' -b vlc -b plasma-browser-integration -tail = true -``` - -Example: `⏵ Artis… - Titl… ⏮ ⏸ ⏭ ` or `⏵ Titl… ⏮ ⏸ ⏭ ` or `⏸ Titl… ⏮ ⏵ ⏭ ` diff --git a/polybar/.config/polybar/bin/player-mpris-tail/player-mpris-tail.py b/polybar/.config/polybar/bin/player-mpris-tail/player-mpris-tail.py deleted file mode 100755 index 3f6a2c4..0000000 --- a/polybar/.config/polybar/bin/player-mpris-tail/player-mpris-tail.py +++ /dev/null @@ -1,532 +0,0 @@ -#!/usr/bin/env python3 - -import sys -import dbus -import os -from operator import itemgetter -import argparse -import re -from urllib.parse import unquote -import time -from dbus.mainloop.glib import DBusGMainLoop -from gi.repository import GLib -DBusGMainLoop(set_as_default=True) - - -FORMAT_STRING = '{icon} {artist} - {title}' -FORMAT_REGEX = re.compile(r'(\{:(?P.*?)(:(?P[wt])(?P\d+))?:(?P.*?):\})', re.I) -FORMAT_TAG_REGEX = re.compile(r'(?P[wt])(?P\d+)') -SAFE_TAG_REGEX = re.compile(r'[{}]') - -class PlayerManager: - def __init__(self, blacklist = [], connect = True): - self.blacklist = blacklist - self._connect = connect - self._session_bus = dbus.SessionBus() - self.players = {} - - self.print_queue = [] - self.connected = False - self.player_states = {} - - self.refreshPlayerList() - - if self._connect: - self.connect() - loop = GLib.MainLoop() - try: - loop.run() - except KeyboardInterrupt: - print("interrupt received, stopping…") - - def connect(self): - self._session_bus.add_signal_receiver(self.onOwnerChangedName, 'NameOwnerChanged') - self._session_bus.add_signal_receiver(self.onChangedProperties, 'PropertiesChanged', - path = '/org/mpris/MediaPlayer2', - sender_keyword='sender') - - def onChangedProperties(self, interface, properties, signature, sender = None): - if sender in self.players: - player = self.players[sender] - # If we know this player, but haven't been able to set up a signal handler - if 'properties_changed' not in player._signals: - # Then trigger the signal handler manually - player.onPropertiesChanged(interface, properties, signature) - else: - # If we don't know this player, get its name and add it - bus_name = self.getBusNameFromOwner(sender) - self.addPlayer(bus_name, sender) - player = self.players[sender] - player.onPropertiesChanged(interface, properties, signature) - - def onOwnerChangedName(self, bus_name, old_owner, new_owner): - if self.busNameIsAPlayer(bus_name): - if new_owner and not old_owner: - self.addPlayer(bus_name, new_owner) - elif old_owner and not new_owner: - self.removePlayer(old_owner) - else: - self.changePlayerOwner(bus_name, old_owner, new_owner) - - def getBusNameFromOwner(self, owner): - player_bus_names = [ bus_name for bus_name in self._session_bus.list_names() if self.busNameIsAPlayer(bus_name) ] - for player_bus_name in player_bus_names: - player_bus_owner = self._session_bus.get_name_owner(player_bus_name) - if owner == player_bus_owner: - return player_bus_name - - def busNameIsAPlayer(self, bus_name): - return bus_name.startswith('org.mpris.MediaPlayer2') and bus_name.split('.')[3] not in self.blacklist - - def refreshPlayerList(self): - player_bus_names = [ bus_name for bus_name in self._session_bus.list_names() if self.busNameIsAPlayer(bus_name) ] - for player_bus_name in player_bus_names: - self.addPlayer(player_bus_name) - if self.connected != True: - self.connected = True - self.printQueue() - - def addPlayer(self, bus_name, owner = None): - player = Player(self._session_bus, bus_name, owner = owner, connect = self._connect, _print = self.print) - self.players[player.owner] = player - - def removePlayer(self, owner): - if owner in self.players: - self.players[owner].disconnect() - del self.players[owner] - # If there are no more players, clear the output - if len(self.players) == 0: - _printFlush(ICON_NONE) - # Else, print the output of the next active player - else: - players = self.getSortedPlayerOwnerList() - if len(players) > 0: - self.players[players[0]].printStatus() - - def changePlayerOwner(self, bus_name, old_owner, new_owner): - player = Player(self._session_bus, bus_name, owner = new_owner, connect = self._connect, _print = self.print) - self.players[new_owner] = player - del self.players[old_owner] - - # Get a list of player owners sorted by current status and age - def getSortedPlayerOwnerList(self): - players = [ - { - 'number': int(owner.split('.')[-1]), - 'status': 2 if player.status == 'playing' else 1 if player.status == 'paused' else 0, - 'owner': owner - } - for owner, player in self.players.items() - ] - return [ info['owner'] for info in reversed(sorted(players, key=itemgetter('status', 'number'))) ] - - # Get latest player that's currently playing - def getCurrentPlayer(self): - playing_players = [ - player_owner for player_owner in self.getSortedPlayerOwnerList() - if - self.players[player_owner].status == 'playing' or - self.players[player_owner].status == 'paused' - ] - return self.players[playing_players[0]] if playing_players else None - - def print(self, status, player): - self.player_states[player.bus_name] = status - - if self.connected: - current_player = self.getCurrentPlayer() - if current_player != None: - _printFlush(self.player_states[current_player.bus_name]) - else: - _printFlush(ICON_STOPPED) - else: - self.print_queue.append([status, player]) - - def printQueue(self): - for args in self.print_queue: - self.print(args[0], args[1]) - self.print_queue.clear() - - -class Player: - def __init__(self, session_bus, bus_name, owner = None, connect = True, _print = None): - self._session_bus = session_bus - self.bus_name = bus_name - self._disconnecting = False - self.__print = _print - - self.metadata = { - 'artist' : '', - 'album' : '', - 'title' : '', - 'track' : 0 - } - - self._rate = 1. - self._positionAtLastUpdate = 0. - self._timeAtLastUpdate = time.time() - self._positionTimerRunning = False - - self._metadata = None - self.status = 'stopped' - self.icon = ICON_NONE - self.icon_reversed = ICON_PLAYING - if owner is not None: - self.owner = owner - else: - self.owner = self._session_bus.get_name_owner(bus_name) - self._obj = self._session_bus.get_object(self.bus_name, '/org/mpris/MediaPlayer2') - self._properties_interface = dbus.Interface(self._obj, dbus_interface='org.freedesktop.DBus.Properties') - self._introspect_interface = dbus.Interface(self._obj, dbus_interface='org.freedesktop.DBus.Introspectable') - self._media_interface = dbus.Interface(self._obj, dbus_interface='org.mpris.MediaPlayer2') - self._player_interface = dbus.Interface(self._obj, dbus_interface='org.mpris.MediaPlayer2.Player') - self._introspect = self._introspect_interface.get_dbus_method('Introspect', dbus_interface=None) - self._getProperty = self._properties_interface.get_dbus_method('Get', dbus_interface=None) - self._playerPlay = self._player_interface.get_dbus_method('Play', dbus_interface=None) - self._playerPause = self._player_interface.get_dbus_method('Pause', dbus_interface=None) - self._playerPlayPause = self._player_interface.get_dbus_method('PlayPause', dbus_interface=None) - self._playerStop = self._player_interface.get_dbus_method('Stop', dbus_interface=None) - self._playerPrevious = self._player_interface.get_dbus_method('Previous', dbus_interface=None) - self._playerNext = self._player_interface.get_dbus_method('Next', dbus_interface=None) - self._playerRaise = self._media_interface.get_dbus_method('Raise', dbus_interface=None) - self._signals = {} - - self.refreshPosition() - self.refreshStatus() - self.refreshMetadata() - - if connect: - self.printStatus() - self.connect() - - def play(self): - self._playerPlay() - def pause(self): - self._playerPause() - def playpause(self): - self._playerPlayPause() - def stop(self): - self._playerStop() - def previous(self): - self._playerPrevious() - def next(self): - self._playerNext() - def raisePlayer(self): - self._playerRaise() - - def connect(self): - if self._disconnecting is not True: - introspect_xml = self._introspect(self.bus_name, '/') - if 'TrackMetadataChanged' in introspect_xml: - self._signals['track_metadata_changed'] = self._session_bus.add_signal_receiver(self.onMetadataChanged, 'TrackMetadataChanged', self.bus_name) - self._signals['seeked'] = self._player_interface.connect_to_signal('Seeked', self.onSeeked) - self._signals['properties_changed'] = self._properties_interface.connect_to_signal('PropertiesChanged', self.onPropertiesChanged) - - def disconnect(self): - self._disconnecting = True - for signal_name, signal_handler in list(self._signals.items()): - signal_handler.remove() - del self._signals[signal_name] - - def refreshStatus(self): - # Some clients (VLC) will momentarily create a new player before removing it again - # so we can't be sure the interface still exists - try: - self.status = str(self._getProperty('org.mpris.MediaPlayer2.Player', 'PlaybackStatus')).lower() - self.updateIcon() - self.checkPositionTimer() - except dbus.exceptions.DBusException: - self.disconnect() - - def refreshMetadata(self): - # Some clients (VLC) will momentarily create a new player before removing it again - # so we can't be sure the interface still exists - try: - self._metadata = self._getProperty('org.mpris.MediaPlayer2.Player', 'Metadata') - self._parseMetadata() - except dbus.exceptions.DBusException: - self.disconnect() - - def updateIcon(self): - self.icon = ( - ICON_PLAYING if self.status == 'playing' else - ICON_PAUSED if self.status == 'paused' else - ICON_STOPPED if self.status == 'stopped' else - ICON_NONE - ) - self.icon_reversed = ( - ICON_PAUSED if self.status == 'playing' else - ICON_PLAYING - ) - - def _print(self, status): - self.__print(status, self) - - def _parseMetadata(self): - if self._metadata != None: - artist = _getProperty(self._metadata, 'xesam:artist', ['']) - if artist != None and len(artist): - self.metadata['artist'] = re.sub(SAFE_TAG_REGEX, """\1\1""", artist[0]) - else: - artists = _getProperty(self._metadata, 'xesam:artists', ['']) - if artists != None and len(artists): - # Note: This only grabs the first artist - self.metadata['artist'] = re.sub(SAFE_TAG_REGEX, """\1\1""", artists[0]) - else: - self.metadata['artist'] = ''; - self.metadata['album'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _getProperty(self._metadata, 'xesam:album', '')) - self.metadata['title'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _getProperty(self._metadata, 'xesam:title', '')) - self.metadata['track'] = _getProperty(self._metadata, 'xesam:trackNumber', '') - length = str(_getProperty(self._metadata, 'xesam:length', '')) - if not len(length): - length = str(_getProperty(self._metadata, 'mpris:length', '')) - if len(length): - self.metadata['length'] = int(length) - else: - self.metadata['length'] = 0 - self.metadata['genre'] = _getProperty(self._metadata, 'xesam:genre', '') - self.metadata['disc'] = _getProperty(self._metadata, 'xesam:discNumber', '') - self.metadata['date'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _getProperty(self._metadata, 'xesam:contentCreated', '')) - self.metadata['year'] = re.sub(SAFE_TAG_REGEX, """\1\1""", self.metadata['date'][0:4]) - self.metadata['url'] = _getProperty(self._metadata, 'xesam:url', '') - self.metadata['filename'] = os.path.basename(self.metadata['url']) - cover = _getProperty(self._metadata, 'xesam:artUrl', '') - if not len(cover): - cover = _getProperty(self._metadata, 'mpris:artUrl', '') - if len(cover): - self.metadata['cover'] = re.sub(SAFE_TAG_REGEX, """\1\1""", cover) - else: - self.metadata['cover'] = '' - - self.metadata['duration'] = _getDuration(self.metadata['length']) - - def onMetadataChanged(self, track_id, metadata): - self.refreshMetadata() - self.printStatus() - - def onPropertiesChanged(self, interface, properties, signature): - updated = False - if dbus.String('Metadata') in properties: - _metadata = properties[dbus.String('Metadata')] - if _metadata != self._metadata: - self._metadata = _metadata - self._parseMetadata() - updated = True - if dbus.String('PlaybackStatus') in properties: - status = str(properties[dbus.String('PlaybackStatus')]).lower() - if status != self.status: - self.status = status - self.checkPositionTimer() - self.updateIcon() - updated = True - if dbus.String('Rate') in properties and dbus.String('PlaybackStatus') not in properties: - self.refreshStatus() - if NEEDS_POSITION and dbus.String('Rate') in properties: - rate = properties[dbus.String('Rate')] - if rate != self._rate: - self._rate = rate - self.refreshPosition() - - if updated: - self.refreshPosition() - self.printStatus() - - def checkPositionTimer(self): - if NEEDS_POSITION and self.status == 'playing' and not self._positionTimerRunning: - self._positionTimerRunning = True - GLib.timeout_add_seconds(1, self._positionTimer) - - def onSeeked(self, position): - self.refreshPosition() - self.printStatus() - - def _positionTimer(self): - self.printStatus() - self._positionTimerRunning = self.status == 'playing' - return self._positionTimerRunning - - def refreshPosition(self): - try: - time_us = self._getProperty('org.mpris.MediaPlayer2.Player', 'Position') - except dbus.exceptions.DBusException: - time_us = 0 - - self._timeAtLastUpdate = time.time() - self._positionAtLastUpdate = time_us / 1000000 - - def _getPosition(self): - if self.status == 'playing': - return self._positionAtLastUpdate + self._rate * (time.time() - self._timeAtLastUpdate) - else: - return self._positionAtLastUpdate - - def _statusReplace(self, match, metadata): - tag = match.group('tag') - format = match.group('format') - formatlen = match.group('formatlen') - text = match.group('text') - tag_found = False - reversed_tag = False - - if tag.startswith('-'): - tag = tag[1:] - reversed_tag = True - - if format is None: - tag_is_format_match = re.match(FORMAT_TAG_REGEX, tag) - if tag_is_format_match: - format = tag_is_format_match.group('format') - formatlen = tag_is_format_match.group('formatlen') - tag_found = True - if format is not None: - text = text.format_map(CleanSafeDict(**metadata)) - if format == 'w': - formatlen = int(formatlen) - text = text[:formatlen] - elif format == 't': - formatlen = int(formatlen) - if len(text) > formatlen: - text = text[:max(formatlen - len(TRUNCATE_STRING), 0)] + TRUNCATE_STRING - if tag_found is False and tag in metadata and len(metadata[tag]): - tag_found = True - - if reversed_tag: - tag_found = not tag_found - - if tag_found: - return text - else: - return '' - - def printStatus(self): - if self.status in [ 'playing', 'paused' ]: - metadata = { **self.metadata, 'icon': self.icon, 'icon-reversed': self.icon_reversed } - if NEEDS_POSITION: - metadata['position'] = time.strftime("%M:%S", time.gmtime(self._getPosition())) - # replace metadata tags in text - text = re.sub(FORMAT_REGEX, lambda match: self._statusReplace(match, metadata), FORMAT_STRING) - # restore polybar tag formatting and replace any remaining metadata tags after that - try: - text = re.sub(r'􏿿p􏿿(.*?)􏿿p􏿿(.*?)􏿿p􏿿(.*?)􏿿p􏿿', r'%{\1}\2%{\3}', text.format_map(CleanSafeDict(**metadata))) - except: - print("Invalid format string") - self._print(text) - else: - self._print(ICON_STOPPED) - - -def _dbusValueToPython(value): - if isinstance(value, dbus.Dictionary): - return {_dbusValueToPython(key): _dbusValueToPython(value) for key, value in value.items()} - elif isinstance(value, dbus.Array): - return [ _dbusValueToPython(item) for item in value ] - elif isinstance(value, dbus.Boolean): - return int(value) == 1 - elif ( - isinstance(value, dbus.Byte) or - isinstance(value, dbus.Int16) or - isinstance(value, dbus.UInt16) or - isinstance(value, dbus.Int32) or - isinstance(value, dbus.UInt32) or - isinstance(value, dbus.Int64) or - isinstance(value, dbus.UInt64) - ): - return int(value) - elif isinstance(value, dbus.Double): - return float(value) - elif ( - isinstance(value, dbus.ObjectPath) or - isinstance(value, dbus.Signature) or - isinstance(value, dbus.String) - ): - return unquote(str(value)) - -def _getProperty(properties, property, default = None): - value = default - if not isinstance(property, dbus.String): - property = dbus.String(property) - if property in properties: - value = properties[property] - return _dbusValueToPython(value) - else: - return value - -def _getDuration(t: int): - seconds = t / 1000000 - return time.strftime("%M:%S", time.gmtime(seconds)) - - -class CleanSafeDict(dict): - def __missing__(self, key): - return '{{{}}}'.format(key) - - -""" -Seems to assure print() actually prints when no terminal is connected -""" - -_last_status = '' -def _printFlush(status, **kwargs): - global _last_status - if status != _last_status: - print(status, **kwargs) - sys.stdout.flush() - _last_status = status - - - -parser = argparse.ArgumentParser() -parser.add_argument('command', help="send the given command to the active player", - choices=[ 'play', 'pause', 'play-pause', 'stop', 'previous', 'next', 'status', 'list', 'current', 'metadata', 'raise' ], - default=None, - nargs='?') -parser.add_argument('-b', '--blacklist', help="ignore a player by it's bus name. Can be be given multiple times (e.g. -b vlc -b audacious)", - action='append', - metavar="BUS_NAME", - default=[]) -parser.add_argument('-f', '--format', default='{icon} {:artist:{artist} - :}{:title:{title}:}{:-title:{filename}:}') -parser.add_argument('--truncate-text', default='…') -parser.add_argument('--icon-playing', default='⏵') -parser.add_argument('--icon-paused', default='⏸') -parser.add_argument('--icon-stopped', default='⏹') -parser.add_argument('--icon-none', default='') -args = parser.parse_args() - -FORMAT_STRING = re.sub(r'%\{(.*?)\}(.*?)%\{(.*?)\}', r'􏿿p􏿿\1􏿿p􏿿\2􏿿p􏿿\3􏿿p􏿿', args.format) -NEEDS_POSITION = "{position}" in FORMAT_STRING - -TRUNCATE_STRING = args.truncate_text -ICON_PLAYING = args.icon_playing -ICON_PAUSED = args.icon_paused -ICON_STOPPED = args.icon_stopped -ICON_NONE = args.icon_none - -if args.command is None: - PlayerManager(blacklist = args.blacklist) -else: - player_manager = PlayerManager(blacklist = args.blacklist, connect = False) - current_player = player_manager.getCurrentPlayer() - if args.command == 'play' and current_player: - current_player.play() - elif args.command == 'pause' and current_player: - current_player.pause() - elif args.command == 'play-pause' and current_player: - current_player.playpause() - elif args.command == 'stop' and current_player: - current_player.stop() - elif args.command == 'previous' and current_player: - current_player.previous() - elif args.command == 'next' and current_player: - current_player.next() - elif args.command == 'status' and current_player: - current_player.printStatus() - elif args.command == 'list': - print("\n".join(sorted([ - "{} : {}".format(player.bus_name.split('.')[3], player.status) - for player in player_manager.players.values() ]))) - elif args.command == 'current' and current_player: - print("{} : {}".format(current_player.bus_name.split('.')[3], current_player.status)) - elif args.command == 'metadata' and current_player: - print(_dbusValueToPython(current_player._metadata)) - elif args.command == 'raise' and current_player: - current_player.raisePlayer() diff --git a/polybar/.config/polybar/bin/player-mpris-tail/screenshots/1.png b/polybar/.config/polybar/bin/player-mpris-tail/screenshots/1.png deleted file mode 100644 index 686c7d619441e233715934fa19792f4ea7b1fc83..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9199 zcmV$lHws=qD~%?Eyvz?oyxj4 zUNJ7KcJnh%rE05^s{BgTCY7rEOl>NWk9bQ~)vnjxvb`(Wl4*&gC6b^>ksv`5Cvo2c z%wRBgzb`+!-|N@M0HCCOLJ@=R_rCYt*Xtf(yt5zFK?I2Azw(MP#1%9?6OovYa3@&y5T|l>2js>ndVXrfC{0>AFrt2tb5l0D#W9$3~vI@g>UosfL|7 zHa&D{zGWR>WV;=;$da;cki-gAD{}(@7urIaDqL?(bLk1XXG;9ly$}%q5lxk|*k!Hr zd2d!uH4%;Fs1T#ti3et`fy!hL0u)3M(I#>SANM{SsTITN-{h8GfIlFAAW-a5#%%a_C&AqZ2-ga8O!wE;uh z02lx=#uy{cE#;GP{NirKA;ZrN&+Sdr>jtV0Zg?8o?g$G|<$SAUTpo)7EDdlfm~)Y^fVr$^<_C${1n4rpw2oMd)t3;9NH^}st7RF>ansU4@KgbHEAnB2$T1spHSEOPs zad;Mz%IsydJ4m$Lt*6rF&#n4`C`T>^0K)v$p?Ft`Hd(>S;SSVoy!499{}e$;J>vjK zgounW&N;~dAST;VA#ux_MiO!nD@d+GC~_UR4q%r85hnu9HJ=YPjdM<%TU5iB<7>Ql z{zZokCzqL__?Px#Ddm&3ow5=yy+J@prCmduG0$C6sDei65z6jO_P@Nf0zJh?gvbER z=qF;2Y2-d*-A;Skz}wiThDQWNS$EVS>z-n44ofq=JLhIrW-Q#fNby2g!nb4K#Xfg! zWp|O@J17*H9@Z8BL9qg|`59%Qo0eTNj&j4HCFV8KG>vm^xEpKV9m1NO>aw|~eQ!^U zxUMrz(-`9b+$f_I5kED7_VFe97ZVLz!D#<%L~=3BgN;t)%7FUfXnwwBh?c=h{FTCo z+-BlfZf;+88UYY-h71`JCr%u}O2oD5nugs`R05GBkumYqsw$ffw)LKkH}TZ+dTCd5 z!F18i6vpmoRQZ_m8MDFJL4&ert4K6Tm12w zpe}bXN*aa=A7wC5CfIgyIdL^nlBAe4?u?Q$jA)^0no+|W8=)%SFVzme&~Rnb9%2NG zGwuZ36V6`mmR<$i2>#$syikycDNtz9?y9PsPay!_@t~R^}S7jk= z4kjBLU>6l4A|P~Mx^UqumFrhlGMWRJ+4?}#V&8iH{JC&qXgwqF^d!NN3aJ;#?4_9E zM^vx7y}6qx0~0fJi$<@*h3&u?B4Uggl@w!)F~&WU#D7j-Q*+`!zi_s_I5wQ(PZx5W zvt5|)z&hs@rAuO)wl{xWrbFy8SnOLboIf9uI%8}uBBfh)vas60Iy|h{3q>`Q8XJ+c zbVOG(*gn)USf<)6+*Thu(A0XMzM(F_94js4@ zyareD9cLx0091=6NAYi`BN&Rm(s!V*y0S_uZEh{z9KZkRW&r_!DNaf!LdJYPAJ=sv z(j%{&dF_QLKwYG_j5m1AGR*tJ=y79BgJ%sVu^7#V^7QAzNY5i-1=x}%iurfAf~?Bfx@OPC+@Ck zW%}*}Kt`9uNVhbNICs*eT8`{es~M>5rr9%1E%rwzPxbp!59Y?!cx8WE_t%b9Wd88+ zqk;n2WFzMUz%-5PM*o<&PQm!$x_b)=XV4BbboTpoooi~wr>49nN8PPc8%29*0F{~M z=!>Ena_r#;-J+rLr%O8y!!7_&^H&5bJ8D}_^~MJ4Zv5{%b2$ftJT?U=PFOl4<{7vW zH=Knm1*9mA?8E5RyN42Wtn9{&p3a#h5+5^(X3Wq!BC=&PG7a$p0|3Bl4tMU|%eY8Y zU8BBsbHa#Yh!E)7_wskT+g{(-I5M)TnHME_s&b=YxIl`=$?C>*ACZBksxn-YJ_}KT zHF#v+7WzS89twJNpaJxi>!ZWV<{zv+cJ|G|=5yUGL-!Uz;wy?IAr@6&=4UbvbYzRs zh8O@+CbN;T80c`UWwJSI7nNQR=iEkX#yE{4lI=iivgD*lDg_`^YbcV~0#Z`|xOJqB!HHgr4T>~&W!~n3dJYE|++}8Zt#IngcqdL?52is!W z_R=WE`s`#`?oj+Pb}5s(?vn7kvXWh!yN*t|C=)CVSLdq{ZfAF6)~QfhyD=eE3xG9! z{me_p8utwZ=kDZpS}(v*CbOAwUIZZ1J)lfe&EF;gc0E^_=7qKu@?{@JMnW{bKN&}# zh9e{LIRU9&M&YSxD|;^%0o-_-^hn*8kuyIv{%Er6)V}JvT3Ah)t5{8K@5^2Bo@iBt zR!XJUM&=$|TSyh9%&_~?h2!Z*KmWx_>xF@X&(u|Fxd(3z)7Ot2>I?zE(Z9TS6aXM` z^S|Dn5daUI@9FG`hWt=iPc95iKDe`4G}RHi-?(sm`{B=ju_~ZtAN-%|qnq9osY73z zo0#lx?yst?p@j`|BCDzGd!<_-zrFr&_QADR$~nYh?bJdHk!(+1~SA9bM51EM?ZW=C3|}IGPawjI@Tv121*9 z$15vCK7BivUQEp0m>!$W39RbuSj~-Go7*f%^Mc)&G7bz-TY0?HbfC3sKUp~Sio=t4ce?0bZBwez!lKdSV&s^weYYl0oVsc{P(fe!M zc{o9=rp~4bHzyu^mMp5tY_%%B^xDYmgR2WE3l4U_ap8FO(XTG&ge>%|!KktAl1O^o zQOfhP+Z8IS`0Dt&eyqwL&}5);BY*#nL>_xCT{zxq=#2O?`}miav%TlL;x>V9>i{C4 z@?cxr;Dva5ETokR$%)00_b2@S;=*Yh{pCBe1xv5G+T-EMuuo6t(~F7u8&ji(UfF^m zh;EIQ$0H(RK9x@AvH2d_Q~&^=7gIB9i;tI!`wt(g1hJt6DtMq&A`&&>7pa&t^h`M1 z+NLw#JKP$`Cmt=2ZxnpZjUCSqoa+u<{qaOX%~m26onJqBe2^t3Ru@Uh> zDH8ng_4|veKQn3=@q}c&{gv;A^zkQS@6P13Q0tlQ{%@ZNy>n$~yaWIcYB>45qwS@w znc=zF90sZ@8~S3+52wZqNVPVswC2Y6*@0KO!qzOHj3;v9hh;_WXRTf8@uW1*Ha z-TmJ_9s23jp$T0E4AJT{G--2YBp)B_JlMK)ZzIt2&EDoxX5`iyh_1GfvRVbpCu=kq zU0Nu{+Ma3ljjeE>rfG#@k*K=0E6!GaxsdJLr?MZy^#d1M+4%bWla&Gl>IPd6{Hs%; z!j+p7h7TaEz5A6n_E(oO3%93}C10dFcILbFDMx>&y6NX~H*7Hbie-zOrd{ zi))*od()wNgXg-#SARU7;6io?5bqGOn9gb8)-&A)zI{6M&Xpm7jNsK%6izZXkgTrT zSEoU4c{=Nj{5});-(A@(o5aW4U-@o`k3AWEcP6hH0zDJ@sfi~MvDWzWm-=e;?Bbp2 z6c0wa+RlErW*rdL1O!vB(w1HwXl;5lF*;{$BBF?;-tr)Vh%shw28*0rbq!_T1E5@P zePVTCbZv1gkuDH`-qdy&DhZq??ZS7snJPLs=!-OVFeq*%H;w4W;$IzX4do|)a`VoN zVZM`NXO3LF*nQ&6%5VOVvU&uu__3=rixezrhueFx&j#PH&@u@nIa+Fl!M zqr{EBzCD)*B7!SV*4}vG*%$h{hK43(Ur0ckOP7_JgR=m{nmYFNFj`()P8)n>bbAR8f@rfTl$uh|? zr5#QH;Rs#1@!=K2c4&UGQ1ShP@ng+*#^y^%xUV@DgqfcY-5lp~wZ;rYRji5tfH*OF z>ga2)b{;>ycKODpuIpyP8jjGF8^8Z3MGS~wezFk${=xY1<~!r_x)~}YMrH-L{F{4I z9nbduo0Cm?D9W}+e|q=fswfVH?g_7Cq&7aEuOw6;IXha2_s3$vrP&hbIuTLyc&x6t zaqB^zb*Y*|kX*d_KNh%58Ez$C{11oP4>#Q!U*G@${?1o>s&*LTc3PiR8t(9Ov#0I<&2O-9`|6=-7g%+Xh0mAWSY2}W@=WRb7< z{-KUzt)ETImC&BL?%1ZWZV>>mh7Vte3yy5*9b@8 z%8lQDl+qCZU~aMy`u@TA@s>Lib2YI(A-{zoUT)AIJN)q zg?-O_rT^rgoch|I4>aaChW}wIX+R1#cI?+^a`xeL5rnf&-<+JzP~=!^Z3)dMZV&)6 z)1R!0!T|Zw^!NnFcynuojSP`N7}RV{-%eT)I=zwD0IUyJ5&$4&OC`kGp4xzdx~>bX z>?|e1%&p1kEJcnrMe_h)Jn8}fThpH=b*T*Ljdihw(q^)nJBXk~L##*;uB?v0+^;^n zKa&&DMGG}oMXLj{Ru_E}U9=vFbiRChKI^aR8VnGXbR7XAork0P!-e^RBSIk{anpbi z0APD-V+&Yyu);tr)Yu+pG&MK2U~-6fY5vMwQdM%lr3v9^FdPkrBc>)a#Tfu#g(1F~ zkzIAqWR%F%(wm75!1{`ij<)b%a?ClVKiD|Ap?p6R}t;OFddznadhJ zLP5SF9IXgPD;&s|8R_ZUrk4Sb0u5CfN0}9k?OlwfX2urH$`Glz@Zqe&G)u4iB)Z6) z^pe#nMNnxWrG*M$7SP`BI>`sCywF}>{_NeUZ5v(aV5MxMhzstd#^3wr7kcGiRN5H2 zfBnORS!Oj=MG3PDsT@Z!ys^mIjPg1AwV05=yWtkSvcv0`(inkaDe;Ma~i$qj^j zLEu~@+z|S;;=aVzTlP%AlKK^>o%G8b7 z@!>?KB-moGba5*u1cwM@Vilf*uTH;m4Dq?wY5I{ z_bc_U4|M$TvGm)Yjw}=b0Gc~q{C9ouyX)_NTmYeQBAu2k3gT1CbII=g&$LzEo!mx% zcxy*BpTD;(14ITOZK5$8A@b%kjzy~^rjw{8$G{gOE1008T}((zKI`P{91A;Rrw%2iQTkdd&=(-X%< z)A-C2;tWu!m`h~VC)X2OO3NY^7g}5UdV6&%^w7iRdAu0F99egppMSJ`B%vA z2h7}kbmw8#;fZp~MT^oxu}}i=IsK-9ELkA50W13d;`xK^b#-hq=|ny!`uWCwdSROb zFkg_*^P~Y!cwp)0XMO#Aleq)v=VXCCvZ|<$Pb$hyP_~G@H2j!#lGXU~Bxj zO9uzO^DMmm>BvGpa%-BpY@kZz5nI51xu!;w3N~fwQ9lfF{#2dD*Z>M8r}-VSr1oGP747 z-o0TwDrL<=ajYpgVOly7I^W(Vi*dUaQDPI#7jCMo^h04I=}>-oT&2J#vA@20eeB+{ znqQ$cCzH=31u82LGYVE(Fw6k-Vh&7~g#ds|Id-)nM)DC`fPAS45GdxC#@FnWN<5vI z?^s2Os+4l0@6YvoCw}lk=rBFIEO2#}G-zyQ8LB?I8490<<>;Pd-5#xzdci1R!U z3Iddh1!41Mc4>80!LHO2UofBhCZN*h-HA``PKEci_MhL^{o1oN{+sV#OPN@Og8&(& zFY61su>!$f$1WtZRP*T-0)SXUOBmB1jn8HP0Ql;{Cx64vzA-THooC_aPogIxe0qFp z1;Bck0Kx2?OQ-;#rS8oqUmWN>7#_Xl?>ZRF++18m03%@m!x;hgbscE+rLWz(c6pN{ z8O~Z)6}X_6fC8ZafO^2oY)_@;N<{#FF~2yr2A)F^pWp=mXu&FjQSRohX9_KE84AGG z{_*P1eqDZ|=VAkJYHNK9>YF1`4%wVdjR`!=vc zcjDvECM);F`Y$MYrM96wY(`#Tj;pr%N|uqrLcUxS>cbiFd4# zF<*6a2q2wWbCkI1qheOeMm;W6IA~nunTh$^KfFDfgy@mhS`G?J71}J8+SYOc00Sj( zV501b000%5A5hQBY!vn7xsTs|yaH7Ne|o6RmmB}>Y=+5W2G}xl|4y6m8T5 zrbM}w=|?4~iyb;yh30D=hzP!#aM0<9UEWX`@;FWra_Px$rc$h;@2ee^hE)`8$Q$Sx z$Zy@5PuN^>D1N5iZ@ylDtf_r}52Klt#jLIUY&FzLxnNZy#^6MpLV*fZpj_8EKuOn~ zSefinuo4>>X$Np3&N)M5;=x=Z1VTV0nSmoBTiZ?{j|{eoC+86nDV<6fkERw&1rDln z6y65x#z+8#nc;P+Z$5dxNn2W+UPi{4XiggwFqg{e0MYueSfw>x>}pb5YMJ%LSz`M; z`dfTLSgihqjyiQt-qeJ{Co9#w%3l)-kSV?=BL(d2RCG@j-|qS?lTM|M-^C}CPoJ^+ z#m;ts(qv*?1IVvVKPo|8o1w-Y$d})ttX5~%7UziV@93=)*&|@>^X(0~f_XSlfl7OX zb3?Dn9nGq4R*<&KyG{TAEK=3b5v>eTKC!8(!b#;b072Va%+IH?F0QH>gtTilP=b(& zcuE?VKX@=5KhphYXR3ym)>68^xiQ`!fyL=hKiRUwbg~bTrN>vdUXFHs^C;X|&j(@c z>eO-`=H4Bii5-o9_0(4mEH5tRsUlF>SliUJb>qL^TV#7XZUgYvnC0pF_v2>|_B=DV zc>Qq!fR^4jkbkancxgSU`&%00{SjE09uml#Be9X~f97J-%Hqs+-XD$~X{pw;qaV!X zG(`8Ap($lkedW`fk_$w{dV62L5M3ExPbTt3=8x`gX|JWVe_Bjw;KVA${Vfgg0})tw zGW7A5qs1l?C^CyOCRk2r`B>w_=F-Evoo5gCy!^fJc;nG2?7aVVsS1T>pXw_Z1sF1 z=daq=)E-LA%!lI^lL}MsPwji7=fHPQ*9@<0~toYERq|9)Ich5;4MVPPQ^uEK}0D!C_SQV>lZV9r?=I!4t=?DOP z{=NG%u_F#OR*?T3qd587$(~F52EKPX^4U_da|4yVtwYyTg8EwI@&s_DtuH}Pc0A6j@(#vzay)% z+l%#N)JH_tL-DYc`1FUj5-;}j>~HO>^6Sa;+8-W1_`^aFRChj{8tAWmY$*Kb%i$W((k{2HN^KwD7_B%D`aT ztGx|l57sz9dVT1vTZxx?dU{*?D*bvYz4nKZ2iF!-wh(}Y@h4Yr;lRbN_=(0K(=!Xp z!@nOJTQd7CqLWSpoNQ&QQGFOsouYyd^6ACL6M?pPbNxXd%NMuTQ;+|Ca&%x{Czq?bLT=*2T)*vBzLm{MF9bvF;|ln4DVp_;1JaXKUi^RyC*3Onmru>F~Ms*pZHgQXx69c>QM+ z{%>5geM7<4+R$4=>o4_mTbi&j{rh>#Y*a=G@!h|+;C_grjMk9-rrP}4b+Ec4-DX+G zshG~J-ku-5_GCp0$wQ6p$UpT!K0Ep0-xLp@kGGxdZY>p3lgl^$VY%rqPSu!M0n*IU zjeCNzy-fQN5W#dY1_GSxoRiFKqz5!*=jH=AdlnAOK@%)@ zatr_vHO2tZ{60{J(R!um3T->y-C=l=ATw{rt@2{smH9Tr%53U=x7@Tch}ag(RBVT} zh&3nv(}~XUN5A;nIgYZqLFxhM9x)Vn?&1hH)?9CLrAF7Y%&j_4BT0`TpGjx3`=Fjf z3G0%5P)DBc=$Jp z`T_#DajFdfOn6~VT-SBZIU;JB#+W8DEn^{o@Q>D6mE@Rg&8WnL6YE^C?g?l?G#!KWIYvbHPL&X8po5as7nU}7;x=}&#R!vi3SKw>73(W*!Q zOX&hfwS~{@ZNaA+yL|E0_Uyex9+;+qp385|u1{TlaQn`du54!YM-_&a_w=r0LB=#i zeum+Ihcclu$CgIPCHCpIXzy^wJMe60RrAsY4|?|^5~tZnW}@_BB!Kn+00WyzL_t(C z0HQ~0BMdG6IJ~eOtc2@qAn%AUTDu@hG>8C^`7{t;Pi0~<~ROG2H9z}xi-~=JcqO{^~cklDLgOBLt}VmcB-YglLAjW@{Fk}K-Z6@ z1J-AI&_M;7!6<)2O<2ztWnqX~>}!Yn8vIM2JephMw*3`;+kI2nKrZg=+6>;>octg; zsa|mfQ6xYz_UYAW-nK5_?y~@M8vsy7^V3%1fOoa zfo((y50_DPKUp1%=8Nqd08n}7TLDN!96)1?bFS;U;i`;h|7^e&PC5tf@_3YOrpg(K zgKL+k7;2Nj&1!L_oN4TJ6F0UFs>zyQUI-mN@Y>11+SKOORxV%Es=AxnT7&w+)X2l4 zJtUJ*Ftu-hN}=t}4CIGBd}pwU&Td(NoF-hpEug6}%68XF9~@YM;(Y}s(zWiI%sCt~ zxO1hwHBdg!*bS`nHVGt&%(H(c=u?})a;*p^YE-u(n}Wt}c$CQ|%(cq58Hqw&(=?yY z2S#s2ZXuB|!-JDTR9wGJ%F+nkxr|Fv#&cE9|E+?XB3EwWJ=NF zTrG#y&dp$zFe^VV=g}4V9aiDoRryV2CR#b4S|uqhPkD=Mm%WEmtredI>a8zp?5GM3 ztZXTn_}(BeKbnYIsS4+$tStlA(#WR>i1z4hcT}dMA>|TdOw%-7=ek}Jm|Kb`*lR-o zZMOjJzQ7?_6(v#wn9;8>Gc5CkEDs(yL@YBe=e#nZ4qX*Dz+N4V*EDpgxV6jY>j0K_ zG@#P{Ir2CFn{!kW7R%^F@87vy8N~K>D(0C8>^xI$zbouA*DbeVcL(TZ<ACF82= z^za3qyGYKsC+rccy%=n{t;GkaW-6a;{TeB$a(N%X{|B0uSNmDk5aIv;002ovPDHLk FV1jO{*L(l~ diff --git a/polybar/.config/polybar/bin/player-mpris-tail/screenshots/2.png b/polybar/.config/polybar/bin/player-mpris-tail/screenshots/2.png deleted file mode 100644 index 7aeabf3e7d5a9f08cdee1a8d786254a46b0786ae..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6192 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 O0000Or>J?c6WCNg64nG z=~RIp6fT#`0=MiMjk+5h9dl>SoYB>g5h?;ch}LfsSG*Rg>5F5HFizTsu2EJ&GPjG1h?+Mn^~8<`+E5Oq&YnGM^Ya~L0T9DNA6`MY z*;hBnR#60CB(AdN7?G^OApnT)$7!qq#a+C3!QH%h)6LAxi0Veo5diz+$B*vyn>TLt z(*_Zhn5=-MxF)l&j05NKODvxxqs3-n~0A=)s!+8lxW2g1i>G zV4aPPjU=kt-tz@KQGu5u1CGJ(bY!6XaY09x^XJc-{tFAg8tANr*@>#NipYj&4F_45 z69#JQ0)M#7ECl`1rAzM4ojbNzv$^e_J%8?2R#x1seq)Ra5@<>bKX~xKeg6D;fb#5c zV!c>f`c$FRaEr1mkiC5Q(!!ovdQ$zSr>6|~{B~HF0D4GNcrcX0 znuKr+z)H2^%SjpRj4tL$H^vp4RG`X^vSc6?(^zrD;bHfmdePYOdbV2R08IeQVfqt zhY-)XxKH?USXI#$ogHPY8OK`o!vp&tP{qcc)O{l8sS+oSL6vgt+I1@)zy%&(5!iqH z=MT$oI|p=lIB%upkAi;CNt3gHUAh^#t*y|eJlYp{=~l#O7>VYSyB{0!M>k4(XW83h zEq0pTvtzEr%Z8B=zk39bbR-xT58XtENp2(Zjl(5NXy%MkBzQjMuAK+z%4<>3_ca+@ z#iYTj5df~m`Wu@YN>W?qxhP26+m{hMn*G^(g3MWt8NTh83-1QKEeI?3r;GT#7+h5Wqu;7uPKtb{=)x%4=6gvIh(aXKw{PE?rB{_a2sgIjl#y&;IE%p$!!`q2 zO7NL(gt9LM{n2e~Za-c}xdH%>#5rhCpgGPFs0FGU8yoe&O7HKgSlDp_IG7+Qryvs5jhIh0?xw_1(MonzQ5PL>udJq_Z%_$F zpmHNBgKGpXuT=c8bJl5M^G4|fAn_3DQY_3)^j97DU6G*@1Jo zM`U7XHjZ4D=k$#A@~8zlqM-AT!Jh;$T*hXIvj&cMS!`Ab#vg(;-O|#MZ6I0##JAuJ z{rESoKHvl@2wsDS)%6BxqBCI>2gL-XI0gWC3<9?@hB?B{)KkmRoWSRjmTiPy{rRWq zd_iYTyh3DiNTd;A;DBSUtb7u!tQIEGLeS}eRY{Qd@88#%@JPbX*8Z6ikY6TG%t%9fS%hzckXD#7CbE0zNWk<<1c(h;Y7`0$~d zpPzR(bg=i!FSiA}KjXncSce*YY3aG~eNp8y5a>sYLa%VHkJ zyp(u&v6Y?jGS=ljWh9<%$G!?}-tGtLL20hQy(o?GkYy0%WAdc$law*Gy)aP;iSbG3 zL08r%qPQ^hAgvJeK_)qFpRglEkpmAE=(aZyt-$3q{Ts%Jl=r(u&A+ zSNM8N)U2svYiIj0U+CMFJhqCzpY50Zoj=+?T^3b7QzFmX9YjIDqonmuz3&?$6b6xL z=suhpgyuQC{}f%{(6^+cfu20zqi1|-UYjv%&0!F?$-P|vRziO@IOx4nV2x2-9JQW! z8&-sv%z5)I@JA#26%1SjptMXLN?KCi@fZBKM?^)JO^kJH4B*99l- zA@o0(AQ^1;`e7Mv#uoAZb1?E?x>SGjGT;1N{Y_-ZF6rOT>aKN6&ykibJ1Q%87}s4F zK5ua#m!204QruR$dSfBAV(+A3$;_DS%F*8kBKOg)@1U%XX)H{L>?nUDeY>}g?>_0? zkCdm`sZ+v-uf5Bs=C-lER~OqJ;d?-jCQ_ye!}1bXR@Q#M2Ob|5%z}?BL|rm@ukyVs z#*QLl_xs6f_foRh*Bm8$*Iuc5RLG3Y1wAUzfDiJ($( /dev/null | wc -l); then -if ! updates_aur=$(trizen -Su --aur --quiet | wc -l); then - updates_aur=0 -fi - -updates=$(("$updates_arch" + "$updates_aur")) - -if [ "$updates" -gt 0 ]; then - echo " $updates" -else - echo "" -fi diff --git a/polybar/.config/polybar/config b/polybar/.config/polybar/config index 4628cce..23fafb7 100644 --- a/polybar/.config/polybar/config +++ b/polybar/.config/polybar/config @@ -380,43 +380,46 @@ empty-notificaitons = false [module/updates-arch-combined] type = custom/script -exec = /bin/sh ~/.config/polybar/bin/updates-arch-combined/updates-arch-combined.sh + +exec = sh ~/.local/share/polybar-scripts/polybar-scripts/updates-arch-combined/updates-arch-combined.sh | tr -d "\#\ " interval = 600 click-left = alacritty -e update-arch label-foreground = ${colors.alert} +format-prefix = " " +format-prefix-foreground=${colors.alert} [module/player-mpris-tail] type = custom/script -exec = python ~/.config/polybar/bin/player-mpris-tail/player-mpris-tail.py -f '{:title: {icon} {artist} - {title}:}' --icon-playing '契' --icon-paused '' --icon-stop '栗' +exec = python ~/.local/share/polybar-scripts/polybar-scripts/player-mpris-tail/player-mpris-tail.py -f '{:title: {icon} {artist} - {title}:}' --icon-playing '契' --icon-paused '' --icon-stop '栗' tail = true -click-left = python ~/.config/polybar/bin/player-mpris-tail/player-mpris-tail.py previous & -click-right = python ~/.config/polybar/bin/player-mpris-tail/player-mpris-tail.py next & -click-middle = python ~/.config/polybar/bin/player-mpris-tail/player-mpris-tail.py play-pause & +click-left = python ~/.local/share/polybar-scripts/polybar-scripts/player-mpris-tail/player-mpris-tail.py previous & +click-right = python ~/.local/share/polybar-scripts/polybar-scripts/player-mpris-tail/player-mpris-tail.py next & +click-middle = python ~/.local/share/polybar-scripts/polybar-scripts/player-mpris-tail/player-mpris-tail.py play-pause & [module/bluetooth] type = custom/script -exec = /bin/sh ~/.config/polybar/bin/isactive-bluetooth +exec = ~/.config/polybar/bin/isactive-bluetooth click-left = ~/.config/polybar/bin/switch-bluetooth [module/rss] type = custom/script -exec = /bin/sh ~/.local/bin/rsscount +exec = ~/.local/bin/rsscount click-left = alacritty --class newsboat -e newsboat click-middle = newsup & [module/mail] type = custom/script -exec = /bin/sh ~/.local/bin/mailcount +exec = ~/.config/polybar/bin/mailcount click-left = alacritty -e neomutt click-middle = mailsync & [module/docker] type = custom/script -exec = dockerstatus +ebinxec = ~./local/share/polybar-scripts/polybar-scripts/dockerstatus interval = 1 label =  %output%