Re-integrate r3740 from the 2.1.8 branch to fix the DirectSoundPlayer2 buffer locking bug.

Updates #1028.

Originally committed to SVN as r3751.
This commit is contained in:
Niels Martin Hansen 2009-10-31 00:54:42 +00:00
parent afd9133fc0
commit d2834dca45

View file

@ -157,36 +157,35 @@ class DirectSoundPlayer2Thread {
// Used to signal state-changes to thread // Used to signal state-changes to thread
HANDLE HANDLE
/// DOCME /// DOCME
event_start_playback, event_start_playback,
/// DOCME /// DOCME
event_stop_playback, event_stop_playback,
/// DOCME /// DOCME
event_update_end_time, event_update_end_time,
/// DOCME /// DOCME
event_set_volume, event_set_volume,
/// DOCME /// DOCME
event_kill_self; event_kill_self;
// Thread communicating back // Thread communicating back
HANDLE HANDLE
/// DOCME /// DOCME
thread_running, thread_running,
/// DOCME
is_playing,
/// DOCME
error_happened;
/// DOCME /// DOCME
wxChar *error_message; is_playing,
/// DOCME
error_happened;
/// DOCME
const wxChar *error_message;
/// DOCME /// DOCME
double volume; double volume;
@ -470,28 +469,46 @@ do_fill_buffer:
int bytes_needed = (int)play_cursor - (int)buffer_offset; int bytes_needed = (int)play_cursor - (int)buffer_offset;
if (bytes_needed < 0) bytes_needed += (int)bufSize; 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; DWORD buf1sz, buf2sz;
void *buf1, *buf2; void *buf1, *buf2;
assert(buffer_offset < bufSize);
assert(bytes_needed <= bufSize);
HRESULT res = bfr->Lock(buffer_offset, bytes_needed, &buf1, &buf1sz, &buf2, &buf2sz, 0); 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 wxLogDebug(_T("DirectSoundPlayer2: Lost and restored buffer"));
// When the buffer was lost the entire contents was lost too, so we have to start over break;
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.")
} }
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); DWORD bytes_filled = FillAndUnlockBuffers(buf1, buf1sz, buf2, buf2sz, next_input_frame, bfr.obj);