2 * Copyright 2021 Andrew Eikum for CodeWeavers
3 * Copyright 2021 RĂ©mi Bernon for CodeWeavers
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include "winstring.h"
27 #include "wine/debug.h"
28 #include "wine/heap.h"
31 #include "activation.h"
32 #include "mmdeviceapi.h"
34 #define WIDL_using_Windows_Foundation
35 #define WIDL_using_Windows_Foundation_Collections
36 #include "windows.foundation.h"
37 #define WIDL_using_Windows_Media_Devices
38 #include "windows.media.devices.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(mmdevapi
);
42 static const char *debugstr_hstring(HSTRING hstr
)
46 if (hstr
&& !((ULONG_PTR
)hstr
>> 16)) return "(invalid)";
47 str
= WindowsGetStringRawBuffer(hstr
, &len
);
48 return wine_dbgstr_wn(str
, len
);
51 static ERole
AudioDeviceRole_to_ERole(AudioDeviceRole role
)
54 case AudioDeviceRole_Communications
:
55 return eCommunications
;
61 struct windows_media_devices
63 IActivationFactory IActivationFactory_iface
;
64 IMediaDeviceStatics IMediaDeviceStatics_iface
;
68 static inline struct windows_media_devices
*impl_from_IActivationFactory(IActivationFactory
*iface
)
70 return CONTAINING_RECORD(iface
, struct windows_media_devices
, IActivationFactory_iface
);
73 static inline struct windows_media_devices
*impl_from_IMediaDeviceStatics(IMediaDeviceStatics
*iface
)
75 return CONTAINING_RECORD(iface
, struct windows_media_devices
, IMediaDeviceStatics_iface
);
78 static HRESULT STDMETHODCALLTYPE
windows_media_devices_QueryInterface(
79 IActivationFactory
*iface
, REFIID iid
, void **out
)
81 struct windows_media_devices
*impl
= impl_from_IActivationFactory(iface
);
83 TRACE("iface %p, iid %s, out %p\n", iface
, debugstr_guid(iid
), out
);
85 if (IsEqualGUID(iid
, &IID_IUnknown
) ||
86 IsEqualGUID(iid
, &IID_IInspectable
) ||
87 IsEqualGUID(iid
, &IID_IAgileObject
) ||
88 IsEqualGUID(iid
, &IID_IActivationFactory
))
90 IUnknown_AddRef(iface
);
95 if (IsEqualGUID(iid
, &IID_IMediaDeviceStatics
))
97 IUnknown_AddRef(iface
);
98 *out
= &impl
->IMediaDeviceStatics_iface
;
102 FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
104 return E_NOINTERFACE
;
107 static ULONG STDMETHODCALLTYPE
windows_media_devices_AddRef(
108 IActivationFactory
*iface
)
110 struct windows_media_devices
*impl
= impl_from_IActivationFactory(iface
);
111 ULONG ref
= InterlockedIncrement(&impl
->ref
);
112 TRACE("iface %p, ref %u.\n", iface
, ref
);
116 static ULONG STDMETHODCALLTYPE
windows_media_devices_Release(
117 IActivationFactory
*iface
)
119 struct windows_media_devices
*impl
= impl_from_IActivationFactory(iface
);
120 ULONG ref
= InterlockedDecrement(&impl
->ref
);
121 TRACE("iface %p, ref %u.\n", iface
, ref
);
125 static HRESULT STDMETHODCALLTYPE
windows_media_devices_GetIids(
126 IActivationFactory
*iface
, ULONG
*iid_count
, IID
**iids
)
128 FIXME("iface %p, iid_count %p, iids %p stub!\n", iface
, iid_count
, iids
);
132 static HRESULT STDMETHODCALLTYPE
windows_media_devices_GetRuntimeClassName(
133 IActivationFactory
*iface
, HSTRING
*class_name
)
135 FIXME("iface %p, class_name %p stub!\n", iface
, class_name
);
139 static HRESULT STDMETHODCALLTYPE
windows_media_devices_GetTrustLevel(
140 IActivationFactory
*iface
, TrustLevel
*trust_level
)
142 FIXME("iface %p, trust_level %p stub!\n", iface
, trust_level
);
146 static HRESULT STDMETHODCALLTYPE
windows_media_devices_ActivateInstance(
147 IActivationFactory
*iface
, IInspectable
**instance
)
149 FIXME("iface %p, instance %p stub!\n", iface
, instance
);
153 static const struct IActivationFactoryVtbl activation_factory_vtbl
=
155 windows_media_devices_QueryInterface
,
156 windows_media_devices_AddRef
,
157 windows_media_devices_Release
,
158 /* IInspectable methods */
159 windows_media_devices_GetIids
,
160 windows_media_devices_GetRuntimeClassName
,
161 windows_media_devices_GetTrustLevel
,
162 /* IActivationFactory methods */
163 windows_media_devices_ActivateInstance
,
166 static HRESULT
get_default_device_id(EDataFlow direction
, AudioDeviceRole role
, HSTRING
*device_id_hstr
)
171 IMMDeviceEnumerator
*devenum
;
172 ERole mmdev_role
= AudioDeviceRole_to_ERole(role
);
174 static const WCHAR id_fmt_pre
[] = L
"\\\\?\\SWD#MMDEVAPI#";
175 static const WCHAR id_fmt_hash
[] = L
"#";
176 static const size_t GUID_STR_LEN
= 38; /* == strlen("{00000000-0000-0000-0000-000000000000}") */
178 *device_id_hstr
= NULL
;
180 hr
= CoCreateInstance(&CLSID_MMDeviceEnumerator
, NULL
,
181 CLSCTX_INPROC_SERVER
, &IID_IMMDeviceEnumerator
, (void**)&devenum
);
184 WARN("Failed to create MMDeviceEnumerator: %08x\n", hr
);
188 hr
= IMMDeviceEnumerator_GetDefaultAudioEndpoint(devenum
, direction
, mmdev_role
, &dev
);
191 WARN("GetDefaultAudioEndpoint failed: %08x\n", hr
);
192 IMMDeviceEnumerator_Release(devenum
);
196 hr
= IMMDevice_GetId(dev
, &devid
);
199 WARN("GetId failed: %08x\n", hr
);
200 IMMDevice_Release(dev
);
201 IMMDeviceEnumerator_Release(devenum
);
205 s
= heap_alloc((sizeof(id_fmt_pre
) - sizeof(WCHAR
)) +
206 (sizeof(id_fmt_hash
) - sizeof(WCHAR
)) +
207 (wcslen(devid
) + GUID_STR_LEN
+ 1 /* nul */) * sizeof(WCHAR
));
209 wcscpy(s
, id_fmt_pre
);
211 wcscat(s
, id_fmt_hash
);
213 if(direction
== eRender
)
214 StringFromGUID2(&DEVINTERFACE_AUDIO_RENDER
, s
+ wcslen(s
), GUID_STR_LEN
+ 1);
216 StringFromGUID2(&DEVINTERFACE_AUDIO_CAPTURE
, s
+ wcslen(s
), GUID_STR_LEN
+ 1);
218 hr
= WindowsCreateString(s
, wcslen(s
), device_id_hstr
);
220 WARN("WindowsCreateString failed: %08x\n", hr
);
224 CoTaskMemFree(devid
);
225 IMMDevice_Release(dev
);
226 IMMDeviceEnumerator_Release(devenum
);
231 static HRESULT WINAPI
media_device_statics_QueryInterface(IMediaDeviceStatics
*iface
,
232 REFIID riid
, void **ppvObject
)
234 struct windows_media_devices
*This
= impl_from_IMediaDeviceStatics(iface
);
235 return windows_media_devices_QueryInterface(&This
->IActivationFactory_iface
, riid
, ppvObject
);
238 static ULONG WINAPI
media_device_statics_AddRef(IMediaDeviceStatics
*iface
)
240 struct windows_media_devices
*This
= impl_from_IMediaDeviceStatics(iface
);
241 return windows_media_devices_AddRef(&This
->IActivationFactory_iface
);
244 static ULONG WINAPI
media_device_statics_Release(IMediaDeviceStatics
*iface
)
246 struct windows_media_devices
*This
= impl_from_IMediaDeviceStatics(iface
);
247 return windows_media_devices_Release(&This
->IActivationFactory_iface
);
250 static HRESULT WINAPI
media_device_statics_GetIids(IMediaDeviceStatics
*iface
,
251 ULONG
*iidCount
, IID
**iids
)
253 struct windows_media_devices
*This
= impl_from_IMediaDeviceStatics(iface
);
254 return windows_media_devices_GetIids(&This
->IActivationFactory_iface
, iidCount
, iids
);
257 static HRESULT WINAPI
media_device_statics_GetRuntimeClassName(IMediaDeviceStatics
*iface
,
260 struct windows_media_devices
*This
= impl_from_IMediaDeviceStatics(iface
);
261 return windows_media_devices_GetRuntimeClassName(&This
->IActivationFactory_iface
, className
);
264 static HRESULT WINAPI
media_device_statics_GetTrustLevel(IMediaDeviceStatics
*iface
,
265 TrustLevel
*trustLevel
)
267 struct windows_media_devices
*This
= impl_from_IMediaDeviceStatics(iface
);
268 return windows_media_devices_GetTrustLevel(&This
->IActivationFactory_iface
, trustLevel
);
271 static HRESULT WINAPI
media_device_statics_GetAudioCaptureSelector(IMediaDeviceStatics
*iface
,
274 FIXME("iface %p, value %p stub!\n", iface
, value
);
278 static HRESULT WINAPI
media_device_statics_GetAudioRenderSelector(IMediaDeviceStatics
*iface
,
281 FIXME("iface %p, value %p stub!\n", iface
, value
);
285 static HRESULT WINAPI
media_device_statics_GetVideoCaptureSelector(IMediaDeviceStatics
*iface
,
288 FIXME("iface %p, value %p stub!\n", iface
, value
);
292 static HRESULT WINAPI
media_device_statics_GetDefaultAudioCaptureId(IMediaDeviceStatics
*iface
,
293 AudioDeviceRole role
, HSTRING
*value
)
295 TRACE("iface %p, role 0x%x, value %p\n", iface
, role
, value
);
296 return get_default_device_id(eCapture
, role
, value
);
299 static HRESULT WINAPI
media_device_statics_GetDefaultAudioRenderId(IMediaDeviceStatics
*iface
,
300 AudioDeviceRole role
, HSTRING
*value
)
302 TRACE("iface %p, role 0x%x, value %p\n", iface
, role
, value
);
303 return get_default_device_id(eRender
, role
, value
);
306 static HRESULT WINAPI
media_device_statics_add_DefaultAudioCaptureDeviceChanged(
307 IMediaDeviceStatics
*iface
,
308 ITypedEventHandler_IInspectable_DefaultAudioCaptureDeviceChangedEventArgs
*handler
,
309 EventRegistrationToken
*token
)
311 FIXME("iface %p, handler %p token %p stub!\n", iface
, handler
, token
);
318 static HRESULT WINAPI
media_device_statics_remove_DefaultAudioCaptureDeviceChanged(
319 IMediaDeviceStatics
*iface
,
320 EventRegistrationToken token
)
322 FIXME("iface %p, token %#I64x stub!\n", iface
, token
.value
);
326 static HRESULT WINAPI
media_device_statics_add_DefaultAudioRenderDeviceChanged(
327 IMediaDeviceStatics
*iface
,
328 ITypedEventHandler_IInspectable_DefaultAudioRenderDeviceChangedEventArgs
*handler
,
329 EventRegistrationToken
*token
)
331 FIXME("iface %p, handler %p token %p stub!\n", iface
, handler
, token
);
338 static HRESULT WINAPI
media_device_statics_remove_DefaultAudioRenderDeviceChanged(
339 IMediaDeviceStatics
*iface
,
340 EventRegistrationToken token
)
342 FIXME("iface %p, token %#I64x stub!\n", iface
, token
.value
);
346 static IMediaDeviceStaticsVtbl media_device_statics_vtbl
= {
347 media_device_statics_QueryInterface
,
348 media_device_statics_AddRef
,
349 media_device_statics_Release
,
350 media_device_statics_GetIids
,
351 media_device_statics_GetRuntimeClassName
,
352 media_device_statics_GetTrustLevel
,
353 media_device_statics_GetAudioCaptureSelector
,
354 media_device_statics_GetAudioRenderSelector
,
355 media_device_statics_GetVideoCaptureSelector
,
356 media_device_statics_GetDefaultAudioCaptureId
,
357 media_device_statics_GetDefaultAudioRenderId
,
358 media_device_statics_add_DefaultAudioCaptureDeviceChanged
,
359 media_device_statics_remove_DefaultAudioCaptureDeviceChanged
,
360 media_device_statics_add_DefaultAudioRenderDeviceChanged
,
361 media_device_statics_remove_DefaultAudioRenderDeviceChanged
,
364 static struct windows_media_devices windows_media_devices
=
366 {&activation_factory_vtbl
},
367 {&media_device_statics_vtbl
},
371 HRESULT WINAPI
DllGetClassObject(REFCLSID clsid
, REFIID riid
, void **out
)
373 FIXME("clsid %s, riid %s, out %p stub!\n", debugstr_guid(clsid
), debugstr_guid(riid
), out
);
374 return CLASS_E_CLASSNOTAVAILABLE
;
377 HRESULT WINAPI
DllGetActivationFactory(HSTRING classid
, IActivationFactory
**factory
)
379 TRACE("classid %s, factory %p.\n", debugstr_hstring(classid
), factory
);
380 *factory
= &windows_media_devices
.IActivationFactory_iface
;
381 IUnknown_AddRef(*factory
);