From ca8a975fedacf1b1db0aaceafbd941c4c482a86e Mon Sep 17 00:00:00 2001 From: Peter Son Struschka Date: Mon, 3 Sep 2018 19:56:45 +0700 Subject: Added i3wm config --- i3wm/.bin/spotifycl | 299 ++++++++++++++++++++++++++ i3wm/.config/i3/config | 211 +++++++++++++++++++ i3wm/.config/polybar/config | 467 +++++++++++++++++++++++++++++++++++++++++ i3wm/.config/polybar/launch.sh | 12 ++ i3wm/.lock.png | Bin 0 -> 3959 bytes i3wm/.lock.sh | 15 ++ i3wm/.rick_lock.png | Bin 0 -> 113100 bytes i3wm/.wallpaper.jpg | Bin 0 -> 651668 bytes 8 files changed, 1004 insertions(+) create mode 100755 i3wm/.bin/spotifycl create mode 100644 i3wm/.config/i3/config create mode 100644 i3wm/.config/polybar/config create mode 100755 i3wm/.config/polybar/launch.sh create mode 100644 i3wm/.lock.png create mode 100755 i3wm/.lock.sh create mode 100644 i3wm/.rick_lock.png create mode 100644 i3wm/.wallpaper.jpg (limited to 'i3wm') diff --git a/i3wm/.bin/spotifycl b/i3wm/.bin/spotifycl new file mode 100755 index 0000000..4cd6943 --- /dev/null +++ b/i3wm/.bin/spotifycl @@ -0,0 +1,299 @@ +#!/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' + 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 + + #self.setup_spotipy() + + 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="org.mpris.MediaPlayer2.spotify" + ) + + 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) + + while True: + connection, client_address = sock.accept() + try: + command = connection.recv(16) + + if command == Spotify.SAVE_REMOVE: + self.save_remove() + except Exception as e: + print(e) + finally: + connection.close() + + def stop_server(self): + self.server_loop.close() + + def send_to_server(self, command: bytes): + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + try: + sock.connect(server_address) + except socket.error: + raise + + try: + sock.sendall(command) + finally: + sock.close() + + @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 setup_spotipy(self): + auth = util.prompt_for_user_token( + username=os.environ.get('SPOTIFY_USERNAME'), + scope='user-library-read,user-library-modify' + ) + self.spotipy = spotipy.Spotify(auth=auth) + + def save_remove(self, retry=False): + try: + metadata, playback_status = self.metadata_status + trackid = metadata['mpris:trackid'] + + self.ignore = True + remove = self.saved_track + self.saved_track = not self.saved_track + try: + if remove: + self.spotipy.current_user_saved_tracks_delete(tracks=[trackid]) + self.output(f'{active_color}Removed from library!{default_color}') + else: + self.spotipy.current_user_saved_tracks_add(tracks=[trackid]) + self.output(f'{active_color}Saved to library!{default_color}') + except SpotifyException: + if not retry: + # Refresh access token + self.setup_spotipy() + self.save_remove(retry=True) + return + else: + raise + time.sleep(2) + self.ignore = False + + metadata, playback_status = self.metadata_status + self.output_playback_status( + data={ + 'Metadata': metadata, + 'PlaybackStatus': playback_status, + } + ) + + except dbus.DBusException: + self.output('Could not connect to spotify.') + + 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): + self.spotify = self.session_bus.get_object( + Spotify.SPOTIFY_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 + trackid = metadata['mpris:trackid'] + + # try: + # self.update_saved_track(trackid=trackid) + # except SpotifyException: + # # Refresh access token + # self.setup_spotipy() + # self.update_saved_track(trackid=trackid) + # if self.saved_track: + # divider = '+' + # self.output(f'{color}{artist} {divider} {title}{default_color}') + + def update_saved_track(self, trackid: str): + self.saved_track = self.spotipy.current_user_saved_tracks_contains( + tracks=[trackid] + )[0] + + 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 == 'org.mpris.MediaPlayer2.spotify': + 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() + + +# @cli.command() +# def save_remove(): +# """Save/remove the currently playing song to/from your library.""" +# spotify = Spotify() +# spotify.send_to_server(Spotify.SAVE_REMOVE) + + +if __name__ == '__main__': + cli() diff --git a/i3wm/.config/i3/config b/i3wm/.config/i3/config new file mode 100644 index 0000000..714498b --- /dev/null +++ b/i3wm/.config/i3/config @@ -0,0 +1,211 @@ +# This file has been auto-generated by i3-config-wizard(1). +# It will not be overwritten, so edit it as you like. +# +# Should you change your keyboard layout some time, delete +# this file and re-run i3-config-wizard(1). +# + +# i3 config file (v4) +# +# Please see https://i3wm.org/docs/userguide.html for a complete reference! + +exec_always --no-startup-id $HOME/.config/polybar/launch.sh +exec_always --no-startup-id xautolock -locker "~/.lock.sh" -time 60 -detectsleep -notify 10 +exec --no-startup-id nm-applet +exec --no-startup-id compton + +set $mod Mod4 +exec_always --no-startup-id feh --bg-scale ~/.wallpaper.jpg +new_window 1pixel + +# Font for window titles. Will also be used by the bar unless a different font +# is used in the bar {} block below. +#font pango:monospace 8 + +# This font is widely installed, provides lots of unicode glyphs, right-to-left +# text rendering and scalability on retina/hidpi displays (thanks to pango). +font pango:DejaVu Sans Mono 8 + +# Before i3 v4.8, we used to recommend this one as the default: +# font -misc-fixed-medium-r-normal--13-120-75-75-C-70-iso10646-1 +# The font above is very space-efficient, that is, it looks good, sharp and +# clear in small sizes. However, its unicode glyph coverage is limited, the old +# X core fonts rendering does not support right-to-left and this being a bitmap +# font, it doesn’t scale on retina/hidpi displays. + +# Use Mouse+$mod to drag floating windows to their wanted position +floating_modifier $mod + +# start a terminal +bindsym $mod+Return exec kitty #i3-sensible-terminal + +# kill focused window +bindsym $mod+Shift+q kill + +# start dmenu (a program launcher) +bindsym $mod+d exec --no-startup-id rofi -show drun +bindsym $mod+x exec --no-startup-id rofi -show run + +bindsym $mod+Tab exec --no-startup-id rofi -show window + +# There also is the (new) i3-dmenu-desktop which only displays applications +# shipping a .desktop file. It is a wrapper around dmenu, so you need that +# installed. +#bindsym $mod+d exec --no-startup-id dmenu_run + +# change focus +bindsym $mod+j focus left +bindsym $mod+k focus down +bindsym $mod+l focus up +bindsym $mod+semicolon focus right + +# alternatively, you can use the cursor keys: +#bindsym $mod+Left focus left +bindsym $mod+Left workspace prev_on_output +bindsym $mod+Down focus down +bindsym $mod+Up focus up +#bindsym $mod+Right focus right +bindsym $mod+Right workspace next_on_output + +# move focused window +bindsym $mod+Shift+j move left +bindsym $mod+Shift+k move down +bindsym $mod+Shift+l move up +bindsym $mod+Shift+semicolon move right + +# alternatively, you can use the cursor keys: +bindsym $mod+Shift+Left move left +bindsym $mod+Shift+Down move down +bindsym $mod+Shift+Up move up +bindsym $mod+Shift+Right move right + +# split in horizontal orientation +bindsym $mod+h split h + +# split in vertical orientation +bindsym $mod+v split v + +# enter fullscreen mode for the focused container +bindsym $mod+f fullscreen toggle + +# change container layout (stacked, tabbed, toggle split) +bindsym $mod+s layout stacking +bindsym $mod+w layout tabbed +bindsym $mod+e layout toggle split + +# toggle tiling / floating +bindsym $mod+Shift+space floating toggle + +# change focus between tiling / floating windows +bindsym $mod+space focus mode_toggle + +# focus the parent container +bindsym $mod+a focus parent + +# focus the child container +#bindsym $mod+d focus child + +# Define names for default workspaces for which we configure key bindings later on. +# We use variables to avoid repeating the names in multiple places. +set $ws1 "1" +set $ws2 "2" +set $ws3 "3" +set $ws4 "4" +set $ws5 "5" +set $ws6 "6" +set $ws7 "7" +set $ws8 "8" +set $ws9 "9" +set $ws10 "10" + +# switch to workspace +bindsym $mod+1 workspace $ws1 +bindsym $mod+2 workspace $ws2 +bindsym $mod+3 workspace $ws3 +bindsym $mod+4 workspace $ws4 +bindsym $mod+5 workspace $ws5 +bindsym $mod+6 workspace $ws6 +bindsym $mod+7 workspace $ws7 +bindsym $mod+8 workspace $ws8 +bindsym $mod+9 workspace $ws9 +bindsym $mod+0 workspace $ws10 + +# move focused container to workspace +bindsym $mod+Shift+1 move container to workspace $ws1 +bindsym $mod+Shift+2 move container to workspace $ws2 +bindsym $mod+Shift+3 move container to workspace $ws3 +bindsym $mod+Shift+4 move container to workspace $ws4 +bindsym $mod+Shift+5 move container to workspace $ws5 +bindsym $mod+Shift+6 move container to workspace $ws6 +bindsym $mod+Shift+7 move container to workspace $ws7 +bindsym $mod+Shift+8 move container to workspace $ws8 +bindsym $mod+Shift+9 move container to workspace $ws9 +bindsym $mod+Shift+0 move container to workspace $ws10 + +# reload the configuration file +bindsym $mod+Shift+c reload +# restart i3 inplace (preserves your layout/session, can be used to upgrade i3) +bindsym $mod+Shift+r restart +# exit i3 (logs you out of your X session) +bindsym $mod+Shift+e exec "i3-nagbar -t warning -m 'You pressed the exit shortcut. Do you really want to exit i3? This will end your X session.' -b 'Yes, exit i3' 'i3-msg exit'" + +# resize window (you can also use the mouse for that) +mode "resize" { + # These bindings trigger as soon as you enter the resize mode + + # Pressing left will shrink the window’s width. + # Pressing right will grow the window’s width. + # Pressing up will shrink the window’s height. + # Pressing down will grow the window’s height. + bindsym j resize shrink width 10 px or 10 ppt + bindsym k resize grow height 10 px or 10 ppt + bindsym l resize shrink height 10 px or 10 ppt + bindsym semicolon resize grow width 10 px or 10 ppt + + # same bindings, but for the arrow keys + bindsym Left resize shrink width 10 px or 10 ppt + bindsym Down resize grow height 10 px or 10 ppt + bindsym Up resize shrink height 10 px or 10 ppt + bindsym Right resize grow width 10 px or 10 ppt + + # back to normal: Enter or Escape or $mod+r + bindsym Return mode "default" + bindsym Escape mode "default" + bindsym $mod+r mode "default" +} + +bindsym $mod+r mode "resize" + + + +bindsym XF86AudioLowerVolume exec --no-startup-id pactl set-sink-mute 0 false && pactl set-sink-volume 0 -5% +bindsym XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-mute 0 false && pactl set-sink-volume 0 +5% +bindsym XF86AudioMute exec --no-startup-id pactl set-sink-mute 0 toggle + +bindsym XF86MonBrightnessDown exec --no-startup-id brightnessctl s 5%- +bindsym XF86MonBrightnessUp exec --no-startup-id brightnessctl s +5% + + +bindsym XF86AudioPlay exec playerctl play-pause +bindsym XF86AudioPause exec playerctl pause +bindsym XF86AudioNext exec playerctl next +bindsym XF86AudioPrev exec playerctl previous + + +bindsym $mod+Control+l exec "xautolock -locknow" + + + +# Gaps + +gaps inner 10 +gaps outer 0 + + + +# Start i3bar to display a workspace bar (plus the system information i3status +# finds out, if available) +#bar { +# status_command i3status +# position top +#} diff --git a/i3wm/.config/polybar/config b/i3wm/.config/polybar/config new file mode 100644 index 0000000..e84be51 --- /dev/null +++ b/i3wm/.config/polybar/config @@ -0,0 +1,467 @@ +;========================================================== +; +; +; ██████╗ ██████╗ ██╗ ██╗ ██╗██████╗ █████╗ ██████╗ +; ██╔══██╗██╔═══██╗██║ ╚██╗ ██╔╝██╔══██╗██╔══██╗██╔══██╗ +; ██████╔╝██║ ██║██║ ╚████╔╝ ██████╔╝███████║██████╔╝ +; ██╔═══╝ ██║ ██║██║ ╚██╔╝ ██╔══██╗██╔══██║██╔══██╗ +; ██║ ╚██████╔╝███████╗██║ ██████╔╝██║ ██║██║ ██║ +; ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ +; +; +; To learn more about how to configure Polybar +; go to https://github.com/jaagr/polybar +; +; The README contains alot of information +; +;========================================================== + +[colors] +n;background = ${xrdb:color0:#222} +background = #222 +background-alt = #444 +;foreground = ${xrdb:color7:#222} +foreground = #dfdfdf +foreground-alt = #555 +primary = #ffb52a +secondary = #e60053 +alert = #bd2c40 + +[bar/topbar] +;monitor = ${env:MONITOR:HDMI-1} +width = 100% +height = 30 +;offset-x = 1% +;offset-y = 1% +radius = 6.0 +fixed-center = false + +background = ${colors.background} +foreground = ${colors.foreground} + +line-size = 3 +line-color = #f00 + +border-size = 10 +border-bottom-size = 0 +border-color = #00000000 + +padding-left = 0 +padding-right = 2 + +module-margin-left = 1 +module-margin-right = 2 + +font-0 = fixed:pixelsize=10;1 +font-1 = unifont:fontformat=truetype:size=8:antialias=false;0 +font-2 = siji:pixelsize=10;1 +font-3 = "Font Awesome 5 Brands:style=Regular:pixelsize=8;1" +font-4 = "Font Awesome 5 Free:style=Regular:pixelsize=8;1" +font-5 = "Font Awesome 5 Free:style=Solid:pixelsize=8;1" + +modules-left = i3 xwindow +modules-center = spotify +modules-right = filesystem backlight pulseaudio xkeyboard memory cpu wlan eth battery temperature date powermenu + +tray-position = right +tray-padding = 2 +;tray-transparent = true +;tray-background = #0063ff +tray-scale = 1 + +;wm-restack = bspwm +;wm-restack = i3 + +;override-redirect = true + +;scroll-up = bspwm-desknext +;scroll-down = bspwm-deskprev + +;scroll-up = i3wm-wsnext +;scroll-down = i3wm-wsprev + +cursor-click = pointer +cursor-scroll = ns-resize + + +[module/spotify] +type = custom/script +exec = spotifycl status +tail = true +format-foreground = ${colors.foreground-alt} +format-underline = ${colors.primary} +click-right = xte 'key XF86AudioPlay' +click-left = xte 'key XF86AudioPlay' +click-middle = xte 'key XF86AudioNext' +scroll-up = xte 'key XF86AudioNext' +scroll-down = xte 'key XF86AudioPrev' + + +[module/xwindow] +type = internal/xwindow +label = %title:0:30:...% + +[module/xkeyboard] +type = internal/xkeyboard +blacklist-0 = num lock + +format = +format-prefix = " " +format-prefix-foreground = ${colors.foreground} +format-prefix-underline = ${colors.secondary} + +label-layout = %name% +label-layout-underline = ${colors.secondary} + +label-indicator-padding = 2 +label-indicator-margin = 1 +label-indicator-background = ${colors.secondary} +label-indicator-underline = ${colors.secondary} + +[module/filesystem] +type = internal/fs +interval = 25 + +mount-0 = / + +label-mounted =  %{F#0a81f5}%mountpoint%%{F-}: %percentage_used%% +label-unmounted = %mountpoint% not mounted +label-unmounted-foreground = ${colors.foreground-alt} + +[module/bspwm] +type = internal/bspwm + +label-focused = %index% +label-focused-background = ${colors.background-alt} +label-focused-underline= ${colors.primary} +label-focused-padding = 2 + +label-occupied = %index% +label-occupied-padding = 2 + +label-urgent = %index%! +label-urgent-background = ${colors.alert} +label-urgent-padding = 2 + +label-empty = %index% +label-empty-foreground = ${colors.foreground-alt} +label-empty-padding = 2 + +; Separator in between workspaces +; label-separator = | + +[module/i3] +type = internal/i3 +format = +index-sort = true +wrapping-scroll = false + +; Only show workspaces on the same output as the bar +;pin-workspaces = true + +label-mode-padding = 2 +label-mode-foreground = #000 +label-mode-background = ${colors.primary} + +; focused = Active workspace on focused monitor +label-focused = %index% +label-focused-background = ${module/bspwm.label-focused-background} +label-focused-underline = ${module/bspwm.label-focused-underline} +label-focused-padding = ${module/bspwm.label-focused-padding} + +; unfocused = Inactive workspace on any monitor +label-unfocused = %index% +label-unfocused-padding = ${module/bspwm.label-occupied-padding} + +; visible = Active workspace on unfocused monitor +label-visible = %index% +label-visible-background = ${self.label-focused-background} +label-visible-underline = ${self.label-focused-underline} +label-visible-padding = ${self.label-focused-padding} + +; urgent = Workspace with urgency hint set +label-urgent = %index% +label-urgent-background = ${module/bspwm.label-urgent-background} +label-urgent-padding = ${module/bspwm.label-urgent-padding} + +; Separator in between workspaces +; label-separator = | + + +[module/mpd] +type = internal/mpd +format-online = + +icon-prev =  +icon-stop =  +icon-play =  +icon-pause =  +icon-next =  + +label-song-maxlen = 25 +label-song-ellipsis = true + +[module/backlight] +type = internal/backlight +card = intel_backlight +format =