diff options
Diffstat (limited to 'bspwm/.local/bin')
| -rwxr-xr-x | bspwm/.local/bin/rofi_goto_workspace | 4 | ||||
| -rwxr-xr-x | bspwm/.local/bin/rofi_moveto_workspace | 4 | ||||
| -rwxr-xr-x | bspwm/.local/bin/rofi_workspace_prompt | 3 | ||||
| -rwxr-xr-x | bspwm/.local/bin/scratch | 3 | ||||
| -rwxr-xr-x | bspwm/.local/bin/spotifycl | 207 |
5 files changed, 221 insertions, 0 deletions
diff --git a/bspwm/.local/bin/rofi_goto_workspace b/bspwm/.local/bin/rofi_goto_workspace new file mode 100755 index 0000000..35e8762 --- /dev/null +++ b/bspwm/.local/bin/rofi_goto_workspace @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +NAME=`rofi_workspace_prompt` +i3-msg workspace $NAME diff --git a/bspwm/.local/bin/rofi_moveto_workspace b/bspwm/.local/bin/rofi_moveto_workspace new file mode 100755 index 0000000..9cc0b9d --- /dev/null +++ b/bspwm/.local/bin/rofi_moveto_workspace @@ -0,0 +1,4 @@ +#!/usr/bin/env bash + +NAME=`rofi_workspace_prompt` +i3-msg move container to workspace $NAME diff --git a/bspwm/.local/bin/rofi_workspace_prompt b/bspwm/.local/bin/rofi_workspace_prompt new file mode 100755 index 0000000..f59d1fa --- /dev/null +++ b/bspwm/.local/bin/rofi_workspace_prompt @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +echo `i3-msg -t get_workspaces | jq '.[].name' | sed 's/\"//g' | rofi -dmenu` diff --git a/bspwm/.local/bin/scratch b/bspwm/.local/bin/scratch new file mode 100755 index 0000000..9fd5901 --- /dev/null +++ b/bspwm/.local/bin/scratch @@ -0,0 +1,3 @@ +#!/usr/bin/sh +bspc query -N -n .floating > /tmp/scratchid +$SHELL diff --git a/bspwm/.local/bin/spotifycl b/bspwm/.local/bin/spotifycl new file mode 100755 index 0000000..ffee9f0 --- /dev/null +++ b/bspwm/.local/bin/spotifycl @@ -0,0 +1,207 @@ +#!/usr/bin/env python + +# MIT License +# +# Copyright (c) 2018 Andreas Backx +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + + +import os +import socket +import sys +import time +import traceback +from concurrent.futures import ThreadPoolExecutor + +import click +import dbus +import dbus.mainloop.glib +import spotipy +import spotipy.util as util +from dbus.mainloop.glib import DBusGMainLoop +from gi.repository import GLib +from spotipy import SpotifyException +from spotipy.oauth2 import SpotifyClientCredentials + +inactive_color = '%{F#6E6E6E}' +active_color = '%{F#CECECE}' +default_color = '%{F-}' + +server_address = '/tmp/spotifycl-socket' + + +class Spotify: + + SPOTIFY_BUS = 'org.mpris.MediaPlayer2.spotify' + SPOTIFYD_BUS = 'org.mpris.MediaPlayer2.spotifyd' + SPOTIFY_OBJECT_PATH = '/org/mpris/MediaPlayer2' + + PLAYER_INTERFACE = 'org.mpris.MediaPlayer2.Player' + PROPERTIES_INTERFACE = 'org.freedesktop.DBus.Properties' + + SAVE_REMOVE = b'save' + + def __init__(self): + DBusGMainLoop(set_as_default=True) + self.session_bus = dbus.SessionBus() + self.last_output = '' + self.empty_output = True + + # Last shown metadata + self.last_title = None + # Whether the current song is added to the library + self.saved_track = False + # Whether to ignore the update + self.ignore = False + + def monitor(self): + self.setup_properties_changed() + self.freedesktop = self.session_bus.get_object( + "org.freedesktop.DBus", + "/org/freedesktop/DBus" + ) + self.freedesktop.connect_to_signal( + "NameOwnerChanged", + self.on_name_owner_changed, + arg0=self.SPOTIFYD_BUS + ) + + executor = ThreadPoolExecutor(max_workers=2) + executor.submit(self._start_glib_loop) + executor.submit(self._start_server) + + def _start_glib_loop(self): + loop = GLib.MainLoop() + loop.run() + + def _start_server(self): + try: + os.unlink(server_address) + except OSError: + if os.path.exists(server_address): + raise + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + sock.bind(server_address) + sock.listen(5) + + @property + def metadata_status(self): + spotify_properties = dbus.Interface( + self.spotify, + dbus_interface=Spotify.PROPERTIES_INTERFACE + ) + metadata = spotify_properties.Get( + Spotify.PLAYER_INTERFACE, + 'Metadata' + ) + playback_status = spotify_properties.Get( + Spotify.PLAYER_INTERFACE, + 'PlaybackStatus' + ) + return metadata, playback_status + + def output(self, line): + if not line: + self.empty_output = True + if line != self.last_output: + print(line, flush=True) + self.last_output = line + + def setup_spotify(self): + try: + self.spotify = self.session_bus.get_object( + Spotify.SPOTIFY_BUS, + Spotify.SPOTIFY_OBJECT_PATH + ) + except dbus.DBusException: + self.spotify = self.session_bus.get_object(Spotify.SPOTIFYD_BUS, Spotify.SPOTIFY_OBJECT_PATH) + + def setup_properties_changed(self): + try: + self.setup_spotify() + self.spotify.connect_to_signal( + 'PropertiesChanged', + self.on_properties_changed + ) + + if self.empty_output: + metadata, playback_status = self.metadata_status + self.output_playback_status( + data={ + 'Metadata': metadata, + 'PlaybackStatus': playback_status, + } + ) + + except dbus.DBusException: + self.output('') + + def output_playback_status(self, data, retry=False): + if self.ignore: + return + + metadata = data['Metadata'] + artists = metadata['xesam:artist'] + artist = artists[0] if artists else None + + if not artist: + self.output('') + return + + title = metadata['xesam:title'] + playback_status = data['PlaybackStatus'] + same_song = title == self.last_title + + color = active_color if playback_status == 'Playing' else inactive_color + # divider = '+' if same_song and self.saved_track else '-' + self.output(f'{color}{artist} - {title}{default_color}') + + if not same_song: + self.last_title = title + + def on_properties_changed(self, interface, data, *args, **kwargs): + self.output_playback_status(data) + + def on_name_owner_changed(self, name, old_owner, new_owner): + if name == self.SPOTIFY_BUS: + if new_owner: + # Spotify was opened. + self.setup_properties_changed() + else: + # Spotify was closed. + self.spotify = None + self.output('') + + +@click.group() +def cli(): + """Script for listening to Spotify over dbus and adding tracks to your library.""" + pass + + +@cli.command() +def status(): + """Follow the status of the currently playing song on Spotify.""" + spotify = Spotify() + spotify.monitor() + + +if __name__ == '__main__': + cli() |
