2 * Copyright 2019 Nikolay Sivov 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
24 #include "mf_private.h"
26 #include "mmdeviceapi.h"
27 #include "audioclient.h"
29 #include "wine/debug.h"
30 #include "wine/heap.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(mfplat
);
36 STREAM_STATE_STOPPED
= 0,
41 enum audio_renderer_flags
49 IMFMediaSink IMFMediaSink_iface
;
50 IMFMediaSinkPreroll IMFMediaSinkPreroll_iface
;
51 IMFStreamSink IMFStreamSink_iface
;
52 IMFMediaTypeHandler IMFMediaTypeHandler_iface
;
53 IMFClockStateSink IMFClockStateSink_iface
;
54 IMFMediaEventGenerator IMFMediaEventGenerator_iface
;
55 IMFGetService IMFGetService_iface
;
56 IMFSimpleAudioVolume IMFSimpleAudioVolume_iface
;
57 IMFAudioStreamVolume IMFAudioStreamVolume_iface
;
58 IMFAudioPolicy IMFAudioPolicy_iface
;
60 IMFMediaEventQueue
*event_queue
;
61 IMFMediaEventQueue
*stream_event_queue
;
62 IMFPresentationClock
*clock
;
63 IMFMediaType
*media_type
;
64 IMFMediaType
*current_media_type
;
66 IAudioClient
*audio_client
;
67 IAudioStreamVolume
*stream_volume
;
68 ISimpleAudioVolume
*audio_volume
;
69 HANDLE buffer_ready_event
;
70 enum stream_state state
;
75 static struct audio_renderer
*impl_from_IMFMediaSink(IMFMediaSink
*iface
)
77 return CONTAINING_RECORD(iface
, struct audio_renderer
, IMFMediaSink_iface
);
80 static struct audio_renderer
*impl_from_IMFMediaSinkPreroll(IMFMediaSinkPreroll
*iface
)
82 return CONTAINING_RECORD(iface
, struct audio_renderer
, IMFMediaSinkPreroll_iface
);
85 static struct audio_renderer
*impl_from_IMFClockStateSink(IMFClockStateSink
*iface
)
87 return CONTAINING_RECORD(iface
, struct audio_renderer
, IMFClockStateSink_iface
);
90 static struct audio_renderer
*impl_from_IMFMediaEventGenerator(IMFMediaEventGenerator
*iface
)
92 return CONTAINING_RECORD(iface
, struct audio_renderer
, IMFMediaEventGenerator_iface
);
95 static struct audio_renderer
*impl_from_IMFGetService(IMFGetService
*iface
)
97 return CONTAINING_RECORD(iface
, struct audio_renderer
, IMFGetService_iface
);
100 static struct audio_renderer
*impl_from_IMFSimpleAudioVolume(IMFSimpleAudioVolume
*iface
)
102 return CONTAINING_RECORD(iface
, struct audio_renderer
, IMFSimpleAudioVolume_iface
);
105 static struct audio_renderer
*impl_from_IMFAudioStreamVolume(IMFAudioStreamVolume
*iface
)
107 return CONTAINING_RECORD(iface
, struct audio_renderer
, IMFAudioStreamVolume_iface
);
110 static struct audio_renderer
*impl_from_IMFAudioPolicy(IMFAudioPolicy
*iface
)
112 return CONTAINING_RECORD(iface
, struct audio_renderer
, IMFAudioPolicy_iface
);
115 static struct audio_renderer
*impl_from_IMFStreamSink(IMFStreamSink
*iface
)
117 return CONTAINING_RECORD(iface
, struct audio_renderer
, IMFStreamSink_iface
);
120 static struct audio_renderer
*impl_from_IMFMediaTypeHandler(IMFMediaTypeHandler
*iface
)
122 return CONTAINING_RECORD(iface
, struct audio_renderer
, IMFMediaTypeHandler_iface
);
125 static HRESULT WINAPI
audio_renderer_sink_QueryInterface(IMFMediaSink
*iface
, REFIID riid
, void **obj
)
127 struct audio_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
129 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
131 if (IsEqualIID(riid
, &IID_IMFMediaSink
) ||
132 IsEqualIID(riid
, &IID_IUnknown
))
136 else if (IsEqualIID(riid
, &IID_IMFMediaSinkPreroll
))
138 *obj
= &renderer
->IMFMediaSinkPreroll_iface
;
140 else if (IsEqualIID(riid
, &IID_IMFClockStateSink
))
142 *obj
= &renderer
->IMFClockStateSink_iface
;
144 else if (IsEqualIID(riid
, &IID_IMFMediaEventGenerator
))
146 *obj
= &renderer
->IMFMediaEventGenerator_iface
;
148 else if (IsEqualIID(riid
, &IID_IMFGetService
))
150 *obj
= &renderer
->IMFGetService_iface
;
154 WARN("Unsupported %s.\n", debugstr_guid(riid
));
156 return E_NOINTERFACE
;
159 IUnknown_AddRef((IUnknown
*)*obj
);
164 static ULONG WINAPI
audio_renderer_sink_AddRef(IMFMediaSink
*iface
)
166 struct audio_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
167 ULONG refcount
= InterlockedIncrement(&renderer
->refcount
);
168 TRACE("%p, refcount %u.\n", iface
, refcount
);
172 static void audio_renderer_release_audio_client(struct audio_renderer
*renderer
)
174 if (renderer
->audio_client
)
175 IAudioClient_Release(renderer
->audio_client
);
176 renderer
->audio_client
= NULL
;
177 if (renderer
->stream_volume
)
178 IAudioStreamVolume_Release(renderer
->stream_volume
);
179 renderer
->stream_volume
= NULL
;
180 if (renderer
->audio_volume
)
181 ISimpleAudioVolume_Release(renderer
->audio_volume
);
182 renderer
->audio_volume
= NULL
;
183 renderer
->flags
&= ~SAR_PREROLLED
;
186 static ULONG WINAPI
audio_renderer_sink_Release(IMFMediaSink
*iface
)
188 struct audio_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
189 ULONG refcount
= InterlockedDecrement(&renderer
->refcount
);
191 TRACE("%p, refcount %u.\n", iface
, refcount
);
195 if (renderer
->event_queue
)
196 IMFMediaEventQueue_Release(renderer
->event_queue
);
197 if (renderer
->stream_event_queue
)
198 IMFMediaEventQueue_Release(renderer
->stream_event_queue
);
200 IMFPresentationClock_Release(renderer
->clock
);
201 if (renderer
->device
)
202 IMMDevice_Release(renderer
->device
);
203 if (renderer
->media_type
)
204 IMFMediaType_Release(renderer
->media_type
);
205 if (renderer
->current_media_type
)
206 IMFMediaType_Release(renderer
->current_media_type
);
207 CloseHandle(renderer
->buffer_ready_event
);
208 audio_renderer_release_audio_client(renderer
);
209 DeleteCriticalSection(&renderer
->cs
);
216 static HRESULT WINAPI
audio_renderer_sink_GetCharacteristics(IMFMediaSink
*iface
, DWORD
*flags
)
218 struct audio_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
220 TRACE("%p, %p.\n", iface
, flags
);
222 if (renderer
->flags
& SAR_SHUT_DOWN
)
223 return MF_E_SHUTDOWN
;
225 *flags
= MEDIASINK_FIXED_STREAMS
| MEDIASINK_CAN_PREROLL
;
230 static HRESULT WINAPI
audio_renderer_sink_AddStreamSink(IMFMediaSink
*iface
, DWORD stream_sink_id
,
231 IMFMediaType
*media_type
, IMFStreamSink
**stream_sink
)
233 struct audio_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
235 TRACE("%p, %#x, %p, %p.\n", iface
, stream_sink_id
, media_type
, stream_sink
);
237 return renderer
->flags
& SAR_SHUT_DOWN
? MF_E_SHUTDOWN
: MF_E_STREAMSINKS_FIXED
;
240 static HRESULT WINAPI
audio_renderer_sink_RemoveStreamSink(IMFMediaSink
*iface
, DWORD stream_sink_id
)
242 struct audio_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
244 TRACE("%p, %#x.\n", iface
, stream_sink_id
);
246 return renderer
->flags
& SAR_SHUT_DOWN
? MF_E_SHUTDOWN
: MF_E_STREAMSINKS_FIXED
;
249 static HRESULT WINAPI
audio_renderer_sink_GetStreamSinkCount(IMFMediaSink
*iface
, DWORD
*count
)
251 struct audio_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
253 TRACE("%p, %p.\n", iface
, count
);
258 if (renderer
->flags
& SAR_SHUT_DOWN
)
259 return MF_E_SHUTDOWN
;
266 static HRESULT WINAPI
audio_renderer_sink_GetStreamSinkByIndex(IMFMediaSink
*iface
, DWORD index
,
267 IMFStreamSink
**stream
)
269 struct audio_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
272 TRACE("%p, %u, %p.\n", iface
, index
, stream
);
274 EnterCriticalSection(&renderer
->cs
);
276 if (renderer
->flags
& SAR_SHUT_DOWN
)
279 hr
= MF_E_INVALIDINDEX
;
282 *stream
= &renderer
->IMFStreamSink_iface
;
283 IMFStreamSink_AddRef(*stream
);
286 LeaveCriticalSection(&renderer
->cs
);
291 static HRESULT WINAPI
audio_renderer_sink_GetStreamSinkById(IMFMediaSink
*iface
, DWORD stream_sink_id
,
292 IMFStreamSink
**stream
)
294 struct audio_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
297 TRACE("%p, %#x, %p.\n", iface
, stream_sink_id
, stream
);
299 EnterCriticalSection(&renderer
->cs
);
301 if (renderer
->flags
& SAR_SHUT_DOWN
)
303 else if (stream_sink_id
> 0)
304 hr
= MF_E_INVALIDSTREAMNUMBER
;
307 *stream
= &renderer
->IMFStreamSink_iface
;
308 IMFStreamSink_AddRef(*stream
);
311 LeaveCriticalSection(&renderer
->cs
);
316 static void audio_renderer_set_presentation_clock(struct audio_renderer
*renderer
, IMFPresentationClock
*clock
)
320 IMFPresentationClock_RemoveClockStateSink(renderer
->clock
, &renderer
->IMFClockStateSink_iface
);
321 IMFPresentationClock_Release(renderer
->clock
);
323 renderer
->clock
= clock
;
326 IMFPresentationClock_AddRef(renderer
->clock
);
327 IMFPresentationClock_AddClockStateSink(renderer
->clock
, &renderer
->IMFClockStateSink_iface
);
331 static HRESULT WINAPI
audio_renderer_sink_SetPresentationClock(IMFMediaSink
*iface
, IMFPresentationClock
*clock
)
333 struct audio_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
336 TRACE("%p, %p.\n", iface
, clock
);
338 EnterCriticalSection(&renderer
->cs
);
340 if (renderer
->flags
& SAR_SHUT_DOWN
)
343 audio_renderer_set_presentation_clock(renderer
, clock
);
345 LeaveCriticalSection(&renderer
->cs
);
350 static HRESULT WINAPI
audio_renderer_sink_GetPresentationClock(IMFMediaSink
*iface
, IMFPresentationClock
**clock
)
352 struct audio_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
355 TRACE("%p, %p.\n", iface
, clock
);
360 EnterCriticalSection(&renderer
->cs
);
362 if (renderer
->flags
& SAR_SHUT_DOWN
)
364 else if (renderer
->clock
)
366 *clock
= renderer
->clock
;
367 IMFPresentationClock_AddRef(*clock
);
372 LeaveCriticalSection(&renderer
->cs
);
377 static HRESULT WINAPI
audio_renderer_sink_Shutdown(IMFMediaSink
*iface
)
379 struct audio_renderer
*renderer
= impl_from_IMFMediaSink(iface
);
381 TRACE("%p.\n", iface
);
383 if (renderer
->flags
& SAR_SHUT_DOWN
)
384 return MF_E_SHUTDOWN
;
386 EnterCriticalSection(&renderer
->cs
);
387 renderer
->flags
|= SAR_SHUT_DOWN
;
388 IMFMediaEventQueue_Shutdown(renderer
->event_queue
);
389 IMFMediaEventQueue_Shutdown(renderer
->stream_event_queue
);
390 audio_renderer_set_presentation_clock(renderer
, NULL
);
391 LeaveCriticalSection(&renderer
->cs
);
396 static const IMFMediaSinkVtbl audio_renderer_sink_vtbl
=
398 audio_renderer_sink_QueryInterface
,
399 audio_renderer_sink_AddRef
,
400 audio_renderer_sink_Release
,
401 audio_renderer_sink_GetCharacteristics
,
402 audio_renderer_sink_AddStreamSink
,
403 audio_renderer_sink_RemoveStreamSink
,
404 audio_renderer_sink_GetStreamSinkCount
,
405 audio_renderer_sink_GetStreamSinkByIndex
,
406 audio_renderer_sink_GetStreamSinkById
,
407 audio_renderer_sink_SetPresentationClock
,
408 audio_renderer_sink_GetPresentationClock
,
409 audio_renderer_sink_Shutdown
,
412 static void audio_renderer_preroll(struct audio_renderer
*renderer
)
416 if (renderer
->flags
& SAR_PREROLLED
)
419 for (i
= 0; i
< 2; ++i
)
420 IMFMediaEventQueue_QueueEventParamVar(renderer
->stream_event_queue
, MEStreamSinkRequestSample
, &GUID_NULL
, S_OK
, NULL
);
421 renderer
->flags
|= SAR_PREROLLED
;
424 static HRESULT WINAPI
audio_renderer_preroll_QueryInterface(IMFMediaSinkPreroll
*iface
, REFIID riid
, void **obj
)
426 struct audio_renderer
*renderer
= impl_from_IMFMediaSinkPreroll(iface
);
427 return IMFMediaSink_QueryInterface(&renderer
->IMFMediaSink_iface
, riid
, obj
);
430 static ULONG WINAPI
audio_renderer_preroll_AddRef(IMFMediaSinkPreroll
*iface
)
432 struct audio_renderer
*renderer
= impl_from_IMFMediaSinkPreroll(iface
);
433 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
436 static ULONG WINAPI
audio_renderer_preroll_Release(IMFMediaSinkPreroll
*iface
)
438 struct audio_renderer
*renderer
= impl_from_IMFMediaSinkPreroll(iface
);
439 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
442 static HRESULT WINAPI
audio_renderer_preroll_NotifyPreroll(IMFMediaSinkPreroll
*iface
, MFTIME start_time
)
444 struct audio_renderer
*renderer
= impl_from_IMFMediaSinkPreroll(iface
);
446 TRACE("%p, %s.\n", iface
, debugstr_time(start_time
));
448 if (renderer
->flags
& SAR_SHUT_DOWN
)
449 return MF_E_SHUTDOWN
;
451 audio_renderer_preroll(renderer
);
452 return IMFMediaEventQueue_QueueEventParamVar(renderer
->stream_event_queue
, MEStreamSinkPrerolled
, &GUID_NULL
, S_OK
, NULL
);
455 static const IMFMediaSinkPrerollVtbl audio_renderer_preroll_vtbl
=
457 audio_renderer_preroll_QueryInterface
,
458 audio_renderer_preroll_AddRef
,
459 audio_renderer_preroll_Release
,
460 audio_renderer_preroll_NotifyPreroll
,
463 static HRESULT WINAPI
audio_renderer_events_QueryInterface(IMFMediaEventGenerator
*iface
, REFIID riid
, void **obj
)
465 struct audio_renderer
*renderer
= impl_from_IMFMediaEventGenerator(iface
);
466 return IMFMediaSink_QueryInterface(&renderer
->IMFMediaSink_iface
, riid
, obj
);
469 static ULONG WINAPI
audio_renderer_events_AddRef(IMFMediaEventGenerator
*iface
)
471 struct audio_renderer
*renderer
= impl_from_IMFMediaEventGenerator(iface
);
472 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
475 static ULONG WINAPI
audio_renderer_events_Release(IMFMediaEventGenerator
*iface
)
477 struct audio_renderer
*renderer
= impl_from_IMFMediaEventGenerator(iface
);
478 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
481 static HRESULT WINAPI
audio_renderer_events_GetEvent(IMFMediaEventGenerator
*iface
, DWORD flags
, IMFMediaEvent
**event
)
483 struct audio_renderer
*renderer
= impl_from_IMFMediaEventGenerator(iface
);
485 TRACE("%p, %#x, %p.\n", iface
, flags
, event
);
487 return IMFMediaEventQueue_GetEvent(renderer
->event_queue
, flags
, event
);
490 static HRESULT WINAPI
audio_renderer_events_BeginGetEvent(IMFMediaEventGenerator
*iface
, IMFAsyncCallback
*callback
,
493 struct audio_renderer
*renderer
= impl_from_IMFMediaEventGenerator(iface
);
495 TRACE("%p, %p, %p.\n", iface
, callback
, state
);
497 return IMFMediaEventQueue_BeginGetEvent(renderer
->event_queue
, callback
, state
);
500 static HRESULT WINAPI
audio_renderer_events_EndGetEvent(IMFMediaEventGenerator
*iface
, IMFAsyncResult
*result
,
501 IMFMediaEvent
**event
)
503 struct audio_renderer
*renderer
= impl_from_IMFMediaEventGenerator(iface
);
505 TRACE("%p, %p, %p.\n", iface
, result
, event
);
507 return IMFMediaEventQueue_EndGetEvent(renderer
->event_queue
, result
, event
);
510 static HRESULT WINAPI
audio_renderer_events_QueueEvent(IMFMediaEventGenerator
*iface
, MediaEventType event_type
,
511 REFGUID ext_type
, HRESULT hr
, const PROPVARIANT
*value
)
513 struct audio_renderer
*renderer
= impl_from_IMFMediaEventGenerator(iface
);
515 TRACE("%p, %u, %s, %#x, %p.\n", iface
, event_type
, debugstr_guid(ext_type
), hr
, value
);
517 return IMFMediaEventQueue_QueueEventParamVar(renderer
->event_queue
, event_type
, ext_type
, hr
, value
);
520 static const IMFMediaEventGeneratorVtbl audio_renderer_events_vtbl
=
522 audio_renderer_events_QueryInterface
,
523 audio_renderer_events_AddRef
,
524 audio_renderer_events_Release
,
525 audio_renderer_events_GetEvent
,
526 audio_renderer_events_BeginGetEvent
,
527 audio_renderer_events_EndGetEvent
,
528 audio_renderer_events_QueueEvent
,
531 static HRESULT WINAPI
audio_renderer_clock_sink_QueryInterface(IMFClockStateSink
*iface
, REFIID riid
, void **obj
)
533 struct audio_renderer
*renderer
= impl_from_IMFClockStateSink(iface
);
534 return IMFMediaSink_QueryInterface(&renderer
->IMFMediaSink_iface
, riid
, obj
);
537 static ULONG WINAPI
audio_renderer_clock_sink_AddRef(IMFClockStateSink
*iface
)
539 struct audio_renderer
*renderer
= impl_from_IMFClockStateSink(iface
);
540 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
543 static ULONG WINAPI
audio_renderer_clock_sink_Release(IMFClockStateSink
*iface
)
545 struct audio_renderer
*renderer
= impl_from_IMFClockStateSink(iface
);
546 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
549 static HRESULT WINAPI
audio_renderer_clock_sink_OnClockStart(IMFClockStateSink
*iface
, MFTIME systime
, LONGLONG offset
)
551 struct audio_renderer
*renderer
= impl_from_IMFClockStateSink(iface
);
554 TRACE("%p, %s, %s.\n", iface
, debugstr_time(systime
), debugstr_time(offset
));
556 EnterCriticalSection(&renderer
->cs
);
557 if (renderer
->audio_client
)
559 if (renderer
->state
== STREAM_STATE_STOPPED
)
561 if (FAILED(hr
= IAudioClient_Start(renderer
->audio_client
)))
562 WARN("Failed to start audio client, hr %#x.\n", hr
);
563 renderer
->state
= STREAM_STATE_RUNNING
;
567 hr
= MF_E_NOT_INITIALIZED
;
569 IMFMediaEventQueue_QueueEventParamVar(renderer
->stream_event_queue
, MEStreamSinkStarted
, &GUID_NULL
, hr
, NULL
);
571 audio_renderer_preroll(renderer
);
572 LeaveCriticalSection(&renderer
->cs
);
577 static HRESULT WINAPI
audio_renderer_clock_sink_OnClockStop(IMFClockStateSink
*iface
, MFTIME systime
)
579 struct audio_renderer
*renderer
= impl_from_IMFClockStateSink(iface
);
582 TRACE("%p, %s.\n", iface
, debugstr_time(systime
));
584 EnterCriticalSection(&renderer
->cs
);
585 if (renderer
->audio_client
)
587 if (renderer
->state
!= STREAM_STATE_STOPPED
)
589 if (SUCCEEDED(hr
= IAudioClient_Stop(renderer
->audio_client
)))
591 if (FAILED(hr
= IAudioClient_Reset(renderer
->audio_client
)))
592 WARN("Failed to reset audio client, hr %#x.\n", hr
);
595 WARN("Failed to stop audio client, hr %#x.\n", hr
);
596 renderer
->state
= STREAM_STATE_STOPPED
;
597 renderer
->flags
&= ~SAR_PREROLLED
;
601 hr
= MF_E_NOT_INITIALIZED
;
603 IMFMediaEventQueue_QueueEventParamVar(renderer
->stream_event_queue
, MEStreamSinkStopped
, &GUID_NULL
, hr
, NULL
);
604 LeaveCriticalSection(&renderer
->cs
);
609 static HRESULT WINAPI
audio_renderer_clock_sink_OnClockPause(IMFClockStateSink
*iface
, MFTIME systime
)
611 struct audio_renderer
*renderer
= impl_from_IMFClockStateSink(iface
);
614 TRACE("%p, %s.\n", iface
, debugstr_time(systime
));
616 EnterCriticalSection(&renderer
->cs
);
617 if (renderer
->state
== STREAM_STATE_RUNNING
)
619 if (renderer
->audio_client
)
621 if (FAILED(hr
= IAudioClient_Stop(renderer
->audio_client
)))
622 WARN("Failed to stop audio client, hr %#x.\n", hr
);
623 renderer
->state
= STREAM_STATE_PAUSED
;
626 hr
= MF_E_NOT_INITIALIZED
;
628 IMFMediaEventQueue_QueueEventParamVar(renderer
->stream_event_queue
, MEStreamSinkPaused
, &GUID_NULL
, hr
, NULL
);
631 hr
= MF_E_INVALID_STATE_TRANSITION
;
632 LeaveCriticalSection(&renderer
->cs
);
637 static HRESULT WINAPI
audio_renderer_clock_sink_OnClockRestart(IMFClockStateSink
*iface
, MFTIME systime
)
639 struct audio_renderer
*renderer
= impl_from_IMFClockStateSink(iface
);
640 BOOL preroll
= FALSE
;
643 TRACE("%p, %s.\n", iface
, debugstr_time(systime
));
645 EnterCriticalSection(&renderer
->cs
);
646 if (renderer
->audio_client
)
648 if ((preroll
= (renderer
->state
!= STREAM_STATE_RUNNING
)))
650 if (FAILED(hr
= IAudioClient_Start(renderer
->audio_client
)))
651 WARN("Failed to start audio client, hr %#x.\n", hr
);
652 renderer
->state
= STREAM_STATE_RUNNING
;
656 hr
= MF_E_NOT_INITIALIZED
;
658 IMFMediaEventQueue_QueueEventParamVar(renderer
->stream_event_queue
, MEStreamSinkStarted
, &GUID_NULL
, hr
, NULL
);
660 audio_renderer_preroll(renderer
);
662 LeaveCriticalSection(&renderer
->cs
);
667 static HRESULT WINAPI
audio_renderer_clock_sink_OnClockSetRate(IMFClockStateSink
*iface
, MFTIME systime
, float rate
)
669 FIXME("%p, %s, %f.\n", iface
, debugstr_time(systime
), rate
);
674 static const IMFClockStateSinkVtbl audio_renderer_clock_sink_vtbl
=
676 audio_renderer_clock_sink_QueryInterface
,
677 audio_renderer_clock_sink_AddRef
,
678 audio_renderer_clock_sink_Release
,
679 audio_renderer_clock_sink_OnClockStart
,
680 audio_renderer_clock_sink_OnClockStop
,
681 audio_renderer_clock_sink_OnClockPause
,
682 audio_renderer_clock_sink_OnClockRestart
,
683 audio_renderer_clock_sink_OnClockSetRate
,
686 static HRESULT WINAPI
audio_renderer_get_service_QueryInterface(IMFGetService
*iface
, REFIID riid
, void **obj
)
688 struct audio_renderer
*renderer
= impl_from_IMFGetService(iface
);
689 return IMFMediaSink_QueryInterface(&renderer
->IMFMediaSink_iface
, riid
, obj
);
692 static ULONG WINAPI
audio_renderer_get_service_AddRef(IMFGetService
*iface
)
694 struct audio_renderer
*renderer
= impl_from_IMFGetService(iface
);
695 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
698 static ULONG WINAPI
audio_renderer_get_service_Release(IMFGetService
*iface
)
700 struct audio_renderer
*renderer
= impl_from_IMFGetService(iface
);
701 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
704 static HRESULT WINAPI
audio_renderer_get_service_GetService(IMFGetService
*iface
, REFGUID service
, REFIID riid
, void **obj
)
706 struct audio_renderer
*renderer
= impl_from_IMFGetService(iface
);
708 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
712 if (IsEqualGUID(service
, &MR_POLICY_VOLUME_SERVICE
) && IsEqualIID(riid
, &IID_IMFSimpleAudioVolume
))
714 *obj
= &renderer
->IMFSimpleAudioVolume_iface
;
716 else if (IsEqualGUID(service
, &MR_STREAM_VOLUME_SERVICE
) && IsEqualIID(riid
, &IID_IMFAudioStreamVolume
))
718 *obj
= &renderer
->IMFAudioStreamVolume_iface
;
720 else if (IsEqualGUID(service
, &MR_AUDIO_POLICY_SERVICE
) && IsEqualIID(riid
, &IID_IMFAudioPolicy
))
722 *obj
= &renderer
->IMFAudioPolicy_iface
;
725 FIXME("Unsupported service %s, interface %s.\n", debugstr_guid(service
), debugstr_guid(riid
));
728 IUnknown_AddRef((IUnknown
*)*obj
);
730 return *obj
? S_OK
: E_NOINTERFACE
;
733 static const IMFGetServiceVtbl audio_renderer_get_service_vtbl
=
735 audio_renderer_get_service_QueryInterface
,
736 audio_renderer_get_service_AddRef
,
737 audio_renderer_get_service_Release
,
738 audio_renderer_get_service_GetService
,
741 static HRESULT WINAPI
audio_renderer_simple_volume_QueryInterface(IMFSimpleAudioVolume
*iface
, REFIID riid
, void **obj
)
743 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
745 if (IsEqualIID(riid
, &IID_IMFSimpleAudioVolume
) ||
746 IsEqualIID(riid
, &IID_IUnknown
))
749 IMFSimpleAudioVolume_AddRef(iface
);
753 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
755 return E_NOINTERFACE
;
758 static ULONG WINAPI
audio_renderer_simple_volume_AddRef(IMFSimpleAudioVolume
*iface
)
760 struct audio_renderer
*renderer
= impl_from_IMFSimpleAudioVolume(iface
);
761 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
764 static ULONG WINAPI
audio_renderer_simple_volume_Release(IMFSimpleAudioVolume
*iface
)
766 struct audio_renderer
*renderer
= impl_from_IMFSimpleAudioVolume(iface
);
767 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
770 static HRESULT WINAPI
audio_renderer_simple_volume_SetMasterVolume(IMFSimpleAudioVolume
*iface
, float level
)
772 struct audio_renderer
*renderer
= impl_from_IMFSimpleAudioVolume(iface
);
775 TRACE("%p, %f.\n", iface
, level
);
777 EnterCriticalSection(&renderer
->cs
);
778 if (renderer
->audio_volume
)
779 hr
= ISimpleAudioVolume_SetMasterVolume(renderer
->audio_volume
, level
, NULL
);
780 LeaveCriticalSection(&renderer
->cs
);
785 static HRESULT WINAPI
audio_renderer_simple_volume_GetMasterVolume(IMFSimpleAudioVolume
*iface
, float *level
)
787 struct audio_renderer
*renderer
= impl_from_IMFSimpleAudioVolume(iface
);
790 TRACE("%p, %p.\n", iface
, level
);
797 EnterCriticalSection(&renderer
->cs
);
798 if (renderer
->audio_volume
)
799 hr
= ISimpleAudioVolume_GetMasterVolume(renderer
->audio_volume
, level
);
800 LeaveCriticalSection(&renderer
->cs
);
805 static HRESULT WINAPI
audio_renderer_simple_volume_SetMute(IMFSimpleAudioVolume
*iface
, BOOL mute
)
807 struct audio_renderer
*renderer
= impl_from_IMFSimpleAudioVolume(iface
);
810 TRACE("%p, %d.\n", iface
, mute
);
812 EnterCriticalSection(&renderer
->cs
);
813 if (renderer
->audio_volume
)
814 hr
= ISimpleAudioVolume_SetMute(renderer
->audio_volume
, mute
, NULL
);
815 LeaveCriticalSection(&renderer
->cs
);
820 static HRESULT WINAPI
audio_renderer_simple_volume_GetMute(IMFSimpleAudioVolume
*iface
, BOOL
*mute
)
822 struct audio_renderer
*renderer
= impl_from_IMFSimpleAudioVolume(iface
);
825 TRACE("%p, %p.\n", iface
, mute
);
832 EnterCriticalSection(&renderer
->cs
);
833 if (renderer
->audio_volume
)
834 hr
= ISimpleAudioVolume_GetMute(renderer
->audio_volume
, mute
);
835 LeaveCriticalSection(&renderer
->cs
);
840 static const IMFSimpleAudioVolumeVtbl audio_renderer_simple_volume_vtbl
=
842 audio_renderer_simple_volume_QueryInterface
,
843 audio_renderer_simple_volume_AddRef
,
844 audio_renderer_simple_volume_Release
,
845 audio_renderer_simple_volume_SetMasterVolume
,
846 audio_renderer_simple_volume_GetMasterVolume
,
847 audio_renderer_simple_volume_SetMute
,
848 audio_renderer_simple_volume_GetMute
,
851 static HRESULT WINAPI
audio_renderer_stream_volume_QueryInterface(IMFAudioStreamVolume
*iface
, REFIID riid
, void **obj
)
853 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
855 if (IsEqualIID(riid
, &IID_IMFAudioStreamVolume
) ||
856 IsEqualIID(riid
, &IID_IUnknown
))
859 IMFAudioStreamVolume_AddRef(iface
);
863 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
865 return E_NOINTERFACE
;
868 static ULONG WINAPI
audio_renderer_stream_volume_AddRef(IMFAudioStreamVolume
*iface
)
870 struct audio_renderer
*renderer
= impl_from_IMFAudioStreamVolume(iface
);
871 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
874 static ULONG WINAPI
audio_renderer_stream_volume_Release(IMFAudioStreamVolume
*iface
)
876 struct audio_renderer
*renderer
= impl_from_IMFAudioStreamVolume(iface
);
877 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
880 static HRESULT WINAPI
audio_renderer_stream_volume_GetChannelCount(IMFAudioStreamVolume
*iface
, UINT32
*count
)
882 struct audio_renderer
*renderer
= impl_from_IMFAudioStreamVolume(iface
);
885 TRACE("%p, %p.\n", iface
, count
);
892 EnterCriticalSection(&renderer
->cs
);
893 if (renderer
->stream_volume
)
894 hr
= IAudioStreamVolume_GetChannelCount(renderer
->stream_volume
, count
);
895 LeaveCriticalSection(&renderer
->cs
);
900 static HRESULT WINAPI
audio_renderer_stream_volume_SetChannelVolume(IMFAudioStreamVolume
*iface
, UINT32 index
, float level
)
902 struct audio_renderer
*renderer
= impl_from_IMFAudioStreamVolume(iface
);
905 TRACE("%p, %u, %f.\n", iface
, index
, level
);
907 EnterCriticalSection(&renderer
->cs
);
908 if (renderer
->stream_volume
)
909 hr
= IAudioStreamVolume_SetChannelVolume(renderer
->stream_volume
, index
, level
);
910 LeaveCriticalSection(&renderer
->cs
);
915 static HRESULT WINAPI
audio_renderer_stream_volume_GetChannelVolume(IMFAudioStreamVolume
*iface
, UINT32 index
, float *level
)
917 struct audio_renderer
*renderer
= impl_from_IMFAudioStreamVolume(iface
);
920 TRACE("%p, %u, %p.\n", iface
, index
, level
);
927 EnterCriticalSection(&renderer
->cs
);
928 if (renderer
->stream_volume
)
929 hr
= IAudioStreamVolume_GetChannelVolume(renderer
->stream_volume
, index
, level
);
930 LeaveCriticalSection(&renderer
->cs
);
935 static HRESULT WINAPI
audio_renderer_stream_volume_SetAllVolumes(IMFAudioStreamVolume
*iface
, UINT32 count
,
936 const float *volumes
)
938 struct audio_renderer
*renderer
= impl_from_IMFAudioStreamVolume(iface
);
941 TRACE("%p, %u, %p.\n", iface
, count
, volumes
);
943 EnterCriticalSection(&renderer
->cs
);
944 if (renderer
->stream_volume
)
945 hr
= IAudioStreamVolume_SetAllVolumes(renderer
->stream_volume
, count
, volumes
);
946 LeaveCriticalSection(&renderer
->cs
);
951 static HRESULT WINAPI
audio_renderer_stream_volume_GetAllVolumes(IMFAudioStreamVolume
*iface
, UINT32 count
, float *volumes
)
953 struct audio_renderer
*renderer
= impl_from_IMFAudioStreamVolume(iface
);
956 TRACE("%p, %u, %p.\n", iface
, count
, volumes
);
962 memset(volumes
, 0, sizeof(*volumes
) * count
);
964 EnterCriticalSection(&renderer
->cs
);
965 if (renderer
->stream_volume
)
966 hr
= IAudioStreamVolume_GetAllVolumes(renderer
->stream_volume
, count
, volumes
);
967 LeaveCriticalSection(&renderer
->cs
);
972 static const IMFAudioStreamVolumeVtbl audio_renderer_stream_volume_vtbl
=
974 audio_renderer_stream_volume_QueryInterface
,
975 audio_renderer_stream_volume_AddRef
,
976 audio_renderer_stream_volume_Release
,
977 audio_renderer_stream_volume_GetChannelCount
,
978 audio_renderer_stream_volume_SetChannelVolume
,
979 audio_renderer_stream_volume_GetChannelVolume
,
980 audio_renderer_stream_volume_SetAllVolumes
,
981 audio_renderer_stream_volume_GetAllVolumes
,
984 static HRESULT WINAPI
audio_renderer_policy_QueryInterface(IMFAudioPolicy
*iface
, REFIID riid
, void **obj
)
986 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
988 if (IsEqualIID(riid
, &IID_IMFAudioPolicy
) ||
989 IsEqualIID(riid
, &IID_IUnknown
))
992 IMFAudioPolicy_AddRef(iface
);
996 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
998 return E_NOINTERFACE
;
1001 static ULONG WINAPI
audio_renderer_policy_AddRef(IMFAudioPolicy
*iface
)
1003 struct audio_renderer
*renderer
= impl_from_IMFAudioPolicy(iface
);
1004 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
1007 static ULONG WINAPI
audio_renderer_policy_Release(IMFAudioPolicy
*iface
)
1009 struct audio_renderer
*renderer
= impl_from_IMFAudioPolicy(iface
);
1010 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
1013 static HRESULT WINAPI
audio_renderer_policy_SetGroupingParam(IMFAudioPolicy
*iface
, REFGUID param
)
1015 FIXME("%p, %s.\n", iface
, debugstr_guid(param
));
1020 static HRESULT WINAPI
audio_renderer_policy_GetGroupingParam(IMFAudioPolicy
*iface
, GUID
*param
)
1022 FIXME("%p, %p.\n", iface
, param
);
1027 static HRESULT WINAPI
audio_renderer_policy_SetDisplayName(IMFAudioPolicy
*iface
, const WCHAR
*name
)
1029 FIXME("%p, %s.\n", iface
, debugstr_w(name
));
1034 static HRESULT WINAPI
audio_renderer_policy_GetDisplayName(IMFAudioPolicy
*iface
, WCHAR
**name
)
1036 FIXME("%p, %p.\n", iface
, name
);
1041 static HRESULT WINAPI
audio_renderer_policy_SetIconPath(IMFAudioPolicy
*iface
, const WCHAR
*path
)
1043 FIXME("%p, %s.\n", iface
, debugstr_w(path
));
1048 static HRESULT WINAPI
audio_renderer_policy_GetIconPath(IMFAudioPolicy
*iface
, WCHAR
**path
)
1050 FIXME("%p, %p.\n", iface
, path
);
1055 static const IMFAudioPolicyVtbl audio_renderer_policy_vtbl
=
1057 audio_renderer_policy_QueryInterface
,
1058 audio_renderer_policy_AddRef
,
1059 audio_renderer_policy_Release
,
1060 audio_renderer_policy_SetGroupingParam
,
1061 audio_renderer_policy_GetGroupingParam
,
1062 audio_renderer_policy_SetDisplayName
,
1063 audio_renderer_policy_GetDisplayName
,
1064 audio_renderer_policy_SetIconPath
,
1065 audio_renderer_policy_GetIconPath
,
1068 static HRESULT
sar_create_mmdevice(IMFAttributes
*attributes
, struct audio_renderer
*renderer
)
1071 unsigned int length
, role
= eMultimedia
;
1072 IMMDeviceEnumerator
*devenum
;
1077 /* Mutually exclusive attributes. */
1078 if (SUCCEEDED(IMFAttributes_GetItem(attributes
, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE
, NULL
)) &&
1079 SUCCEEDED(IMFAttributes_GetItem(attributes
, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID
, NULL
)))
1081 return E_INVALIDARG
;
1085 if (FAILED(hr
= CoCreateInstance(&CLSID_MMDeviceEnumerator
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IMMDeviceEnumerator
,
1086 (void **)&devenum
)))
1092 if (attributes
&& SUCCEEDED(IMFAttributes_GetUINT32(attributes
, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ROLE
, &role
)))
1093 TRACE("Specified role %d.\n", role
);
1095 if (attributes
&& SUCCEEDED(IMFAttributes_GetAllocatedString(attributes
, &MF_AUDIO_RENDERER_ATTRIBUTE_ENDPOINT_ID
,
1096 &endpoint
, &length
)))
1098 TRACE("Specified end point %s.\n", debugstr_w(endpoint
));
1099 hr
= IMMDeviceEnumerator_GetDevice(devenum
, endpoint
, &renderer
->device
);
1100 CoTaskMemFree(endpoint
);
1103 hr
= IMMDeviceEnumerator_GetDefaultAudioEndpoint(devenum
, eRender
, role
, &renderer
->device
);
1106 hr
= MF_E_NO_AUDIO_PLAYBACK_DEVICE
;
1108 IMMDeviceEnumerator_Release(devenum
);
1113 static HRESULT WINAPI
audio_renderer_stream_QueryInterface(IMFStreamSink
*iface
, REFIID riid
, void **obj
)
1115 struct audio_renderer
*renderer
= impl_from_IMFStreamSink(iface
);
1117 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
1119 if (IsEqualIID(riid
, &IID_IMFStreamSink
) ||
1120 IsEqualIID(riid
, &IID_IMFMediaEventGenerator
) ||
1121 IsEqualIID(riid
, &IID_IUnknown
))
1123 *obj
= &renderer
->IMFStreamSink_iface
;
1125 else if (IsEqualIID(riid
, &IID_IMFMediaTypeHandler
))
1127 *obj
= &renderer
->IMFMediaTypeHandler_iface
;
1131 WARN("Unsupported %s.\n", debugstr_guid(riid
));
1133 return E_NOINTERFACE
;
1136 IUnknown_AddRef((IUnknown
*)*obj
);
1141 static ULONG WINAPI
audio_renderer_stream_AddRef(IMFStreamSink
*iface
)
1143 struct audio_renderer
*renderer
= impl_from_IMFStreamSink(iface
);
1144 return IMFMediaSink_AddRef(&renderer
->IMFMediaSink_iface
);
1147 static ULONG WINAPI
audio_renderer_stream_Release(IMFStreamSink
*iface
)
1149 struct audio_renderer
*renderer
= impl_from_IMFStreamSink(iface
);
1150 return IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
1153 static HRESULT WINAPI
audio_renderer_stream_GetEvent(IMFStreamSink
*iface
, DWORD flags
, IMFMediaEvent
**event
)
1155 struct audio_renderer
*renderer
= impl_from_IMFStreamSink(iface
);
1157 TRACE("%p, %#x, %p.\n", iface
, flags
, event
);
1159 if (renderer
->flags
& SAR_SHUT_DOWN
)
1160 return MF_E_STREAMSINK_REMOVED
;
1162 return IMFMediaEventQueue_GetEvent(renderer
->stream_event_queue
, flags
, event
);
1165 static HRESULT WINAPI
audio_renderer_stream_BeginGetEvent(IMFStreamSink
*iface
, IMFAsyncCallback
*callback
,
1168 struct audio_renderer
*renderer
= impl_from_IMFStreamSink(iface
);
1170 TRACE("%p, %p, %p.\n", iface
, callback
, state
);
1172 if (renderer
->flags
& SAR_SHUT_DOWN
)
1173 return MF_E_STREAMSINK_REMOVED
;
1175 return IMFMediaEventQueue_BeginGetEvent(renderer
->stream_event_queue
, callback
, state
);
1178 static HRESULT WINAPI
audio_renderer_stream_EndGetEvent(IMFStreamSink
*iface
, IMFAsyncResult
*result
,
1179 IMFMediaEvent
**event
)
1181 struct audio_renderer
*renderer
= impl_from_IMFStreamSink(iface
);
1183 TRACE("%p, %p, %p.\n", iface
, result
, event
);
1185 if (renderer
->flags
& SAR_SHUT_DOWN
)
1186 return MF_E_STREAMSINK_REMOVED
;
1188 return IMFMediaEventQueue_EndGetEvent(renderer
->stream_event_queue
, result
, event
);
1191 static HRESULT WINAPI
audio_renderer_stream_QueueEvent(IMFStreamSink
*iface
, MediaEventType event_type
,
1192 REFGUID ext_type
, HRESULT hr
, const PROPVARIANT
*value
)
1194 struct audio_renderer
*renderer
= impl_from_IMFStreamSink(iface
);
1196 TRACE("%p, %u, %s, %#x, %p.\n", iface
, event_type
, debugstr_guid(ext_type
), hr
, value
);
1198 if (renderer
->flags
& SAR_SHUT_DOWN
)
1199 return MF_E_STREAMSINK_REMOVED
;
1201 return IMFMediaEventQueue_QueueEventParamVar(renderer
->stream_event_queue
, event_type
, ext_type
, hr
, value
);
1204 static HRESULT WINAPI
audio_renderer_stream_GetMediaSink(IMFStreamSink
*iface
, IMFMediaSink
**sink
)
1206 struct audio_renderer
*renderer
= impl_from_IMFStreamSink(iface
);
1208 TRACE("%p, %p.\n", iface
, sink
);
1210 if (renderer
->flags
& SAR_SHUT_DOWN
)
1211 return MF_E_STREAMSINK_REMOVED
;
1213 *sink
= &renderer
->IMFMediaSink_iface
;
1214 IMFMediaSink_AddRef(*sink
);
1219 static HRESULT WINAPI
audio_renderer_stream_GetIdentifier(IMFStreamSink
*iface
, DWORD
*identifier
)
1221 struct audio_renderer
*renderer
= impl_from_IMFStreamSink(iface
);
1223 TRACE("%p, %p.\n", iface
, identifier
);
1225 if (renderer
->flags
& SAR_SHUT_DOWN
)
1226 return MF_E_STREAMSINK_REMOVED
;
1233 static HRESULT WINAPI
audio_renderer_stream_GetMediaTypeHandler(IMFStreamSink
*iface
, IMFMediaTypeHandler
**handler
)
1235 struct audio_renderer
*renderer
= impl_from_IMFStreamSink(iface
);
1237 TRACE("%p, %p.\n", iface
, handler
);
1242 if (renderer
->flags
& SAR_SHUT_DOWN
)
1243 return MF_E_STREAMSINK_REMOVED
;
1245 *handler
= &renderer
->IMFMediaTypeHandler_iface
;
1246 IMFMediaTypeHandler_AddRef(*handler
);
1251 static HRESULT WINAPI
audio_renderer_stream_ProcessSample(IMFStreamSink
*iface
, IMFSample
*sample
)
1253 FIXME("%p, %p.\n", iface
, sample
);
1258 static HRESULT WINAPI
audio_renderer_stream_PlaceMarker(IMFStreamSink
*iface
, MFSTREAMSINK_MARKER_TYPE marker_type
,
1259 const PROPVARIANT
*marker_value
, const PROPVARIANT
*context_value
)
1261 FIXME("%p, %d, %p, %p.\n", iface
, marker_type
, marker_value
, context_value
);
1266 static HRESULT WINAPI
audio_renderer_stream_Flush(IMFStreamSink
*iface
)
1268 FIXME("%p.\n", iface
);
1273 static const IMFStreamSinkVtbl audio_renderer_stream_vtbl
=
1275 audio_renderer_stream_QueryInterface
,
1276 audio_renderer_stream_AddRef
,
1277 audio_renderer_stream_Release
,
1278 audio_renderer_stream_GetEvent
,
1279 audio_renderer_stream_BeginGetEvent
,
1280 audio_renderer_stream_EndGetEvent
,
1281 audio_renderer_stream_QueueEvent
,
1282 audio_renderer_stream_GetMediaSink
,
1283 audio_renderer_stream_GetIdentifier
,
1284 audio_renderer_stream_GetMediaTypeHandler
,
1285 audio_renderer_stream_ProcessSample
,
1286 audio_renderer_stream_PlaceMarker
,
1287 audio_renderer_stream_Flush
,
1290 static HRESULT WINAPI
audio_renderer_stream_type_handler_QueryInterface(IMFMediaTypeHandler
*iface
, REFIID riid
,
1293 struct audio_renderer
*renderer
= impl_from_IMFMediaTypeHandler(iface
);
1294 return IMFStreamSink_QueryInterface(&renderer
->IMFStreamSink_iface
, riid
, obj
);
1297 static ULONG WINAPI
audio_renderer_stream_type_handler_AddRef(IMFMediaTypeHandler
*iface
)
1299 struct audio_renderer
*renderer
= impl_from_IMFMediaTypeHandler(iface
);
1300 return IMFStreamSink_AddRef(&renderer
->IMFStreamSink_iface
);
1303 static ULONG WINAPI
audio_renderer_stream_type_handler_Release(IMFMediaTypeHandler
*iface
)
1305 struct audio_renderer
*renderer
= impl_from_IMFMediaTypeHandler(iface
);
1306 return IMFStreamSink_Release(&renderer
->IMFStreamSink_iface
);
1309 static HRESULT WINAPI
audio_renderer_stream_type_handler_IsMediaTypeSupported(IMFMediaTypeHandler
*iface
,
1310 IMFMediaType
*in_type
, IMFMediaType
**out_type
)
1312 struct audio_renderer
*renderer
= impl_from_IMFMediaTypeHandler(iface
);
1316 TRACE("%p, %p, %p.\n", iface
, in_type
, out_type
);
1318 EnterCriticalSection(&renderer
->cs
);
1319 hr
= renderer
->current_media_type
&& IMFMediaType_IsEqual(renderer
->current_media_type
, in_type
, &flags
) == S_OK
?
1320 S_OK
: MF_E_INVALIDMEDIATYPE
;
1321 LeaveCriticalSection(&renderer
->cs
);
1326 static HRESULT WINAPI
audio_renderer_stream_type_handler_GetMediaTypeCount(IMFMediaTypeHandler
*iface
, DWORD
*count
)
1328 TRACE("%p, %p.\n", iface
, count
);
1335 static HRESULT WINAPI
audio_renderer_stream_type_handler_GetMediaTypeByIndex(IMFMediaTypeHandler
*iface
, DWORD index
,
1336 IMFMediaType
**media_type
)
1338 struct audio_renderer
*renderer
= impl_from_IMFMediaTypeHandler(iface
);
1340 TRACE("%p, %u, %p.\n", iface
, index
, media_type
);
1344 *media_type
= renderer
->media_type
;
1345 IMFMediaType_AddRef(*media_type
);
1351 static HRESULT
audio_renderer_create_audio_client(struct audio_renderer
*renderer
)
1356 audio_renderer_release_audio_client(renderer
);
1358 hr
= IMMDevice_Activate(renderer
->device
, &IID_IAudioClient
, CLSCTX_INPROC_SERVER
, NULL
,
1359 (void **)&renderer
->audio_client
);
1362 WARN("Failed to create audio client, hr %#x.\n", hr
);
1366 /* FIXME: use SAR configuration for flags and session id. */
1368 /* FIXME: for now always use default format. */
1369 if (FAILED(hr
= IAudioClient_GetMixFormat(renderer
->audio_client
, &wfx
)))
1371 WARN("Failed to get audio format, hr %#x.\n", hr
);
1375 hr
= IAudioClient_Initialize(renderer
->audio_client
, AUDCLNT_SHAREMODE_SHARED
, AUDCLNT_STREAMFLAGS_EVENTCALLBACK
,
1376 1000000, 0, wfx
, NULL
);
1380 WARN("Failed to initialize audio client, hr %#x.\n", hr
);
1384 if (FAILED(hr
= IAudioClient_GetService(renderer
->audio_client
, &IID_IAudioStreamVolume
,
1385 (void **)&renderer
->stream_volume
)))
1387 WARN("Failed to get stream volume control, hr %#x.\n", hr
);
1391 if (FAILED(hr
= IAudioClient_GetService(renderer
->audio_client
, &IID_ISimpleAudioVolume
, (void **)&renderer
->audio_volume
)))
1393 WARN("Failed to get audio volume control, hr %#x.\n", hr
);
1397 if (FAILED(hr
= IAudioClient_SetEventHandle(renderer
->audio_client
, renderer
->buffer_ready_event
)))
1399 WARN("Failed to set event handle, hr %#x.\n", hr
);
1406 static HRESULT WINAPI
audio_renderer_stream_type_handler_SetCurrentMediaType(IMFMediaTypeHandler
*iface
,
1407 IMFMediaType
*media_type
)
1409 struct audio_renderer
*renderer
= impl_from_IMFMediaTypeHandler(iface
);
1410 const unsigned int test_flags
= MF_MEDIATYPE_EQUAL_MAJOR_TYPES
| MF_MEDIATYPE_EQUAL_FORMAT_TYPES
;
1411 BOOL compare_result
;
1415 TRACE("%p, %p.\n", iface
, media_type
);
1420 EnterCriticalSection(&renderer
->cs
);
1421 if (SUCCEEDED(IMFMediaType_IsEqual(renderer
->media_type
, media_type
, &flags
)) && ((flags
& test_flags
) == test_flags
))
1423 if (renderer
->current_media_type
)
1424 IMFMediaType_Release(renderer
->current_media_type
);
1425 renderer
->current_media_type
= media_type
;
1426 IMFMediaType_AddRef(renderer
->current_media_type
);
1428 if (SUCCEEDED(hr
= audio_renderer_create_audio_client(renderer
)))
1430 if (SUCCEEDED(IMFMediaType_Compare(renderer
->media_type
, (IMFAttributes
*)media_type
, MF_ATTRIBUTES_MATCH_OUR_ITEMS
,
1431 &compare_result
)) && !compare_result
)
1433 IMFMediaEventQueue_QueueEventParamVar(renderer
->stream_event_queue
, MEStreamSinkFormatInvalidated
, &GUID_NULL
,
1435 audio_renderer_preroll(renderer
);
1440 hr
= MF_E_INVALIDMEDIATYPE
;
1441 LeaveCriticalSection(&renderer
->cs
);
1446 static HRESULT WINAPI
audio_renderer_stream_type_handler_GetCurrentMediaType(IMFMediaTypeHandler
*iface
,
1447 IMFMediaType
**media_type
)
1449 struct audio_renderer
*renderer
= impl_from_IMFMediaTypeHandler(iface
);
1452 TRACE("%p, %p.\n", iface
, media_type
);
1454 EnterCriticalSection(&renderer
->cs
);
1455 if (renderer
->current_media_type
)
1457 *media_type
= renderer
->current_media_type
;
1458 IMFMediaType_AddRef(*media_type
);
1461 hr
= MF_E_NOT_INITIALIZED
;
1462 LeaveCriticalSection(&renderer
->cs
);
1467 static HRESULT WINAPI
audio_renderer_stream_type_handler_GetMajorType(IMFMediaTypeHandler
*iface
, GUID
*type
)
1469 struct audio_renderer
*renderer
= impl_from_IMFMediaTypeHandler(iface
);
1471 TRACE("%p, %p.\n", iface
, type
);
1476 if (renderer
->flags
& SAR_SHUT_DOWN
)
1477 return MF_E_STREAMSINK_REMOVED
;
1479 memcpy(type
, &MFMediaType_Audio
, sizeof(*type
));
1483 static const IMFMediaTypeHandlerVtbl audio_renderer_stream_type_handler_vtbl
=
1485 audio_renderer_stream_type_handler_QueryInterface
,
1486 audio_renderer_stream_type_handler_AddRef
,
1487 audio_renderer_stream_type_handler_Release
,
1488 audio_renderer_stream_type_handler_IsMediaTypeSupported
,
1489 audio_renderer_stream_type_handler_GetMediaTypeCount
,
1490 audio_renderer_stream_type_handler_GetMediaTypeByIndex
,
1491 audio_renderer_stream_type_handler_SetCurrentMediaType
,
1492 audio_renderer_stream_type_handler_GetCurrentMediaType
,
1493 audio_renderer_stream_type_handler_GetMajorType
,
1496 static HRESULT
audio_renderer_collect_supported_types(struct audio_renderer
*renderer
)
1498 IAudioClient
*client
;
1499 WAVEFORMATEX
*format
;
1502 if (FAILED(hr
= MFCreateMediaType(&renderer
->media_type
)))
1505 hr
= IMMDevice_Activate(renderer
->device
, &IID_IAudioClient
, CLSCTX_INPROC_SERVER
, NULL
, (void **)&client
);
1508 WARN("Failed to create audio client, hr %#x.\n", hr
);
1514 hr
= IAudioClient_GetMixFormat(client
, &format
);
1515 IAudioClient_Release(client
);
1518 WARN("Failed to get device audio format, hr %#x.\n", hr
);
1522 hr
= MFInitMediaTypeFromWaveFormatEx(renderer
->media_type
, format
, format
->cbSize
+ sizeof(*format
));
1523 CoTaskMemFree(format
);
1526 WARN("Failed to initialize media type, hr %#x.\n", hr
);
1530 IMFMediaType_DeleteItem(renderer
->media_type
, &MF_MT_AUDIO_PREFER_WAVEFORMATEX
);
1535 static HRESULT
sar_create_object(IMFAttributes
*attributes
, void *user_context
, IUnknown
**obj
)
1537 struct audio_renderer
*renderer
;
1540 TRACE("%p, %p, %p.\n", attributes
, user_context
, obj
);
1542 if (!(renderer
= heap_alloc_zero(sizeof(*renderer
))))
1543 return E_OUTOFMEMORY
;
1545 renderer
->IMFMediaSink_iface
.lpVtbl
= &audio_renderer_sink_vtbl
;
1546 renderer
->IMFMediaSinkPreroll_iface
.lpVtbl
= &audio_renderer_preroll_vtbl
;
1547 renderer
->IMFStreamSink_iface
.lpVtbl
= &audio_renderer_stream_vtbl
;
1548 renderer
->IMFMediaTypeHandler_iface
.lpVtbl
= &audio_renderer_stream_type_handler_vtbl
;
1549 renderer
->IMFClockStateSink_iface
.lpVtbl
= &audio_renderer_clock_sink_vtbl
;
1550 renderer
->IMFMediaEventGenerator_iface
.lpVtbl
= &audio_renderer_events_vtbl
;
1551 renderer
->IMFGetService_iface
.lpVtbl
= &audio_renderer_get_service_vtbl
;
1552 renderer
->IMFSimpleAudioVolume_iface
.lpVtbl
= &audio_renderer_simple_volume_vtbl
;
1553 renderer
->IMFAudioStreamVolume_iface
.lpVtbl
= &audio_renderer_stream_volume_vtbl
;
1554 renderer
->IMFAudioPolicy_iface
.lpVtbl
= &audio_renderer_policy_vtbl
;
1555 renderer
->refcount
= 1;
1556 InitializeCriticalSection(&renderer
->cs
);
1557 renderer
->buffer_ready_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
1559 if (FAILED(hr
= MFCreateEventQueue(&renderer
->event_queue
)))
1562 if (FAILED(hr
= MFCreateEventQueue(&renderer
->stream_event_queue
)))
1565 if (FAILED(hr
= sar_create_mmdevice(attributes
, renderer
)))
1568 if (FAILED(hr
= audio_renderer_collect_supported_types(renderer
)))
1571 *obj
= (IUnknown
*)&renderer
->IMFMediaSink_iface
;
1577 IMFMediaSink_Release(&renderer
->IMFMediaSink_iface
);
1582 static void sar_shutdown_object(void *user_context
, IUnknown
*obj
)
1586 if (SUCCEEDED(IUnknown_QueryInterface(obj
, &IID_IMFMediaSink
, (void **)&sink
)))
1588 IMFMediaSink_Shutdown(sink
);
1589 IMFMediaSink_Release(sink
);
1593 static void sar_free_private(void *user_context
)
1597 static const struct activate_funcs sar_activate_funcs
=
1600 sar_shutdown_object
,
1604 /***********************************************************************
1605 * MFCreateAudioRendererActivate (mf.@)
1607 HRESULT WINAPI
MFCreateAudioRendererActivate(IMFActivate
**activate
)
1609 TRACE("%p.\n", activate
);
1614 return create_activation_object(NULL
, &sar_activate_funcs
, activate
);
1617 /***********************************************************************
1618 * MFCreateAudioRenderer (mf.@)
1620 HRESULT WINAPI
MFCreateAudioRenderer(IMFAttributes
*attributes
, IMFMediaSink
**sink
)
1625 TRACE("%p, %p.\n", attributes
, sink
);
1627 if (SUCCEEDED(hr
= sar_create_object(attributes
, NULL
, &object
)))
1629 hr
= IUnknown_QueryInterface(object
, &IID_IMFMediaSink
, (void **)sink
);
1630 IUnknown_Release(object
);