config

betoissues' dotfiles
git clone git://git.betoissues.com/config.git
Historial | Archivos | Refs | Submódulos | README

commit 41375f6830603f8e2ac049a162a5c7e32fd2b785
parent 530b0ec2fb8560ab1f10eddfbee1ce84938a89c4
Autor: Alberto Castillo G <me@betoissues.com>
Date:   Sat, 19 Sep 2020 02:41:53 -0500

Add pulseaudio-control for polybar

Diffstat:
Mpolybar/.config/polybar/config | 88++++++++++++++-----------------------------------------------------------------
Dpolybar/.config/polybar/polystock | 1-
Apolybar/.config/polybar/pulseaudio/pulseaudio-control.bash | 356+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 archivos modificado, 371 insercioness(+), 74 removidass(-)

diff --git a/polybar/.config/polybar/config b/polybar/.config/polybar/config @@ -25,7 +25,7 @@ background = ${colors.background} foreground = ${colors.foreground} border-size = 1 -line-size = 2 +line-size = 3 padding = 1 module-margin = 1 @@ -35,7 +35,6 @@ font-2 = "cryptocoins:size=12;0.9" font-3 = "WenQuanYi Zen Hei Mono:size=10;1" modules-left = gmail spotify -modules-center = eth xrp aapl nio modules-right = network pulseaudio date tray-position = right @@ -66,43 +65,16 @@ format-underline = ${colors.dark-yellow} click-left = xdg-open https://mail.google.com [module/pulseaudio] -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_12_00.3.analog-stereo - -; Use PA_VOLUME_UI_MAX (~153%) if true, or PA_VOLUME_NORM (100%) if false -; Default: true -use-ui-max = true -interval = 5 -label-muted =  muted -label-muted-foreground = #666 -format-volume = <ramp-volume> <label-volume> -format-volume-underline = ${colors.dark-yellow} -format-muted-underline = ${colors.dark-red} - -; Only applies if <ramp-volume> is used -ramp-volume-0 =  -ramp-volume-1 =  -ramp-volume-2 =  -click-right = pavucontrol & - -[module/cpu] -type = internal/cpu -interval = 2 -format-prefix = "💻 " -format-prefix-foreground = ${colors.foreground-alt} -format-underline = #f90000 -label = %percentage:2%% - -[module/memory] -type = internal/memory -interval = 2 -format-prefix = "🗍 " -format-prefix-foreground = ${colors.foreground} +type = custom/script +tail = true format-underline = ${colors.dark-yellow} -label = %percentage_used:2%% + +exec = ~/.config/polybar/pulseaudio/pulseaudio-control.bash listen +click-left = ~/.config/polybar/pulseaudio/pulseaudio-control.bash togmute +click-right = ~/.config/polybar/pulseaudio/pulseaudio-control.bash next-sink +scroll-up = ~/.config/polybar/pulseaudio/pulseaudio-control.bash up +scroll-down = ~/.config/polybar/pulseaudio/pulseaudio-control.bash down +label-foreground = ${colors.foreground} [module/network] type = internal/network @@ -110,16 +82,17 @@ interface = enp39s0 interval = 5.0 format-connected-underline = ${colors.dark-yellow} -label-connected =  %upspeed%  %downspeed% +label-connected = " %upspeed%  %downspeed%" label-disconnected = ❎ not connected [module/spotify] type = custom/script interval = 1 -format-prefix = " " -format = <label> -exec = python ~/.config/polybar/spotify/spotify_status.py -f '{play_pause}{artist} - {song}' -p '[playing] ,[paused] ' +format =  <label> +exec = python ~/.config/polybar/spotify/spotify_status.py -f '{play_pause}{artist} - {song}' -p ',[paused] ' +click-left = playerctl play-pause +click-right = spotify format-underline = ${colors.dark-yellow} [module/date] @@ -140,8 +113,6 @@ label = %date%%time% [module/brightness] type = internal/xbacklight -; Create scroll handlers used to set the backlight value -; Default: true enable-scroll = true format = <ramp> <label> @@ -206,35 +177,6 @@ label-charging = ⚡ %percentage%% label-discharging = %percentage%% label-full = " ☀ " -[module/eth] -type = custom/script -exec = ~/.config/polybar/polystock/polystock.py --customticker ETH-USD -tail = true -label = %output% -format-underline = #ffb52a - -[module/xrp] -type = custom/script -exec = ~/.config/polybar/polystock/polystock.py --customticker XRP-USD -tail = true -label = %output% -format-underline = #ffb52a - -[module/aapl] -type = custom/script -exec = ~/.config/polybar/polystock/polystock.py --customticker AAPL -tail = true -label = %output% -format-underline = #ffb52a - -[module/nio] -type = custom/script -exec = ~/.config/polybar/polystock/polystock.py --customticker NIO -tail = true -label = %output% -format-underline = #ffb52a - - [settings] screenchange-reload = true diff --git a/polybar/.config/polybar/polystock b/polybar/.config/polybar/polystock @@ -1 +0,0 @@ -Subproject commit fbd644eeacbd6262e168598bfc162e0552faffaf diff --git a/polybar/.config/polybar/pulseaudio/pulseaudio-control.bash b/polybar/.config/polybar/pulseaudio/pulseaudio-control.bash @@ -0,0 +1,356 @@ +#!/usr/bin/env bash + +################################################################## +# Polybar Pulseaudio Control # +# https://github.com/marioortizmanero/polybar-pulseaudio-control # +################################################################## + +# Script configuration (more info in the README) +OSD="yes" # On Screen Display message for KDE if enabled +INC=5 # Increment when lowering/rising the volume +MAX_VOL=130 # Maximum volume +AUTOSYNC="no" # All programs have the same volume if enabled +VOLUME_ICONS=( " " " " " " ) # Volume icons array, from lower volume to higher +MUTED_ICON=" " # Muted volume icon +MUTED_COLOR="%{F#666666}" # Color when the audio is muted +NOTIFICATIONS="no" # Notifications when switching sinks if enabled +SINK_ICON=" " # Icon always shown to the left of the default sink names + +# Blacklist of PulseAudio sink names when switching between them. To obtain +# the names of your active sinks, use `pactl list sinks short`. +SINK_BLACKLIST=( + "alsa_output.pci-0000_2f_00.4.iec958-stereo" +) + +# Maps PulseAudio sink names to human-readable names +declare -A SINK_NICKNAMES +SINK_NICKNAMES["alsa_output.usb-Yamaha_Corporation_Steinberg_UR22mkII-00.analog-stereo"]="UR22mkII" +SINK_NICKNAMES["alsa_output.pci-0000_2d_00.1.hdmi-stereo-extra1"]="HDMI" + + +# Environment & global constants for the script +LANGUAGE=en_US # Some calls depend on English outputs of pactl +END_COLOR="%{F-}" + + +# Saves the currently default sink into a variable named `curSink`. It will +# return an error code when pulseaudio isn't running. +function getCurSink() { + if ! pulseaudio --check; then return 1; fi + curSink=$(pacmd list-sinks | awk '/\* index:/{print $3}') +} + + +# Saves the sink passed by parameter's volume into a variable named `curVol`. +function getCurVol() { + curVol=$(pacmd list-sinks | grep -A 15 'index: '"$1"'' | grep 'volume:' | grep -E -v 'base volume:' | awk -F : '{print $3; exit}' | grep -o -P '.{0,3}%' | sed 's/.$//' | tr -d ' ') +} + + +# Saves the name of the sink passed by parameter into a variable named +# `sinkName`. +function getSinkName() { + sinkName=$(pactl list sinks short | awk -v sink="$1" '{ if ($1 == sink) {print $2} }') +} + + +# Saves the name to be displayed for the sink passed by parameter into a +# variable called `nickname`. +# If a mapping for the sink name exists, that is used. Otherwise, the string +# "Sink #<index>" is used. +function getNickname() { + getSinkName "$1" + if [ -n "${SINK_NICKNAMES[$sinkName]}" ]; then + nickname="${SINK_NICKNAMES[$sinkName]}" + else + nickname="Sink #$1" + fi +} + + +# Saves the status of the sink passed by parameter into a variable named +# `isMuted`. +function getIsMuted() { + isMuted=$(pacmd list-sinks | grep -A 15 "index: $1" | awk '/muted/ {print $2; exit}') +} + + +# Saves all the sink inputs of the sink passed by parameter into a string +# named `sinkInputs`. +function getSinkInputs() { + sinkInputs=$(pacmd list-sink-inputs | grep -B 4 "sink: $1 " | awk '/index:/{print $2}') +} + + +function volUp() { + # Obtaining the current volume from pacmd into $curVol. + if ! getCurSink; then + echo "PulseAudio not running" + return 1 + fi + getCurVol "$curSink" + local maxLimit=$((MAX_VOL - INC)) + + # Checking the volume upper bounds so that if MAX_VOL was 100% and the + # increase percentage was 3%, a 99% volume would top at 100% instead + # of 102%. If the volume is above the maximum limit, nothing is done. + if [ "$curVol" -le "$MAX_VOL" ] && [ "$curVol" -ge "$maxLimit" ]; then + pactl set-sink-volume "$curSink" "$MAX_VOL%" + elif [ "$curVol" -lt "$maxLimit" ]; then + pactl set-sink-volume "$curSink" "+$INC%" + fi + + if [ $OSD = "yes" ]; then showOSD "$curSink"; fi + if [ $AUTOSYNC = "yes" ]; then volSync; fi +} + + +function volDown() { + # Pactl already handles the volume lower bounds so that negative values + # are ignored. + if ! getCurSink; then + echo "PulseAudio not running" + return 1 + fi + pactl set-sink-volume "$curSink" "-$INC%" + + if [ $OSD = "yes" ]; then showOSD "$curSink"; fi + if [ $AUTOSYNC = "yes" ]; then volSync; fi +} + + +function volSync() { + if ! getCurSink; then + echo "PulseAudio not running" + return 1 + fi + getSinkInputs "$curSink" + getCurVol "$curSink" + + # Every output found in the active sink has their volume set to the + # current one. This will only be called if $AUTOSYNC is `yes`. + for each in $sinkInputs; do + pactl set-sink-input-volume "$each" "$curVol%" + done +} + + +function volMute() { + # Switch to mute/unmute the volume with pactl. + if ! getCurSink; then + echo "PulseAudio not running" + return 1 + fi + if [ "$1" = "toggle" ]; then + getIsMuted "$curSink" + if [ "$isMuted" = "yes" ]; then + pactl set-sink-mute "$curSink" "no" + else + pactl set-sink-mute "$curSink" "yes" + fi + elif [ "$1" = "mute" ]; then + pactl set-sink-mute "$curSink" "yes" + elif [ "$1" = "unmute" ]; then + pactl set-sink-mute "$curSink" "no" + fi + + if [ $OSD = "yes" ]; then showOSD "$curSink"; fi +} + + +function nextSink() { + # The final sinks list, removing the blacklisted ones from the list of + # currently available sinks. + if ! getCurSink; then + echo "PulseAudio not running" + return 1 + fi + + # Obtaining a tuple of sink indexes after removing the blacklisted devices + # with their name. + sinks=() + local i=0 + while read -r line; do + index=$(echo "$line" | cut -f1) + name=$(echo "$line" | cut -f2) + + # If it's in the blacklist, continue the main loop. Otherwise, add + # it to the list. + for sink in "${SINK_BLACKLIST[@]}"; do + if [ "$sink" = "$name" ]; then + continue 2 + fi + done + + sinks[$i]="$index" + i=$((i + 1)) + done < <(pactl list short sinks) + + # If the resulting list is empty, nothing is done + if [ ${#sinks[@]} -eq 0 ]; then return; fi + + # If the current sink is greater or equal than last one, pick the first + # sink in the list. Otherwise just pick the next sink avaliable. + local newSink + if [ "$curSink" -ge "${sinks[-1]}" ]; then + newSink=${sinks[0]} + else + for sink in "${sinks[@]}"; do + if [ "$curSink" -lt "$sink" ]; then + newSink=$sink + break + fi + done + fi + + # The new sink is set + pacmd set-default-sink "$newSink" + + # Move all audio threads to new sink + local inputs=$(pactl list short sink-inputs | cut -f 1) + for i in $inputs; do + pacmd move-sink-input "$i" "$newSink" + done + + if [ $NOTIFICATIONS = "yes" ]; then + getNickname "$newSink" + + if command -v dunstify &>/dev/null; then + notify="dunstify --replace 201839192" + else + notify="notify-send" + fi + $notify "PulseAudio" "Changed output to $nickname" --icon=audio-headphones-symbolic & + fi +} + + +# This function assumes that PulseAudio is already running. It only supports +# KDE OSDs for now. It will show a system message with the status of the +# sink passed by parameter, or the currently active one by default. +function showOSD() { + if [ -z "$1" ]; then + curSink="$1" + else + getCurSink + fi + getCurVol "$curSink" + getIsMuted "$curSink" + qdbus org.kde.kded /modules/kosd showVolume "$curVol" "$isMuted" +} + + +function listen() { + local firstRun=0 + + # Listen for changes and immediately create new output for the bar. + # This is faster than having the script on an interval. + LANG=$LANGUAGE pactl subscribe 2>/dev/null | { + while true; do + { + # If this is the first time just continue and print the current + # state. Otherwise wait for events. This is to prevent the + # module being empty until an event occurs. + if [ $firstRun -eq 0 ]; then + firstRun=1 + else + read -r event || break + # Avoid double events + if ! echo "$event" | grep -e "on card" -e "on sink" -e "on server"; then + continue + fi + fi + } &>/dev/null + output + done + } +} + + +function output() { + if ! getCurSink; then + echo "PulseAudio not running" + return 1 + fi + getCurVol "$curSink" + getIsMuted "$curSink" + + # Fixed volume icons over max volume + local iconsLen=${#VOLUME_ICONS[@]} + if [ "$iconsLen" -ne 0 ]; then + local volSplit=$((MAX_VOL / iconsLen)) + for i in $(seq 1 "$iconsLen"); do + if [ $((i * volSplit)) -ge "$curVol" ]; then + volIcon="${VOLUME_ICONS[$((i-1))]}" + break + fi + done + else + volIcon="" + fi + + getNickname "$curSink" + + # Showing the formatted message + if [ "$isMuted" = "yes" ]; then + echo "${MUTED_COLOR}${MUTED_ICON}${curVol}% ${SINK_ICON}${nickname}${END_COLOR}" + else + echo "${volIcon}${curVol}% ${SINK_ICON}${nickname}" + fi +} + + +function usage() { + echo "Usage: $0 ACTION" + echo "" + echo "Actions:" + echo " help display this help and exit" + echo " output print the PulseAudio status once" + echo " listen listen for changes in PulseAudio to automatically" + echo " update this script's output" + echo " up, down increase or decrease the default sink's volume" + echo " mute, unmute mute or unmute the default sink's audio" + echo " togmute switch between muted and unmuted" + echo " next-sink switch to the next available sink" + echo " sync synchronize all the output streams volume to" + echo " the be the same as the current sink's volume" + echo "" + echo "Author:" + echo " Mario O. M." + echo "More info on GitHub:" + echo " https://github.com/marioortizmanero/polybar-pulseaudio-control" +} + + +case "$1" in + up) + volUp + ;; + down) + volDown + ;; + togmute) + volMute toggle + ;; + mute) + volMute mute + ;; + unmute) + volMute unmute + ;; + sync) + volSync + ;; + listen) + listen + ;; + next-sink) + nextSink + ;; + output) + output + ;; + *) + usage + ;; +esac