+ Added bspwm, sxhkd, and polybar
This commit is contained in:
parent
29a1ca8ab2
commit
9a50ab1c1a
14 changed files with 1558 additions and 0 deletions
76
.config/bspwm/bspwmrc
Executable file
76
.config/bspwm/bspwmrc
Executable file
|
@ -0,0 +1,76 @@
|
|||
#! /bin/dash
|
||||
|
||||
sxhkd &
|
||||
xsetroot -cursor_name left_ptr &
|
||||
nitrogen --restore &
|
||||
compton &
|
||||
$HOME/.scripts/launch-conky.sh &
|
||||
$HOME/.config/polybar/launch.sh &
|
||||
|
||||
bspc monitor -d 1 2 3 4 5 6 7 8 9 10
|
||||
|
||||
primaryB = "#60C0FF"
|
||||
|
||||
bspc config border_width 2
|
||||
bspc config focused_border_color "#60C0FF"
|
||||
#bspc config normal_border_color $BORDER_NORMAL_COLOR
|
||||
#bspc config active_border_color $BORDER_NORMAL_COLOR
|
||||
bspc config active_border_color "#60C0ff"
|
||||
#bspc config normal_border_color
|
||||
bspc config window_gap 10
|
||||
bspc config top_padding 30
|
||||
bspc config bottom_padding 0
|
||||
bspc config left_padding 0
|
||||
bspc config right_padding 0
|
||||
bspc config single_monocle false
|
||||
bspc config click_to_focus true
|
||||
bspc config split_ratio 0.50
|
||||
bspc config borderless_monocle true
|
||||
bspc config gapless_monocle true
|
||||
bspc config focus_by_distance true
|
||||
bspc config focus_follows_pointer true
|
||||
bspc config history_aware_focus true
|
||||
bspc config remove_disabled_monitors true
|
||||
bspc config merge_overlapping_monitors true
|
||||
bspc config pointer_modifier mod4
|
||||
bspc config pointer_action1 move
|
||||
bspc config pointer_action2 resize_side
|
||||
bspc config pointer_action3 resize_corner
|
||||
|
||||
bspc rule -a Gimp desktop='^8' state=floating follow=on
|
||||
bspc rule -a firefox desktop='^2'
|
||||
bspc rule -a obs desktop='^3'
|
||||
bspc rule -a URxvt:cmus desktop='^4'
|
||||
bspc rule -a spotify desktop='^4'
|
||||
bspc rule -a Spotify desktop='^4'
|
||||
bspc rule -a mplayer2 state=floating
|
||||
bspc rule -a Kupfer.py focus=on
|
||||
bspc rule -a Screenkey manage=off
|
||||
bspc rule -a Kodi desktop='^3'
|
||||
bspc rule -a feh state=floating
|
||||
bspc rule -a lxappearance state=floating
|
||||
bspc rule -a Lxappearance state=floating
|
||||
bspc rule -a Steam desktop='^6'
|
||||
bspc rule -a steam desktop='^6'
|
||||
bspc rule -a gravitdesigner desktop='^8' state=floating
|
||||
bspc rule -a GravitDesigner desktop='^8' state=floating
|
||||
bspc rule -a electronplayer desktop='^3'
|
||||
bspc rule -a mcpelauncher-client desktop='^6' state=monocle
|
||||
bspc rule -a citra-qt desktop='^6'
|
||||
bspc rule -a Citra desktop='^6'
|
||||
bspc rule -a Citra:citra-qt desktop='^6'
|
||||
bspc rule -a org-tlauncher-tlauncher-rmo-TLauncher:sun-awt-X11-XFramePeer desktop='^6'
|
||||
bspc rule -a org-tlauncher-tlauncher-rmo-TLauncher desktop='^6'
|
||||
bspc rule -a PCSX2 desktop='^6'
|
||||
bspc rule -a whatsapp-nativefier-d52542 desktop='^9'
|
||||
bspc rule -a TelegramDesktop:telegram-desktop desktop='^9'
|
||||
bspc rule -a Brave-browser:brave-browser desktop='^2'
|
||||
bspc rule -a Code:code desktop='^5'
|
||||
bspc rule -a Wine:photoshop.exe desktop='^8'
|
||||
bspc rule -a File-roller:file-roller state=floating
|
||||
bspc rule -a PacketTracer7:PacketTracer7 desktop='^7' state=floating
|
||||
bspc rule -a discord:discord desktop='^9'
|
||||
bspc rule -a qTox:qtox desktop='^9'
|
||||
bspc rule -a pr:pr desktop='^10'
|
||||
bspc rule -a firefox:Toolkit desktop='^3' state=floating
|
||||
bspc rule -a mpv:gl state=floating
|
583
.config/polybar/config
Executable file
583
.config/polybar/config
Executable file
|
@ -0,0 +1,583 @@
|
|||
[global/wm]
|
||||
;https://github.com/jaagr/polybar/wiki/Configuration#global-wm-settings
|
||||
margin-top = 0
|
||||
margin-bottom = 0
|
||||
|
||||
[settings]
|
||||
;https://github.com/jaagr/polybar/wiki/Configuration#application-settings
|
||||
throttle-output = 5
|
||||
throttle-output-for = 10
|
||||
throttle-input-for = 30
|
||||
screenchange-reload = true
|
||||
compositing-background = over
|
||||
compositing-foreground = over
|
||||
compositing-overline = over
|
||||
compositing-underline = over
|
||||
compositing-border = over
|
||||
enable-ipc = true
|
||||
|
||||
; Define fallback values used by all module formats
|
||||
format-foreground = #FF0000
|
||||
format-background = #00FF00
|
||||
format-underline =
|
||||
format-overline =
|
||||
format-spacing =
|
||||
format-padding =
|
||||
format-margin =
|
||||
format-offset =
|
||||
|
||||
[colors]
|
||||
; My Scheme theme ============
|
||||
; D = Darker Color
|
||||
; L = Lighter Color
|
||||
background = #2f3640
|
||||
foreground = #f5f6fa
|
||||
foregroundD = #2f3640
|
||||
primary = #37b0ff
|
||||
primaryL1 = #60C0FF
|
||||
primaryL2 = #8DD2FE
|
||||
primaryD1 = #0EA0FF
|
||||
primaryD2 = #0299FB
|
||||
secondary1 = #4466ff
|
||||
secondary1L1 = #6B85FF
|
||||
secondary1L2 = #95A8FE
|
||||
secondary1D1 = #1D45FF
|
||||
secondary2 = #2affb9
|
||||
secondary2D1 = #00FFAB
|
||||
secondary2D3 = #00C282
|
||||
alert = #e84118
|
||||
volume-min = #a3be8c
|
||||
volume-med = #ebcb8b
|
||||
volume-max = #bf616a
|
||||
; =======================
|
||||
|
||||
[bar/bspwm]
|
||||
;monitor = ${env:MONITOR}
|
||||
;monitor-fallback = HDMI1
|
||||
width = 100%
|
||||
height = 30
|
||||
;offset-x = 1%
|
||||
;offset-y = 1%
|
||||
radius = 0.0
|
||||
fixed-center = true
|
||||
bottom = false
|
||||
separator =
|
||||
|
||||
background = ${colors.background}
|
||||
foreground = ${colors.foreground}
|
||||
|
||||
line-size = 2
|
||||
line-color = #f00
|
||||
|
||||
wm-restack = bspwm
|
||||
override-redirect = true
|
||||
|
||||
; Enable support for inter-process messaging
|
||||
; See the Messaging wiki page for more details.
|
||||
enable-ipc = true
|
||||
|
||||
border-size = 0
|
||||
;border-left-size = 0
|
||||
;border-right-size = 25
|
||||
;border-top-size = 0
|
||||
;border-bottom-size = 25
|
||||
border-color = #00000000
|
||||
|
||||
;padding-left =
|
||||
;padding-right =
|
||||
|
||||
module-margin-left = 0
|
||||
module-margin-right = 0
|
||||
|
||||
;https://github.com/jaagr/polybar/wiki/Fonts
|
||||
font-0 = "UbuntuMono Nerd Font:size=10;2"
|
||||
font-1 = "UbuntuMono Nerd Font:size=16;3"
|
||||
font-2 = "Sarasa Term J:bold:size=9;2"
|
||||
font-3 = "Nimbus Sans:bold:size=9;2"
|
||||
font-4 = "Iosevka Nerd Font:bold:size=9;2"
|
||||
font-5 = "FontAwesome5Free:bold:style=solid:size=9;2"
|
||||
|
||||
; ----------------------------------------------------------------------------------------
|
||||
modules-left = previous player-mpris player-mpris-tail mpd volume
|
||||
modules-center = bspwm
|
||||
modules-right = wirednetwork temp battery updates date prompt
|
||||
; ----------------------------------------------------------------------------------------
|
||||
|
||||
tray-detached = false
|
||||
tray-offset-x = 0
|
||||
tray-offset-y = 0
|
||||
tray-position = left
|
||||
tray-padding = 2
|
||||
tray-maxsize = 13
|
||||
tray-scale = 1.0
|
||||
tray-background = ${colors.secondary1D1}
|
||||
|
||||
scroll-up = bspwm-desknext
|
||||
scroll-down = bspwm-deskprev
|
||||
|
||||
# ----- Module -----
|
||||
[module/bspwm]
|
||||
type = internal/bspwm
|
||||
|
||||
enable-click = true
|
||||
enable-scroll = true
|
||||
reverse-scroll = true
|
||||
pin-workspaces = true
|
||||
|
||||
ws-icon-0 = 1;
|
||||
ws-icon-1 = 2;
|
||||
ws-icon-2 = 3;喇
|
||||
ws-icon-3 = 4;ﱘ
|
||||
ws-icon-4 = 5;
|
||||
ws-icon-5 = 6;
|
||||
ws-icon-6 = 7;
|
||||
ws-icon-7 = 8;
|
||||
ws-icon-8 = 9;
|
||||
ws-icon-9 = 10;
|
||||
ws-icon-default = " "
|
||||
|
||||
format-font = 5
|
||||
format = <label-state>
|
||||
format-background = #434758
|
||||
format-padding = 2
|
||||
|
||||
label-focused = %icon%
|
||||
;label-focused-background = #434758
|
||||
;label-focused-underline=
|
||||
label-focused-padding = 1
|
||||
label-focused-foreground = ${colors.primary}
|
||||
|
||||
label-occupied = %icon%
|
||||
;label-occupied-underline = #00a8ff
|
||||
label-occupied-padding = 1
|
||||
;label-occupied-background = #434758
|
||||
|
||||
label-urgent = %icon%
|
||||
label-urgent-padding = 1
|
||||
|
||||
label-empty = %icon%
|
||||
label-empty-foreground = #7f8fa6
|
||||
label-empty-padding = 1
|
||||
;label-empty-underline = #7f8fa6
|
||||
;label-empty-background = #434758
|
||||
|
||||
label-monocle = "ﬕ"
|
||||
label-monocle-padding = 2
|
||||
;label-monocle-background = #0097e6
|
||||
label-monocle-foreground = ${colors.foreground}
|
||||
label-tiled = ""
|
||||
label-tiled-padding = 2
|
||||
;label-tiled-background = #0097e6
|
||||
label-tiled-foreground = ${colors.foreground}
|
||||
label-fullscreen = ""
|
||||
label-fullscreen-padding = 2
|
||||
;label-fullscreen-background = #0097e6
|
||||
label-fullscreen-foreground = ${colors.foreground}
|
||||
label-floating = ""
|
||||
label-floating-padding = 2
|
||||
;label-floating-background = #0097e6
|
||||
label-floating-foreground = ${colors.foreground}
|
||||
label-pseudotiled = ""
|
||||
label-pseudotiled-padding = 2
|
||||
;label-pseudotiled-background = #0097e6
|
||||
label-pseudotiled-foreground = ${colors.foreground}
|
||||
label-locked = " "
|
||||
label-locked-foreground = ${colors.foreground}
|
||||
label-sticky = " "
|
||||
label-sticky-foreground = ${colors.foreground}
|
||||
label-private = " "
|
||||
label-private-foreground = ${colors.foreground}
|
||||
|
||||
; Separator in between workspaces
|
||||
;label-separator = |
|
||||
;label-separator-padding = 10
|
||||
;label-separator-foreground = #ffb52a
|
||||
|
||||
format-foreground = ${colors.foreground}
|
||||
;format-background = ${colors.background}
|
||||
|
||||
# ----- XWindow -----
|
||||
[module/xwindow]
|
||||
;https://github.com/jaagr/polybar/wiki/Module:-xwindow
|
||||
type = internal/xwindow
|
||||
|
||||
; Available tokens:
|
||||
; %title%
|
||||
; Default: %title%
|
||||
label-font = 3
|
||||
label = %title%
|
||||
label-maxlen = 50
|
||||
|
||||
format-prefix = " "
|
||||
format-foreground = ${colors.foreground}
|
||||
format-background = ${colors.background}
|
||||
|
||||
# ----- Spotify -----
|
||||
[module/spotify]
|
||||
;https://github.com/NicholasFeldman/dotfiles/blob/master/polybar/.config/polybar/spotify.sh
|
||||
type = custom/script
|
||||
#exec = ~/.config/polybar/scripts/spotify.sh
|
||||
interval = 1
|
||||
click-left = "dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.PlayPause"
|
||||
|
||||
;format = <label>
|
||||
format-foreground = ${colors.foreground}
|
||||
format-background = #44bd32
|
||||
format-padding = 2
|
||||
;format-underline = transparent
|
||||
format-prefix = " "
|
||||
format-prefix-foreground = ${colors.foreground}
|
||||
label-font = 3
|
||||
label = %output:0:22%
|
||||
|
||||
[module/previous]
|
||||
type = custom/script
|
||||
interval = 1
|
||||
format = "%{T3}<label>"
|
||||
format-padding = 2
|
||||
format-background = #4cd137
|
||||
format-foreground = ${colors.foreground}
|
||||
; Previous song icon
|
||||
#exec = $HOME/.config/polybar/scripts/spotprev.sh
|
||||
line-size = 1
|
||||
click-left = "dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Previous"
|
||||
|
||||
[module/next]
|
||||
type = custom/script
|
||||
interval = 1
|
||||
format = "%{T3}<label>"
|
||||
format-padding = 2
|
||||
format-background = #4cd137
|
||||
format-foreground = ${colors.foreground}
|
||||
; Next song icon
|
||||
#exec = ~/.config/polybar/scripts/spotnext.sh
|
||||
line-size = 1
|
||||
click-left = "dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Next"
|
||||
|
||||
[module/playpause]
|
||||
type = custom/ipc
|
||||
; Default
|
||||
hook-0 = echo ""
|
||||
; Playing
|
||||
hook-1 = echo ""
|
||||
; Paused
|
||||
hook-2 = echo ""
|
||||
initial = 1
|
||||
format-underline = #1db954
|
||||
line-size = 1
|
||||
click-left = "dbus-send --print-reply --dest=org.mpris.MediaPlayer2.spotify /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.PlayPause"
|
||||
|
||||
|
||||
# ----- Network -----
|
||||
[module/wirednetwork]
|
||||
type = internal/network
|
||||
interface = enp2s0
|
||||
|
||||
format-connected-foreground = ${colors.foreground}
|
||||
format-connected-background = ${colors.secondary2D3}
|
||||
format-connected-padding = 2
|
||||
format-connected-font = 1
|
||||
format-connected = <label-connected>
|
||||
|
||||
format-disconnected-foreground = ${colors.foreground}
|
||||
format-disconnected-background = ${colors.alert}
|
||||
format-disconnected-padding = 2
|
||||
format-disconnected = <label-disconnected>
|
||||
|
||||
format-padding = 2
|
||||
label-font = 1
|
||||
label-connected =
|
||||
label-disconnected =
|
||||
|
||||
# ----- Date / Time -----
|
||||
[module/date]
|
||||
type = internal/date
|
||||
|
||||
; Seconds to sleep between updates
|
||||
; Default: 1.0
|
||||
interval = 1.0
|
||||
|
||||
; See "http://en.cppreference.com/w/cpp/io/manip/put_time" for details on how to format the date string
|
||||
; NOTE: if you want to use syntax tags here you need to use %%{...}
|
||||
date = %d/%m/%y
|
||||
|
||||
; Optional time format
|
||||
time = %H:%M
|
||||
|
||||
; if `date-alt` or `time-alt` is defined, clicking
|
||||
; the module will toggle between formats
|
||||
date-alt = %A, %d %b
|
||||
time-alt = %H:%M
|
||||
|
||||
format-prefix = " "
|
||||
format = <label>
|
||||
format-background = ${colors.primary}
|
||||
format-foreground = ${colors.foreground}
|
||||
format-padding = 2
|
||||
label = %date% • %time%
|
||||
label-font = 3
|
||||
;label-foreground = #9A32DB
|
||||
|
||||
# ----- cmus -----
|
||||
[module/cmus]
|
||||
type = custom/script
|
||||
#exec-if = "pgrep -x cmus"
|
||||
#exec = ~/.config/polybar/scripts/player-cmus.sh
|
||||
interval = 1
|
||||
format-prefix = " "
|
||||
format = <label>
|
||||
format-foreground = ${colors.foreground}
|
||||
format-background = ${colors.secondary1L1}
|
||||
format-padding = 2
|
||||
label-font = 3
|
||||
click-left = "dbus-send --print-reply --dest=org.mpris.MediaPlayer2.cmus /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.PlayPause"
|
||||
; cmus-remote -n &
|
||||
click-right = cmus-remote -r &
|
||||
click-middle = cmus-remote -u &
|
||||
label = %output:0:22%
|
||||
|
||||
[module/cplaypause]
|
||||
type = custom/script
|
||||
#exec-if = "pgrep -x cmus"
|
||||
#exec = ~/.config/polybar/scripts/cmus.sh
|
||||
interval = 1
|
||||
format = <label>
|
||||
format-foreground = ${colors.foreground}
|
||||
format-background = ${colors.secondary1}
|
||||
format-padding = 1
|
||||
click-left = "dbus-send --print-reply --dest=org.mpris.MediaPlayer2.cmus /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.PlayPause"
|
||||
|
||||
|
||||
[module/cnext]
|
||||
type = custom/script
|
||||
#exec-if = "pgrep -x cmus"
|
||||
#exec = ~/.config/polybar/scripts/cnext.sh
|
||||
interval = 1
|
||||
format = <label>
|
||||
format-foreground = ${colors.foreground}
|
||||
format-background = ${colors.secondary1}
|
||||
format-padding = 1
|
||||
click-left = "dbus-send --print-reply --dest=org.mpris.MediaPlayer2.cmus /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Next"
|
||||
|
||||
[module/cprev]
|
||||
type = custom/script
|
||||
#exec-if = "pgrep cmus"
|
||||
#exec = ~/.config/polybar/scripts/cprev.sh
|
||||
interval = 1
|
||||
format = <label>
|
||||
format-foreground = ${colors.foreground}
|
||||
format-background = ${colors.secondary1}
|
||||
format-padding = 1
|
||||
click-left = "dbus-send --print-reply --dest=org.mpris.MediaPlayer2.cmus /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.Previous"
|
||||
|
||||
# ----- Music [MPris] -----
|
||||
|
||||
[module/player-mpris-tail]
|
||||
type = custom/script
|
||||
exec = ~/.config/polybar/scripts/player-mpris-tail.py -f '{:artist:t10:{artist}:}{:artist: - :}{:t10:{title}:}'
|
||||
tail = true
|
||||
label-font = 3
|
||||
format-prefix = " "
|
||||
format-foreground = ${colors.foreground}
|
||||
format-background = ${colors.secondary1L1}
|
||||
format-padding = 2
|
||||
click-left = ~/.config/polybar/scripts/player-mpris-tail.py play-pause &
|
||||
scroll-up = ~/.config/polybar/scripts/player-mpris-tail.py next &
|
||||
scroll-down = ~/.config/polybar/scripts/player-mpris-tail.py previous &
|
||||
|
||||
[module/player-mpris]
|
||||
type = custom/script
|
||||
exec = ~/.config/polybar/scripts/player-mpris-tail.py -f '%{A1:~/.config/polybar/scripts/player-mpris-tail.py previous:} 玲 %{A} %{A1:~/.config/polybar/scripts/player-mpris-tail.py play-pause:} {icon-reversed} %{A} %{A1:~/.config/polybar/scripts/player-mpris-tail.py next:} 怜 %{A}' --icon-paused --icon-playing 契
|
||||
tail = true
|
||||
label-font = 1
|
||||
format-foreground = ${colors.foreground}
|
||||
format-background = ${colors.secondary1}
|
||||
format-padding = 1
|
||||
|
||||
|
||||
|
||||
# ----- Music [MPD] -----
|
||||
|
||||
[module/mpd]
|
||||
type = internal/mpd
|
||||
|
||||
; Host where mpd is running (either ip or domain name)
|
||||
; Can also be the full path to a unix socket where mpd is running.
|
||||
host = localhost
|
||||
port = 6600
|
||||
|
||||
format-online-padding = 2
|
||||
format-online-prefix = " "
|
||||
format-online = <label-song>
|
||||
format-online-foreground = ${colors.foreground}
|
||||
format-online-background = ${colors.secondary1L1}
|
||||
label-song-font = 3
|
||||
label-song = %artist% - %title:0:10%
|
||||
click-left = "dbus-send --print-reply --dest=org.mpris.MediaPlayer2.mpd /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.PlayPause"
|
||||
[module/mpdplaypause]
|
||||
type = internal/mpd
|
||||
|
||||
; Host where mpd is running (either ip or domain name)
|
||||
; Can also be the full path to a unix socket where mpd is running.
|
||||
host = localhost
|
||||
port = 6600
|
||||
|
||||
format-online-padding = 2
|
||||
format-online-prefix = " "
|
||||
format-online = <label-song>
|
||||
format-online-foreground = ${colors.foreground}
|
||||
format-online-background = ${colors.secondary1L1}
|
||||
label-song-font = 3
|
||||
label-song = %artist% - %title:0:10%
|
||||
click-left = "dbus-send --print-reply --dest=org.mpris.MediaPlayer2.mpd /org/mpris/MediaPlayer2 org.mpris.MediaPlayer2.Player.PlayPause"
|
||||
|
||||
# ----- Volume Tail -----
|
||||
[module/vol-tail]
|
||||
type = custom/script
|
||||
exec = ~/.config/polybar/scripts/pulseaudio-tail.sh
|
||||
tail = true
|
||||
click-right = exec pavucontrol &
|
||||
click-left = ~/polybar-scripts/pulseaudio-tail.sh --mute &
|
||||
scroll-up = ~/polybar-scripts/pulseaudio-tail.sh --up &
|
||||
scroll-down = ~/polybar-scripts/pulseaudio-tail.sh --down &
|
||||
|
||||
# ----- Volume -----
|
||||
[module/volume]
|
||||
type = internal/pulseaudio
|
||||
|
||||
; Sink to be used, if it exists (find using `pacmd list-sinks`, name field)
|
||||
; If not, uses default sink
|
||||
sink = alsa_output.pci-0000_00_1b.0.analog-stereo
|
||||
|
||||
; Use PA_VOLUME_UI_MAX (~153%) if true, or PA_VOLUME_NORM (100%) if false
|
||||
; Default: true
|
||||
use-ui-max = false
|
||||
|
||||
; Interval for volume increase/decrease (in percent points)
|
||||
; Default: 5
|
||||
interval = 5
|
||||
|
||||
format-muted-foreground = ${colors.foreground}
|
||||
format-muted-background = #434758
|
||||
format-muted = ﱝ <label-muted>
|
||||
format-muted-padding = 2
|
||||
format-volume-foreground = ${colors.foreground}
|
||||
format-volume-background = #434758
|
||||
format-volume = <ramp-volume> <label-volume>
|
||||
format-volume-padding = 2
|
||||
|
||||
label-volume-font = 3
|
||||
|
||||
label-muted-font = 3
|
||||
label-muted = M
|
||||
label-muted-foreground = ${colors.alert}
|
||||
|
||||
; Only applies if <ramp-volume> is used
|
||||
ramp-volume-0 = 奄
|
||||
ramp-volume-1 = 奔
|
||||
ramp-volume-2 = 墳
|
||||
|
||||
# ----- Updates -----
|
||||
|
||||
[module/updates]
|
||||
type = custom/script
|
||||
exec = ~/.config/polybar/scripts/updates.sh
|
||||
label-font = 3
|
||||
format-prefix = "ﮮ "
|
||||
format-padding = 2
|
||||
format-background = ${colors.primaryD1}
|
||||
format-foreground = ${colors.foreground}
|
||||
interval = 600
|
||||
|
||||
# ----- Prompt -----
|
||||
[module/prompt]
|
||||
type = custom/script
|
||||
interval = 1
|
||||
format = "<label>"
|
||||
format-padding = 2
|
||||
format-background = ${colors.primaryL1}
|
||||
format-foreground = ${colors.foreground}
|
||||
exec = echo ""
|
||||
click-left = sh ~/.scripts/prompt
|
||||
|
||||
# ----- Battery -----
|
||||
[module/battery]
|
||||
type = internal/battery
|
||||
|
||||
; This is useful in case the battery never reports 100% charge
|
||||
full-at = 99
|
||||
|
||||
; Use the following command to list batteries and adapters:
|
||||
; $ ls -1 /sys/class/power_supply/
|
||||
battery = BAT0
|
||||
adapter = ADP1
|
||||
|
||||
poll-interval = 5
|
||||
|
||||
format-charging = <animation-charging> ""
|
||||
format-discharging = <ramp-capacity>
|
||||
format = <label>
|
||||
format-background = ${colors.primary}
|
||||
format-foreground = ${colors.foreground}
|
||||
|
||||
label =
|
||||
ramp-capacity-0 =
|
||||
ramp-capacity-1 =
|
||||
ramp-capacity-2 =
|
||||
ramp-capacity-3 =
|
||||
ramp-capacity-4 =
|
||||
|
||||
animation-charging-0 =
|
||||
animation-charging-1 =
|
||||
animation-charging-2 =
|
||||
animation-charging-3 =
|
||||
animation-charging-4 =
|
||||
animation-charging-framerate = 750
|
||||
|
||||
[module/temp]
|
||||
type = internal/temperature
|
||||
|
||||
; Seconds to sleep between updates
|
||||
; Default: 1
|
||||
interval = 0.5
|
||||
|
||||
; Thermal zone to use
|
||||
; To list all the zone types, run
|
||||
; $ for i in /sys/class/thermal/thermal_zone*; do echo "$i: $(<$i/type)"; done
|
||||
; Default: 0
|
||||
thermal-zone = 0
|
||||
|
||||
; Full path of temperature sysfs path
|
||||
; Use `sensors` to find preferred temperature source, then run
|
||||
; $ for i in /sys/class/hwmon/hwmon*/temp*_input; do echo "$(<$(dirname $i)/name): $(cat ${i%_*}_label 2>/dev/null || echo $(basename ${i%_*})) $(readlink -f $i)"; done
|
||||
; to find path to desired file
|
||||
; Default reverts to thermal zone setting
|
||||
hwmon-path = /sys/devices/virtual/thermal/thermal_zone0/hwmon0/temp3_input
|
||||
|
||||
; Base temperature for where to start the ramp (in degrees celsius)
|
||||
; Default: 0
|
||||
base-temperature = 0
|
||||
|
||||
; Threshold temperature to display warning label (in degrees celsius)
|
||||
; Default: 80
|
||||
warn-temperature = 100
|
||||
|
||||
format = <ramp> <label>
|
||||
format-background = ${colors.primaryD2}
|
||||
;format-warn = <ramp> <label-warn>
|
||||
;format-warn-padding = 2
|
||||
;format-warn-background = ${colors.primaryD2}
|
||||
format-padding = 2
|
||||
|
||||
label-font = 5
|
||||
label = %temperature-c%
|
||||
;label-warn-font = 5
|
||||
;label-warn = %temperature-c%
|
||||
;label-warn-foreground = ${colors.urgent}
|
||||
|
||||
ramp-font = 7
|
||||
ramp-0 =
|
||||
ramp-1 =
|
||||
ramp-2 =
|
||||
ramp-foreground = ${colors.foreground}
|
||||
|
13
.config/polybar/launch.sh
Executable file
13
.config/polybar/launch.sh
Executable file
|
@ -0,0 +1,13 @@
|
|||
#!/bin/dash
|
||||
|
||||
# Terminate already running bar instances
|
||||
killall -q polybar
|
||||
|
||||
# Wait until the processes have been shut down
|
||||
while pgrep -u $UID -x polybar >/dev/null; do sleep 1; done
|
||||
|
||||
# Launch Polybar, using default config location ~/.config/polybar/config
|
||||
polybar bspwm &
|
||||
|
||||
echo "Polybar launched..."
|
||||
|
15
.config/polybar/scripts/cmus.sh
Executable file
15
.config/polybar/scripts/cmus.sh
Executable file
|
@ -0,0 +1,15 @@
|
|||
#!/bin/dash
|
||||
main() {
|
||||
status=$(cmus-remote -Q | grep "status")
|
||||
if [ "$status" = "status playing" ]; then
|
||||
echo ""
|
||||
elif [ "$status" = "status paused" ]; then
|
||||
echo "契"
|
||||
elif [ "$status" = "status stopped" ]; then
|
||||
echo "栗"
|
||||
else
|
||||
echo ""
|
||||
fi
|
||||
echo $status
|
||||
}
|
||||
main "$@"
|
7
.config/polybar/scripts/cnext.sh
Executable file
7
.config/polybar/scripts/cnext.sh
Executable file
|
@ -0,0 +1,7 @@
|
|||
#!/bin/sh
|
||||
|
||||
main() {
|
||||
echo "怜 "
|
||||
}
|
||||
|
||||
main "$@"
|
7
.config/polybar/scripts/cprev.sh
Executable file
7
.config/polybar/scripts/cprev.sh
Executable file
|
@ -0,0 +1,7 @@
|
|||
#!/bin/sh
|
||||
|
||||
main() {
|
||||
echo " 玲"
|
||||
}
|
||||
|
||||
main "$@"
|
38
.config/polybar/scripts/player-cmus.sh
Executable file
38
.config/polybar/scripts/player-cmus.sh
Executable file
|
@ -0,0 +1,38 @@
|
|||
#!/bin/sh
|
||||
|
||||
if info=$(cmus-remote -Q 2> /dev/null); then
|
||||
status=$(echo "$info" | grep -v "set " | grep -v "tag " | grep "status " | cut -d ' ' -f 2)
|
||||
|
||||
if [ "$status" = "playing" ] || [ "$status" = "paused" ] || [ "$status" = "stopped" ]; then
|
||||
title=$(echo "$info" | grep -v 'set ' | grep " title " | cut -d ' ' -f 3-)
|
||||
artist=$(echo "$info" | grep -v 'set ' | grep " artist " | cut -d ' ' -f 3-)
|
||||
position=$(echo "$info" | grep -v "set " | grep -v "tag " | grep "position " | cut -d ' ' -f 2)
|
||||
duration=$(echo "$info" | grep -v "set " | grep -v "tag " | grep "duration " | cut -d ' ' -f 2)
|
||||
|
||||
if [ "$duration" -ge 0 ]; then
|
||||
pos_minutes=$(printf "%02d" $((position / 60)))
|
||||
pos_seconds=$(printf "%02d" $((position % 60)))
|
||||
|
||||
dur_minutes=$(printf "%02d" $((duration / 60)))
|
||||
dur_seconds=$(printf "%02d" $((duration % 60)))
|
||||
|
||||
info_string="| $pos_minutes:$pos_seconds / $dur_minutes:$dur_seconds"
|
||||
fi
|
||||
|
||||
info_string="$artist - $title"
|
||||
|
||||
if [ "$status" = "playing" ]; then
|
||||
echo "$info_string"
|
||||
elif [ "$status" = "paused" ]; then
|
||||
echo "$info_string"
|
||||
elif [ "$status" = "stopped" ]; then
|
||||
echo "$info_string"
|
||||
else
|
||||
echo ""
|
||||
fi
|
||||
else
|
||||
echo ""
|
||||
fi
|
||||
else
|
||||
echo ""
|
||||
fi
|
527
.config/polybar/scripts/player-mpris-tail.py
Executable file
527
.config/polybar/scripts/player-mpris-tail.py
Executable file
|
@ -0,0 +1,527 @@
|
|||
#!/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<tag>.*?)(:(?P<format>[wt])(?P<formatlen>\d+))?:(?P<text>.*?):\})', re.I)
|
||||
FORMAT_TAG_REGEX = re.compile(r'(?P<format>[wt])(?P<formatlen>\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:
|
||||
# Obtain properties from _metadata
|
||||
_artist = _getProperty(self._metadata, 'xesam:artist', [''])
|
||||
_album = _getProperty(self._metadata, 'xesam:album', '')
|
||||
_title = _getProperty(self._metadata, 'xesam:title', '')
|
||||
_track = _getProperty(self._metadata, 'xesam:trackNumber', '')
|
||||
_genre = _getProperty(self._metadata, 'xesam:genre', [''])
|
||||
_disc = _getProperty(self._metadata, 'xesam:discNumber', '')
|
||||
_length = _getProperty(self._metadata, 'xesam:length', 0) or _getProperty(self._metadata, 'mpris:length', 0)
|
||||
_length_int = _length if type(_length) is int else int(float(_length))
|
||||
_date = _getProperty(self._metadata, 'xesam:contentCreated', '')
|
||||
_year = _date[0:4] if len(_date) else ''
|
||||
_url = _getProperty(self._metadata, 'xesam:url', '')
|
||||
_cover = _getProperty(self._metadata, 'xesam:artUrl', '') or _getProperty(self._metadata, 'mpris:artUrl', '')
|
||||
_duration = _getDuration(_length_int)
|
||||
# Update metadata
|
||||
self.metadata['artist'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _firstIfList(_artist))
|
||||
self.metadata['album'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _firstIfList(_album))
|
||||
self.metadata['title'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _firstIfList(_title))
|
||||
self.metadata['track'] = _track
|
||||
self.metadata['genre'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _firstIfList(_genre))
|
||||
self.metadata['disc'] = _disc
|
||||
self.metadata['date'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _date)
|
||||
self.metadata['year'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _year)
|
||||
self.metadata['url'] = _url
|
||||
self.metadata['filename'] = os.path.basename(_url)
|
||||
self.metadata['length'] = _length_int
|
||||
self.metadata['cover'] = re.sub(SAFE_TAG_REGEX, """\1\1""", _firstIfList(_cover))
|
||||
self.metadata['duration'] = _duration
|
||||
|
||||
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))
|
||||
|
||||
def _firstIfList(_value):
|
||||
return _value[0] if type(_value) is list and len(_value) else _value
|
||||
|
||||
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\1p\2p\3p', 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()
|
66
.config/polybar/scripts/pulseaudio-tail.sh
Executable file
66
.config/polybar/scripts/pulseaudio-tail.sh
Executable file
|
@ -0,0 +1,66 @@
|
|||
#!/bin/sh
|
||||
|
||||
update_sink() {
|
||||
sink = alsa_output.pci-0000_00_1b.0.analog-stereo
|
||||
}
|
||||
|
||||
volume_up() {
|
||||
update_sink
|
||||
pactl set-sink-volume "$sink" +1%
|
||||
}
|
||||
|
||||
volume_down() {
|
||||
update_sink
|
||||
pactl set-sink-volume "$sink" -1%
|
||||
}
|
||||
|
||||
volume_mute() {
|
||||
update_sink
|
||||
pactl set-sink-mute "$sink" toggle
|
||||
}
|
||||
|
||||
volume_print() {
|
||||
update_sink
|
||||
|
||||
active_port=$(pacmd list-sinks | sed -n "/index: $sink/,/index:/p" | grep active)
|
||||
if echo "$active_port" | grep -q speaker; then
|
||||
icon="#1"
|
||||
elif echo "$active_port" | grep -q headphones; then
|
||||
icon="#2"
|
||||
else
|
||||
icon="#3"
|
||||
fi
|
||||
|
||||
muted=$(pamixer --sink "$sink" --get-mute)
|
||||
|
||||
if [ "$muted" = true ]; then
|
||||
echo "$icon --"
|
||||
else
|
||||
echo "$icon $(pamixer --sink "$sink" --get-volume)"
|
||||
fi
|
||||
}
|
||||
|
||||
listen() {
|
||||
volume_print
|
||||
|
||||
pactl subscribe | while read -r event; do
|
||||
if echo "$event" | grep -qv "Client"; then
|
||||
volume_print
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
case "$1" in
|
||||
--up)
|
||||
volume_up
|
||||
;;
|
||||
--down)
|
||||
volume_down
|
||||
;;
|
||||
--mute)
|
||||
volume_mute
|
||||
;;
|
||||
*)
|
||||
listen
|
||||
;;
|
||||
esac
|
25
.config/polybar/scripts/spotify.sh
Executable file
25
.config/polybar/scripts/spotify.sh
Executable file
|
@ -0,0 +1,25 @@
|
|||
#!/bin/sh
|
||||
|
||||
main() {
|
||||
|
||||
if ! pgrep -x spotify >/dev/null; then
|
||||
echo "";exit
|
||||
fi
|
||||
|
||||
|
||||
cmd="org.freedesktop.DBus.Properties.Get"
|
||||
domain="org.mpris.MediaPlayer2"
|
||||
path="/org/mpris/MediaPlayer2"
|
||||
|
||||
meta=$(dbus-send --print-reply --dest=${domain}.spotify \
|
||||
/org/mpris/MediaPlayer2 org.freedesktop.DBus.Properties.Get string:${domain}.Player string:Metadata)
|
||||
|
||||
artist=$(echo "$meta" | sed -nr '/xesam:artist"/,+2s/^ +string "(.*)"$/\1/p' | tail -1 | sed 's/\&/\\&/g' | sed 's#\/#\\/#g')
|
||||
album=$(echo "$meta" | sed -nr '/xesam:album"/,+2s/^ +variant +string "(.*)"$/\1/p' | tail -1| sed 's/\&/\\&/g'| sed 's#\/#\\/#g')
|
||||
title=$(echo "$meta" | sed -nr '/xesam:title"/,+2s/^ +variant +string "(.*)"$/\1/p' | tail -1 | sed 's/\&/\\&/g'| sed 's#\/#\\/#g')
|
||||
|
||||
echo "${*:-%artist% - %title%}" | sed "s/%artist%/$artist/g;s/%title%/$title/g;s/%album%/$album/g"i | sed "s/\&/\&/g" | sed "s#\/#\/#g"
|
||||
|
||||
}
|
||||
|
||||
main "$@"
|
11
.config/polybar/scripts/spotnext.sh
Executable file
11
.config/polybar/scripts/spotnext.sh
Executable file
|
@ -0,0 +1,11 @@
|
|||
#!/bin/sh
|
||||
|
||||
main() {
|
||||
if ! pgrep -x spotify >/dev/null; then
|
||||
echo "";exit
|
||||
fi
|
||||
|
||||
echo "怜"
|
||||
}
|
||||
|
||||
main "$@"
|
11
.config/polybar/scripts/spotprev.sh
Executable file
11
.config/polybar/scripts/spotprev.sh
Executable file
|
@ -0,0 +1,11 @@
|
|||
#!/bin/sh
|
||||
|
||||
main() {
|
||||
if ! pgrep -x spotify >/dev/null; then
|
||||
echo "";exit
|
||||
fi
|
||||
|
||||
echo " 玲"
|
||||
}
|
||||
|
||||
main "$@"
|
21
.config/polybar/scripts/updates.sh
Executable file
21
.config/polybar/scripts/updates.sh
Executable file
|
@ -0,0 +1,21 @@
|
|||
#!/bin/sh
|
||||
|
||||
if ! updates_arch=$(checkupdates 2> /dev/null | wc -l ); then
|
||||
updates_arch=0
|
||||
fi
|
||||
|
||||
if ! updates_aur=$(yay -Qum 2> /dev/null | wc -l); then
|
||||
# if ! updates_aur=$(cower -u 2> /dev/null | wc -l); then
|
||||
# if ! updates_aur=$(trizen -Su --aur --quiet | wc -l); then
|
||||
# if ! updates_aur=$(pikaur -Qua 2> /dev/null | wc -l); then
|
||||
# if ! updates_aur=$(rua upgrade --printonly 2> /dev/null | wc -l); then
|
||||
updates_aur=0
|
||||
fi
|
||||
|
||||
updates=$(("$updates_arch" + "$updates_aur"))
|
||||
|
||||
if [ "$updates" -gt 0 ]; then
|
||||
echo "$updates"
|
||||
else
|
||||
echo ""
|
||||
fi
|
158
.config/sxhkd/sxhkdrc
Executable file
158
.config/sxhkd/sxhkdrc
Executable file
|
@ -0,0 +1,158 @@
|
|||
#
|
||||
# wm independent hotkeys
|
||||
#
|
||||
|
||||
# terminal emulator
|
||||
super + Return
|
||||
urxvt
|
||||
|
||||
super + alt + t
|
||||
urxvt
|
||||
|
||||
# program launcher
|
||||
super + space
|
||||
rofi -show drun -theme ~/.config/rofi/theme/Android/grid.rasi
|
||||
|
||||
# make sxhkd reload its configuration files:
|
||||
super + Escape
|
||||
pkill -USR1 -x sxhkd
|
||||
|
||||
#
|
||||
# bspwm hotkeys
|
||||
#
|
||||
|
||||
# prompt (restart/suspend/shutdown/logout)
|
||||
super + control + q
|
||||
sh $HOME/.scripts/prompt
|
||||
|
||||
super + control + r
|
||||
sh $HOME/.scripts/resolution.sh
|
||||
|
||||
# quit/restart bspwm
|
||||
super + alt + {q,r}
|
||||
bspc {quit,wm -r}
|
||||
|
||||
# close and kill
|
||||
super + {_,shift + }q
|
||||
bspc node -{c,k}
|
||||
|
||||
# alternate between the tiled and monocle layout
|
||||
super + Tab
|
||||
bspc desktop -l next
|
||||
|
||||
# send the newest marked node to the newest preselected node
|
||||
super + y
|
||||
bspc node newest.marked.local -n newest.!automatic.local
|
||||
|
||||
# swap the current node and the biggest node
|
||||
super + g
|
||||
bspc node -s biggest
|
||||
|
||||
#
|
||||
# state/flags
|
||||
#
|
||||
|
||||
# set the window state
|
||||
super + {t,shift + t,s,f}
|
||||
bspc node -t {tiled,pseudo_tiled,floating,fullscreen}
|
||||
|
||||
# set the node flags
|
||||
super + ctrl + {m,x,y,z}
|
||||
bspc node -g {marked,locked,sticky,private}
|
||||
|
||||
#
|
||||
# focus/swap
|
||||
#
|
||||
|
||||
# focus the node in the given direction
|
||||
super + {_,shift + }{j,k,i,l}
|
||||
bspc node -{f,s} {west,south,north,east}
|
||||
|
||||
# focus the node for the given path jump
|
||||
super + {p,b,comma,period}
|
||||
bspc node -f @{parent,brother,first,second}
|
||||
|
||||
# focus the next/previous node in the current desktop
|
||||
super + {_,shift + }c
|
||||
bspc node -f {next,prev}.local
|
||||
|
||||
# focus the next/previous desktop in the current monitor
|
||||
super + bracket{left,right}
|
||||
bspc desktop -f {prev,next}.local
|
||||
|
||||
# focus the last node/desktop
|
||||
super + grave
|
||||
bspc desktop -f last
|
||||
|
||||
# focus the older or newer node in the focus history
|
||||
super + {o,i}
|
||||
bspc wm -h off; \
|
||||
bspc node {older,newer} -f; \
|
||||
bspc wm -h on
|
||||
|
||||
# focus or send to the given desktop
|
||||
super + {_,shift + }{1-9,0}
|
||||
bspc {desktop -f,node -d} '^{1-9,10}'
|
||||
|
||||
#
|
||||
# preselect
|
||||
#
|
||||
|
||||
# preselect the direction
|
||||
super + ctrl + {j,k,i,l}
|
||||
bspc node -p {west,south,north,east}
|
||||
|
||||
# preselect the ratio
|
||||
super + ctrl + {1-9}
|
||||
bspc node -o 0.{1-9}
|
||||
|
||||
# cancel the preselection for the focused node
|
||||
super + ctrl + space
|
||||
bspc node -p cancel
|
||||
|
||||
# cancel the preselection for the focused desktop
|
||||
super + ctrl + shift + space
|
||||
bspc query -N -d | xargs -I id -n 1 bspc node id -p cancel
|
||||
|
||||
#
|
||||
# move/resize
|
||||
#
|
||||
|
||||
# expand a window by moving one of its side outward
|
||||
super + alt + {j,k,i,l}
|
||||
bspc node -z {left -20 0,bottom 0 20,top 0 -20,right 20 0}
|
||||
|
||||
# contract a window by moving one of its side inward
|
||||
super + alt + shift + {j,k,i,l}
|
||||
bspc node -z {right -20 0,top 0 20,bottom 0 -20,left 20 0}
|
||||
|
||||
# move a floating window
|
||||
super + {Left,Down,Up,Right}
|
||||
bspc node -v {-20 0,0 20,0 -20,20 0}
|
||||
|
||||
## application launchers
|
||||
# music
|
||||
super + alt + m
|
||||
sh $HOME/.scripts/musicplayer.sh
|
||||
# video/media player
|
||||
super + alt + v
|
||||
sh $HOME/.scripts/video.sh
|
||||
# games
|
||||
super + alt + p
|
||||
sh $HOME/.scripts/play.sh
|
||||
# firefox
|
||||
super + alt + b
|
||||
firefox
|
||||
# passmenu
|
||||
alt + y
|
||||
passmenu
|
||||
# screenshot
|
||||
super + Print
|
||||
sh $HOME/.scripts/ss.sh
|
||||
# gravit-designer
|
||||
super + alt + g
|
||||
"$HOME/my Files/Gravit/GravitDesigner.AppImage"
|
||||
# volume
|
||||
super + alt + control + v
|
||||
sh $HOME/.scripts/volume.sh
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue