2 * Copyright 2011-2012 Maarten Lankhorst
3 * Copyright 2010-2011 Maarten Lankhorst for CodeWeavers
4 * Copyright 2011 Andrew Eikum for CodeWeavers
5 * Copyright 2022 Huw Davies
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include <audiopolicy.h>
25 #include <mmdeviceapi.h>
28 #include <wine/debug.h>
29 #include <wine/unixlib.h>
34 WINE_DEFAULT_DEBUG_CHANNEL(mmdevapi
);
36 extern void sessions_lock(void) DECLSPEC_HIDDEN
;
37 extern void sessions_unlock(void) DECLSPEC_HIDDEN
;
39 void set_stream_volumes(struct audio_client
*This
)
41 struct set_volumes_params params
;
43 params
.stream
= This
->stream
;
44 params
.master_volume
= (This
->session
->mute
? 0.0f
: This
->session
->master_vol
);
45 params
.volumes
= This
->vols
;
46 params
.session_volumes
= This
->session
->channel_vols
;
48 WINE_UNIX_CALL(set_volumes
, ¶ms
);
51 static inline struct audio_client
*impl_from_IAudioCaptureClient(IAudioCaptureClient
*iface
)
53 return CONTAINING_RECORD(iface
, struct audio_client
, IAudioCaptureClient_iface
);
56 static inline struct audio_client
*impl_from_IAudioClock(IAudioClock
*iface
)
58 return CONTAINING_RECORD(iface
, struct audio_client
, IAudioClock_iface
);
61 static inline struct audio_client
*impl_from_IAudioClock2(IAudioClock2
*iface
)
63 return CONTAINING_RECORD(iface
, struct audio_client
, IAudioClock2_iface
);
66 static inline struct audio_client
*impl_from_IAudioStreamVolume(IAudioStreamVolume
*iface
)
68 return CONTAINING_RECORD(iface
, struct audio_client
, IAudioStreamVolume_iface
);
71 static HRESULT WINAPI
capture_QueryInterface(IAudioCaptureClient
*iface
, REFIID riid
, void **ppv
)
73 struct audio_client
*This
= impl_from_IAudioCaptureClient(iface
);
75 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
80 if (IsEqualIID(riid
, &IID_IUnknown
) ||
81 IsEqualIID(riid
, &IID_IAudioCaptureClient
))
83 else if (IsEqualIID(riid
, &IID_IMarshal
)) {
84 return IUnknown_QueryInterface(This
->marshal
, riid
, ppv
);
90 IUnknown_AddRef((IUnknown
*)*ppv
);
95 static ULONG WINAPI
capture_AddRef(IAudioCaptureClient
*iface
)
97 struct audio_client
*This
= impl_from_IAudioCaptureClient(iface
);
98 return IAudioClient3_AddRef(&This
->IAudioClient3_iface
);
101 static ULONG WINAPI
capture_Release(IAudioCaptureClient
*iface
)
103 struct audio_client
*This
= impl_from_IAudioCaptureClient(iface
);
104 return IAudioClient3_Release(&This
->IAudioClient3_iface
);
107 static HRESULT WINAPI
capture_GetBuffer(IAudioCaptureClient
*iface
, BYTE
**data
, UINT32
*frames
,
108 DWORD
*flags
, UINT64
*devpos
, UINT64
*qpcpos
)
110 struct audio_client
*This
= impl_from_IAudioCaptureClient(iface
);
111 struct get_capture_buffer_params params
;
113 TRACE("(%p)->(%p, %p, %p, %p, %p)\n", This
, data
, frames
, flags
, devpos
, qpcpos
);
120 if (!frames
|| !flags
)
124 return AUDCLNT_E_NOT_INITIALIZED
;
126 params
.stream
= This
->stream
;
128 params
.frames
= frames
;
129 params
.flags
= (UINT
*)flags
;
130 params
.devpos
= devpos
;
131 params
.qpcpos
= qpcpos
;
133 WINE_UNIX_CALL(get_capture_buffer
, ¶ms
);
135 return params
.result
;
138 static HRESULT WINAPI
capture_ReleaseBuffer(IAudioCaptureClient
*iface
, UINT32 done
)
140 struct audio_client
*This
= impl_from_IAudioCaptureClient(iface
);
141 struct release_capture_buffer_params params
;
143 TRACE("(%p)->(%u)\n", This
, done
);
146 return AUDCLNT_E_NOT_INITIALIZED
;
148 params
.stream
= This
->stream
;
151 WINE_UNIX_CALL(release_capture_buffer
, ¶ms
);
153 return params
.result
;
156 static HRESULT WINAPI
capture_GetNextPacketSize(IAudioCaptureClient
*iface
, UINT32
*frames
)
158 struct audio_client
*This
= impl_from_IAudioCaptureClient(iface
);
159 struct get_next_packet_size_params params
;
161 TRACE("(%p)->(%p)\n", This
, frames
);
167 return AUDCLNT_E_NOT_INITIALIZED
;
169 params
.stream
= This
->stream
;
170 params
.frames
= frames
;
172 WINE_UNIX_CALL(get_next_packet_size
, ¶ms
);
174 return params
.result
;
177 const IAudioCaptureClientVtbl AudioCaptureClient_Vtbl
=
179 capture_QueryInterface
,
183 capture_ReleaseBuffer
,
184 capture_GetNextPacketSize
187 static HRESULT WINAPI
clock_QueryInterface(IAudioClock
*iface
, REFIID riid
, void **ppv
)
189 struct audio_client
*This
= impl_from_IAudioClock(iface
);
191 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
196 if (IsEqualIID(riid
, &IID_IUnknown
) ||
197 IsEqualIID(riid
, &IID_IAudioClock
))
199 else if (IsEqualIID(riid
, &IID_IAudioClock2
))
200 *ppv
= &This
->IAudioClock2_iface
;
201 else if (IsEqualIID(riid
, &IID_IMarshal
)) {
202 return IUnknown_QueryInterface(This
->marshal
, riid
, ppv
);
205 return E_NOINTERFACE
;
208 IUnknown_AddRef((IUnknown
*)*ppv
);
213 static ULONG WINAPI
clock_AddRef(IAudioClock
*iface
)
215 struct audio_client
*This
= impl_from_IAudioClock(iface
);
216 return IAudioClient3_AddRef(&This
->IAudioClient3_iface
);
219 static ULONG WINAPI
clock_Release(IAudioClock
*iface
)
221 struct audio_client
*This
= impl_from_IAudioClock(iface
);
222 return IAudioClient3_Release(&This
->IAudioClient3_iface
);
225 static HRESULT WINAPI
clock_GetFrequency(IAudioClock
*iface
, UINT64
*freq
)
227 struct audio_client
*This
= impl_from_IAudioClock(iface
);
228 struct get_frequency_params params
;
230 TRACE("(%p)->(%p)\n", This
, freq
);
233 return AUDCLNT_E_NOT_INITIALIZED
;
235 params
.stream
= This
->stream
;
238 WINE_UNIX_CALL(get_frequency
, ¶ms
);
240 return params
.result
;
243 static HRESULT WINAPI
clock_GetPosition(IAudioClock
*iface
, UINT64
*pos
, UINT64
*qpctime
)
245 struct audio_client
*This
= impl_from_IAudioClock(iface
);
246 struct get_position_params params
;
248 TRACE("(%p)->(%p, %p)\n", This
, pos
, qpctime
);
254 return AUDCLNT_E_NOT_INITIALIZED
;
256 params
.stream
= This
->stream
;
257 params
.device
= FALSE
;
259 params
.qpctime
= qpctime
;
261 WINE_UNIX_CALL(get_position
, ¶ms
);
263 return params
.result
;
266 static HRESULT WINAPI
clock_GetCharacteristics(IAudioClock
*iface
, DWORD
*chars
)
268 struct audio_client
*This
= impl_from_IAudioClock(iface
);
270 TRACE("(%p)->(%p)\n", This
, chars
);
275 *chars
= AUDIOCLOCK_CHARACTERISTIC_FIXED_FREQ
;
280 const IAudioClockVtbl AudioClock_Vtbl
=
282 clock_QueryInterface
,
287 clock_GetCharacteristics
290 static HRESULT WINAPI
clock2_QueryInterface(IAudioClock2
*iface
, REFIID riid
, void **ppv
)
292 struct audio_client
*This
= impl_from_IAudioClock2(iface
);
293 return IAudioClock_QueryInterface(&This
->IAudioClock_iface
, riid
, ppv
);
296 static ULONG WINAPI
clock2_AddRef(IAudioClock2
*iface
)
298 struct audio_client
*This
= impl_from_IAudioClock2(iface
);
299 return IAudioClient3_AddRef(&This
->IAudioClient3_iface
);
302 static ULONG WINAPI
clock2_Release(IAudioClock2
*iface
)
304 struct audio_client
*This
= impl_from_IAudioClock2(iface
);
305 return IAudioClient3_Release(&This
->IAudioClient3_iface
);
308 static HRESULT WINAPI
clock2_GetDevicePosition(IAudioClock2
*iface
, UINT64
*pos
, UINT64
*qpctime
)
310 struct audio_client
*This
= impl_from_IAudioClock2(iface
);
311 struct get_position_params params
;
313 TRACE("(%p)->(%p, %p)\n", This
, pos
, qpctime
);
319 return AUDCLNT_E_NOT_INITIALIZED
;
321 params
.stream
= This
->stream
;
322 params
.device
= TRUE
;
324 params
.qpctime
= qpctime
;
326 WINE_UNIX_CALL(get_position
, ¶ms
);
328 return params
.result
;
331 const IAudioClock2Vtbl AudioClock2_Vtbl
=
333 clock2_QueryInterface
,
336 clock2_GetDevicePosition
339 static HRESULT WINAPI
streamvolume_QueryInterface(IAudioStreamVolume
*iface
, REFIID riid
,
342 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
347 if (IsEqualIID(riid
, &IID_IUnknown
) ||
348 IsEqualIID(riid
, &IID_IAudioStreamVolume
))
350 else if (IsEqualIID(riid
, &IID_IMarshal
)) {
351 struct audio_client
*This
= impl_from_IAudioStreamVolume(iface
);
352 return IUnknown_QueryInterface(This
->marshal
, riid
, ppv
);
355 return E_NOINTERFACE
;
358 IUnknown_AddRef((IUnknown
*)*ppv
);
363 static ULONG WINAPI
streamvolume_AddRef(IAudioStreamVolume
*iface
)
365 struct audio_client
*This
= impl_from_IAudioStreamVolume(iface
);
366 return IAudioClient3_AddRef(&This
->IAudioClient3_iface
);
369 static ULONG WINAPI
streamvolume_Release(IAudioStreamVolume
*iface
)
371 struct audio_client
*This
= impl_from_IAudioStreamVolume(iface
);
372 return IAudioClient3_Release(&This
->IAudioClient3_iface
);
375 static HRESULT WINAPI
streamvolume_GetChannelCount(IAudioStreamVolume
*iface
, UINT32
*out
)
377 struct audio_client
*This
= impl_from_IAudioStreamVolume(iface
);
379 TRACE("(%p)->(%p)\n", This
, out
);
384 *out
= This
->channel_count
;
389 static HRESULT WINAPI
streamvolume_SetChannelVolume(IAudioStreamVolume
*iface
, UINT32 index
,
392 struct audio_client
*This
= impl_from_IAudioStreamVolume(iface
);
394 TRACE("(%p)->(%d, %f)\n", This
, index
, level
);
396 if (level
< 0.f
|| level
> 1.f
)
400 return AUDCLNT_E_NOT_INITIALIZED
;
402 if (index
>= This
->channel_count
)
407 This
->vols
[index
] = level
;
408 set_stream_volumes(This
);
415 static HRESULT WINAPI
streamvolume_GetChannelVolume(IAudioStreamVolume
*iface
, UINT32 index
,
418 struct audio_client
*This
= impl_from_IAudioStreamVolume(iface
);
420 TRACE("(%p)->(%d, %p)\n", This
, index
, level
);
426 return AUDCLNT_E_NOT_INITIALIZED
;
428 if (index
>= This
->channel_count
)
431 *level
= This
->vols
[index
];
436 static HRESULT WINAPI
streamvolume_SetAllVolumes(IAudioStreamVolume
*iface
, UINT32 count
,
439 struct audio_client
*This
= impl_from_IAudioStreamVolume(iface
);
442 TRACE("(%p)->(%d, %p)\n", This
, count
, levels
);
448 return AUDCLNT_E_NOT_INITIALIZED
;
450 if (count
!= This
->channel_count
)
455 for (i
= 0; i
< count
; ++i
)
456 This
->vols
[i
] = levels
[i
];
457 set_stream_volumes(This
);
464 static HRESULT WINAPI
streamvolume_GetAllVolumes(IAudioStreamVolume
*iface
, UINT32 count
,
467 struct audio_client
*This
= impl_from_IAudioStreamVolume(iface
);
470 TRACE("(%p)->(%d, %p)\n", This
, count
, levels
);
476 return AUDCLNT_E_NOT_INITIALIZED
;
478 if (count
!= This
->channel_count
)
483 for (i
= 0; i
< count
; ++i
)
484 levels
[i
] = This
->vols
[i
];
491 const IAudioStreamVolumeVtbl AudioStreamVolume_Vtbl
=
493 streamvolume_QueryInterface
,
495 streamvolume_Release
,
496 streamvolume_GetChannelCount
,
497 streamvolume_SetChannelVolume
,
498 streamvolume_GetChannelVolume
,
499 streamvolume_SetAllVolumes
,
500 streamvolume_GetAllVolumes