winepulse: Move AudioCaptureClient into mmdevapi.
[wine.git] / dlls / mmdevapi / client.c
blob8c75c7d80a2556fd7798d65f628ef42dc61e2a0b
1 /*
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
22 #define COBJMACROS
24 #include <audiopolicy.h>
25 #include <mmdeviceapi.h>
26 #include <winternl.h>
28 #include <wine/debug.h>
29 #include <wine/unixlib.h>
31 #include "mmdevdrv.h"
32 #include "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, &params);
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);
77 if (!ppv)
78 return E_POINTER;
80 if (IsEqualIID(riid, &IID_IUnknown) ||
81 IsEqualIID(riid, &IID_IAudioCaptureClient))
82 *ppv = iface;
83 else if (IsEqualIID(riid, &IID_IMarshal)) {
84 return IUnknown_QueryInterface(This->marshal, riid, ppv);
85 } else {
86 *ppv = NULL;
87 return E_NOINTERFACE;
90 IUnknown_AddRef((IUnknown *)*ppv);
92 return S_OK;
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);
115 if (!data)
116 return E_POINTER;
118 *data = NULL;
120 if (!frames || !flags)
121 return E_POINTER;
123 if (!This->stream)
124 return AUDCLNT_E_NOT_INITIALIZED;
126 params.stream = This->stream;
127 params.data = data;
128 params.frames = frames;
129 params.flags = (UINT *)flags;
130 params.devpos = devpos;
131 params.qpcpos = qpcpos;
133 WINE_UNIX_CALL(get_capture_buffer, &params);
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);
145 if (!This->stream)
146 return AUDCLNT_E_NOT_INITIALIZED;
148 params.stream = This->stream;
149 params.done = done;
151 WINE_UNIX_CALL(release_capture_buffer, &params);
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);
163 if (!frames)
164 return E_POINTER;
166 if (!This->stream)
167 return AUDCLNT_E_NOT_INITIALIZED;
169 params.stream = This->stream;
170 params.frames = frames;
172 WINE_UNIX_CALL(get_next_packet_size, &params);
174 return params.result;
177 const IAudioCaptureClientVtbl AudioCaptureClient_Vtbl =
179 capture_QueryInterface,
180 capture_AddRef,
181 capture_Release,
182 capture_GetBuffer,
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);
193 if (!ppv)
194 return E_POINTER;
196 if (IsEqualIID(riid, &IID_IUnknown) ||
197 IsEqualIID(riid, &IID_IAudioClock))
198 *ppv = iface;
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);
203 } else {
204 *ppv = NULL;
205 return E_NOINTERFACE;
208 IUnknown_AddRef((IUnknown *)*ppv);
210 return S_OK;
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);
232 if (!This->stream)
233 return AUDCLNT_E_NOT_INITIALIZED;
235 params.stream = This->stream;
236 params.freq = freq;
238 WINE_UNIX_CALL(get_frequency, &params);
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);
250 if (!pos)
251 return E_POINTER;
253 if (!This->stream)
254 return AUDCLNT_E_NOT_INITIALIZED;
256 params.stream = This->stream;
257 params.device = FALSE;
258 params.pos = pos;
259 params.qpctime = qpctime;
261 WINE_UNIX_CALL(get_position, &params);
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);
272 if (!chars)
273 return E_POINTER;
275 *chars = AUDIOCLOCK_CHARACTERISTIC_FIXED_FREQ;
277 return S_OK;
280 const IAudioClockVtbl AudioClock_Vtbl =
282 clock_QueryInterface,
283 clock_AddRef,
284 clock_Release,
285 clock_GetFrequency,
286 clock_GetPosition,
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);
315 if (!pos)
316 return E_POINTER;
318 if (!This->stream)
319 return AUDCLNT_E_NOT_INITIALIZED;
321 params.stream = This->stream;
322 params.device = TRUE;
323 params.pos = pos;
324 params.qpctime = qpctime;
326 WINE_UNIX_CALL(get_position, &params);
328 return params.result;
331 const IAudioClock2Vtbl AudioClock2_Vtbl =
333 clock2_QueryInterface,
334 clock2_AddRef,
335 clock2_Release,
336 clock2_GetDevicePosition
339 static HRESULT WINAPI streamvolume_QueryInterface(IAudioStreamVolume *iface, REFIID riid,
340 void **ppv)
342 TRACE("(%p)->(%s, %p)\n", iface, debugstr_guid(riid), ppv);
344 if (!ppv)
345 return E_POINTER;
347 if (IsEqualIID(riid, &IID_IUnknown) ||
348 IsEqualIID(riid, &IID_IAudioStreamVolume))
349 *ppv = iface;
350 else if (IsEqualIID(riid, &IID_IMarshal)) {
351 struct audio_client *This = impl_from_IAudioStreamVolume(iface);
352 return IUnknown_QueryInterface(This->marshal, riid, ppv);
353 } else {
354 *ppv = NULL;
355 return E_NOINTERFACE;
358 IUnknown_AddRef((IUnknown *)*ppv);
360 return S_OK;
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);
381 if (!out)
382 return E_POINTER;
384 *out = This->channel_count;
386 return S_OK;
389 static HRESULT WINAPI streamvolume_SetChannelVolume(IAudioStreamVolume *iface, UINT32 index,
390 float level)
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)
397 return E_INVALIDARG;
399 if (!This->stream)
400 return AUDCLNT_E_NOT_INITIALIZED;
402 if (index >= This->channel_count)
403 return E_INVALIDARG;
405 sessions_lock();
407 This->vols[index] = level;
408 set_stream_volumes(This);
410 sessions_unlock();
412 return S_OK;
415 static HRESULT WINAPI streamvolume_GetChannelVolume(IAudioStreamVolume *iface, UINT32 index,
416 float *level)
418 struct audio_client *This = impl_from_IAudioStreamVolume(iface);
420 TRACE("(%p)->(%d, %p)\n", This, index, level);
422 if (!level)
423 return E_POINTER;
425 if (!This->stream)
426 return AUDCLNT_E_NOT_INITIALIZED;
428 if (index >= This->channel_count)
429 return E_INVALIDARG;
431 *level = This->vols[index];
433 return S_OK;
436 static HRESULT WINAPI streamvolume_SetAllVolumes(IAudioStreamVolume *iface, UINT32 count,
437 const float *levels)
439 struct audio_client *This = impl_from_IAudioStreamVolume(iface);
440 unsigned int i;
442 TRACE("(%p)->(%d, %p)\n", This, count, levels);
444 if (!levels)
445 return E_POINTER;
447 if (!This->stream)
448 return AUDCLNT_E_NOT_INITIALIZED;
450 if (count != This->channel_count)
451 return E_INVALIDARG;
453 sessions_lock();
455 for (i = 0; i < count; ++i)
456 This->vols[i] = levels[i];
457 set_stream_volumes(This);
459 sessions_unlock();
461 return S_OK;
464 static HRESULT WINAPI streamvolume_GetAllVolumes(IAudioStreamVolume *iface, UINT32 count,
465 float *levels)
467 struct audio_client *This = impl_from_IAudioStreamVolume(iface);
468 unsigned int i;
470 TRACE("(%p)->(%d, %p)\n", This, count, levels);
472 if (!levels)
473 return E_POINTER;
475 if (!This->stream)
476 return AUDCLNT_E_NOT_INITIALIZED;
478 if (count != This->channel_count)
479 return E_INVALIDARG;
481 sessions_lock();
483 for (i = 0; i < count; ++i)
484 levels[i] = This->vols[i];
486 sessions_unlock();
488 return S_OK;
491 const IAudioStreamVolumeVtbl AudioStreamVolume_Vtbl =
493 streamvolume_QueryInterface,
494 streamvolume_AddRef,
495 streamvolume_Release,
496 streamvolume_GetChannelCount,
497 streamvolume_SetChannelVolume,
498 streamvolume_GetChannelVolume,
499 streamvolume_SetAllVolumes,
500 streamvolume_GetAllVolumes