| /* | |
| * Unit tests for duplex functions | |
| * | |
| * Copyright (c) 2006 Robert Reif | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General Public | |
| * License along with this library; if not, write to the Free Software | |
| * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | |
| */ | |
| #define COBJMACROS | |
| #include <windows.h> | |
| #include <stdio.h> | |
| #include "wine/test.h" | |
| #include "mmsystem.h" | |
| #include "dsound.h" | |
| #include "dsconf.h" | |
| #include "dsound_test.h" | |
| static HRESULT (WINAPI *pDirectSoundFullDuplexCreate)(LPCGUID, LPCGUID, | |
| LPCDSCBUFFERDESC, LPCDSBUFFERDESC, HWND, DWORD, LPDIRECTSOUNDFULLDUPLEX *, | |
| LPDIRECTSOUNDCAPTUREBUFFER8*, LPDIRECTSOUNDBUFFER8*, LPUNKNOWN)=NULL; | |
| static void IDirectSoundFullDuplex_test(LPDIRECTSOUNDFULLDUPLEX dsfdo, | |
| BOOL initialized, LPCGUID lpGuidCapture, | |
| LPCGUID lpGuidRender) | |
| { | |
| HRESULT rc; | |
| int ref; | |
| IUnknown * unknown; | |
| IDirectSound * ds; | |
| IDirectSound8 * ds8; | |
| IDirectSoundCapture * dsc; | |
| IDirectSoundFullDuplex * dsfd; | |
| /* Try to Query for objects */ | |
| rc=IDirectSoundFullDuplex_QueryInterface(dsfdo,&IID_IUnknown,(LPVOID*)&unknown); | |
| ok(rc==DS_OK,"IDirectSoundFullDuplex_QueryInterface(IID_IUnknown) failed: %08x\n", rc); | |
| if (rc==DS_OK) { | |
| ref=IDirectSoundFullDuplex_Release(unknown); | |
| ok(ref==0, "IDirectSoundFullDuplex_Release() has %d references, " | |
| "should have 0\n", ref); | |
| } | |
| rc=IDirectSoundFullDuplex_QueryInterface(dsfdo,&IID_IDirectSound,(LPVOID*)&ds); | |
| ok(rc==(initialized?DS_OK:E_NOINTERFACE),"IDirectSoundFullDuplex_QueryInterface(IID_IDirectSound) failed: %08x\n", rc); | |
| if (rc==DS_OK) { | |
| ref=IDirectSound_Release(ds); | |
| ok(ref==0, "IDirectSound_Release() has %d references, " | |
| "should have 0\n", ref); | |
| } | |
| rc=IDirectSoundFullDuplex_QueryInterface(dsfdo,&IID_IDirectSound8,(LPVOID*)&ds8); | |
| ok(rc==(initialized?DS_OK:E_NOINTERFACE),"IDirectSoundFullDuplex_QueryInterface(IID_IDirectSound8) " | |
| "failed: %08x\n",rc); | |
| if (rc==DS_OK) { | |
| IDirectSoundFullDuplex * dsfd1; | |
| rc=IDirectSound8_QueryInterface(ds8,&IID_IDirectSoundFullDuplex,(LPVOID*)&dsfd1); | |
| ok(rc==DS_OK,"IDirectSound8_QueryInterface(IID_IDirectSoundFullDuplex) " | |
| "failed: %08x\n",rc); | |
| if (rc==DS_OK) { | |
| ref=IDirectSoundFullDuplex_Release(dsfd1); | |
| ok(ref==1, "IDirectSoundFullDuplex_Release() has %d references, " | |
| "should have 1\n", ref); | |
| } | |
| ref=IDirectSound8_Release(ds8); | |
| ok(ref==0, "IDirectSound8_Release() has %d references, " | |
| "should have 0\n", ref); | |
| } | |
| rc=IDirectSoundFullDuplex_QueryInterface(dsfdo,&IID_IDirectSoundCapture,(LPVOID*)&dsc); | |
| ok(rc==(initialized?DS_OK:E_NOINTERFACE),"IDirectSoundFullDuplex_QueryInterface(IID_IDirectSoundCapture) " | |
| "failed: %08x\n",rc); | |
| if (rc==DS_OK) { | |
| ref=IDirectSoundCapture_Release(dsc); | |
| ok(ref==0, "IDirectSoundCapture_Release() has %d references, " | |
| "should have 0\n", ref); | |
| } | |
| rc=IDirectSoundFullDuplex_QueryInterface(dsfdo,&IID_IDirectSoundFullDuplex,(LPVOID*)&dsfd); | |
| ok(rc==DS_OK,"IDirectSoundFullDuplex_QueryInterface(IID_IDirectSoundFullDuplex) " | |
| "failed: %08x\n",rc); | |
| if (rc==DS_OK) { | |
| ok(dsfdo==dsfd, "different interfaces\n"); | |
| ref=IDirectSound8_Release(dsfd); | |
| ok(ref==1, "IDirectSoundFullDuplex_Release() has %d references, should have 1\n", ref); | |
| } | |
| ref=IDirectSoundFullDuplex_Release(dsfdo); | |
| ok(ref==0, "IDirectSoundFullDuplex_Release() has %d references, " | |
| "should have 0\n", ref); | |
| } | |
| static void IDirectSoundFullDuplex_tests(void) | |
| { | |
| HRESULT rc; | |
| LPDIRECTSOUNDFULLDUPLEX dsfdo = NULL; | |
| DSCBUFFERDESC DSCBufferDesc; | |
| DSBUFFERDESC DSBufferDesc; | |
| LPDIRECTSOUNDCAPTUREBUFFER8 pDSCBuffer8; | |
| LPDIRECTSOUNDBUFFER8 pDSBuffer8; | |
| WAVEFORMATEX wfex; | |
| trace("Testing IDirectSoundFullDuplex\n"); | |
| /* try the COM class factory method of creation with no devices specified */ | |
| rc=CoCreateInstance(&CLSID_DirectSoundFullDuplex, NULL, | |
| CLSCTX_INPROC_SERVER, &IID_IDirectSoundFullDuplex, | |
| (void**)&dsfdo); | |
| ok(rc==S_OK||rc==REGDB_E_CLASSNOTREG||rc==CLASS_E_CLASSNOTAVAILABLE, | |
| "CoCreateInstance(CLSID_DirectSoundFullDuplex) failed: 0x%08x\n", rc); | |
| if (rc==REGDB_E_CLASSNOTREG) { | |
| trace(" Class Not Registered\n"); | |
| return; | |
| } else if (rc==CLASS_E_CLASSNOTAVAILABLE) { | |
| trace(" Class Not Available\n"); | |
| return; | |
| } | |
| if (dsfdo) | |
| IDirectSoundFullDuplex_test(dsfdo, FALSE, NULL, NULL); | |
| /* try the COM class factory method of creation with default devices | |
| * specified */ | |
| rc=CoCreateInstance(&CLSID_DirectSoundFullDuplex, NULL, | |
| CLSCTX_INPROC_SERVER, &IID_IDirectSoundFullDuplex, | |
| (void**)&dsfdo); | |
| ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSoundFullDuplex) failed: 0x%08x\n", rc); | |
| if (dsfdo) | |
| IDirectSoundFullDuplex_test(dsfdo, FALSE, &DSDEVID_DefaultCapture, | |
| &DSDEVID_DefaultPlayback); | |
| /* try the COM class factory method of creation with default voice | |
| * devices specified */ | |
| rc=CoCreateInstance(&CLSID_DirectSoundFullDuplex, NULL, | |
| CLSCTX_INPROC_SERVER, &IID_IDirectSoundFullDuplex, | |
| (void**)&dsfdo); | |
| ok(rc==S_OK,"CoCreateInstance(CLSID_DirectSoundFullDuplex) failed: 0x%08x\n", rc); | |
| if (dsfdo) | |
| IDirectSoundFullDuplex_test(dsfdo, FALSE, &DSDEVID_DefaultVoiceCapture, | |
| &DSDEVID_DefaultVoicePlayback); | |
| /* try the COM class factory method of creation with a bad | |
| * IID specified */ | |
| rc=CoCreateInstance(&CLSID_DirectSoundFullDuplex, NULL, | |
| CLSCTX_INPROC_SERVER, &CLSID_DirectSoundPrivate, | |
| (void**)&dsfdo); | |
| ok(rc==E_NOINTERFACE, | |
| "CoCreateInstance(CLSID_DirectSoundFullDuplex,CLSID_DirectSoundPrivate) " | |
| "should have failed: 0x%08x\n", rc); | |
| ZeroMemory(&wfex, sizeof(wfex)); | |
| wfex.wFormatTag = WAVE_FORMAT_PCM; | |
| wfex.nChannels = 1; | |
| wfex.nSamplesPerSec = 8000; | |
| wfex.wBitsPerSample = 16; | |
| wfex.nBlockAlign = (wfex.wBitsPerSample * wfex.nChannels) / 8; | |
| wfex.nAvgBytesPerSec = wfex.nSamplesPerSec * wfex.nBlockAlign; | |
| ZeroMemory(&DSCBufferDesc, sizeof(DSCBufferDesc)); | |
| DSCBufferDesc.dwSize = sizeof(DSCBufferDesc); | |
| DSCBufferDesc.dwFlags = DSCBCAPS_WAVEMAPPED; | |
| DSCBufferDesc.dwBufferBytes = 8192; | |
| DSCBufferDesc.lpwfxFormat = &wfex; | |
| ZeroMemory(&DSBufferDesc, sizeof(DSBufferDesc)); | |
| DSBufferDesc.dwSize = sizeof(DSBufferDesc); | |
| DSBufferDesc.dwFlags = DSBCAPS_GLOBALFOCUS; | |
| DSBufferDesc.dwBufferBytes = 8192; | |
| DSBufferDesc.lpwfxFormat = &wfex; | |
| /* try with no device specified */ | |
| rc=pDirectSoundFullDuplexCreate(NULL,NULL,&DSCBufferDesc,&DSBufferDesc, | |
| get_hwnd(),DSSCL_EXCLUSIVE ,&dsfdo,&pDSCBuffer8, | |
| &pDSBuffer8,NULL); | |
| ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL||rc==DSERR_INVALIDCALL, | |
| "DirectSoundFullDuplexCreate(NULL,NULL) failed: %08x\n",rc); | |
| if (rc==S_OK && dsfdo) | |
| IDirectSoundFullDuplex_test(dsfdo, TRUE, NULL, NULL); | |
| /* try with default devices specified */ | |
| rc=pDirectSoundFullDuplexCreate(&DSDEVID_DefaultCapture, | |
| &DSDEVID_DefaultPlayback,&DSCBufferDesc, | |
| &DSBufferDesc,get_hwnd(),DSSCL_EXCLUSIVE,&dsfdo, | |
| &pDSCBuffer8,&pDSBuffer8,NULL); | |
| ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL||rc==DSERR_INVALIDCALL, | |
| "DirectSoundFullDuplexCreate(DSDEVID_DefaultCapture," | |
| "DSDEVID_DefaultPlayback) failed: %08x\n", rc); | |
| if (rc==DS_OK && dsfdo) | |
| IDirectSoundFullDuplex_test(dsfdo, TRUE, NULL, NULL); | |
| /* try with default voice devices specified */ | |
| rc=pDirectSoundFullDuplexCreate(&DSDEVID_DefaultVoiceCapture, | |
| &DSDEVID_DefaultVoicePlayback, | |
| &DSCBufferDesc,&DSBufferDesc,get_hwnd(),DSSCL_EXCLUSIVE, | |
| &dsfdo,&pDSCBuffer8,&pDSBuffer8,NULL); | |
| ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL||rc==DSERR_INVALIDCALL, | |
| "DirectSoundFullDuplexCreate(DSDEVID_DefaultVoiceCapture," | |
| "DSDEVID_DefaultVoicePlayback) failed: %08x\n", rc); | |
| if (rc==DS_OK && dsfdo) | |
| IDirectSoundFullDuplex_test(dsfdo, TRUE, NULL, NULL); | |
| /* try with bad devices specified */ | |
| rc=pDirectSoundFullDuplexCreate(&DSDEVID_DefaultVoicePlayback, | |
| &DSDEVID_DefaultVoiceCapture, | |
| &DSCBufferDesc,&DSBufferDesc,get_hwnd(),DSSCL_EXCLUSIVE, | |
| &dsfdo,&pDSCBuffer8,&pDSBuffer8,NULL); | |
| ok(rc==DSERR_NODRIVER||rc==DSERR_INVALIDCALL, | |
| "DirectSoundFullDuplexCreate(DSDEVID_DefaultVoicePlayback," | |
| "DSDEVID_DefaultVoiceCapture) should have failed: %08x\n", rc); | |
| if (rc==DS_OK && dsfdo) | |
| IDirectSoundFullDuplex_Release(dsfdo); | |
| } | |
| 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*)0xdeadbeef, 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)); | |
| } | |
| START_TEST(duplex) | |
| { | |
| HMODULE hDsound; | |
| CoInitialize(NULL); | |
| hDsound = LoadLibraryA("dsound.dll"); | |
| if (hDsound) | |
| { | |
| pDirectSoundFullDuplexCreate=(void*)GetProcAddress(hDsound, | |
| "DirectSoundFullDuplexCreate"); | |
| if (pDirectSoundFullDuplexCreate) { | |
| test_COM(); | |
| IDirectSoundFullDuplex_tests(); | |
| } else | |
| skip("DirectSoundFullDuplexCreate missing - skipping all tests\n"); | |
| FreeLibrary(hDsound); | |
| } | |
| else | |
| skip("dsound.dll not found - skipping all tests\n"); | |
| CoUninitialize(); | |
| } |