Skip to content

Commit

Permalink
devenum: Register DirectSound devices as codec devices.
Browse files Browse the repository at this point in the history
Signed-off-by: Zebediah Figura <[email protected]>
Signed-off-by: Alexandre Julliard <[email protected]>
  • Loading branch information
zfigura authored and julliard committed Mar 12, 2018
1 parent 5b4a182 commit 2f87691
Show file tree
Hide file tree
Showing 52 changed files with 232 additions and 462 deletions.
2 changes: 1 addition & 1 deletion dlls/devenum/Makefile.in
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
MODULE = devenum.dll
IMPORTS = strmiids uuid ole32 oleaut32 avicap32 winmm user32 advapi32
IMPORTS = strmiids uuid ole32 oleaut32 avicap32 winmm user32 advapi32 dsound
DELAYIMPORTS = msvfw32

C_SRCS = \
Expand Down
130 changes: 90 additions & 40 deletions dlls/devenum/createdevenum.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "devenum_private.h"
#include "vfw.h"
#include "aviriff.h"
#include "dsound.h"

#include "wine/debug.h"
#include "wine/unicode.h"
Expand All @@ -52,7 +53,6 @@ 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 wszWaveOutID[] = {'W','a','v','e','O','u','t','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);
Expand Down Expand Up @@ -509,6 +509,91 @@ static void register_legacy_filters(void)
if (hkeyFilter) RegCloseKey(hkeyFilter);
}

static BOOL CALLBACK register_dsound_devices(GUID *guid, const WCHAR *desc, const WCHAR *module, void *context)
{
static const WCHAR defaultW[] = {'D','e','f','a','u','l','t',' ','D','i','r','e','c','t','S','o','u','n','d',' ','D','e','v','i','c','e',0};
static const WCHAR directsoundW[] = {'D','i','r','e','c','t','S','o','u','n','d',':',' ',0};
static const WCHAR dsguidW[] = {'D','S','G','u','i','d',0};
IPropertyBag *prop_bag = NULL;
REGFILTERPINS2 rgpins = {0};
REGPINTYPES rgtypes = {0};
REGFILTER2 rgf = {0};
WCHAR clsid[CHARS_IN_GUID];
IMoniker *mon = NULL;
VARIANT var;
HRESULT hr;

hr = DEVENUM_CreateAMCategoryKey(&CLSID_AudioRendererCategory);
if (FAILED(hr)) goto cleanup;

V_VT(&var) = VT_BSTR;
if (guid)
{
WCHAR *name = heap_alloc(sizeof(defaultW) + strlenW(desc) * sizeof(WCHAR));
if (!name)
goto cleanup;
strcpyW(name, directsoundW);
strcatW(name, desc);

V_BSTR(&var) = SysAllocString(name);
heap_free(name);
}
else
V_BSTR(&var) = SysAllocString(defaultW);

if (!V_BSTR(&var))
goto cleanup;

hr = register_codec(&CLSID_AudioRendererCategory, 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_DSoundRender, 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 = guid ? MERIT_DO_NOT_USE : MERIT_PREFERRED;
rgf.u.s2.cPins2 = 1;
rgf.u.s2.rgPins2 = &rgpins;
rgpins.dwFlags = REG_PINFLAG_B_RENDERER;
/* FIXME: native registers many more formats */
rgpins.nMediaTypes = 1;
rgpins.lpMediaType = &rgtypes;
rgtypes.clsMajorType = &MEDIATYPE_Audio;
rgtypes.clsMinorType = &MEDIASUBTYPE_PCM;

write_filter_data(prop_bag, &rgf);

/* write DSound guid */
V_VT(&var) = VT_BSTR;
StringFromGUID2(guid ? guid : &GUID_NULL, clsid, CHARS_IN_GUID);
if (!(V_BSTR(&var) = SysAllocString(clsid)))
goto cleanup;
hr = IPropertyBag_Write(prop_bag, dsguidW, &var);
if (FAILED(hr)) goto cleanup;

cleanup:
VariantClear(&var);
if (prop_bag) IPropertyBag_Release(prop_bag);
if (mon) IMoniker_Release(mon);

return TRUE;
}

/**********************************************************************
* DEVENUM_ICreateDevEnum_CreateClassEnumerator
*/
Expand All @@ -518,6 +603,8 @@ static HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator(
IEnumMoniker **ppEnumMoniker,
DWORD dwFlags)
{
HRESULT hr;

TRACE("(%p)->(%s, %p, %x)\n", iface, debugstr_guid(clsidDeviceClass), ppEnumMoniker, dwFlags);

if (!ppEnumMoniker)
Expand All @@ -527,6 +614,8 @@ static HRESULT WINAPI DEVENUM_ICreateDevEnum_CreateClassEnumerator(

register_codecs();
register_legacy_filters();
hr = DirectSoundEnumerateW(&register_dsound_devices, NULL);
if (FAILED(hr)) return hr;

return create_EnumMoniker(clsidDeviceClass, ppEnumMoniker);
}
Expand Down Expand Up @@ -620,8 +709,6 @@ static void register_vfw_codecs(void)
static HRESULT register_codecs(void)
{
HRESULT res;
WCHAR szDSoundNameFormat[MAX_PATH + 1];
WCHAR szDSoundName[MAX_PATH + 1];
WCHAR class[CHARS_IN_GUID];
DWORD iDefaultDevice = -1;
UINT numDevs;
Expand Down Expand Up @@ -657,12 +744,6 @@ static HRESULT register_codecs(void)
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);
/*
Expand Down Expand Up @@ -713,37 +794,6 @@ static HRESULT register_codecs(void)
wocaps.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, wszWaveOutID, &var);
else
pPropBag = NULL;

V_VT(&var) = VT_LPWSTR;
V_BSTR(&var) = wocaps.szPname;
if (SUCCEEDED(res))
res = IPropertyBag_Write(pPropBag, wszFriendlyName, &var);
if (pPropBag)
IPropertyBag_Release(pPropBag);
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)
Expand Down
2 changes: 0 additions & 2 deletions dlls/devenum/devenum.rc
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT

STRINGTABLE
{
IDS_DEVENUM_DSDEFAULT "Default DirectSound"
IDS_DEVENUM_DS "DirectSound: %s"
IDS_DEVENUM_WODEFAULT "Default WaveOut Device"
IDS_DEVENUM_MIDEFAULT "Default MidiOut Device"
}
Expand Down
2 changes: 0 additions & 2 deletions dlls/devenum/devenum_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,6 @@ extern const WCHAR clsid_keyname[6] DECLSPEC_HIDDEN;
/**********************************************************************
* Resource IDs
*/
#define IDS_DEVENUM_DSDEFAULT 7
#define IDS_DEVENUM_DS 8
#define IDS_DEVENUM_WODEFAULT 9
#define IDS_DEVENUM_MIDEFAULT 10
#define IDS_DEVENUM_KSDEFAULT 11
Expand Down
2 changes: 1 addition & 1 deletion dlls/devenum/tests/Makefile.in
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
TESTDLL = devenum.dll
IMPORTS = oleaut32 ole32 advapi32
IMPORTS = advapi32 dsound oleaut32 ole32

C_SRCS = \
devenum.c
94 changes: 94 additions & 0 deletions dlls/devenum/tests/devenum.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
#include "strmif.h"
#include "uuids.h"
#include "vfwmsgs.h"
#include "mmsystem.h"
#include "dsound.h"

DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);

static const WCHAR friendly_name[] = {'F','r','i','e','n','d','l','y','N','a','m','e',0};
static const WCHAR fcc_handlerW[] = {'F','c','c','H','a','n','d','l','e','r',0};
Expand Down Expand Up @@ -526,6 +530,94 @@ static void test_legacy_filter(void)
IParseDisplayName_Release(parser);
}

static BOOL CALLBACK test_dsound(GUID *guid, const WCHAR *desc, const WCHAR *module, void *context)
{
static const WCHAR defaultW[] = {'D','e','f','a','u','l','t',' ','D','i','r','e','c','t','S','o','u','n','d',' ','D','e','v','i','c','e',0};
static const WCHAR directsoundW[] = {'D','i','r','e','c','t','S','o','u','n','d',':',' ',0};
static const WCHAR dsguidW[] = {'D','S','G','u','i','d',0};
IParseDisplayName *parser;
IPropertyBag *prop_bag;
IMoniker *mon;
WCHAR buffer[200];
WCHAR name[200];
VARIANT var;
HRESULT hr;

if (guid)
{
lstrcpyW(name, directsoundW);
lstrcatW(name, desc);
}
else
{
lstrcpyW(name, defaultW);
guid = (GUID *)&GUID_NULL;
}

hr = CoCreateInstance(&CLSID_CDeviceMoniker, NULL, CLSCTX_INPROC, &IID_IParseDisplayName, (void **)&parser);
ok(hr == S_OK, "Failed to create ParseDisplayName: %#x\n", hr);

lstrcpyW(buffer, deviceW);
lstrcatW(buffer, cmW);
StringFromGUID2(&CLSID_AudioRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID);
lstrcatW(buffer, backslashW);
lstrcatW(buffer, name);

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))
{
/* Win8+ uses the GUID instead of the device name */
IPropertyBag_Release(prop_bag);
IMoniker_Release(mon);

lstrcpyW(buffer, deviceW);
lstrcatW(buffer, cmW);
StringFromGUID2(&CLSID_AudioRendererCategory, buffer + lstrlenW(buffer), CHARS_IN_GUID);
lstrcatW(buffer, backslashW);
lstrcatW(buffer, directsoundW);
StringFromGUID2(guid, buffer + lstrlenW(buffer) - 1, CHARS_IN_GUID);

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);
}
ok(hr == S_OK, "Read failed: %#x\n", hr);

ok(!lstrcmpW(name, V_BSTR(&var)), "expected %s, got %s\n",
wine_dbgstr_w(name), 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_DSoundRender, 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, dsguidW, &var, NULL);
ok(hr == S_OK, "Read failed: %#x\n", hr);

StringFromGUID2(guid, 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)));

IPropertyBag_Release(prop_bag);
IMoniker_Release(mon);
IParseDisplayName_Release(parser);
return TRUE;
}

START_TEST(devenum)
{
IBindCtx *bind_ctx = NULL;
Expand All @@ -549,6 +641,8 @@ START_TEST(devenum)
test_codec();

test_legacy_filter();
hr = DirectSoundEnumerateW(test_dsound, NULL);
ok(hr == S_OK, "got %#x\n", hr);

CoUninitialize();
}
10 changes: 1 addition & 9 deletions po/ar.po
Original file line number Diff line number Diff line change
Expand Up @@ -2933,18 +2933,10 @@ msgid "Note: The private key for this certificate is not exportable."
msgstr "ملاحظة : لا يمكن تصدير المفتاح الخاص لهذه الشهادة."

#: devenum.rc:33
msgid "Default DirectSound"
msgstr "مخدم الصّوت الافتراضي"

#: devenum.rc:34
msgid "DirectSound: %s"
msgstr "مخدم الصوت: %s"

#: devenum.rc:35
msgid "Default WaveOut Device"
msgstr "الجهاز الافتراضي لإخراج الموجات"

#: devenum.rc:36
#: devenum.rc:34
msgid "Default MidiOut Device"
msgstr "الجهاز الافتراضي لإخراج النوطات"

Expand Down
10 changes: 1 addition & 9 deletions po/bg.po
Original file line number Diff line number Diff line change
Expand Up @@ -2924,18 +2924,10 @@ msgid "Note: The private key for this certificate is not exportable."
msgstr ""

#: devenum.rc:33
msgid "Default DirectSound"
msgstr ""

#: devenum.rc:34
msgid "DirectSound: %s"
msgstr ""

#: devenum.rc:35
msgid "Default WaveOut Device"
msgstr ""

#: devenum.rc:36
#: devenum.rc:34
msgid "Default MidiOut Device"
msgstr ""

Expand Down
10 changes: 1 addition & 9 deletions po/ca.po
Original file line number Diff line number Diff line change
Expand Up @@ -2959,18 +2959,10 @@ msgid "Note: The private key for this certificate is not exportable."
msgstr "Nota: La clau privada d'aquest certificat no és exportable."

#: devenum.rc:33
msgid "Default DirectSound"
msgstr "DirectSound per defecte"

#: devenum.rc:34
msgid "DirectSound: %s"
msgstr "DirectSound: %s"

#: devenum.rc:35
msgid "Default WaveOut Device"
msgstr "Dispositiu de WaveOut per defecte"

#: devenum.rc:36
#: devenum.rc:34
msgid "Default MidiOut Device"
msgstr "Dispositiu de MidiOut per defecte"

Expand Down
Loading

0 comments on commit 2f87691

Please sign in to comment.