Make error handling in DSound2 audio player more robust. When an error happened in the playback thread, the error_happened flag was set, but was never cleared when the error was detected in the main thread. Furthermore, the main thread didn't act upon the error besides showing it, it kept acting as if the playback thread was still alive and playing, causing the error to be triggered continuously requiring you to kill Aegisub to get out.

Made the error_happened event reset itself after being checked so the check only succeeds the first time. (The playback thread returns from its threadproc upon error.) Mark playback thread as dead when error is detected, such that a new thread will be created next time playback is started, effectively making errors non-fatal.
Playback still works as expected, however I haven't tested what actually happens now when an error occurs.

Originally committed to SVN as r2968.
This commit is contained in:
Niels Martin Hansen 2009-05-22 01:41:31 +00:00
parent bceabf4848
commit ef4021f757
2 changed files with 63 additions and 23 deletions

View file

@ -153,6 +153,7 @@ public:
int64_t GetCurrentFrame(); int64_t GetCurrentFrame();
int64_t GetEndFrame(); int64_t GetEndFrame();
double GetVolume(); double GetVolume();
bool IsDead();
}; };
@ -455,6 +456,8 @@ DWORD DirectSoundPlayer2Thread::FillAndUnlockBuffers(void *buf1, DWORD buf1sz, v
void DirectSoundPlayer2Thread::CheckError() void DirectSoundPlayer2Thread::CheckError()
{
try
{ {
switch (WaitForSingleObject(error_happened, 0)) switch (WaitForSingleObject(error_happened, 0))
{ {
@ -472,6 +475,13 @@ void DirectSoundPlayer2Thread::CheckError()
return; return;
} }
} }
catch (...)
{
ResetEvent(is_playing);
ResetEvent(thread_running);
throw;
}
}
DirectSoundPlayer2Thread::DirectSoundPlayer2Thread(AudioProvider *provider, int _WantedLatency, int _BufferLength) DirectSoundPlayer2Thread::DirectSoundPlayer2Thread(AudioProvider *provider, int _WantedLatency, int _BufferLength)
@ -484,7 +494,7 @@ DirectSoundPlayer2Thread::DirectSoundPlayer2Thread(AudioProvider *provider, int
thread_running = CreateEvent(0, TRUE, FALSE, 0); thread_running = CreateEvent(0, TRUE, FALSE, 0);
is_playing = CreateEvent(0, TRUE, FALSE, 0); is_playing = CreateEvent(0, TRUE, FALSE, 0);
error_happened = CreateEvent(0, TRUE, FALSE, 0); error_happened = CreateEvent(0, FALSE, FALSE, 0);
error_message = 0; error_message = 0;
volume = 1.0; volume = 1.0;
@ -610,6 +620,19 @@ double DirectSoundPlayer2Thread::GetVolume()
} }
bool DirectSoundPlayer2Thread::IsDead()
{
switch (WaitForSingleObject(thread_running, 0))
{
case WAIT_OBJECT_0:
return false;
default:
return true;
}
}
DirectSoundPlayer2::DirectSoundPlayer2() DirectSoundPlayer2::DirectSoundPlayer2()
@ -634,9 +657,24 @@ DirectSoundPlayer2::~DirectSoundPlayer2()
} }
bool DirectSoundPlayer2::IsThreadAlive()
{
if (!thread) return false;
if (thread->IsDead())
{
delete thread;
thread = 0;
return false;
}
return true;
}
void DirectSoundPlayer2::OpenStream() void DirectSoundPlayer2::OpenStream()
{ {
if (thread) return; if (IsThreadAlive()) return;
try try
{ {
@ -652,7 +690,7 @@ void DirectSoundPlayer2::OpenStream()
void DirectSoundPlayer2::CloseStream() void DirectSoundPlayer2::CloseStream()
{ {
if (!thread) return; if (!IsThreadAlive()) return;
try try
{ {
@ -670,7 +708,7 @@ void DirectSoundPlayer2::SetProvider(AudioProvider *provider)
{ {
try try
{ {
if (thread && provider != GetProvider()) if (IsThreadAlive() && provider != GetProvider())
{ {
delete thread; delete thread;
thread = new DirectSoundPlayer2Thread(provider, WantedLatency, BufferLength); thread = new DirectSoundPlayer2Thread(provider, WantedLatency, BufferLength);
@ -705,7 +743,7 @@ void DirectSoundPlayer2::Stop(bool timerToo)
{ {
try try
{ {
if (thread) thread->Stop(); if (IsThreadAlive()) thread->Stop();
if (timerToo && displayTimer) { if (timerToo && displayTimer) {
displayTimer->Stop(); displayTimer->Stop();
@ -722,7 +760,7 @@ bool DirectSoundPlayer2::IsPlaying()
{ {
try try
{ {
if (!thread) return false; if (!IsThreadAlive()) return false;
return thread->IsPlaying(); return thread->IsPlaying();
} }
catch (const wxChar *msg) catch (const wxChar *msg)
@ -737,7 +775,7 @@ int64_t DirectSoundPlayer2::GetStartPosition()
{ {
try try
{ {
if (!thread) return 0; if (!IsThreadAlive()) return 0;
return thread->GetStartFrame(); return thread->GetStartFrame();
} }
catch (const wxChar *msg) catch (const wxChar *msg)
@ -752,7 +790,7 @@ int64_t DirectSoundPlayer2::GetEndPosition()
{ {
try try
{ {
if (!thread) return 0; if (!IsThreadAlive()) return 0;
return thread->GetEndFrame(); return thread->GetEndFrame();
} }
catch (const wxChar *msg) catch (const wxChar *msg)
@ -767,7 +805,7 @@ int64_t DirectSoundPlayer2::GetCurrentPosition()
{ {
try try
{ {
if (!thread) return 0; if (!IsThreadAlive()) return 0;
return thread->GetCurrentFrame(); return thread->GetCurrentFrame();
} }
catch (const wxChar *msg) catch (const wxChar *msg)
@ -782,7 +820,7 @@ void DirectSoundPlayer2::SetEndPosition(int64_t pos)
{ {
try try
{ {
if (thread) thread->SetEndFrame(pos); if (IsThreadAlive()) thread->SetEndFrame(pos);
} }
catch (const wxChar *msg) catch (const wxChar *msg)
{ {
@ -795,7 +833,7 @@ void DirectSoundPlayer2::SetCurrentPosition(int64_t pos)
{ {
try try
{ {
if (thread) thread->Play(pos, thread->GetEndFrame()-pos); if (IsThreadAlive()) thread->Play(pos, thread->GetEndFrame()-pos);
} }
catch (const wxChar *msg) catch (const wxChar *msg)
{ {
@ -808,7 +846,7 @@ void DirectSoundPlayer2::SetVolume(double vol)
{ {
try try
{ {
if (thread) thread->SetVolume(vol); if (IsThreadAlive()) thread->SetVolume(vol);
} }
catch (const wxChar *msg) catch (const wxChar *msg)
{ {
@ -821,7 +859,7 @@ double DirectSoundPlayer2::GetVolume()
{ {
try try
{ {
if (!thread) return 0; if (!IsThreadAlive()) return 0;
return thread->GetVolume(); return thread->GetVolume();
} }
catch (const wxChar *msg) catch (const wxChar *msg)

View file

@ -49,6 +49,8 @@ protected:
int WantedLatency; int WantedLatency;
int BufferLength; int BufferLength;
bool IsThreadAlive();
public: public:
DirectSoundPlayer2(); DirectSoundPlayer2();
~DirectSoundPlayer2(); ~DirectSoundPlayer2();