2 * Copyright 2011 Andrew Eikum for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "wine/debug.h"
28 #include "wine/heap.h"
29 #include "wine/list.h"
30 #include "wine/unixlib.h"
33 #include "mmdeviceapi.h"
39 #include "endpointvolume.h"
40 #include "audioclient.h"
41 #include "audiopolicy.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(coreaudio
);
46 unixlib_handle_t coreaudio_handle
= 0;
48 #define NULL_PTR_ERR MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, RPC_X_NULL_REF_POINTER)
50 static const REFERENCE_TIME DefaultPeriod
= 100000;
51 static const REFERENCE_TIME MinimumPeriod
= 50000;
54 typedef struct ACImpl ACImpl
;
56 typedef struct _AudioSession
{
70 typedef struct _AudioSessionWrapper
{
71 IAudioSessionControl2 IAudioSessionControl2_iface
;
72 IChannelAudioVolume IChannelAudioVolume_iface
;
73 ISimpleAudioVolume ISimpleAudioVolume_iface
;
78 AudioSession
*session
;
79 } AudioSessionWrapper
;
82 IAudioClient3 IAudioClient3_iface
;
83 IAudioRenderClient IAudioRenderClient_iface
;
84 IAudioCaptureClient IAudioCaptureClient_iface
;
85 IAudioClock IAudioClock_iface
;
86 IAudioClock2 IAudioClock2_iface
;
87 IAudioStreamVolume IAudioStreamVolume_iface
;
92 IUnknown
*pUnkFTMarshal
;
95 UINT32 channel_count
, period_ms
;
103 AudioSession
*session
;
104 AudioSessionWrapper
*session_wrapper
;
106 stream_handle stream
;
110 static const IAudioClient3Vtbl AudioClient3_Vtbl
;
111 static const IAudioRenderClientVtbl AudioRenderClient_Vtbl
;
112 static const IAudioCaptureClientVtbl AudioCaptureClient_Vtbl
;
113 static const IAudioSessionControl2Vtbl AudioSessionControl2_Vtbl
;
114 static const ISimpleAudioVolumeVtbl SimpleAudioVolume_Vtbl
;
115 static const IAudioClockVtbl AudioClock_Vtbl
;
116 static const IAudioClock2Vtbl AudioClock2_Vtbl
;
117 static const IAudioStreamVolumeVtbl AudioStreamVolume_Vtbl
;
118 static const IChannelAudioVolumeVtbl ChannelAudioVolume_Vtbl
;
119 static const IAudioSessionManager2Vtbl AudioSessionManager2_Vtbl
;
121 typedef struct _SessionMgr
{
122 IAudioSessionManager2 IAudioSessionManager2_iface
;
129 static const WCHAR
*drv_key_devicesW
= L
"Software\\Wine\\Drivers\\winecoreaudio.drv\\devices";
131 static HANDLE g_timer_q
;
133 static CRITICAL_SECTION g_sessions_lock
;
134 static CRITICAL_SECTION_DEBUG g_sessions_lock_debug
=
136 0, 0, &g_sessions_lock
,
137 { &g_sessions_lock_debug
.ProcessLocksList
, &g_sessions_lock_debug
.ProcessLocksList
},
138 0, 0, { (DWORD_PTR
)(__FILE__
": g_sessions_lock") }
140 static CRITICAL_SECTION g_sessions_lock
= { &g_sessions_lock_debug
, -1, 0, 0, 0, 0 };
141 static struct list g_sessions
= LIST_INIT(g_sessions
);
143 static AudioSessionWrapper
*AudioSessionWrapper_Create(ACImpl
*client
);
145 static inline ACImpl
*impl_from_IAudioClient3(IAudioClient3
*iface
)
147 return CONTAINING_RECORD(iface
, ACImpl
, IAudioClient3_iface
);
150 static inline ACImpl
*impl_from_IAudioRenderClient(IAudioRenderClient
*iface
)
152 return CONTAINING_RECORD(iface
, ACImpl
, IAudioRenderClient_iface
);
155 static inline ACImpl
*impl_from_IAudioCaptureClient(IAudioCaptureClient
*iface
)
157 return CONTAINING_RECORD(iface
, ACImpl
, IAudioCaptureClient_iface
);
160 static inline AudioSessionWrapper
*impl_from_IAudioSessionControl2(IAudioSessionControl2
*iface
)
162 return CONTAINING_RECORD(iface
, AudioSessionWrapper
, IAudioSessionControl2_iface
);
165 static inline AudioSessionWrapper
*impl_from_ISimpleAudioVolume(ISimpleAudioVolume
*iface
)
167 return CONTAINING_RECORD(iface
, AudioSessionWrapper
, ISimpleAudioVolume_iface
);
170 static inline AudioSessionWrapper
*impl_from_IChannelAudioVolume(IChannelAudioVolume
*iface
)
172 return CONTAINING_RECORD(iface
, AudioSessionWrapper
, IChannelAudioVolume_iface
);
175 static inline ACImpl
*impl_from_IAudioClock(IAudioClock
*iface
)
177 return CONTAINING_RECORD(iface
, ACImpl
, IAudioClock_iface
);
180 static inline ACImpl
*impl_from_IAudioClock2(IAudioClock2
*iface
)
182 return CONTAINING_RECORD(iface
, ACImpl
, IAudioClock2_iface
);
185 static inline ACImpl
*impl_from_IAudioStreamVolume(IAudioStreamVolume
*iface
)
187 return CONTAINING_RECORD(iface
, ACImpl
, IAudioStreamVolume_iface
);
190 static inline SessionMgr
*impl_from_IAudioSessionManager2(IAudioSessionManager2
*iface
)
192 return CONTAINING_RECORD(iface
, SessionMgr
, IAudioSessionManager2_iface
);
195 BOOL WINAPI
DllMain(HINSTANCE dll
, DWORD reason
, void *reserved
)
199 case DLL_PROCESS_ATTACH
:
200 if(NtQueryVirtualMemory(GetCurrentProcess(), dll
, MemoryWineUnixFuncs
,
201 &coreaudio_handle
, sizeof(coreaudio_handle
), NULL
))
203 g_timer_q
= CreateTimerQueue();
208 case DLL_PROCESS_DETACH
:
210 DeleteCriticalSection(&g_sessions_lock
);
216 /* From <dlls/mmdevapi/mmdevapi.h> */
217 enum DriverPriority
{
218 Priority_Unavailable
= 0,
224 int WINAPI
AUDDRV_GetPriority(void)
226 return Priority_Neutral
;
229 static void set_device_guid(EDataFlow flow
, HKEY drv_key
, const WCHAR
*key_name
,
237 lr
= RegCreateKeyExW(HKEY_CURRENT_USER
, drv_key_devicesW
, 0, NULL
, 0, KEY_WRITE
,
238 NULL
, &drv_key
, NULL
);
239 if(lr
!= ERROR_SUCCESS
){
240 ERR("RegCreateKeyEx(drv_key) failed: %lu\n", lr
);
246 lr
= RegCreateKeyExW(drv_key
, key_name
, 0, NULL
, 0, KEY_WRITE
,
248 if(lr
!= ERROR_SUCCESS
){
249 ERR("RegCreateKeyEx(%s) failed: %lu\n", wine_dbgstr_w(key_name
), lr
);
253 lr
= RegSetValueExW(key
, L
"guid", 0, REG_BINARY
, (BYTE
*)guid
,
255 if(lr
!= ERROR_SUCCESS
)
256 ERR("RegSetValueEx(%s\\guid) failed: %lu\n", wine_dbgstr_w(key_name
), lr
);
261 RegCloseKey(drv_key
);
264 static void get_device_guid(EDataFlow flow
, DWORD device_id
, GUID
*guid
)
266 HKEY key
= NULL
, dev_key
;
267 DWORD type
, size
= sizeof(*guid
);
276 swprintf(key_name
+ 2, ARRAY_SIZE(key_name
), L
"%u", device_id
);
278 if(RegOpenKeyExW(HKEY_CURRENT_USER
, drv_key_devicesW
, 0, KEY_WRITE
|KEY_READ
, &key
) == ERROR_SUCCESS
){
279 if(RegOpenKeyExW(key
, key_name
, 0, KEY_READ
, &dev_key
) == ERROR_SUCCESS
){
280 if(RegQueryValueExW(dev_key
, L
"guid", 0, &type
,
281 (BYTE
*)guid
, &size
) == ERROR_SUCCESS
){
282 if(type
== REG_BINARY
){
283 RegCloseKey(dev_key
);
287 ERR("Invalid type for device %s GUID: %lu; ignoring and overwriting\n",
288 wine_dbgstr_w(key_name
), type
);
290 RegCloseKey(dev_key
);
296 set_device_guid(flow
, key
, key_name
, guid
);
302 static void set_stream_volumes(ACImpl
*This
, int channel
)
304 struct set_volumes_params params
;
306 params
.stream
= This
->stream
;
307 params
.master_volume
= This
->session
->mute
? 0.0f
: This
->session
->master_vol
;
308 params
.volumes
= This
->vols
;
309 params
.session_volumes
= This
->session
->channel_vols
;
310 params
.channel
= channel
;
312 UNIX_CALL(set_volumes
, ¶ms
);
315 HRESULT WINAPI
AUDDRV_GetEndpointIDs(EDataFlow flow
, WCHAR
***ids_out
,
316 GUID
**guids_out
, UINT
*num
, UINT
*def_index
)
318 struct get_endpoint_ids_params params
;
323 TRACE("%d %p %p %p\n", flow
, ids_out
, num
, def_index
);
327 params
.endpoints
= NULL
;
329 heap_free(params
.endpoints
);
330 params
.endpoints
= heap_alloc(params
.size
);
331 UNIX_CALL(get_endpoint_ids
, ¶ms
);
332 }while(params
.result
== HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
));
334 if(FAILED(params
.result
)) goto end
;
336 ids
= heap_alloc_zero(params
.num
* sizeof(*ids
));
337 guids
= heap_alloc(params
.num
* sizeof(*guids
));
339 params
.result
= E_OUTOFMEMORY
;
343 for(i
= 0; i
< params
.num
; i
++){
344 WCHAR
*name
= (WCHAR
*)((char *)params
.endpoints
+ params
.endpoints
[i
].name
);
345 int size
= (wcslen(name
) + 1) * sizeof(WCHAR
);
347 ids
[i
] = heap_alloc(size
);
349 params
.result
= E_OUTOFMEMORY
;
352 memcpy(ids
[i
], name
, size
);
353 get_device_guid(flow
, params
.endpoints
[i
].id
, guids
+ i
);
355 *def_index
= params
.default_idx
;
358 heap_free(params
.endpoints
);
359 if(FAILED(params
.result
)){
362 for(i
= 0; i
< params
.num
; i
++) heap_free(ids
[i
]);
371 return params
.result
;
374 static BOOL
get_deviceid_by_guid(GUID
*guid
, DWORD
*id
, EDataFlow
*flow
)
381 if(RegOpenKeyExW(HKEY_CURRENT_USER
, drv_key_devicesW
, 0, KEY_READ
, &devices_key
) != ERROR_SUCCESS
){
382 ERR("No devices in registry?\n");
391 key_name_size
= sizeof(key_name
);
392 if(RegEnumKeyExW(devices_key
, i
++, key_name
, &key_name_size
, NULL
,
393 NULL
, NULL
, NULL
) != ERROR_SUCCESS
)
396 if(RegOpenKeyExW(devices_key
, key_name
, 0, KEY_READ
, &key
) != ERROR_SUCCESS
){
397 WARN("Couldn't open key: %s\n", wine_dbgstr_w(key_name
));
401 size
= sizeof(reg_guid
);
402 if(RegQueryValueExW(key
, L
"guid", 0, &type
,
403 (BYTE
*)®_guid
, &size
) == ERROR_SUCCESS
){
404 if(IsEqualGUID(®_guid
, guid
)){
406 RegCloseKey(devices_key
);
408 TRACE("Found matching device key: %s\n", wine_dbgstr_w(key_name
));
410 if(key_name
[0] == '0')
412 else if(key_name
[0] == '1')
415 ERR("Unknown device type: %c\n", key_name
[0]);
419 *id
= wcstoul(key_name
+ 2, NULL
, 10);
428 RegCloseKey(devices_key
);
430 WARN("No matching device in registry for GUID %s\n", debugstr_guid(guid
));
435 HRESULT WINAPI
AUDDRV_GetAudioEndpoint(GUID
*guid
, IMMDevice
*dev
, IAudioClient
**out
)
442 TRACE("%s %p %p\n", debugstr_guid(guid
), dev
, out
);
444 if(!get_deviceid_by_guid(guid
, &dev_id
, &dataflow
))
445 return AUDCLNT_E_DEVICE_INVALIDATED
;
447 if(dataflow
!= eRender
&& dataflow
!= eCapture
)
450 This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(ACImpl
));
452 return E_OUTOFMEMORY
;
454 This
->IAudioClient3_iface
.lpVtbl
= &AudioClient3_Vtbl
;
455 This
->IAudioRenderClient_iface
.lpVtbl
= &AudioRenderClient_Vtbl
;
456 This
->IAudioCaptureClient_iface
.lpVtbl
= &AudioCaptureClient_Vtbl
;
457 This
->IAudioClock_iface
.lpVtbl
= &AudioClock_Vtbl
;
458 This
->IAudioClock2_iface
.lpVtbl
= &AudioClock2_Vtbl
;
459 This
->IAudioStreamVolume_iface
.lpVtbl
= &AudioStreamVolume_Vtbl
;
461 This
->dataflow
= dataflow
;
463 hr
= CoCreateFreeThreadedMarshaler((IUnknown
*)&This
->IAudioClient3_iface
, &This
->pUnkFTMarshal
);
465 HeapFree(GetProcessHeap(), 0, This
);
470 IMMDevice_AddRef(This
->parent
);
472 This
->dev_id
= dev_id
;
474 *out
= (IAudioClient
*)&This
->IAudioClient3_iface
;
475 IAudioClient3_AddRef(&This
->IAudioClient3_iface
);
480 static HRESULT WINAPI
AudioClient_QueryInterface(IAudioClient3
*iface
,
481 REFIID riid
, void **ppv
)
483 ACImpl
*This
= impl_from_IAudioClient3(iface
);
484 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
489 if(IsEqualIID(riid
, &IID_IUnknown
) ||
490 IsEqualIID(riid
, &IID_IAudioClient
) ||
491 IsEqualIID(riid
, &IID_IAudioClient2
) ||
492 IsEqualIID(riid
, &IID_IAudioClient3
))
494 else if(IsEqualIID(riid
, &IID_IMarshal
))
495 return IUnknown_QueryInterface(This
->pUnkFTMarshal
, riid
, ppv
);
498 IUnknown_AddRef((IUnknown
*)*ppv
);
501 WARN("Unknown interface %s\n", debugstr_guid(riid
));
502 return E_NOINTERFACE
;
505 static ULONG WINAPI
AudioClient_AddRef(IAudioClient3
*iface
)
507 ACImpl
*This
= impl_from_IAudioClient3(iface
);
509 ref
= InterlockedIncrement(&This
->ref
);
510 TRACE("(%p) Refcount now %lu\n", This
, ref
);
514 static ULONG WINAPI
AudioClient_Release(IAudioClient3
*iface
)
516 ACImpl
*This
= impl_from_IAudioClient3(iface
);
517 struct release_stream_params params
;
520 ref
= InterlockedDecrement(&This
->ref
);
521 TRACE("(%p) Refcount now %lu\n", This
, ref
);
526 event
= CreateEventW(NULL
, TRUE
, FALSE
, NULL
);
527 wait
= !DeleteTimerQueueTimer(g_timer_q
, This
->timer
, event
);
528 wait
= wait
&& GetLastError() == ERROR_IO_PENDING
;
530 WaitForSingleObject(event
, INFINITE
);
534 params
.stream
= This
->stream
;
535 UNIX_CALL(release_stream
, ¶ms
);
538 EnterCriticalSection(&g_sessions_lock
);
539 list_remove(&This
->entry
);
540 LeaveCriticalSection(&g_sessions_lock
);
542 HeapFree(GetProcessHeap(), 0, This
->vols
);
543 IMMDevice_Release(This
->parent
);
544 IUnknown_Release(This
->pUnkFTMarshal
);
545 HeapFree(GetProcessHeap(), 0, This
);
550 static void dump_fmt(const WAVEFORMATEX
*fmt
)
552 TRACE("wFormatTag: 0x%x (", fmt
->wFormatTag
);
553 switch(fmt
->wFormatTag
){
554 case WAVE_FORMAT_PCM
:
555 TRACE("WAVE_FORMAT_PCM");
557 case WAVE_FORMAT_IEEE_FLOAT
:
558 TRACE("WAVE_FORMAT_IEEE_FLOAT");
560 case WAVE_FORMAT_EXTENSIBLE
:
561 TRACE("WAVE_FORMAT_EXTENSIBLE");
569 TRACE("nChannels: %u\n", fmt
->nChannels
);
570 TRACE("nSamplesPerSec: %lu\n", fmt
->nSamplesPerSec
);
571 TRACE("nAvgBytesPerSec: %lu\n", fmt
->nAvgBytesPerSec
);
572 TRACE("nBlockAlign: %u\n", fmt
->nBlockAlign
);
573 TRACE("wBitsPerSample: %u\n", fmt
->wBitsPerSample
);
574 TRACE("cbSize: %u\n", fmt
->cbSize
);
576 if(fmt
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
){
577 WAVEFORMATEXTENSIBLE
*fmtex
= (void*)fmt
;
578 TRACE("dwChannelMask: %08lx\n", fmtex
->dwChannelMask
);
579 TRACE("Samples: %04x\n", fmtex
->Samples
.wReserved
);
580 TRACE("SubFormat: %s\n", wine_dbgstr_guid(&fmtex
->SubFormat
));
584 static void session_init_vols(AudioSession
*session
, UINT channels
)
586 if(session
->channel_count
< channels
){
589 if(session
->channel_vols
)
590 session
->channel_vols
= HeapReAlloc(GetProcessHeap(), 0,
591 session
->channel_vols
, sizeof(float) * channels
);
593 session
->channel_vols
= HeapAlloc(GetProcessHeap(), 0,
594 sizeof(float) * channels
);
595 if(!session
->channel_vols
)
598 for(i
= session
->channel_count
; i
< channels
; ++i
)
599 session
->channel_vols
[i
] = 1.f
;
601 session
->channel_count
= channels
;
605 static AudioSession
*create_session(const GUID
*guid
, IMMDevice
*device
,
610 ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(AudioSession
));
614 memcpy(&ret
->guid
, guid
, sizeof(GUID
));
616 ret
->device
= device
;
618 list_init(&ret
->clients
);
620 list_add_head(&g_sessions
, &ret
->entry
);
622 session_init_vols(ret
, num_channels
);
624 ret
->master_vol
= 1.f
;
629 /* if channels == 0, then this will return or create a session with
630 * matching dataflow and GUID. otherwise, channels must also match */
631 static HRESULT
get_audio_session(const GUID
*sessionguid
,
632 IMMDevice
*device
, UINT channels
, AudioSession
**out
)
634 AudioSession
*session
;
636 if(!sessionguid
|| IsEqualGUID(sessionguid
, &GUID_NULL
)){
637 *out
= create_session(&GUID_NULL
, device
, channels
);
639 return E_OUTOFMEMORY
;
645 LIST_FOR_EACH_ENTRY(session
, &g_sessions
, AudioSession
, entry
){
646 if(session
->device
== device
&&
647 IsEqualGUID(sessionguid
, &session
->guid
)){
648 session_init_vols(session
, channels
);
655 *out
= create_session(sessionguid
, device
, channels
);
657 return E_OUTOFMEMORY
;
663 static HRESULT WINAPI
AudioClient_Initialize(IAudioClient3
*iface
,
664 AUDCLNT_SHAREMODE mode
, DWORD flags
, REFERENCE_TIME duration
,
665 REFERENCE_TIME period
, const WAVEFORMATEX
*fmt
,
666 const GUID
*sessionguid
)
668 ACImpl
*This
= impl_from_IAudioClient3(iface
);
669 struct release_stream_params release_params
;
670 struct create_stream_params params
;
671 stream_handle stream
;
674 TRACE("(%p)->(%x, %lx, %s, %s, %p, %s)\n", This
, mode
, flags
,
675 wine_dbgstr_longlong(duration
), wine_dbgstr_longlong(period
), fmt
, debugstr_guid(sessionguid
));
682 if(mode
!= AUDCLNT_SHAREMODE_SHARED
&& mode
!= AUDCLNT_SHAREMODE_EXCLUSIVE
)
685 if(flags
& ~(AUDCLNT_STREAMFLAGS_CROSSPROCESS
|
686 AUDCLNT_STREAMFLAGS_LOOPBACK
|
687 AUDCLNT_STREAMFLAGS_EVENTCALLBACK
|
688 AUDCLNT_STREAMFLAGS_NOPERSIST
|
689 AUDCLNT_STREAMFLAGS_RATEADJUST
|
690 AUDCLNT_SESSIONFLAGS_EXPIREWHENUNOWNED
|
691 AUDCLNT_SESSIONFLAGS_DISPLAY_HIDE
|
692 AUDCLNT_SESSIONFLAGS_DISPLAY_HIDEWHENEXPIRED
|
693 AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY
|
694 AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM
)){
695 FIXME("Unknown flags: %08lx\n", flags
);
699 if(mode
== AUDCLNT_SHAREMODE_SHARED
){
700 period
= DefaultPeriod
;
701 if( duration
< 3 * period
)
702 duration
= 3 * period
;
704 if(fmt
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
){
705 if(((WAVEFORMATEXTENSIBLE
*)fmt
)->dwChannelMask
== 0 ||
706 ((WAVEFORMATEXTENSIBLE
*)fmt
)->dwChannelMask
& SPEAKER_RESERVED
)
707 return AUDCLNT_E_UNSUPPORTED_FORMAT
;
711 period
= DefaultPeriod
; /* not minimum */
712 if(period
< MinimumPeriod
|| period
> 5000000)
713 return AUDCLNT_E_INVALID_DEVICE_PERIOD
;
714 if(duration
> 20000000) /* the smaller the period, the lower this limit */
715 return AUDCLNT_E_BUFFER_SIZE_ERROR
;
716 if(flags
& AUDCLNT_STREAMFLAGS_EVENTCALLBACK
){
717 if(duration
!= period
)
718 return AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL
;
719 FIXME("EXCLUSIVE mode with EVENTCALLBACK\n");
720 return AUDCLNT_E_DEVICE_IN_USE
;
722 if( duration
< 8 * period
)
723 duration
= 8 * period
; /* may grow above 2s */
727 EnterCriticalSection(&g_sessions_lock
);
730 LeaveCriticalSection(&g_sessions_lock
);
731 return AUDCLNT_E_ALREADY_INITIALIZED
;
734 params
.dev_id
= This
->dev_id
;
735 params
.flow
= This
->dataflow
;
737 params
.duration
= duration
;
738 params
.period
= period
;
740 params
.stream
= &stream
;
742 UNIX_CALL(create_stream
, ¶ms
);
743 if(FAILED(params
.result
)){
744 LeaveCriticalSection(&g_sessions_lock
);
745 return params
.result
;
749 This
->channel_count
= fmt
->nChannels
;
750 This
->period_ms
= period
/ 10000;
752 This
->vols
= HeapAlloc(GetProcessHeap(), 0, This
->channel_count
* sizeof(float));
754 params
.result
= E_OUTOFMEMORY
;
758 for(i
= 0; i
< This
->channel_count
; ++i
)
761 params
.result
= get_audio_session(sessionguid
, This
->parent
, fmt
->nChannels
, &This
->session
);
762 if(FAILED(params
.result
)) goto end
;
764 list_add_tail(&This
->session
->clients
, &This
->entry
);
767 if(FAILED(params
.result
)){
768 release_params
.stream
= stream
;
769 UNIX_CALL(release_stream
, &release_params
);
770 HeapFree(GetProcessHeap(), 0, This
->vols
);
773 This
->stream
= stream
;
774 set_stream_volumes(This
, -1);
777 LeaveCriticalSection(&g_sessions_lock
);
779 return params
.result
;
782 static HRESULT WINAPI
AudioClient_GetBufferSize(IAudioClient3
*iface
,
785 ACImpl
*This
= impl_from_IAudioClient3(iface
);
786 struct get_buffer_size_params params
;
788 TRACE("(%p)->(%p)\n", This
, frames
);
794 return AUDCLNT_E_NOT_INITIALIZED
;
796 params
.stream
= This
->stream
;
797 params
.frames
= frames
;
798 UNIX_CALL(get_buffer_size
, ¶ms
);
799 return params
.result
;
802 static HRESULT WINAPI
AudioClient_GetStreamLatency(IAudioClient3
*iface
,
805 ACImpl
*This
= impl_from_IAudioClient3(iface
);
806 struct get_latency_params params
;
808 TRACE("(%p)->(%p)\n", This
, out
);
814 return AUDCLNT_E_NOT_INITIALIZED
;
816 params
.stream
= This
->stream
;
817 params
.latency
= out
;
818 UNIX_CALL(get_latency
, ¶ms
);
819 return params
.result
;
822 static HRESULT WINAPI
AudioClient_GetCurrentPadding(IAudioClient3
*iface
,
825 ACImpl
*This
= impl_from_IAudioClient3(iface
);
826 struct get_current_padding_params params
;
828 TRACE("(%p)->(%p)\n", This
, numpad
);
834 return AUDCLNT_E_NOT_INITIALIZED
;
836 params
.stream
= This
->stream
;
837 params
.padding
= numpad
;
838 UNIX_CALL(get_current_padding
, ¶ms
);
839 return params
.result
;
842 static HRESULT WINAPI
AudioClient_IsFormatSupported(IAudioClient3
*iface
,
843 AUDCLNT_SHAREMODE mode
, const WAVEFORMATEX
*pwfx
,
844 WAVEFORMATEX
**outpwfx
)
846 ACImpl
*This
= impl_from_IAudioClient3(iface
);
847 struct is_format_supported_params params
;
849 TRACE("(%p)->(%x, %p, %p)\n", This
, mode
, pwfx
, outpwfx
);
850 if(pwfx
) dump_fmt(pwfx
);
852 params
.dev_id
= This
->dev_id
;
853 params
.flow
= This
->dataflow
;
855 params
.fmt_in
= pwfx
;
856 params
.fmt_out
= NULL
;
860 if(mode
== AUDCLNT_SHAREMODE_SHARED
)
861 params
.fmt_out
= CoTaskMemAlloc(sizeof(*params
.fmt_out
));
863 UNIX_CALL(is_format_supported
, ¶ms
);
865 if(params
.result
== S_FALSE
)
866 *outpwfx
= ¶ms
.fmt_out
->Format
;
868 CoTaskMemFree(params
.fmt_out
);
870 return params
.result
;
873 static HRESULT WINAPI
AudioClient_GetMixFormat(IAudioClient3
*iface
,
876 ACImpl
*This
= impl_from_IAudioClient3(iface
);
877 struct get_mix_format_params params
;
879 TRACE("(%p)->(%p)\n", This
, pwfx
);
885 params
.dev_id
= This
->dev_id
;
886 params
.flow
= This
->dataflow
;
887 params
.fmt
= CoTaskMemAlloc(sizeof(WAVEFORMATEXTENSIBLE
));
889 return E_OUTOFMEMORY
;
891 UNIX_CALL(get_mix_format
, ¶ms
);
893 if(SUCCEEDED(params
.result
)){
894 *pwfx
= ¶ms
.fmt
->Format
;
897 CoTaskMemFree(params
.fmt
);
899 return params
.result
;
902 static HRESULT WINAPI
AudioClient_GetDevicePeriod(IAudioClient3
*iface
,
903 REFERENCE_TIME
*defperiod
, REFERENCE_TIME
*minperiod
)
905 ACImpl
*This
= impl_from_IAudioClient3(iface
);
907 TRACE("(%p)->(%p, %p)\n", This
, defperiod
, minperiod
);
909 if(!defperiod
&& !minperiod
)
913 *defperiod
= DefaultPeriod
;
915 *minperiod
= MinimumPeriod
;
920 void CALLBACK
ca_period_cb(void *user
, BOOLEAN timer
)
925 SetEvent(This
->event
);
928 static HRESULT WINAPI
AudioClient_Start(IAudioClient3
*iface
)
930 ACImpl
*This
= impl_from_IAudioClient3(iface
);
931 struct start_params params
;
933 TRACE("(%p)\n", This
);
936 return AUDCLNT_E_NOT_INITIALIZED
;
938 if((This
->flags
& AUDCLNT_STREAMFLAGS_EVENTCALLBACK
) && !This
->event
)
939 return AUDCLNT_E_EVENTHANDLE_NOT_SET
;
941 params
.stream
= This
->stream
;
942 UNIX_CALL(start
, ¶ms
);
944 if(SUCCEEDED(params
.result
)){
945 if(This
->event
&& !This
->timer
){
946 if(!CreateTimerQueueTimer(&This
->timer
, g_timer_q
, ca_period_cb
, This
, 0,
947 This
->period_ms
, WT_EXECUTEINTIMERTHREAD
)){
949 IAudioClient3_Stop(iface
);
950 WARN("Unable to create timer: %lu\n", GetLastError());
951 return E_OUTOFMEMORY
;
955 return params
.result
;
958 static HRESULT WINAPI
AudioClient_Stop(IAudioClient3
*iface
)
960 ACImpl
*This
= impl_from_IAudioClient3(iface
);
961 struct stop_params params
;
963 TRACE("(%p)\n", This
);
966 return AUDCLNT_E_NOT_INITIALIZED
;
968 params
.stream
= This
->stream
;
969 UNIX_CALL(stop
, ¶ms
);
970 return params
.result
;
973 static HRESULT WINAPI
AudioClient_Reset(IAudioClient3
*iface
)
975 ACImpl
*This
= impl_from_IAudioClient3(iface
);
976 struct reset_params params
;
978 TRACE("(%p)\n", This
);
981 return AUDCLNT_E_NOT_INITIALIZED
;
983 params
.stream
= This
->stream
;
984 UNIX_CALL(reset
, ¶ms
);
985 return params
.result
;
988 static HRESULT WINAPI
AudioClient_SetEventHandle(IAudioClient3
*iface
,
991 ACImpl
*This
= impl_from_IAudioClient3(iface
);
994 TRACE("(%p)->(%p)\n", This
, event
);
1000 return AUDCLNT_E_NOT_INITIALIZED
;
1002 EnterCriticalSection(&g_sessions_lock
);
1004 if(!(This
->flags
& AUDCLNT_STREAMFLAGS_EVENTCALLBACK
))
1005 hr
= AUDCLNT_E_EVENTHANDLE_NOT_EXPECTED
;
1006 else if(This
->event
){
1007 FIXME("called twice\n");
1008 hr
= HRESULT_FROM_WIN32(ERROR_INVALID_NAME
);
1010 This
->event
= event
;
1012 LeaveCriticalSection(&g_sessions_lock
);
1017 static HRESULT WINAPI
AudioClient_GetService(IAudioClient3
*iface
, REFIID riid
,
1020 ACImpl
*This
= impl_from_IAudioClient3(iface
);
1023 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
1030 return AUDCLNT_E_NOT_INITIALIZED
;
1032 EnterCriticalSection(&g_sessions_lock
);
1034 if(IsEqualIID(riid
, &IID_IAudioRenderClient
)){
1035 if(This
->dataflow
!= eRender
){
1036 hr
= AUDCLNT_E_WRONG_ENDPOINT_TYPE
;
1039 IAudioRenderClient_AddRef(&This
->IAudioRenderClient_iface
);
1040 *ppv
= &This
->IAudioRenderClient_iface
;
1041 }else if(IsEqualIID(riid
, &IID_IAudioCaptureClient
)){
1042 if(This
->dataflow
!= eCapture
){
1043 hr
= AUDCLNT_E_WRONG_ENDPOINT_TYPE
;
1046 IAudioCaptureClient_AddRef(&This
->IAudioCaptureClient_iface
);
1047 *ppv
= &This
->IAudioCaptureClient_iface
;
1048 }else if(IsEqualIID(riid
, &IID_IAudioClock
)){
1049 IAudioClock_AddRef(&This
->IAudioClock_iface
);
1050 *ppv
= &This
->IAudioClock_iface
;
1051 }else if(IsEqualIID(riid
, &IID_IAudioStreamVolume
)){
1052 IAudioStreamVolume_AddRef(&This
->IAudioStreamVolume_iface
);
1053 *ppv
= &This
->IAudioStreamVolume_iface
;
1054 }else if(IsEqualIID(riid
, &IID_IAudioSessionControl
)){
1055 if(!This
->session_wrapper
){
1056 This
->session_wrapper
= AudioSessionWrapper_Create(This
);
1057 if(!This
->session_wrapper
){
1062 IAudioSessionControl2_AddRef(&This
->session_wrapper
->IAudioSessionControl2_iface
);
1064 *ppv
= &This
->session_wrapper
->IAudioSessionControl2_iface
;
1065 }else if(IsEqualIID(riid
, &IID_IChannelAudioVolume
)){
1066 if(!This
->session_wrapper
){
1067 This
->session_wrapper
= AudioSessionWrapper_Create(This
);
1068 if(!This
->session_wrapper
){
1073 IChannelAudioVolume_AddRef(&This
->session_wrapper
->IChannelAudioVolume_iface
);
1075 *ppv
= &This
->session_wrapper
->IChannelAudioVolume_iface
;
1076 }else if(IsEqualIID(riid
, &IID_ISimpleAudioVolume
)){
1077 if(!This
->session_wrapper
){
1078 This
->session_wrapper
= AudioSessionWrapper_Create(This
);
1079 if(!This
->session_wrapper
){
1084 ISimpleAudioVolume_AddRef(&This
->session_wrapper
->ISimpleAudioVolume_iface
);
1086 *ppv
= &This
->session_wrapper
->ISimpleAudioVolume_iface
;
1091 FIXME("stub %s\n", debugstr_guid(riid
));
1096 LeaveCriticalSection(&g_sessions_lock
);
1100 static HRESULT WINAPI
AudioClient_IsOffloadCapable(IAudioClient3
*iface
,
1101 AUDIO_STREAM_CATEGORY category
, BOOL
*offload_capable
)
1103 ACImpl
*This
= impl_from_IAudioClient3(iface
);
1105 TRACE("(%p)->(0x%x, %p)\n", This
, category
, offload_capable
);
1107 if(!offload_capable
)
1108 return E_INVALIDARG
;
1110 *offload_capable
= FALSE
;
1115 static HRESULT WINAPI
AudioClient_SetClientProperties(IAudioClient3
*iface
,
1116 const AudioClientProperties
*prop
)
1118 ACImpl
*This
= impl_from_IAudioClient3(iface
);
1119 const Win8AudioClientProperties
*legacy_prop
= (const Win8AudioClientProperties
*)prop
;
1121 TRACE("(%p)->(%p)\n", This
, prop
);
1126 if(legacy_prop
->cbSize
== sizeof(AudioClientProperties
)){
1127 TRACE("{ bIsOffload: %u, eCategory: 0x%x, Options: 0x%x }\n",
1128 legacy_prop
->bIsOffload
,
1129 legacy_prop
->eCategory
,
1131 }else if(legacy_prop
->cbSize
== sizeof(Win8AudioClientProperties
)){
1132 TRACE("{ bIsOffload: %u, eCategory: 0x%x }\n",
1133 legacy_prop
->bIsOffload
,
1134 legacy_prop
->eCategory
);
1136 WARN("Unsupported Size = %d\n", legacy_prop
->cbSize
);
1137 return E_INVALIDARG
;
1141 if(legacy_prop
->bIsOffload
)
1142 return AUDCLNT_E_ENDPOINT_OFFLOAD_NOT_CAPABLE
;
1147 static HRESULT WINAPI
AudioClient_GetBufferSizeLimits(IAudioClient3
*iface
,
1148 const WAVEFORMATEX
*format
, BOOL event_driven
, REFERENCE_TIME
*min_duration
,
1149 REFERENCE_TIME
*max_duration
)
1151 ACImpl
*This
= impl_from_IAudioClient3(iface
);
1153 FIXME("(%p)->(%p, %u, %p, %p)\n", This
, format
, event_driven
, min_duration
, max_duration
);
1158 static HRESULT WINAPI
AudioClient_GetSharedModeEnginePeriod(IAudioClient3
*iface
,
1159 const WAVEFORMATEX
*format
, UINT32
*default_period_frames
, UINT32
*unit_period_frames
,
1160 UINT32
*min_period_frames
, UINT32
*max_period_frames
)
1162 ACImpl
*This
= impl_from_IAudioClient3(iface
);
1164 FIXME("(%p)->(%p, %p, %p, %p, %p)\n", This
, format
, default_period_frames
, unit_period_frames
,
1165 min_period_frames
, max_period_frames
);
1170 static HRESULT WINAPI
AudioClient_GetCurrentSharedModeEnginePeriod(IAudioClient3
*iface
,
1171 WAVEFORMATEX
**cur_format
, UINT32
*cur_period_frames
)
1173 ACImpl
*This
= impl_from_IAudioClient3(iface
);
1175 FIXME("(%p)->(%p, %p)\n", This
, cur_format
, cur_period_frames
);
1180 static HRESULT WINAPI
AudioClient_InitializeSharedAudioStream(IAudioClient3
*iface
,
1181 DWORD flags
, UINT32 period_frames
, const WAVEFORMATEX
*format
,
1182 const GUID
*session_guid
)
1184 ACImpl
*This
= impl_from_IAudioClient3(iface
);
1186 FIXME("(%p)->(0x%lx, %u, %p, %s)\n", This
, flags
, period_frames
, format
, debugstr_guid(session_guid
));
1191 static const IAudioClient3Vtbl AudioClient3_Vtbl
=
1193 AudioClient_QueryInterface
,
1195 AudioClient_Release
,
1196 AudioClient_Initialize
,
1197 AudioClient_GetBufferSize
,
1198 AudioClient_GetStreamLatency
,
1199 AudioClient_GetCurrentPadding
,
1200 AudioClient_IsFormatSupported
,
1201 AudioClient_GetMixFormat
,
1202 AudioClient_GetDevicePeriod
,
1206 AudioClient_SetEventHandle
,
1207 AudioClient_GetService
,
1208 AudioClient_IsOffloadCapable
,
1209 AudioClient_SetClientProperties
,
1210 AudioClient_GetBufferSizeLimits
,
1211 AudioClient_GetSharedModeEnginePeriod
,
1212 AudioClient_GetCurrentSharedModeEnginePeriod
,
1213 AudioClient_InitializeSharedAudioStream
,
1216 static HRESULT WINAPI
AudioRenderClient_QueryInterface(
1217 IAudioRenderClient
*iface
, REFIID riid
, void **ppv
)
1219 ACImpl
*This
= impl_from_IAudioRenderClient(iface
);
1220 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
1226 if(IsEqualIID(riid
, &IID_IUnknown
) ||
1227 IsEqualIID(riid
, &IID_IAudioRenderClient
))
1229 else if(IsEqualIID(riid
, &IID_IMarshal
))
1230 return IUnknown_QueryInterface(This
->pUnkFTMarshal
, riid
, ppv
);
1233 IUnknown_AddRef((IUnknown
*)*ppv
);
1237 WARN("Unknown interface %s\n", debugstr_guid(riid
));
1238 return E_NOINTERFACE
;
1241 static ULONG WINAPI
AudioRenderClient_AddRef(IAudioRenderClient
*iface
)
1243 ACImpl
*This
= impl_from_IAudioRenderClient(iface
);
1244 return AudioClient_AddRef(&This
->IAudioClient3_iface
);
1247 static ULONG WINAPI
AudioRenderClient_Release(IAudioRenderClient
*iface
)
1249 ACImpl
*This
= impl_from_IAudioRenderClient(iface
);
1250 return AudioClient_Release(&This
->IAudioClient3_iface
);
1253 static HRESULT WINAPI
AudioRenderClient_GetBuffer(IAudioRenderClient
*iface
,
1254 UINT32 frames
, BYTE
**data
)
1256 ACImpl
*This
= impl_from_IAudioRenderClient(iface
);
1257 struct get_render_buffer_params params
;
1259 TRACE("(%p)->(%u, %p)\n", This
, frames
, data
);
1265 params
.stream
= This
->stream
;
1266 params
.frames
= frames
;
1268 UNIX_CALL(get_render_buffer
, ¶ms
);
1269 return params
.result
;
1272 static HRESULT WINAPI
AudioRenderClient_ReleaseBuffer(
1273 IAudioRenderClient
*iface
, UINT32 frames
, DWORD flags
)
1275 ACImpl
*This
= impl_from_IAudioRenderClient(iface
);
1276 struct release_render_buffer_params params
;
1278 TRACE("(%p)->(%u, %lx)\n", This
, frames
, flags
);
1280 params
.stream
= This
->stream
;
1281 params
.frames
= frames
;
1282 params
.flags
= flags
;
1283 UNIX_CALL(release_render_buffer
, ¶ms
);
1284 return params
.result
;
1287 static const IAudioRenderClientVtbl AudioRenderClient_Vtbl
= {
1288 AudioRenderClient_QueryInterface
,
1289 AudioRenderClient_AddRef
,
1290 AudioRenderClient_Release
,
1291 AudioRenderClient_GetBuffer
,
1292 AudioRenderClient_ReleaseBuffer
1295 static HRESULT WINAPI
AudioCaptureClient_QueryInterface(
1296 IAudioCaptureClient
*iface
, REFIID riid
, void **ppv
)
1298 ACImpl
*This
= impl_from_IAudioCaptureClient(iface
);
1299 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
1305 if(IsEqualIID(riid
, &IID_IUnknown
) ||
1306 IsEqualIID(riid
, &IID_IAudioCaptureClient
))
1308 else if(IsEqualIID(riid
, &IID_IMarshal
))
1309 return IUnknown_QueryInterface(This
->pUnkFTMarshal
, riid
, ppv
);
1312 IUnknown_AddRef((IUnknown
*)*ppv
);
1316 WARN("Unknown interface %s\n", debugstr_guid(riid
));
1317 return E_NOINTERFACE
;
1320 static ULONG WINAPI
AudioCaptureClient_AddRef(IAudioCaptureClient
*iface
)
1322 ACImpl
*This
= impl_from_IAudioCaptureClient(iface
);
1323 return IAudioClient3_AddRef(&This
->IAudioClient3_iface
);
1326 static ULONG WINAPI
AudioCaptureClient_Release(IAudioCaptureClient
*iface
)
1328 ACImpl
*This
= impl_from_IAudioCaptureClient(iface
);
1329 return IAudioClient3_Release(&This
->IAudioClient3_iface
);
1332 static HRESULT WINAPI
AudioCaptureClient_GetBuffer(IAudioCaptureClient
*iface
,
1333 BYTE
**data
, UINT32
*frames
, DWORD
*flags
, UINT64
*devpos
,
1336 ACImpl
*This
= impl_from_IAudioCaptureClient(iface
);
1337 struct get_capture_buffer_params params
;
1339 TRACE("(%p)->(%p, %p, %p, %p, %p)\n", This
, data
, frames
, flags
,
1347 if(!frames
|| !flags
)
1350 params
.stream
= This
->stream
;
1352 params
.frames
= frames
;
1353 params
.flags
= flags
;
1354 params
.devpos
= devpos
;
1355 params
.qpcpos
= qpcpos
;
1356 UNIX_CALL(get_capture_buffer
, ¶ms
);
1357 return params
.result
;
1360 static HRESULT WINAPI
AudioCaptureClient_ReleaseBuffer(
1361 IAudioCaptureClient
*iface
, UINT32 done
)
1363 ACImpl
*This
= impl_from_IAudioCaptureClient(iface
);
1364 struct release_capture_buffer_params params
;
1366 TRACE("(%p)->(%u)\n", This
, done
);
1368 params
.stream
= This
->stream
;
1370 UNIX_CALL(release_capture_buffer
, ¶ms
);
1371 return params
.result
;
1374 static HRESULT WINAPI
AudioCaptureClient_GetNextPacketSize(
1375 IAudioCaptureClient
*iface
, UINT32
*frames
)
1377 ACImpl
*This
= impl_from_IAudioCaptureClient(iface
);
1378 struct get_next_packet_size_params params
;
1380 TRACE("(%p)->(%p)\n", This
, frames
);
1385 params
.stream
= This
->stream
;
1386 params
.frames
= frames
;
1387 UNIX_CALL(get_next_packet_size
, ¶ms
);
1388 return params
.result
;
1391 static const IAudioCaptureClientVtbl AudioCaptureClient_Vtbl
=
1393 AudioCaptureClient_QueryInterface
,
1394 AudioCaptureClient_AddRef
,
1395 AudioCaptureClient_Release
,
1396 AudioCaptureClient_GetBuffer
,
1397 AudioCaptureClient_ReleaseBuffer
,
1398 AudioCaptureClient_GetNextPacketSize
1401 static HRESULT WINAPI
AudioClock_QueryInterface(IAudioClock
*iface
,
1402 REFIID riid
, void **ppv
)
1404 ACImpl
*This
= impl_from_IAudioClock(iface
);
1406 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
1412 if(IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IAudioClock
))
1414 else if(IsEqualIID(riid
, &IID_IAudioClock2
))
1415 *ppv
= &This
->IAudioClock2_iface
;
1417 IUnknown_AddRef((IUnknown
*)*ppv
);
1421 WARN("Unknown interface %s\n", debugstr_guid(riid
));
1422 return E_NOINTERFACE
;
1425 static ULONG WINAPI
AudioClock_AddRef(IAudioClock
*iface
)
1427 ACImpl
*This
= impl_from_IAudioClock(iface
);
1428 return IAudioClient3_AddRef(&This
->IAudioClient3_iface
);
1431 static ULONG WINAPI
AudioClock_Release(IAudioClock
*iface
)
1433 ACImpl
*This
= impl_from_IAudioClock(iface
);
1434 return IAudioClient3_Release(&This
->IAudioClient3_iface
);
1437 static HRESULT WINAPI
AudioClock_GetFrequency(IAudioClock
*iface
, UINT64
*freq
)
1439 ACImpl
*This
= impl_from_IAudioClock(iface
);
1440 struct get_frequency_params params
;
1442 TRACE("(%p)->(%p)\n", This
, freq
);
1444 params
.stream
= This
->stream
;
1446 UNIX_CALL(get_frequency
, ¶ms
);
1447 return params
.result
;
1450 static HRESULT WINAPI
AudioClock_GetPosition(IAudioClock
*iface
, UINT64
*pos
,
1453 ACImpl
*This
= impl_from_IAudioClock(iface
);
1454 struct get_position_params params
;
1456 TRACE("(%p)->(%p, %p)\n", This
, pos
, qpctime
);
1461 params
.stream
= This
->stream
;
1463 params
.qpctime
= qpctime
;
1464 UNIX_CALL(get_position
, ¶ms
);
1465 return params
.result
;
1468 static HRESULT WINAPI
AudioClock_GetCharacteristics(IAudioClock
*iface
,
1471 ACImpl
*This
= impl_from_IAudioClock(iface
);
1473 TRACE("(%p)->(%p)\n", This
, chars
);
1478 *chars
= AUDIOCLOCK_CHARACTERISTIC_FIXED_FREQ
;
1483 static const IAudioClockVtbl AudioClock_Vtbl
=
1485 AudioClock_QueryInterface
,
1488 AudioClock_GetFrequency
,
1489 AudioClock_GetPosition
,
1490 AudioClock_GetCharacteristics
1493 static HRESULT WINAPI
AudioClock2_QueryInterface(IAudioClock2
*iface
,
1494 REFIID riid
, void **ppv
)
1496 ACImpl
*This
= impl_from_IAudioClock2(iface
);
1497 return IAudioClock_QueryInterface(&This
->IAudioClock_iface
, riid
, ppv
);
1500 static ULONG WINAPI
AudioClock2_AddRef(IAudioClock2
*iface
)
1502 ACImpl
*This
= impl_from_IAudioClock2(iface
);
1503 return IAudioClient3_AddRef(&This
->IAudioClient3_iface
);
1506 static ULONG WINAPI
AudioClock2_Release(IAudioClock2
*iface
)
1508 ACImpl
*This
= impl_from_IAudioClock2(iface
);
1509 return IAudioClient3_Release(&This
->IAudioClient3_iface
);
1512 static HRESULT WINAPI
AudioClock2_GetDevicePosition(IAudioClock2
*iface
,
1513 UINT64
*pos
, UINT64
*qpctime
)
1515 ACImpl
*This
= impl_from_IAudioClock2(iface
);
1517 FIXME("(%p)->(%p, %p)\n", This
, pos
, qpctime
);
1522 static const IAudioClock2Vtbl AudioClock2_Vtbl
=
1524 AudioClock2_QueryInterface
,
1526 AudioClock2_Release
,
1527 AudioClock2_GetDevicePosition
1530 static AudioSessionWrapper
*AudioSessionWrapper_Create(ACImpl
*client
)
1532 AudioSessionWrapper
*ret
;
1534 ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1535 sizeof(AudioSessionWrapper
));
1539 ret
->IAudioSessionControl2_iface
.lpVtbl
= &AudioSessionControl2_Vtbl
;
1540 ret
->ISimpleAudioVolume_iface
.lpVtbl
= &SimpleAudioVolume_Vtbl
;
1541 ret
->IChannelAudioVolume_iface
.lpVtbl
= &ChannelAudioVolume_Vtbl
;
1545 ret
->client
= client
;
1547 ret
->session
= client
->session
;
1548 IAudioClient3_AddRef(&client
->IAudioClient3_iface
);
1554 static HRESULT WINAPI
AudioSessionControl_QueryInterface(
1555 IAudioSessionControl2
*iface
, REFIID riid
, void **ppv
)
1557 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
1563 if(IsEqualIID(riid
, &IID_IUnknown
) ||
1564 IsEqualIID(riid
, &IID_IAudioSessionControl
) ||
1565 IsEqualIID(riid
, &IID_IAudioSessionControl2
))
1568 IUnknown_AddRef((IUnknown
*)*ppv
);
1572 WARN("Unknown interface %s\n", debugstr_guid(riid
));
1573 return E_NOINTERFACE
;
1576 static ULONG WINAPI
AudioSessionControl_AddRef(IAudioSessionControl2
*iface
)
1578 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1580 ref
= InterlockedIncrement(&This
->ref
);
1581 TRACE("(%p) Refcount now %lu\n", This
, ref
);
1585 static ULONG WINAPI
AudioSessionControl_Release(IAudioSessionControl2
*iface
)
1587 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1590 EnterCriticalSection(&g_sessions_lock
);
1592 ref
= InterlockedDecrement(&This
->ref
);
1593 TRACE("(%p) Refcount now %lu\n", This
, ref
);
1596 This
->client
->session_wrapper
= NULL
;
1597 AudioClient_Release(&This
->client
->IAudioClient3_iface
);
1599 HeapFree(GetProcessHeap(), 0, This
);
1602 LeaveCriticalSection(&g_sessions_lock
);
1606 static HRESULT WINAPI
AudioSessionControl_GetState(IAudioSessionControl2
*iface
,
1607 AudioSessionState
*state
)
1609 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1610 struct is_started_params params
;
1613 TRACE("(%p)->(%p)\n", This
, state
);
1616 return NULL_PTR_ERR
;
1618 EnterCriticalSection(&g_sessions_lock
);
1620 if(list_empty(&This
->session
->clients
)){
1621 *state
= AudioSessionStateExpired
;
1622 LeaveCriticalSection(&g_sessions_lock
);
1626 LIST_FOR_EACH_ENTRY(client
, &This
->session
->clients
, ACImpl
, entry
){
1627 params
.stream
= client
->stream
;
1628 UNIX_CALL(is_started
, ¶ms
);
1629 if(params
.result
== S_OK
){
1630 *state
= AudioSessionStateActive
;
1631 LeaveCriticalSection(&g_sessions_lock
);
1636 LeaveCriticalSection(&g_sessions_lock
);
1638 *state
= AudioSessionStateInactive
;
1643 static HRESULT WINAPI
AudioSessionControl_GetDisplayName(
1644 IAudioSessionControl2
*iface
, WCHAR
**name
)
1646 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1648 FIXME("(%p)->(%p) - stub\n", This
, name
);
1653 static HRESULT WINAPI
AudioSessionControl_SetDisplayName(
1654 IAudioSessionControl2
*iface
, const WCHAR
*name
, const GUID
*session
)
1656 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1658 FIXME("(%p)->(%p, %s) - stub\n", This
, name
, debugstr_guid(session
));
1663 static HRESULT WINAPI
AudioSessionControl_GetIconPath(
1664 IAudioSessionControl2
*iface
, WCHAR
**path
)
1666 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1668 FIXME("(%p)->(%p) - stub\n", This
, path
);
1673 static HRESULT WINAPI
AudioSessionControl_SetIconPath(
1674 IAudioSessionControl2
*iface
, const WCHAR
*path
, const GUID
*session
)
1676 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1678 FIXME("(%p)->(%p, %s) - stub\n", This
, path
, debugstr_guid(session
));
1683 static HRESULT WINAPI
AudioSessionControl_GetGroupingParam(
1684 IAudioSessionControl2
*iface
, GUID
*group
)
1686 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1688 FIXME("(%p)->(%p) - stub\n", This
, group
);
1693 static HRESULT WINAPI
AudioSessionControl_SetGroupingParam(
1694 IAudioSessionControl2
*iface
, const GUID
*group
, const GUID
*session
)
1696 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1698 FIXME("(%p)->(%s, %s) - stub\n", This
, debugstr_guid(group
),
1699 debugstr_guid(session
));
1704 static HRESULT WINAPI
AudioSessionControl_RegisterAudioSessionNotification(
1705 IAudioSessionControl2
*iface
, IAudioSessionEvents
*events
)
1707 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1709 FIXME("(%p)->(%p) - stub\n", This
, events
);
1714 static HRESULT WINAPI
AudioSessionControl_UnregisterAudioSessionNotification(
1715 IAudioSessionControl2
*iface
, IAudioSessionEvents
*events
)
1717 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1719 FIXME("(%p)->(%p) - stub\n", This
, events
);
1724 static HRESULT WINAPI
AudioSessionControl_GetSessionIdentifier(
1725 IAudioSessionControl2
*iface
, WCHAR
**id
)
1727 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1729 FIXME("(%p)->(%p) - stub\n", This
, id
);
1734 static HRESULT WINAPI
AudioSessionControl_GetSessionInstanceIdentifier(
1735 IAudioSessionControl2
*iface
, WCHAR
**id
)
1737 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1739 FIXME("(%p)->(%p) - stub\n", This
, id
);
1744 static HRESULT WINAPI
AudioSessionControl_GetProcessId(
1745 IAudioSessionControl2
*iface
, DWORD
*pid
)
1747 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1749 TRACE("(%p)->(%p)\n", This
, pid
);
1754 *pid
= GetCurrentProcessId();
1759 static HRESULT WINAPI
AudioSessionControl_IsSystemSoundsSession(
1760 IAudioSessionControl2
*iface
)
1762 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1764 TRACE("(%p)\n", This
);
1769 static HRESULT WINAPI
AudioSessionControl_SetDuckingPreference(
1770 IAudioSessionControl2
*iface
, BOOL optout
)
1772 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1774 TRACE("(%p)->(%d)\n", This
, optout
);
1779 static const IAudioSessionControl2Vtbl AudioSessionControl2_Vtbl
=
1781 AudioSessionControl_QueryInterface
,
1782 AudioSessionControl_AddRef
,
1783 AudioSessionControl_Release
,
1784 AudioSessionControl_GetState
,
1785 AudioSessionControl_GetDisplayName
,
1786 AudioSessionControl_SetDisplayName
,
1787 AudioSessionControl_GetIconPath
,
1788 AudioSessionControl_SetIconPath
,
1789 AudioSessionControl_GetGroupingParam
,
1790 AudioSessionControl_SetGroupingParam
,
1791 AudioSessionControl_RegisterAudioSessionNotification
,
1792 AudioSessionControl_UnregisterAudioSessionNotification
,
1793 AudioSessionControl_GetSessionIdentifier
,
1794 AudioSessionControl_GetSessionInstanceIdentifier
,
1795 AudioSessionControl_GetProcessId
,
1796 AudioSessionControl_IsSystemSoundsSession
,
1797 AudioSessionControl_SetDuckingPreference
1800 static HRESULT WINAPI
SimpleAudioVolume_QueryInterface(
1801 ISimpleAudioVolume
*iface
, REFIID riid
, void **ppv
)
1803 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
1809 if(IsEqualIID(riid
, &IID_IUnknown
) ||
1810 IsEqualIID(riid
, &IID_ISimpleAudioVolume
))
1813 IUnknown_AddRef((IUnknown
*)*ppv
);
1817 WARN("Unknown interface %s\n", debugstr_guid(riid
));
1818 return E_NOINTERFACE
;
1821 static ULONG WINAPI
SimpleAudioVolume_AddRef(ISimpleAudioVolume
*iface
)
1823 AudioSessionWrapper
*This
= impl_from_ISimpleAudioVolume(iface
);
1824 return AudioSessionControl_AddRef(&This
->IAudioSessionControl2_iface
);
1827 static ULONG WINAPI
SimpleAudioVolume_Release(ISimpleAudioVolume
*iface
)
1829 AudioSessionWrapper
*This
= impl_from_ISimpleAudioVolume(iface
);
1830 return AudioSessionControl_Release(&This
->IAudioSessionControl2_iface
);
1833 static HRESULT WINAPI
SimpleAudioVolume_SetMasterVolume(
1834 ISimpleAudioVolume
*iface
, float level
, const GUID
*context
)
1836 AudioSessionWrapper
*This
= impl_from_ISimpleAudioVolume(iface
);
1837 AudioSession
*session
= This
->session
;
1840 TRACE("(%p)->(%f, %s)\n", session
, level
, wine_dbgstr_guid(context
));
1842 if(level
< 0.f
|| level
> 1.f
)
1843 return E_INVALIDARG
;
1846 FIXME("Notifications not supported yet\n");
1848 EnterCriticalSection(&g_sessions_lock
);
1850 session
->master_vol
= level
;
1852 LIST_FOR_EACH_ENTRY(client
, &session
->clients
, ACImpl
, entry
)
1853 set_stream_volumes(client
, -1);
1855 LeaveCriticalSection(&g_sessions_lock
);
1860 static HRESULT WINAPI
SimpleAudioVolume_GetMasterVolume(
1861 ISimpleAudioVolume
*iface
, float *level
)
1863 AudioSessionWrapper
*This
= impl_from_ISimpleAudioVolume(iface
);
1864 AudioSession
*session
= This
->session
;
1866 TRACE("(%p)->(%p)\n", session
, level
);
1869 return NULL_PTR_ERR
;
1871 *level
= session
->master_vol
;
1876 static HRESULT WINAPI
SimpleAudioVolume_SetMute(ISimpleAudioVolume
*iface
,
1877 BOOL mute
, const GUID
*context
)
1879 AudioSessionWrapper
*This
= impl_from_ISimpleAudioVolume(iface
);
1880 AudioSession
*session
= This
->session
;
1883 TRACE("(%p)->(%u, %s)\n", session
, mute
, debugstr_guid(context
));
1886 FIXME("Notifications not supported yet\n");
1888 EnterCriticalSection(&g_sessions_lock
);
1890 session
->mute
= mute
;
1892 LIST_FOR_EACH_ENTRY(client
, &session
->clients
, ACImpl
, entry
)
1893 set_stream_volumes(client
, -1);
1895 LeaveCriticalSection(&g_sessions_lock
);
1900 static HRESULT WINAPI
SimpleAudioVolume_GetMute(ISimpleAudioVolume
*iface
,
1903 AudioSessionWrapper
*This
= impl_from_ISimpleAudioVolume(iface
);
1904 AudioSession
*session
= This
->session
;
1906 TRACE("(%p)->(%p)\n", session
, mute
);
1909 return NULL_PTR_ERR
;
1911 *mute
= session
->mute
;
1916 static const ISimpleAudioVolumeVtbl SimpleAudioVolume_Vtbl
=
1918 SimpleAudioVolume_QueryInterface
,
1919 SimpleAudioVolume_AddRef
,
1920 SimpleAudioVolume_Release
,
1921 SimpleAudioVolume_SetMasterVolume
,
1922 SimpleAudioVolume_GetMasterVolume
,
1923 SimpleAudioVolume_SetMute
,
1924 SimpleAudioVolume_GetMute
1927 static HRESULT WINAPI
AudioStreamVolume_QueryInterface(
1928 IAudioStreamVolume
*iface
, REFIID riid
, void **ppv
)
1930 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
1936 if(IsEqualIID(riid
, &IID_IUnknown
) ||
1937 IsEqualIID(riid
, &IID_IAudioStreamVolume
))
1940 IUnknown_AddRef((IUnknown
*)*ppv
);
1944 WARN("Unknown interface %s\n", debugstr_guid(riid
));
1945 return E_NOINTERFACE
;
1948 static ULONG WINAPI
AudioStreamVolume_AddRef(IAudioStreamVolume
*iface
)
1950 ACImpl
*This
= impl_from_IAudioStreamVolume(iface
);
1951 return IAudioClient3_AddRef(&This
->IAudioClient3_iface
);
1954 static ULONG WINAPI
AudioStreamVolume_Release(IAudioStreamVolume
*iface
)
1956 ACImpl
*This
= impl_from_IAudioStreamVolume(iface
);
1957 return IAudioClient3_Release(&This
->IAudioClient3_iface
);
1960 static HRESULT WINAPI
AudioStreamVolume_GetChannelCount(
1961 IAudioStreamVolume
*iface
, UINT32
*out
)
1963 ACImpl
*This
= impl_from_IAudioStreamVolume(iface
);
1965 TRACE("(%p)->(%p)\n", This
, out
);
1970 *out
= This
->channel_count
;
1975 static HRESULT WINAPI
AudioStreamVolume_SetChannelVolume(
1976 IAudioStreamVolume
*iface
, UINT32 index
, float level
)
1978 ACImpl
*This
= impl_from_IAudioStreamVolume(iface
);
1980 TRACE("(%p)->(%d, %f)\n", This
, index
, level
);
1982 if(level
< 0.f
|| level
> 1.f
)
1983 return E_INVALIDARG
;
1985 if(index
>= This
->channel_count
)
1986 return E_INVALIDARG
;
1988 EnterCriticalSection(&g_sessions_lock
);
1990 This
->vols
[index
] = level
;
1992 WARN("CoreAudio doesn't support per-channel volume control\n");
1993 set_stream_volumes(This
, index
);
1995 LeaveCriticalSection(&g_sessions_lock
);
2000 static HRESULT WINAPI
AudioStreamVolume_GetChannelVolume(
2001 IAudioStreamVolume
*iface
, UINT32 index
, float *level
)
2003 ACImpl
*This
= impl_from_IAudioStreamVolume(iface
);
2005 TRACE("(%p)->(%d, %p)\n", This
, index
, level
);
2010 if(index
>= This
->channel_count
)
2011 return E_INVALIDARG
;
2013 *level
= This
->vols
[index
];
2018 static HRESULT WINAPI
AudioStreamVolume_SetAllVolumes(
2019 IAudioStreamVolume
*iface
, UINT32 count
, const float *levels
)
2021 ACImpl
*This
= impl_from_IAudioStreamVolume(iface
);
2024 TRACE("(%p)->(%d, %p)\n", This
, count
, levels
);
2029 if(count
!= This
->channel_count
)
2030 return E_INVALIDARG
;
2032 EnterCriticalSection(&g_sessions_lock
);
2034 for(i
= 0; i
< count
; ++i
)
2035 This
->vols
[i
] = levels
[i
];
2037 set_stream_volumes(This
, -1);
2039 LeaveCriticalSection(&g_sessions_lock
);
2044 static HRESULT WINAPI
AudioStreamVolume_GetAllVolumes(
2045 IAudioStreamVolume
*iface
, UINT32 count
, float *levels
)
2047 ACImpl
*This
= impl_from_IAudioStreamVolume(iface
);
2050 TRACE("(%p)->(%d, %p)\n", This
, count
, levels
);
2055 if(count
!= This
->channel_count
)
2056 return E_INVALIDARG
;
2058 EnterCriticalSection(&g_sessions_lock
);
2060 for(i
= 0; i
< count
; ++i
)
2061 levels
[i
] = This
->vols
[i
];
2063 LeaveCriticalSection(&g_sessions_lock
);
2068 static const IAudioStreamVolumeVtbl AudioStreamVolume_Vtbl
=
2070 AudioStreamVolume_QueryInterface
,
2071 AudioStreamVolume_AddRef
,
2072 AudioStreamVolume_Release
,
2073 AudioStreamVolume_GetChannelCount
,
2074 AudioStreamVolume_SetChannelVolume
,
2075 AudioStreamVolume_GetChannelVolume
,
2076 AudioStreamVolume_SetAllVolumes
,
2077 AudioStreamVolume_GetAllVolumes
2080 static HRESULT WINAPI
ChannelAudioVolume_QueryInterface(
2081 IChannelAudioVolume
*iface
, REFIID riid
, void **ppv
)
2083 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
2089 if(IsEqualIID(riid
, &IID_IUnknown
) ||
2090 IsEqualIID(riid
, &IID_IChannelAudioVolume
))
2093 IUnknown_AddRef((IUnknown
*)*ppv
);
2097 WARN("Unknown interface %s\n", debugstr_guid(riid
));
2098 return E_NOINTERFACE
;
2101 static ULONG WINAPI
ChannelAudioVolume_AddRef(IChannelAudioVolume
*iface
)
2103 AudioSessionWrapper
*This
= impl_from_IChannelAudioVolume(iface
);
2104 return AudioSessionControl_AddRef(&This
->IAudioSessionControl2_iface
);
2107 static ULONG WINAPI
ChannelAudioVolume_Release(IChannelAudioVolume
*iface
)
2109 AudioSessionWrapper
*This
= impl_from_IChannelAudioVolume(iface
);
2110 return AudioSessionControl_Release(&This
->IAudioSessionControl2_iface
);
2113 static HRESULT WINAPI
ChannelAudioVolume_GetChannelCount(
2114 IChannelAudioVolume
*iface
, UINT32
*out
)
2116 AudioSessionWrapper
*This
= impl_from_IChannelAudioVolume(iface
);
2117 AudioSession
*session
= This
->session
;
2119 TRACE("(%p)->(%p)\n", session
, out
);
2122 return NULL_PTR_ERR
;
2124 *out
= session
->channel_count
;
2129 static HRESULT WINAPI
ChannelAudioVolume_SetChannelVolume(
2130 IChannelAudioVolume
*iface
, UINT32 index
, float level
,
2131 const GUID
*context
)
2133 AudioSessionWrapper
*This
= impl_from_IChannelAudioVolume(iface
);
2134 AudioSession
*session
= This
->session
;
2137 TRACE("(%p)->(%d, %f, %s)\n", session
, index
, level
,
2138 wine_dbgstr_guid(context
));
2140 if(level
< 0.f
|| level
> 1.f
)
2141 return E_INVALIDARG
;
2143 if(index
>= session
->channel_count
)
2144 return E_INVALIDARG
;
2147 FIXME("Notifications not supported yet\n");
2149 EnterCriticalSection(&g_sessions_lock
);
2151 session
->channel_vols
[index
] = level
;
2153 WARN("CoreAudio doesn't support per-channel volume control\n");
2154 LIST_FOR_EACH_ENTRY(client
, &session
->clients
, ACImpl
, entry
)
2155 set_stream_volumes(client
, index
);
2157 LeaveCriticalSection(&g_sessions_lock
);
2162 static HRESULT WINAPI
ChannelAudioVolume_GetChannelVolume(
2163 IChannelAudioVolume
*iface
, UINT32 index
, float *level
)
2165 AudioSessionWrapper
*This
= impl_from_IChannelAudioVolume(iface
);
2166 AudioSession
*session
= This
->session
;
2168 TRACE("(%p)->(%d, %p)\n", session
, index
, level
);
2171 return NULL_PTR_ERR
;
2173 if(index
>= session
->channel_count
)
2174 return E_INVALIDARG
;
2176 *level
= session
->channel_vols
[index
];
2181 static HRESULT WINAPI
ChannelAudioVolume_SetAllVolumes(
2182 IChannelAudioVolume
*iface
, UINT32 count
, const float *levels
,
2183 const GUID
*context
)
2185 AudioSessionWrapper
*This
= impl_from_IChannelAudioVolume(iface
);
2186 AudioSession
*session
= This
->session
;
2190 TRACE("(%p)->(%d, %p, %s)\n", session
, count
, levels
,
2191 wine_dbgstr_guid(context
));
2194 return NULL_PTR_ERR
;
2196 if(count
!= session
->channel_count
)
2197 return E_INVALIDARG
;
2200 FIXME("Notifications not supported yet\n");
2202 EnterCriticalSection(&g_sessions_lock
);
2204 for(i
= 0; i
< count
; ++i
)
2205 session
->channel_vols
[i
] = levels
[i
];
2207 LIST_FOR_EACH_ENTRY(client
, &session
->clients
, ACImpl
, entry
)
2208 set_stream_volumes(client
, -1);
2210 LeaveCriticalSection(&g_sessions_lock
);
2215 static HRESULT WINAPI
ChannelAudioVolume_GetAllVolumes(
2216 IChannelAudioVolume
*iface
, UINT32 count
, float *levels
)
2218 AudioSessionWrapper
*This
= impl_from_IChannelAudioVolume(iface
);
2219 AudioSession
*session
= This
->session
;
2222 TRACE("(%p)->(%d, %p)\n", session
, count
, levels
);
2225 return NULL_PTR_ERR
;
2227 if(count
!= session
->channel_count
)
2228 return E_INVALIDARG
;
2230 for(i
= 0; i
< count
; ++i
)
2231 levels
[i
] = session
->channel_vols
[i
];
2236 static const IChannelAudioVolumeVtbl ChannelAudioVolume_Vtbl
=
2238 ChannelAudioVolume_QueryInterface
,
2239 ChannelAudioVolume_AddRef
,
2240 ChannelAudioVolume_Release
,
2241 ChannelAudioVolume_GetChannelCount
,
2242 ChannelAudioVolume_SetChannelVolume
,
2243 ChannelAudioVolume_GetChannelVolume
,
2244 ChannelAudioVolume_SetAllVolumes
,
2245 ChannelAudioVolume_GetAllVolumes
2248 static HRESULT WINAPI
AudioSessionManager_QueryInterface(IAudioSessionManager2
*iface
,
2249 REFIID riid
, void **ppv
)
2251 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
2257 if(IsEqualIID(riid
, &IID_IUnknown
) ||
2258 IsEqualIID(riid
, &IID_IAudioSessionManager
) ||
2259 IsEqualIID(riid
, &IID_IAudioSessionManager2
))
2262 IUnknown_AddRef((IUnknown
*)*ppv
);
2266 WARN("Unknown interface %s\n", debugstr_guid(riid
));
2267 return E_NOINTERFACE
;
2270 static ULONG WINAPI
AudioSessionManager_AddRef(IAudioSessionManager2
*iface
)
2272 SessionMgr
*This
= impl_from_IAudioSessionManager2(iface
);
2274 ref
= InterlockedIncrement(&This
->ref
);
2275 TRACE("(%p) Refcount now %lu\n", This
, ref
);
2279 static ULONG WINAPI
AudioSessionManager_Release(IAudioSessionManager2
*iface
)
2281 SessionMgr
*This
= impl_from_IAudioSessionManager2(iface
);
2283 ref
= InterlockedDecrement(&This
->ref
);
2284 TRACE("(%p) Refcount now %lu\n", This
, ref
);
2286 HeapFree(GetProcessHeap(), 0, This
);
2290 static HRESULT WINAPI
AudioSessionManager_GetAudioSessionControl(
2291 IAudioSessionManager2
*iface
, const GUID
*session_guid
, DWORD flags
,
2292 IAudioSessionControl
**out
)
2294 SessionMgr
*This
= impl_from_IAudioSessionManager2(iface
);
2295 AudioSession
*session
;
2296 AudioSessionWrapper
*wrapper
;
2299 TRACE("(%p)->(%s, %lx, %p)\n", This
, debugstr_guid(session_guid
),
2302 hr
= get_audio_session(session_guid
, This
->device
, 0, &session
);
2306 wrapper
= AudioSessionWrapper_Create(NULL
);
2308 return E_OUTOFMEMORY
;
2310 wrapper
->session
= session
;
2312 *out
= (IAudioSessionControl
*)&wrapper
->IAudioSessionControl2_iface
;
2317 static HRESULT WINAPI
AudioSessionManager_GetSimpleAudioVolume(
2318 IAudioSessionManager2
*iface
, const GUID
*session_guid
, DWORD flags
,
2319 ISimpleAudioVolume
**out
)
2321 SessionMgr
*This
= impl_from_IAudioSessionManager2(iface
);
2322 AudioSession
*session
;
2323 AudioSessionWrapper
*wrapper
;
2326 TRACE("(%p)->(%s, %lx, %p)\n", This
, debugstr_guid(session_guid
),
2329 hr
= get_audio_session(session_guid
, This
->device
, 0, &session
);
2333 wrapper
= AudioSessionWrapper_Create(NULL
);
2335 return E_OUTOFMEMORY
;
2337 wrapper
->session
= session
;
2339 *out
= &wrapper
->ISimpleAudioVolume_iface
;
2344 static HRESULT WINAPI
AudioSessionManager_GetSessionEnumerator(
2345 IAudioSessionManager2
*iface
, IAudioSessionEnumerator
**out
)
2347 SessionMgr
*This
= impl_from_IAudioSessionManager2(iface
);
2348 FIXME("(%p)->(%p) - stub\n", This
, out
);
2352 static HRESULT WINAPI
AudioSessionManager_RegisterSessionNotification(
2353 IAudioSessionManager2
*iface
, IAudioSessionNotification
*notification
)
2355 SessionMgr
*This
= impl_from_IAudioSessionManager2(iface
);
2356 FIXME("(%p)->(%p) - stub\n", This
, notification
);
2360 static HRESULT WINAPI
AudioSessionManager_UnregisterSessionNotification(
2361 IAudioSessionManager2
*iface
, IAudioSessionNotification
*notification
)
2363 SessionMgr
*This
= impl_from_IAudioSessionManager2(iface
);
2364 FIXME("(%p)->(%p) - stub\n", This
, notification
);
2368 static HRESULT WINAPI
AudioSessionManager_RegisterDuckNotification(
2369 IAudioSessionManager2
*iface
, const WCHAR
*session_id
,
2370 IAudioVolumeDuckNotification
*notification
)
2372 SessionMgr
*This
= impl_from_IAudioSessionManager2(iface
);
2373 FIXME("(%p)->(%p) - stub\n", This
, notification
);
2377 static HRESULT WINAPI
AudioSessionManager_UnregisterDuckNotification(
2378 IAudioSessionManager2
*iface
,
2379 IAudioVolumeDuckNotification
*notification
)
2381 SessionMgr
*This
= impl_from_IAudioSessionManager2(iface
);
2382 FIXME("(%p)->(%p) - stub\n", This
, notification
);
2386 static const IAudioSessionManager2Vtbl AudioSessionManager2_Vtbl
=
2388 AudioSessionManager_QueryInterface
,
2389 AudioSessionManager_AddRef
,
2390 AudioSessionManager_Release
,
2391 AudioSessionManager_GetAudioSessionControl
,
2392 AudioSessionManager_GetSimpleAudioVolume
,
2393 AudioSessionManager_GetSessionEnumerator
,
2394 AudioSessionManager_RegisterSessionNotification
,
2395 AudioSessionManager_UnregisterSessionNotification
,
2396 AudioSessionManager_RegisterDuckNotification
,
2397 AudioSessionManager_UnregisterDuckNotification
2400 HRESULT WINAPI
AUDDRV_GetAudioSessionManager(IMMDevice
*device
,
2401 IAudioSessionManager2
**out
)
2405 This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(SessionMgr
));
2407 return E_OUTOFMEMORY
;
2409 This
->IAudioSessionManager2_iface
.lpVtbl
= &AudioSessionManager2_Vtbl
;
2410 This
->device
= device
;
2413 *out
= &This
->IAudioSessionManager2_iface
;