static int dsound_get_status_out (LPDIRECTSOUNDBUFFER dsb, DWORD *statusp, dsound *s) { HRESULT hr; hr = IDirectSoundBuffer_GetStatus (dsb, statusp); if (FAILED (hr)) { dsound_logerr (hr, "Could not get playback buffer status\n"); return -1; } if (*statusp & DSERR_BUFFERLOST) { dsound_restore_out(dsb, s); return -1; } return 0; }
static int dsound_get_status_out (LPDIRECTSOUNDBUFFER dsb, DWORD *statusp) { HRESULT hr; int i; for (i = 0; i < conf.getstatus_retries; ++i) { hr = IDirectSoundBuffer_GetStatus (dsb, statusp); if (FAILED (hr)) { dsound_logerr (hr, "Could not get playback buffer status\n"); return -1; } if (*statusp & DSERR_BUFFERLOST) { if (dsound_restore_out (dsb)) { return -1; } continue; } break; } return 0; }
static int dsound_run_out (HWVoiceOut *hw) { int err; HRESULT hr; DSoundVoiceOut *ds = (DSoundVoiceOut *) hw; LPDIRECTSOUNDBUFFER dsb = ds->dsound_buffer; int live, len, hwshift; DWORD blen1, blen2; DWORD len1, len2; DWORD decr; DWORD wpos, ppos, old_pos; LPVOID p1, p2; int bufsize; if (!dsb) { dolog ("Attempt to run empty with playback buffer\n"); return 0; } hwshift = hw->info.shift; bufsize = hw->samples << hwshift; live = audio_pcm_hw_get_live_out (hw); hr = IDirectSoundBuffer_GetCurrentPosition ( dsb, &ppos, ds->first_time ? &wpos : NULL ); if (hr == DSERR_BUFFERLOST) { if (dsound_restore_out(dsb)) return 0; hr = IDirectSoundBuffer_GetCurrentPosition(dsb, &ppos, ds->first_time ? &wpos : NULL); if (hr == DSERR_BUFFERLOST) return 0; // Avoid log flooding if the error is still there. } if (FAILED (hr)) { dsound_logerr (hr, "Could not get playback buffer position\n"); return 0; } len = live << hwshift; if (ds->first_time) { if (conf.latency_millis) { DWORD cur_blat; cur_blat = audio_ring_dist (wpos, ppos, bufsize); ds->first_time = 0; old_pos = wpos; old_pos += millis_to_bytes (&hw->info, conf.latency_millis) - cur_blat; old_pos %= bufsize; old_pos &= ~hw->info.align; } else { old_pos = wpos; } #ifdef DEBUG_DSOUND ds->played = 0; ds->mixed = 0; #endif } else { if (ds->old_pos == ppos) { #ifdef DEBUG_DSOUND dolog ("old_pos == ppos\n"); #endif return 0; } #ifdef DEBUG_DSOUND ds->played += audio_ring_dist (ds->old_pos, ppos, bufsize); #endif old_pos = ds->old_pos; } if ((old_pos < ppos) && ((old_pos + len) > ppos)) { len = ppos - old_pos; } else { if ((old_pos > ppos) && ((old_pos + len) > (ppos + bufsize))) { len = bufsize - old_pos + ppos; } } if (audio_bug (AUDIO_FUNC, len < 0 || len > bufsize)) { dolog ("len=%d bufsize=%d old_pos=%ld ppos=%ld\n", len, bufsize, old_pos, ppos); return 0; } len &= ~hw->info.align; if (!len) { return 0; } #ifdef DEBUG_DSOUND ds->old_ppos = ppos; #endif err = dsound_lock_out ( dsb, &hw->info, old_pos, len, &p1, &p2, &blen1, &blen2, 0 ); if (err) { return 0; } len1 = blen1 >> hwshift; len2 = blen2 >> hwshift; decr = len1 + len2; if (p1 && len1) { dsound_write_sample (hw, p1, len1); } if (p2 && len2) { dsound_write_sample (hw, p2, len2); } dsound_unlock_out (dsb, p1, p2, blen1, blen2); ds->old_pos = (old_pos + (decr << hwshift)) % bufsize; #ifdef DEBUG_DSOUND ds->mixed += decr << hwshift; dolog ("played %lu mixed %lu diff %ld sec %f\n", ds->played, ds->mixed, ds->mixed - ds->played, abs (ds->mixed - ds->played) / (double) hw->info.bytes_per_second); #endif return decr; }