void SNDDXDeInit() { DWORD status=0; if (lpDSB2) { IDirectSoundBuffer8_GetStatus(lpDSB2, &status); if(status == DSBSTATUS_PLAYING) IDirectSoundBuffer8_Stop(lpDSB2); IDirectSoundBuffer8_Release(lpDSB2); lpDSB2 = NULL; } if (lpDSB) { IDirectSoundBuffer8_Release(lpDSB); lpDSB = NULL; } if (lpDS8) { IDirectSound8_Release(lpDS8); lpDS8 = NULL; } }
static gboolean gst_directsound_ring_buffer_release (GstRingBuffer * buf) { GstDirectSoundRingBuffer * dsoundbuffer; dsoundbuffer = GST_DIRECTSOUND_RING_BUFFER (buf); /* first we have to ensure our ring buffer is stopped */ gst_directsound_ring_buffer_stop (buf); GST_DSOUND_LOCK (dsoundbuffer); /* release secondary DirectSound buffer */ if (dsoundbuffer->pDSB8) { IDirectSoundBuffer8_Release (dsoundbuffer->pDSB8); dsoundbuffer->pDSB8 = NULL; } gst_buffer_unref (buf->data); buf->data = NULL; GST_DSOUND_UNLOCK (dsoundbuffer); return TRUE; }
static ULONG WINAPI IDirectMusicAudioPathImpl_IUnknown_Release (LPUNKNOWN iface) { ICOM_THIS_MULTI(IDirectMusicAudioPathImpl, UnknownVtbl, iface); ULONG ref = InterlockedDecrement(&This->ref); TRACE("(%p): ReleaseRef to %d\n", This, ref); if (ref == 0) { if (This->pDSBuffer) { IDirectSoundBuffer8_Release(This->pDSBuffer); } HeapFree(GetProcessHeap(), 0, This); } DMIME_UnlockModule(); return ref; }
EXPORT void CALL CloseDLL (void) { #ifdef THREADED TerminateThread (handleAudioThread, 0); #endif if (lpdsbuf) { IDirectSoundBuffer8_Stop(lpdsbuf); IDirectSoundBuffer8_Release(lpdsbuf); lpdsbuf = NULL; } if ( lpds ) { IDirectSound8_Release(lpds); lpds = NULL; } }
static void test_COM(void) { IDirectSoundFullDuplex *dsfd = (IDirectSoundFullDuplex*)0xdeadbeef; IDirectSound *ds; IDirectSound8 *ds8; IDirectSoundCapture *dsc; IUnknown *unk, *unk8; IDirectSoundBuffer8 *dsb8; IDirectSoundCaptureBuffer8 *dscb8; DSBUFFERDESC bufdesc; DSCBUFFERDESC cbufdesc; WAVEFORMATEX wfx; ULONG refcount; HRESULT hr; /* COM aggregation */ hr = CoCreateInstance(&CLSID_DirectSoundFullDuplex, (IUnknown*)&dsfd, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&dsfd); ok(hr == CLASS_E_NOAGGREGATION, "DirectSoundFullDuplex create failed: %08x, expected CLASS_E_NOAGGREGATION\n", hr); ok(!dsfd, "dsfd = %p\n", dsfd); /* Invalid RIID */ hr = CoCreateInstance(&CLSID_DirectSoundFullDuplex, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectSound3DBuffer, (void**)&dsfd); ok(hr == E_NOINTERFACE, "DirectSoundFullDuplex create failed: %08x, expected E_NOINTERFACE\n", hr); /* Different refcount for IDirectSoundFullDuplex and for IUnknown */ hr = CoCreateInstance(&CLSID_DirectSoundFullDuplex, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectSoundFullDuplex, (void**)&dsfd); ok(hr == S_OK, "DirectSoundFullDuplex create failed: %08x, expected S_OK\n", hr); refcount = IDirectSoundFullDuplex_AddRef(dsfd); ok(refcount == 2, "refcount == %u, expected 2\n", refcount); hr = IDirectSoundFullDuplex_QueryInterface(dsfd, &IID_IUnknown, (void**)&unk); ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr); refcount = IUnknown_AddRef(unk); ok(refcount == 2, "refcount == %u, expected 2\n", refcount); /* Not initialized */ hr = IDirectSoundFullDuplex_QueryInterface(dsfd, &IID_IDirectSound8, (void**)&ds8); ok(hr == E_NOINTERFACE, "QueryInterface for IID_IDirectSound8 failed: %08x, expected E_NOINTERFACE\n", hr); hr = IDirectSoundFullDuplex_QueryInterface(dsfd, &IID_IDirectSoundCapture, (void**)&dsc); ok(hr == E_NOINTERFACE, "QueryInterface for IID_IDirectSoundCapture failed: %08x, expected E_NOINTERFACE\n", hr); init_format(&wfx, WAVE_FORMAT_PCM, 44100, 16, 1); ZeroMemory(&bufdesc, sizeof(bufdesc)); bufdesc.dwSize = sizeof(bufdesc); bufdesc.dwBufferBytes = wfx.nAvgBytesPerSec; bufdesc.lpwfxFormat = &wfx; ZeroMemory(&cbufdesc, sizeof(cbufdesc)); cbufdesc.dwSize = sizeof(cbufdesc); cbufdesc.dwBufferBytes = wfx.nAvgBytesPerSec; cbufdesc.lpwfxFormat = &wfx; hr = IDirectSoundFullDuplex_Initialize(dsfd, NULL, NULL, &cbufdesc, &bufdesc, get_hwnd(), DSSCL_EXCLUSIVE, NULL, NULL); ok(hr == E_INVALIDARG, "IDirectSoundFullDuplex_Initialize failed: %08x, expected E_INVALIDARG\n", hr); hr = IDirectSoundFullDuplex_Initialize(dsfd, NULL, NULL, &cbufdesc, &bufdesc, get_hwnd(), DSSCL_EXCLUSIVE, &dscb8, &dsb8); if (hr == DSERR_NODRIVER || hr == DSERR_INVALIDCALL) { skip("No driver\n"); return; } ok(hr == S_OK, "IDirectSoundFullDuplex_Initialize failed: %08x\n", hr); /* IDirectSound and IDirectSound8 */ hr = IDirectSoundFullDuplex_QueryInterface(dsfd, &IID_IDirectSound8, (void**)&ds8); ok(hr == S_OK, "QueryInterface for IID_IDirectSound8 failed: %08x\n", hr); refcount = IDirectSound8_AddRef(ds8); ok(refcount == 2, "refcount == %u, expected 2\n", refcount); hr = IDirectSoundFullDuplex_QueryInterface(dsfd, &IID_IDirectSound, (void**)&ds); ok(hr == S_OK, "QueryInterface for IID_IDirectSound failed: %08x\n", hr); refcount = IDirectSound8_AddRef(ds8); ok(refcount == 4, "refcount == %u, expected 4\n", refcount); refcount = IDirectSound_AddRef(ds); ok(refcount == 5, "refcount == %u, expected 5\n", refcount); hr = IDirectSound8_QueryInterface(ds8, &IID_IUnknown, (void**)&unk8); ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr); ok(unk == unk8, "Got different IUnknown when QI'ing IDirectSoundFullDuplex and IDirectSound\n"); refcount = IUnknown_AddRef(unk8); ok(refcount == 4, "refcount == %u, expected 4\n", refcount); refcount = IDirectSound_AddRef(ds); ok(refcount == 6, "refcount == %u, expected 6\n", refcount); refcount = IDirectSoundFullDuplex_AddRef(dsfd); ok(refcount == 3, "refcount == %u, expected 3\n", refcount); /* IDirectSoundCapture */ hr = IDirectSoundFullDuplex_QueryInterface(dsfd, &IID_IDirectSoundCapture, (void**)&dsc); ok(hr == S_OK, "QueryInterface for IID_IDirectSoundCapture failed: %08x\n", hr); refcount = IDirectSoundCapture_AddRef(dsc); ok(refcount == 2, "refcount == %u, expected 2\n", refcount); refcount = IDirectSoundFullDuplex_AddRef(dsfd); ok(refcount == 4, "refcount == %u, expected 4\n", refcount); hr = IDirectSoundCapture_QueryInterface(ds8, &IID_IUnknown, (void**)&unk8); ok(hr == S_OK, "QueryInterface for IID_IUnknown failed: %08x\n", hr); ok(unk == unk8, "Got different IUnknown when QI'ing IDirectSoundFullDuplex and IDirectSoundCapture\n"); refcount = IUnknown_AddRef(unk8); ok(refcount == 6, "refcount == %u, expected 6\n", refcount); IDirectSoundBuffer8_Release(dsb8); IDirectSoundCaptureBuffer8_Release(dscb8); while (IDirectSound8_Release(ds8)); while (IDirectSoundCapture_Release(dsc)); while (IDirectSoundFullDuplex_Release(dsfd)); while (IUnknown_Release(unk)); }
static HRESULT WINAPI IDirectSoundFullDuplexImpl_Initialize(IDirectSoundFullDuplex *iface, const GUID *capture_dev, const GUID *render_dev, const DSCBUFFERDESC *cbufdesc, const DSBUFFERDESC *bufdesc, HWND hwnd, DWORD level, IDirectSoundCaptureBuffer8 **dscb8, IDirectSoundBuffer8 **dsb8) { IDirectSoundFullDuplexImpl *This = impl_from_IDirectSoundFullDuplex(iface); IDirectSound8 *ds8 = NULL; IDirectSoundCapture8 *dsc8 = NULL; HRESULT hr; TRACE("(%p,%s,%s,%p,%p,%p,%x,%p,%p)\n", This, debugstr_guid(capture_dev), debugstr_guid(render_dev), cbufdesc, bufdesc, hwnd, level, dscb8, dsb8); if (!dscb8 || !dsb8) return E_INVALIDARG; *dscb8 = NULL; *dsb8 = NULL; if (This->ds8_unk || This->dsc8_unk) { WARN("already initialized\n"); return DSERR_ALREADYINITIALIZED; } hr = IDirectSoundImpl_Create(&This->IUnknown_iface, &IID_IUnknown, (void**)&This->ds8_unk, TRUE); if (SUCCEEDED(hr)) { IUnknown_QueryInterface(This->ds8_unk, &IID_IDirectSound8, (void**)&ds8); hr = IDirectSound8_Initialize(ds8, render_dev); } if (hr != DS_OK) { WARN("Creating/initializing IDirectSound8 failed\n"); goto error; } IDirectSound8_SetCooperativeLevel(ds8, hwnd, level); hr = IDirectSound8_CreateSoundBuffer(ds8, bufdesc, (IDirectSoundBuffer**)dsb8, NULL); if (hr != DS_OK) { WARN("IDirectSoundBuffer_Create() failed\n"); goto error; } hr = IDirectSoundCaptureImpl_Create(&This->IUnknown_iface, &IID_IUnknown, (void**)&This->dsc8_unk, TRUE); if (SUCCEEDED(hr)) { IUnknown_QueryInterface(This->dsc8_unk, &IID_IDirectSoundCapture8, (void**)&dsc8); hr = IDirectSoundCapture_Initialize(dsc8, capture_dev); } if (hr != DS_OK) { WARN("Creating/initializing IDirectSoundCapture8 failed\n"); goto error; } hr = IDirectSoundCapture_CreateCaptureBuffer(dsc8, cbufdesc, (IDirectSoundCaptureBuffer**)dscb8, NULL); if (hr != DS_OK) { WARN("IDirectSoundCapture_CreateCaptureBuffer() failed\n"); goto error; } IDirectSound8_Release(ds8); IDirectSoundCapture_Release(dsc8); return DS_OK; error: if (*dsb8) { IDirectSoundBuffer8_Release(*dsb8); *dsb8 = NULL; } if (ds8) IDirectSound8_Release(ds8); if (This->ds8_unk) { IUnknown_Release(This->ds8_unk); This->ds8_unk = NULL; } if (*dscb8) { IDirectSoundCaptureBuffer8_Release(*dscb8); *dscb8 = NULL; } if (dsc8) IDirectSoundCapture_Release(dsc8); if (This->dsc8_unk) { IUnknown_Release(This->dsc8_unk); This->dsc8_unk = NULL; } return hr; }
static DWORD WINAPI gst_directsound_write_proc (LPVOID lpParameter) { GstRingBuffer * buf; GstDirectSoundRingBuffer * dsoundbuffer; HRESULT hr; DWORD dwStatus; LPVOID pLockedBuffer1 = NULL, pLockedBuffer2 = NULL; DWORD dwSizeBuffer1 = 0, dwSizeBuffer2 = 0; DWORD dwCurrentPlayCursor = 0; gint64 freeBufferSize = 0; guint8 * readptr = NULL; gint readseg = 0; guint len = 0; gint retries = 0; gboolean flushing = FALSE; gboolean should_run = TRUE; gboolean error = FALSE; buf = (GstRingBuffer *) lpParameter; dsoundbuffer = GST_DIRECTSOUND_RING_BUFFER (buf); do { GST_DSOUND_LOCK (dsoundbuffer); if (dsoundbuffer->flushing || !dsoundbuffer->pDSB8) { GST_DSOUND_UNLOCK (dsoundbuffer); goto complete; } GST_DSOUND_UNLOCK (dsoundbuffer); restore_buffer: /* get current buffer status */ GST_DSOUND_LOCK (dsoundbuffer); hr = IDirectSoundBuffer8_GetStatus (dsoundbuffer->pDSB8, &dwStatus); GST_DSOUND_UNLOCK (dsoundbuffer); if (dwStatus & DSBSTATUS_BUFFERLOST) { GST_DEBUG ("Buffer was lost, attempting to restore"); GST_DSOUND_LOCK (dsoundbuffer); hr = IDirectSoundBuffer8_Restore (dsoundbuffer->pDSB8); GST_DSOUND_UNLOCK (dsoundbuffer); /* restore may fail again, ensure we restore the * buffer before we continue */ if (FAILED(hr) && hr == DSERR_BUFFERLOST) { if (retries++ < MAX_LOST_RETRIES) { GST_DEBUG ("Unable to restore, trying again"); goto restore_buffer; } else { GST_ELEMENT_ERROR (dsoundbuffer->dsoundsink, RESOURCE, FAILED, ("%ls.", DXGetErrorDescription9W(hr)), ("gst_directsound_write_proc: IDirectSoundBuffer8_Restore, hr = %X", (unsigned int) hr)); goto complete; } } } /* get current play cursor and write cursor positions */ GST_DSOUND_LOCK (dsoundbuffer); hr = IDirectSoundBuffer8_GetCurrentPosition (dsoundbuffer->pDSB8, &dwCurrentPlayCursor, NULL); GST_DSOUND_UNLOCK (dsoundbuffer); if (G_UNLIKELY (FAILED(hr))) { /* try and reopen the default directsound device */ if (hr == DIRECTSOUND_ERROR_DEVICE_RECONFIGURED) { /* we have to wait a while for the sound device removal to actually * be processed before attempting to reopen the device. Yes, this sucks */ Sleep (2000); GST_DSOUND_LOCK (dsoundbuffer); IDirectSoundBuffer8_Release (dsoundbuffer->pDSB8); dsoundbuffer->pDSB8 = NULL; GST_DSOUND_UNLOCK (dsoundbuffer); if (gst_directsound_ring_buffer_close_device (buf) && gst_directsound_ring_buffer_open_device (buf) && gst_directsound_create_buffer (buf) ) { dsoundbuffer->buffer_write_offset = 0; goto restore_buffer; } } /* only trigger an error if we're not already in an error state */ if (FAILED(hr) && !error) { GST_ELEMENT_ERROR (dsoundbuffer->dsoundsink, RESOURCE, FAILED, ("%ls.", DXGetErrorDescription9W(hr)), ("gst_directsound_write_proc: IDirectSoundBuffer8_GetCurrentPosition, hr = %X", (unsigned int) hr)); error = TRUE; goto complete; } } GST_LOG ("Current Play Cursor: %u Current Write Offset: %d", (unsigned int) dwCurrentPlayCursor, dsoundbuffer->buffer_write_offset); /* calculate the free size of the circular buffer */ GST_DSOUND_LOCK (dsoundbuffer); if (dwCurrentPlayCursor <= dsoundbuffer->buffer_write_offset) freeBufferSize = dsoundbuffer->buffer_size - (dsoundbuffer->buffer_write_offset - dwCurrentPlayCursor); else freeBufferSize = dwCurrentPlayCursor - dsoundbuffer->buffer_write_offset; GST_DSOUND_UNLOCK (dsoundbuffer); if (!gst_ring_buffer_prepare_read (buf, &readseg, &readptr, &len)) goto complete; len -= dsoundbuffer->segoffset; GST_LOG ("Size of segment to write: %d Free buffer size: %lld", len, freeBufferSize); /* If we can't write this into directsound because we don't have enough * space, then start playback if we're currently paused. Then, sleep * for a little while to wait until space is available */ if (len >= freeBufferSize) { if (!(dwStatus & DSBSTATUS_PLAYING)) { GST_DSOUND_LOCK (dsoundbuffer); hr = IDirectSoundBuffer8_Play (dsoundbuffer->pDSB8, 0, 0, DSBPLAY_LOOPING); GST_DSOUND_UNLOCK (dsoundbuffer); if (FAILED(hr)) { GST_WARNING ("gst_directsound_write_proc: IDirectSoundBuffer8_Play, hr = %X", (unsigned int) hr); } } goto complete; } /* lock it */ GST_DSOUND_LOCK (dsoundbuffer); hr = IDirectSoundBuffer8_Lock (dsoundbuffer->pDSB8, dsoundbuffer->buffer_write_offset, len, &pLockedBuffer1, &dwSizeBuffer1, &pLockedBuffer2, &dwSizeBuffer2, 0L); /* copy chunks */ if (SUCCEEDED (hr)) { if (len <= dwSizeBuffer1) { memcpy (pLockedBuffer1, (LPBYTE) readptr + dsoundbuffer->segoffset, len); } else { memcpy (pLockedBuffer1, (LPBYTE) readptr + dsoundbuffer->segoffset, dwSizeBuffer1); memcpy (pLockedBuffer2, (LPBYTE) readptr + dsoundbuffer->segoffset + dwSizeBuffer1, len - dwSizeBuffer1); } IDirectSoundBuffer8_Unlock (dsoundbuffer->pDSB8, pLockedBuffer1, dwSizeBuffer1, pLockedBuffer2, dwSizeBuffer2); } else { GST_WARNING ("gst_directsound_write_proc: IDirectSoundBuffer8_Lock, hr = %X", (unsigned int) hr); } /* update tracking data */ dsoundbuffer->segoffset += dwSizeBuffer1 + (len - dwSizeBuffer1); dsoundbuffer->buffer_write_offset += dwSizeBuffer1 + (len - dwSizeBuffer1); dsoundbuffer->buffer_write_offset %= dsoundbuffer->buffer_size; GST_DSOUND_UNLOCK (dsoundbuffer); freeBufferSize -= dwSizeBuffer1 + (len - dwSizeBuffer1); GST_LOG ("DirectSound Buffer1 Data Size: %u DirectSound Buffer2 Data Size: %u", (unsigned int) dwSizeBuffer1, (unsigned int) dwSizeBuffer2); GST_LOG ("Free buffer size: %lld", freeBufferSize); /* check if we read a whole segment */ GST_DSOUND_LOCK (dsoundbuffer); if (dsoundbuffer->segoffset == dsoundbuffer->segsize) { GST_DSOUND_UNLOCK (dsoundbuffer); /* advance to next segment */ gst_ring_buffer_clear (buf, readseg); gst_ring_buffer_advance (buf, 1); GST_DSOUND_LOCK (dsoundbuffer); dsoundbuffer->segoffset = 0; } GST_DSOUND_UNLOCK (dsoundbuffer); complete: GST_DSOUND_LOCK (dsoundbuffer); should_run = dsoundbuffer->should_run; flushing = dsoundbuffer->flushing; retries = 0; GST_DSOUND_UNLOCK (dsoundbuffer); /* it's extremely important to sleep in without the lock! */ if (len >= freeBufferSize || flushing || error) Sleep (dsoundbuffer->min_sleep_time); } while(should_run); return 0; }