devenum: Register waveIn devices as codec devices.
Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
b7fdedd323
commit
c64f6ad08d
|
@ -52,7 +52,6 @@ static const WCHAR wszDirection[] = {'D','i','r','e','c','t','i','o','n',0};
|
|||
static const WCHAR wszIsRendered[] = {'I','s','R','e','n','d','e','r','e','d',0};
|
||||
static const WCHAR wszTypes[] = {'T','y','p','e','s',0};
|
||||
static const WCHAR wszFriendlyName[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
|
||||
static const WCHAR wszWaveInID[] = {'W','a','v','e','I','n','I','D',0};
|
||||
static const WCHAR wszFilterData[] = {'F','i','l','t','e','r','D','a','t','a',0};
|
||||
|
||||
static ULONG WINAPI DEVENUM_ICreateDevEnum_AddRef(ICreateDevEnum * iface);
|
||||
|
@ -673,6 +672,72 @@ cleanup:
|
|||
}
|
||||
}
|
||||
|
||||
static void register_wavein_devices(void)
|
||||
{
|
||||
static const WCHAR waveinidW[] = {'W','a','v','e','I','n','I','d',0};
|
||||
IPropertyBag *prop_bag = NULL;
|
||||
REGFILTER2 rgf = {0};
|
||||
WCHAR clsid[CHARS_IN_GUID];
|
||||
IMoniker *mon = NULL;
|
||||
WAVEINCAPSW caps;
|
||||
int i, count;
|
||||
VARIANT var;
|
||||
HRESULT hr;
|
||||
|
||||
hr = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory);
|
||||
if (FAILED(hr)) return;
|
||||
|
||||
count = waveInGetNumDevs();
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
waveInGetDevCapsW(i, &caps, sizeof(caps));
|
||||
|
||||
V_VT(&var) = VT_BSTR;
|
||||
|
||||
V_BSTR(&var) = SysAllocString(caps.szPname);
|
||||
if (!(V_BSTR(&var)))
|
||||
goto cleanup;
|
||||
|
||||
hr = register_codec(&CLSID_AudioInputDeviceCategory, V_BSTR(&var), &mon);
|
||||
if (FAILED(hr)) goto cleanup;
|
||||
|
||||
hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag);
|
||||
if (FAILED(hr)) goto cleanup;
|
||||
|
||||
/* write friendly name */
|
||||
hr = IPropertyBag_Write(prop_bag, wszFriendlyName, &var);
|
||||
if (FAILED(hr)) goto cleanup;
|
||||
VariantClear(&var);
|
||||
|
||||
/* write clsid */
|
||||
V_VT(&var) = VT_BSTR;
|
||||
StringFromGUID2(&CLSID_AudioRecord, clsid, CHARS_IN_GUID);
|
||||
if (!(V_BSTR(&var) = SysAllocString(clsid)))
|
||||
goto cleanup;
|
||||
hr = IPropertyBag_Write(prop_bag, clsid_keyname, &var);
|
||||
if (FAILED(hr)) goto cleanup;
|
||||
VariantClear(&var);
|
||||
|
||||
/* write filter data */
|
||||
rgf.dwVersion = 2;
|
||||
rgf.dwMerit = MERIT_DO_NOT_USE;
|
||||
|
||||
write_filter_data(prop_bag, &rgf);
|
||||
|
||||
/* write WaveInId */
|
||||
V_VT(&var) = VT_I4;
|
||||
V_I4(&var) = i;
|
||||
hr = IPropertyBag_Write(prop_bag, waveinidW, &var);
|
||||
if (FAILED(hr)) goto cleanup;
|
||||
|
||||
cleanup:
|
||||
VariantClear(&var);
|
||||
if (prop_bag) IPropertyBag_Release(prop_bag);
|
||||
if (mon) IMoniker_Release(mon);
|
||||
}
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* DEVENUM_ICreateDevEnum_CreateClassEnumerator
|
||||
*/
|
||||
|
@ -696,6 +761,7 @@ static HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator(
|
|||
hr = DirectSoundEnumerateW(®ister_dsound_devices, NULL);
|
||||
if (FAILED(hr)) return hr;
|
||||
register_waveout_devices();
|
||||
register_wavein_devices();
|
||||
|
||||
return create_EnumMoniker(clsidDeviceClass, ppEnumMoniker);
|
||||
}
|
||||
|
@ -832,73 +898,10 @@ static HRESULT register_codecs(void)
|
|||
if (SUCCEEDED(res))
|
||||
{
|
||||
UINT i;
|
||||
WAVEINCAPSW wicaps;
|
||||
MIDIOUTCAPSW mocaps;
|
||||
REGPINTYPES * pTypes;
|
||||
IPropertyBag * pPropBag = NULL;
|
||||
|
||||
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);
|
||||
|
||||
|
||||
if (pMoniker) {
|
||||
VARIANT var;
|
||||
|
||||
V_VT(&var) = VT_I4;
|
||||
V_I4(&var) = i;
|
||||
res = IMoniker_BindToStorage(pMoniker, NULL, NULL, &IID_IPropertyBag, (LPVOID)&pPropBag);
|
||||
if (SUCCEEDED(res))
|
||||
res = IPropertyBag_Write(pPropBag, wszWaveInID, &var);
|
||||
else
|
||||
pPropBag = NULL;
|
||||
|
||||
V_VT(&var) = VT_LPWSTR;
|
||||
V_BSTR(&var) = wicaps.szPname;
|
||||
if (SUCCEEDED(res))
|
||||
res = IPropertyBag_Write(pPropBag, wszFriendlyName, &var);
|
||||
|
||||
if (pPropBag)
|
||||
IPropertyBag_Release(pPropBag);
|
||||
IMoniker_Release(pMoniker);
|
||||
}
|
||||
|
||||
CoTaskMemFree(pTypes);
|
||||
}
|
||||
}
|
||||
|
||||
numDevs = midiOutGetNumDevs();
|
||||
|
||||
res = DEVENUM_CreateAMCategoryKey(&CLSID_MidiRendererCategory);
|
||||
|
|
|
@ -726,6 +726,92 @@ static void test_waveout(void)
|
|||
IParseDisplayName_Release(parser);
|
||||
}
|
||||
|
||||
static void test_wavein(void)
|
||||
{
|
||||
static const WCHAR waveinidW[] = {'W','a','v','e','I','n','I','d',0};
|
||||
IParseDisplayName *parser;
|
||||
IPropertyBag *prop_bag;
|
||||
IMoniker *mon;
|
||||
WCHAR endpoint[200];
|
||||
WCHAR buffer[200];
|
||||
WAVEINCAPSW caps;
|
||||
MMRESULT mmr;
|
||||
int count, i;
|
||||
VARIANT var;
|
||||
HRESULT hr;
|
||||
|
||||
hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser);
|
||||
ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr);
|
||||
|
||||
count = waveInGetNumDevs();
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
waveInGetDevCapsW(i, &caps, sizeof(caps));
|
||||
|
||||
lstrcpyW(buffer, deviceW);
|
||||
lstrcatW(buffer, cmW);
|
||||
StringFromGUID2(&CLSID_AudioInputDeviceCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID);
|
||||
lstrcatW(buffer, backslashW);
|
||||
lstrcatW(buffer, caps.szPname);
|
||||
|
||||
mon = check_display_name(parser, buffer);
|
||||
|
||||
hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag);
|
||||
ok(hr == S_OK, "BindToStorage failed: %#x\n", hr);
|
||||
|
||||
VariantInit(&var);
|
||||
hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
|
||||
if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND))
|
||||
{
|
||||
IPropertyBag_Release(prop_bag);
|
||||
IMoniker_Release(mon);
|
||||
|
||||
/* Win8+ uses the endpoint GUID instead of the device name */
|
||||
mmr = waveInMessage((HWAVEIN)(DWORD_PTR) i, DRV_QUERYFUNCTIONINSTANCEID,
|
||||
(DWORD_PTR) endpoint, sizeof(endpoint));
|
||||
ok(!mmr, "waveInMessage failed: %u\n", mmr);
|
||||
|
||||
lstrcpyW(buffer, deviceW);
|
||||
lstrcatW(buffer, cmW);
|
||||
StringFromGUID2(&CLSID_AudioInputDeviceCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID);
|
||||
lstrcatW(buffer, backslashW);
|
||||
lstrcatW(buffer, waveW);
|
||||
lstrcatW(buffer, strchrW(endpoint, '}') + 2);
|
||||
|
||||
mon = check_display_name(parser, buffer);
|
||||
|
||||
hr = IMoniker_BindToStorage(mon, NULL, NULL, &IID_IPropertyBag, (void **)&prop_bag);
|
||||
ok(hr == S_OK, "BindToStorage failed: %#x\n", hr);
|
||||
|
||||
hr = IPropertyBag_Read(prop_bag, friendly_name, &var, NULL);
|
||||
}
|
||||
ok(hr == S_OK, "Read failed: %#x\n", hr);
|
||||
|
||||
ok(!strncmpW(caps.szPname, V_BSTR(&var), lstrlenW(caps.szPname)), "expected %s, got %s\n",
|
||||
wine_dbgstr_w(caps.szPname), wine_dbgstr_w(V_BSTR(&var)));
|
||||
|
||||
VariantClear(&var);
|
||||
hr = IPropertyBag_Read(prop_bag, clsidW, &var, NULL);
|
||||
ok(hr == S_OK, "Read failed: %#x\n", hr);
|
||||
|
||||
StringFromGUID2(&CLSID_AudioRecord, buffer, CHARS_IN_GUID);
|
||||
ok(!lstrcmpW(buffer, V_BSTR(&var)), "expected %s, got %s\n",
|
||||
wine_dbgstr_w(buffer), wine_dbgstr_w(V_BSTR(&var)));
|
||||
|
||||
VariantClear(&var);
|
||||
hr = IPropertyBag_Read(prop_bag, waveinidW, &var, NULL);
|
||||
ok(hr == S_OK, "Read failed: %#x\n", hr);
|
||||
|
||||
ok(V_I4(&var) == i, "expected %d, got %d\n", i, V_I4(&var));
|
||||
|
||||
IPropertyBag_Release(prop_bag);
|
||||
IMoniker_Release(mon);
|
||||
}
|
||||
|
||||
IParseDisplayName_Release(parser);
|
||||
}
|
||||
|
||||
START_TEST(devenum)
|
||||
{
|
||||
IBindCtx *bind_ctx = NULL;
|
||||
|
@ -752,6 +838,7 @@ START_TEST(devenum)
|
|||
hr = DirectSoundEnumerateW(test_dsound, NULL);
|
||||
ok(hr == S_OK, "got %#x\n", hr);
|
||||
test_waveout();
|
||||
test_wavein();
|
||||
|
||||
CoUninitialize();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue