greshake / i3status-rust

Very resourcefriendly and feature-rich replacement for i3status, written in pure Rust
GNU General Public License v3.0
2.81k stars 472 forks source link

How to hide sound blocks for devices that are not present? (bluetooth/USB headsets, etc) #2023

Closed ashleyghooper closed 3 months ago

ashleyghooper commented 3 months ago

I use multiple sound sinks during a user session, for example I use headsets sometimes.

I was using a sound block generated from the below Nix code, which covers all sinks:

           {
             block = "sound";
             driver = "pulseaudio";
             format = " $output_name{$volume|N/A}";
             name = "alsa_output.usb-Logitech_Logitech_USB_Headset-00.analog-stereo";
             mappings = {
               "alsa_output.pci-0000_00_1b.0.analog-stereo" = "🔈";
               "alsa_output.pci-0000_00_1b.0.pro-output-3" = "🔈";
               "alsa_output.usb-Logitech_Logitech_USB_Headset-00.analog-stereo" = "🎧";
               "bluez_output.F4_B6_88_76_30_85.1" = "🎧";
               "bluez_sink.F4_B6_88_76_30_85.a2dp_sink" = "🎧";
               "bluez_sink.F4_B6_88_76_30_85.handsfree_head_unit" = "🎧";
               "bluez_sink.F4_B6_88_76_30_85.*" = "🎧";
             };
           }

With the above, I can only adjust sound for the built-in sound card, so I split into multiple blocks:

            {
              block = "sound";
              driver = "pulseaudio";
              format = " $output_name{$volume|N/A}";
              name = "alsa_output.pci-0000_00_1b.0.analog-stereo";
              mappings = {
                "alsa_output.pci-0000_00_1b.0.*" = "🔈";
              };
            }
            {
              block = "sound";
              driver = "pulseaudio";
              format = " $output_name{$volume|N/A}";
              name = "alsa_output.usb-Logitech_Logitech_USB_Headset-00.analog-stereo";
              mappings = {
                "alsa_output.usb-Logitech_Logitech_USB_Headset-00.analog-stereo" = "🎧";
                "bluez_output.F4_B6_88_76_30_85.1" = "🎧";
                "bluez_sink.F4_B6_88_76_30_85.*" = "🎧";
              };
            }
            {
              block = "sound";
              driver = "pulseaudio";
              format = " $output_name{$volume|N/A}";
              name = "bluez_output.F4_B6_88_76_30_85.1";
              mappings = {
                "bluez_output.F4_B6_88_76_30_85.1" = "🎧";
                "bluez_sink.F4_B6_88_76_30_85.*" = "🎧";
              };
            }

Now I can adjust the volume, but I don't want to show the blocks for the 'pluggable' sinks when they aren't available. I see if_command but that doesn't seem to account for plugging in a sink during a session, but rather runs only on startup of the status bar.

Is there a way to do this?

(Also, you can see from my config mappings that would not be possible for the device name - it doesn't seem to be possible to use a wildcard for name - is that something that could be supported? Can log a feature request if so).

bim9262 commented 3 months ago

What I do is not specify a name at all and have a cmd assigned to the sound block that cycles the active sink. That way I can always see and change the active sink's volume.

I did a quick skim, it looks like a regex name could be supported.

ashleyghooper commented 3 months ago

Thank you, cycling the active sink is actually something I didn't think of and would save space on my bar.

So I'd just need one sound block and wouldn't need a regex for name, if I understand correctly.

bim9262 commented 3 months ago

Exactly!

This is my config:

[[block]]
block = "sound"
format = " $icon $output_name "
[[block.click]]
button = "left"
action = "toggle_mute"
[[block.click]]
button = "right"
cmd = "nextSink.awk"

This is the script I use to cycle the sinks: https://github.com/bim9262/dotfiles/blob/main/bin/executable_nextSink.awk

ashleyghooper commented 3 months ago

Here is another example in bash.