diff options
| author | Scott Mansell <phiren@gmail.com> | 2015-09-30 00:51:34 +1300 |
|---|---|---|
| committer | Scott Mansell <phiren@gmail.com> | 2015-10-03 16:31:55 +1300 |
| commit | a10a3ecbaccbbbdc31be5898cbc9a88ab2d8b872 (patch) | |
| tree | 9b57a28c4b3cd70a73102b2f7e87cc9127027b55 /Source/Core/AudioCommon/AlsaSoundStream.cpp | |
| parent | 6658d21215e459591ffc1c007def8e015ee4b4d9 (diff) | |
ALSA: Don't block on Clear() call.
snd_pcm_writei() is meant to block block until all samples are written,
but apparently in some situations it can block for much longer, prehaps
even a infinite time, in the case of virtual machine FifoCI runs in.
Because it grabed a mutex before blocking, it could also block the
Clear() call for an infinite length of time, blocking dolphin's emu
thread.
snd_pcm_writei() also takes 10-15 seconds if you run dolphin under GDB
and can randomly take 5 or so seconds during normal usage.
By moving all the pause code to the ALSA thread, Clear() no-longer
blocks and everyone keeps their sanity.
Diffstat (limited to 'Source/Core/AudioCommon/AlsaSoundStream.cpp')
| -rw-r--r-- | Source/Core/AudioCommon/AlsaSoundStream.cpp | 46 |
1 files changed, 23 insertions, 23 deletions
diff --git a/Source/Core/AudioCommon/AlsaSoundStream.cpp b/Source/Core/AudioCommon/AlsaSoundStream.cpp index 10b05e8441..19a21acf66 100644 --- a/Source/Core/AudioCommon/AlsaSoundStream.cpp +++ b/Source/Core/AudioCommon/AlsaSoundStream.cpp @@ -48,21 +48,31 @@ void AlsaSound::Update() void AlsaSound::SoundLoop() { Common::SetCurrentThreadName("Audio thread - alsa"); - while (m_thread_status.load() == ALSAThreadStatus::RUNNING) + while (m_thread_status.load() != ALSAThreadStatus::STOPPING) { - std::unique_lock<std::mutex> lock(cv_m); - cv.wait(lock, [this]{return !m_muted || m_thread_status.load() != ALSAThreadStatus::RUNNING;}); - - m_mixer->Mix(mix_buffer, frames_to_deliver); - int rc = snd_pcm_writei(handle, mix_buffer, frames_to_deliver); - if (rc == -EPIPE) + while (m_thread_status.load() == ALSAThreadStatus::RUNNING) { - // Underrun - snd_pcm_prepare(handle); + m_mixer->Mix(mix_buffer, frames_to_deliver); + int rc = snd_pcm_writei(handle, mix_buffer, frames_to_deliver); + if (rc == -EPIPE) + { + // Underrun + snd_pcm_prepare(handle); + } + else if (rc < 0) + { + ERROR_LOG(AUDIO, "writei fail: %s", snd_strerror(rc)); + } } - else if (rc < 0) + if (m_thread_status.load() == ALSAThreadStatus::PAUSED) { - ERROR_LOG(AUDIO, "writei fail: %s", snd_strerror(rc)); + snd_pcm_drop(handle); // Stop sound output + + // Block until thread status changes. + std::unique_lock<std::mutex> lock(cv_m); + cv.wait(lock, [this]{ return m_thread_status.load() != ALSAThreadStatus::PAUSED; }); + + snd_pcm_prepare(handle); // resume sound output } } AlsaShutdown(); @@ -73,18 +83,8 @@ void AlsaSound::SoundLoop() void AlsaSound::Clear(bool muted) { m_muted = muted; - if (m_muted) - { - std::lock_guard<std::mutex> lock(cv_m); - snd_pcm_drop(handle); - } - else - { - std::unique_lock<std::mutex> lock(cv_m); - snd_pcm_prepare(handle); - lock.unlock(); - cv.notify_one(); - } + m_thread_status.store(muted ? ALSAThreadStatus::PAUSED : ALSAThreadStatus::RUNNING); + cv.notify_one(); // Notify thread that status has changed } bool AlsaSound::AlsaInit() |
