[PATCH 1/2] mf: Add volume control stubs for SAR.

Nikolay Sivov nsivov at codeweavers.com
Thu Apr 9 07:36:20 CDT 2020


Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
 dlls/mf/sar.c      | 221 +++++++++++++++++++++++++++++++++++++++++++++
 dlls/mf/tests/mf.c |   9 ++
 include/mfidl.idl  |  36 ++++++++
 3 files changed, 266 insertions(+)

diff --git a/dlls/mf/sar.c b/dlls/mf/sar.c
index 4ebd64facf..04b1d7a684 100644
--- a/dlls/mf/sar.c
+++ b/dlls/mf/sar.c
@@ -48,6 +48,9 @@ struct audio_renderer
     IMFMediaSinkPreroll IMFMediaSinkPreroll_iface;
     IMFClockStateSink IMFClockStateSink_iface;
     IMFMediaEventGenerator IMFMediaEventGenerator_iface;
+    IMFGetService IMFGetService_iface;
+    IMFSimpleAudioVolume IMFSimpleAudioVolume_iface;
+    IMFAudioStreamVolume IMFAudioStreamVolume_iface;
     LONG refcount;
     IMFMediaEventQueue *event_queue;
     IMFPresentationClock *clock;
@@ -76,6 +79,21 @@ static struct audio_renderer *impl_from_IMFMediaEventGenerator(IMFMediaEventGene
     return CONTAINING_RECORD(iface, struct audio_renderer, IMFMediaEventGenerator_iface);
 }
 
+static struct audio_renderer *impl_from_IMFGetService(IMFGetService *iface)
+{
+    return CONTAINING_RECORD(iface, struct audio_renderer, IMFGetService_iface);
+}
+
+static struct audio_renderer *impl_from_IMFSimpleAudioVolume(IMFSimpleAudioVolume *iface)
+{
+    return CONTAINING_RECORD(iface, struct audio_renderer, IMFSimpleAudioVolume_iface);
+}
+
+static struct audio_renderer *impl_from_IMFAudioStreamVolume(IMFAudioStreamVolume *iface)
+{
+    return CONTAINING_RECORD(iface, struct audio_renderer, IMFAudioStreamVolume_iface);
+}
+
 static struct audio_renderer_stream *impl_from_IMFStreamSink(IMFStreamSink *iface)
 {
     return CONTAINING_RECORD(iface, struct audio_renderer_stream, IMFStreamSink_iface);
@@ -109,6 +127,10 @@ static HRESULT WINAPI audio_renderer_sink_QueryInterface(IMFMediaSink *iface, RE
     {
         *obj = &renderer->IMFMediaEventGenerator_iface;
     }
+    else if (IsEqualIID(riid, &IID_IMFGetService))
+    {
+        *obj = &renderer->IMFGetService_iface;
+    }
     else
     {
         WARN("Unsupported %s.\n", debugstr_guid(riid));
@@ -521,6 +543,202 @@ static const IMFClockStateSinkVtbl audio_renderer_clock_sink_vtbl =
     audio_renderer_clock_sink_OnClockSetRate,
 };
 
+static HRESULT WINAPI audio_renderer_get_service_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
+{
+    struct audio_renderer *renderer = impl_from_IMFGetService(iface);
+    return IMFMediaSink_QueryInterface(&renderer->IMFMediaSink_iface, riid, obj);
+}
+
+static ULONG WINAPI audio_renderer_get_service_AddRef(IMFGetService *iface)
+{
+    struct audio_renderer *renderer = impl_from_IMFGetService(iface);
+    return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
+}
+
+static ULONG WINAPI audio_renderer_get_service_Release(IMFGetService *iface)
+{
+    struct audio_renderer *renderer = impl_from_IMFGetService(iface);
+    return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
+}
+
+static HRESULT WINAPI audio_renderer_get_service_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
+{
+    struct audio_renderer *renderer = impl_from_IMFGetService(iface);
+
+    TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
+
+    *obj = NULL;
+
+    if (IsEqualGUID(service, &MR_POLICY_VOLUME_SERVICE) && IsEqualIID(riid, &IID_IMFSimpleAudioVolume))
+    {
+        *obj = &renderer->IMFSimpleAudioVolume_iface;
+    }
+    else if (IsEqualGUID(service, &MR_STREAM_VOLUME_SERVICE) && IsEqualIID(riid, &IID_IMFAudioStreamVolume))
+    {
+        *obj = &renderer->IMFAudioStreamVolume_iface;
+    }
+    else
+        FIXME("Unsupported service %s, interface %s.\n", debugstr_guid(service), debugstr_guid(riid));
+
+    if (*obj)
+        IUnknown_AddRef((IUnknown *)*obj);
+
+    return *obj ? S_OK : E_NOINTERFACE;
+}
+
+static const IMFGetServiceVtbl audio_renderer_get_service_vtbl =
+{
+    audio_renderer_get_service_QueryInterface,
+    audio_renderer_get_service_AddRef,
+    audio_renderer_get_service_Release,
+    audio_renderer_get_service_GetService,
+};
+
+static HRESULT WINAPI audio_renderer_simple_volume_QueryInterface(IMFSimpleAudioVolume *iface, REFIID riid, void **obj)
+{
+    TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
+
+    if (IsEqualIID(riid, &IID_IMFSimpleAudioVolume) ||
+            IsEqualIID(riid, &IID_IUnknown))
+    {
+        *obj = iface;
+        IMFSimpleAudioVolume_AddRef(iface);
+        return S_OK;
+    }
+
+    WARN("Unsupported interface %s.\n", debugstr_guid(riid));
+    *obj = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI audio_renderer_simple_volume_AddRef(IMFSimpleAudioVolume *iface)
+{
+    struct audio_renderer *renderer = impl_from_IMFSimpleAudioVolume(iface);
+    return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
+}
+
+static ULONG WINAPI audio_renderer_simple_volume_Release(IMFSimpleAudioVolume *iface)
+{
+    struct audio_renderer *renderer = impl_from_IMFSimpleAudioVolume(iface);
+    return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
+}
+
+static HRESULT WINAPI audio_renderer_simple_volume_SetMasterVolume(IMFSimpleAudioVolume *iface, float level)
+{
+    FIXME("%p, %f.\n", iface, level);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI audio_renderer_simple_volume_GetMasterVolume(IMFSimpleAudioVolume *iface, float *level)
+{
+    FIXME("%p, %p.\n", iface, level);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI audio_renderer_simple_volume_SetMute(IMFSimpleAudioVolume *iface, BOOL mute)
+{
+    FIXME("%p, %d.\n", iface, mute);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI audio_renderer_simple_volume_GetMute(IMFSimpleAudioVolume *iface, BOOL *mute)
+{
+    FIXME("%p, %p.\n", iface, mute);
+
+    return E_NOTIMPL;
+}
+
+static const IMFSimpleAudioVolumeVtbl audio_renderer_simple_volume_vtbl =
+{
+    audio_renderer_simple_volume_QueryInterface,
+    audio_renderer_simple_volume_AddRef,
+    audio_renderer_simple_volume_Release,
+    audio_renderer_simple_volume_SetMasterVolume,
+    audio_renderer_simple_volume_GetMasterVolume,
+    audio_renderer_simple_volume_SetMute,
+    audio_renderer_simple_volume_GetMute,
+};
+
+static HRESULT WINAPI audio_renderer_stream_volume_QueryInterface(IMFAudioStreamVolume *iface, REFIID riid, void **obj)
+{
+    TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
+
+    if (IsEqualIID(riid, &IID_IMFAudioStreamVolume) ||
+            IsEqualIID(riid, &IID_IUnknown))
+    {
+        *obj = iface;
+        IMFAudioStreamVolume_AddRef(iface);
+        return S_OK;
+    }
+
+    WARN("Unsupported interface %s.\n", debugstr_guid(riid));
+    *obj = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI audio_renderer_stream_volume_AddRef(IMFAudioStreamVolume *iface)
+{
+    struct audio_renderer *renderer = impl_from_IMFAudioStreamVolume(iface);
+    return IMFMediaSink_AddRef(&renderer->IMFMediaSink_iface);
+}
+
+static ULONG WINAPI audio_renderer_stream_volume_Release(IMFAudioStreamVolume *iface)
+{
+    struct audio_renderer *renderer = impl_from_IMFAudioStreamVolume(iface);
+    return IMFMediaSink_Release(&renderer->IMFMediaSink_iface);
+}
+
+static HRESULT WINAPI audio_renderer_stream_volume_GetChannelCount(IMFAudioStreamVolume *iface, UINT32 *count)
+{
+    FIXME("%p, %p.\n", iface, count);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI audio_renderer_stream_volume_SetChannelVolume(IMFAudioStreamVolume *iface, UINT32 index, float level)
+{
+    FIXME("%p, %u, %f.\n", iface, index, level);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI audio_renderer_stream_volume_GetChannelVolume(IMFAudioStreamVolume *iface, UINT32 index, float *level)
+{
+    FIXME("%p, %u, %p.\n", iface, index, level);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI audio_renderer_stream_volume_SetAllVolumes(IMFAudioStreamVolume *iface, UINT32 count,
+        const float *volumes)
+{
+    FIXME("%p, %u, %p.\n", iface, count, volumes);
+
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI audio_renderer_stream_volume_GetAllVolumes(IMFAudioStreamVolume *iface, UINT32 count, float *volumes)
+{
+    FIXME("%p, %u, %p.\n", iface, count, volumes);
+
+    return E_NOTIMPL;
+}
+
+static const IMFAudioStreamVolumeVtbl audio_renderer_stream_volume_vtbl =
+{
+    audio_renderer_stream_volume_QueryInterface,
+    audio_renderer_stream_volume_AddRef,
+    audio_renderer_stream_volume_Release,
+    audio_renderer_stream_volume_GetChannelCount,
+    audio_renderer_stream_volume_SetChannelVolume,
+    audio_renderer_stream_volume_GetChannelVolume,
+    audio_renderer_stream_volume_SetAllVolumes,
+    audio_renderer_stream_volume_GetAllVolumes,
+};
+
 static HRESULT sar_create_mmdevice(IMFAttributes *attributes, IMMDevice **device)
 {
     WCHAR *endpoint;
@@ -894,6 +1112,9 @@ static HRESULT sar_create_object(IMFAttributes *attributes, void *user_context,
     renderer->IMFMediaSinkPreroll_iface.lpVtbl = &audio_renderer_preroll_vtbl;
     renderer->IMFClockStateSink_iface.lpVtbl = &audio_renderer_clock_sink_vtbl;
     renderer->IMFMediaEventGenerator_iface.lpVtbl = &audio_renderer_events_vtbl;
+    renderer->IMFGetService_iface.lpVtbl = &audio_renderer_get_service_vtbl;
+    renderer->IMFSimpleAudioVolume_iface.lpVtbl = &audio_renderer_simple_volume_vtbl;
+    renderer->IMFAudioStreamVolume_iface.lpVtbl = &audio_renderer_stream_volume_vtbl;
     renderer->refcount = 1;
     InitializeCriticalSection(&renderer->cs);
 
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index 72c70fcafe..fbcbb6272b 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -2811,6 +2811,15 @@ if (SUCCEEDED(hr))
 }
     IMFStreamSink_Release(stream_sink);
 
+    /* Volume control */
+    hr = MFGetService((IUnknown *)sink, &MR_POLICY_VOLUME_SERVICE, &IID_IMFSimpleAudioVolume, (void **)&unk);
+    ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
+    IUnknown_Release(unk);
+
+    hr = MFGetService((IUnknown *)sink, &MR_STREAM_VOLUME_SERVICE, &IID_IMFAudioStreamVolume, (void **)&unk);
+    ok(hr == S_OK, "Failed to get interface, hr %#x.\n", hr);
+    IUnknown_Release(unk);
+
     /* Shutdown */
     hr = IMFMediaSink_Shutdown(sink);
     ok(hr == S_OK, "Failed to shut down, hr %#x.\n", hr);
diff --git a/include/mfidl.idl b/include/mfidl.idl
index 5a7398f290..13286296bc 100644
--- a/include/mfidl.idl
+++ b/include/mfidl.idl
@@ -956,6 +956,39 @@ enum
     MF_RESOLUTION_WRITE                                                 = 0x00020000,
 };
 
+[
+    object,
+    uuid(089edf13-cf71-4338-8d13-9e569dbdc319),
+]
+interface IMFSimpleAudioVolume : IUnknown
+{
+    HRESULT SetMasterVolume([in] float level);
+    HRESULT GetMasterVolume([out] float *level);
+    HRESULT SetMute([in] BOOL mute);
+    HRESULT GetMute([out] BOOL *mute);
+}
+
+[
+    object,
+    uuid(76b1bbdb-4ec8-4f36-b106-70a9316df593),
+]
+interface IMFAudioStreamVolume : IUnknown
+{
+    HRESULT GetChannelCount([out] UINT32 *count);
+    HRESULT SetChannelVolume(
+        [in] UINT32 index,
+        [in] const float level);
+    HRESULT GetChannelVolume(
+        [in] UINT32 index,
+        [out] float *level);
+    HRESULT SetAllVolumes(
+        [in] UINT32 count,
+        [in, size_is(count)] const float *volumes);
+    HRESULT GetAllVolumes(
+        [in] UINT32 count,
+        [out, size_is(count)] float *volumes);
+}
+
 cpp_quote("#ifdef __cplusplus")
 cpp_quote("static inline HRESULT MFSetAttributeSize(IMFAttributes *attributes, REFGUID key, UINT32 width, UINT32 height)")
 cpp_quote("{")
@@ -1056,6 +1089,9 @@ cpp_quote("EXTERN_GUID(MF_TOPOLOGY_STATIC_PLAYBACK_OPTIMIZATIONS, 0xb86cac42, 0x
 cpp_quote("EXTERN_GUID(MF_RATE_CONTROL_SERVICE, 0x866fa297, 0xb802, 0x4bf8, 0x9d, 0xc9, 0x5e, 0x3b, 0x6a, 0x9f, 0x53, 0xc9);")
 cpp_quote("EXTERN_GUID(MF_LOCAL_MFT_REGISTRATION_SERVICE, 0xddf5cf9c, 0x4506, 0x45aa, 0xab, 0xf0, 0x6d, 0x5d, 0x94, 0xdd, 0x1b, 0x4a);")
 cpp_quote("EXTERN_C const GUID MF_SCRUBBING_SERVICE;")
+cpp_quote("EXTERN_GUID(MR_POLICY_VOLUME_SERVICE, 0x1abaa2ac, 0x9d3b, 0x47c6, 0xab, 0x48, 0xc5, 0x95, 0x06, 0xde, 0x78, 0x4d);")
+cpp_quote("EXTERN_GUID(MR_CAPTURE_POLICY_VOLUME_SERVICE, 0x24030acd, 0x107a, 0x4265, 0x97, 0x5c, 0x41, 0x4e, 0x33, 0xe6, 0x5f, 0x2a);")
+cpp_quote("EXTERN_GUID(MR_STREAM_VOLUME_SERVICE, 0xf8b5fa2f, 0x32ef, 0x46f5, 0xb1, 0x72, 0x13, 0x21, 0x21, 0x2f, 0xb2, 0xc4);")
 
 cpp_quote("EXTERN_GUID(MF_SAMPLEGRABBERSINK_SAMPLE_TIME_OFFSET, 0x62e3d776, 0x8100, 0x4e03, 0xa6, 0xe8, 0xbd, 0x38, 0x57, 0xac, 0x9c, 0x47);")
 cpp_quote("EXTERN_GUID(MF_SAMPLEGRABBERSINK_IGNORE_CLOCK, 0x0efda2c0, 0x2b69, 0x4e2e, 0xab, 0x8d, 0x46, 0xdc, 0xbf, 0xf7, 0xd2, 0x5d);")
-- 
2.25.1




More information about the wine-devel mailing list