From d2834dca45a153af8fe557572f0228c693308622 Mon Sep 17 00:00:00 2001 From: Niels Martin Hansen Date: Sat, 31 Oct 2009 00:54:42 +0000 Subject: [PATCH] Re-integrate r3740 from the 2.1.8 branch to fix the DirectSoundPlayer2 buffer locking bug. Updates #1028. Originally committed to SVN as r3751. --- aegisub/src/audio_player_dsound2.cpp | 85 +++++++++++++++++----------- 1 file changed, 51 insertions(+), 34 deletions(-) diff --git a/aegisub/src/audio_player_dsound2.cpp b/aegisub/src/audio_player_dsound2.cpp index ecfe701e9..a2749ba82 100644 --- a/aegisub/src/audio_player_dsound2.cpp +++ b/aegisub/src/audio_player_dsound2.cpp @@ -157,36 +157,35 @@ class DirectSoundPlayer2Thread { // Used to signal state-changes to thread HANDLE - /// DOCME - event_start_playback, + /// DOCME + event_start_playback, - /// DOCME - event_stop_playback, + /// DOCME + event_stop_playback, - /// DOCME - event_update_end_time, + /// DOCME + event_update_end_time, - /// DOCME - event_set_volume, + /// DOCME + event_set_volume, - /// DOCME - event_kill_self; + /// DOCME + event_kill_self; // Thread communicating back HANDLE - /// DOCME - thread_running, - - /// DOCME - is_playing, - - /// DOCME - error_happened; - + /// DOCME + thread_running, /// DOCME - wxChar *error_message; + is_playing, + + /// DOCME + error_happened; + + /// DOCME + const wxChar *error_message; /// DOCME double volume; @@ -470,28 +469,46 @@ do_fill_buffer: int bytes_needed = (int)play_cursor - (int)buffer_offset; if (bytes_needed < 0) bytes_needed += (int)bufSize; + // Requesting zero buffer makes Windows cry, and zero buffer seemed to be + // a common request on Windows 7. (Maybe related to the new timer coalescing?) + // We'll probably get non-zero bytes requested on the next iteration. + if (bytes_needed == 0) + break; + DWORD buf1sz, buf2sz; void *buf1, *buf2; + assert(buffer_offset < bufSize); + assert(bytes_needed <= bufSize); + HRESULT res = bfr->Lock(buffer_offset, bytes_needed, &buf1, &buf1sz, &buf2, &buf2sz, 0); - while (FAILED(res)) // yes, while, so I can break out of it without a goto! + switch (res) { - if (res == DSERR_BUFFERLOST) + case DSERR_BUFFERLOST: + // Try to regain the buffer + // When the buffer was lost the entire contents was lost too, so we have to start over + if (SUCCEEDED(bfr->Restore()) && + SUCCEEDED(bfr->Lock(0, bufSize, &buf1, &buf1sz, &buf2, &buf2sz, 0)) && + SUCCEEDED(bfr->Play(0, 0, DSBPLAY_LOOPING))) { - // Try to regain the buffer - // When the buffer was lost the entire contents was lost too, so we have to start over - if (SUCCEEDED(bfr->Restore()) && - SUCCEEDED(bfr->Lock(0, bufSize, &buf1, &buf1sz, &buf2, &buf2sz, 0)) && - SUCCEEDED(bfr->Play(0, 0, DSBPLAY_LOOPING))) - { - wxLogDebug(_T("DirectSoundPlayer2: Lost and restored buffer")); - break; - } - - REPORT_ERROR("Lost buffer and could not restore it.") + wxLogDebug(_T("DirectSoundPlayer2: Lost and restored buffer")); + break; } + REPORT_ERROR("Lost buffer and could not restore it.") - REPORT_ERROR("Could not lock buffer for filling.") + case DSERR_INVALIDPARAM: + REPORT_ERROR("Invalid parameters to IDirectSoundBuffer8::Lock().") + + case DSERR_INVALIDCALL: + REPORT_ERROR("Invalid call to IDirectSoundBuffer8::Lock().") + + case DSERR_PRIOLEVELNEEDED: + REPORT_ERROR("Incorrect priority level set on DirectSoundBuffer8 object.") + + default: + if (FAILED(res)) + REPORT_ERROR("Could not lock audio buffer, unknown error.") + break; } DWORD bytes_filled = FillAndUnlockBuffers(buf1, buf1sz, buf2, buf2sz, next_input_frame, bfr.obj);