mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-26 15:55:31 +01:00
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.
This commit is contained in:
parent
6658d21215
commit
a10a3ecbac
@ -48,21 +48,31 @@ void AlsaSound::Update()
|
|||||||
void AlsaSound::SoundLoop()
|
void AlsaSound::SoundLoop()
|
||||||
{
|
{
|
||||||
Common::SetCurrentThreadName("Audio thread - alsa");
|
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);
|
while (m_thread_status.load() == ALSAThreadStatus::RUNNING)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
// Underrun
|
m_mixer->Mix(mix_buffer, frames_to_deliver);
|
||||||
snd_pcm_prepare(handle);
|
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();
|
AlsaShutdown();
|
||||||
@ -73,18 +83,8 @@ void AlsaSound::SoundLoop()
|
|||||||
void AlsaSound::Clear(bool muted)
|
void AlsaSound::Clear(bool muted)
|
||||||
{
|
{
|
||||||
m_muted = muted;
|
m_muted = muted;
|
||||||
if (m_muted)
|
m_thread_status.store(muted ? ALSAThreadStatus::PAUSED : ALSAThreadStatus::RUNNING);
|
||||||
{
|
cv.notify_one(); // Notify thread that status has changed
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AlsaSound::AlsaInit()
|
bool AlsaSound::AlsaInit()
|
||||||
|
@ -46,6 +46,7 @@ private:
|
|||||||
enum class ALSAThreadStatus
|
enum class ALSAThreadStatus
|
||||||
{
|
{
|
||||||
RUNNING,
|
RUNNING,
|
||||||
|
PAUSED,
|
||||||
STOPPING,
|
STOPPING,
|
||||||
STOPPED,
|
STOPPED,
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user