Commit c65106e3 authored by Tristan Matthews's avatar Tristan Matthews
Browse files

* #6852: alsa: retry if device is busy

This is due to an issue with dmix where it will not release the device
after being closed.
parent 73a54bf0
......@@ -101,11 +101,20 @@ AlsaLayer::~AlsaLayer (void)
closePlaybackStream();
}
// Retry approach taken from pa_linux_alsa.c, part of PortAudio
bool AlsaLayer::openDevice(snd_pcm_t **pcm, const std::string &dev, snd_pcm_stream_t stream)
{
int err = snd_pcm_open(pcm, dev.c_str(),stream, 0);
static const int MAX_RETRIES = 100;
int err = snd_pcm_open(pcm, dev.c_str(), stream, 0);
// Retry if busy, since dmix plugin may not have released the device yet
for (int tries = 0; tries < MAX_RETRIES and err == -EBUSY; ++tries) {
usleep(10000);
err = snd_pcm_open(pcm, dev.c_str(), stream, 0);
}
if (err < 0) {
_error("Alsa: couldn't open device %s : %s", dev.c_str(), snd_strerror(err));
_error("Alsa: couldn't open device %s : %s", dev.c_str(),
snd_strerror(err));
return false;
}
......@@ -141,9 +150,8 @@ AlsaLayer::startStream (void)
if (not is_capture_open_) {
is_capture_open_ = openDevice(&captureHandle_, pcmc, SND_PCM_STREAM_CAPTURE);
if (not is_capture_open_) {
if (not is_capture_open_)
Manager::instance().getDbusManager()->getConfigurationManager()->errorAlert(ALSA_CAPTURE_DEVICE);
}
}
if (not is_playback_open_) {
......
......@@ -146,6 +146,11 @@ class AlsaLayer : public AudioLayer
private:
/**
* Calls snd_pcm_open and retries if device is busy, since dmix plugin
* will often hold on to a device temporarily after it has been opened
* and closed.
*/
bool openDevice(snd_pcm_t **pcm, const std::string &dev, snd_pcm_stream_t stream);
/**
......
......@@ -1994,6 +1994,7 @@ void ManagerImpl::setAudioPlugin (const std::string& audioPlugin)
// Recreate audio driver with new settings
delete _audiodriver;
_audiodriver = new AlsaLayer;
assert(preferences.getAudioApi() == ALSA_API_STR);
if (wasStarted)
_audiodriver->startStream();
......@@ -2033,6 +2034,7 @@ void ManagerImpl::setAudioDevice (const int index, int streamType)
// Recreate audio driver with new settings
delete _audiodriver;
_audiodriver = new AlsaLayer;
assert(preferences.getAudioApi() == ALSA_API_STR);
if (wasStarted)
_audiodriver->startStream();
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment