2 * Copyright 2011 Andrew Eikum 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
30 #include "mmdeviceapi.h"
36 #include "endpointvolume.h"
37 #include "audiopolicy.h"
38 #include "audioclient.h"
40 #include "wine/debug.h"
41 #include "wine/list.h"
42 #include "wine/unixlib.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(oss
);
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
;
101 AudioSession
*session
;
102 AudioSessionWrapper
*session_wrapper
;
110 typedef struct _SessionMgr
{
111 IAudioSessionManager2 IAudioSessionManager2_iface
;
118 typedef struct _OSSDevice
{
125 static struct list g_devices
= LIST_INIT(g_devices
);
127 static const WCHAR drv_key_devicesW
[] = {'S','o','f','t','w','a','r','e','\\',
128 'W','i','n','e','\\','D','r','i','v','e','r','s','\\',
129 'w','i','n','e','o','s','s','.','d','r','v','\\','d','e','v','i','c','e','s',0};
130 static const WCHAR guidW
[] = {'g','u','i','d',0};
132 static CRITICAL_SECTION g_sessions_lock
;
133 static CRITICAL_SECTION_DEBUG g_sessions_lock_debug
=
135 0, 0, &g_sessions_lock
,
136 { &g_sessions_lock_debug
.ProcessLocksList
, &g_sessions_lock_debug
.ProcessLocksList
},
137 0, 0, { (DWORD_PTR
)(__FILE__
": g_sessions_lock") }
139 static CRITICAL_SECTION g_sessions_lock
= { &g_sessions_lock_debug
, -1, 0, 0, 0, 0 };
140 static struct list g_sessions
= LIST_INIT(g_sessions
);
142 static AudioSessionWrapper
*AudioSessionWrapper_Create(ACImpl
*client
);
144 static const IAudioClient3Vtbl AudioClient3_Vtbl
;
145 static const IAudioRenderClientVtbl AudioRenderClient_Vtbl
;
146 static const IAudioCaptureClientVtbl AudioCaptureClient_Vtbl
;
147 static const IAudioSessionControl2Vtbl AudioSessionControl2_Vtbl
;
148 static const ISimpleAudioVolumeVtbl SimpleAudioVolume_Vtbl
;
149 static const IAudioClockVtbl AudioClock_Vtbl
;
150 static const IAudioClock2Vtbl AudioClock2_Vtbl
;
151 static const IAudioStreamVolumeVtbl AudioStreamVolume_Vtbl
;
152 static const IChannelAudioVolumeVtbl ChannelAudioVolume_Vtbl
;
153 static const IAudioSessionManager2Vtbl AudioSessionManager2_Vtbl
;
155 static inline ACImpl
*impl_from_IAudioClient3(IAudioClient3
*iface
)
157 return CONTAINING_RECORD(iface
, ACImpl
, IAudioClient3_iface
);
160 static inline ACImpl
*impl_from_IAudioRenderClient(IAudioRenderClient
*iface
)
162 return CONTAINING_RECORD(iface
, ACImpl
, IAudioRenderClient_iface
);
165 static inline ACImpl
*impl_from_IAudioCaptureClient(IAudioCaptureClient
*iface
)
167 return CONTAINING_RECORD(iface
, ACImpl
, IAudioCaptureClient_iface
);
170 static inline AudioSessionWrapper
*impl_from_IAudioSessionControl2(IAudioSessionControl2
*iface
)
172 return CONTAINING_RECORD(iface
, AudioSessionWrapper
, IAudioSessionControl2_iface
);
175 static inline AudioSessionWrapper
*impl_from_ISimpleAudioVolume(ISimpleAudioVolume
*iface
)
177 return CONTAINING_RECORD(iface
, AudioSessionWrapper
, ISimpleAudioVolume_iface
);
180 static inline AudioSessionWrapper
*impl_from_IChannelAudioVolume(IChannelAudioVolume
*iface
)
182 return CONTAINING_RECORD(iface
, AudioSessionWrapper
, IChannelAudioVolume_iface
);
185 static inline ACImpl
*impl_from_IAudioClock(IAudioClock
*iface
)
187 return CONTAINING_RECORD(iface
, ACImpl
, IAudioClock_iface
);
190 static inline ACImpl
*impl_from_IAudioClock2(IAudioClock2
*iface
)
192 return CONTAINING_RECORD(iface
, ACImpl
, IAudioClock2_iface
);
195 static inline ACImpl
*impl_from_IAudioStreamVolume(IAudioStreamVolume
*iface
)
197 return CONTAINING_RECORD(iface
, ACImpl
, IAudioStreamVolume_iface
);
200 static inline SessionMgr
*impl_from_IAudioSessionManager2(IAudioSessionManager2
*iface
)
202 return CONTAINING_RECORD(iface
, SessionMgr
, IAudioSessionManager2_iface
);
205 BOOL WINAPI
DllMain(HINSTANCE dll
, DWORD reason
, void *reserved
)
209 case DLL_PROCESS_ATTACH
:
210 if(__wine_init_unix_call()) return FALSE
;
213 case DLL_PROCESS_DETACH
:
216 OSSDevice
*iter
, *iter2
;
218 DeleteCriticalSection(&g_sessions_lock
);
220 LIST_FOR_EACH_ENTRY_SAFE(iter
, iter2
, &g_devices
, OSSDevice
, entry
){
221 HeapFree(GetProcessHeap(), 0, iter
);
229 int WINAPI
AUDDRV_GetPriority(void)
231 struct test_connect_params params
;
235 OSS_CALL(test_connect
, ¶ms
);
237 return params
.priority
;
240 static HRESULT
stream_release(stream_handle stream
, HANDLE timer_thread
)
242 struct release_stream_params params
;
244 params
.stream
= stream
;
245 params
.timer_thread
= timer_thread
;
246 OSS_CALL(release_stream
, ¶ms
);
248 return params
.result
;
251 static DWORD WINAPI
timer_thread(void *user
)
253 struct timer_loop_params params
;
254 struct ACImpl
*This
= user
;
256 params
.stream
= This
->stream
;
257 OSS_CALL(timer_loop
, ¶ms
);
262 static void set_device_guid(EDataFlow flow
, HKEY drv_key
, const WCHAR
*key_name
,
270 lr
= RegCreateKeyExW(HKEY_CURRENT_USER
, drv_key_devicesW
, 0, NULL
, 0, KEY_WRITE
,
271 NULL
, &drv_key
, NULL
);
272 if(lr
!= ERROR_SUCCESS
){
273 ERR("RegCreateKeyEx(drv_key) failed: %lu\n", lr
);
279 lr
= RegCreateKeyExW(drv_key
, key_name
, 0, NULL
, 0, KEY_WRITE
,
281 if(lr
!= ERROR_SUCCESS
){
282 ERR("RegCreateKeyEx(%s) failed: %lu\n", wine_dbgstr_w(key_name
), lr
);
286 lr
= RegSetValueExW(key
, guidW
, 0, REG_BINARY
, (BYTE
*)guid
,
288 if(lr
!= ERROR_SUCCESS
)
289 ERR("RegSetValueEx(%s\\guid) failed: %lu\n", wine_dbgstr_w(key_name
), lr
);
294 RegCloseKey(drv_key
);
297 static void get_device_guid(EDataFlow flow
, const char *device
, GUID
*guid
)
299 HKEY key
= NULL
, dev_key
;
300 DWORD type
, size
= sizeof(*guid
);
308 MultiByteToWideChar(CP_UNIXCP
, 0, device
, -1, key_name
+ 2, ARRAY_SIZE(key_name
) - 2);
310 if(RegOpenKeyExW(HKEY_CURRENT_USER
, drv_key_devicesW
, 0, KEY_WRITE
|KEY_READ
, &key
) == ERROR_SUCCESS
){
311 if(RegOpenKeyExW(key
, key_name
, 0, KEY_READ
, &dev_key
) == ERROR_SUCCESS
){
312 if(RegQueryValueExW(dev_key
, guidW
, 0, &type
,
313 (BYTE
*)guid
, &size
) == ERROR_SUCCESS
){
314 if(type
== REG_BINARY
){
315 RegCloseKey(dev_key
);
319 ERR("Invalid type for device %s GUID: %lu; ignoring and overwriting\n",
320 wine_dbgstr_w(key_name
), type
);
322 RegCloseKey(dev_key
);
328 set_device_guid(flow
, key
, key_name
, guid
);
334 static void set_stream_volumes(ACImpl
*This
)
336 struct set_volumes_params params
;
338 params
.stream
= This
->stream
;
339 params
.master_volume
= (This
->session
->mute
? 0.0f
: This
->session
->master_vol
);
340 params
.volumes
= This
->vols
;
341 params
.session_volumes
= This
->session
->channel_vols
;
343 OSS_CALL(set_volumes
, ¶ms
);
346 static const OSSDevice
*get_ossdevice_from_guid(const GUID
*guid
)
349 LIST_FOR_EACH_ENTRY(dev_item
, &g_devices
, OSSDevice
, entry
)
350 if(IsEqualGUID(guid
, &dev_item
->guid
))
355 static void device_add(OSSDevice
*oss_dev
)
357 if(get_ossdevice_from_guid(&oss_dev
->guid
)) /* already in list */
358 HeapFree(GetProcessHeap(), 0, oss_dev
);
360 list_add_tail(&g_devices
, &oss_dev
->entry
);
363 HRESULT WINAPI
AUDDRV_GetEndpointIDs(EDataFlow flow
, WCHAR
***ids_out
, GUID
**guids_out
,
364 UINT
*num
, UINT
*def_index
)
366 struct get_endpoint_ids_params params
;
371 TRACE("%d %p %p %p %p\n", flow
, ids
, guids
, num
, def_index
);
375 params
.endpoints
= NULL
;
377 HeapFree(GetProcessHeap(), 0, params
.endpoints
);
378 params
.endpoints
= HeapAlloc(GetProcessHeap(), 0, params
.size
);
379 OSS_CALL(get_endpoint_ids
, ¶ms
);
380 }while(params
.result
== HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER
));
382 if(FAILED(params
.result
)) goto end
;
384 ids
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, params
.num
* sizeof(*ids
));
385 guids
= HeapAlloc(GetProcessHeap(), 0, params
.num
* sizeof(*guids
));
387 params
.result
= E_OUTOFMEMORY
;
391 for(i
= 0; i
< params
.num
; i
++){
392 WCHAR
*name
= (WCHAR
*)((char *)params
.endpoints
+ params
.endpoints
[i
].name
);
393 char *device
= (char *)params
.endpoints
+ params
.endpoints
[i
].device
;
394 unsigned int name_size
= (wcslen(name
) + 1) * sizeof(WCHAR
);
395 unsigned int dev_size
= strlen(device
) + 1;
398 ids
[i
] = HeapAlloc(GetProcessHeap(), 0, name_size
);
399 oss_dev
= HeapAlloc(GetProcessHeap(), 0, offsetof(OSSDevice
, devnode
[dev_size
]));
400 if(!ids
[i
] || !oss_dev
){
401 HeapFree(GetProcessHeap(), 0, oss_dev
);
402 params
.result
= E_OUTOFMEMORY
;
405 memcpy(ids
[i
], name
, name_size
);
406 get_device_guid(flow
, device
, guids
+ i
);
408 oss_dev
->flow
= flow
;
409 oss_dev
->guid
= guids
[i
];
410 memcpy(oss_dev
->devnode
, device
, dev_size
);
413 *def_index
= params
.default_idx
;
416 HeapFree(GetProcessHeap(), 0, params
.endpoints
);
417 if(FAILED(params
.result
)){
418 HeapFree(GetProcessHeap(), 0, guids
);
420 for(i
= 0; i
< params
.num
; i
++)
421 HeapFree(GetProcessHeap(), 0, ids
[i
]);
422 HeapFree(GetProcessHeap(), 0, ids
);
430 return params
.result
;
433 HRESULT WINAPI
AUDDRV_GetAudioEndpoint(GUID
*guid
, IMMDevice
*dev
,
437 const OSSDevice
*oss_dev
;
441 TRACE("%s %p %p\n", debugstr_guid(guid
), dev
, out
);
443 oss_dev
= get_ossdevice_from_guid(guid
);
445 WARN("Unknown GUID: %s\n", debugstr_guid(guid
));
446 return AUDCLNT_E_DEVICE_INVALIDATED
;
448 len
= strlen(oss_dev
->devnode
);
449 This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, offsetof(ACImpl
, devnode
[len
+ 1]));
451 return E_OUTOFMEMORY
;
453 hr
= CoCreateFreeThreadedMarshaler((IUnknown
*)&This
->IAudioClient3_iface
, &This
->pUnkFTMarshal
);
455 HeapFree(GetProcessHeap(), 0, This
);
459 This
->dataflow
= oss_dev
->flow
;
460 strcpy(This
->devnode
, oss_dev
->devnode
);
462 This
->IAudioClient3_iface
.lpVtbl
= &AudioClient3_Vtbl
;
463 This
->IAudioRenderClient_iface
.lpVtbl
= &AudioRenderClient_Vtbl
;
464 This
->IAudioCaptureClient_iface
.lpVtbl
= &AudioCaptureClient_Vtbl
;
465 This
->IAudioClock_iface
.lpVtbl
= &AudioClock_Vtbl
;
466 This
->IAudioClock2_iface
.lpVtbl
= &AudioClock2_Vtbl
;
467 This
->IAudioStreamVolume_iface
.lpVtbl
= &AudioStreamVolume_Vtbl
;
470 IMMDevice_AddRef(This
->parent
);
472 *out
= (IAudioClient
*)&This
->IAudioClient3_iface
;
473 IAudioClient3_AddRef(&This
->IAudioClient3_iface
);
478 static HRESULT WINAPI
AudioClient_QueryInterface(IAudioClient3
*iface
,
479 REFIID riid
, void **ppv
)
481 ACImpl
*This
= impl_from_IAudioClient3(iface
);
482 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
487 if(IsEqualIID(riid
, &IID_IUnknown
) ||
488 IsEqualIID(riid
, &IID_IAudioClient
) ||
489 IsEqualIID(riid
, &IID_IAudioClient2
) ||
490 IsEqualIID(riid
, &IID_IAudioClient3
))
492 else if(IsEqualIID(riid
, &IID_IMarshal
))
493 return IUnknown_QueryInterface(This
->pUnkFTMarshal
, riid
, ppv
);
495 IUnknown_AddRef((IUnknown
*)*ppv
);
498 WARN("Unknown interface %s\n", debugstr_guid(riid
));
499 return E_NOINTERFACE
;
502 static ULONG WINAPI
AudioClient_AddRef(IAudioClient3
*iface
)
504 ACImpl
*This
= impl_from_IAudioClient3(iface
);
506 ref
= InterlockedIncrement(&This
->ref
);
507 TRACE("(%p) Refcount now %lu\n", This
, ref
);
511 static ULONG WINAPI
AudioClient_Release(IAudioClient3
*iface
)
513 ACImpl
*This
= impl_from_IAudioClient3(iface
);
516 ref
= InterlockedDecrement(&This
->ref
);
517 TRACE("(%p) Refcount now %lu\n", This
, ref
);
519 IAudioClient3_Stop(iface
);
520 IMMDevice_Release(This
->parent
);
521 IUnknown_Release(This
->pUnkFTMarshal
);
523 EnterCriticalSection(&g_sessions_lock
);
524 list_remove(&This
->entry
);
525 LeaveCriticalSection(&g_sessions_lock
);
527 HeapFree(GetProcessHeap(), 0, This
->vols
);
529 stream_release(This
->stream
, This
->timer_thread
);
530 HeapFree(GetProcessHeap(), 0, This
);
535 static void dump_fmt(const WAVEFORMATEX
*fmt
)
537 TRACE("wFormatTag: 0x%x (", fmt
->wFormatTag
);
538 switch(fmt
->wFormatTag
){
539 case WAVE_FORMAT_PCM
:
540 TRACE("WAVE_FORMAT_PCM");
542 case WAVE_FORMAT_IEEE_FLOAT
:
543 TRACE("WAVE_FORMAT_IEEE_FLOAT");
545 case WAVE_FORMAT_EXTENSIBLE
:
546 TRACE("WAVE_FORMAT_EXTENSIBLE");
554 TRACE("nChannels: %u\n", fmt
->nChannels
);
555 TRACE("nSamplesPerSec: %lu\n", fmt
->nSamplesPerSec
);
556 TRACE("nAvgBytesPerSec: %lu\n", fmt
->nAvgBytesPerSec
);
557 TRACE("nBlockAlign: %u\n", fmt
->nBlockAlign
);
558 TRACE("wBitsPerSample: %u\n", fmt
->wBitsPerSample
);
559 TRACE("cbSize: %u\n", fmt
->cbSize
);
561 if(fmt
->wFormatTag
== WAVE_FORMAT_EXTENSIBLE
){
562 WAVEFORMATEXTENSIBLE
*fmtex
= (void*)fmt
;
563 TRACE("dwChannelMask: %08lx\n", fmtex
->dwChannelMask
);
564 TRACE("Samples: %04x\n", fmtex
->Samples
.wReserved
);
565 TRACE("SubFormat: %s\n", wine_dbgstr_guid(&fmtex
->SubFormat
));
569 static void session_init_vols(AudioSession
*session
, UINT channels
)
571 if(session
->channel_count
< channels
){
574 if(session
->channel_vols
)
575 session
->channel_vols
= HeapReAlloc(GetProcessHeap(), 0,
576 session
->channel_vols
, sizeof(float) * channels
);
578 session
->channel_vols
= HeapAlloc(GetProcessHeap(), 0,
579 sizeof(float) * channels
);
580 if(!session
->channel_vols
)
583 for(i
= session
->channel_count
; i
< channels
; ++i
)
584 session
->channel_vols
[i
] = 1.f
;
586 session
->channel_count
= channels
;
590 static AudioSession
*create_session(const GUID
*guid
, IMMDevice
*device
,
595 ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(AudioSession
));
599 memcpy(&ret
->guid
, guid
, sizeof(GUID
));
601 ret
->device
= device
;
603 list_init(&ret
->clients
);
605 list_add_head(&g_sessions
, &ret
->entry
);
607 session_init_vols(ret
, num_channels
);
609 ret
->master_vol
= 1.f
;
614 /* if channels == 0, then this will return or create a session with
615 * matching dataflow and GUID. otherwise, channels must also match */
616 static HRESULT
get_audio_session(const GUID
*sessionguid
,
617 IMMDevice
*device
, UINT channels
, AudioSession
**out
)
619 AudioSession
*session
;
621 if(!sessionguid
|| IsEqualGUID(sessionguid
, &GUID_NULL
)){
622 *out
= create_session(&GUID_NULL
, device
, channels
);
624 return E_OUTOFMEMORY
;
630 LIST_FOR_EACH_ENTRY(session
, &g_sessions
, AudioSession
, entry
){
631 if(session
->device
== device
&&
632 IsEqualGUID(sessionguid
, &session
->guid
)){
633 session_init_vols(session
, channels
);
640 *out
= create_session(sessionguid
, device
, channels
);
642 return E_OUTOFMEMORY
;
648 static HRESULT WINAPI
AudioClient_Initialize(IAudioClient3
*iface
,
649 AUDCLNT_SHAREMODE mode
, DWORD flags
, REFERENCE_TIME duration
,
650 REFERENCE_TIME period
, const WAVEFORMATEX
*fmt
,
651 const GUID
*sessionguid
)
653 ACImpl
*This
= impl_from_IAudioClient3(iface
);
654 struct create_stream_params params
;
655 stream_handle stream
;
658 TRACE("(%p)->(%x, %lx, %s, %s, %p, %s)\n", This
, mode
, flags
,
659 wine_dbgstr_longlong(duration
), wine_dbgstr_longlong(period
), fmt
, debugstr_guid(sessionguid
));
666 if(mode
!= AUDCLNT_SHAREMODE_SHARED
&& mode
!= AUDCLNT_SHAREMODE_EXCLUSIVE
)
669 if(flags
& ~(AUDCLNT_STREAMFLAGS_CROSSPROCESS
|
670 AUDCLNT_STREAMFLAGS_LOOPBACK
|
671 AUDCLNT_STREAMFLAGS_EVENTCALLBACK
|
672 AUDCLNT_STREAMFLAGS_NOPERSIST
|
673 AUDCLNT_STREAMFLAGS_RATEADJUST
|
674 AUDCLNT_SESSIONFLAGS_EXPIREWHENUNOWNED
|
675 AUDCLNT_SESSIONFLAGS_DISPLAY_HIDE
|
676 AUDCLNT_SESSIONFLAGS_DISPLAY_HIDEWHENEXPIRED
|
677 AUDCLNT_STREAMFLAGS_SRC_DEFAULT_QUALITY
|
678 AUDCLNT_STREAMFLAGS_AUTOCONVERTPCM
)){
679 FIXME("Unknown flags: %08lx\n", flags
);
683 if(mode
== AUDCLNT_SHAREMODE_SHARED
){
684 period
= DefaultPeriod
;
685 if( duration
< 3 * period
)
686 duration
= 3 * period
;
689 period
= DefaultPeriod
; /* not minimum */
690 if(period
< MinimumPeriod
|| period
> 5000000)
691 return AUDCLNT_E_INVALID_DEVICE_PERIOD
;
692 if(duration
> 20000000) /* the smaller the period, the lower this limit */
693 return AUDCLNT_E_BUFFER_SIZE_ERROR
;
694 if(flags
& AUDCLNT_STREAMFLAGS_EVENTCALLBACK
){
695 if(duration
!= period
)
696 return AUDCLNT_E_BUFDURATION_PERIOD_NOT_EQUAL
;
697 FIXME("EXCLUSIVE mode with EVENTCALLBACK\n");
698 return AUDCLNT_E_DEVICE_IN_USE
;
700 if( duration
< 8 * period
)
701 duration
= 8 * period
; /* may grow above 2s */
705 EnterCriticalSection(&g_sessions_lock
);
708 LeaveCriticalSection(&g_sessions_lock
);
709 return AUDCLNT_E_ALREADY_INITIALIZED
;
713 params
.device
= This
->devnode
;
714 params
.flow
= This
->dataflow
;
716 params
.flags
= flags
;
717 params
.duration
= duration
;
718 params
.period
= period
;
720 params
.channel_count
= NULL
;
721 params
.stream
= &stream
;
723 OSS_CALL(create_stream
, ¶ms
);
724 if(FAILED(params
.result
)){
725 LeaveCriticalSection(&g_sessions_lock
);
726 return params
.result
;
729 This
->channel_count
= fmt
->nChannels
;
730 This
->vols
= HeapAlloc(GetProcessHeap(), 0, This
->channel_count
* sizeof(float));
732 params
.result
= E_OUTOFMEMORY
;
735 for(i
= 0; i
< This
->channel_count
; ++i
)
738 params
.result
= get_audio_session(sessionguid
, This
->parent
, This
->channel_count
,
742 if(FAILED(params
.result
)){
743 stream_release(stream
, NULL
);
744 HeapFree(GetProcessHeap(), 0, This
->vols
);
747 list_add_tail(&This
->session
->clients
, &This
->entry
);
748 This
->stream
= stream
;
749 set_stream_volumes(This
);
752 LeaveCriticalSection(&g_sessions_lock
);
754 return params
.result
;
757 static HRESULT WINAPI
AudioClient_GetBufferSize(IAudioClient3
*iface
,
760 ACImpl
*This
= impl_from_IAudioClient3(iface
);
761 struct get_buffer_size_params params
;
763 TRACE("(%p)->(%p)\n", This
, frames
);
769 return AUDCLNT_E_NOT_INITIALIZED
;
771 params
.stream
= This
->stream
;
772 params
.frames
= frames
;
774 OSS_CALL(get_buffer_size
, ¶ms
);
775 TRACE("buffer size: %u\n", *frames
);
777 return params
.result
;
780 static HRESULT WINAPI
AudioClient_GetStreamLatency(IAudioClient3
*iface
,
781 REFERENCE_TIME
*latency
)
783 ACImpl
*This
= impl_from_IAudioClient3(iface
);
784 struct get_latency_params params
;
786 TRACE("(%p)->(%p)\n", This
, latency
);
792 return AUDCLNT_E_NOT_INITIALIZED
;
794 params
.stream
= This
->stream
;
795 params
.latency
= latency
;
796 OSS_CALL(get_latency
, ¶ms
);
798 return params
.result
;
801 static HRESULT WINAPI
AudioClient_GetCurrentPadding(IAudioClient3
*iface
,
804 ACImpl
*This
= impl_from_IAudioClient3(iface
);
805 struct get_current_padding_params params
;
807 TRACE("(%p)->(%p)\n", This
, numpad
);
813 return AUDCLNT_E_NOT_INITIALIZED
;
815 params
.stream
= This
->stream
;
816 params
.padding
= numpad
;
817 OSS_CALL(get_current_padding
, ¶ms
);
818 TRACE("padding: %u\n", *numpad
);
820 return params
.result
;
823 static HRESULT WINAPI
AudioClient_IsFormatSupported(IAudioClient3
*iface
,
824 AUDCLNT_SHAREMODE mode
, const WAVEFORMATEX
*fmt
,
827 ACImpl
*This
= impl_from_IAudioClient3(iface
);
828 struct is_format_supported_params params
;
830 TRACE("(%p)->(%x, %p, %p)\n", This
, mode
, fmt
, out
);
831 if(fmt
) dump_fmt(fmt
);
833 params
.device
= This
->devnode
;
834 params
.flow
= This
->dataflow
;
837 params
.fmt_out
= NULL
;
841 if(mode
== AUDCLNT_SHAREMODE_SHARED
)
842 params
.fmt_out
= CoTaskMemAlloc(sizeof(*params
.fmt_out
));
844 OSS_CALL(is_format_supported
, ¶ms
);
846 if(params
.result
== S_FALSE
)
847 *out
= ¶ms
.fmt_out
->Format
;
849 CoTaskMemFree(params
.fmt_out
);
851 return params
.result
;
854 static HRESULT WINAPI
AudioClient_GetMixFormat(IAudioClient3
*iface
,
857 ACImpl
*This
= impl_from_IAudioClient3(iface
);
858 struct get_mix_format_params params
;
860 TRACE("(%p)->(%p)\n", This
, pwfx
);
866 params
.device
= This
->devnode
;
867 params
.flow
= This
->dataflow
;
868 params
.fmt
= CoTaskMemAlloc(sizeof(WAVEFORMATEXTENSIBLE
));
870 return E_OUTOFMEMORY
;
872 OSS_CALL(get_mix_format
, ¶ms
);
874 if(SUCCEEDED(params
.result
)){
875 *pwfx
= ¶ms
.fmt
->Format
;
878 CoTaskMemFree(params
.fmt
);
880 return params
.result
;
883 static HRESULT WINAPI
AudioClient_GetDevicePeriod(IAudioClient3
*iface
,
884 REFERENCE_TIME
*defperiod
, REFERENCE_TIME
*minperiod
)
886 ACImpl
*This
= impl_from_IAudioClient3(iface
);
888 TRACE("(%p)->(%p, %p)\n", This
, defperiod
, minperiod
);
890 if(!defperiod
&& !minperiod
)
894 *defperiod
= DefaultPeriod
;
896 *minperiod
= MinimumPeriod
;
901 static HRESULT WINAPI
AudioClient_Start(IAudioClient3
*iface
)
903 ACImpl
*This
= impl_from_IAudioClient3(iface
);
904 struct start_params params
;
906 TRACE("(%p)\n", This
);
908 EnterCriticalSection(&g_sessions_lock
);
911 LeaveCriticalSection(&g_sessions_lock
);
912 return AUDCLNT_E_NOT_INITIALIZED
;
915 params
.stream
= This
->stream
;
916 OSS_CALL(start
, ¶ms
);
918 if(SUCCEEDED(params
.result
) && !This
->timer_thread
){
919 This
->timer_thread
= CreateThread(NULL
, 0, timer_thread
, This
, 0, NULL
);
920 SetThreadPriority(This
->timer_thread
, THREAD_PRIORITY_TIME_CRITICAL
);
923 LeaveCriticalSection(&g_sessions_lock
);
925 return params
.result
;
928 static HRESULT WINAPI
AudioClient_Stop(IAudioClient3
*iface
)
930 ACImpl
*This
= impl_from_IAudioClient3(iface
);
931 struct stop_params params
;
933 TRACE("(%p)\n", This
);
936 return AUDCLNT_E_NOT_INITIALIZED
;
938 params
.stream
= This
->stream
;
939 OSS_CALL(stop
, ¶ms
);
941 return params
.result
;
944 static HRESULT WINAPI
AudioClient_Reset(IAudioClient3
*iface
)
946 ACImpl
*This
= impl_from_IAudioClient3(iface
);
947 struct reset_params params
;
949 TRACE("(%p)\n", This
);
952 return AUDCLNT_E_NOT_INITIALIZED
;
954 params
.stream
= This
->stream
;
955 OSS_CALL(reset
, ¶ms
);
957 return params
.result
;
960 static HRESULT WINAPI
AudioClient_SetEventHandle(IAudioClient3
*iface
,
963 ACImpl
*This
= impl_from_IAudioClient3(iface
);
964 struct set_event_handle_params params
;
966 TRACE("(%p)->(%p)\n", This
, event
);
972 return AUDCLNT_E_NOT_INITIALIZED
;
974 params
.stream
= This
->stream
;
975 params
.event
= event
;
976 OSS_CALL(set_event_handle
, ¶ms
);
978 return params
.result
;
981 static HRESULT WINAPI
AudioClient_GetService(IAudioClient3
*iface
, REFIID riid
,
984 ACImpl
*This
= impl_from_IAudioClient3(iface
);
986 TRACE("(%p)->(%s, %p)\n", This
, debugstr_guid(riid
), ppv
);
992 EnterCriticalSection(&g_sessions_lock
);
995 LeaveCriticalSection(&g_sessions_lock
);
996 return AUDCLNT_E_NOT_INITIALIZED
;
999 if(IsEqualIID(riid
, &IID_IAudioRenderClient
)){
1000 if(This
->dataflow
!= eRender
){
1001 LeaveCriticalSection(&g_sessions_lock
);
1002 return AUDCLNT_E_WRONG_ENDPOINT_TYPE
;
1004 IAudioRenderClient_AddRef(&This
->IAudioRenderClient_iface
);
1005 *ppv
= &This
->IAudioRenderClient_iface
;
1006 }else if(IsEqualIID(riid
, &IID_IAudioCaptureClient
)){
1007 if(This
->dataflow
!= eCapture
){
1008 LeaveCriticalSection(&g_sessions_lock
);
1009 return AUDCLNT_E_WRONG_ENDPOINT_TYPE
;
1011 IAudioCaptureClient_AddRef(&This
->IAudioCaptureClient_iface
);
1012 *ppv
= &This
->IAudioCaptureClient_iface
;
1013 }else if(IsEqualIID(riid
, &IID_IAudioClock
)){
1014 IAudioClock_AddRef(&This
->IAudioClock_iface
);
1015 *ppv
= &This
->IAudioClock_iface
;
1016 }else if(IsEqualIID(riid
, &IID_IAudioStreamVolume
)){
1017 IAudioStreamVolume_AddRef(&This
->IAudioStreamVolume_iface
);
1018 *ppv
= &This
->IAudioStreamVolume_iface
;
1019 }else if(IsEqualIID(riid
, &IID_IAudioSessionControl
)){
1020 if(!This
->session_wrapper
){
1021 This
->session_wrapper
= AudioSessionWrapper_Create(This
);
1022 if(!This
->session_wrapper
){
1023 LeaveCriticalSection(&g_sessions_lock
);
1024 return E_OUTOFMEMORY
;
1027 IAudioSessionControl2_AddRef(&This
->session_wrapper
->IAudioSessionControl2_iface
);
1029 *ppv
= &This
->session_wrapper
->IAudioSessionControl2_iface
;
1030 }else if(IsEqualIID(riid
, &IID_IChannelAudioVolume
)){
1031 if(!This
->session_wrapper
){
1032 This
->session_wrapper
= AudioSessionWrapper_Create(This
);
1033 if(!This
->session_wrapper
){
1034 LeaveCriticalSection(&g_sessions_lock
);
1035 return E_OUTOFMEMORY
;
1038 IChannelAudioVolume_AddRef(&This
->session_wrapper
->IChannelAudioVolume_iface
);
1040 *ppv
= &This
->session_wrapper
->IChannelAudioVolume_iface
;
1041 }else if(IsEqualIID(riid
, &IID_ISimpleAudioVolume
)){
1042 if(!This
->session_wrapper
){
1043 This
->session_wrapper
= AudioSessionWrapper_Create(This
);
1044 if(!This
->session_wrapper
){
1045 LeaveCriticalSection(&g_sessions_lock
);
1046 return E_OUTOFMEMORY
;
1049 ISimpleAudioVolume_AddRef(&This
->session_wrapper
->ISimpleAudioVolume_iface
);
1051 *ppv
= &This
->session_wrapper
->ISimpleAudioVolume_iface
;
1055 LeaveCriticalSection(&g_sessions_lock
);
1059 LeaveCriticalSection(&g_sessions_lock
);
1061 FIXME("stub %s\n", debugstr_guid(riid
));
1062 return E_NOINTERFACE
;
1065 static HRESULT WINAPI
AudioClient_IsOffloadCapable(IAudioClient3
*iface
,
1066 AUDIO_STREAM_CATEGORY category
, BOOL
*offload_capable
)
1068 ACImpl
*This
= impl_from_IAudioClient3(iface
);
1070 TRACE("(%p)->(0x%x, %p)\n", This
, category
, offload_capable
);
1072 if(!offload_capable
)
1073 return E_INVALIDARG
;
1075 *offload_capable
= FALSE
;
1080 static HRESULT WINAPI
AudioClient_SetClientProperties(IAudioClient3
*iface
,
1081 const AudioClientProperties
*prop
)
1083 ACImpl
*This
= impl_from_IAudioClient3(iface
);
1084 const Win8AudioClientProperties
*legacy_prop
= (const Win8AudioClientProperties
*)prop
;
1086 TRACE("(%p)->(%p)\n", This
, prop
);
1091 if(legacy_prop
->cbSize
== sizeof(AudioClientProperties
)){
1092 TRACE("{ bIsOffload: %u, eCategory: 0x%x, Options: 0x%x }\n",
1093 legacy_prop
->bIsOffload
,
1094 legacy_prop
->eCategory
,
1096 }else if(legacy_prop
->cbSize
== sizeof(Win8AudioClientProperties
)){
1097 TRACE("{ bIsOffload: %u, eCategory: 0x%x }\n",
1098 legacy_prop
->bIsOffload
,
1099 legacy_prop
->eCategory
);
1101 WARN("Unsupported Size = %d\n", legacy_prop
->cbSize
);
1102 return E_INVALIDARG
;
1106 if(legacy_prop
->bIsOffload
)
1107 return AUDCLNT_E_ENDPOINT_OFFLOAD_NOT_CAPABLE
;
1112 static HRESULT WINAPI
AudioClient_GetBufferSizeLimits(IAudioClient3
*iface
,
1113 const WAVEFORMATEX
*format
, BOOL event_driven
, REFERENCE_TIME
*min_duration
,
1114 REFERENCE_TIME
*max_duration
)
1116 ACImpl
*This
= impl_from_IAudioClient3(iface
);
1118 FIXME("(%p)->(%p, %u, %p, %p)\n", This
, format
, event_driven
, min_duration
, max_duration
);
1123 static HRESULT WINAPI
AudioClient_GetSharedModeEnginePeriod(IAudioClient3
*iface
,
1124 const WAVEFORMATEX
*format
, UINT32
*default_period_frames
, UINT32
*unit_period_frames
,
1125 UINT32
*min_period_frames
, UINT32
*max_period_frames
)
1127 ACImpl
*This
= impl_from_IAudioClient3(iface
);
1129 FIXME("(%p)->(%p, %p, %p, %p, %p)\n", This
, format
, default_period_frames
, unit_period_frames
,
1130 min_period_frames
, max_period_frames
);
1135 static HRESULT WINAPI
AudioClient_GetCurrentSharedModeEnginePeriod(IAudioClient3
*iface
,
1136 WAVEFORMATEX
**cur_format
, UINT32
*cur_period_frames
)
1138 ACImpl
*This
= impl_from_IAudioClient3(iface
);
1140 FIXME("(%p)->(%p, %p)\n", This
, cur_format
, cur_period_frames
);
1145 static HRESULT WINAPI
AudioClient_InitializeSharedAudioStream(IAudioClient3
*iface
,
1146 DWORD flags
, UINT32 period_frames
, const WAVEFORMATEX
*format
,
1147 const GUID
*session_guid
)
1149 ACImpl
*This
= impl_from_IAudioClient3(iface
);
1151 FIXME("(%p)->(0x%lx, %u, %p, %s)\n", This
, flags
, period_frames
, format
, debugstr_guid(session_guid
));
1156 static const IAudioClient3Vtbl AudioClient3_Vtbl
=
1158 AudioClient_QueryInterface
,
1160 AudioClient_Release
,
1161 AudioClient_Initialize
,
1162 AudioClient_GetBufferSize
,
1163 AudioClient_GetStreamLatency
,
1164 AudioClient_GetCurrentPadding
,
1165 AudioClient_IsFormatSupported
,
1166 AudioClient_GetMixFormat
,
1167 AudioClient_GetDevicePeriod
,
1171 AudioClient_SetEventHandle
,
1172 AudioClient_GetService
,
1173 AudioClient_IsOffloadCapable
,
1174 AudioClient_SetClientProperties
,
1175 AudioClient_GetBufferSizeLimits
,
1176 AudioClient_GetSharedModeEnginePeriod
,
1177 AudioClient_GetCurrentSharedModeEnginePeriod
,
1178 AudioClient_InitializeSharedAudioStream
,
1181 static HRESULT WINAPI
AudioRenderClient_QueryInterface(
1182 IAudioRenderClient
*iface
, REFIID riid
, void **ppv
)
1184 ACImpl
*This
= impl_from_IAudioRenderClient(iface
);
1185 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
1191 if(IsEqualIID(riid
, &IID_IUnknown
) ||
1192 IsEqualIID(riid
, &IID_IAudioRenderClient
))
1194 else if(IsEqualIID(riid
, &IID_IMarshal
))
1195 return IUnknown_QueryInterface(This
->pUnkFTMarshal
, riid
, ppv
);
1197 IUnknown_AddRef((IUnknown
*)*ppv
);
1201 WARN("Unknown interface %s\n", debugstr_guid(riid
));
1202 return E_NOINTERFACE
;
1205 static ULONG WINAPI
AudioRenderClient_AddRef(IAudioRenderClient
*iface
)
1207 ACImpl
*This
= impl_from_IAudioRenderClient(iface
);
1208 return AudioClient_AddRef(&This
->IAudioClient3_iface
);
1211 static ULONG WINAPI
AudioRenderClient_Release(IAudioRenderClient
*iface
)
1213 ACImpl
*This
= impl_from_IAudioRenderClient(iface
);
1214 return AudioClient_Release(&This
->IAudioClient3_iface
);
1217 static HRESULT WINAPI
AudioRenderClient_GetBuffer(IAudioRenderClient
*iface
,
1218 UINT32 frames
, BYTE
**data
)
1220 ACImpl
*This
= impl_from_IAudioRenderClient(iface
);
1221 struct get_render_buffer_params params
;
1223 TRACE("(%p)->(%u, %p)\n", This
, frames
, data
);
1230 params
.stream
= This
->stream
;
1231 params
.frames
= frames
;
1233 OSS_CALL(get_render_buffer
, ¶ms
);
1235 return params
.result
;
1238 static HRESULT WINAPI
AudioRenderClient_ReleaseBuffer(
1239 IAudioRenderClient
*iface
, UINT32 written_frames
, DWORD flags
)
1241 ACImpl
*This
= impl_from_IAudioRenderClient(iface
);
1242 struct release_render_buffer_params params
;
1244 TRACE("(%p)->(%u, %lx)\n", This
, written_frames
, flags
);
1246 params
.stream
= This
->stream
;
1247 params
.written_frames
= written_frames
;
1248 params
.flags
= flags
;
1249 OSS_CALL(release_render_buffer
, ¶ms
);
1251 return params
.result
;
1254 static const IAudioRenderClientVtbl AudioRenderClient_Vtbl
= {
1255 AudioRenderClient_QueryInterface
,
1256 AudioRenderClient_AddRef
,
1257 AudioRenderClient_Release
,
1258 AudioRenderClient_GetBuffer
,
1259 AudioRenderClient_ReleaseBuffer
1262 static HRESULT WINAPI
AudioCaptureClient_QueryInterface(
1263 IAudioCaptureClient
*iface
, REFIID riid
, void **ppv
)
1265 ACImpl
*This
= impl_from_IAudioCaptureClient(iface
);
1266 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
1272 if(IsEqualIID(riid
, &IID_IUnknown
) ||
1273 IsEqualIID(riid
, &IID_IAudioCaptureClient
))
1275 else if(IsEqualIID(riid
, &IID_IMarshal
))
1276 return IUnknown_QueryInterface(This
->pUnkFTMarshal
, riid
, ppv
);
1278 IUnknown_AddRef((IUnknown
*)*ppv
);
1282 WARN("Unknown interface %s\n", debugstr_guid(riid
));
1283 return E_NOINTERFACE
;
1286 static ULONG WINAPI
AudioCaptureClient_AddRef(IAudioCaptureClient
*iface
)
1288 ACImpl
*This
= impl_from_IAudioCaptureClient(iface
);
1289 return IAudioClient3_AddRef(&This
->IAudioClient3_iface
);
1292 static ULONG WINAPI
AudioCaptureClient_Release(IAudioCaptureClient
*iface
)
1294 ACImpl
*This
= impl_from_IAudioCaptureClient(iface
);
1295 return IAudioClient3_Release(&This
->IAudioClient3_iface
);
1298 static HRESULT WINAPI
AudioCaptureClient_GetBuffer(IAudioCaptureClient
*iface
,
1299 BYTE
**data
, UINT32
*frames
, DWORD
*flags
, UINT64
*devpos
,
1302 ACImpl
*This
= impl_from_IAudioCaptureClient(iface
);
1303 struct get_capture_buffer_params params
;
1305 TRACE("(%p)->(%p, %p, %p, %p, %p)\n", This
, data
, frames
, flags
,
1313 if(!frames
|| !flags
)
1316 params
.stream
= This
->stream
;
1318 params
.frames
= frames
;
1319 params
.flags
= (UINT
*)flags
;
1320 params
.devpos
= devpos
;
1321 params
.qpcpos
= qpcpos
;
1322 OSS_CALL(get_capture_buffer
, ¶ms
);
1324 return params
.result
;
1327 static HRESULT WINAPI
AudioCaptureClient_ReleaseBuffer(
1328 IAudioCaptureClient
*iface
, UINT32 done
)
1330 ACImpl
*This
= impl_from_IAudioCaptureClient(iface
);
1331 struct release_capture_buffer_params params
;
1333 TRACE("(%p)->(%u)\n", This
, done
);
1335 params
.stream
= This
->stream
;
1337 OSS_CALL(release_capture_buffer
, ¶ms
);
1339 return params
.result
;
1342 static HRESULT WINAPI
AudioCaptureClient_GetNextPacketSize(
1343 IAudioCaptureClient
*iface
, UINT32
*frames
)
1345 ACImpl
*This
= impl_from_IAudioCaptureClient(iface
);
1346 struct get_next_packet_size_params params
;
1348 TRACE("(%p)->(%p)\n", This
, frames
);
1353 params
.stream
= This
->stream
;
1354 params
.frames
= frames
;
1355 OSS_CALL(get_next_packet_size
, ¶ms
);
1357 return params
.result
;
1360 static const IAudioCaptureClientVtbl AudioCaptureClient_Vtbl
=
1362 AudioCaptureClient_QueryInterface
,
1363 AudioCaptureClient_AddRef
,
1364 AudioCaptureClient_Release
,
1365 AudioCaptureClient_GetBuffer
,
1366 AudioCaptureClient_ReleaseBuffer
,
1367 AudioCaptureClient_GetNextPacketSize
1370 static HRESULT WINAPI
AudioClock_QueryInterface(IAudioClock
*iface
,
1371 REFIID riid
, void **ppv
)
1373 ACImpl
*This
= impl_from_IAudioClock(iface
);
1375 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
1381 if(IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IAudioClock
))
1383 else if(IsEqualIID(riid
, &IID_IAudioClock2
))
1384 *ppv
= &This
->IAudioClock2_iface
;
1386 IUnknown_AddRef((IUnknown
*)*ppv
);
1390 WARN("Unknown interface %s\n", debugstr_guid(riid
));
1391 return E_NOINTERFACE
;
1394 static ULONG WINAPI
AudioClock_AddRef(IAudioClock
*iface
)
1396 ACImpl
*This
= impl_from_IAudioClock(iface
);
1397 return IAudioClient3_AddRef(&This
->IAudioClient3_iface
);
1400 static ULONG WINAPI
AudioClock_Release(IAudioClock
*iface
)
1402 ACImpl
*This
= impl_from_IAudioClock(iface
);
1403 return IAudioClient3_Release(&This
->IAudioClient3_iface
);
1406 static HRESULT WINAPI
AudioClock_GetFrequency(IAudioClock
*iface
, UINT64
*freq
)
1408 ACImpl
*This
= impl_from_IAudioClock(iface
);
1409 struct get_frequency_params params
;
1411 TRACE("(%p)->(%p)\n", This
, freq
);
1413 params
.stream
= This
->stream
;
1415 OSS_CALL(get_frequency
, ¶ms
);
1417 return params
.result
;
1420 static HRESULT WINAPI
AudioClock_GetPosition(IAudioClock
*iface
, UINT64
*pos
,
1423 ACImpl
*This
= impl_from_IAudioClock(iface
);
1424 struct get_position_params params
;
1426 TRACE("(%p)->(%p, %p)\n", This
, pos
, qpctime
);
1431 params
.stream
= This
->stream
;
1432 params
.device
= FALSE
;
1434 params
.qpctime
= qpctime
;
1435 OSS_CALL(get_position
, ¶ms
);
1437 return params
.result
;
1440 static HRESULT WINAPI
AudioClock_GetCharacteristics(IAudioClock
*iface
,
1443 ACImpl
*This
= impl_from_IAudioClock(iface
);
1445 TRACE("(%p)->(%p)\n", This
, chars
);
1450 *chars
= AUDIOCLOCK_CHARACTERISTIC_FIXED_FREQ
;
1455 static const IAudioClockVtbl AudioClock_Vtbl
=
1457 AudioClock_QueryInterface
,
1460 AudioClock_GetFrequency
,
1461 AudioClock_GetPosition
,
1462 AudioClock_GetCharacteristics
1465 static HRESULT WINAPI
AudioClock2_QueryInterface(IAudioClock2
*iface
,
1466 REFIID riid
, void **ppv
)
1468 ACImpl
*This
= impl_from_IAudioClock2(iface
);
1469 return IAudioClock_QueryInterface(&This
->IAudioClock_iface
, riid
, ppv
);
1472 static ULONG WINAPI
AudioClock2_AddRef(IAudioClock2
*iface
)
1474 ACImpl
*This
= impl_from_IAudioClock2(iface
);
1475 return IAudioClient3_AddRef(&This
->IAudioClient3_iface
);
1478 static ULONG WINAPI
AudioClock2_Release(IAudioClock2
*iface
)
1480 ACImpl
*This
= impl_from_IAudioClock2(iface
);
1481 return IAudioClient3_Release(&This
->IAudioClient3_iface
);
1484 static HRESULT WINAPI
AudioClock2_GetDevicePosition(IAudioClock2
*iface
,
1485 UINT64
*pos
, UINT64
*qpctime
)
1487 ACImpl
*This
= impl_from_IAudioClock2(iface
);
1489 FIXME("(%p)->(%p, %p)\n", This
, pos
, qpctime
);
1494 static const IAudioClock2Vtbl AudioClock2_Vtbl
=
1496 AudioClock2_QueryInterface
,
1498 AudioClock2_Release
,
1499 AudioClock2_GetDevicePosition
1502 static AudioSessionWrapper
*AudioSessionWrapper_Create(ACImpl
*client
)
1504 AudioSessionWrapper
*ret
;
1506 ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
1507 sizeof(AudioSessionWrapper
));
1511 ret
->IAudioSessionControl2_iface
.lpVtbl
= &AudioSessionControl2_Vtbl
;
1512 ret
->ISimpleAudioVolume_iface
.lpVtbl
= &SimpleAudioVolume_Vtbl
;
1513 ret
->IChannelAudioVolume_iface
.lpVtbl
= &ChannelAudioVolume_Vtbl
;
1517 ret
->client
= client
;
1519 ret
->session
= client
->session
;
1520 AudioClient_AddRef(&client
->IAudioClient3_iface
);
1526 static HRESULT WINAPI
AudioSessionControl_QueryInterface(
1527 IAudioSessionControl2
*iface
, REFIID riid
, void **ppv
)
1529 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
1535 if(IsEqualIID(riid
, &IID_IUnknown
) ||
1536 IsEqualIID(riid
, &IID_IAudioSessionControl
) ||
1537 IsEqualIID(riid
, &IID_IAudioSessionControl2
))
1540 IUnknown_AddRef((IUnknown
*)*ppv
);
1544 WARN("Unknown interface %s\n", debugstr_guid(riid
));
1545 return E_NOINTERFACE
;
1548 static ULONG WINAPI
AudioSessionControl_AddRef(IAudioSessionControl2
*iface
)
1550 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1552 ref
= InterlockedIncrement(&This
->ref
);
1553 TRACE("(%p) Refcount now %lu\n", This
, ref
);
1557 static ULONG WINAPI
AudioSessionControl_Release(IAudioSessionControl2
*iface
)
1559 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1561 ref
= InterlockedDecrement(&This
->ref
);
1562 TRACE("(%p) Refcount now %lu\n", This
, ref
);
1565 EnterCriticalSection(&g_sessions_lock
);
1566 This
->client
->session_wrapper
= NULL
;
1567 LeaveCriticalSection(&g_sessions_lock
);
1568 AudioClient_Release(&This
->client
->IAudioClient3_iface
);
1570 HeapFree(GetProcessHeap(), 0, This
);
1575 static HRESULT WINAPI
AudioSessionControl_GetState(IAudioSessionControl2
*iface
,
1576 AudioSessionState
*state
)
1578 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1579 struct is_started_params params
;
1582 TRACE("(%p)->(%p)\n", This
, state
);
1585 return NULL_PTR_ERR
;
1587 EnterCriticalSection(&g_sessions_lock
);
1589 if(list_empty(&This
->session
->clients
)){
1590 *state
= AudioSessionStateExpired
;
1591 LeaveCriticalSection(&g_sessions_lock
);
1595 LIST_FOR_EACH_ENTRY(client
, &This
->session
->clients
, ACImpl
, entry
){
1596 params
.stream
= client
->stream
;
1597 OSS_CALL(is_started
, ¶ms
);
1598 if(params
.result
== S_OK
){
1599 *state
= AudioSessionStateActive
;
1600 LeaveCriticalSection(&g_sessions_lock
);
1605 LeaveCriticalSection(&g_sessions_lock
);
1607 *state
= AudioSessionStateInactive
;
1612 static HRESULT WINAPI
AudioSessionControl_GetDisplayName(
1613 IAudioSessionControl2
*iface
, WCHAR
**name
)
1615 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1617 FIXME("(%p)->(%p) - stub\n", This
, name
);
1622 static HRESULT WINAPI
AudioSessionControl_SetDisplayName(
1623 IAudioSessionControl2
*iface
, const WCHAR
*name
, const GUID
*session
)
1625 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1627 FIXME("(%p)->(%p, %s) - stub\n", This
, name
, debugstr_guid(session
));
1632 static HRESULT WINAPI
AudioSessionControl_GetIconPath(
1633 IAudioSessionControl2
*iface
, WCHAR
**path
)
1635 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1637 FIXME("(%p)->(%p) - stub\n", This
, path
);
1642 static HRESULT WINAPI
AudioSessionControl_SetIconPath(
1643 IAudioSessionControl2
*iface
, const WCHAR
*path
, const GUID
*session
)
1645 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1647 FIXME("(%p)->(%p, %s) - stub\n", This
, path
, debugstr_guid(session
));
1652 static HRESULT WINAPI
AudioSessionControl_GetGroupingParam(
1653 IAudioSessionControl2
*iface
, GUID
*group
)
1655 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1657 FIXME("(%p)->(%p) - stub\n", This
, group
);
1662 static HRESULT WINAPI
AudioSessionControl_SetGroupingParam(
1663 IAudioSessionControl2
*iface
, const GUID
*group
, const GUID
*session
)
1665 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1667 FIXME("(%p)->(%s, %s) - stub\n", This
, debugstr_guid(group
),
1668 debugstr_guid(session
));
1673 static HRESULT WINAPI
AudioSessionControl_RegisterAudioSessionNotification(
1674 IAudioSessionControl2
*iface
, IAudioSessionEvents
*events
)
1676 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1678 FIXME("(%p)->(%p) - stub\n", This
, events
);
1683 static HRESULT WINAPI
AudioSessionControl_UnregisterAudioSessionNotification(
1684 IAudioSessionControl2
*iface
, IAudioSessionEvents
*events
)
1686 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1688 FIXME("(%p)->(%p) - stub\n", This
, events
);
1693 static HRESULT WINAPI
AudioSessionControl_GetSessionIdentifier(
1694 IAudioSessionControl2
*iface
, WCHAR
**id
)
1696 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1698 FIXME("(%p)->(%p) - stub\n", This
, id
);
1703 static HRESULT WINAPI
AudioSessionControl_GetSessionInstanceIdentifier(
1704 IAudioSessionControl2
*iface
, WCHAR
**id
)
1706 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1708 FIXME("(%p)->(%p) - stub\n", This
, id
);
1713 static HRESULT WINAPI
AudioSessionControl_GetProcessId(
1714 IAudioSessionControl2
*iface
, DWORD
*pid
)
1716 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1718 TRACE("(%p)->(%p)\n", This
, pid
);
1723 *pid
= GetCurrentProcessId();
1728 static HRESULT WINAPI
AudioSessionControl_IsSystemSoundsSession(
1729 IAudioSessionControl2
*iface
)
1731 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1733 TRACE("(%p)\n", This
);
1738 static HRESULT WINAPI
AudioSessionControl_SetDuckingPreference(
1739 IAudioSessionControl2
*iface
, BOOL optout
)
1741 AudioSessionWrapper
*This
= impl_from_IAudioSessionControl2(iface
);
1743 TRACE("(%p)->(%d)\n", This
, optout
);
1748 static const IAudioSessionControl2Vtbl AudioSessionControl2_Vtbl
=
1750 AudioSessionControl_QueryInterface
,
1751 AudioSessionControl_AddRef
,
1752 AudioSessionControl_Release
,
1753 AudioSessionControl_GetState
,
1754 AudioSessionControl_GetDisplayName
,
1755 AudioSessionControl_SetDisplayName
,
1756 AudioSessionControl_GetIconPath
,
1757 AudioSessionControl_SetIconPath
,
1758 AudioSessionControl_GetGroupingParam
,
1759 AudioSessionControl_SetGroupingParam
,
1760 AudioSessionControl_RegisterAudioSessionNotification
,
1761 AudioSessionControl_UnregisterAudioSessionNotification
,
1762 AudioSessionControl_GetSessionIdentifier
,
1763 AudioSessionControl_GetSessionInstanceIdentifier
,
1764 AudioSessionControl_GetProcessId
,
1765 AudioSessionControl_IsSystemSoundsSession
,
1766 AudioSessionControl_SetDuckingPreference
1769 static HRESULT WINAPI
SimpleAudioVolume_QueryInterface(
1770 ISimpleAudioVolume
*iface
, REFIID riid
, void **ppv
)
1772 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
1778 if(IsEqualIID(riid
, &IID_IUnknown
) ||
1779 IsEqualIID(riid
, &IID_ISimpleAudioVolume
))
1782 IUnknown_AddRef((IUnknown
*)*ppv
);
1786 WARN("Unknown interface %s\n", debugstr_guid(riid
));
1787 return E_NOINTERFACE
;
1790 static ULONG WINAPI
SimpleAudioVolume_AddRef(ISimpleAudioVolume
*iface
)
1792 AudioSessionWrapper
*This
= impl_from_ISimpleAudioVolume(iface
);
1793 return AudioSessionControl_AddRef(&This
->IAudioSessionControl2_iface
);
1796 static ULONG WINAPI
SimpleAudioVolume_Release(ISimpleAudioVolume
*iface
)
1798 AudioSessionWrapper
*This
= impl_from_ISimpleAudioVolume(iface
);
1799 return AudioSessionControl_Release(&This
->IAudioSessionControl2_iface
);
1802 static HRESULT WINAPI
SimpleAudioVolume_SetMasterVolume(
1803 ISimpleAudioVolume
*iface
, float level
, const GUID
*context
)
1805 AudioSessionWrapper
*This
= impl_from_ISimpleAudioVolume(iface
);
1806 AudioSession
*session
= This
->session
;
1809 TRACE("(%p)->(%f, %s)\n", session
, level
, wine_dbgstr_guid(context
));
1811 if(level
< 0.f
|| level
> 1.f
)
1812 return E_INVALIDARG
;
1815 FIXME("Notifications not supported yet\n");
1817 EnterCriticalSection(&g_sessions_lock
);
1819 session
->master_vol
= level
;
1821 TRACE("OSS doesn't support setting volume\n");
1822 LIST_FOR_EACH_ENTRY(client
, &session
->clients
, ACImpl
, entry
)
1823 set_stream_volumes(client
);
1825 LeaveCriticalSection(&g_sessions_lock
);
1830 static HRESULT WINAPI
SimpleAudioVolume_GetMasterVolume(
1831 ISimpleAudioVolume
*iface
, float *level
)
1833 AudioSessionWrapper
*This
= impl_from_ISimpleAudioVolume(iface
);
1834 AudioSession
*session
= This
->session
;
1836 TRACE("(%p)->(%p)\n", session
, level
);
1839 return NULL_PTR_ERR
;
1841 *level
= session
->master_vol
;
1846 static HRESULT WINAPI
SimpleAudioVolume_SetMute(ISimpleAudioVolume
*iface
,
1847 BOOL mute
, const GUID
*context
)
1849 AudioSessionWrapper
*This
= impl_from_ISimpleAudioVolume(iface
);
1850 AudioSession
*session
= This
->session
;
1853 TRACE("(%p)->(%u, %s)\n", session
, mute
, debugstr_guid(context
));
1855 EnterCriticalSection(&g_sessions_lock
);
1857 session
->mute
= mute
;
1859 LIST_FOR_EACH_ENTRY(client
, &session
->clients
, ACImpl
, entry
)
1860 set_stream_volumes(client
);
1862 LeaveCriticalSection(&g_sessions_lock
);
1867 static HRESULT WINAPI
SimpleAudioVolume_GetMute(ISimpleAudioVolume
*iface
,
1870 AudioSessionWrapper
*This
= impl_from_ISimpleAudioVolume(iface
);
1871 AudioSession
*session
= This
->session
;
1873 TRACE("(%p)->(%p)\n", session
, mute
);
1876 return NULL_PTR_ERR
;
1878 *mute
= This
->session
->mute
;
1883 static const ISimpleAudioVolumeVtbl SimpleAudioVolume_Vtbl
=
1885 SimpleAudioVolume_QueryInterface
,
1886 SimpleAudioVolume_AddRef
,
1887 SimpleAudioVolume_Release
,
1888 SimpleAudioVolume_SetMasterVolume
,
1889 SimpleAudioVolume_GetMasterVolume
,
1890 SimpleAudioVolume_SetMute
,
1891 SimpleAudioVolume_GetMute
1894 static HRESULT WINAPI
AudioStreamVolume_QueryInterface(
1895 IAudioStreamVolume
*iface
, REFIID riid
, void **ppv
)
1897 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
1903 if(IsEqualIID(riid
, &IID_IUnknown
) ||
1904 IsEqualIID(riid
, &IID_IAudioStreamVolume
))
1907 IUnknown_AddRef((IUnknown
*)*ppv
);
1911 WARN("Unknown interface %s\n", debugstr_guid(riid
));
1912 return E_NOINTERFACE
;
1915 static ULONG WINAPI
AudioStreamVolume_AddRef(IAudioStreamVolume
*iface
)
1917 ACImpl
*This
= impl_from_IAudioStreamVolume(iface
);
1918 return IAudioClient3_AddRef(&This
->IAudioClient3_iface
);
1921 static ULONG WINAPI
AudioStreamVolume_Release(IAudioStreamVolume
*iface
)
1923 ACImpl
*This
= impl_from_IAudioStreamVolume(iface
);
1924 return IAudioClient3_Release(&This
->IAudioClient3_iface
);
1927 static HRESULT WINAPI
AudioStreamVolume_GetChannelCount(
1928 IAudioStreamVolume
*iface
, UINT32
*out
)
1930 ACImpl
*This
= impl_from_IAudioStreamVolume(iface
);
1932 TRACE("(%p)->(%p)\n", This
, out
);
1937 *out
= This
->channel_count
;
1942 static HRESULT WINAPI
AudioStreamVolume_SetChannelVolume(
1943 IAudioStreamVolume
*iface
, UINT32 index
, float level
)
1945 ACImpl
*This
= impl_from_IAudioStreamVolume(iface
);
1947 TRACE("(%p)->(%d, %f)\n", This
, index
, level
);
1949 if(level
< 0.f
|| level
> 1.f
)
1950 return E_INVALIDARG
;
1952 if(index
>= This
->channel_count
)
1953 return E_INVALIDARG
;
1955 EnterCriticalSection(&g_sessions_lock
);
1957 This
->vols
[index
] = level
;
1959 TRACE("OSS doesn't support setting volume\n");
1960 set_stream_volumes(This
);
1962 LeaveCriticalSection(&g_sessions_lock
);
1967 static HRESULT WINAPI
AudioStreamVolume_GetChannelVolume(
1968 IAudioStreamVolume
*iface
, UINT32 index
, float *level
)
1970 ACImpl
*This
= impl_from_IAudioStreamVolume(iface
);
1972 TRACE("(%p)->(%d, %p)\n", This
, index
, level
);
1977 if(index
>= This
->channel_count
)
1978 return E_INVALIDARG
;
1980 *level
= This
->vols
[index
];
1985 static HRESULT WINAPI
AudioStreamVolume_SetAllVolumes(
1986 IAudioStreamVolume
*iface
, UINT32 count
, const float *levels
)
1988 ACImpl
*This
= impl_from_IAudioStreamVolume(iface
);
1991 TRACE("(%p)->(%d, %p)\n", This
, count
, levels
);
1996 if(count
!= This
->channel_count
)
1997 return E_INVALIDARG
;
1999 EnterCriticalSection(&g_sessions_lock
);
2001 for(i
= 0; i
< count
; ++i
)
2002 This
->vols
[i
] = levels
[i
];
2004 TRACE("OSS doesn't support setting volume\n");
2005 set_stream_volumes(This
);
2007 LeaveCriticalSection(&g_sessions_lock
);
2012 static HRESULT WINAPI
AudioStreamVolume_GetAllVolumes(
2013 IAudioStreamVolume
*iface
, UINT32 count
, float *levels
)
2015 ACImpl
*This
= impl_from_IAudioStreamVolume(iface
);
2018 TRACE("(%p)->(%d, %p)\n", This
, count
, levels
);
2023 if(count
!= This
->channel_count
)
2024 return E_INVALIDARG
;
2026 EnterCriticalSection(&g_sessions_lock
);
2028 for(i
= 0; i
< count
; ++i
)
2029 levels
[i
] = This
->vols
[i
];
2031 LeaveCriticalSection(&g_sessions_lock
);
2036 static const IAudioStreamVolumeVtbl AudioStreamVolume_Vtbl
=
2038 AudioStreamVolume_QueryInterface
,
2039 AudioStreamVolume_AddRef
,
2040 AudioStreamVolume_Release
,
2041 AudioStreamVolume_GetChannelCount
,
2042 AudioStreamVolume_SetChannelVolume
,
2043 AudioStreamVolume_GetChannelVolume
,
2044 AudioStreamVolume_SetAllVolumes
,
2045 AudioStreamVolume_GetAllVolumes
2048 static HRESULT WINAPI
ChannelAudioVolume_QueryInterface(
2049 IChannelAudioVolume
*iface
, REFIID riid
, void **ppv
)
2051 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
2057 if(IsEqualIID(riid
, &IID_IUnknown
) ||
2058 IsEqualIID(riid
, &IID_IChannelAudioVolume
))
2061 IUnknown_AddRef((IUnknown
*)*ppv
);
2065 WARN("Unknown interface %s\n", debugstr_guid(riid
));
2066 return E_NOINTERFACE
;
2069 static ULONG WINAPI
ChannelAudioVolume_AddRef(IChannelAudioVolume
*iface
)
2071 AudioSessionWrapper
*This
= impl_from_IChannelAudioVolume(iface
);
2072 return AudioSessionControl_AddRef(&This
->IAudioSessionControl2_iface
);
2075 static ULONG WINAPI
ChannelAudioVolume_Release(IChannelAudioVolume
*iface
)
2077 AudioSessionWrapper
*This
= impl_from_IChannelAudioVolume(iface
);
2078 return AudioSessionControl_Release(&This
->IAudioSessionControl2_iface
);
2081 static HRESULT WINAPI
ChannelAudioVolume_GetChannelCount(
2082 IChannelAudioVolume
*iface
, UINT32
*out
)
2084 AudioSessionWrapper
*This
= impl_from_IChannelAudioVolume(iface
);
2085 AudioSession
*session
= This
->session
;
2087 TRACE("(%p)->(%p)\n", session
, out
);
2090 return NULL_PTR_ERR
;
2092 *out
= session
->channel_count
;
2097 static HRESULT WINAPI
ChannelAudioVolume_SetChannelVolume(
2098 IChannelAudioVolume
*iface
, UINT32 index
, float level
,
2099 const GUID
*context
)
2101 AudioSessionWrapper
*This
= impl_from_IChannelAudioVolume(iface
);
2102 AudioSession
*session
= This
->session
;
2105 TRACE("(%p)->(%d, %f, %s)\n", session
, index
, level
,
2106 wine_dbgstr_guid(context
));
2108 if(level
< 0.f
|| level
> 1.f
)
2109 return E_INVALIDARG
;
2111 if(index
>= session
->channel_count
)
2112 return E_INVALIDARG
;
2115 FIXME("Notifications not supported yet\n");
2117 EnterCriticalSection(&g_sessions_lock
);
2119 session
->channel_vols
[index
] = level
;
2121 TRACE("OSS doesn't support setting volume\n");
2122 LIST_FOR_EACH_ENTRY(client
, &session
->clients
, ACImpl
, entry
)
2123 set_stream_volumes(client
);
2125 LeaveCriticalSection(&g_sessions_lock
);
2130 static HRESULT WINAPI
ChannelAudioVolume_GetChannelVolume(
2131 IChannelAudioVolume
*iface
, UINT32 index
, float *level
)
2133 AudioSessionWrapper
*This
= impl_from_IChannelAudioVolume(iface
);
2134 AudioSession
*session
= This
->session
;
2136 TRACE("(%p)->(%d, %p)\n", session
, index
, level
);
2139 return NULL_PTR_ERR
;
2141 if(index
>= session
->channel_count
)
2142 return E_INVALIDARG
;
2144 *level
= session
->channel_vols
[index
];
2149 static HRESULT WINAPI
ChannelAudioVolume_SetAllVolumes(
2150 IChannelAudioVolume
*iface
, UINT32 count
, const float *levels
,
2151 const GUID
*context
)
2153 AudioSessionWrapper
*This
= impl_from_IChannelAudioVolume(iface
);
2154 AudioSession
*session
= This
->session
;
2158 TRACE("(%p)->(%d, %p, %s)\n", session
, count
, levels
,
2159 wine_dbgstr_guid(context
));
2162 return NULL_PTR_ERR
;
2164 if(count
!= session
->channel_count
)
2165 return E_INVALIDARG
;
2168 FIXME("Notifications not supported yet\n");
2170 EnterCriticalSection(&g_sessions_lock
);
2172 for(i
= 0; i
< count
; ++i
)
2173 session
->channel_vols
[i
] = levels
[i
];
2175 TRACE("OSS doesn't support setting volume\n");
2176 LIST_FOR_EACH_ENTRY(client
, &session
->clients
, ACImpl
, entry
)
2177 set_stream_volumes(client
);
2179 LeaveCriticalSection(&g_sessions_lock
);
2184 static HRESULT WINAPI
ChannelAudioVolume_GetAllVolumes(
2185 IChannelAudioVolume
*iface
, UINT32 count
, float *levels
)
2187 AudioSessionWrapper
*This
= impl_from_IChannelAudioVolume(iface
);
2188 AudioSession
*session
= This
->session
;
2191 TRACE("(%p)->(%d, %p)\n", session
, count
, levels
);
2194 return NULL_PTR_ERR
;
2196 if(count
!= session
->channel_count
)
2197 return E_INVALIDARG
;
2199 for(i
= 0; i
< count
; ++i
)
2200 levels
[i
] = session
->channel_vols
[i
];
2205 static const IChannelAudioVolumeVtbl ChannelAudioVolume_Vtbl
=
2207 ChannelAudioVolume_QueryInterface
,
2208 ChannelAudioVolume_AddRef
,
2209 ChannelAudioVolume_Release
,
2210 ChannelAudioVolume_GetChannelCount
,
2211 ChannelAudioVolume_SetChannelVolume
,
2212 ChannelAudioVolume_GetChannelVolume
,
2213 ChannelAudioVolume_SetAllVolumes
,
2214 ChannelAudioVolume_GetAllVolumes
2217 static HRESULT WINAPI
AudioSessionManager_QueryInterface(IAudioSessionManager2
*iface
,
2218 REFIID riid
, void **ppv
)
2220 TRACE("(%p)->(%s, %p)\n", iface
, debugstr_guid(riid
), ppv
);
2226 if(IsEqualIID(riid
, &IID_IUnknown
) ||
2227 IsEqualIID(riid
, &IID_IAudioSessionManager
) ||
2228 IsEqualIID(riid
, &IID_IAudioSessionManager2
))
2231 IUnknown_AddRef((IUnknown
*)*ppv
);
2235 WARN("Unknown interface %s\n", debugstr_guid(riid
));
2236 return E_NOINTERFACE
;
2239 static ULONG WINAPI
AudioSessionManager_AddRef(IAudioSessionManager2
*iface
)
2241 SessionMgr
*This
= impl_from_IAudioSessionManager2(iface
);
2243 ref
= InterlockedIncrement(&This
->ref
);
2244 TRACE("(%p) Refcount now %lu\n", This
, ref
);
2248 static ULONG WINAPI
AudioSessionManager_Release(IAudioSessionManager2
*iface
)
2250 SessionMgr
*This
= impl_from_IAudioSessionManager2(iface
);
2252 ref
= InterlockedDecrement(&This
->ref
);
2253 TRACE("(%p) Refcount now %lu\n", This
, ref
);
2255 HeapFree(GetProcessHeap(), 0, This
);
2259 static HRESULT WINAPI
AudioSessionManager_GetAudioSessionControl(
2260 IAudioSessionManager2
*iface
, const GUID
*session_guid
, DWORD flags
,
2261 IAudioSessionControl
**out
)
2263 SessionMgr
*This
= impl_from_IAudioSessionManager2(iface
);
2264 AudioSession
*session
;
2265 AudioSessionWrapper
*wrapper
;
2268 TRACE("(%p)->(%s, %lx, %p)\n", This
, debugstr_guid(session_guid
),
2271 hr
= get_audio_session(session_guid
, This
->device
, 0, &session
);
2275 wrapper
= AudioSessionWrapper_Create(NULL
);
2277 return E_OUTOFMEMORY
;
2279 wrapper
->session
= session
;
2281 *out
= (IAudioSessionControl
*)&wrapper
->IAudioSessionControl2_iface
;
2286 static HRESULT WINAPI
AudioSessionManager_GetSimpleAudioVolume(
2287 IAudioSessionManager2
*iface
, const GUID
*session_guid
, DWORD flags
,
2288 ISimpleAudioVolume
**out
)
2290 SessionMgr
*This
= impl_from_IAudioSessionManager2(iface
);
2291 AudioSession
*session
;
2292 AudioSessionWrapper
*wrapper
;
2295 TRACE("(%p)->(%s, %lx, %p)\n", This
, debugstr_guid(session_guid
),
2298 hr
= get_audio_session(session_guid
, This
->device
, 0, &session
);
2302 wrapper
= AudioSessionWrapper_Create(NULL
);
2304 return E_OUTOFMEMORY
;
2306 wrapper
->session
= session
;
2308 *out
= &wrapper
->ISimpleAudioVolume_iface
;
2313 static HRESULT WINAPI
AudioSessionManager_GetSessionEnumerator(
2314 IAudioSessionManager2
*iface
, IAudioSessionEnumerator
**out
)
2316 SessionMgr
*This
= impl_from_IAudioSessionManager2(iface
);
2317 FIXME("(%p)->(%p) - stub\n", This
, out
);
2321 static HRESULT WINAPI
AudioSessionManager_RegisterSessionNotification(
2322 IAudioSessionManager2
*iface
, IAudioSessionNotification
*notification
)
2324 SessionMgr
*This
= impl_from_IAudioSessionManager2(iface
);
2325 FIXME("(%p)->(%p) - stub\n", This
, notification
);
2329 static HRESULT WINAPI
AudioSessionManager_UnregisterSessionNotification(
2330 IAudioSessionManager2
*iface
, IAudioSessionNotification
*notification
)
2332 SessionMgr
*This
= impl_from_IAudioSessionManager2(iface
);
2333 FIXME("(%p)->(%p) - stub\n", This
, notification
);
2337 static HRESULT WINAPI
AudioSessionManager_RegisterDuckNotification(
2338 IAudioSessionManager2
*iface
, const WCHAR
*session_id
,
2339 IAudioVolumeDuckNotification
*notification
)
2341 SessionMgr
*This
= impl_from_IAudioSessionManager2(iface
);
2342 FIXME("(%p)->(%p) - stub\n", This
, notification
);
2346 static HRESULT WINAPI
AudioSessionManager_UnregisterDuckNotification(
2347 IAudioSessionManager2
*iface
,
2348 IAudioVolumeDuckNotification
*notification
)
2350 SessionMgr
*This
= impl_from_IAudioSessionManager2(iface
);
2351 FIXME("(%p)->(%p) - stub\n", This
, notification
);
2355 static const IAudioSessionManager2Vtbl AudioSessionManager2_Vtbl
=
2357 AudioSessionManager_QueryInterface
,
2358 AudioSessionManager_AddRef
,
2359 AudioSessionManager_Release
,
2360 AudioSessionManager_GetAudioSessionControl
,
2361 AudioSessionManager_GetSimpleAudioVolume
,
2362 AudioSessionManager_GetSessionEnumerator
,
2363 AudioSessionManager_RegisterSessionNotification
,
2364 AudioSessionManager_UnregisterSessionNotification
,
2365 AudioSessionManager_RegisterDuckNotification
,
2366 AudioSessionManager_UnregisterDuckNotification
2369 HRESULT WINAPI
AUDDRV_GetAudioSessionManager(IMMDevice
*device
,
2370 IAudioSessionManager2
**out
)
2374 This
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(SessionMgr
));
2376 return E_OUTOFMEMORY
;
2378 This
->IAudioSessionManager2_iface
.lpVtbl
= &AudioSessionManager2_Vtbl
;
2379 This
->device
= device
;
2382 *out
= &This
->IAudioSessionManager2_iface
;