summaryrefslogtreecommitdiff
path: root/Source/Core/AudioCommon/AlsaSoundStream.cpp
diff options
context:
space:
mode:
authorScott Mansell <phiren@gmail.com>2015-09-30 00:51:34 +1300
committerScott Mansell <phiren@gmail.com>2015-10-03 16:31:55 +1300
commita10a3ecbaccbbbdc31be5898cbc9a88ab2d8b872 (patch)
tree9b57a28c4b3cd70a73102b2f7e87cc9127027b55 /Source/Core/AudioCommon/AlsaSoundStream.cpp
parent6658d21215e459591ffc1c007def8e015ee4b4d9 (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.cpp46
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()