Firefox drops ALSA; apulse to the rescue

John Tsiombikas

11 December 2017

Once again I'm caught between a rock and a stupid place. Mozilla joined Harry Pottering and the eternal september of GNU/Linux, who carries on dead-set on tearing down everything simple and elegant in the userland, replacing it with crude immitations of the beast (MacOS X). So in an inspired move, firefox went bananas and dropped its ALSA audio backend with release 57. And everyone who doesn't fancy spending 10% of their battery life on a byzantine audio contraption, is left with silent southpark, and kung fury without the awesome 80s synths and the buttery voice of David Hasselhoff.

I tried switching to chromium for a month, but I just couldn't stomach it. Now I always maintained that if everyone switches to pulse audio, I can always make a pulse wrapper over alsa, but I really didn't want to have to deal with that. Thankfully, I didn't have to bother, because a guy called Rinat Ibragimov beat me to it, and wrote apulse: a thin libpulse replacment which works with ALSA.

So in theory running apulse firefox should be sufficient to have sound in firefox 57 again. Unfortunately I had to take some more steps, and since I'm certain I'll forget all about them next time I’m trying to do the same on another computer, I'll keep a note here of the extra steps I had to take, to make apulse work with firefox on my computer.

Sandbox security settings

Firefox now runs tabs in their own process with extra security, which by default disallows ad-hoc filesystem access. In order for apulse to do its job, it needs to access the ALSA device files under /dev/snd, and the .asoundrc configuration file in the user's home directory. Alsa also needs to be able to call ioctl system calls. To this end we have to modify a few about:config settings. Specifically:

Selecting the correct playback device

If we don't want apulse to try and use the default alsa device for audio playback, we need to set the APULSE_PLAYBACK_DEVICE environment variable. This is particularly important because firefox tries to output floating point audio samples, and the dmix (software mixing) output which is probably the default, or even worse hw, doesn't do format conversions. A list of currently available devices can be obtained by running aplay -L.

Initially I tried setting APULSE_PLAYBACK_DEVICE=plughw:0,0 which handles format conversions, but unfortunately then I lost the ability to mix the audio output of multiple processes, and whenever one firefox tab was playing sound or even holding the device open for some reason, nothing else in the system (not even another firefox tab) could. One way to fix this problem is to define another plug type output (in .asoundrc), which then feeds dmix instead of hw as is the case with plughw. Here's what I used in my .asoundrc to achieve that:

pcm.plugdmix {
    type plug
    slave.pcm "dmix"

Then it's only a matter of setting APULSE_PLAYBACK_DEVICE=plugdmix, and I have both format conversions and software mixing at the same time.

Selecting the correct recording device

Less important, but sometimes it's nice to have recording capability in the browser. I'm using a USB webcam as microphone, so in order to direct apulse to use it, I need to set APULSE_CAPTURE_DEVICE=plughw:2,0 (0 is the embedded sound chip, 1 is the nvidia HDMI audio, and 2 is my USB webcam). Actually it might be preferable to just set this device as the default in .asoundrc, but I never bothered, since all programs usually have settings for which device to use.

This was initially posted in my old wordpress blog. Visit the original version to see any comments.

Discuss this post

Back to my blog