FreeBSD Desktop – Part 29 – Configuration – Audio Improvements

I recently added some improvements to my audio configs and settings on FreeBSD desktop.


freebsd-audio

Each of these ideas is nothing special or groundbreaking – but they all improve usability of daily FreeBSD desktop experience.

The Table of Contents for this article contains.

  • Default Audio Output
  • PulseAudio Output Change
  • Openbox Generated Sound Menu
  • Automatic Audio Output Change
  • Direct Deadbeef Audio Controls
  • Reset mixer(1) Settings
  • Sound for USB Device Attach/Detach
  • Default Audio Output
  • Summary

One of the usual things on a FreeBSD desktop is that user needs to – after attaching USB headphones – manually switch to them with sysctl(8) as root and then restart all audio apps so they will be able to use new audio output.

// LIST SOUND DEVICES

desktop # cat /dev/sndstat
Installed devices:
pcm0: <Conexant CX20590 (Analog 2.0+HP/2.0)> (play/rec) default
No devices installed from userspace



// AFTER ATTACHING USB HEADPHONES NEW pcm1 DEVICE APPEARS

desktop # cat /dev/sndstat
Installed devices:
pcm0: <Conexant CX20590 (Analog 2.0+HP/2.0)> (play/rec)
pcm1: <USB audio> (play/rec) default
No devices installed from userspace



// SWITCH TO NEW pcm1 DEVICE WITH sysctl(8) COMMAND

desktop # sysctl hw.snd.default_unit=1

… and after you are done listening the audio on USB audio device – then You need to do the opposite – switch back the hw.snd.default_unit to 0 sound device and also restart the audio apps again.

PulseAudio Output Change

On of the things that is indirectly forced on FreeBSD desktop users is PulseAudio. Not that long from now Firefox default audio output was switched from native FreeBSD OSS to PulseAudio for example. More and more apps are switched to it … but there at least is ONE advantage in that situation. When using PulseAudio You can switch its output on the fly as many times as You want without the need to kill or restart the applications playing audio.

Here is how it looks from the command line perspective.

// LIST PulseAudio OUTPUTS

desktop % pactl list sinks | grep 'Name: '
        Name: oss_output.dsp0
        Name: oss_output.dsp1

desktop % pactl get-default-sink
oss_output.dsp0



// SET dsp1 (ITS pcm1 ON FREEBSD DEVICES) AS DEFAULT AUDIO OUTPUT

desktop % pactl set-default-sink oss_output.dsp1

desktop % pactl get-default-sink
oss_output.dsp1



// SWITCH BACK TO dsp0 AUDIO OUTPUT

desktop % pactl set-default-sink oss_output.dsp0

desktop % pactl get-default-sink
oss_output.dsp0

But You can also use GUI pavucontrol(1) command to change PulseAudio output.

Here is the Playback tab opened.

pavucontrol-list

… and here is how You can switch current output audio device on the fly.

pavucontrol-select

Openbox Generated Sound Menu

I used it since quite long time – but I updated it with news links – for example to PulseAudio graphical interface.

The part that goes into the Openbox menu configurations is shown below.

<menu id="sound" label="sound" execute="__openbox_freebsd_sound.sh" icon="/home/vermaden/.config/openbox/icons/speaker.png" />

It looks like that on my system.

openbox-sound-menu

If You use Openbox then you may download it from this – __openbox_freebsd_sound.sh – place.

Automatic Audio Output Change

It is possible – with the use of FreeBSD devd(8) daemon – to make FreeBSD automatically switch to new audio source after its attach. I wrote the audio-source-switch.sh script for that purpose.

Here is the needed devd(8) configuration to make it work.

desktop # pkg install -y x11/zenity

desktop % cat /usr/local/etc/devd/audio_source.conf
                                                                                                                                                         
# USB/HEADPHONES/attach
attach 100 {
  device-name "pcm[0-9]+";
  action "su -l vermaden -c 'env DISPLAY=:0 /home/vermaden/scripts/audio-source-switch.sh attach 1> /dev/null 2> /dev/null &' &";
};

# USB/HEADPHONES/detach
detach 100 {
  device-name "pcm[0-9]+";
  action "su -l vermaden -c 'env DISPLAY=:0 /home/vermaden/scripts/audio-source-switch.sh detach 1> /dev/null 2> /dev/null &' &";
};

Remember to restart the devd(8) daemon everytime You dump a new config in the /usr/local/etc/devd directory.

Keep in mind that x11/zenity is needed for it to display information properly.

Now – after this change – when You plug in new USB audio output – You will see this zenity(1) dialog window.

new-audio-nothing-playing-attach

But that is only if You DO NOT play any audio currently.

If – for example – You currently use Deadbeef audio player to play music – You will see this zenity(1) dialog instead.

new-audio-output-attach

It will ask You if You want to kill that Deadbeef PID – so if You start it again – You will be able to use new audio output – but You may NOT want to kill it – hence the question.

You may also recompile Deadbeef with PulseAudio output support. Here is how the Deadbeef options in Preferences looks like after recompilation with PulseAudio support.

deadbeed-pulseaudio-output

If You already have another USB audio output attached and decided to detach it – and nothing is playing the audio – my zenity(1) script will dialog this dialog.

new-audio-nothing-playing-detach

… and if something is using the FreeBSD audio/sound subsystem – then this one.

tint2-deadbeef-buttons

Direct Deadbeef Audio Controls

I really like the mouse I use daily – the Logitech M720 – as much as I really like to use the additional buttons to increase/decrease the volume – I would really wish it would have ANOTHER two additional buttons for the next and previous song on the Deadbeef player.

Because of that I decided to add a dedicated set of buttons on my Tint2 bar on top – that would allow me to change the current Deadbeef song to the next one … or previous one … or pause it.

new-audio-output-detach

The Tint2 config was updates with this content.

desktop % grep player ~/.tint2rc
  launcher_item_app      = /home/vermaden/.apps/player-prev.desktop
  launcher_item_app      = /home/vermaden/.apps/player-stop.desktop
  launcher_item_app      = /home/vermaden/.apps/player-pause.desktop
  launcher_item_app      = /home/vermaden/.apps/player-play.desktop
  launcher_item_app      = /home/vermaden/.apps/player-next.desktop

… and the Deadbeef buttons configs looks as follows.

desktop % cat ~/.apps/player-next.desktop
[Desktop Entry]
Type=Application
Name=Deadbeef
Exec=deadbeef --next
Icon=/home/vermaden/.icons/vermaden/player-next.png

desktop % cat ~/.apps/player-pause.desktop
[Desktop Entry]
Type=Application
Name=Deadbeef
Exec=deadbeef --toggle-pause
Icon=/home/vermaden/.icons/vermaden/player-pause.png

desktop % cat ~/.apps/player-play.desktop
[Desktop Entry]
Type=Application
Name=Deadbeef
Exec=deadbeef --play
Icon=/home/vermaden/.icons/vermaden/player-play.png

desktop % cat ~/.apps/player-prev.desktop
[Desktop Entry]
Type=Application
Name=Deadbeef
Exec=deadbeef --prev
Icon=/home/vermaden/.icons/vermaden/player-prev.png

desktop % cat ~/.apps/player-stop.desktop
[Desktop Entry]
Type=Application
Name=Deadbeef
Exec=deadbeef --stop
Icon=/home/vermaden/.icons/vermaden/player-stop.png

Reset mixer(1) Settings

One of the things that annoyed me was the mixer settings when I tried to join some call/teleconference. It seemed like a random pointless fuckup. Not anymore. With small and simple mix.sh script it all gets to normal and everything works out of the box.

Here is how the mix.sh script looks like.

desktop % cat ~/scripts/mix.sh
mixer vol.volume=0.6
mixer mic.volume=0.85
mixer rec.volume=0.85
mixer pcm.volume=1.0
mixer speaker.volume=0.0
mixer monitor.volume=0.0
mixer

… and how it works.

desktop % mix.sh 
pcm0:mixer:  on hdaa0  (play/rec) (default)
    vol       = 0.60:0.60     pbk
    pcm       = 1.00:1.00     pbk
    speaker   = 0.00:0.00     pbk
    mic       = 0.85:0.85     rec src
    rec       = 0.85:0.85     pbk
    monitor   = 0.00:0.00     rec

Sound for USB Device Attach/Detach

Most desktop oriented operating systems do play some type of sound for device attach/detach so the user would get a feedback that the system is aware of his actions – like – well – attaching or detaching a USB device πŸ™‚

By default FreeBSD does not do anything like that – but its not hard to add such an action to the FreeBSD devd(8) daemon.

With the following devd(8) config FreeBSD will now play a dedicated sound on each USB device attach or detach event.

In the beginning I did not knew which sound to pick from – but after some thoughts I decided to pick some Worms Armageddon sounds – from the 007 sound theme.

worms-logo

The devd(8) config looks like that one below.

desktop # pkg install -y audio/mpg123

desktop % cat /usr/local/etc/devd/USB.conf

# USB/attach
notify 10 {
  match "system" "USB";
  match "type"   "ATTACH";
  action "su -l vermaden -c 'env DISPLAY=:0 /usr/local/bin/mpg123 /usr/local/etc/devd/USB.attach.mp3' &";
};

# USB/detach
notify 10 {
  match "system" "USB";
  match "type"   "DETACH";
  action "su -l vermaden -c 'env DISPLAY=:0 /usr/local/bin/mpg123 /usr/local/etc/devd/USB.detach.mp3' &";
};

I also assume that You will have audio/mpg123 installed to play these sounds.

Because WordPress is very limited – it will not allow me to upload plain MP3 files – but we will overcome that limitation. For the record – it is not a technical limitation – its just a limitation of the FREE PLAN that I am using on the WordPress page.

bear-grylls

Here are the commands You need to execute to fetch these two MP3 files.

desktop ~ # fetch \
              -o /usr/local/etc/devd/usb.detach.mp3.zip
              https://vermaden.files.wordpress.com/2024/01/usb.detach.mp3_.docx
/usr/local/etc/devd/usb.detach.mp3.zip                9588  B   40 MBps    00s

desktop ~ # fetch \
              -o /usr/local/etc/devd/usb.attach.mp3.zip \
              https://vermaden.files.wordpress.com/2024/01/usb.attach.mp3_.docx
/usr/local/etc/devd/usb.attach.mp3.zip                  11 kB   41 MBps    00s

desktop ~ # cd /usr/local/etc/devd

desktop /usr/local/etc/devd # unzip usb.detach.mp3.zip
Archive:  usb.detach.mp3.zip
 extracting: USB.detach.mp3  

desktop /usr/local/etc/devd # unzip usb.attach.mp3.zip
Archive:  usb.attach.mp3.zip
 extracting: USB.attach.mp3  

Now as You have the needed MP3 files – restart the devd(8) daemon.

Now everytime You will attach or detach USB device You will hear appropriate Worms Armageddon sound.

Summary

I think that I can say that nothing prevents You from running FreeBSD desktop daily. If the FreeBSD is the desktop You want – and You are still running macOS or Windows instead – You are just lazy as fuck πŸ™‚

UPDATE 1 – Other FreeBSD Audio Improvements

As usual I got a lot additional good stuff from the comments from many places.

Below I would try to summarize them.

Firefox

For the Firefox browser its possible to check the media/audio devices with about:support#media URL.

UPDATE1-firefox-media

GTK-Mixer

To have a GUI for the various volume settings You can use GTK-Mixer and its available in the FreeBSD package as audio/gtk-mixer name.

desktop # pkg install audio/gtk-mixer

desktop % gtk-mixer

Here is how it looks like.

UPDATE1-gtk-mixer

FreeBSD Audio Stack Improvements

Seems that Christos Margiolis is already working on some Audio Stack Improvements on FreeBSD thanks to FreeBSD Foundation.

This is his message:

The past (and first) week working on the audio stack, sponsored by the FreeBSD Foundation, I:

- Set up my development environment; a VM image running -CURRENT in bhyve with PCI-passthru
  enabled to do all of the driver (kernel generallly) development in the VM.

- Wrote a small series of patches for vmrun.sh:
  https://reviews.freebsd.org/D43269
  https://reviews.freebsd.org/D43270

- Modified the snd_uaudio(4) driver to provide information about the sound card
  (manufacturer, model and attached driver), as opposed to the current generic "USB Audio"
  string, so /dev/sndstat and programs like mixer(8) can output more useful information
  about USB audio devices.
  https://reviews.freebsd.org/D43347

- Submitted a patch to update (and unify) the description format for all sound devices,
  since some of them haven't been touched for years.
  https://reviews.freebsd.org/D43349

- Implemented device_set_descf() , a printf-like version of device_set_desc().
  https://reviews.freebsd.org/D43370

- Was preparing a few more smaller patches.

- Started looking into possible solutions to
  https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=194727
  also mentioned in the first paragraph of the BUGS section of the snd_uaudio(4) man page.

Christos

Check the the links from the message above – a lot of great FreeBSD Audio Stack changes are coming.

PulseAudio

Someone also notified my that instead of writing a script for PulseAudio to automatically switch to just connected device on could load the module-switch-on-port-available or module-switch-on-connect module.

Check the details in the pacmd list-modules command.

desktop % pacmd list-modules | grep -B 1 -A 7 module-switch 
    index: 4
        name: 
        argument: 
        used: -1
        load once: yes
        properties:
                module.author = "David Henningsson"
                module.description = "Switches ports and profiles when devices are plugged/unplugged"
                module.version = "16.1"

EOF

6 thoughts on “FreeBSD Desktop – Part 29 – Configuration – Audio Improvements

  1. Pingback: Valuable News – 2024/01/15 | πšŸπšŽπš›πš–πšŠπšπšŽπš—

  2. Olivier

    Thanks for one more awesome article!

    Regarding your MP3 file that you can’t upload on your WordPress, next time you can try another trick: using steganography! By using security/stegify ports and hiding the MP3 in a JPG file could be a fun way to make it work πŸ˜‰

    Like

    Reply
  3. henryhu9

    Ah finally! Someone will try to deal with the ‘user space app can block the kernel from suspend/shutdown’ issue, instead of blaming the user space app for that…

    Like

    Reply
  4. Chris

    Have you tried PipeWire yet on FreeBSD? On Linux this has become really mature as a drop-in replacement for the PulseAudio server and works very well. Although it is in ports and packages, I never managed to get it working on FreeBSD.

    Usually you just start pipewire, pipewire-pulse and wireplumber with XDG_RUNTIME_DIR set and pulseaudio disabled and it works. Yet on FreeBSD all I get is a dummy device in pavucontrol.

    Like

    Reply

Leave a comment