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
30 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(mfplat
);
36 DEFINE_GUID(_MF_TOPO_MEDIA_ITEM
, 0x6c1bb4df, 0x59ba, 0x4020, 0x85, 0x0c, 0x35, 0x79, 0xa2, 0x7a, 0xe2, 0x51);
37 DEFINE_GUID(_MF_CUSTOM_SINK
, 0x7c1bb4df, 0x59ba, 0x4020, 0x85, 0x0c, 0x35, 0x79, 0xa2, 0x7a, 0xe2, 0x51);
39 static const WCHAR eventclassW
[] = L
"MediaPlayerEventCallbackClass";
41 static LONG startup_refcount
;
42 static HINSTANCE mfplay_instance
;
44 static void platform_startup(void)
46 if (InterlockedIncrement(&startup_refcount
) == 1)
47 MFStartup(MF_VERSION
, MFSTARTUP_FULL
);
50 static void platform_shutdown(void)
52 if (InterlockedDecrement(&startup_refcount
) == 0)
58 IMFPMediaItem IMFPMediaItem_iface
;
60 IMFPMediaPlayer
*player
;
61 IMFMediaSource
*source
;
62 IMFPresentationDescriptor
*pd
;
70 IMFPMediaPlayer IMFPMediaPlayer_iface
;
71 IPropertyStore IPropertyStore_iface
;
72 IMFAsyncCallback resolver_callback
;
73 IMFAsyncCallback events_callback
;
74 IMFAsyncCallback session_events_callback
;
76 IMFPMediaPlayerCallback
*callback
;
77 IPropertyStore
*propstore
;
78 IMFSourceResolver
*resolver
;
79 IMFMediaSession
*session
;
81 MFP_CREATION_OPTIONS options
;
82 MFP_MEDIAPLAYER_STATE state
;
90 MFP_EVENT_HEADER header
;
96 IUnknown IUnknown_iface
;
100 MFP_EVENT_HEADER header
;
101 struct generic_event generic
;
103 MFP_PAUSE_EVENT pause
;
105 MFP_POSITION_SET_EVENT position_set
;
106 MFP_RATE_SET_EVENT rate_set
;
107 MFP_MEDIAITEM_CREATED_EVENT item_created
;
108 MFP_MEDIAITEM_SET_EVENT item_set
;
109 MFP_MEDIAITEM_CLEARED_EVENT item_cleared
;
111 MFP_ERROR_EVENT error
;
112 MFP_PLAYBACK_ENDED_EVENT ended
;
113 MFP_ACQUIRE_USER_CREDENTIAL_EVENT acquire_creds
;
117 static struct media_player
*impl_from_IMFPMediaPlayer(IMFPMediaPlayer
*iface
)
119 return CONTAINING_RECORD(iface
, struct media_player
, IMFPMediaPlayer_iface
);
122 static struct media_player
*impl_from_IPropertyStore(IPropertyStore
*iface
)
124 return CONTAINING_RECORD(iface
, struct media_player
, IPropertyStore_iface
);
127 static struct media_player
*impl_from_resolver_IMFAsyncCallback(IMFAsyncCallback
*iface
)
129 return CONTAINING_RECORD(iface
, struct media_player
, resolver_callback
);
132 static struct media_player
*impl_from_events_IMFAsyncCallback(IMFAsyncCallback
*iface
)
134 return CONTAINING_RECORD(iface
, struct media_player
, events_callback
);
137 static struct media_player
*impl_from_session_events_IMFAsyncCallback(IMFAsyncCallback
*iface
)
139 return CONTAINING_RECORD(iface
, struct media_player
, session_events_callback
);
142 static struct media_item
*impl_from_IMFPMediaItem(IMFPMediaItem
*iface
)
144 return CONTAINING_RECORD(iface
, struct media_item
, IMFPMediaItem_iface
);
147 static struct media_event
*impl_event_from_IUnknown(IUnknown
*iface
)
149 return CONTAINING_RECORD(iface
, struct media_event
, IUnknown_iface
);
152 static HRESULT WINAPI
media_event_QueryInterface(IUnknown
*iface
, REFIID riid
, void **obj
)
154 if (IsEqualIID(riid
, &IID_IUnknown
))
157 IUnknown_AddRef(iface
);
162 return E_NOINTERFACE
;
165 static ULONG WINAPI
media_event_AddRef(IUnknown
*iface
)
167 struct media_event
*event
= impl_event_from_IUnknown(iface
);
168 ULONG refcount
= InterlockedIncrement(&event
->refcount
);
170 TRACE("%p, refcount %u.\n", iface
, refcount
);
175 static ULONG WINAPI
media_event_Release(IUnknown
*iface
)
177 struct media_event
*event
= impl_event_from_IUnknown(iface
);
178 ULONG refcount
= InterlockedDecrement(&event
->refcount
);
180 TRACE("%p, refcount %u.\n", iface
, refcount
);
184 if (event
->u
.header
.pMediaPlayer
)
185 IMFPMediaPlayer_Release(event
->u
.header
.pMediaPlayer
);
186 if (event
->u
.header
.pPropertyStore
)
187 IPropertyStore_Release(event
->u
.header
.pPropertyStore
);
189 switch (event
->u
.header
.eEventType
)
191 /* Most types share same layout. */
192 case MFP_EVENT_TYPE_PLAY
:
193 case MFP_EVENT_TYPE_PAUSE
:
194 case MFP_EVENT_TYPE_STOP
:
195 case MFP_EVENT_TYPE_POSITION_SET
:
196 case MFP_EVENT_TYPE_RATE_SET
:
197 case MFP_EVENT_TYPE_MEDIAITEM_CREATED
:
198 case MFP_EVENT_TYPE_MEDIAITEM_SET
:
199 case MFP_EVENT_TYPE_FRAME_STEP
:
200 case MFP_EVENT_TYPE_MEDIAITEM_CLEARED
:
201 case MFP_EVENT_TYPE_PLAYBACK_ENDED
:
202 if (event
->u
.generic
.item
)
203 IMFPMediaItem_Release(event
->u
.generic
.item
);
205 case MFP_EVENT_TYPE_MF
:
206 if (event
->u
.event
.pMFMediaEvent
)
207 IMFMediaEvent_Release(event
->u
.event
.pMFMediaEvent
);
208 if (event
->u
.event
.pMediaItem
)
209 IMFPMediaItem_Release(event
->u
.event
.pMediaItem
);
212 FIXME("Unsupported event %u.\n", event
->u
.header
.eEventType
);
222 static const IUnknownVtbl media_event_vtbl
=
224 media_event_QueryInterface
,
229 static HRESULT
media_event_create(struct media_player
*player
, MFP_EVENT_TYPE event_type
,
230 HRESULT hr
, IMFPMediaItem
*item
, struct media_event
**event
)
232 struct media_event
*object
;
234 if (!(object
= calloc(1, sizeof(*object
))))
235 return E_OUTOFMEMORY
;
237 object
->IUnknown_iface
.lpVtbl
= &media_event_vtbl
;
238 object
->refcount
= 1;
239 object
->u
.header
.eEventType
= event_type
;
240 object
->u
.header
.hrEvent
= hr
;
241 object
->u
.header
.pMediaPlayer
= &player
->IMFPMediaPlayer_iface
;
242 IMFPMediaPlayer_AddRef(object
->u
.header
.pMediaPlayer
);
243 object
->u
.header
.eState
= player
->state
;
246 case MFP_EVENT_TYPE_PLAY
:
247 case MFP_EVENT_TYPE_PAUSE
:
248 case MFP_EVENT_TYPE_STOP
:
249 case MFP_EVENT_TYPE_POSITION_SET
:
250 case MFP_EVENT_TYPE_RATE_SET
:
251 case MFP_EVENT_TYPE_MEDIAITEM_CREATED
:
252 case MFP_EVENT_TYPE_MEDIAITEM_SET
:
253 case MFP_EVENT_TYPE_FRAME_STEP
:
254 case MFP_EVENT_TYPE_MEDIAITEM_CLEARED
:
255 case MFP_EVENT_TYPE_PLAYBACK_ENDED
:
256 object
->u
.generic
.item
= item
;
257 if (object
->u
.generic
.item
)
258 IMFPMediaItem_AddRef(object
->u
.generic
.item
);
260 case MFP_EVENT_TYPE_MF
:
261 object
->u
.event
.pMediaItem
= item
;
262 if (object
->u
.event
.pMediaItem
)
263 IMFPMediaItem_AddRef(object
->u
.event
.pMediaItem
);
269 /* FIXME: set properties for some events? */
276 static LRESULT WINAPI
media_player_event_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
278 struct media_event
*event
= (void *)lparam
;
279 struct media_player
*player
;
283 player
= impl_from_IMFPMediaPlayer(event
->u
.header
.pMediaPlayer
);
284 if (player
->callback
)
285 IMFPMediaPlayerCallback_OnMediaPlayerEvent(player
->callback
, &event
->u
.header
);
286 IUnknown_Release(&event
->IUnknown_iface
);
290 return DefWindowProcW(hwnd
, msg
, wparam
, lparam
);
293 static void media_player_set_state(struct media_player
*player
, MFP_MEDIAPLAYER_STATE state
)
295 if (player
->state
!= MFP_MEDIAPLAYER_STATE_SHUTDOWN
)
297 if (state
== MFP_MEDIAPLAYER_STATE_SHUTDOWN
)
298 IMFMediaSession_Shutdown(player
->session
);
299 player
->state
= state
;
303 static HRESULT WINAPI
media_item_QueryInterface(IMFPMediaItem
*iface
, REFIID riid
, void **obj
)
305 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
307 if (IsEqualIID(riid
, &IID_IMFPMediaItem
) ||
308 IsEqualIID(riid
, &IID_IUnknown
))
311 IMFPMediaItem_AddRef(iface
);
315 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
317 return E_NOINTERFACE
;
320 static ULONG WINAPI
media_item_AddRef(IMFPMediaItem
*iface
)
322 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
323 ULONG refcount
= InterlockedIncrement(&item
->refcount
);
325 TRACE("%p, refcount %u.\n", iface
, refcount
);
330 static ULONG WINAPI
media_item_Release(IMFPMediaItem
*iface
)
332 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
333 ULONG refcount
= InterlockedDecrement(&item
->refcount
);
335 TRACE("%p, refcount %u.\n", iface
, refcount
);
340 IMFPMediaPlayer_Release(item
->player
);
342 IMFMediaSource_Release(item
->source
);
344 IMFPresentationDescriptor_Release(item
->pd
);
346 IUnknown_Release(item
->object
);
354 static HRESULT WINAPI
media_item_GetMediaPlayer(IMFPMediaItem
*iface
,
355 IMFPMediaPlayer
**player
)
357 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
359 TRACE("%p, %p.\n", iface
, player
);
361 *player
= item
->player
;
362 IMFPMediaPlayer_AddRef(*player
);
367 static HRESULT WINAPI
media_item_GetURL(IMFPMediaItem
*iface
, LPWSTR
*url
)
369 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
371 TRACE("%p, %p.\n", iface
, url
);
374 return MF_E_NOT_FOUND
;
376 if (!(*url
= CoTaskMemAlloc((wcslen(item
->url
) + 1) * sizeof(*item
->url
))))
377 return E_OUTOFMEMORY
;
379 wcscpy(*url
, item
->url
);
384 static HRESULT WINAPI
media_item_GetObject(IMFPMediaItem
*iface
, IUnknown
**object
)
386 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
388 TRACE("%p, %p.\n", iface
, object
);
391 return MF_E_NOT_FOUND
;
393 *object
= item
->object
;
394 IUnknown_AddRef(*object
);
399 static HRESULT WINAPI
media_item_GetUserData(IMFPMediaItem
*iface
, DWORD_PTR
*user_data
)
401 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
403 TRACE("%p, %p.\n", iface
, user_data
);
405 *user_data
= item
->user_data
;
410 static HRESULT WINAPI
media_item_SetUserData(IMFPMediaItem
*iface
, DWORD_PTR user_data
)
412 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
414 TRACE("%p, %lx.\n", iface
, user_data
);
416 item
->user_data
= user_data
;
421 static HRESULT WINAPI
media_item_GetStartStopPosition(IMFPMediaItem
*iface
, GUID
*start_format
,
422 PROPVARIANT
*start_position
, GUID
*stop_format
, PROPVARIANT
*stop_position
)
424 FIXME("%p, %p, %p, %p, %p.\n", iface
, start_format
, start_position
, stop_format
, stop_position
);
429 static HRESULT WINAPI
media_item_SetStartStopPosition(IMFPMediaItem
*iface
, const GUID
*start_format
,
430 const PROPVARIANT
*start_position
, const GUID
*stop_format
, const PROPVARIANT
*stop_position
)
432 FIXME("%p, %s, %p, %s, %p.\n", iface
, debugstr_guid(start_format
), start_position
,
433 debugstr_guid(stop_format
), stop_position
);
438 static HRESULT WINAPI
media_item_HasVideo(IMFPMediaItem
*iface
, BOOL
*has_video
, BOOL
*selected
)
440 FIXME("%p, %p, %p.\n", iface
, has_video
, selected
);
445 static HRESULT WINAPI
media_item_HasAudio(IMFPMediaItem
*iface
, BOOL
*has_audio
, BOOL
*selected
)
447 FIXME("%p, %p, %p.\n", iface
, has_audio
, selected
);
452 static HRESULT WINAPI
media_item_IsProtected(IMFPMediaItem
*iface
, BOOL
*protected)
454 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
456 TRACE("%p, %p.\n", iface
, protected);
458 *protected = MFRequireProtectedEnvironment(item
->pd
) == S_OK
;
463 static HRESULT WINAPI
media_item_GetDuration(IMFPMediaItem
*iface
, REFGUID format
, PROPVARIANT
*value
)
465 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
467 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(format
), value
);
469 return IMFPresentationDescriptor_GetItem(item
->pd
, &MF_PD_DURATION
, value
);
472 static HRESULT WINAPI
media_item_GetNumberOfStreams(IMFPMediaItem
*iface
, DWORD
*count
)
474 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
476 TRACE("%p, %p.\n", iface
, count
);
478 return IMFPresentationDescriptor_GetStreamDescriptorCount(item
->pd
, count
);
481 static HRESULT WINAPI
media_item_GetStreamSelection(IMFPMediaItem
*iface
, DWORD index
, BOOL
*selected
)
483 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
484 IMFStreamDescriptor
*sd
;
487 TRACE("%p, %u, %p.\n", iface
, index
, selected
);
489 if (SUCCEEDED(hr
= IMFPresentationDescriptor_GetStreamDescriptorByIndex(item
->pd
, index
, selected
, &sd
)))
490 IMFStreamDescriptor_Release(sd
);
495 static HRESULT WINAPI
media_item_SetStreamSelection(IMFPMediaItem
*iface
, DWORD index
, BOOL select
)
497 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
499 TRACE("%p, %u, %d.\n", iface
, index
, select
);
501 return select
? IMFPresentationDescriptor_SelectStream(item
->pd
, index
) :
502 IMFPresentationDescriptor_DeselectStream(item
->pd
, index
);
505 static HRESULT WINAPI
media_item_GetStreamAttribute(IMFPMediaItem
*iface
, DWORD index
, REFGUID key
,
508 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
509 IMFStreamDescriptor
*sd
;
513 TRACE("%p, %u, %s, %p.\n", iface
, index
, debugstr_guid(key
), value
);
515 if (SUCCEEDED(hr
= IMFPresentationDescriptor_GetStreamDescriptorByIndex(item
->pd
, index
, &selected
, &sd
)))
517 hr
= IMFStreamDescriptor_GetItem(sd
, key
, value
);
518 IMFStreamDescriptor_Release(sd
);
524 static HRESULT WINAPI
media_item_GetPresentationAttribute(IMFPMediaItem
*iface
, REFGUID key
,
527 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
529 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
531 return IMFPresentationDescriptor_GetItem(item
->pd
, key
, value
);
534 static HRESULT WINAPI
media_item_GetCharacteristics(IMFPMediaItem
*iface
, MFP_MEDIAITEM_CHARACTERISTICS
*flags
)
536 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
539 TRACE("%p, %p.\n", iface
, flags
);
543 if (SUCCEEDED(hr
= IMFMediaSource_GetCharacteristics(item
->source
, flags
)))
545 *flags
&= (MFP_MEDIAITEM_IS_LIVE
| MFP_MEDIAITEM_CAN_SEEK
|
546 MFP_MEDIAITEM_CAN_PAUSE
| MFP_MEDIAITEM_HAS_SLOW_SEEK
);
552 static HRESULT WINAPI
media_item_SetStreamSink(IMFPMediaItem
*iface
, DWORD index
, IUnknown
*sink
)
554 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
555 IMFStreamDescriptor
*sd
;
556 IUnknown
*sink_object
;
560 TRACE("%p, %u, %p.\n", iface
, index
, sink
);
562 if (FAILED(hr
= IMFPresentationDescriptor_GetStreamDescriptorByIndex(item
->pd
, index
, &selected
, &sd
)))
567 if (FAILED(hr
= IUnknown_QueryInterface(sink
, &IID_IMFStreamSink
, (void **)&sink_object
)))
568 hr
= IUnknown_QueryInterface(sink
, &IID_IMFActivate
, (void **)&sink_object
);
572 hr
= IMFStreamDescriptor_SetUnknown(sd
, &_MF_CUSTOM_SINK
, sink_object
);
573 IUnknown_Release(sink_object
);
577 IMFStreamDescriptor_DeleteItem(sd
, &_MF_CUSTOM_SINK
);
579 IMFStreamDescriptor_Release(sd
);
584 static HRESULT WINAPI
media_item_GetMetadata(IMFPMediaItem
*iface
, IPropertyStore
**metadata
)
586 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
588 TRACE("%p, %p.\n", iface
, metadata
);
590 return MFGetService((IUnknown
*)item
->source
, &MF_PROPERTY_HANDLER_SERVICE
,
591 &IID_IPropertyStore
, (void **)&metadata
);
594 static const IMFPMediaItemVtbl media_item_vtbl
=
596 media_item_QueryInterface
,
599 media_item_GetMediaPlayer
,
601 media_item_GetObject
,
602 media_item_GetUserData
,
603 media_item_SetUserData
,
604 media_item_GetStartStopPosition
,
605 media_item_SetStartStopPosition
,
608 media_item_IsProtected
,
609 media_item_GetDuration
,
610 media_item_GetNumberOfStreams
,
611 media_item_GetStreamSelection
,
612 media_item_SetStreamSelection
,
613 media_item_GetStreamAttribute
,
614 media_item_GetPresentationAttribute
,
615 media_item_GetCharacteristics
,
616 media_item_SetStreamSink
,
617 media_item_GetMetadata
,
620 static struct media_item
*unsafe_impl_from_IMFPMediaItem(IMFPMediaItem
*iface
)
624 assert(iface
->lpVtbl
== (IMFPMediaItemVtbl
*)&media_item_vtbl
);
625 return CONTAINING_RECORD(iface
, struct media_item
, IMFPMediaItem_iface
);
628 static HRESULT
create_media_item(IMFPMediaPlayer
*player
, DWORD_PTR user_data
, struct media_item
**item
)
630 struct media_item
*object
;
632 if (!(object
= calloc(1, sizeof(*object
))))
633 return E_OUTOFMEMORY
;
635 object
->IMFPMediaItem_iface
.lpVtbl
= &media_item_vtbl
;
636 object
->refcount
= 1;
637 object
->user_data
= user_data
;
638 object
->player
= player
;
639 IMFPMediaPlayer_AddRef(object
->player
);
646 static HRESULT
media_item_set_source(struct media_item
*item
, IUnknown
*object
)
648 IMFPresentationDescriptor
*pd
;
649 IMFMediaSource
*source
;
652 if (FAILED(hr
= IUnknown_QueryInterface(object
, &IID_IMFMediaSource
, (void **)&source
)))
655 if (FAILED(hr
= IMFMediaSource_CreatePresentationDescriptor(source
, &pd
)))
657 WARN("Failed to get presentation descriptor, hr %#x.\n", hr
);
658 IMFMediaSource_Release(source
);
662 item
->source
= source
;
668 static void media_player_queue_event(struct media_player
*player
, struct media_event
*event
)
670 if (player
->options
& MFP_OPTION_FREE_THREADED_CALLBACK
)
672 MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_MULTITHREADED
, &player
->events_callback
, &event
->IUnknown_iface
);
676 IUnknown_AddRef(&event
->IUnknown_iface
);
677 PostMessageW(player
->event_window
, WM_USER
, 0, (LPARAM
)event
);
681 static HRESULT WINAPI
media_player_QueryInterface(IMFPMediaPlayer
*iface
, REFIID riid
, void **obj
)
683 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
685 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
687 if (IsEqualIID(riid
, &IID_IMFPMediaPlayer
) ||
688 IsEqualIID(riid
, &IID_IUnknown
))
690 *obj
= &player
->IMFPMediaPlayer_iface
;
692 else if (IsEqualIID(riid
, &IID_IPropertyStore
))
694 *obj
= &player
->IPropertyStore_iface
;
698 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
701 return E_NOINTERFACE
;
704 IUnknown_AddRef((IUnknown
*)*obj
);
708 static ULONG WINAPI
media_player_AddRef(IMFPMediaPlayer
*iface
)
710 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
711 ULONG refcount
= InterlockedIncrement(&player
->refcount
);
713 TRACE("%p, refcount %u.\n", iface
, refcount
);
718 static ULONG WINAPI
media_player_Release(IMFPMediaPlayer
*iface
)
720 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
721 ULONG refcount
= InterlockedDecrement(&player
->refcount
);
723 TRACE("%p, refcount %u.\n", iface
, refcount
);
727 if (player
->callback
)
728 IMFPMediaPlayerCallback_Release(player
->callback
);
729 if (player
->propstore
)
730 IPropertyStore_Release(player
->propstore
);
731 if (player
->resolver
)
732 IMFSourceResolver_Release(player
->resolver
);
734 IMFMediaSession_Release(player
->session
);
735 DestroyWindow(player
->event_window
);
736 DeleteCriticalSection(&player
->cs
);
745 static HRESULT WINAPI
media_player_Play(IMFPMediaPlayer
*iface
)
747 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
750 TRACE("%p.\n", iface
);
753 return IMFMediaSession_Start(player
->session
, &GUID_NULL
, &pos
);
756 static HRESULT WINAPI
media_player_Pause(IMFPMediaPlayer
*iface
)
758 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
760 TRACE("%p.\n", iface
);
762 return IMFMediaSession_Pause(player
->session
);
765 static HRESULT WINAPI
media_player_Stop(IMFPMediaPlayer
*iface
)
767 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
769 TRACE("%p.\n", iface
);
771 return IMFMediaSession_Stop(player
->session
);
774 static HRESULT WINAPI
media_player_FrameStep(IMFPMediaPlayer
*iface
)
776 FIXME("%p.\n", iface
);
781 static HRESULT WINAPI
media_player_SetPosition(IMFPMediaPlayer
*iface
, REFGUID postype
, const PROPVARIANT
*position
)
783 FIXME("%p, %s, %p.\n", iface
, debugstr_guid(postype
), position
);
788 static HRESULT WINAPI
media_player_GetPosition(IMFPMediaPlayer
*iface
, REFGUID postype
, PROPVARIANT
*position
)
790 FIXME("%p, %s, %p.\n", iface
, debugstr_guid(postype
), position
);
795 static HRESULT WINAPI
media_player_GetDuration(IMFPMediaPlayer
*iface
, REFGUID postype
, PROPVARIANT
*position
)
797 FIXME("%p, %s, %p.\n", iface
, debugstr_guid(postype
), position
);
802 static HRESULT WINAPI
media_player_SetRate(IMFPMediaPlayer
*iface
, float rate
)
804 FIXME("%p, %f.\n", iface
, rate
);
809 static HRESULT WINAPI
media_player_GetRate(IMFPMediaPlayer
*iface
, float *rate
)
811 FIXME("%p, %p.\n", iface
, rate
);
816 static HRESULT WINAPI
media_player_GetSupportedRates(IMFPMediaPlayer
*iface
, BOOL forward
,
817 float *slowest_rate
, float *fastest_rate
)
819 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
823 TRACE("%p, %d, %p, %p.\n", iface
, forward
, slowest_rate
, fastest_rate
);
825 if (SUCCEEDED(hr
= MFGetService((IUnknown
*)player
->session
, &MF_RATE_CONTROL_SERVICE
, &IID_IMFRateSupport
, (void **)&rs
)))
827 if (SUCCEEDED(hr
= IMFRateSupport_GetSlowestRate(rs
, forward
? MFRATE_FORWARD
: MFRATE_REVERSE
, FALSE
, slowest_rate
)))
828 hr
= IMFRateSupport_GetFastestRate(rs
, forward
? MFRATE_FORWARD
: MFRATE_REVERSE
, FALSE
, fastest_rate
);
829 IMFRateSupport_Release(rs
);
835 static HRESULT WINAPI
media_player_GetState(IMFPMediaPlayer
*iface
, MFP_MEDIAPLAYER_STATE
*state
)
837 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
839 TRACE("%p, %p.\n", iface
, state
);
841 *state
= player
->state
;
846 static HRESULT
media_player_create_item_from_url(struct media_player
*player
,
847 const WCHAR
*url
, BOOL sync
, DWORD_PTR user_data
, IMFPMediaItem
**ret
)
849 struct media_item
*item
;
850 MF_OBJECT_TYPE obj_type
;
856 if (FAILED(hr
= create_media_item(&player
->IMFPMediaPlayer_iface
, user_data
, &item
)))
859 if (url
&& !(item
->url
= wcsdup(url
)))
861 IMFPMediaItem_Release(&item
->IMFPMediaItem_iface
);
862 return E_OUTOFMEMORY
;
867 if (SUCCEEDED(hr
= IMFSourceResolver_CreateObjectFromURL(player
->resolver
, url
, MF_RESOLUTION_MEDIASOURCE
,
868 player
->propstore
, &obj_type
, &object
)))
870 hr
= media_item_set_source(item
, object
);
871 IUnknown_Release(object
);
876 *ret
= &item
->IMFPMediaItem_iface
;
877 IMFPMediaItem_AddRef(*ret
);
880 IMFPMediaItem_Release(&item
->IMFPMediaItem_iface
);
886 hr
= IMFSourceResolver_BeginCreateObjectFromURL(player
->resolver
, url
, MF_RESOLUTION_MEDIASOURCE
,
887 player
->propstore
, NULL
, &player
->resolver_callback
, (IUnknown
*)&item
->IMFPMediaItem_iface
);
889 IMFPMediaItem_Release(&item
->IMFPMediaItem_iface
);
895 static HRESULT WINAPI
media_player_CreateMediaItemFromURL(IMFPMediaPlayer
*iface
,
896 const WCHAR
*url
, BOOL sync
, DWORD_PTR user_data
, IMFPMediaItem
**item
)
898 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
901 TRACE("%p, %s, %d, %lx, %p.\n", iface
, debugstr_w(url
), sync
, user_data
, item
);
903 EnterCriticalSection(&player
->cs
);
904 if (player
->state
== MFP_MEDIAPLAYER_STATE_SHUTDOWN
)
907 hr
= media_player_create_item_from_url(player
, url
, sync
, user_data
, item
);
908 LeaveCriticalSection(&player
->cs
);
913 static HRESULT
media_player_create_item_from_object(struct media_player
*player
,
914 IUnknown
*object
, BOOL sync
, DWORD_PTR user_data
, IMFPMediaItem
**ret
)
916 struct media_item
*item
;
917 MF_OBJECT_TYPE obj_type
;
919 IMFByteStream
*stream
= NULL
;
920 IMFMediaSource
*source
= NULL
;
924 if (FAILED(hr
= create_media_item(&player
->IMFPMediaPlayer_iface
, user_data
, &item
)))
927 item
->object
= object
;
928 IUnknown_AddRef(item
->object
);
930 if (FAILED(IUnknown_QueryInterface(object
, &IID_IMFMediaSource
, (void **)&source
)))
931 IUnknown_QueryInterface(object
, &IID_IMFByteStream
, (void **)&stream
);
933 if (!source
&& !stream
)
935 WARN("Unsupported object type.\n");
936 IMFPMediaItem_Release(&item
->IMFPMediaItem_iface
);
943 hr
= IMFSourceResolver_CreateObjectFromByteStream(player
->resolver
, stream
, NULL
,
944 MF_RESOLUTION_MEDIASOURCE
, player
->propstore
, &obj_type
, &object
);
946 IUnknown_AddRef(object
);
949 hr
= media_item_set_source(item
, object
);
951 IUnknown_Release(object
);
955 *ret
= &item
->IMFPMediaItem_iface
;
956 IMFPMediaItem_AddRef(*ret
);
959 IMFPMediaItem_Release(&item
->IMFPMediaItem_iface
);
965 hr
= IMFSourceResolver_BeginCreateObjectFromByteStream(player
->resolver
, stream
, NULL
, MF_RESOLUTION_MEDIASOURCE
,
966 player
->propstore
, NULL
, &player
->resolver_callback
, (IUnknown
*)&item
->IMFPMediaItem_iface
);
970 /* Resolver callback will check again if item's object is a source. */
971 hr
= MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_MULTITHREADED
, &player
->resolver_callback
,
972 (IUnknown
*)&item
->IMFPMediaItem_iface
);
975 IMFPMediaItem_Release(&item
->IMFPMediaItem_iface
);
979 IMFMediaSource_Release(source
);
981 IMFByteStream_Release(stream
);
986 static HRESULT WINAPI
media_player_CreateMediaItemFromObject(IMFPMediaPlayer
*iface
,
987 IUnknown
*object
, BOOL sync
, DWORD_PTR user_data
, IMFPMediaItem
**item
)
989 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
992 TRACE("%p, %p, %d, %lx, %p.\n", iface
, object
, sync
, user_data
, item
);
994 EnterCriticalSection(&player
->cs
);
995 if (player
->state
== MFP_MEDIAPLAYER_STATE_SHUTDOWN
)
998 hr
= media_player_create_item_from_object(player
, object
, sync
, user_data
, item
);
999 LeaveCriticalSection(&player
->cs
);
1004 static HRESULT
media_item_get_stream_type(IMFStreamDescriptor
*sd
, GUID
*major
)
1006 IMFMediaTypeHandler
*handler
;
1009 if (SUCCEEDED(hr
= IMFStreamDescriptor_GetMediaTypeHandler(sd
, &handler
)))
1011 hr
= IMFMediaTypeHandler_GetMajorType(handler
, major
);
1012 IMFMediaTypeHandler_Release(handler
);
1018 static HRESULT
media_item_create_topology(struct media_player
*player
, struct media_item
*item
, IMFTopology
**out
)
1020 IMFTopologyNode
*src_node
, *sink_node
;
1021 IMFActivate
*sar_activate
;
1022 IMFStreamDescriptor
*sd
;
1023 IMFTopology
*topology
;
1029 if (FAILED(hr
= MFCreateTopology(&topology
)))
1032 /* FIXME: handle user sinks */
1034 /* Use first stream if none selected. */
1035 if (player
->output_window
)
1037 FIXME("Video streams are not handled.\n");
1040 /* Set up audio branches for all selected streams. */
1043 while (SUCCEEDED(IMFPresentationDescriptor_GetStreamDescriptorByIndex(item
->pd
, idx
++, &selected
, &sd
)))
1045 if (selected
&& SUCCEEDED(media_item_get_stream_type(sd
, &major
)) && IsEqualGUID(&major
, &MFMediaType_Audio
))
1047 if (SUCCEEDED(hr
= MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE
, &src_node
)))
1049 IMFTopologyNode_SetUnknown(src_node
, &MF_TOPONODE_SOURCE
, (IUnknown
*)item
->source
);
1050 IMFTopologyNode_SetUnknown(src_node
, &MF_TOPONODE_PRESENTATION_DESCRIPTOR
, (IUnknown
*)item
->pd
);
1051 IMFTopologyNode_SetUnknown(src_node
, &MF_TOPONODE_STREAM_DESCRIPTOR
, (IUnknown
*)sd
);
1053 IMFTopology_AddNode(topology
, src_node
);
1056 if (SUCCEEDED(hr
= MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE
, &sink_node
)))
1058 if (SUCCEEDED(MFCreateAudioRendererActivate(&sar_activate
)))
1060 IMFTopologyNode_SetObject(sink_node
, (IUnknown
*)sar_activate
);
1061 IMFActivate_Release(sar_activate
);
1064 IMFTopology_AddNode(topology
, sink_node
);
1067 if (src_node
&& sink_node
)
1068 IMFTopologyNode_ConnectOutput(src_node
, 0, sink_node
, 0);
1071 IMFTopologyNode_Release(src_node
);
1073 IMFTopologyNode_Release(sink_node
);
1076 IMFStreamDescriptor_Release(sd
);
1084 static HRESULT WINAPI
media_player_SetMediaItem(IMFPMediaPlayer
*iface
, IMFPMediaItem
*item_iface
)
1086 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1087 struct media_item
*item
= unsafe_impl_from_IMFPMediaItem(item_iface
);
1088 IMFTopology
*topology
;
1091 TRACE("%p, %p.\n", iface
, item_iface
);
1093 if (item
->player
!= iface
)
1094 return E_INVALIDARG
;
1096 if (FAILED(hr
= media_item_create_topology(player
, item
, &topology
)))
1099 IMFTopology_SetUnknown(topology
, &_MF_TOPO_MEDIA_ITEM
, (IUnknown
*)item_iface
);
1100 hr
= IMFMediaSession_SetTopology(player
->session
, MFSESSION_SETTOPOLOGY_IMMEDIATE
, topology
);
1101 IMFTopology_Release(topology
);
1106 static HRESULT WINAPI
media_player_ClearMediaItem(IMFPMediaPlayer
*iface
)
1108 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1110 TRACE("%p.\n", iface
);
1112 return IMFMediaSession_SetTopology(player
->session
, MFSESSION_SETTOPOLOGY_CLEAR_CURRENT
, NULL
);
1115 static HRESULT WINAPI
media_player_GetMediaItem(IMFPMediaPlayer
*iface
, IMFPMediaItem
**item
)
1117 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1120 TRACE("%p, %p.\n", iface
, item
);
1125 EnterCriticalSection(&player
->cs
);
1126 if (player
->state
== MFP_MEDIAPLAYER_STATE_SHUTDOWN
)
1128 else if (!player
->item
)
1129 hr
= MF_E_NOT_FOUND
;
1132 *item
= player
->item
;
1133 IMFPMediaItem_AddRef(player
->item
);
1135 LeaveCriticalSection(&player
->cs
);
1140 static HRESULT WINAPI
media_player_GetVolume(IMFPMediaPlayer
*iface
, float *volume
)
1142 FIXME("%p, %p.\n", iface
, volume
);
1147 static HRESULT WINAPI
media_player_SetVolume(IMFPMediaPlayer
*iface
, float volume
)
1149 FIXME("%p, %.8e.\n", iface
, volume
);
1154 static HRESULT WINAPI
media_player_GetBalance(IMFPMediaPlayer
*iface
, float *balance
)
1156 FIXME("%p, %p.\n", iface
, balance
);
1161 static HRESULT WINAPI
media_player_SetBalance(IMFPMediaPlayer
*iface
, float balance
)
1163 FIXME("%p, %.8e.\n", iface
, balance
);
1168 static HRESULT WINAPI
media_player_GetMute(IMFPMediaPlayer
*iface
, BOOL
*mute
)
1170 FIXME("%p, %p.\n", iface
, mute
);
1175 static HRESULT WINAPI
media_player_SetMute(IMFPMediaPlayer
*iface
, BOOL mute
)
1177 FIXME("%p, %d.\n", iface
, mute
);
1182 static HRESULT WINAPI
media_player_GetNativeVideoSize(IMFPMediaPlayer
*iface
,
1183 SIZE
*video
, SIZE
*arvideo
)
1185 FIXME("%p, %p, %p.\n", iface
, video
, arvideo
);
1190 static HRESULT WINAPI
media_player_GetIdealVideoSize(IMFPMediaPlayer
*iface
,
1191 SIZE
*min_size
, SIZE
*max_size
)
1193 FIXME("%p, %p, %p.\n", iface
, min_size
, max_size
);
1198 static HRESULT WINAPI
media_player_SetVideoSourceRect(IMFPMediaPlayer
*iface
,
1199 MFVideoNormalizedRect
const *rect
)
1201 FIXME("%p, %p.\n", iface
, rect
);
1206 static HRESULT WINAPI
media_player_GetVideoSourceRect(IMFPMediaPlayer
*iface
,
1207 MFVideoNormalizedRect
*rect
)
1209 FIXME("%p, %p.\n", iface
, rect
);
1214 static HRESULT WINAPI
media_player_SetAspectRatioMode(IMFPMediaPlayer
*iface
, DWORD mode
)
1216 FIXME("%p, %u.\n", iface
, mode
);
1221 static HRESULT WINAPI
media_player_GetAspectRatioMode(IMFPMediaPlayer
*iface
,
1224 FIXME("%p, %p.\n", iface
, mode
);
1229 static HRESULT WINAPI
media_player_GetVideoWindow(IMFPMediaPlayer
*iface
, HWND
*window
)
1231 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1233 TRACE("%p, %p.\n", iface
, window
);
1235 *window
= player
->output_window
;
1240 static HRESULT WINAPI
media_player_UpdateVideo(IMFPMediaPlayer
*iface
)
1242 FIXME("%p.\n", iface
);
1247 static HRESULT WINAPI
media_player_SetBorderColor(IMFPMediaPlayer
*iface
, COLORREF color
)
1249 FIXME("%p, %#x.\n", iface
, color
);
1254 static HRESULT WINAPI
media_player_GetBorderColor(IMFPMediaPlayer
*iface
, COLORREF
*color
)
1256 FIXME("%p, %p.\n", iface
, color
);
1261 static HRESULT WINAPI
media_player_InsertEffect(IMFPMediaPlayer
*iface
, IUnknown
*effect
,
1264 FIXME("%p, %p, %d.\n", iface
, effect
, optional
);
1269 static HRESULT WINAPI
media_player_RemoveEffect(IMFPMediaPlayer
*iface
, IUnknown
*effect
)
1271 FIXME("%p, %p.\n", iface
, effect
);
1276 static HRESULT WINAPI
media_player_RemoveAllEffects(IMFPMediaPlayer
*iface
)
1278 FIXME("%p.\n", iface
);
1283 static HRESULT WINAPI
media_player_Shutdown(IMFPMediaPlayer
*iface
)
1285 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1287 TRACE("%p.\n", iface
);
1289 EnterCriticalSection(&player
->cs
);
1290 media_player_set_state(player
, MFP_MEDIAPLAYER_STATE_SHUTDOWN
);
1293 IMFPMediaItem_Release(player
->item
);
1294 player
->item
= NULL
;
1296 LeaveCriticalSection(&player
->cs
);
1301 static const IMFPMediaPlayerVtbl media_player_vtbl
=
1303 media_player_QueryInterface
,
1304 media_player_AddRef
,
1305 media_player_Release
,
1309 media_player_FrameStep
,
1310 media_player_SetPosition
,
1311 media_player_GetPosition
,
1312 media_player_GetDuration
,
1313 media_player_SetRate
,
1314 media_player_GetRate
,
1315 media_player_GetSupportedRates
,
1316 media_player_GetState
,
1317 media_player_CreateMediaItemFromURL
,
1318 media_player_CreateMediaItemFromObject
,
1319 media_player_SetMediaItem
,
1320 media_player_ClearMediaItem
,
1321 media_player_GetMediaItem
,
1322 media_player_GetVolume
,
1323 media_player_SetVolume
,
1324 media_player_GetBalance
,
1325 media_player_SetBalance
,
1326 media_player_GetMute
,
1327 media_player_SetMute
,
1328 media_player_GetNativeVideoSize
,
1329 media_player_GetIdealVideoSize
,
1330 media_player_SetVideoSourceRect
,
1331 media_player_GetVideoSourceRect
,
1332 media_player_SetAspectRatioMode
,
1333 media_player_GetAspectRatioMode
,
1334 media_player_GetVideoWindow
,
1335 media_player_UpdateVideo
,
1336 media_player_SetBorderColor
,
1337 media_player_GetBorderColor
,
1338 media_player_InsertEffect
,
1339 media_player_RemoveEffect
,
1340 media_player_RemoveAllEffects
,
1341 media_player_Shutdown
,
1344 static HRESULT WINAPI
media_player_propstore_QueryInterface(IPropertyStore
*iface
,
1345 REFIID riid
, void **obj
)
1347 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1348 return IMFPMediaPlayer_QueryInterface(&player
->IMFPMediaPlayer_iface
, riid
, obj
);
1351 static ULONG WINAPI
media_player_propstore_AddRef(IPropertyStore
*iface
)
1353 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1354 return IMFPMediaPlayer_AddRef(&player
->IMFPMediaPlayer_iface
);
1357 static ULONG WINAPI
media_player_propstore_Release(IPropertyStore
*iface
)
1359 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1360 return IMFPMediaPlayer_Release(&player
->IMFPMediaPlayer_iface
);
1363 static HRESULT WINAPI
media_player_propstore_GetCount(IPropertyStore
*iface
, DWORD
*count
)
1365 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1367 TRACE("%p, %p.\n", iface
, count
);
1369 return IPropertyStore_GetCount(player
->propstore
, count
);
1372 static HRESULT WINAPI
media_player_propstore_GetAt(IPropertyStore
*iface
, DWORD prop
, PROPERTYKEY
*key
)
1374 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1376 TRACE("%p, %u, %p.\n", iface
, prop
, key
);
1378 return IPropertyStore_GetAt(player
->propstore
, prop
, key
);
1381 static HRESULT WINAPI
media_player_propstore_GetValue(IPropertyStore
*iface
, REFPROPERTYKEY key
, PROPVARIANT
*value
)
1383 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1385 TRACE("%p, %p, %p.\n", iface
, key
, value
);
1387 return IPropertyStore_GetValue(player
->propstore
, key
, value
);
1390 static HRESULT WINAPI
media_player_propstore_SetValue(IPropertyStore
*iface
, REFPROPERTYKEY key
, REFPROPVARIANT value
)
1392 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1394 TRACE("%p, %p, %p.\n", iface
, key
, value
);
1396 return IPropertyStore_SetValue(player
->propstore
, key
, value
);
1399 static HRESULT WINAPI
media_player_propstore_Commit(IPropertyStore
*iface
)
1401 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1403 TRACE("%p.\n", iface
);
1405 return IPropertyStore_Commit(player
->propstore
);
1408 static const IPropertyStoreVtbl media_player_propstore_vtbl
=
1410 media_player_propstore_QueryInterface
,
1411 media_player_propstore_AddRef
,
1412 media_player_propstore_Release
,
1413 media_player_propstore_GetCount
,
1414 media_player_propstore_GetAt
,
1415 media_player_propstore_GetValue
,
1416 media_player_propstore_SetValue
,
1417 media_player_propstore_Commit
,
1420 static HRESULT WINAPI
media_player_callback_QueryInterface(IMFAsyncCallback
*iface
,
1421 REFIID riid
, void **obj
)
1423 if (IsEqualIID(riid
, &IID_IMFAsyncCallback
) ||
1424 IsEqualIID(riid
, &IID_IUnknown
))
1427 IMFAsyncCallback_AddRef(iface
);
1432 return E_NOINTERFACE
;
1435 static ULONG WINAPI
media_player_resolver_callback_AddRef(IMFAsyncCallback
*iface
)
1437 struct media_player
*player
= impl_from_resolver_IMFAsyncCallback(iface
);
1438 return IMFPMediaPlayer_AddRef(&player
->IMFPMediaPlayer_iface
);
1441 static ULONG WINAPI
media_player_resolver_callback_Release(IMFAsyncCallback
*iface
)
1443 struct media_player
*player
= impl_from_resolver_IMFAsyncCallback(iface
);
1444 return IMFPMediaPlayer_Release(&player
->IMFPMediaPlayer_iface
);
1447 static HRESULT WINAPI
media_player_callback_GetParameters(IMFAsyncCallback
*iface
, DWORD
*flags
,
1453 static HRESULT WINAPI
media_player_resolver_callback_Invoke(IMFAsyncCallback
*iface
, IMFAsyncResult
*result
)
1455 struct media_player
*player
= impl_from_resolver_IMFAsyncCallback(iface
);
1456 struct media_event
*event
;
1457 IUnknown
*object
, *state
;
1458 MF_OBJECT_TYPE obj_type
;
1459 struct media_item
*item
;
1462 if (FAILED(IMFAsyncResult_GetState(result
, &state
)))
1465 item
= impl_from_IMFPMediaItem((IMFPMediaItem
*)state
);
1469 if (FAILED(hr
= IUnknown_QueryInterface(item
->object
, &IID_IMFMediaSource
, (void **)&object
)))
1470 hr
= IMFSourceResolver_EndCreateObjectFromByteStream(player
->resolver
, result
, &obj_type
, &object
);
1473 hr
= IMFSourceResolver_EndCreateObjectFromURL(player
->resolver
, result
, &obj_type
, &object
);
1477 hr
= media_item_set_source(item
, object
);
1478 IUnknown_Release(object
);
1482 WARN("Failed to set media source, hr %#x.\n", hr
);
1484 if (FAILED(media_event_create(player
, MFP_EVENT_TYPE_MEDIAITEM_CREATED
, hr
,
1485 &item
->IMFPMediaItem_iface
, &event
)))
1487 WARN("Failed to create event object.\n");
1488 IUnknown_Release(state
);
1491 event
->u
.item_created
.dwUserData
= item
->user_data
;
1493 media_player_queue_event(player
, event
);
1495 IUnknown_Release(&event
->IUnknown_iface
);
1496 IUnknown_Release(state
);
1501 static const IMFAsyncCallbackVtbl media_player_resolver_callback_vtbl
=
1503 media_player_callback_QueryInterface
,
1504 media_player_resolver_callback_AddRef
,
1505 media_player_resolver_callback_Release
,
1506 media_player_callback_GetParameters
,
1507 media_player_resolver_callback_Invoke
,
1510 static ULONG WINAPI
media_player_events_callback_AddRef(IMFAsyncCallback
*iface
)
1512 struct media_player
*player
= impl_from_events_IMFAsyncCallback(iface
);
1513 return IMFPMediaPlayer_AddRef(&player
->IMFPMediaPlayer_iface
);
1516 static ULONG WINAPI
media_player_events_callback_Release(IMFAsyncCallback
*iface
)
1518 struct media_player
*player
= impl_from_events_IMFAsyncCallback(iface
);
1519 return IMFPMediaPlayer_Release(&player
->IMFPMediaPlayer_iface
);
1522 static HRESULT WINAPI
media_player_events_callback_Invoke(IMFAsyncCallback
*iface
, IMFAsyncResult
*result
)
1524 struct media_player
*player
= impl_from_events_IMFAsyncCallback(iface
);
1525 struct media_event
*event
;
1528 if (FAILED(IMFAsyncResult_GetState(result
, &state
)))
1531 event
= impl_event_from_IUnknown(state
);
1533 if (player
->callback
)
1534 IMFPMediaPlayerCallback_OnMediaPlayerEvent(player
->callback
, &event
->u
.header
);
1536 IUnknown_Release(state
);
1541 static const IMFAsyncCallbackVtbl media_player_events_callback_vtbl
=
1543 media_player_callback_QueryInterface
,
1544 media_player_events_callback_AddRef
,
1545 media_player_events_callback_Release
,
1546 media_player_callback_GetParameters
,
1547 media_player_events_callback_Invoke
,
1550 static ULONG WINAPI
media_player_session_events_callback_AddRef(IMFAsyncCallback
*iface
)
1552 struct media_player
*player
= impl_from_session_events_IMFAsyncCallback(iface
);
1553 return IMFPMediaPlayer_AddRef(&player
->IMFPMediaPlayer_iface
);
1556 static ULONG WINAPI
media_player_session_events_callback_Release(IMFAsyncCallback
*iface
)
1558 struct media_player
*player
= impl_from_session_events_IMFAsyncCallback(iface
);
1559 return IMFPMediaPlayer_Release(&player
->IMFPMediaPlayer_iface
);
1562 static void media_player_change_state(struct media_player
*player
, MFP_MEDIAPLAYER_STATE state
,
1563 HRESULT event_status
, struct media_event
**event
)
1565 MFP_EVENT_TYPE event_type
;
1567 EnterCriticalSection(&player
->cs
);
1569 if (state
== MFP_MEDIAPLAYER_STATE_PLAYING
)
1570 event_type
= MFP_EVENT_TYPE_PLAY
;
1571 else if (state
== MFP_MEDIAPLAYER_STATE_PAUSED
)
1572 event_type
= MFP_EVENT_TYPE_PAUSE
;
1574 event_type
= MFP_EVENT_TYPE_STOP
;
1576 media_player_set_state(player
, state
);
1577 media_event_create(player
, event_type
, event_status
, player
->item
, event
);
1579 LeaveCriticalSection(&player
->cs
);
1582 static void media_player_set_item(struct media_player
*player
, IMFTopology
*topology
, HRESULT event_status
,
1583 struct media_event
**event
)
1585 IMFPMediaItem
*item
;
1587 if (FAILED(IMFTopology_GetUnknown(topology
, &_MF_TOPO_MEDIA_ITEM
, &IID_IMFPMediaItem
, (void **)&item
)))
1590 EnterCriticalSection(&player
->cs
);
1593 IMFPMediaItem_Release(player
->item
);
1594 player
->item
= item
;
1595 IMFPMediaItem_AddRef(player
->item
);
1597 media_event_create(player
, MFP_EVENT_TYPE_MEDIAITEM_SET
, event_status
, item
, event
);
1599 LeaveCriticalSection(&player
->cs
);
1601 IMFPMediaItem_Release(item
);
1604 static void media_player_clear_item(struct media_player
*player
, HRESULT event_status
,
1605 struct media_event
**event
)
1607 IMFPMediaItem
*item
;
1609 EnterCriticalSection(&player
->cs
);
1611 item
= player
->item
;
1612 player
->item
= NULL
;
1614 media_event_create(player
, MFP_EVENT_TYPE_MEDIAITEM_SET
, event_status
, item
, event
);
1616 LeaveCriticalSection(&player
->cs
);
1619 static void media_player_create_forward_event(struct media_player
*player
, HRESULT event_status
, IMFMediaEvent
*session_event
,
1620 struct media_event
**event
)
1622 EnterCriticalSection(&player
->cs
);
1624 if (SUCCEEDED(media_event_create(player
, MFP_EVENT_TYPE_MF
, event_status
, player
->item
, event
)))
1626 IMFMediaEvent_GetType(session_event
, &(*event
)->u
.event
.MFEventType
);
1627 (*event
)->u
.event
.pMFMediaEvent
= session_event
;
1628 IMFMediaEvent_AddRef((*event
)->u
.event
.pMFMediaEvent
);
1631 LeaveCriticalSection(&player
->cs
);
1634 static void media_player_create_playback_ended_event(struct media_player
*player
, HRESULT event_status
,
1635 struct media_event
**event
)
1637 EnterCriticalSection(&player
->cs
);
1639 if (SUCCEEDED(media_event_create(player
, MFP_EVENT_TYPE_PLAYBACK_ENDED
, event_status
, player
->item
, event
)))
1642 IMFPMediaItem_Release(player
->item
);
1643 player
->item
= NULL
;
1646 LeaveCriticalSection(&player
->cs
);
1649 static HRESULT WINAPI
media_player_session_events_callback_Invoke(IMFAsyncCallback
*iface
,
1650 IMFAsyncResult
*result
)
1652 struct media_player
*player
= impl_from_session_events_IMFAsyncCallback(iface
);
1653 MediaEventType session_event_type
= MEUnknown
;
1654 struct media_event
*event
= NULL
;
1655 IMFMediaEvent
*session_event
;
1656 MFP_MEDIAPLAYER_STATE state
;
1657 HRESULT hr
, event_status
;
1658 IMFPMediaItem
*item
= NULL
;
1659 IMFTopology
*topology
;
1660 unsigned int status
;
1663 if (FAILED(hr
= IMFMediaSession_EndGetEvent(player
->session
, result
, &session_event
)))
1666 IMFMediaEvent_GetType(session_event
, &session_event_type
);
1667 IMFMediaEvent_GetStatus(session_event
, &event_status
);
1669 switch (session_event_type
)
1671 case MESessionStarted
:
1672 case MESessionStopped
:
1673 case MESessionPaused
:
1675 if (session_event_type
== MESessionStarted
)
1676 state
= MFP_MEDIAPLAYER_STATE_PLAYING
;
1677 else if (session_event_type
== MESessionPaused
)
1678 state
= MFP_MEDIAPLAYER_STATE_PAUSED
;
1680 state
= MFP_MEDIAPLAYER_STATE_STOPPED
;
1682 media_player_change_state(player
, state
, event_status
, &event
);
1686 case MESessionTopologySet
:
1688 value
.vt
= VT_EMPTY
;
1689 if (SUCCEEDED(IMFMediaEvent_GetValue(session_event
, &value
)))
1691 if (value
.vt
== VT_EMPTY
)
1693 media_player_clear_item(player
, event_status
, &event
);
1695 else if (value
.vt
== VT_UNKNOWN
&& value
.punkVal
&&
1696 SUCCEEDED(IUnknown_QueryInterface(value
.punkVal
, &IID_IMFTopology
, (void **)&topology
)))
1698 media_player_set_item(player
, topology
, event_status
, &event
);
1699 IMFTopology_Release(topology
);
1701 PropVariantClear(&value
);
1706 case MESessionTopologyStatus
:
1708 if (SUCCEEDED(IMFMediaEvent_GetUINT32(session_event
, &MF_EVENT_TOPOLOGY_STATUS
, &status
)) &&
1709 status
== MF_TOPOSTATUS_ENDED
)
1711 media_player_create_playback_ended_event(player
, event_status
, &event
);
1716 case MEBufferingStarted
:
1717 case MEBufferingStopped
:
1718 case MEExtendedType
:
1719 case MEReconnectStart
:
1720 case MEReconnectEnd
:
1721 case MERendererEvent
:
1722 case MEStreamSinkFormatChanged
:
1724 media_player_create_forward_event(player
, event_status
, session_event
, &event
);
1730 media_event_create(player
, MFP_EVENT_TYPE_ERROR
, event_status
, NULL
, &event
);
1739 IMFPMediaItem_Release(item
);
1743 media_player_queue_event(player
, event
);
1744 IUnknown_Release(&event
->IUnknown_iface
);
1747 IMFMediaSession_BeginGetEvent(player
->session
, &player
->session_events_callback
, NULL
);
1748 IMFMediaEvent_Release(session_event
);
1753 static const IMFAsyncCallbackVtbl media_player_session_events_callback_vtbl
=
1755 media_player_callback_QueryInterface
,
1756 media_player_session_events_callback_AddRef
,
1757 media_player_session_events_callback_Release
,
1758 media_player_callback_GetParameters
,
1759 media_player_session_events_callback_Invoke
,
1762 HRESULT WINAPI
MFPCreateMediaPlayer(const WCHAR
*url
, BOOL start_playback
, MFP_CREATION_OPTIONS options
,
1763 IMFPMediaPlayerCallback
*callback
, HWND window
, IMFPMediaPlayer
**player
)
1765 struct media_player
*object
;
1768 TRACE("%s, %d, %#x, %p, %p, %p.\n", debugstr_w(url
), start_playback
, options
, callback
, window
, player
);
1770 if (!(object
= calloc(1, sizeof(*object
))))
1771 return E_OUTOFMEMORY
;
1775 object
->IMFPMediaPlayer_iface
.lpVtbl
= &media_player_vtbl
;
1776 object
->IPropertyStore_iface
.lpVtbl
= &media_player_propstore_vtbl
;
1777 object
->resolver_callback
.lpVtbl
= &media_player_resolver_callback_vtbl
;
1778 object
->events_callback
.lpVtbl
= &media_player_events_callback_vtbl
;
1779 object
->session_events_callback
.lpVtbl
= &media_player_session_events_callback_vtbl
;
1780 object
->refcount
= 1;
1781 object
->callback
= callback
;
1782 if (object
->callback
)
1783 IMFPMediaPlayerCallback_AddRef(object
->callback
);
1784 object
->options
= options
;
1785 object
->output_window
= window
;
1786 InitializeCriticalSection(&object
->cs
);
1787 if (FAILED(hr
= CreatePropertyStore(&object
->propstore
)))
1789 if (FAILED(hr
= MFCreateSourceResolver(&object
->resolver
)))
1791 if (FAILED(hr
= MFCreateMediaSession(NULL
, &object
->session
)))
1793 if (FAILED(hr
= IMFMediaSession_BeginGetEvent(object
->session
, &object
->session_events_callback
, NULL
)))
1795 if (!(object
->options
& MFP_OPTION_FREE_THREADED_CALLBACK
))
1797 object
->event_window
= CreateWindowW(eventclassW
, NULL
, 0, 0, 0, 0, 0, HWND_MESSAGE
,
1798 0, mfplay_instance
, NULL
);
1801 *player
= &object
->IMFPMediaPlayer_iface
;
1807 IMFPMediaPlayer_Release(&object
->IMFPMediaPlayer_iface
);
1812 static void media_player_register_window_class(void)
1814 WNDCLASSW cls
= { 0 };
1816 cls
.lpfnWndProc
= media_player_event_proc
;
1817 cls
.hInstance
= mfplay_instance
;
1818 cls
.lpszClassName
= eventclassW
;
1820 RegisterClassW(&cls
);
1823 BOOL WINAPI
DllMain(HINSTANCE instance
, DWORD reason
, void *reserved
)
1827 case DLL_PROCESS_ATTACH
:
1828 mfplay_instance
= instance
;
1829 DisableThreadLibraryCalls(instance
);
1830 media_player_register_window_class();
1832 case DLL_PROCESS_DETACH
:
1833 if (reserved
) break;
1834 UnregisterClassW(eventclassW
, instance
);