I have coded an application that uses ALSA and plays back movie's audios, together with their videos. I have pulseaudio installed by default as it comes with Ubuntu Xenian.
My goal is to provide the user with an easy pull-down where they can select the audio device to play the audio in.
The first audio device is "default" and defaults to ALSA's default in the Ubuntu Sound Preferences. All that works fine. I can change the Ubuntu Sound Preferences and the default driver immediately picks up the other cards or outputs in the system.
My problem is that when I choose the default, which is equivalent to plughw:0,0, when I go to force select in my program the plughw:0,0 (HDA Intel PCH: ALC1150 Analog), I get a Device or resource busy.
Sure enough, if I do:
$ fuser -v /dev/snd/* USUARIO ORDEN DE ACCESO PID /dev/snd/controlC0: gga 3594 F.... pulseaudio /dev/snd/controlC1: gga 3594 F.... pulseaudio /dev/snd/pcmC0D0p: gga 4821 F...m pulseaudio
I am very careful in closing the audio before reopening it again. However the resource remains busy for about 7 seconds. Then it turns into:
USUARIO ORDEN DE ACCESO PID /dev/snd/controlC0: gga 3594 F.... pulseaudio /dev/snd/controlC1: gga 3594 F.... pulseaudio /dev/snd/pcmC0D0p: gga 4821 F...m mrViewer
and the audio works again. My close function looks like:
bool ALSAEngine::close() {
if ( _pcm_handle ) { int err = snd_pcm_drop( _pcm_handle ); if ( err < 0 ) { std::cerr << "ERROR: [alsa] snd_pcm_drop failed with " << snd_strerror(err) << std::endl; } err = snd_pcm_close( _pcm_handle ); if ( err < 0 ) { std::cerr << "ERROR: [alsa] snd_pcm_close failed with " << snd_strerror(err) << std::endl; } _pcm_handle = NULL; }
return true; }
and the open function (simplified till it fails).
bool ALSAEngine::open( const unsigned channels, const unsigned freq, const AudioFormat format, const unsigned bits ) {
try { close();
int status; unsigned int test_format = (unsigned int) format; char buf[256];
/* Open the audio device */ /* Name of device should depend on # channels in spec */ _pcm_handle = NULL; status = snd_pcm_open(&_pcm_handle, device().c_str(), SND_PCM_STREAM_PLAYBACK, 0);
if ( status < 0 || _pcm_handle == NULL ) { sprintf( buf, _("Couldn't open audio device %s: %s"), device().c_str(), snd_strerror(status)); THROW(buf); }
....snip.....
}