diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c index 2ef767b7871..5d74238a916 100644 --- a/dlls/mf/sar.c +++ b/dlls/mf/sar.c @@ -22,6 +22,8 @@ #include "mfidl.h" #include "mferror.h" #include "mf_private.h" +#include "initguid.h" +#include "mmdeviceapi.h" #include "wine/debug.h" #include "wine/heap.h" @@ -447,9 +449,55 @@ static const IMFClockStateSinkVtbl audio_renderer_clock_sink_vtbl = audio_renderer_clock_sink_OnClockSetRate, }; +static HRESULT sar_create_mmdevice(IMFAttributes *attributes, IMMDevice **device) +{ + WCHAR *endpoint; + unsigned int length, role = eMultimedia; + IMMDeviceEnumerator *devenum; + HRESULT hr; + + if (attributes) + { + /* Mutually exclusive attributes. */ + if (SUCCEEDED(IMFAttributes_GetItem(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE, NULL)) && + SUCCEEDED(IMFAttributes_GetItem(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID, NULL))) + { + return E_INVALIDARG; + } + } + + if (FAILED(hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_INPROC_SERVER, &IID_IMMDeviceEnumerator, + (void **)&devenum))) + { + return hr; + } + + role = eMultimedia; + if (attributes && SUCCEEDED(IMFAttributes_GetUINT32(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE, &role))) + TRACE("Specified role %d.\n", role); + + if (attributes && SUCCEEDED(IMFAttributes_GetAllocatedString(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID, + &endpoint, &length))) + { + TRACE("Specified end point %s.\n", debugstr_w(endpoint)); + hr = IMMDeviceEnumerator_GetDevice(devenum, endpoint, device); + CoTaskMemFree(endpoint); + } + else + hr = IMMDeviceEnumerator_GetDefaultAudioEndpoint(devenum, eRender, role, device); + + if (FAILED(hr)) + hr = MF_E_NO_AUDIO_PLAYBACK_DEVICE; + + IMMDeviceEnumerator_Release(devenum); + + return hr; +} + static HRESULT sar_create_object(IMFAttributes *attributes, void *user_context, IUnknown **obj) { struct audio_renderer *renderer; + IMMDevice *device; HRESULT hr; TRACE("%p, %p, %p.\n", attributes, user_context, obj); @@ -467,6 +515,11 @@ static HRESULT sar_create_object(IMFAttributes *attributes, void *user_context, if (FAILED(hr = MFCreateEventQueue(&renderer->event_queue))) goto failed; + if (FAILED(hr = sar_create_mmdevice(attributes, &device))) + goto failed; + + IMMDevice_Release(device); + *obj = (IUnknown *)&renderer->IMFMediaSink_iface; return S_OK; diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 98e180e453c..4f293621028 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -38,6 +38,7 @@ DEFINE_GUID(MFVideoFormat_ABGR32, 0x00000020, 0x0000, 0x0010, 0x80, 0x00, 0x00, #include "mfapi.h" #include "mferror.h" #include "mfidl.h" +#include "mmdeviceapi.h" #include "wine/test.h" @@ -2636,6 +2637,7 @@ static void test_sar(void) IMFClockStateSink *state_sink; IMFMediaSink *sink, *sink2; IMFStreamSink *stream_sink; + IMFAttributes *attributes; IMFActivate *activate; MFCLOCK_STATE state; DWORD flags, count; @@ -2823,6 +2825,31 @@ todo_wine hr = MFShutdown(); ok(hr == S_OK, "Shutdown failure, hr %#x.\n", hr); + /* SAR attributes */ + hr = MFCreateAttributes(&attributes, 0); + ok(hr == S_OK, "Failed to create attributes, hr %#x.\n", hr); + + /* Specify role. */ + hr = IMFAttributes_SetUINT32(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE, eMultimedia); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + hr = MFCreateAudioRenderer(attributes, &sink); + ok(hr == S_OK, "Failed to create a sink, hr %#x.\n", hr); + IMFMediaSink_Release(sink); + + /* Invalid endpoint. */ + hr = IMFAttributes_SetString(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID, L"endpoint"); + ok(hr == S_OK, "Failed to set attribute, hr %#x.\n", hr); + + hr = MFCreateAudioRenderer(attributes, &sink); + ok(hr == E_INVALIDARG, "Unexpected hr %#x.\n", hr); + + hr = IMFAttributes_DeleteItem(attributes, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE); + ok(hr == S_OK, "Failed to remove attribute, hr %#x.\n", hr); + + hr = MFCreateAudioRenderer(attributes, &sink); + ok(hr == MF_E_NO_AUDIO_PLAYBACK_DEVICE, "Failed to create a sink, hr %#x.\n", hr); + CoUninitialize(); }