1

I am trying to configure Openbox's rc.xml file in order to manipulate my soundcards with one keypress. Because I have multiple sound cards on my system I have to manipulate multiple sinks at once so I use multiple commands separated with & like this:

    <keybind key="XF86AudioRaiseVolumen">
   <action name="Execute">
     <command>pactl set-sink-volume alsa_output.usb-Focusrite_Scarlett_2i4_USB-00.multichannel-output +5% & pactl set-sink-volume alsa_output.pci-0000_00_1b.0.analog-stereo +5% & pactl set-sink-volume alsa_output.usb-Focusrite_Scarlett_2i4_USB-00.analog-surround-40 +5%</command>
   </action>
</keybind>

For some reason this won't work in rc.xml. Can anyone help me?

4 Answers 4

3

You need to put the commands into a shell script, make that script executable and then uses this script as the command.

<command>/usr/local/bin/volume_up</command>

The contents of /usr/local/bin/volume_up

#!/bin/sh
pactl set-sink-volume alsa_output.usb-Focusrite_Scarlett_2i4_USB-00.multichannel-output +5% &
pactl set-sink-volume alsa_output.pci-0000_00_1b.0.analog-stereo +5% &
pactl set-sink-volume alsa_output.usb-Focusrite_Scarlett_2i4_USB-00.analog-surround-40 +5%

and make it executable

chmod +x /usr/local/bin/volume_up

The reason is that Openbox is not executing the contents of the command element in a shell instead it tries to execute it directly.

From the documentation for <command>:

A string which is the command to be executed, along with any arguments to be passed to it. The "~" tilde character will be expanded to your home directory, but no other shell expansions or scripting syntax may be used in the command unless they are passed to the sh command. Also, the & character must be written as & in order to be parsed correctly. is a deprecated name for .

Another benefit is that you can rewrite the script to also be able lower the volume

#!/bin/sh

change_volume() {
    pactl set-sink-volume alsa_output.usb-Focusrite_Scarlett_2i4_USB-00.multichannel-output "$1"
    pactl set-sink-volume alsa_output.pci-0000_00_1b.0.analog-stereo "$1"
    pactl set-sink-volume alsa_output.usb-Focusrite_Scarlett_2i4_USB-00.analog-surround-40 "$1"
}

main() {
    case "$1" in
      up)
         change_volume +5%
         ;;
      down)
         change_volume -5%
         ;;
     *)
         printf "volume <command>\n"
         printf "          up \n"
         printf "         down\n"
    esac
}

main "$@"

This would be saved under /usr/local/bin/volume and would be use like this

<command>/usr/local/bin/volume up</command>
<command>/usr/local/bin/volume down</command>
3
  • This is a possible fix, but not exactly what I need.
    – 71GA
    Sep 21, 2016 at 14:10
  • @71GA What is it that you need? Sep 21, 2016 at 14:41
  • @71GA I added the link to the documentation for <command> and the quote. It mentioned that you can call sh -c to do such a thing. Sep 21, 2016 at 14:48
3

If you do not mind the order and the fact that all of these will be executed more or less at once you can do:

<keybind key="XF86AudioRaiseVolumen">
   <action name="Execute">
     <command>pactl set-sink-volume alsa_output.usb-Focusrite_Scarlett_2i4_USB-00.multichannel-output +5%</command>
   </action>

   <action name="Execute">
     <command>pactl set-sink-volume alsa_output.pci-0000_00_1b.0.analog-stereo +5%</command>
   </action>

   <action name="Execute">
     <command>pactl set-sink-volume alsa_output.usb-Focusrite_Scarlett_2i4_USB-00.analog-surround-40 +5%</command>
   </action>
</keybind>
1
  • This is also a good suggestion! But in my case the order of commands matters.
    – 71GA
    Oct 21, 2018 at 7:26
1

I've created a bind which increase/decrease volume for all components, this way you will have sure that the wanted component will be affected, if want to make some component disabled just mute it.

<keybind key="XF86AudioRaiseVolume">
  <action name="Execute">
    <command>bash -c "pactl list | grep -oP 'Sink #\K([0-9]+)' | while read -r i ; do pactl -- set-sink-volume $i +3% ; done"</command>
  </action>
</keybind>
<!--  decrease volume  -->
<keybind key="XF86AudioLowerVolume">
  <action name="Execute">
    <command>bash -c "pactl list | grep -oP 'Sink #\K([0-9]+)' | while read -r i ; do pactl -- set-sink-volume $i -3% ; done"</command>
  </action>
</keybind>
0

I guess this would be cleaner and shorter for your use case:

<keybind key="XF86AudioLowerVolume">
 <action name="Execute">
  <command>sh -c "pactl list sinks | grep 'Sink #' | cut -d'#' -f2 | xargs -I@ pactl -- set-sink-volume @ -2000"</command>
 </action>
</keybind>
<keybind key="XF86AudioRaiseVolume">
 <action name="Execute">
  <command>sh -c "pactl list sinks | grep 'Sink #' | cut -d'#' -f2 | xargs -I@ pactl -- set-sink-volume @ +2000"</command>
 </action>
</keybind>

It will list all the sinks and for each increase/decrease the volume. For example when you have jack or bluetooth speakers connected there will be multiple. This is exactly the setup that I am using.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .