I use volnoti, a notification service, together with my i3 window manager, in my i3config file I tried to implement the commands for volnoti like this:
# Pulse Audio controls
# Increase sound volume
bindsym XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-volume 1 +5% && pkill -RTMIN+1 i3blocks && volnoti-show $(amixer -c 1 -M -D pulse get Master | grep -o '[0-9]*%' -m 1 | grep -o '[0-9]*')
# Decrease sound volume
bindsym XF86AudioLowerVolume exec --no-startup-id pactl set-sink-volume 1 -5% && pkill -RTMIN+1 i3blocks && volnoti-show $(amixer -c 1 -M -D pulse get Master | grep -o '[0-9]*%' -m 1 | grep -o '[0-9]*')
# Mute sound
bindsym XF86AudioMute exec --no-startup-id pactl set-sink-mute 1 toggle && pkill -RTMIN+1 i3blocks && if [[ -n $(amixer -c 1 -M -D pulse get Master | grep '\[off\]' -m 1) ]]; then volnoti-show -m; else volnoti-show $(amixer -c 1 -M -D pulse get Master | grep -o '[0-9]*%' -m 1 | grep -o '[0-9]*'); fi
Increasing and decreasing is shown without problems, but if I mute the sound i3 logs this error:
ERROR: Could not translate string to key symbol: "split+h"
[libi3] ERROR: Surface 0x555ee0dfd3b0 is not initialized, skipping drawing.
[libi3] ERROR: Surface 0x555ee0dfd3b0 is not initialized, skipping drawing.
[libi3] ERROR: Surface 0x555ee0dfd3b0 is not initialized, skipping drawing.
ERROR: Received ConfigureNotify for unknown window 0x00800000
ERROR: Received ExposeEvent for unknown window 0x00800000
ERROR: Received ConfigureNotify for unknown window 0x00800000
ERROR: Received ConfigureNotify for unknown window 0x00800003
ERROR: Received ConfigureNotify for unknown window 0x00800003
ERROR: Received ConfigureNotify for unknown window 0x00800006
ERROR: Received ConfigureNotify for unknown window 0x00800006
ERROR: Received ConfigureNotify for unknown window 0x00800009
ERROR: Received ConfigureNotify for unknown window 0x00800009
ERROR: Received ConfigureNotify for unknown window 0x0080000c
ERROR: Received ConfigureNotify for unknown window 0x0080000c
ERROR: Expected one of these tokens: <end>, '[', 'move', 'exec', 'exit', 'restart', 'reload', 'shmlog', 'debuglog', 'border', 'layout', 'append_layout', 'workspace', 'focus', 'kill', 'open', 'fullscreen', 'sticky', 'split', 'floating', 'mark', 'unmark', 'resize', 'rename', 'nop', 'scratchpad', 'title_format', 'mode', 'bar'
ERROR: Your command: exec --no-startup-id pactl set-sink-mute 1 toggle && pkill -RTMIN+1 i3blocks && "if [[ -n $(amixer -c 1 -M -D pulse get Master | grep '\[off\]' -m 1) ]]; then volnoti-show -m; else volnoti-show $(amixer -c 1 -M -D pulse get Master | grep -o '[0-9]*%' -m 1 | grep -o '[0-9]*'); fi"
ERROR: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
I have to admit, it is not the most elegant solution. But it's working, except for the last line. If I execute the last part directly in a terminal, it's working fine and mute is detected properly:
if [[ -n $(amixer -c 1 -M -D pulse get Master | grep '\[off\]' -m 1) ]]; then volnoti-show -m; else volnoti-show $(amixer -c 1 -M -D pulse get Master | grep -o '[0-9]*%' -m 1 | grep -o '[0-9]*'); fi
There are a lot of pitfalls when using complex shell commands within the i3 configuration. i3 uses certain special characters as syntactic elements but does not provide a full featured way to quote them. In this case i3 interprets the ;
as an i3 command separator and expects that it is followed by an i3 command, which then
is not.
You can try putting the complete command part within double quotes, e.g.
bindsym XF86AudioMute exec --no-startup-id "pactl set-sink-mute 1 toggle && pkill -RTMIN+1 i3blocks && if [[ -n $(amixer -c 1 -M -D pulse get Master | grep '\[off\]' -m 1) ]]; then volnoti-show -m; else volnoti-show $(amixer -c 1 -M -D pulse get Master | grep -o '[0-9]*%' -m 1 | grep -o '[0-9]*'); fi"
This may or may not work. (And in the error message it looks like you already tried to quote a part of the command)
A better way to solve issues like this is usually to put the shell code into a script and just bind that to a shortcut.
Script, e.g. volcontrol.sh
:
#!/bin/sh
# Pulse Audio controls
case $1 in
raise)
# Increase sound volume
pactl set-sink-volume 1 +5% && pkill -RTMIN+1 i3blocks && volnoti-show $(amixer -c 1 -M -D pulse get Master | grep -o '[0-9]*%' -m 1 | grep -o '[0-9]*')
;;
lower)
# Decrease sound volume
pactl set-sink-volume 1 -5% && pkill -RTMIN+1 i3blocks && volnoti-show $(amixer -c 1 -M -D pulse get Master | grep -o '[0-9]*%' -m 1 | grep -o '[0-9]*')
;;
mute)
# Mute sound
pactl set-sink-mute 1 toggle && pkill -RTMIN+1 i3blocks && if [[ -n $(amixer -c 1 -M -D pulse get Master | grep '\[off\]' -m 1) ]]; then volnoti-show -m; else volnoti-show $(amixer -c 1 -M -D pulse get Master | grep -o '[0-9]*%' -m 1 | grep -o '[0-9]*'); fi
;;
esac
i3 config
# Pulse Audio controls
# Increase sound volume
bindsym XF86AudioRaiseVolume exec --no-startup-id /path/to/volcontrol.sh raise
# Decrease sound volume
bindsym XF86AudioLowerVolume exec --no-startup-id /path/to/volcontrol.sh lower
# Mute sound
bindsym XF86AudioMute exec --no-startup-id /path/to/volcontrol.sh mute
This avoids all issues with i3 misunderstanding shell code for configuration settings and so allows for more flexibility, especially when chaining multiple shell commands or using more complex shell contstructs.
User contributions licensed under CC BY-SA 3.0