static void wave_in_tests(void) { WAVEINCAPSA capsA; WAVEINCAPSW capsW; WAVEFORMATEX format; HWAVEIN win; MMRESULT rc; DWORD preferred, status; UINT ndev,d; ndev=waveInGetNumDevs(); trace("found %d WaveIn devices\n",ndev); rc = waveInMessage((HWAVEIN)WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR)&preferred, (DWORD_PTR)&status); ok((ndev == 0 && (rc == MMSYSERR_NODRIVER || rc == MMSYSERR_BADDEVICEID)) || rc == MMSYSERR_NOTSUPPORTED || rc == MMSYSERR_NOERROR, "waveInMessage(DRVM_MAPPER_PREFERRED_GET) failed: %u\n", rc); if(rc != MMSYSERR_NOTSUPPORTED) ok((ndev == 0 && (preferred == -1 || broken(preferred != -1))) || preferred < ndev, "Got invalid preferred device: 0x%x\n", preferred); rc=waveInGetDevCapsA(ndev+1,&capsA,sizeof(capsA)); ok(rc==MMSYSERR_BADDEVICEID, "waveInGetDevCapsA(%s): MMSYSERR_BADDEVICEID expected, got %s\n", dev_name(ndev+1),wave_in_error(rc)); rc=waveInGetDevCapsA(WAVE_MAPPER,&capsA,sizeof(capsA)); ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NODRIVER || (!ndev && (rc==MMSYSERR_BADDEVICEID)), "waveInGetDevCapsA(%s): got %s\n",dev_name(WAVE_MAPPER),wave_in_error(rc)); rc=waveInGetDevCapsW(ndev+1,&capsW,sizeof(capsW)); ok(rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NOTSUPPORTED, "waveInGetDevCapsW(%s): MMSYSERR_BADDEVICEID or MMSYSERR_NOTSUPPORTED " "expected, got %s\n",dev_name(ndev+1),wave_in_error(rc)); rc=waveInGetDevCapsW(WAVE_MAPPER,&capsW,sizeof(capsW)); ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NODRIVER || rc==MMSYSERR_NOTSUPPORTED || (!ndev && (rc==MMSYSERR_BADDEVICEID)), "waveInGetDevCapsW(%s): got %s\n", dev_name(ndev+1),wave_in_error(rc)); format.wFormatTag=WAVE_FORMAT_PCM; format.nChannels=2; format.wBitsPerSample=16; format.nSamplesPerSec=44100; format.nBlockAlign=format.nChannels*format.wBitsPerSample/8; format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign; format.cbSize=0; rc=waveInOpen(&win,ndev+1,&format,0,0,CALLBACK_NULL); ok(rc==MMSYSERR_BADDEVICEID, "waveInOpen(%s): MMSYSERR_BADDEVICEID expected, got %s\n", dev_name(ndev+1),wave_in_error(rc)); for (d=0;d<ndev;d++) wave_in_test_device(d); if (ndev>0) wave_in_test_device(WAVE_MAPPER); }
static void wave_in_tests(void) { WAVEINCAPSA capsA; WAVEINCAPSW capsW; WAVEFORMATEX format; HWAVEIN win; MMRESULT rc; UINT ndev,d; ndev=waveInGetNumDevs(); trace("found %d WaveIn devices\n",ndev); rc=waveInGetDevCapsA(ndev+1,&capsA,sizeof(capsA)); ok(rc==MMSYSERR_BADDEVICEID, "waveInGetDevCapsA(%s): MMSYSERR_BADDEVICEID expected, got %s\n", dev_name(ndev+1),wave_in_error(rc)); rc=waveInGetDevCapsA(WAVE_MAPPER,&capsA,sizeof(capsA)); ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NODRIVER || (!ndev && (rc==MMSYSERR_BADDEVICEID)), "waveInGetDevCapsA(%s): got %s\n",dev_name(WAVE_MAPPER),wave_in_error(rc)); rc=waveInGetDevCapsW(ndev+1,&capsW,sizeof(capsW)); ok(rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NOTSUPPORTED, "waveInGetDevCapsW(%s): MMSYSERR_BADDEVICEID or MMSYSERR_NOTSUPPORTED " "expected, got %s\n",dev_name(ndev+1),wave_in_error(rc)); rc=waveInGetDevCapsW(WAVE_MAPPER,&capsW,sizeof(capsW)); ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NODRIVER || rc==MMSYSERR_NOTSUPPORTED || (!ndev && (rc==MMSYSERR_BADDEVICEID)), "waveInGetDevCapsW(%s): got %s\n", dev_name(ndev+1),wave_in_error(rc)); format.wFormatTag=WAVE_FORMAT_PCM; format.nChannels=2; format.wBitsPerSample=16; format.nSamplesPerSec=44100; format.nBlockAlign=format.nChannels*format.wBitsPerSample/8; format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign; format.cbSize=0; rc=waveInOpen(&win,ndev+1,&format,0,0,CALLBACK_NULL); ok(rc==MMSYSERR_BADDEVICEID, "waveInOpen(%s): MMSYSERR_BADDEVICEID expected, got %s\n", dev_name(ndev+1),wave_in_error(rc)); for (d=0;d<ndev;d++) wave_in_test_device(d); if (ndev>0) wave_in_test_device(WAVE_MAPPER); }
static DWORD widGetDevCaps(UINT wDevID, WAVEMAPDATA* wim, LPWAVEINCAPSW lpWaveCaps, DWORD dwParam2) { TRACE("(%04x, %p %p %08x)\n", wDevID, wim, lpWaveCaps, dwParam2); /* if opened low driver, forward message */ if (WAVEMAP_IsData(wim)) return waveInGetDevCapsW((UINT_PTR)wim->u.in.hInnerWave, lpWaveCaps, dwParam2); /* else if no drivers, nothing to map so return bad device */ if (waveInGetNumDevs() == 0) { WARN("bad device id\n"); return MMSYSERR_BADDEVICEID; } /* otherwise, return caps of mapper itself */ if (wDevID == (UINT)-1 || wDevID == (UINT16)-1) { WAVEINCAPSW wic; static const WCHAR init[] = {'W','i','n','e',' ','w','a','v','e',' ','i','n',' ','m','a','p','p','e','r',0}; wic.wMid = 0x00FF; wic.wPid = 0x0001; wic.vDriverVersion = 0x0001; strcpyW(wic.szPname, init); wic.dwFormats = WAVE_FORMAT_96M08 | WAVE_FORMAT_96S08 | WAVE_FORMAT_96M16 | WAVE_FORMAT_96S16 | WAVE_FORMAT_48M08 | WAVE_FORMAT_48S08 | WAVE_FORMAT_48M16 | WAVE_FORMAT_48S16 | WAVE_FORMAT_4M08 | WAVE_FORMAT_4S08 | WAVE_FORMAT_4M16 | WAVE_FORMAT_4S16 | WAVE_FORMAT_2M08 | WAVE_FORMAT_2S08 | WAVE_FORMAT_2M16 | WAVE_FORMAT_2S16 | WAVE_FORMAT_1M08 | WAVE_FORMAT_1S08 | WAVE_FORMAT_1M16 | WAVE_FORMAT_1S16; wic.wChannels = 2; memcpy(lpWaveCaps, &wic, min(dwParam2, sizeof(wic))); return MMSYSERR_NOERROR; } ERR("This shouldn't happen\n"); return MMSYSERR_ERROR; }
static void ProbeCaptureDevices(void) { al_string *iter, *end; ALuint numdevs; ALuint i; clear_devlist(&CaptureDevices); numdevs = waveInGetNumDevs(); VECTOR_RESERVE(CaptureDevices, numdevs); for(i = 0; i < numdevs; i++) { WAVEINCAPSW WaveCaps; al_string dname; AL_STRING_INIT(dname); if(waveInGetDevCapsW(i, &WaveCaps, sizeof(WaveCaps)) == MMSYSERR_NOERROR) { ALuint count = 0; do { al_string_copy_wcstr(&dname, WaveCaps.szPname); if(count != 0) { char str[64]; snprintf(str, sizeof(str), " #%d", count+1); al_string_append_cstr(&dname, str); } count++; iter = VECTOR_ITER_BEGIN(CaptureDevices); end = VECTOR_ITER_END(CaptureDevices); for(; iter != end; iter++) { if(al_string_cmp(*iter, dname) == 0) break; } } while(iter != end); TRACE("Got device \"%s\", ID %u\n", al_string_get_cstr(dname), i); } VECTOR_PUSH_BACK(CaptureDevices, dname); } }
static void ProbeCaptureDevices(void) { ALuint numdevs; ALuint i; clear_devlist(&CaptureDevices); numdevs = waveInGetNumDevs(); VECTOR_RESIZE(CaptureDevices, 0, numdevs); for(i = 0;i < numdevs;i++) { WAVEINCAPSW WaveCaps; const al_string *iter; al_string dname; AL_STRING_INIT(dname); if(waveInGetDevCapsW(i, &WaveCaps, sizeof(WaveCaps)) == MMSYSERR_NOERROR) { ALuint count = 0; while(1) { alstr_copy_cstr(&dname, DEVNAME_HEAD); alstr_append_wcstr(&dname, WaveCaps.szPname); if(count != 0) { char str[64]; snprintf(str, sizeof(str), " #%d", count+1); alstr_append_cstr(&dname, str); } count++; #define MATCH_ENTRY(i) (alstr_cmp(dname, *(i)) == 0) VECTOR_FIND_IF(iter, const al_string, CaptureDevices, MATCH_ENTRY); if(iter == VECTOR_END(CaptureDevices)) break; #undef MATCH_ENTRY } TRACE("Got device \"%s\", ID %u\n", alstr_get_cstr(dname), i); } VECTOR_PUSH_BACK(CaptureDevices, dname); } }
/********************************************************************** * DEVENUM_CreateSpecialCategories (INTERNAL) * * Creates the keys in the registry for the dynamic categories */ static HRESULT DEVENUM_CreateSpecialCategories(void) { HRESULT res; WCHAR szDSoundNameFormat[MAX_PATH + 1]; WCHAR szDSoundName[MAX_PATH + 1]; DWORD iDefaultDevice = -1; UINT numDevs; IFilterMapper2 * pMapper = NULL; REGFILTER2 rf2; REGFILTERPINS2 rfp2; WCHAR path[MAX_PATH]; HKEY basekey; if (DEVENUM_populate_handle) return S_OK; DEVENUM_populate_handle = CreateEventW(NULL, TRUE, FALSE, DEVENUM_populate_handle_nameW); if (GetLastError() == ERROR_ALREADY_EXISTS) { /* Webcams can take some time to scan if the driver is badly written and it enables them, * so have a 10 s timeout here */ if (WaitForSingleObject(DEVENUM_populate_handle, 10000) == WAIT_TIMEOUT) WARN("Waiting for object timed out\n"); TRACE("No need to rescan\n"); return S_OK; } TRACE("Scanning for devices\n"); /* Since devices can change between session, for example because you just plugged in a webcam * or switched from pulseaudio to alsa, delete all old devices first */ if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_AudioRendererCategory, &basekey, path, MAX_PATH))) RegDeleteTreeW(basekey, path); if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_AudioInputDeviceCategory, &basekey, path, MAX_PATH))) RegDeleteTreeW(basekey, path); if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_VideoInputDeviceCategory, &basekey, path, MAX_PATH))) RegDeleteTreeW(basekey, path); if (SUCCEEDED(DEVENUM_GetCategoryKey(&CLSID_MidiRendererCategory, &basekey, path, MAX_PATH))) RegDeleteTreeW(basekey, path); rf2.dwVersion = 2; rf2.dwMerit = MERIT_PREFERRED; rf2.u.s1.cPins2 = 1; rf2.u.s1.rgPins2 = &rfp2; rfp2.cInstances = 1; rfp2.nMediums = 0; rfp2.lpMedium = NULL; rfp2.clsPinCategory = &IID_NULL; if (!LoadStringW(DEVENUM_hInstance, IDS_DEVENUM_DS, szDSoundNameFormat, sizeof(szDSoundNameFormat)/sizeof(szDSoundNameFormat[0])-1)) { ERR("Couldn't get string resource (GetLastError() is %d)\n", GetLastError()); return HRESULT_FROM_WIN32(GetLastError()); } res = CoCreateInstance(&CLSID_FilterMapper2, NULL, CLSCTX_INPROC, &IID_IFilterMapper2, (void **) &pMapper); /* * Fill in info for devices */ if (SUCCEEDED(res)) { UINT i; WAVEOUTCAPSW wocaps; WAVEINCAPSW wicaps; MIDIOUTCAPSW mocaps; REGPINTYPES * pTypes; numDevs = waveOutGetNumDevs(); res = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory); if (FAILED(res)) /* can't register any devices in this category */ numDevs = 0; rfp2.dwFlags = REG_PINFLAG_B_RENDERER; for (i = 0; i < numDevs; i++) { if (waveOutGetDevCapsW(i, &wocaps, sizeof(WAVEOUTCAPSW)) == MMSYSERR_NOERROR) { IMoniker * pMoniker = NULL; rfp2.nMediaTypes = 1; pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES)); if (!pTypes) { IFilterMapper2_Release(pMapper); return E_OUTOFMEMORY; } /* FIXME: Native devenum seems to register a lot more types for * DSound than we do. Not sure what purpose they serve */ pTypes[0].clsMajorType = &MEDIATYPE_Audio; pTypes[0].clsMinorType = &MEDIASUBTYPE_PCM; rfp2.lpMediaType = pTypes; res = IFilterMapper2_RegisterFilter(pMapper, &CLSID_AudioRender, wocaps.szPname, &pMoniker, &CLSID_AudioRendererCategory, wocaps.szPname, &rf2); /* FIXME: do additional stuff with IMoniker here, depending on what RegisterFilter does */ if (pMoniker) { IMoniker_Release(pMoniker); pMoniker = NULL; } wsprintfW(szDSoundName, szDSoundNameFormat, wocaps.szPname); res = IFilterMapper2_RegisterFilter(pMapper, &CLSID_DSoundRender, szDSoundName, &pMoniker, &CLSID_AudioRendererCategory, szDSoundName, &rf2); /* FIXME: do additional stuff with IMoniker here, depending on what RegisterFilter does */ if (pMoniker) IMoniker_Release(pMoniker); if (i == iDefaultDevice) { FIXME("Default device\n"); } CoTaskMemFree(pTypes); } } numDevs = waveInGetNumDevs(); res = DEVENUM_CreateAMCategoryKey(&CLSID_AudioInputDeviceCategory); if (FAILED(res)) /* can't register any devices in this category */ numDevs = 0; rfp2.dwFlags = REG_PINFLAG_B_OUTPUT; for (i = 0; i < numDevs; i++) { if (waveInGetDevCapsW(i, &wicaps, sizeof(WAVEINCAPSW)) == MMSYSERR_NOERROR) { IMoniker * pMoniker = NULL; rfp2.nMediaTypes = 1; pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES)); if (!pTypes) { IFilterMapper2_Release(pMapper); return E_OUTOFMEMORY; } /* FIXME: Not sure if these are correct */ pTypes[0].clsMajorType = &MEDIATYPE_Audio; pTypes[0].clsMinorType = &MEDIASUBTYPE_PCM; rfp2.lpMediaType = pTypes; res = IFilterMapper2_RegisterFilter(pMapper, &CLSID_AudioRecord, wicaps.szPname, &pMoniker, &CLSID_AudioInputDeviceCategory, wicaps.szPname, &rf2); /* FIXME: do additional stuff with IMoniker here, depending on what RegisterFilter does */ if (pMoniker) IMoniker_Release(pMoniker); CoTaskMemFree(pTypes); } } numDevs = midiOutGetNumDevs(); res = DEVENUM_CreateAMCategoryKey(&CLSID_MidiRendererCategory); if (FAILED(res)) /* can't register any devices in this category */ numDevs = 0; rfp2.dwFlags = REG_PINFLAG_B_RENDERER; for (i = 0; i < numDevs; i++) { if (midiOutGetDevCapsW(i, &mocaps, sizeof(MIDIOUTCAPSW)) == MMSYSERR_NOERROR) { IMoniker * pMoniker = NULL; rfp2.nMediaTypes = 1; pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES)); if (!pTypes) { IFilterMapper2_Release(pMapper); return E_OUTOFMEMORY; } /* FIXME: Not sure if these are correct */ pTypes[0].clsMajorType = &MEDIATYPE_Midi; pTypes[0].clsMinorType = &MEDIASUBTYPE_None; rfp2.lpMediaType = pTypes; res = IFilterMapper2_RegisterFilter(pMapper, &CLSID_AVIMIDIRender, mocaps.szPname, &pMoniker, &CLSID_MidiRendererCategory, mocaps.szPname, &rf2); /* FIXME: do additional stuff with IMoniker here, depending on what RegisterFilter does */ /* Native version sets MidiOutId */ if (pMoniker) IMoniker_Release(pMoniker); if (i == iDefaultDevice) { FIXME("Default device\n"); } CoTaskMemFree(pTypes); } } res = DEVENUM_CreateAMCategoryKey(&CLSID_VideoInputDeviceCategory); if (SUCCEEDED(res)) for (i = 0; i < 10; i++) { WCHAR szDeviceName[32], szDeviceVersion[32], szDevicePath[10]; if (capGetDriverDescriptionW ((WORD) i, szDeviceName, sizeof(szDeviceName)/sizeof(WCHAR), szDeviceVersion, sizeof(szDeviceVersion)/sizeof(WCHAR))) { IMoniker * pMoniker = NULL; IPropertyBag * pPropBag = NULL; WCHAR dprintf[] = { 'v','i','d','e','o','%','d',0 }; snprintfW(szDevicePath, sizeof(szDevicePath)/sizeof(WCHAR), dprintf, i); /* The above code prevents 1 device with a different ID overwriting another */ rfp2.nMediaTypes = 1; pTypes = CoTaskMemAlloc(rfp2.nMediaTypes * sizeof(REGPINTYPES)); if (!pTypes) { IFilterMapper2_Release(pMapper); return E_OUTOFMEMORY; } pTypes[0].clsMajorType = &MEDIATYPE_Video; pTypes[0].clsMinorType = &MEDIASUBTYPE_None; rfp2.lpMediaType = pTypes; res = IFilterMapper2_RegisterFilter(pMapper, &CLSID_VfwCapture, szDeviceName, &pMoniker, &CLSID_VideoInputDeviceCategory, szDevicePath, &rf2); if (pMoniker) { OLECHAR wszVfwIndex[] = { 'V','F','W','I','n','d','e','x',0 }; VARIANT var; V_VT(&var) = VT_I4; V_UNION(&var, ulVal) = i; res = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID)&pPropBag); if (SUCCEEDED(res)) res = IPropertyBag_Write(pPropBag, wszVfwIndex, &var); IMoniker_Release(pMoniker); } if (i == iDefaultDevice) FIXME("Default device\n"); CoTaskMemFree(pTypes); } } } if (pMapper) IFilterMapper2_Release(pMapper); SetEvent(DEVENUM_populate_handle); return res; }
HRESULT DSoundEnumerate( LPDSENUMCALLBACKA lpDSEnumCallbackA, LPDSENUMCALLBACKW lpDSEnumCallbackW, LPVOID lpContext, BOOL bPlayback) { ULONG ResourceId; BOOL bResult; LPFILTERINFO CurInfo; WAVEOUTCAPSW WaveOutCaps; WAVEINCAPSW WaveInCaps; if (!RootInfo) { EnumAudioDeviceInterfaces(&RootInfo); } if (lpDSEnumCallbackA == NULL && lpDSEnumCallbackW == NULL) { DPRINT("No callback\n"); return DSERR_INVALIDPARAM; } if (bPlayback) { /* use resource id of playback string */ ResourceId = IDS_PRIMARY_PLAYBACK_DEVICE; } else { /* use resource id of playback string */ ResourceId = IDS_PRIMARY_RECORD_DEVICE; } if (RootInfo) { /* perform first callback */ bResult = DoDSoundCallback(lpDSEnumCallbackA, lpDSEnumCallbackW, NULL, ResourceId, NULL, L"", lpContext); if (!bResult) { /* callback asked as to stop */ return DS_OK; } /* now iterate through all devices */ CurInfo = RootInfo; do { if (bPlayback && !IsEqualGUID(&CurInfo->DeviceGuid[1], &GUID_NULL)) { RtlZeroMemory(&WaveOutCaps, sizeof(WAVEOUTCAPSW)); /* sanity check */ ASSERT(CurInfo->MappedId[1] != ULONG_MAX); /* get wave out caps */ waveOutGetDevCapsW((UINT_PTR)CurInfo->MappedId[1], &WaveOutCaps, sizeof(WAVEOUTCAPSW)); WaveOutCaps.szPname[MAXPNAMELEN-1] = L'\0'; bResult = DoDSoundCallback(lpDSEnumCallbackA, lpDSEnumCallbackW, &CurInfo->DeviceGuid[1], 0, WaveOutCaps.szPname, L"" /* FIXME */, lpContext); if (!bResult) { /* callback asked as to stop */ return DS_OK; } } else if (!bPlayback && !IsEqualGUID(&CurInfo->DeviceGuid[0], &GUID_NULL)) { RtlZeroMemory(&WaveInCaps, sizeof(WAVEINCAPSW)); /* sanity check */ ASSERT(CurInfo->MappedId[1] != ULONG_MAX); /* get wave in caps */ waveInGetDevCapsW((UINT_PTR)CurInfo->MappedId[0], &WaveInCaps, sizeof(WAVEINCAPSW)); WaveInCaps.szPname[MAXPNAMELEN-1] = L'\0'; bResult = DoDSoundCallback(lpDSEnumCallbackA, lpDSEnumCallbackW, &CurInfo->DeviceGuid[0], 0, WaveInCaps.szPname, L"" /* FIXME */, lpContext); if (!bResult) { /* callback asked as to stop */ return DS_OK; } } /* move to next entry */ CurInfo = CurInfo->lpNext; }while(CurInfo); } return DS_OK; }
static void wave_in_test_device(UINT_PTR device) { WAVEINCAPSA capsA; WAVEINCAPSW capsW; WAVEFORMATEX format; WAVEFORMATEXTENSIBLE wfex; HWAVEIN win; MMRESULT rc; UINT f; WCHAR * nameW; CHAR * nameA; DWORD size; DWORD dwPageSize; BYTE * twoPages; SYSTEM_INFO sSysInfo; DWORD flOldProtect; BOOL res; GetSystemInfo(&sSysInfo); dwPageSize = sSysInfo.dwPageSize; rc=waveInGetDevCapsA(device,&capsA,sizeof(capsA)); ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NODRIVER, "waveInGetDevCapsA(%s): failed to get capabilities: rc=%s\n", dev_name(device),wave_in_error(rc)); if (rc==MMSYSERR_BADDEVICEID || rc==MMSYSERR_NODRIVER) return; rc=waveInGetDevCapsW(device,&capsW,sizeof(capsW)); ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NOTSUPPORTED, "waveInGetDevCapsW(%s): MMSYSERR_NOERROR or MMSYSERR_NOTSUPPORTED " "expected, got %s\n",dev_name(device),wave_in_error(rc)); rc=waveInGetDevCapsA(device,NULL,sizeof(capsA)); ok(rc==MMSYSERR_INVALPARAM, "waveInGetDevCapsA(%s): MMSYSERR_INVALPARAM expected, got %s\n", dev_name(device),wave_in_error(rc)); rc=waveInGetDevCapsW(device,NULL,sizeof(capsW)); ok(rc==MMSYSERR_INVALPARAM || rc==MMSYSERR_NOTSUPPORTED, "waveInGetDevCapsW(%s): MMSYSERR_INVALPARAM or MMSYSERR_NOTSUPPORTED " "expected, got %s\n",dev_name(device),wave_in_error(rc)); if (0) { /* FIXME: this works on windows but crashes wine */ rc=waveInGetDevCapsA(device,(LPWAVEINCAPSA)1,sizeof(capsA)); ok(rc==MMSYSERR_INVALPARAM, "waveInGetDevCapsA(%s): MMSYSERR_INVALPARAM expected, got %s\n", dev_name(device),wave_in_error(rc)); rc=waveInGetDevCapsW(device,(LPWAVEINCAPSW)1,sizeof(capsW)); ok(rc==MMSYSERR_INVALPARAM || rc==MMSYSERR_NOTSUPPORTED, "waveInGetDevCapsW(%s): MMSYSERR_INVALPARAM or MMSYSERR_NOTSUPPORTED " "expected, got %s\n",dev_name(device),wave_in_error(rc)); } rc=waveInGetDevCapsA(device,&capsA,4); ok(rc==MMSYSERR_NOERROR, "waveInGetDevCapsA(%s): MMSYSERR_NOERROR expected, got %s\n", dev_name(device),wave_in_error(rc)); rc=waveInGetDevCapsW(device,&capsW,4); ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_NOTSUPPORTED || rc==MMSYSERR_INVALPARAM, /* Vista, W2K8 */ "waveInGetDevCapsW(%s): unexpected return value %s\n", dev_name(device),wave_in_error(rc)); nameA=NULL; rc=waveInMessage((HWAVEIN)device, DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&size, 0); ok(rc==MMSYSERR_NOERROR || rc==MMSYSERR_INVALPARAM || rc==MMSYSERR_NOTSUPPORTED, "waveInMessage(%s): failed to get interface size: rc=%s\n", dev_name(device),wave_in_error(rc)); if (rc==MMSYSERR_NOERROR) { nameW = HeapAlloc(GetProcessHeap(), 0, size); rc=waveInMessage((HWAVEIN)device, DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)nameW, size); ok(rc==MMSYSERR_NOERROR,"waveInMessage(%s): failed to get interface " "name: rc=%s\n",dev_name(device),wave_in_error(rc)); ok(lstrlenW(nameW)+1==size/sizeof(WCHAR), "got an incorrect size %d\n", size); if (rc==MMSYSERR_NOERROR) { nameA = HeapAlloc(GetProcessHeap(), 0, size/sizeof(WCHAR)); WideCharToMultiByte(CP_ACP, 0, nameW, size/sizeof(WCHAR), nameA, size/sizeof(WCHAR), NULL, NULL); } HeapFree(GetProcessHeap(), 0, nameW); } else if (rc==MMSYSERR_NOTSUPPORTED) { nameA=HeapAlloc(GetProcessHeap(), 0, sizeof("not supported")); strcpy(nameA, "not supported"); } trace(" %s: \"%s\" (%s) %d.%d (%d:%d)\n",dev_name(device),capsA.szPname, (nameA?nameA:"failed"),capsA.vDriverVersion >> 8, capsA.vDriverVersion & 0xff,capsA.wMid,capsA.wPid); trace(" channels=%d formats=%05x\n", capsA.wChannels,capsA.dwFormats); HeapFree(GetProcessHeap(), 0, nameA); for (f=0;f<NB_WIN_FORMATS;f++) { format.wFormatTag=WAVE_FORMAT_PCM; format.nChannels=win_formats[f][3]; format.wBitsPerSample=win_formats[f][2]; format.nSamplesPerSec=win_formats[f][1]; format.nBlockAlign=format.nChannels*format.wBitsPerSample/8; format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign; format.cbSize=0; wave_in_test_deviceIn(device,&format,win_formats[f][0],0, &capsA); if (device != WAVE_MAPPER) { wave_in_test_deviceIn(device,&format,win_formats[f][0], WAVE_FORMAT_DIRECT, &capsA); wave_in_test_deviceIn(device,&format,win_formats[f][0], WAVE_MAPPED, &capsA); } } /* Try a PCMWAVEFORMAT aligned next to an unaccessible page for bounds * checking */ twoPages = VirtualAlloc(NULL, 2 * dwPageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); ok(twoPages!=NULL,"Failed to allocate 2 pages of memory\n"); if (twoPages) { res = VirtualProtect(twoPages + dwPageSize, dwPageSize, PAGE_NOACCESS, &flOldProtect); ok(res, "Failed to set memory access on second page\n"); if (res) { LPWAVEFORMATEX pwfx = (LPWAVEFORMATEX)(twoPages + dwPageSize - sizeof(PCMWAVEFORMAT)); pwfx->wFormatTag=WAVE_FORMAT_PCM; pwfx->nChannels=1; pwfx->wBitsPerSample=8; pwfx->nSamplesPerSec=22050; pwfx->nBlockAlign=pwfx->nChannels*pwfx->wBitsPerSample/8; pwfx->nAvgBytesPerSec=pwfx->nSamplesPerSec*pwfx->nBlockAlign; wave_in_test_deviceIn(device,pwfx,WAVE_FORMAT_2M08,0, &capsA); if (device != WAVE_MAPPER) { wave_in_test_deviceIn(device,pwfx,WAVE_FORMAT_2M08, WAVE_FORMAT_DIRECT, &capsA); wave_in_test_deviceIn(device,pwfx,WAVE_FORMAT_2M08, WAVE_MAPPED, &capsA); } } VirtualFree(twoPages, 2 * dwPageSize, MEM_RELEASE); } /* test non PCM formats */ format.wFormatTag=WAVE_FORMAT_MULAW; format.nChannels=1; format.wBitsPerSample=8; format.nSamplesPerSec=8000; format.nBlockAlign=format.nChannels*format.wBitsPerSample/8; format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign; format.cbSize=0; rc=waveInOpen(&win,device,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT); ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM, "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc)); if (rc==MMSYSERR_NOERROR) { waveInClose(win); wave_in_test_deviceIn(device,&format,0,0,&capsA); } else trace("waveInOpen(%s): WAVE_FORMAT_MULAW not supported\n", dev_name(device)); format.wFormatTag=WAVE_FORMAT_ADPCM; format.nChannels=2; format.wBitsPerSample=4; format.nSamplesPerSec=22050; format.nBlockAlign=format.nChannels*format.wBitsPerSample/8; format.nAvgBytesPerSec=format.nSamplesPerSec*format.nBlockAlign; format.cbSize=0; rc=waveInOpen(&win,device,&format,0,0,CALLBACK_NULL|WAVE_FORMAT_DIRECT); ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM, "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc)); if (rc==MMSYSERR_NOERROR) { waveInClose(win); wave_in_test_deviceIn(device,&format,0,0,&capsA); } else trace("waveInOpen(%s): WAVE_FORMAT_ADPCM not supported\n", dev_name(device)); /* test if WAVEFORMATEXTENSIBLE supported */ wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE; wfex.Format.nChannels=2; wfex.Format.wBitsPerSample=16; wfex.Format.nSamplesPerSec=22050; wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8; wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec* wfex.Format.nBlockAlign; wfex.Format.cbSize=22; wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample; wfex.dwChannelMask=SPEAKER_ALL; wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM; rc=waveInOpen(&win,device,&wfex.Format,0,0, CALLBACK_NULL|WAVE_FORMAT_DIRECT); ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM, "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc)); if (rc==MMSYSERR_NOERROR) { waveInClose(win); wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA); } else trace("waveInOpen(%s): WAVE_FORMAT_EXTENSIBLE not supported\n", dev_name(device)); /* test if 4 channels supported */ wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE; wfex.Format.nChannels=4; wfex.Format.wBitsPerSample=16; wfex.Format.nSamplesPerSec=22050; wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8; wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec* wfex.Format.nBlockAlign; wfex.Format.cbSize=22; wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample; wfex.dwChannelMask=SPEAKER_ALL; wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM; rc=waveInOpen(&win,device,&wfex.Format,0,0, CALLBACK_NULL|WAVE_FORMAT_DIRECT); ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM, "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc)); if (rc==MMSYSERR_NOERROR) { waveInClose(win); wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA); } else trace("waveInOpen(%s): 4 channels not supported\n", dev_name(device)); /* test if 6 channels supported */ wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE; wfex.Format.nChannels=6; wfex.Format.wBitsPerSample=16; wfex.Format.nSamplesPerSec=22050; wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8; wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec* wfex.Format.nBlockAlign; wfex.Format.cbSize=22; wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample; wfex.dwChannelMask=SPEAKER_ALL; wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM; rc=waveInOpen(&win,device,&wfex.Format,0,0, CALLBACK_NULL|WAVE_FORMAT_DIRECT); ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM, "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc)); if (rc==MMSYSERR_NOERROR) { waveInClose(win); wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA); } else trace("waveInOpen(%s): 6 channels not supported\n", dev_name(device)); if (0) { /* FIXME: ALSA doesn't like this */ /* test if 24 bit samples supported */ wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE; wfex.Format.nChannels=2; wfex.Format.wBitsPerSample=24; wfex.Format.nSamplesPerSec=22050; wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8; wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec* wfex.Format.nBlockAlign; wfex.Format.cbSize=22; wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample; wfex.dwChannelMask=SPEAKER_ALL; wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM; rc=waveInOpen(&win,device,&wfex.Format,0,0, CALLBACK_NULL|WAVE_FORMAT_DIRECT); ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM, "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc)); if (rc==MMSYSERR_NOERROR) { waveInClose(win); wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA); } else trace("waveInOpen(%s): 24 bit samples not supported\n", dev_name(device)); } /* test if 32 bit samples supported */ wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE; wfex.Format.nChannels=2; wfex.Format.wBitsPerSample=32; wfex.Format.nSamplesPerSec=22050; wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8; wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec* wfex.Format.nBlockAlign; wfex.Format.cbSize=22; wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample; wfex.dwChannelMask=SPEAKER_ALL; wfex.SubFormat=KSDATAFORMAT_SUBTYPE_PCM; rc=waveInOpen(&win,device,&wfex.Format,0,0, CALLBACK_NULL|WAVE_FORMAT_DIRECT); ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM, "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc)); if (rc==MMSYSERR_NOERROR) { waveInClose(win); wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA); } else trace("waveInOpen(%s): 32 bit samples not supported\n", dev_name(device)); /* test if 32 bit float samples supported */ wfex.Format.wFormatTag=WAVE_FORMAT_EXTENSIBLE; wfex.Format.nChannels=2; wfex.Format.wBitsPerSample=32; wfex.Format.nSamplesPerSec=22050; wfex.Format.nBlockAlign=wfex.Format.nChannels*wfex.Format.wBitsPerSample/8; wfex.Format.nAvgBytesPerSec=wfex.Format.nSamplesPerSec* wfex.Format.nBlockAlign; wfex.Format.cbSize=22; wfex.Samples.wValidBitsPerSample=wfex.Format.wBitsPerSample; wfex.dwChannelMask=SPEAKER_ALL; wfex.SubFormat=KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; rc=waveInOpen(&win,device,&wfex.Format,0,0, CALLBACK_NULL|WAVE_FORMAT_DIRECT); ok(rc==MMSYSERR_NOERROR || rc==WAVERR_BADFORMAT || rc==MMSYSERR_INVALFLAG || rc==MMSYSERR_INVALPARAM, "waveInOpen(%s): returned: %s\n",dev_name(device),wave_in_error(rc)); if (rc==MMSYSERR_NOERROR) { waveInClose(win); wave_in_test_deviceIn(device,&wfex.Format,0,0,&capsA); } else trace("waveInOpen(%s): 32 bit float samples not supported\n", dev_name(device)); }
HRESULT WINAPI KSPropertySetImpl_Get( LPKSPROPERTYSET iface, REFGUID guidPropSet, ULONG dwPropID, LPVOID pInstanceData, ULONG cbInstanceData, LPVOID pPropData, ULONG cbPropData, PULONG pcbReturned ) { LPOLESTR pStr; //HRESULT hr; MMRESULT Result; WAVEINCAPSW CapsIn; WAVEOUTCAPSW CapsOut; GUID DeviceGuid; LPFILTERINFO Filter = NULL; PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA Desc; StringFromIID(guidPropSet, &pStr); //DPRINT("Requested Property %ws dwPropID %u pInstanceData %p cbInstanceData %u pPropData %p cbPropData %u pcbReturned %p\n", // pStr, dwPropID, pInstanceData, cbInstanceData, pPropData, cbPropData, pcbReturned); CoTaskMemFree(pStr); if (!IsEqualGUID(guidPropSet, &DSPROPSETID_DirectSoundDevice)) { /* unsupported property set */ return E_PROP_ID_UNSUPPORTED; } if (dwPropID == DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1) { if (cbPropData < sizeof(DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA)) { /* invalid parameter */ return DSERR_INVALIDPARAM; } Desc = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA)pPropData; if (IsEqualGUID(&Desc->DeviceId, &GUID_NULL)) { if (Desc->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) { DPRINT("Using default capture guid\n"); CopyMemory(&DeviceGuid, &DSDEVID_DefaultCapture, sizeof(GUID)); } else { DPRINT("Using default playback guid\n"); CopyMemory(&DeviceGuid, &DSDEVID_DefaultPlayback, sizeof(GUID)); } } else { /* use provided guid */ CopyMemory(&DeviceGuid, &Desc->DeviceId, sizeof(GUID)); } if (GetDeviceID(&DeviceGuid, &Desc->DeviceId) != DS_OK) { DPRINT("Unknown device guid\n"); return DSERR_INVALIDPARAM; } /* sanity check */ ASSERT(FindDeviceByGuid(&Desc->DeviceId, &Filter)); ASSERT(Filter != NULL); /* fill in description */ if (IsEqualGUID(&Desc->DeviceId, &Filter->DeviceGuid[0])) { /* capture device */ Desc->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE; Desc->WaveDeviceId = Filter->MappedId[0]; Result = waveInGetDevCapsW(Filter->MappedId[0], &CapsIn, sizeof(WAVEINCAPSW)); if (Result != MMSYSERR_NOERROR) { CapsIn.szPname[0] = 0; DPRINT("waveInGetDevCaps Device %u failed with %x\n", Filter->MappedId[0], Result); } CapsIn.szPname[MAXPNAMELEN-1] = 0; wcscpy(Desc->DescriptionW, CapsIn.szPname); WideCharToMultiByte(CP_ACP, 0, CapsIn.szPname, -1, Desc->DescriptionA, sizeof(Desc->DescriptionA), NULL, NULL); } else { /* render device */ Desc->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER; Desc->WaveDeviceId = Filter->MappedId[1]; Result = waveOutGetDevCapsW(Filter->MappedId[1], &CapsOut, sizeof(WAVEOUTCAPSW)); if (Result != MMSYSERR_NOERROR) { CapsOut.szPname[0] = 0; DPRINT("waveOutGetDevCaps Device %u failed with %x\n", Filter->MappedId[1], Result); } CapsOut.szPname[MAXPNAMELEN-1] = 0; wcscpy(Desc->DescriptionW, CapsOut.szPname); WideCharToMultiByte(CP_ACP, 0, CapsOut.szPname, -1, Desc->DescriptionA, sizeof(Desc->DescriptionA), NULL, NULL); } /* ReactOS doesnt support vxd or emulated */ Desc->Type = DIRECTSOUNDDEVICE_TYPE_WDM; Desc->ModuleA[0] = 0; Desc->ModuleW[0] = 0; *pcbReturned = sizeof(DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA); return S_OK; } UNIMPLEMENTED return E_PROP_ID_UNSUPPORTED; }
static HRESULT DSPROPERTY_WaveDeviceMappingW( LPVOID pPropData, ULONG cbPropData, PULONG pcbReturned ) { HRESULT hr = DSERR_INVALIDPARAM; PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W_DATA ppd; TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n", pPropData,cbPropData,pcbReturned); ppd = pPropData; if (!ppd) { WARN("invalid parameter: pPropData\n"); return DSERR_INVALIDPARAM; } if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_RENDER) { ULONG wod; unsigned int wodn; TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_RENDER\n"); wodn = waveOutGetNumDevs(); for (wod = 0; wod < wodn; wod++) { WAVEOUTCAPSW capsW; MMRESULT res; res = waveOutGetDevCapsW(wod, &capsW, sizeof(capsW)); if (res == MMSYSERR_NOERROR) { if (lstrcmpW(capsW.szPname, ppd->DeviceName) == 0) { ppd->DeviceId = DSOUND_renderer_guids[wod]; hr = DS_OK; TRACE("found %s for %s\n", debugstr_guid(&ppd->DeviceId), debugstr_w(ppd->DeviceName)); break; } } } } else if (ppd->DataFlow == DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE) { ULONG wid; unsigned int widn; TRACE("DataFlow=DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE\n"); widn = waveInGetNumDevs(); for (wid = 0; wid < widn; wid++) { WAVEINCAPSW capsW; MMRESULT res; res = waveInGetDevCapsW(wid, &capsW, sizeof(capsW)); if (res == MMSYSERR_NOERROR) { if (lstrcmpW(capsW.szPname, ppd->DeviceName) == 0) { ppd->DeviceId = DSOUND_capture_guids[wid]; hr = DS_OK; TRACE("found %s for %s\n", debugstr_guid(&ppd->DeviceId), debugstr_w(ppd->DeviceName)); break; } } } } if (pcbReturned) *pcbReturned = cbPropData; return hr; }