From 58dd2f63f61df49dfd65e3aaff80e93babd255d3 Mon Sep 17 00:00:00 2001 From: Liam Waldron Date: Thu, 14 Sep 2023 08:01:22 -0400 Subject: [PATCH] hi --- config | 86 ++++++++++---- config.ltop => config.i3 | 86 ++++++++++---- fehbg | 4 + i3blocks/config | 96 ++++++++++++++++ i3blocks/scripts/arch-update | 155 ++++++++++++++++++++++++++ i3blocks/scripts/batterybar | 137 +++++++++++++++++++++++ i3blocks/scripts/disk | 48 ++++++++ i3blocks/scripts/dunst | 40 +++++++ i3blocks/scripts/mediaplayer | 159 ++++++++++++++++++++++++++ i3blocks/scripts/playerctl | 43 +++++++ i3blocks/scripts/shutdown_menu | 186 +++++++++++++++++++++++++++++++ i3blocks/scripts/volume | 91 +++++++++++++++ i3blocks/scripts/volume-pipewire | 172 ++++++++++++++++++++++++++++ install.sh | 35 ++++++ 14 files changed, 1290 insertions(+), 48 deletions(-) rename config.ltop => config.i3 (72%) create mode 100644 i3blocks/config create mode 100755 i3blocks/scripts/arch-update create mode 100755 i3blocks/scripts/batterybar create mode 100755 i3blocks/scripts/disk create mode 100755 i3blocks/scripts/dunst create mode 100755 i3blocks/scripts/mediaplayer create mode 100755 i3blocks/scripts/playerctl create mode 100755 i3blocks/scripts/shutdown_menu create mode 100755 i3blocks/scripts/volume create mode 100755 i3blocks/scripts/volume-pipewire create mode 100644 install.sh diff --git a/config b/config index 9f3f623..fb5cfb4 100644 --- a/config +++ b/config @@ -13,7 +13,7 @@ set $mod Mod4 # Font for window titles. Will also be used by the bar unless a different font # is used in the bar {} block below. -font pango:Source Code Pro 8 +font pango:Source Code Pro 11 # This font is widely installed, provides lots of unicode glyphs, right-to-left # text rendering and scalability on retina/hidpi displays (thanks to pango). @@ -28,18 +28,42 @@ exec --no-startup-id dex --autostart --environment i3 # xss-lock grabs a logind suspend inhibit lock and will use i3lock to lock the # screen before suspend. Use loginctl lock-session to lock your screen. -#exec --no-startup-id xss-lock --transfer-sleep-lock -- i3lock --nofork +exec --no-startup-id xss-lock --transfer-sleep-lock -- i3lock --nofork # NetworkManager is the most popular way to manage wireless networks on Linux, # and nm-applet is a desktop environment-independent system tray GUI for it. exec --no-startup-id nm-applet # Use pactl to adjust volume in PulseAudio. -set $refresh_i3status killall -SIGUSR1 i3status -bindsym XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ +5% && $refresh_i3status -bindsym XF86AudioLowerVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ -5% && $refresh_i3status -bindsym XF86AudioMute exec --no-startup-id pactl set-sink-mute @DEFAULT_SINK@ toggle && $refresh_i3status -bindsym XF86AudioMicMute exec --no-startup-id pactl set-source-mute @DEFAULT_SOURCE@ toggle && $refresh_i3status +#set $refresh_i3status killall -SIGUSR1 i3status +#bindsym XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ +5% && $refresh_i3status +#bindsym XF86AudioLowerVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ -5% && $refresh_i3status +#bindsym XF86AudioMute exec --no-startup-id pactl set-sink-mute @DEFAULT_SINK@ toggle && $refresh_i3status +#bindsym XF86AudioMicMute exec --no-startup-id pactl set-source-mute @DEFAULT_SOURCE@ toggle && $refresh_i3status + +### + +# Pipewire-pulse +#bindsym XF86AudioMute exec pactl set-sink-mute 0 toggle +#bindsym XF86AudioMute --release exec pkill -RTMIN+1 i3blocks +#bindsym XF86AudioLowerVolume exec pactl set-sink-volume 0 -5% +#bindsym XF86AudioLowerVolume --release exec pkill -RTMIN+1 i3blocks +#bindsym XF86AudioRaiseVolume exec pactl set-sink-volume 0 +5% +#bindsym XF86AudioRaiseVolume --release exec pkill -RTMIN+1 i3blocks + +# Media player controls +#bindsym XF86AudioPlay exec playerctl play-pause +#bindsym XF86AudioPause exec playerctl play-pause +#bindsym XF86AudioNext exec playerctl next +#bindsym XF86AudioPrev exec playerctl previous + +# change volume or toggle mute +bindsym XF86AudioRaiseVolume exec amixer -q -D pulse sset Master 5%+ && pkill -RTMIN+10 i3blocks +bindsym XF86AudioLowerVolume exec amixer -q -D pulse sset Master 5%- && pkill -RTMIN+10 i3blocks +bindsym XF86AudioMute exec amixer -q -D pulse sset Master toggle && pkill -RTMIN+10 i3blocks + +bindsym XF86MonBrightnessUp exec --no-startup-id brightnessctl s +10 +bindsym XF86MonBrightnessDown exec --no-startup-id brightnessctl s 10- # Use Mouse+$mod to drag floating windows to their wanted position floating_modifier $mod @@ -59,10 +83,10 @@ bindsym $mod+r exec rofi -show drun # bindcode $mod+40 exec --no-startup-id i3-dmenu-desktop # change focus -bindsym $mod+j focus left -bindsym $mod+k focus down -bindsym $mod+l focus up -bindsym $mod+semicolon focus right +#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 @@ -71,10 +95,10 @@ bindsym $mod+Up focus up bindsym $mod+Right focus right # 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 +#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 @@ -183,24 +207,31 @@ bindsym $mod+z mode "resize" # finds out, if available) bar { colors { - background #282828 + background #1d2021 + separator #d79921 focused_workspace #d79921 #d79921 #282828 active_workspace #d79921 #d79921 #282828 inactive_workspace #3c3836 #3c3836 #282828 } + tray_output primary + font pango:Source Code Pro 12 + #status_command bumblebee-status \ + # -m playerctl disk pasink pasource battery date time \ + # -p root.path=/ time.format="%H:%M" date.format="%a, %b %d %Y" playerctl.format="{{title}} - by {{artist}} - on {{album}}" \ + # -t gruvbox-powerline + #status_command i3status + separator_symbol " / " + status_command i3blocks position top - font pango:Source Code Pro for Powerline 12 - status_command bumblebee-status \ - -m playerctl pasink pasource network battery date time \ - -p root.path=/ time.format="%H:%M" date.format="%a, %b %d %Y" playerctl.format="{{title}} - by {{artist}} - on {{album}}" \ - -t gruvbox-powerline - #status_command i3blocks } - #bar { # status_command i3blocks #} +# Polybar + +# exec --no-startup-id /home/arco/.config/polybar/launch.sh + # Start compositor exec picom --vsync --backend glx & @@ -229,7 +260,7 @@ client.background #282828 # Wallpaper - exec $HOME/.config/i3/fehbg & + exec_always $HOME/.config/i3/fehbg & # Notification Daemon @@ -238,3 +269,10 @@ client.background #282828 # Screenshot bindsym $mod+Shift+s exec --no-startup-id maim "/home/arco/Screenshots/$(date).png" +# Lock Screen +bindsym $mod+l exec --no-startup-id betterlockscreen -u "/home/arco/Wallpapers/platform.jpg" -l + +#gaps inner 10 +#gaps outer 10 + +exec --no-startup-id kdeconnect-indicator & disown diff --git a/config.ltop b/config.i3 similarity index 72% rename from config.ltop rename to config.i3 index 9f3f623..fb5cfb4 100644 --- a/config.ltop +++ b/config.i3 @@ -13,7 +13,7 @@ set $mod Mod4 # Font for window titles. Will also be used by the bar unless a different font # is used in the bar {} block below. -font pango:Source Code Pro 8 +font pango:Source Code Pro 11 # This font is widely installed, provides lots of unicode glyphs, right-to-left # text rendering and scalability on retina/hidpi displays (thanks to pango). @@ -28,18 +28,42 @@ exec --no-startup-id dex --autostart --environment i3 # xss-lock grabs a logind suspend inhibit lock and will use i3lock to lock the # screen before suspend. Use loginctl lock-session to lock your screen. -#exec --no-startup-id xss-lock --transfer-sleep-lock -- i3lock --nofork +exec --no-startup-id xss-lock --transfer-sleep-lock -- i3lock --nofork # NetworkManager is the most popular way to manage wireless networks on Linux, # and nm-applet is a desktop environment-independent system tray GUI for it. exec --no-startup-id nm-applet # Use pactl to adjust volume in PulseAudio. -set $refresh_i3status killall -SIGUSR1 i3status -bindsym XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ +5% && $refresh_i3status -bindsym XF86AudioLowerVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ -5% && $refresh_i3status -bindsym XF86AudioMute exec --no-startup-id pactl set-sink-mute @DEFAULT_SINK@ toggle && $refresh_i3status -bindsym XF86AudioMicMute exec --no-startup-id pactl set-source-mute @DEFAULT_SOURCE@ toggle && $refresh_i3status +#set $refresh_i3status killall -SIGUSR1 i3status +#bindsym XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ +5% && $refresh_i3status +#bindsym XF86AudioLowerVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ -5% && $refresh_i3status +#bindsym XF86AudioMute exec --no-startup-id pactl set-sink-mute @DEFAULT_SINK@ toggle && $refresh_i3status +#bindsym XF86AudioMicMute exec --no-startup-id pactl set-source-mute @DEFAULT_SOURCE@ toggle && $refresh_i3status + +### + +# Pipewire-pulse +#bindsym XF86AudioMute exec pactl set-sink-mute 0 toggle +#bindsym XF86AudioMute --release exec pkill -RTMIN+1 i3blocks +#bindsym XF86AudioLowerVolume exec pactl set-sink-volume 0 -5% +#bindsym XF86AudioLowerVolume --release exec pkill -RTMIN+1 i3blocks +#bindsym XF86AudioRaiseVolume exec pactl set-sink-volume 0 +5% +#bindsym XF86AudioRaiseVolume --release exec pkill -RTMIN+1 i3blocks + +# Media player controls +#bindsym XF86AudioPlay exec playerctl play-pause +#bindsym XF86AudioPause exec playerctl play-pause +#bindsym XF86AudioNext exec playerctl next +#bindsym XF86AudioPrev exec playerctl previous + +# change volume or toggle mute +bindsym XF86AudioRaiseVolume exec amixer -q -D pulse sset Master 5%+ && pkill -RTMIN+10 i3blocks +bindsym XF86AudioLowerVolume exec amixer -q -D pulse sset Master 5%- && pkill -RTMIN+10 i3blocks +bindsym XF86AudioMute exec amixer -q -D pulse sset Master toggle && pkill -RTMIN+10 i3blocks + +bindsym XF86MonBrightnessUp exec --no-startup-id brightnessctl s +10 +bindsym XF86MonBrightnessDown exec --no-startup-id brightnessctl s 10- # Use Mouse+$mod to drag floating windows to their wanted position floating_modifier $mod @@ -59,10 +83,10 @@ bindsym $mod+r exec rofi -show drun # bindcode $mod+40 exec --no-startup-id i3-dmenu-desktop # change focus -bindsym $mod+j focus left -bindsym $mod+k focus down -bindsym $mod+l focus up -bindsym $mod+semicolon focus right +#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 @@ -71,10 +95,10 @@ bindsym $mod+Up focus up bindsym $mod+Right focus right # 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 +#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 @@ -183,24 +207,31 @@ bindsym $mod+z mode "resize" # finds out, if available) bar { colors { - background #282828 + background #1d2021 + separator #d79921 focused_workspace #d79921 #d79921 #282828 active_workspace #d79921 #d79921 #282828 inactive_workspace #3c3836 #3c3836 #282828 } + tray_output primary + font pango:Source Code Pro 12 + #status_command bumblebee-status \ + # -m playerctl disk pasink pasource battery date time \ + # -p root.path=/ time.format="%H:%M" date.format="%a, %b %d %Y" playerctl.format="{{title}} - by {{artist}} - on {{album}}" \ + # -t gruvbox-powerline + #status_command i3status + separator_symbol " / " + status_command i3blocks position top - font pango:Source Code Pro for Powerline 12 - status_command bumblebee-status \ - -m playerctl pasink pasource network battery date time \ - -p root.path=/ time.format="%H:%M" date.format="%a, %b %d %Y" playerctl.format="{{title}} - by {{artist}} - on {{album}}" \ - -t gruvbox-powerline - #status_command i3blocks } - #bar { # status_command i3blocks #} +# Polybar + +# exec --no-startup-id /home/arco/.config/polybar/launch.sh + # Start compositor exec picom --vsync --backend glx & @@ -229,7 +260,7 @@ client.background #282828 # Wallpaper - exec $HOME/.config/i3/fehbg & + exec_always $HOME/.config/i3/fehbg & # Notification Daemon @@ -238,3 +269,10 @@ client.background #282828 # Screenshot bindsym $mod+Shift+s exec --no-startup-id maim "/home/arco/Screenshots/$(date).png" +# Lock Screen +bindsym $mod+l exec --no-startup-id betterlockscreen -u "/home/arco/Wallpapers/platform.jpg" -l + +#gaps inner 10 +#gaps outer 10 + +exec --no-startup-id kdeconnect-indicator & disown diff --git a/fehbg b/fehbg index 32c0a6b..7a4cdd0 100755 --- a/fehbg +++ b/fehbg @@ -6,3 +6,7 @@ #feh --no-fehbg --bg-scale '/home/arco/Wallpapers/ign_mountains.png' #feh --no-fehbg --bg-scale '/home/arco/Wallpapers/C-Hello-World.png' feh --no-fehbg --bg-scale '/home/arco/Wallpapers/platform.jpg' +#feh --no-fehbg --bg-scale '/home/arco/Wallpapers/arch-gruvbox.png' +#feh --no-fehbg --bg-scale '/home/arco/Wallpapers/gruvbox-simple.png' +#feh --no-fehbg --bg-scale '/home/arco/Wallpapers/hl2.jpg' +#feh --no-fehbg --bg-scale '/home/arco/Wallpapers/term.jpg' diff --git a/i3blocks/config b/i3blocks/config new file mode 100644 index 0000000..4b90ade --- /dev/null +++ b/i3blocks/config @@ -0,0 +1,96 @@ +# i3blocks configuration file +# +# The i3blocks man page describes the usage of the binary, +# and its website describes the configuration: +# +# https://vivien.github.io/i3blocks + +SCRIPT_DIR=/home/arco/.config/i3blocks/scripts + +# Global properties +separator=true +separator_block_width=30 + +[mediaplayer] +command=$SCRIPT_DIR/mediaplayer +interval=1 + +#[documentation] +#full_text=Documentation +#website=https://vivien.github.io/i3blocks +#command=xdg-open "$website" +#color=#f12711 + +#[greetings] +#color=#f5af19 +#command=echo "Hello, $USER!" +#interval=once + +[volume] +command=$SCRIPT_DIR/volume +LABEL=♪ +#LABEL=VOL +interval=once +signal=10 +STEP=5% +MIXER=pulse +#SCONTROL=[determined automatically] +#NATURAL_MAPPING=0 + +[dunst] +command=$SCRIPT_DIR/dunst +interval=once +format=json +markup=pango +#min_width=50 +align=center + +[disk] +command=$SCRIPT_DIR/disk +DIR=/ +LABEL=🖴 +interval=30 + +[batterybar] +command=$SCRIPT_DIR/batterybar +label=⏻ +interval=5 +markup=pango +min_width=bat: ■■■■■ +# Discharging colors low to high +C1=#FF0027 +C2=#FF3B05 +C3=#FFB923 +C4=#FFD000 +C5=#E4FF00 +C6=#ADFF00 +C7=#6DFF00 +C8=#10BA00 +CHARGING_COLOR=#00AFE3 +FULL_COLOR=#FFFFFF +AC_COLOR=#535353 + +[time] +command=date '+%m/%d/%Y %H:%M' +interval=15 + +[shutdown_menu] +full_text= ⏻ Power Menu +# If you are using FontAwesome, we recommend the power-off icon: +# http://fontawesome.io/icon/power-off/ +command=$SCRIPT_DIR/shutdown_menu +#FG_COLOR=#bbbbbb +#BG_COLOR=#111111 +#HLFG_COLOR=#111111 +#HLBG_COLOR=#bbbbbb +#BORDER_COLOR=#222222 +ROFI_TEXT=⏻ +ROFI_OPTIONS=-width 11 -location 0 -hide-scrollbar -bw 2 +#ZENITY_TITLE=Menu +#ZENITY_TEXT=Action: +#ZENITY_OPTIONS=--column= --hide-header +#ENABLE_CONFIRMATIONS=true (must be true or false) +#LAUNCHER=rofi #(must be rofi or zenity) +LOCKSCRIPT=betterlockscreen -u "/home/arco/Wallpapers/platform.jpg" -l +background=#d79921 +color=#282828 diff --git a/i3blocks/scripts/arch-update b/i3blocks/scripts/arch-update new file mode 100755 index 0000000..89f244c --- /dev/null +++ b/i3blocks/scripts/arch-update @@ -0,0 +1,155 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2017 Marcel Patzwahl +# Licensed under the terms of the GNU GPL v3 only. +# +# i3blocks blocklet script to see the available updates of pacman and the AUR +import subprocess +from subprocess import check_output +import argparse +import os +import re + + +def create_argparse(): + def _default(name, default='', arg_type=str): + val = default + if name in os.environ: + val = os.environ[name] + return arg_type(val) + + strbool = lambda s: s.lower() in ['t', 'true', '1'] + strlist = lambda s: s.split() + + parser = argparse.ArgumentParser(description='Check for pacman updates') + parser.add_argument( + '-b', + '--base_color', + default = _default('BASE_COLOR', 'green'), + help='base color of the output(default=green)' + ) + parser.add_argument( + '-u', + '--updates_available_color', + default = _default('UPDATE_COLOR', 'yellow'), + help='color of the output, when updates are available(default=yellow)' + ) + parser.add_argument( + '-a', + '--aur', + action = 'store_const', + const = True, + default = _default('AUR', 'False', strbool), + help='Include AUR packages. Attn: Yaourt must be installed' + ) + parser.add_argument( + '-y', + '--aur_yay', + action = 'store_const', + const = True, + default = _default('AUR_YAY', 'False', strbool), + help='Include AUR packages. Attn: Yay must be installed' + ) + parser.add_argument( + '-q', + '--quiet', + action = 'store_const', + const = True, + default = _default('QUIET', 'False', strbool), + help = 'Do not produce output when system is up to date' + ) + parser.add_argument( + '-w', + '--watch', + nargs='*', + default = _default('WATCH', arg_type=strlist), + help='Explicitly watch for specified packages. ' + 'Listed elements are treated as regular expressions for matching.' + ) + return parser.parse_args() + + +def get_updates(): + output = '' + try: + output = check_output(['checkupdates']).decode('utf-8') + except subprocess.CalledProcessError as exc: + # checkupdates exits with 2 and no output if no updates are available. + # we ignore this case and go on + if not (exc.returncode == 2 and not exc.output): + raise exc + if not output: + return [] + + updates = [line.split(' ')[0] + for line in output.split('\n') + if line] + + return updates + + +def get_aur_yaourt_updates(): + output = '' + try: + output = check_output(['yaourt', '-Qua']).decode('utf-8') + except subprocess.CalledProcessError as exc: + # yaourt exits with 1 and no output if no updates are available. + # we ignore this case and go on + if not (exc.returncode == 1 and not exc.output): + raise exc + if not output: + return [] + + aur_updates = [line.split(' ')[0] + for line in output.split('\n') + if line.startswith('aur/')] + + return aur_updates + +def get_aur_yay_updates(): + output = check_output(['yay', '-Qua']).decode('utf-8') + if not output: + return [] + + aur_updates = [line.split(' ')[0] for line in output.split('\n') if line] + + return aur_updates + + +def matching_updates(updates, watch_list): + matches = set() + for u in updates: + for w in watch_list: + if re.match(w, u): + matches.add(u) + + return matches + + +label = os.environ.get("LABEL","") +message = "{0}{2}" +args = create_argparse() + +updates = get_updates() +if args.aur: + updates += get_aur_yaourt_updates() +elif args.aur_yay: + updates += get_aur_yay_updates() + +update_count = len(updates) +if update_count > 0: + if update_count == 1: + info = str(update_count) + ' update available' + short_info = str(update_count) + ' update' + else: + info = str(update_count) + ' updates available' + short_info = str(update_count) + ' updates' + + matches = matching_updates(updates, args.watch) + if matches: + info += ' [{0}]'.format(', '.join(matches)) + short_info += '*' + print(message.format(label, args.updates_available_color, info)) + print(message.format(label, args.updates_available_color, short_info)) +elif not args.quiet: + print(message.format(label, args.base_color, 'system up to date')) diff --git a/i3blocks/scripts/batterybar b/i3blocks/scripts/batterybar new file mode 100755 index 0000000..0308aba --- /dev/null +++ b/i3blocks/scripts/batterybar @@ -0,0 +1,137 @@ +#!/usr/bin/env bash +# batterybar; displays battery percentage as a bar on i3blocks +# +# Copyright 2015 Keftaa +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301, USA. +# +# +readarray -t output <<< $(acpi battery) +battery_count=${#output[@]} + +for line in "${output[@]}"; +do + percentages+=($(echo "$line" | grep -o -m1 '[0-9]\{1,3\}%' | tr -d '%')) + statuses+=($(echo "$line" | egrep -o -m1 'Discharging|Charging|AC|Full|Unknown')) + remaining=$(echo "$line" | egrep -o -m1 '[0-9][0-9]:[0-9][0-9]') + if [[ -n $remaining ]]; then + remainings+=(" ($remaining)") + else + remainings+=("") + fi +done + +squares="■" + +#There are 8 colors that reflect the current battery percentage when +#discharging +dis_colors=("${C1:-#FF0027}" "${C2:-#FF3B05}" "${C3:-#FFB923}" + "${C4:-#FFD000}" "${C5:-#E4FF00}" "${C6:-#ADFF00}" + "${C7:-#6DFF00}" "${C8:-#10BA00}") +charging_color="${CHARGING_COLOR:-#00AFE3}" +full_color="${FULL_COLOR:-#FFFFFF}" +ac_color="${AC_COLOR:-#535353}" + + +while getopts 1:2:3:4:5:6:7:8:c:f:a:h opt; do + case "$opt" in + 1) dis_colors[0]="$OPTARG";; + 2) dis_colors[1]="$OPTARG";; + 3) dis_colors[2]="$OPTARG";; + 4) dis_colors[3]="$OPTARG";; + 5) dis_colors[4]="$OPTARG";; + 6) dis_colors[5]="$OPTARG";; + 7) dis_colors[6]="$OPTARG";; + 8) dis_colors[7]="$OPTARG";; + c) charging_color="$OPTARG";; + f) full_color="$OPTARG";; + a) ac_color="$OPTARG";; + h) printf "Usage: batterybar [OPTION] color + When discharging, there are 8 [1-8] levels colors. + You can specify custom colors, for example: + + batterybar -1 red -2 \"#F6F6F6\" -8 green + + You can also specify the colors for the charging, AC and + charged states: + + batterybar -c green -f white -a \"#EEEEEE\"\n"; + exit 0; + esac +done + +end=$(($battery_count - 1)) +for i in $(seq 0 $end); +do + if (( percentages[$i] > 0 && percentages[$i] < 20 )); then + squares="■" + elif (( percentages[$i] >= 20 && percentages[$i] < 40 )); then + squares="■■" + elif (( percentages[$i] >= 40 && percentages[$i] < 60 )); then + squares="■■■" + elif (( percentages[$i] >= 60 && percentages[$i] < 80 )); then + squares="■■■■" + elif (( percentages[$i] >=80 )); then + squares="■■■■■" + fi + + if [[ "${statuses[$i]}" = "Unknown" ]]; then + squares="?$squares" + fi + + case "${statuses[$i]}" in + "Charging") + color="$charging_color" + ;; + "Full") + color="$full_color" + ;; + "AC") + color="$ac_color" + ;; + "Discharging"|"Unknown") + if (( percentages[$i] >= 0 && percentages[$i] < 10 )); then + color="${dis_colors[0]}" + elif (( percentages[$i] >= 10 && percentages[$i] < 20 )); then + color="${dis_colors[1]}" + elif (( percentages[$i] >= 20 && percentages[$i] < 30 )); then + color="${dis_colors[2]}" + elif (( percentages[$i] >= 30 && percentages[$i] < 40 )); then + color="${dis_colors[3]}" + elif (( percentages[$i] >= 40 && percentages[$i] < 60 )); then + color="${dis_colors[4]}" + elif (( percentages[$i] >= 60 && percentages[$i] < 70 )); then + color="${dis_colors[5]}" + elif (( percentages[$i] >= 70 && percentages[$i] < 80 )); then + color="${dis_colors[6]}" + elif (( percentages[$i] >= 80 )); then + color="${dis_colors[7]}" + fi + ;; + esac + + # Print Battery number if there is more than one + if (( $end > 0 )) ; then + message="$message $(($i + 1)):" + fi + + if [[ "$BLOCK_BUTTON" -eq 1 ]]; then + message="$message ${statuses[$i]} ${percentages[$i]}%${remainings[i]}" + fi + message="$message $squares" +done + +echo $message diff --git a/i3blocks/scripts/disk b/i3blocks/scripts/disk new file mode 100755 index 0000000..9d64cc1 --- /dev/null +++ b/i3blocks/scripts/disk @@ -0,0 +1,48 @@ +#!/usr/bin/env sh +# Copyright (C) 2014 Julien Bonjean + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +DIR="${DIR:-$BLOCK_INSTANCE}" +DIR="${DIR:-$HOME}" +ALERT_LOW="${ALERT_LOW:-$1}" +ALERT_LOW="${ALERT_LOW:-10}" # color will turn red under this value (default: 10%) + +LOCAL_FLAG="-l" +if [ "$1" = "-n" ] || [ "$2" = "-n" ]; then + LOCAL_FLAG="" +fi + +df -h -P $LOCAL_FLAG "$DIR" | awk -v label="$LABEL" -v alert_low=$ALERT_LOW ' +/\/.*/ { + # full text + print label $4 + + # short text + print label $4 + + use=$5 + + # no need to continue parsing + exit 0 +} + +END { + gsub(/%$/,"",use) + if (100 - use < alert_low) { + # color + print "#FF0000" + } +} +' diff --git a/i3blocks/scripts/dunst b/i3blocks/scripts/dunst new file mode 100755 index 0000000..915acb3 --- /dev/null +++ b/i3blocks/scripts/dunst @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +""" +A do-not-disturb button for muting Dunst notifications in i3 using i3blocks + +Mute is handled using the `dunstctl` command. +""" + +__author__ = "Jessey White-Cinis " +__copyright__ = "Copyright (c) 2019 Jessey White-Cinis" +__license__ = "MIT" +__version__ = "1.1.0" + +import os +import subprocess as sp +import json + +def mute_toggle(): + '''Toggle dunst notifications''' + sp.run(["dunstctl", "set-paused", "toggle"], check=True) + +def clicked(): + '''Returns True if the button was clicked''' + button = os.environ.get("BLOCK_BUTTON", None) + return bool(button) + +def muted(): + '''Returns True if Dunst is muted''' + output = sp.check_output(('dunstctl', 'is-paused')) + return u'true' == output.strip().decode("UTF-8") + +if clicked(): + # toggle button click to turn mute on and off + mute_toggle() + +if muted(): + RTN = {"full_text":"\uf1f6"} +else: + RTN = {"full_text":"\uf0f3"} + +print(json.dumps(RTN)) diff --git a/i3blocks/scripts/mediaplayer b/i3blocks/scripts/mediaplayer new file mode 100755 index 0000000..7259080 --- /dev/null +++ b/i3blocks/scripts/mediaplayer @@ -0,0 +1,159 @@ +#!/usr/bin/env perl +# Copyright (C) 2014 Tony Crisci +# Copyright (C) 2015 Thiago Perrotta + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# For all media players except mpd/cmus/rhythmbox, MPRIS support should be +# enabled and the playerctl binary should be in your path. +# See https://github.com/acrisci/playerctl + +# Set instance=NAME in the i3blocks configuration to specify a music player +# (playerctl will attempt to connect to org.mpris.MediaPlayer2.[NAME] on your +# DBus session). If instance is empty, playerctl will connect to the first +# supported media player it finds. + +use Time::HiRes qw(usleep); +use Env qw(BLOCK_INSTANCE); + +use constant DELAY => 50; # Delay in ms to let network-based players (spotify) reflect new data. +use constant SPOTIFY_STR => 'spotify'; + +my @metadata = (); +my $player_arg = ""; + +if ($BLOCK_INSTANCE) { + $player_arg = "--player='$BLOCK_INSTANCE'"; +} + +sub buttons { + my $method = shift; + + if($method eq 'mpd') { + if ($ENV{'BLOCK_BUTTON'} == 1) { + system("mpc prev &>/dev/null"); + } elsif ($ENV{'BLOCK_BUTTON'} == 2) { + system("mpc toggle &>/dev/null"); + } elsif ($ENV{'BLOCK_BUTTON'} == 3) { + system("mpc next &>/dev/null"); + } elsif ($ENV{'BLOCK_BUTTON'} == 4) { + system("mpc volume +10 &>/dev/null"); + } elsif ($ENV{'BLOCK_BUTTON'} == 5) { + system("mpc volume -10 &>/dev/null"); + } + } elsif ($method eq 'cmus') { + if ($ENV{'BLOCK_BUTTON'} == 1) { + system("cmus-remote --prev"); + } elsif ($ENV{'BLOCK_BUTTON'} == 2) { + system("cmus-remote --pause"); + } elsif ($ENV{'BLOCK_BUTTON'} == 3) { + system("cmus-remote --next"); + } + } elsif ($method eq 'playerctl') { + if ($ENV{'BLOCK_BUTTON'} == 1) { + system("playerctl $player_arg previous"); + usleep(DELAY * 1000) if $BLOCK_INSTANCE eq SPOTIFY_STR; + } elsif ($ENV{'BLOCK_BUTTON'} == 2) { + system("playerctl $player_arg play-pause"); + } elsif ($ENV{'BLOCK_BUTTON'} == 3) { + system("playerctl $player_arg next"); + usleep(DELAY * 1000) if $BLOCK_INSTANCE eq SPOTIFY_STR; + } elsif ($ENV{'BLOCK_BUTTON'} == 4) { + system("playerctl $player_arg volume 0.01+"); + } elsif ($ENV{'BLOCK_BUTTON'} == 5) { + system("playerctl $player_arg volume 0.01-"); + } + } elsif ($method eq 'rhythmbox') { + if ($ENV{'BLOCK_BUTTON'} == 1) { + system("rhythmbox-client --previous"); + } elsif ($ENV{'BLOCK_BUTTON'} == 2) { + system("rhythmbox-client --play-pause"); + } elsif ($ENV{'BLOCK_BUTTON'} == 3) { + system("rhythmbox-client --next"); + } + } +} + +sub cmus { + my @cmus = split /^/, qx(cmus-remote -Q); + if ($? == 0) { + foreach my $line (@cmus) { + my @data = split /\s/, $line; + if (shift @data eq 'tag') { + my $key = shift @data; + my $value = join ' ', @data; + + @metadata[0] = $value if $key eq 'artist'; + @metadata[1] = $value if $key eq 'title'; + } + } + + if (@metadata) { + buttons('cmus'); + + # metadata found so we are done + print(join ' - ', @metadata); + print("\n"); + exit 0; + } + } +} + +sub mpd { + my $data = qx(mpc current); + if (not $data eq '') { + buttons("mpd"); + print($data); + exit 0; + } +} + +sub playerctl { + buttons('playerctl'); + + my $artist = qx(playerctl $player_arg metadata artist 2>/dev/null); + chomp $artist; + # exit status will be nonzero when playerctl cannot find your player + exit(0) if $? || $artist eq '(null)'; + + push(@metadata, $artist) if $artist; + + my $title = qx(playerctl $player_arg metadata title); + exit(0) if $? || $title eq '(null)'; + + push(@metadata, $title) if $title; + + print(join(" - ", @metadata)) if @metadata; +} + +sub rhythmbox { + buttons('rhythmbox'); + + my $data = qx(rhythmbox-client --print-playing --no-start); + print($data); +} + +if ($player_arg =~ /mpd/) { + mpd; +} +elsif ($player_arg =~ /cmus/) { + cmus; +} +elsif ($player_arg =~ /rhythmbox/) { + rhythmbox; +} +else { + playerctl; +} +print("\n"); diff --git a/i3blocks/scripts/playerctl b/i3blocks/scripts/playerctl new file mode 100755 index 0000000..ce22dde --- /dev/null +++ b/i3blocks/scripts/playerctl @@ -0,0 +1,43 @@ +#!/bin/bash +# Based on https://aur.archlinux.org/packages/playerctl/ + +INSTANCE="${BLOCK_INSTANCE}" + +if [[ "${INSTANCE}" != "" ]]; then + ARGUMENTS="--player ${INSTANCE}" + ps -e | grep "${INSTANCE}" &> /dev/null +fi +if [ $? == 1 ]; then + exit 0 +fi + +ICON_PLAY="➤" +ICON_PAUSE="Ⅱ" +ICON_STOP="≠" +CUR_ICON="" + +if [[ "${BLOCK_BUTTON}" -eq 1 ]]; then + $(playerctl ${ARGUMENTS} previous) +elif [[ "${BLOCK_BUTTON}" -eq 2 ]]; then + $(playerctl ${ARGUMENTS} play-pause) +elif [[ "${BLOCK_BUTTON}" -eq 3 ]]; then + $(playerctl ${ARGUMENTS} next) +fi + +PLAYER_STATUS=$(playerctl ${ARGUMENTS} status) +INFO_TITLE=$(playerctl ${ARGUMENTS} metadata title) +INFO_ALBUM=$(playerctl ${ARGUMENTS} metadata album) +INFO_ARTIST=$(playerctl ${ARGUMENTS} metadata artist) + +if [[ "${PLAYER_STATUS}" = "Paused" ]]; then + CUR_ICON="${ICON_PAUSE}" +elif [[ "${PLAYER_STATUS}" = "Playing" ]]; then + CUR_ICON="${ICON_PLAY}" +else + CUR_ICON="${ICON_STOP}" +fi + +if [[ "${INFO_TITLE}" != "" ]] && [[ "${INFO_ARTIST}" != "" ]]; then + echo "${INFO_ARTIST} - ${INFO_TITLE} ${CUR_ICON}" + echo "${INFO_ARTIST} - ${INFO_TITLE} ${CUR_ICON}" +fi diff --git a/i3blocks/scripts/shutdown_menu b/i3blocks/scripts/shutdown_menu new file mode 100755 index 0000000..7ae826f --- /dev/null +++ b/i3blocks/scripts/shutdown_menu @@ -0,0 +1,186 @@ +#!/usr/bin/env bash +# +# Use rofi/zenity to change system runstate thanks to systemd. +# +# Note: this currently relies on associative array support in the shell. +# +# Inspired from i3pystatus wiki: +# https://github.com/enkore/i3pystatus/wiki/Shutdown-Menu +# +# Copyright 2015 Benjamin Chrétien +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +####################################################################### +# BEGIN CONFIG # +####################################################################### + +# Use a custom lock script +#LOCKSCRIPT="i3lock-extra -m pixelize" + +# Colors: FG (foreground), BG (background), HL (highlighted) +FG_COLOR="${FG_COLOR:-#bbbbbb}" +BG_COLOR="${BG_COLOR:-#111111}" +HLFG_COLOR="${HLFG_COLOR:-#111111}" +HLBG_COLOR="${HLBG_COLOR:-#bbbbbb}" +BORDER_COLOR="${BORDER_COLOR:-#222222}" + +# Options not related to colors +ROFI_TEXT="${ROFI_TEXT:-Menu:}" +ROFI_OPTIONS=(${ROFI_OPTIONS:--theme-str 'window {width: 11%; border: 2;} listview {scrollbar: false;}' -location 3}) + +# Zenity options +ZENITY_TITLE="${ZENITY_TITLE:-Menu}" +ZENITY_TEXT="${ZENITY_TEXT:-Action:}" +ZENITY_OPTIONS=(${ZENITY_OPTIONS:---column= --hide-header}) + +####################################################################### +# END CONFIG # +####################################################################### + +# Whether to ask for user's confirmation +enable_confirmation=${ENABLE_CONFIRMATIONS:-false} + +# Preferred launcher if both are available +preferred_launcher="${LAUNCHER:-rofi}" + +usage="$(basename "$0") [-h] [-c] [-p name] -- display a menu for shutdown, reboot, lock etc. + +where: + -h show this help text + -c ask for user confirmation + -p preferred launcher (rofi or zenity) + +This script depends on: + - systemd, + - i3, + - rofi or zenity." + +# Check whether the user-defined launcher is valid +launcher_list=(rofi zenity) +function check_launcher() { + if [[ ! "${launcher_list[@]}" =~ (^|[[:space:]])"$1"($|[[:space:]]) ]]; then + echo "Supported launchers: ${launcher_list[*]}" + exit 1 + else + # Get array with unique elements and preferred launcher first + # Note: uniq expects a sorted list, so we cannot use it + i=1 + launcher_list=($(for l in "$1" "${launcher_list[@]}"; do printf "%i %s\n" "$i" "$l"; let i+=1; done \ + | sort -uk2 | sort -nk1 | cut -d' ' -f2- | tr '\n' ' ')) + fi +} + +# Parse CLI arguments +while getopts "hcp:" option; do + case "${option}" in + h) echo "${usage}" + exit 0 + ;; + c) enable_confirmation=true + ;; + p) preferred_launcher="${OPTARG}" + check_launcher "${preferred_launcher}" + ;; + *) exit 1 + ;; + esac +done +check_launcher "${preferred_launcher}" + +# Check whether a command exists +function command_exists() { + command -v "$1" &> /dev/null 2>&1 +} + +# systemctl required +if ! command_exists systemctl ; then + exit 1 +fi + +# menu defined as an associative array +typeset -A menu + +# Menu with keys/commands +menu=( + [Shutdown]="systemctl poweroff" + [Reboot]="systemctl reboot" + [Hibernate]="systemctl hibernate" + [Suspend]="systemctl suspend" + [Halt]="systemctl halt" + [Lock]="${LOCKSCRIPT:-i3lock --color=${BG_COLOR#"#"}}" + [Logout]="i3-msg exit" + [Cancel]="" +) +menu_nrows=${#menu[@]} + +# Menu entries that may trigger a confirmation message +menu_confirm="Shutdown Reboot Hibernate Suspend Halt Logout" + +launcher_exe="" +launcher_options="" +rofi_colors="" + +function prepare_launcher() { + if [[ "$1" == "rofi" ]]; then + rofi_colors=(-bc "${BORDER_COLOR}" -bg "${BG_COLOR}" -fg "${FG_COLOR}" \ + -hlfg "${HLFG_COLOR}" -hlbg "${HLBG_COLOR}") + launcher_exe="rofi" + launcher_options=(-dmenu -i -lines "${menu_nrows}" -p "${ROFI_TEXT}" \ + "${rofi_colors[@]}" "${ROFI_OPTIONS[@]}") + elif [[ "$1" == "zenity" ]]; then + launcher_exe="zenity" + launcher_options=(--list --title="${ZENITY_TITLE}" --text="${ZENITY_TEXT}" \ + "${ZENITY_OPTIONS[@]}") + fi +} + +for l in "${launcher_list[@]}"; do + if command_exists "${l}" ; then + prepare_launcher "${l}" + break + fi +done + +# No launcher available +if [[ -z "${launcher_exe}" ]]; then + exit 1 +fi + +launcher=(${launcher_exe} "${launcher_options[@]}") +selection="$(printf '%s\n' "${!menu[@]}" | sort | "${launcher[@]}")" + +function ask_confirmation() { + if [ "${launcher_exe}" == "rofi" ]; then + confirmed=$(echo -e "Yes\nNo" | rofi -dmenu -i -lines 2 -p "${selection}?" \ + "${rofi_colors[@]}" "${ROFI_OPTIONS[@]}") + [ "${confirmed}" == "Yes" ] && confirmed=0 + elif [ "${launcher_exe}" == "zenity" ]; then + zenity --question --text "Are you sure you want to ${selection,,}?" + confirmed=$? + fi + + if [ "${confirmed}" == 0 ]; then + i3-msg -q "exec ${menu[${selection}]}" + fi +} + +if [[ $? -eq 0 && ! -z ${selection} ]]; then + if [[ "${enable_confirmation}" = true && \ + ${menu_confirm} =~ (^|[[:space:]])"${selection}"($|[[:space:]]) ]]; then + ask_confirmation + else + i3-msg -q "exec ${menu[${selection}]}" + fi +fi diff --git a/i3blocks/scripts/volume b/i3blocks/scripts/volume new file mode 100755 index 0000000..e8e1372 --- /dev/null +++ b/i3blocks/scripts/volume @@ -0,0 +1,91 @@ +#!/usr/bin/env bash +# Copyright (C) 2014 Julien Bonjean +# Copyright (C) 2014 Alexander Keller + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +#------------------------------------------------------------------------ + +# The second parameter overrides the mixer selection +# For PulseAudio users, eventually use "pulse" +# For Jack/Jack2 users, use "jackplug" +# For ALSA users, you may use "default" for your primary card +# or you may use hw:# where # is the number of the card desired +if [[ -z "$MIXER" ]] ; then + MIXER="default" + if command -v pulseaudio >/dev/null 2>&1 && pulseaudio --check ; then + # pulseaudio is running, but not all installations use "pulse" + if amixer -D pulse info >/dev/null 2>&1 ; then + MIXER="pulse" + fi + fi + [ -n "$(lsmod | grep jack)" ] && MIXER="jackplug" + MIXER="${2:-$MIXER}" +fi + +# The instance option sets the control to report and configure +# This defaults to the first control of your selected mixer +# For a list of the available, use `amixer -D $Your_Mixer scontrols` +if [[ -z "$SCONTROL" ]] ; then + SCONTROL="${BLOCK_INSTANCE:-$(amixer -D $MIXER scontrols | + sed -n "s/Simple mixer control '\([^']*\)',0/\1/p" | + head -n1 + )}" +fi + +# The first parameter sets the step to change the volume by (and units to display) +# This may be in in % or dB (eg. 5% or 3dB) +if [[ -z "$STEP" ]] ; then + STEP="${1:-5%}" +fi + +# AMIXER(1): +# "Use the mapped volume for evaluating the percentage representation like alsamixer, to be +# more natural for human ear." +NATURAL_MAPPING=${NATURAL_MAPPING:-0} +if [[ "$NATURAL_MAPPING" != "0" ]] ; then + AMIXER_PARAMS="-M" +fi + +#------------------------------------------------------------------------ + +capability() { # Return "Capture" if the device is a capture device + amixer $AMIXER_PARAMS -D $MIXER get $SCONTROL | + sed -n "s/ Capabilities:.*cvolume.*/Capture/p" +} + +volume() { + amixer $AMIXER_PARAMS -D $MIXER get $SCONTROL $(capability) +} + +format() { + + perl_filter='if (/.*\[(\d+%)\] (\[(-?\d+.\d+dB)\] )?\[(on|off)\]/)' + perl_filter+='{CORE::say $4 eq "off" ? "MUTE" : "' + # If dB was selected, print that instead + perl_filter+=$([[ $STEP = *dB ]] && echo '$3' || echo '$1') + perl_filter+='"; exit}' + output=$(perl -ne "$perl_filter") + echo "$LABEL$output" +} + +#------------------------------------------------------------------------ + +case $BLOCK_BUTTON in + 3) amixer $AMIXER_PARAMS -q -D $MIXER sset $SCONTROL $(capability) toggle ;; # right click, mute/unmute + 4) amixer $AMIXER_PARAMS -q -D $MIXER sset $SCONTROL $(capability) ${STEP}+ unmute ;; # scroll up, increase + 5) amixer $AMIXER_PARAMS -q -D $MIXER sset $SCONTROL $(capability) ${STEP}- unmute ;; # scroll down, decrease +esac + +volume | format diff --git a/i3blocks/scripts/volume-pipewire b/i3blocks/scripts/volume-pipewire new file mode 100755 index 0000000..bc7da69 --- /dev/null +++ b/i3blocks/scripts/volume-pipewire @@ -0,0 +1,172 @@ +#!/bin/bash +# Displays the default device, volume, and mute status for i3blocks + +set -a + +AUDIO_HIGH_SYMBOL=${AUDIO_HIGH_SYMBOL:-' '} + +AUDIO_MED_THRESH=${AUDIO_MED_THRESH:-50} +AUDIO_MED_SYMBOL=${AUDIO_MED_SYMBOL:-' '} + +AUDIO_LOW_THRESH=${AUDIO_LOW_THRESH:-0} +AUDIO_LOW_SYMBOL=${AUDIO_LOW_SYMBOL:-' '} + +AUDIO_MUTED_SYMBOL=${AUDIO_MUTED_SYMBOL:-' '} + +AUDIO_DELTA=${AUDIO_DELTA:-5} + +DEFAULT_COLOR=${DEFAULT_COLOR:-"#ffffff"} +MUTED_COLOR=${MUTED_COLOR:-"#a0a0a0"} + +LONG_FORMAT=${LONG_FORMAT:-'${SYMB} ${VOL}% [${INDEX}:${NAME}]'} +SHORT_FORMAT=${SHORT_FORMAT:-'${SYMB} ${VOL}% [${INDEX}]'} +USE_ALSA_NAME=${USE_ALSA_NAME:-0} +USE_DESCRIPTION=${USE_DESCRIPTION:-0} + +SUBSCRIBE=${SUBSCRIBE:-0} + +MIXER=${MIXER:-""} +SCONTROL=${SCONTROL:-""} + +while getopts F:Sf:adH:M:L:X:T:t:C:c:i:m:s:h opt; do + case "$opt" in + S) SUBSCRIBE=1 ;; + F) LONG_FORMAT="$OPTARG" ;; + f) SHORT_FORMAT="$OPTARG" ;; + a) USE_ALSA_NAME=1 ;; + d) USE_DESCRIPTION=1 ;; + H) AUDIO_HIGH_SYMBOL="$OPTARG" ;; + M) AUDIO_MED_SYMBOL="$OPTARG" ;; + L) AUDIO_LOW_SYMBOL="$OPTARG" ;; + X) AUDIO_MUTED_SYMBOL="$OPTARG" ;; + T) AUDIO_MED_THRESH="$OPTARG" ;; + t) AUDIO_LOW_THRESH="$OPTARG" ;; + C) DEFAULT_COLOR="$OPTARG" ;; + c) MUTED_COLOR="$OPTARG" ;; + i) AUDIO_INTERVAL="$OPTARG" ;; + m) MIXER="$OPTARG" ;; + s) SCONTROL="$OPTARG" ;; + h) printf \ +"Usage: volume-pulseaudio [-S] [-F format] [-f format] [-p] [-a|-d] [-H symb] [-M symb] + [-L symb] [-X symb] [-T thresh] [-t thresh] [-C color] [-c color] [-i inter] + [-m mixer] [-s scontrol] [-h] +Options: +-F, -f\tOutput format (-F long format, -f short format) to use, with exposed variables: +\${SYMB}, \${VOL}, \${INDEX}, \${NAME} +-S\tSubscribe to volume events (requires persistent block, always uses long format) +-a\tUse ALSA name if possible +-d\tUse device description instead of name if possible +-H\tSymbol to use when audio level is high. Default: '$AUDIO_HIGH_SYMBOL' +-M\tSymbol to use when audio level is medium. Default: '$AUDIO_MED_SYMBOL' +-L\tSymbol to use when audio level is low. Default: '$AUDIO_LOW_SYMBOL' +-X\tSymbol to use when audio is muted. Default: '$AUDIO_MUTED_SYMBOL' +-T\tThreshold for medium audio level. Default: $AUDIO_MED_THRESH +-t\tThreshold for low audio level. Default: $AUDIO_LOW_THRESH +-C\tColor for non-muted audio. Default: $DEFAULT_COLOR +-c\tColor for muted audio. Default: $MUTED_COLOR +-i\tInterval size of volume increase/decrease. Default: $AUDIO_DELTA +-m\tUse the given mixer. +-s\tUse the given scontrol. +-h\tShow this help text +" && exit 0;; + esac +done + +if [[ -z "$MIXER" ]] ; then + MIXER="default" + if amixer -D pulse info >/dev/null 2>&1 ; then + MIXER="pulse" + fi +fi + +if [[ -z "$SCONTROL" ]] ; then + SCONTROL=$(amixer -D "$MIXER" scontrols | sed -n "s/Simple mixer control '\([^']*\)',0/\1/p" | head -n1) +fi + +CAPABILITY=$(amixer -D $MIXER get $SCONTROL | sed -n "s/ Capabilities:.*cvolume.*/Capture/p") + + +function move_sinks_to_new_default { + DEFAULT_SINK=$1 + pactl list sink-inputs | grep 'Sink Input #' | grep -o '[0-9]\+' | while read SINK + do + pactl move-sink-input $SINK $DEFAULT_SINK + done +} + +function set_default_playback_device_next { + inc=${1:-1} + num_devices=$(pactl list sinks | grep -c Name:) + sink_arr=($(pactl list sinks | grep Name: | sed -r 's/\s+Name: (.+)/\1/')) + default_sink=$(pactl get-default-sink) + default_sink_index=$(for i in "${!sink_arr[@]}"; do if [[ "$default_sink" = "${sink_arr[$i]}" ]]; then echo "$i"; fi done) + default_sink_index=$(( ($default_sink_index + $num_devices + $inc) % $num_devices )) + default_sink=${sink_arr[$default_sink_index]} + pactl set-default-sink $default_sink + move_sinks_to_new_default $default_sink +} + +case "$BLOCK_BUTTON" in + 1) set_default_playback_device_next ;; + 2) amixer -q -D $MIXER sset $SCONTROL $CAPABILITY toggle ;; + 3) set_default_playback_device_next -1 ;; + 4) amixer -q -D $MIXER sset $SCONTROL $CAPABILITY $AUDIO_DELTA%+ ;; + 5) amixer -q -D $MIXER sset $SCONTROL $CAPABILITY $AUDIO_DELTA%- ;; +esac + +function print_format { + echo "$1" | envsubst '${SYMB}${VOL}${INDEX}${NAME}' +} + +function print_block { + ACTIVE=$(pactl list sinks | grep "State\: RUNNING" -B4 -A55 | grep "Name:\|Volume: \(front-left\|mono\)\|Mute:\|api.alsa.pcm.card = \|node.nick = ") + for Name in NAME MUTED VOL INDEX NICK; do + read $Name + done < <(echo "$ACTIVE") + INDEX=$(echo "$INDEX" | grep -o '".*"' | sed 's/"//g') + VOL=$(echo "$VOL" | grep -o "[0-9]*%" | head -1 ) + VOL="${VOL%?}" + NAME=$(echo "$NICK" | grep -o '".*"' | sed 's/"//g') + + if [[ $USE_ALSA_NAME == 1 ]] ; then + ALSA_NAME=$(pactl list sinks |\ +awk '/^\s*\*/{f=1}/^\s*index:/{f=0}f' |\ +grep "alsa.name\|alsa.mixer_name" |\ +head -n1 |\ +sed 's/.*= "\(.*\)".*/\1/') + NAME=${ALSA_NAME:-$NAME} + elif [[ $USE_DESCRIPTION == 1 ]] ; then + DESCRIPTION=$(pactl list sinks | grep "State\: RUNNING" -B4 -A55 | grep 'Description: ' | sed 's/^.*: //') + NAME=${DESCRIPTION:-$NAME} + fi + + if [[ $MUTED =~ "no" ]] ; then + SYMB=$AUDIO_HIGH_SYMBOL + [[ $VOL -le $AUDIO_MED_THRESH ]] && SYMB=$AUDIO_MED_SYMBOL + [[ $VOL -le $AUDIO_LOW_THRESH ]] && SYMB=$AUDIO_LOW_SYMBOL + COLOR=$DEFAULT_COLOR + else + SYMB=$AUDIO_MUTED_SYMBOL + COLOR=$MUTED_COLOR + fi + + if [[ $ACTIVE = "" ]] ; then + echo "Sound inactive" + COLOR='#222225' + fi + + if [[ $SUBSCRIBE == 1 ]] ; then + print_format "$LONG_FORMAT" + else + print_format "$LONG_FORMAT" + print_format "$SHORT_FORMAT" + echo "$COLOR" + fi +} + +print_block +if [[ $SUBSCRIBE == 1 ]] ; then + while read -r EVENT; do + print_block + done < <(pactl subscribe | stdbuf -oL grep change) +fi diff --git a/install.sh b/install.sh new file mode 100644 index 0000000..46df4fc --- /dev/null +++ b/install.sh @@ -0,0 +1,35 @@ +#!/bin/bash + +export red="\033[1;31m" +export green="\033[1;32m" +export blue="\033[1;34m" +export reset="\033[m" +export check="\xE2\x9C\x93" +export error="\xE2\x9C\x95" + +DEPENDENCIES=("/bin/i3" "/bin/i3blocks" "/bin/feh" "/bin/rofi" "/bin/maim" "/bin/dunst") + +printf "${blue}[i]${reset} Checking dependencies...\n" +for d in ${DEPENDENCIES[@]}; do + sleep 0.1 + which ${d} + if [ "$?" != 0 ]; then + printf "${red}[${error}]${reset} Dependency ${d} not found.\n" + exit 1 + fi +done + +printf "${blue}[i]${reset} This script will overwrite your current i3 configuration.\n" +read -p "$(printf "${blue}[i]${reset} Continue? [y/n] ")" -n 1 -r + if [[ $REPLY =~ ^[Yy]$ ]]; then + printf "\n" + cp ${HOME}/.config/i3/config ${HOME}/.config/i3/config.old + printf "${blue}[i]${reset} Saved old configuration as ${HOME}/.config/i3/config.old.\n" + ln -sv config.i3 ${HOME}/.config/i3/config + ln -sv fehbg ${HOME}/.config/i3/fehbg + ln -sv i3blocks ${HOME}/.config/i3blbocks + printf "${blue}[i]${reset} WARNING: Do not delete this directory. This script set up symlinks to this directory. Removing it will effectively uninstall the rice.\n" + printf "${green}[${check}]${reset} Finished.\n" + exit 0 + fi +