How to switch audio output in FreeBSD on the fly
That's quite a known problem in FreeBSD that most programs do not respect FreeBSD audio subsystem and won't react to switching audio outputs using mixerctl or mixertui.
Usually you'd have to restart the program so that it would acknowledge the change.
Thankfully, there's FreeBSD documentation that explains how to fix that.
You can generally follow the steps explained there about virtual_oss, but it boils down to:
pkg install virtual_oss
service virtual_oss enable
service virtual_oss start
Then you have to determine your sound devices:
me@fbdesktop:~ % cat /dev/sndstat
Installed devices:
pcm0: <Realtek ALC887 (Rear Analog 5.1/2.0)> (play/rec)
pcm1: <Realtek ALC887 (Front Analog)> (play/rec)
pcm2: <Realtek ALC887 (Rear Digital)> (play)
pcm3: <Intel Cougar Point (HDMI/DP 8ch)> (play)
pcm4: <Intel Cougar Point (HDMI/DP 8ch)> (play)
pcm5: <Intel Cougar Point (HDMI/DP 8ch)> (play)
pcm6: <XiiSound Technology Corporation GG-HS420W> (play/rec) default
Installed devices from userspace:
dsp: <Virtual OSS> (play/rec)
So in my case I need pcm0 (rear output) and pcm6 (my wireless headphones).
To actually switch audio output you need one of these commands:
virtual_oss_cmd /dev/dsp.ctl -f /dev/dsp0
virtual_oss_cmd /dev/dsp.ctl -f /dev/dsp6
I have to point out that documentation uses /dev/vdsp.ctl file which doesn't exist on my system.
But these commands require root privileges, so I added this to my doas.conf:
permit nopass :wheel as root cmd /usr/local/sbin/virtual_oss_cmd
...Aaaand Firefox still doesn't care about this. But we can fix this too.
If you use Firefox or any of its fork, you should go to about:config and look for media.cubeb.backend parameter.
If it doesn't exist (it probably doesn't), you should create it (String parameter) with the value "oss" (without quotes).
It basically tells Firefox to use OSS as a backend.
mpv, qutebrowser just work without any tinkering.
With these simple steps my audio now switches on the fly, no need to restart an application or pause/unpause.
You can write a simple script using dmenu or rofi or create a hotkey (depending on your preferred WM/DE) to switch audio outputs.