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
;
66 LONGLONG start_position
;
67 LONGLONG stop_position
;
72 IMFPMediaPlayer IMFPMediaPlayer_iface
;
73 IPropertyStore IPropertyStore_iface
;
74 IMFAsyncCallback resolver_callback
;
75 IMFAsyncCallback events_callback
;
76 IMFAsyncCallback session_events_callback
;
78 IMFPMediaPlayerCallback
*callback
;
79 IPropertyStore
*propstore
;
80 IMFSourceResolver
*resolver
;
81 IMFMediaSession
*session
;
83 MFP_CREATION_OPTIONS options
;
84 MFP_MEDIAPLAYER_STATE state
;
92 MFP_EVENT_HEADER header
;
98 IUnknown IUnknown_iface
;
102 MFP_EVENT_HEADER header
;
103 struct generic_event generic
;
105 MFP_PAUSE_EVENT pause
;
107 MFP_POSITION_SET_EVENT position_set
;
108 MFP_RATE_SET_EVENT rate_set
;
109 MFP_MEDIAITEM_CREATED_EVENT item_created
;
110 MFP_MEDIAITEM_SET_EVENT item_set
;
111 MFP_MEDIAITEM_CLEARED_EVENT item_cleared
;
113 MFP_ERROR_EVENT error
;
114 MFP_PLAYBACK_ENDED_EVENT ended
;
115 MFP_ACQUIRE_USER_CREDENTIAL_EVENT acquire_creds
;
119 static struct media_player
*impl_from_IMFPMediaPlayer(IMFPMediaPlayer
*iface
)
121 return CONTAINING_RECORD(iface
, struct media_player
, IMFPMediaPlayer_iface
);
124 static struct media_player
*impl_from_IPropertyStore(IPropertyStore
*iface
)
126 return CONTAINING_RECORD(iface
, struct media_player
, IPropertyStore_iface
);
129 static struct media_player
*impl_from_resolver_IMFAsyncCallback(IMFAsyncCallback
*iface
)
131 return CONTAINING_RECORD(iface
, struct media_player
, resolver_callback
);
134 static struct media_player
*impl_from_events_IMFAsyncCallback(IMFAsyncCallback
*iface
)
136 return CONTAINING_RECORD(iface
, struct media_player
, events_callback
);
139 static struct media_player
*impl_from_session_events_IMFAsyncCallback(IMFAsyncCallback
*iface
)
141 return CONTAINING_RECORD(iface
, struct media_player
, session_events_callback
);
144 static struct media_item
*impl_from_IMFPMediaItem(IMFPMediaItem
*iface
)
146 return CONTAINING_RECORD(iface
, struct media_item
, IMFPMediaItem_iface
);
149 static struct media_event
*impl_event_from_IUnknown(IUnknown
*iface
)
151 return CONTAINING_RECORD(iface
, struct media_event
, IUnknown_iface
);
154 static HRESULT WINAPI
media_event_QueryInterface(IUnknown
*iface
, REFIID riid
, void **obj
)
156 if (IsEqualIID(riid
, &IID_IUnknown
))
159 IUnknown_AddRef(iface
);
164 return E_NOINTERFACE
;
167 static ULONG WINAPI
media_event_AddRef(IUnknown
*iface
)
169 struct media_event
*event
= impl_event_from_IUnknown(iface
);
170 ULONG refcount
= InterlockedIncrement(&event
->refcount
);
172 TRACE("%p, refcount %u.\n", iface
, refcount
);
177 static ULONG WINAPI
media_event_Release(IUnknown
*iface
)
179 struct media_event
*event
= impl_event_from_IUnknown(iface
);
180 ULONG refcount
= InterlockedDecrement(&event
->refcount
);
182 TRACE("%p, refcount %u.\n", iface
, refcount
);
186 if (event
->u
.header
.pMediaPlayer
)
187 IMFPMediaPlayer_Release(event
->u
.header
.pMediaPlayer
);
188 if (event
->u
.header
.pPropertyStore
)
189 IPropertyStore_Release(event
->u
.header
.pPropertyStore
);
191 switch (event
->u
.header
.eEventType
)
193 /* Most types share same layout. */
194 case MFP_EVENT_TYPE_PLAY
:
195 case MFP_EVENT_TYPE_PAUSE
:
196 case MFP_EVENT_TYPE_STOP
:
197 case MFP_EVENT_TYPE_POSITION_SET
:
198 case MFP_EVENT_TYPE_RATE_SET
:
199 case MFP_EVENT_TYPE_MEDIAITEM_CREATED
:
200 case MFP_EVENT_TYPE_MEDIAITEM_SET
:
201 case MFP_EVENT_TYPE_FRAME_STEP
:
202 case MFP_EVENT_TYPE_MEDIAITEM_CLEARED
:
203 case MFP_EVENT_TYPE_PLAYBACK_ENDED
:
204 if (event
->u
.generic
.item
)
205 IMFPMediaItem_Release(event
->u
.generic
.item
);
207 case MFP_EVENT_TYPE_MF
:
208 if (event
->u
.event
.pMFMediaEvent
)
209 IMFMediaEvent_Release(event
->u
.event
.pMFMediaEvent
);
210 if (event
->u
.event
.pMediaItem
)
211 IMFPMediaItem_Release(event
->u
.event
.pMediaItem
);
214 FIXME("Unsupported event %u.\n", event
->u
.header
.eEventType
);
224 static const IUnknownVtbl media_event_vtbl
=
226 media_event_QueryInterface
,
231 static HRESULT
media_event_create(struct media_player
*player
, MFP_EVENT_TYPE event_type
,
232 HRESULT hr
, IMFPMediaItem
*item
, struct media_event
**event
)
234 struct media_event
*object
;
236 if (!(object
= calloc(1, sizeof(*object
))))
237 return E_OUTOFMEMORY
;
239 object
->IUnknown_iface
.lpVtbl
= &media_event_vtbl
;
240 object
->refcount
= 1;
241 object
->u
.header
.eEventType
= event_type
;
242 object
->u
.header
.hrEvent
= hr
;
243 object
->u
.header
.pMediaPlayer
= &player
->IMFPMediaPlayer_iface
;
244 IMFPMediaPlayer_AddRef(object
->u
.header
.pMediaPlayer
);
245 object
->u
.header
.eState
= player
->state
;
248 case MFP_EVENT_TYPE_PLAY
:
249 case MFP_EVENT_TYPE_PAUSE
:
250 case MFP_EVENT_TYPE_STOP
:
251 case MFP_EVENT_TYPE_POSITION_SET
:
252 case MFP_EVENT_TYPE_RATE_SET
:
253 case MFP_EVENT_TYPE_MEDIAITEM_CREATED
:
254 case MFP_EVENT_TYPE_MEDIAITEM_SET
:
255 case MFP_EVENT_TYPE_FRAME_STEP
:
256 case MFP_EVENT_TYPE_MEDIAITEM_CLEARED
:
257 case MFP_EVENT_TYPE_PLAYBACK_ENDED
:
258 object
->u
.generic
.item
= item
;
259 if (object
->u
.generic
.item
)
260 IMFPMediaItem_AddRef(object
->u
.generic
.item
);
262 case MFP_EVENT_TYPE_MF
:
263 object
->u
.event
.pMediaItem
= item
;
264 if (object
->u
.event
.pMediaItem
)
265 IMFPMediaItem_AddRef(object
->u
.event
.pMediaItem
);
271 /* FIXME: set properties for some events? */
278 static LRESULT WINAPI
media_player_event_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
280 struct media_event
*event
= (void *)lparam
;
281 struct media_player
*player
;
285 player
= impl_from_IMFPMediaPlayer(event
->u
.header
.pMediaPlayer
);
286 if (player
->callback
)
287 IMFPMediaPlayerCallback_OnMediaPlayerEvent(player
->callback
, &event
->u
.header
);
288 IUnknown_Release(&event
->IUnknown_iface
);
292 return DefWindowProcW(hwnd
, msg
, wparam
, lparam
);
295 static void media_player_set_state(struct media_player
*player
, MFP_MEDIAPLAYER_STATE state
)
297 if (player
->state
!= MFP_MEDIAPLAYER_STATE_SHUTDOWN
)
299 if (state
== MFP_MEDIAPLAYER_STATE_SHUTDOWN
)
300 IMFMediaSession_Shutdown(player
->session
);
301 player
->state
= state
;
305 static HRESULT WINAPI
media_item_QueryInterface(IMFPMediaItem
*iface
, REFIID riid
, void **obj
)
307 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
309 if (IsEqualIID(riid
, &IID_IMFPMediaItem
) ||
310 IsEqualIID(riid
, &IID_IUnknown
))
313 IMFPMediaItem_AddRef(iface
);
317 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
319 return E_NOINTERFACE
;
322 static ULONG WINAPI
media_item_AddRef(IMFPMediaItem
*iface
)
324 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
325 ULONG refcount
= InterlockedIncrement(&item
->refcount
);
327 TRACE("%p, refcount %u.\n", iface
, refcount
);
332 static ULONG WINAPI
media_item_Release(IMFPMediaItem
*iface
)
334 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
335 ULONG refcount
= InterlockedDecrement(&item
->refcount
);
337 TRACE("%p, refcount %u.\n", iface
, refcount
);
342 IMFPMediaPlayer_Release(item
->player
);
344 IMFMediaSource_Release(item
->source
);
346 IMFPresentationDescriptor_Release(item
->pd
);
348 IUnknown_Release(item
->object
);
356 static HRESULT WINAPI
media_item_GetMediaPlayer(IMFPMediaItem
*iface
,
357 IMFPMediaPlayer
**player
)
359 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
361 TRACE("%p, %p.\n", iface
, player
);
363 *player
= item
->player
;
364 IMFPMediaPlayer_AddRef(*player
);
369 static HRESULT WINAPI
media_item_GetURL(IMFPMediaItem
*iface
, LPWSTR
*url
)
371 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
373 TRACE("%p, %p.\n", iface
, url
);
376 return MF_E_NOT_FOUND
;
378 if (!(*url
= CoTaskMemAlloc((wcslen(item
->url
) + 1) * sizeof(*item
->url
))))
379 return E_OUTOFMEMORY
;
381 wcscpy(*url
, item
->url
);
386 static HRESULT WINAPI
media_item_GetObject(IMFPMediaItem
*iface
, IUnknown
**object
)
388 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
390 TRACE("%p, %p.\n", iface
, object
);
393 return MF_E_NOT_FOUND
;
395 *object
= item
->object
;
396 IUnknown_AddRef(*object
);
401 static HRESULT WINAPI
media_item_GetUserData(IMFPMediaItem
*iface
, DWORD_PTR
*user_data
)
403 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
405 TRACE("%p, %p.\n", iface
, user_data
);
407 *user_data
= item
->user_data
;
412 static HRESULT WINAPI
media_item_SetUserData(IMFPMediaItem
*iface
, DWORD_PTR user_data
)
414 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
416 TRACE("%p, %lx.\n", iface
, user_data
);
418 item
->user_data
= user_data
;
423 static HRESULT
media_item_set_position(const GUID
*format
, const PROPVARIANT
*position
, LARGE_INTEGER
*ret
)
427 if (format
&& !IsEqualGUID(format
, &MFP_POSITIONTYPE_100NS
))
430 if ((format
!= NULL
) ^ (position
!= NULL
))
433 if (position
&& position
->vt
!= VT_EMPTY
&& position
->vt
!= VT_I8
)
436 if ((!format
&& !position
) || position
->vt
== VT_EMPTY
)
439 if (position
->hVal
.QuadPart
== 0)
440 return MF_E_OUT_OF_RANGE
;
442 ret
->QuadPart
= position
->hVal
.QuadPart
;
447 static void media_item_get_position(LONGLONG value
, GUID
*format
, PROPVARIANT
*position
)
452 memcpy(format
, &MFP_POSITIONTYPE_100NS
, sizeof(*format
));
456 position
->vt
= VT_I8
;
457 position
->hVal
.QuadPart
= value
;
461 static HRESULT WINAPI
media_item_GetStartStopPosition(IMFPMediaItem
*iface
, GUID
*start_format
,
462 PROPVARIANT
*start_position
, GUID
*stop_format
, PROPVARIANT
*stop_position
)
464 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
466 TRACE("%p, %p, %p, %p, %p.\n", iface
, start_format
, start_position
, stop_format
, stop_position
);
469 start_position
->vt
= VT_EMPTY
;
471 stop_position
->vt
= VT_EMPTY
;
473 if (((start_format
!= NULL
) ^ (start_position
!= NULL
)) ||
474 ((stop_format
!= NULL
) ^ (stop_position
!= NULL
)))
479 media_item_get_position(item
->start_position
, start_format
, start_position
);
480 media_item_get_position(item
->stop_position
, stop_format
, stop_position
);
485 static HRESULT WINAPI
media_item_SetStartStopPosition(IMFPMediaItem
*iface
, const GUID
*start_format
,
486 const PROPVARIANT
*start_position
, const GUID
*stop_format
, const PROPVARIANT
*stop_position
)
488 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
489 LARGE_INTEGER start
, stop
;
492 TRACE("%p, %s, %p, %s, %p.\n", iface
, debugstr_guid(start_format
), start_position
,
493 debugstr_guid(stop_format
), stop_position
);
495 hr
= media_item_set_position(start_format
, start_position
, &start
);
497 hr
= media_item_set_position(stop_format
, stop_position
, &stop
);
502 if (start
.QuadPart
> stop
.QuadPart
)
503 return MF_E_OUT_OF_RANGE
;
505 item
->start_position
= start
.QuadPart
;
506 item
->stop_position
= stop
.QuadPart
;
511 static HRESULT
media_item_get_stream_type(IMFStreamDescriptor
*sd
, GUID
*major
)
513 IMFMediaTypeHandler
*handler
;
516 if (SUCCEEDED(hr
= IMFStreamDescriptor_GetMediaTypeHandler(sd
, &handler
)))
518 hr
= IMFMediaTypeHandler_GetMajorType(handler
, major
);
519 IMFMediaTypeHandler_Release(handler
);
525 static HRESULT
media_item_has_stream(struct media_item
*item
, const GUID
*major
, BOOL
*has_stream
, BOOL
*is_selected
)
527 IMFStreamDescriptor
*sd
;
528 unsigned int idx
= 0;
532 *has_stream
= *is_selected
= FALSE
;
534 while (SUCCEEDED(IMFPresentationDescriptor_GetStreamDescriptorByIndex(item
->pd
, idx
++, &selected
, &sd
)))
536 if (SUCCEEDED(media_item_get_stream_type(sd
, &guid
)) && IsEqualGUID(&guid
, major
))
539 *is_selected
= selected
;
542 IMFStreamDescriptor_Release(sd
);
544 if (*has_stream
&& *is_selected
)
551 static HRESULT WINAPI
media_item_HasVideo(IMFPMediaItem
*iface
, BOOL
*has_video
, BOOL
*selected
)
553 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
555 TRACE("%p, %p, %p.\n", iface
, has_video
, selected
);
557 return media_item_has_stream(item
, &MFMediaType_Video
, has_video
, selected
);
560 static HRESULT WINAPI
media_item_HasAudio(IMFPMediaItem
*iface
, BOOL
*has_audio
, BOOL
*selected
)
562 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
564 TRACE("%p, %p, %p.\n", iface
, has_audio
, selected
);
566 return media_item_has_stream(item
, &MFMediaType_Audio
, has_audio
, selected
);
569 static HRESULT WINAPI
media_item_IsProtected(IMFPMediaItem
*iface
, BOOL
*protected)
571 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
573 TRACE("%p, %p.\n", iface
, protected);
575 *protected = MFRequireProtectedEnvironment(item
->pd
) == S_OK
;
580 static HRESULT WINAPI
media_item_GetDuration(IMFPMediaItem
*iface
, REFGUID format
, PROPVARIANT
*value
)
582 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
584 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(format
), value
);
586 return IMFPresentationDescriptor_GetItem(item
->pd
, &MF_PD_DURATION
, value
);
589 static HRESULT WINAPI
media_item_GetNumberOfStreams(IMFPMediaItem
*iface
, DWORD
*count
)
591 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
593 TRACE("%p, %p.\n", iface
, count
);
595 return IMFPresentationDescriptor_GetStreamDescriptorCount(item
->pd
, count
);
598 static HRESULT WINAPI
media_item_GetStreamSelection(IMFPMediaItem
*iface
, DWORD index
, BOOL
*selected
)
600 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
601 IMFStreamDescriptor
*sd
;
604 TRACE("%p, %u, %p.\n", iface
, index
, selected
);
606 if (SUCCEEDED(hr
= IMFPresentationDescriptor_GetStreamDescriptorByIndex(item
->pd
, index
, selected
, &sd
)))
607 IMFStreamDescriptor_Release(sd
);
612 static HRESULT WINAPI
media_item_SetStreamSelection(IMFPMediaItem
*iface
, DWORD index
, BOOL select
)
614 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
616 TRACE("%p, %u, %d.\n", iface
, index
, select
);
618 return select
? IMFPresentationDescriptor_SelectStream(item
->pd
, index
) :
619 IMFPresentationDescriptor_DeselectStream(item
->pd
, index
);
622 static HRESULT WINAPI
media_item_GetStreamAttribute(IMFPMediaItem
*iface
, DWORD index
, REFGUID key
,
625 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
626 IMFStreamDescriptor
*sd
;
630 TRACE("%p, %u, %s, %p.\n", iface
, index
, debugstr_guid(key
), value
);
632 if (SUCCEEDED(hr
= IMFPresentationDescriptor_GetStreamDescriptorByIndex(item
->pd
, index
, &selected
, &sd
)))
634 hr
= IMFStreamDescriptor_GetItem(sd
, key
, value
);
635 IMFStreamDescriptor_Release(sd
);
641 static HRESULT WINAPI
media_item_GetPresentationAttribute(IMFPMediaItem
*iface
, REFGUID key
,
644 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
646 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
648 return IMFPresentationDescriptor_GetItem(item
->pd
, key
, value
);
651 static HRESULT WINAPI
media_item_GetCharacteristics(IMFPMediaItem
*iface
, MFP_MEDIAITEM_CHARACTERISTICS
*flags
)
653 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
656 TRACE("%p, %p.\n", iface
, flags
);
660 if (SUCCEEDED(hr
= IMFMediaSource_GetCharacteristics(item
->source
, flags
)))
662 *flags
&= (MFP_MEDIAITEM_IS_LIVE
| MFP_MEDIAITEM_CAN_SEEK
|
663 MFP_MEDIAITEM_CAN_PAUSE
| MFP_MEDIAITEM_HAS_SLOW_SEEK
);
669 static HRESULT WINAPI
media_item_SetStreamSink(IMFPMediaItem
*iface
, DWORD index
, IUnknown
*sink
)
671 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
672 IMFStreamDescriptor
*sd
;
673 IUnknown
*sink_object
;
677 TRACE("%p, %u, %p.\n", iface
, index
, sink
);
679 if (FAILED(hr
= IMFPresentationDescriptor_GetStreamDescriptorByIndex(item
->pd
, index
, &selected
, &sd
)))
684 if (FAILED(hr
= IUnknown_QueryInterface(sink
, &IID_IMFStreamSink
, (void **)&sink_object
)))
685 hr
= IUnknown_QueryInterface(sink
, &IID_IMFActivate
, (void **)&sink_object
);
689 hr
= IMFStreamDescriptor_SetUnknown(sd
, &_MF_CUSTOM_SINK
, sink_object
);
690 IUnknown_Release(sink_object
);
694 IMFStreamDescriptor_DeleteItem(sd
, &_MF_CUSTOM_SINK
);
696 IMFStreamDescriptor_Release(sd
);
701 static HRESULT WINAPI
media_item_GetMetadata(IMFPMediaItem
*iface
, IPropertyStore
**metadata
)
703 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
705 TRACE("%p, %p.\n", iface
, metadata
);
707 return MFGetService((IUnknown
*)item
->source
, &MF_PROPERTY_HANDLER_SERVICE
,
708 &IID_IPropertyStore
, (void **)metadata
);
711 static const IMFPMediaItemVtbl media_item_vtbl
=
713 media_item_QueryInterface
,
716 media_item_GetMediaPlayer
,
718 media_item_GetObject
,
719 media_item_GetUserData
,
720 media_item_SetUserData
,
721 media_item_GetStartStopPosition
,
722 media_item_SetStartStopPosition
,
725 media_item_IsProtected
,
726 media_item_GetDuration
,
727 media_item_GetNumberOfStreams
,
728 media_item_GetStreamSelection
,
729 media_item_SetStreamSelection
,
730 media_item_GetStreamAttribute
,
731 media_item_GetPresentationAttribute
,
732 media_item_GetCharacteristics
,
733 media_item_SetStreamSink
,
734 media_item_GetMetadata
,
737 static struct media_item
*unsafe_impl_from_IMFPMediaItem(IMFPMediaItem
*iface
)
741 assert(iface
->lpVtbl
== (IMFPMediaItemVtbl
*)&media_item_vtbl
);
742 return CONTAINING_RECORD(iface
, struct media_item
, IMFPMediaItem_iface
);
745 static HRESULT
create_media_item(IMFPMediaPlayer
*player
, DWORD_PTR user_data
, struct media_item
**item
)
747 struct media_item
*object
;
749 if (!(object
= calloc(1, sizeof(*object
))))
750 return E_OUTOFMEMORY
;
752 object
->IMFPMediaItem_iface
.lpVtbl
= &media_item_vtbl
;
753 object
->refcount
= 1;
754 object
->user_data
= user_data
;
755 object
->player
= player
;
756 IMFPMediaPlayer_AddRef(object
->player
);
763 static HRESULT
media_item_set_source(struct media_item
*item
, IUnknown
*object
)
765 IMFPresentationDescriptor
*pd
;
766 IMFMediaSource
*source
;
769 if (FAILED(hr
= IUnknown_QueryInterface(object
, &IID_IMFMediaSource
, (void **)&source
)))
772 if (FAILED(hr
= IMFMediaSource_CreatePresentationDescriptor(source
, &pd
)))
774 WARN("Failed to get presentation descriptor, hr %#x.\n", hr
);
775 IMFMediaSource_Release(source
);
779 item
->source
= source
;
785 static void media_player_queue_event(struct media_player
*player
, struct media_event
*event
)
787 if (player
->options
& MFP_OPTION_FREE_THREADED_CALLBACK
)
789 MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_MULTITHREADED
, &player
->events_callback
, &event
->IUnknown_iface
);
793 IUnknown_AddRef(&event
->IUnknown_iface
);
794 PostMessageW(player
->event_window
, WM_USER
, 0, (LPARAM
)event
);
798 static HRESULT WINAPI
media_player_QueryInterface(IMFPMediaPlayer
*iface
, REFIID riid
, void **obj
)
800 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
802 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
804 if (IsEqualIID(riid
, &IID_IMFPMediaPlayer
) ||
805 IsEqualIID(riid
, &IID_IUnknown
))
807 *obj
= &player
->IMFPMediaPlayer_iface
;
809 else if (IsEqualIID(riid
, &IID_IPropertyStore
))
811 *obj
= &player
->IPropertyStore_iface
;
815 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
818 return E_NOINTERFACE
;
821 IUnknown_AddRef((IUnknown
*)*obj
);
825 static ULONG WINAPI
media_player_AddRef(IMFPMediaPlayer
*iface
)
827 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
828 ULONG refcount
= InterlockedIncrement(&player
->refcount
);
830 TRACE("%p, refcount %u.\n", iface
, refcount
);
835 static ULONG WINAPI
media_player_Release(IMFPMediaPlayer
*iface
)
837 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
838 ULONG refcount
= InterlockedDecrement(&player
->refcount
);
840 TRACE("%p, refcount %u.\n", iface
, refcount
);
844 if (player
->callback
)
845 IMFPMediaPlayerCallback_Release(player
->callback
);
846 if (player
->propstore
)
847 IPropertyStore_Release(player
->propstore
);
848 if (player
->resolver
)
849 IMFSourceResolver_Release(player
->resolver
);
851 IMFMediaSession_Release(player
->session
);
852 DestroyWindow(player
->event_window
);
853 DeleteCriticalSection(&player
->cs
);
862 static HRESULT WINAPI
media_player_Play(IMFPMediaPlayer
*iface
)
864 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
867 TRACE("%p.\n", iface
);
870 return IMFMediaSession_Start(player
->session
, &GUID_NULL
, &pos
);
873 static HRESULT WINAPI
media_player_Pause(IMFPMediaPlayer
*iface
)
875 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
877 TRACE("%p.\n", iface
);
879 return IMFMediaSession_Pause(player
->session
);
882 static HRESULT WINAPI
media_player_Stop(IMFPMediaPlayer
*iface
)
884 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
886 TRACE("%p.\n", iface
);
888 return IMFMediaSession_Stop(player
->session
);
891 static HRESULT WINAPI
media_player_FrameStep(IMFPMediaPlayer
*iface
)
893 FIXME("%p.\n", iface
);
898 static HRESULT WINAPI
media_player_SetPosition(IMFPMediaPlayer
*iface
, REFGUID postype
, const PROPVARIANT
*position
)
900 FIXME("%p, %s, %p.\n", iface
, debugstr_guid(postype
), position
);
905 static HRESULT WINAPI
media_player_GetPosition(IMFPMediaPlayer
*iface
, REFGUID postype
, PROPVARIANT
*position
)
907 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
908 IMFPresentationClock
*presentation_clock
;
912 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(postype
), position
);
917 if (!IsEqualGUID(postype
, &MFP_POSITIONTYPE_100NS
))
920 EnterCriticalSection(&player
->cs
);
921 if (player
->state
== MFP_MEDIAPLAYER_STATE_SHUTDOWN
)
923 else if (!player
->item
)
924 hr
= MF_E_INVALIDREQUEST
;
927 if (SUCCEEDED(hr
= IMFMediaSession_GetClock(player
->session
, &clock
)))
929 if (SUCCEEDED(hr
= IMFClock_QueryInterface(clock
, &IID_IMFPresentationClock
, (void **)&presentation_clock
)))
931 position
->vt
= VT_UI8
;
932 hr
= IMFPresentationClock_GetTime(presentation_clock
, (MFTIME
*)&position
->uhVal
.QuadPart
);
933 IMFPresentationClock_Release(presentation_clock
);
935 IMFClock_Release(clock
);
938 LeaveCriticalSection(&player
->cs
);
943 static HRESULT WINAPI
media_player_GetDuration(IMFPMediaPlayer
*iface
, REFGUID postype
, PROPVARIANT
*duration
)
945 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
948 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(postype
), duration
);
953 if (!IsEqualGUID(postype
, &MFP_POSITIONTYPE_100NS
))
956 EnterCriticalSection(&player
->cs
);
957 if (player
->state
== MFP_MEDIAPLAYER_STATE_SHUTDOWN
)
959 else if (!player
->item
)
960 hr
= MF_E_INVALIDREQUEST
;
962 /* FIXME: use start/stop markers for resulting duration */
963 hr
= IMFPMediaItem_GetDuration(player
->item
, postype
, duration
);
964 LeaveCriticalSection(&player
->cs
);
969 static HRESULT WINAPI
media_player_SetRate(IMFPMediaPlayer
*iface
, float rate
)
971 FIXME("%p, %f.\n", iface
, rate
);
976 static HRESULT WINAPI
media_player_GetRate(IMFPMediaPlayer
*iface
, float *rate
)
978 FIXME("%p, %p.\n", iface
, rate
);
983 static HRESULT WINAPI
media_player_GetSupportedRates(IMFPMediaPlayer
*iface
, BOOL forward
,
984 float *slowest_rate
, float *fastest_rate
)
986 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
990 TRACE("%p, %d, %p, %p.\n", iface
, forward
, slowest_rate
, fastest_rate
);
992 if (SUCCEEDED(hr
= MFGetService((IUnknown
*)player
->session
, &MF_RATE_CONTROL_SERVICE
, &IID_IMFRateSupport
, (void **)&rs
)))
994 if (SUCCEEDED(hr
= IMFRateSupport_GetSlowestRate(rs
, forward
? MFRATE_FORWARD
: MFRATE_REVERSE
, FALSE
, slowest_rate
)))
995 hr
= IMFRateSupport_GetFastestRate(rs
, forward
? MFRATE_FORWARD
: MFRATE_REVERSE
, FALSE
, fastest_rate
);
996 IMFRateSupport_Release(rs
);
1002 static HRESULT WINAPI
media_player_GetState(IMFPMediaPlayer
*iface
, MFP_MEDIAPLAYER_STATE
*state
)
1004 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1006 TRACE("%p, %p.\n", iface
, state
);
1008 *state
= player
->state
;
1013 static HRESULT
media_player_create_item_from_url(struct media_player
*player
,
1014 const WCHAR
*url
, BOOL sync
, DWORD_PTR user_data
, IMFPMediaItem
**ret
)
1016 struct media_item
*item
;
1017 MF_OBJECT_TYPE obj_type
;
1021 if (FAILED(hr
= create_media_item(&player
->IMFPMediaPlayer_iface
, user_data
, &item
)))
1024 if (url
&& !(item
->url
= wcsdup(url
)))
1026 IMFPMediaItem_Release(&item
->IMFPMediaItem_iface
);
1027 return E_OUTOFMEMORY
;
1037 if (SUCCEEDED(hr
= IMFSourceResolver_CreateObjectFromURL(player
->resolver
, url
, MF_RESOLUTION_MEDIASOURCE
,
1038 player
->propstore
, &obj_type
, &object
)))
1040 hr
= media_item_set_source(item
, object
);
1041 IUnknown_Release(object
);
1046 *ret
= &item
->IMFPMediaItem_iface
;
1047 IMFPMediaItem_AddRef(*ret
);
1050 IMFPMediaItem_Release(&item
->IMFPMediaItem_iface
);
1056 if (!player
->callback
)
1058 WARN("Asynchronous item creation is not supported without user callback.\n");
1059 return MF_E_INVALIDREQUEST
;
1062 if (ret
) *ret
= NULL
;
1064 hr
= IMFSourceResolver_BeginCreateObjectFromURL(player
->resolver
, url
, MF_RESOLUTION_MEDIASOURCE
,
1065 player
->propstore
, NULL
, &player
->resolver_callback
, (IUnknown
*)&item
->IMFPMediaItem_iface
);
1067 IMFPMediaItem_Release(&item
->IMFPMediaItem_iface
);
1073 static HRESULT WINAPI
media_player_CreateMediaItemFromURL(IMFPMediaPlayer
*iface
,
1074 const WCHAR
*url
, BOOL sync
, DWORD_PTR user_data
, IMFPMediaItem
**item
)
1076 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1079 TRACE("%p, %s, %d, %lx, %p.\n", iface
, debugstr_w(url
), sync
, user_data
, item
);
1081 EnterCriticalSection(&player
->cs
);
1082 if (player
->state
== MFP_MEDIAPLAYER_STATE_SHUTDOWN
)
1085 hr
= media_player_create_item_from_url(player
, url
, sync
, user_data
, item
);
1086 LeaveCriticalSection(&player
->cs
);
1091 static HRESULT
media_player_create_item_from_object(struct media_player
*player
,
1092 IUnknown
*object
, BOOL sync
, DWORD_PTR user_data
, IMFPMediaItem
**ret
)
1094 struct media_item
*item
;
1095 MF_OBJECT_TYPE obj_type
;
1097 IMFByteStream
*stream
= NULL
;
1098 IMFMediaSource
*source
= NULL
;
1102 if (FAILED(hr
= create_media_item(&player
->IMFPMediaPlayer_iface
, user_data
, &item
)))
1105 item
->object
= object
;
1106 IUnknown_AddRef(item
->object
);
1108 if (FAILED(IUnknown_QueryInterface(object
, &IID_IMFMediaSource
, (void **)&source
)))
1109 IUnknown_QueryInterface(object
, &IID_IMFByteStream
, (void **)&stream
);
1111 if (!source
&& !stream
)
1113 WARN("Unsupported object type.\n");
1114 IMFPMediaItem_Release(&item
->IMFPMediaItem_iface
);
1115 return E_UNEXPECTED
;
1121 hr
= IMFSourceResolver_CreateObjectFromByteStream(player
->resolver
, stream
, NULL
,
1122 MF_RESOLUTION_MEDIASOURCE
, player
->propstore
, &obj_type
, &object
);
1124 IUnknown_AddRef(object
);
1127 hr
= media_item_set_source(item
, object
);
1129 IUnknown_Release(object
);
1133 *ret
= &item
->IMFPMediaItem_iface
;
1134 IMFPMediaItem_AddRef(*ret
);
1137 IMFPMediaItem_Release(&item
->IMFPMediaItem_iface
);
1143 hr
= IMFSourceResolver_BeginCreateObjectFromByteStream(player
->resolver
, stream
, NULL
, MF_RESOLUTION_MEDIASOURCE
,
1144 player
->propstore
, NULL
, &player
->resolver_callback
, (IUnknown
*)&item
->IMFPMediaItem_iface
);
1148 /* Resolver callback will check again if item's object is a source. */
1149 hr
= MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_MULTITHREADED
, &player
->resolver_callback
,
1150 (IUnknown
*)&item
->IMFPMediaItem_iface
);
1153 IMFPMediaItem_Release(&item
->IMFPMediaItem_iface
);
1157 IMFMediaSource_Release(source
);
1159 IMFByteStream_Release(stream
);
1164 static HRESULT WINAPI
media_player_CreateMediaItemFromObject(IMFPMediaPlayer
*iface
,
1165 IUnknown
*object
, BOOL sync
, DWORD_PTR user_data
, IMFPMediaItem
**item
)
1167 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1170 TRACE("%p, %p, %d, %lx, %p.\n", iface
, object
, sync
, user_data
, item
);
1172 EnterCriticalSection(&player
->cs
);
1173 if (player
->state
== MFP_MEDIAPLAYER_STATE_SHUTDOWN
)
1176 hr
= media_player_create_item_from_object(player
, object
, sync
, user_data
, item
);
1177 LeaveCriticalSection(&player
->cs
);
1182 static HRESULT
media_item_create_source_node(struct media_item
*item
, IMFStreamDescriptor
*sd
,
1183 IMFTopologyNode
**node
)
1187 if (SUCCEEDED(hr
= MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE
, node
)))
1189 IMFTopologyNode_SetUnknown(*node
, &MF_TOPONODE_SOURCE
, (IUnknown
*)item
->source
);
1190 IMFTopologyNode_SetUnknown(*node
, &MF_TOPONODE_PRESENTATION_DESCRIPTOR
, (IUnknown
*)item
->pd
);
1191 IMFTopologyNode_SetUnknown(*node
, &MF_TOPONODE_STREAM_DESCRIPTOR
, (IUnknown
*)sd
);
1192 if (item
->start_position
)
1193 IMFTopologyNode_SetUINT64(*node
, &MF_TOPONODE_MEDIASTART
, item
->start_position
);
1194 if (item
->stop_position
)
1195 IMFTopologyNode_SetUINT64(*node
, &MF_TOPONODE_MEDIASTOP
, item
->stop_position
);
1201 static HRESULT
media_item_create_sink_node(IUnknown
*sink
, IMFTopologyNode
**node
)
1205 if (SUCCEEDED(hr
= MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE
, node
)))
1206 IMFTopologyNode_SetObject(*node
, sink
);
1211 static HRESULT
media_item_create_topology(struct media_player
*player
, struct media_item
*item
, IMFTopology
**out
)
1213 IMFTopologyNode
*src_node
, *sink_node
;
1214 BOOL selected
, video_added
= FALSE
;
1215 IMFStreamDescriptor
*sd
;
1216 IMFTopology
*topology
;
1222 if (FAILED(hr
= MFCreateTopology(&topology
)))
1225 /* Set up branches for all selected streams. */
1228 while (SUCCEEDED(IMFPresentationDescriptor_GetStreamDescriptorByIndex(item
->pd
, idx
++, &selected
, &sd
)))
1230 if (!selected
|| FAILED(media_item_get_stream_type(sd
, &major
)))
1232 IMFStreamDescriptor_Release(sd
);
1238 if (SUCCEEDED(IMFStreamDescriptor_GetUnknown(sd
, &_MF_CUSTOM_SINK
, &IID_IUnknown
, (void **)&sink
)))
1240 /* User sink is attached as-is. */
1242 else if (IsEqualGUID(&major
, &MFMediaType_Audio
))
1244 if (FAILED(hr
= MFCreateAudioRendererActivate((IMFActivate
**)&sink
)))
1245 WARN("Failed to create SAR activation object, hr %#x.\n", hr
);
1247 else if (IsEqualGUID(&major
, &MFMediaType_Video
) && player
->output_window
&& !video_added
)
1249 if (FAILED(hr
= MFCreateVideoRendererActivate(player
->output_window
, (IMFActivate
**)&sink
)))
1250 WARN("Failed to create EVR activation object, hr %#x.\n", hr
);
1251 video_added
= SUCCEEDED(hr
);
1256 hr
= media_item_create_source_node(item
, sd
, &src_node
);
1258 hr
= media_item_create_sink_node(sink
, &sink_node
);
1262 IMFTopology_AddNode(topology
, src_node
);
1263 IMFTopology_AddNode(topology
, sink_node
);
1264 IMFTopologyNode_ConnectOutput(src_node
, 0, sink_node
, 0);
1268 IMFTopologyNode_Release(src_node
);
1270 IMFTopologyNode_Release(sink_node
);
1272 IUnknown_Release(sink
);
1275 IMFStreamDescriptor_Release(sd
);
1278 IMFTopology_SetUINT32(topology
, &MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES
, TRUE
);
1285 static HRESULT WINAPI
media_player_SetMediaItem(IMFPMediaPlayer
*iface
, IMFPMediaItem
*item_iface
)
1287 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1288 struct media_item
*item
;
1289 IMFTopology
*topology
;
1292 TRACE("%p, %p.\n", iface
, item_iface
);
1297 item
= unsafe_impl_from_IMFPMediaItem(item_iface
);
1298 if (item
->player
!= iface
)
1299 return E_INVALIDARG
;
1301 if (FAILED(hr
= media_item_create_topology(player
, item
, &topology
)))
1304 IMFTopology_SetUnknown(topology
, &_MF_TOPO_MEDIA_ITEM
, (IUnknown
*)item_iface
);
1305 hr
= IMFMediaSession_SetTopology(player
->session
, MFSESSION_SETTOPOLOGY_IMMEDIATE
, topology
);
1306 IMFTopology_Release(topology
);
1311 static HRESULT WINAPI
media_player_ClearMediaItem(IMFPMediaPlayer
*iface
)
1313 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1315 TRACE("%p.\n", iface
);
1317 return IMFMediaSession_SetTopology(player
->session
, MFSESSION_SETTOPOLOGY_CLEAR_CURRENT
, NULL
);
1320 static HRESULT WINAPI
media_player_GetMediaItem(IMFPMediaPlayer
*iface
, IMFPMediaItem
**item
)
1322 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1325 TRACE("%p, %p.\n", iface
, item
);
1330 EnterCriticalSection(&player
->cs
);
1331 if (player
->state
== MFP_MEDIAPLAYER_STATE_SHUTDOWN
)
1333 else if (!player
->item
)
1334 hr
= MF_E_NOT_FOUND
;
1337 *item
= player
->item
;
1338 IMFPMediaItem_AddRef(player
->item
);
1340 LeaveCriticalSection(&player
->cs
);
1345 static HRESULT WINAPI
media_player_GetVolume(IMFPMediaPlayer
*iface
, float *volume
)
1347 FIXME("%p, %p.\n", iface
, volume
);
1352 static HRESULT WINAPI
media_player_SetVolume(IMFPMediaPlayer
*iface
, float volume
)
1354 FIXME("%p, %.8e.\n", iface
, volume
);
1359 static HRESULT WINAPI
media_player_GetBalance(IMFPMediaPlayer
*iface
, float *balance
)
1361 FIXME("%p, %p.\n", iface
, balance
);
1366 static HRESULT WINAPI
media_player_SetBalance(IMFPMediaPlayer
*iface
, float balance
)
1368 FIXME("%p, %.8e.\n", iface
, balance
);
1373 static HRESULT WINAPI
media_player_GetMute(IMFPMediaPlayer
*iface
, BOOL
*mute
)
1375 FIXME("%p, %p.\n", iface
, mute
);
1380 static HRESULT WINAPI
media_player_SetMute(IMFPMediaPlayer
*iface
, BOOL mute
)
1382 FIXME("%p, %d.\n", iface
, mute
);
1387 static HRESULT
media_player_get_display_control(const struct media_player
*player
,
1388 IMFVideoDisplayControl
**display_control
)
1390 HRESULT hr
= MFGetService((IUnknown
*)player
->session
, &MR_VIDEO_RENDER_SERVICE
,
1391 &IID_IMFVideoDisplayControl
, (void **)display_control
);
1392 if (SUCCEEDED(hr
)) return hr
;
1393 return hr
== MF_E_SHUTDOWN
? hr
: MF_E_INVALIDREQUEST
;
1396 static HRESULT WINAPI
media_player_GetNativeVideoSize(IMFPMediaPlayer
*iface
,
1397 SIZE
*video
, SIZE
*arvideo
)
1399 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1400 IMFVideoDisplayControl
*display_control
;
1403 TRACE("%p, %p, %p.\n", iface
, video
, arvideo
);
1405 if (SUCCEEDED(hr
= media_player_get_display_control(player
, &display_control
)))
1407 hr
= IMFVideoDisplayControl_GetNativeVideoSize(display_control
, video
, arvideo
);
1408 IMFVideoDisplayControl_Release(display_control
);
1414 static HRESULT WINAPI
media_player_GetIdealVideoSize(IMFPMediaPlayer
*iface
,
1415 SIZE
*min_size
, SIZE
*max_size
)
1417 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1418 IMFVideoDisplayControl
*display_control
;
1421 TRACE("%p, %p, %p.\n", iface
, min_size
, max_size
);
1423 if (SUCCEEDED(hr
= media_player_get_display_control(player
, &display_control
)))
1425 hr
= IMFVideoDisplayControl_GetIdealVideoSize(display_control
, min_size
, max_size
);
1426 IMFVideoDisplayControl_Release(display_control
);
1432 static HRESULT WINAPI
media_player_SetVideoSourceRect(IMFPMediaPlayer
*iface
,
1433 MFVideoNormalizedRect
const *rect
)
1435 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1436 IMFVideoDisplayControl
*display_control
;
1440 TRACE("%p, %p.\n", iface
, rect
);
1442 if (!GetClientRect(player
->output_window
, &dst_rect
))
1443 hr
= HRESULT_FROM_WIN32(GetLastError());
1444 else if (SUCCEEDED(hr
= media_player_get_display_control(player
, &display_control
)))
1446 hr
= IMFVideoDisplayControl_SetVideoPosition(display_control
, rect
, &dst_rect
);
1447 IMFVideoDisplayControl_Release(display_control
);
1453 static HRESULT WINAPI
media_player_GetVideoSourceRect(IMFPMediaPlayer
*iface
,
1454 MFVideoNormalizedRect
*rect
)
1456 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1457 IMFVideoDisplayControl
*display_control
;
1461 TRACE("%p, %p.\n", iface
, rect
);
1463 if (SUCCEEDED(hr
= media_player_get_display_control(player
, &display_control
)))
1465 hr
= IMFVideoDisplayControl_GetVideoPosition(display_control
, rect
, &dest
);
1466 IMFVideoDisplayControl_Release(display_control
);
1472 static HRESULT WINAPI
media_player_SetAspectRatioMode(IMFPMediaPlayer
*iface
, DWORD mode
)
1474 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1475 IMFVideoDisplayControl
*display_control
;
1478 TRACE("%p, %u.\n", iface
, mode
);
1480 if (SUCCEEDED(hr
= media_player_get_display_control(player
, &display_control
)))
1482 hr
= IMFVideoDisplayControl_SetAspectRatioMode(display_control
, mode
);
1483 IMFVideoDisplayControl_Release(display_control
);
1489 static HRESULT WINAPI
media_player_GetAspectRatioMode(IMFPMediaPlayer
*iface
,
1492 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1493 IMFVideoDisplayControl
*display_control
;
1496 TRACE("%p, %p.\n", iface
, mode
);
1498 if (SUCCEEDED(hr
= media_player_get_display_control(player
, &display_control
)))
1500 hr
= IMFVideoDisplayControl_GetAspectRatioMode(display_control
, mode
);
1501 IMFVideoDisplayControl_Release(display_control
);
1507 static HRESULT WINAPI
media_player_GetVideoWindow(IMFPMediaPlayer
*iface
, HWND
*window
)
1509 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1511 TRACE("%p, %p.\n", iface
, window
);
1513 *window
= player
->output_window
;
1518 static HRESULT WINAPI
media_player_UpdateVideo(IMFPMediaPlayer
*iface
)
1520 FIXME("%p.\n", iface
);
1525 static HRESULT WINAPI
media_player_SetBorderColor(IMFPMediaPlayer
*iface
, COLORREF color
)
1527 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1528 IMFVideoDisplayControl
*display_control
;
1531 TRACE("%p, %#x.\n", iface
, color
);
1533 if (SUCCEEDED(hr
= media_player_get_display_control(player
, &display_control
)))
1535 hr
= IMFVideoDisplayControl_SetBorderColor(display_control
, color
);
1536 IMFVideoDisplayControl_Release(display_control
);
1542 static HRESULT WINAPI
media_player_GetBorderColor(IMFPMediaPlayer
*iface
, COLORREF
*color
)
1544 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1545 IMFVideoDisplayControl
*display_control
;
1548 TRACE("%p, %p.\n", iface
, color
);
1550 if (SUCCEEDED(hr
= media_player_get_display_control(player
, &display_control
)))
1552 hr
= IMFVideoDisplayControl_GetBorderColor(display_control
, color
);
1553 IMFVideoDisplayControl_Release(display_control
);
1559 static HRESULT WINAPI
media_player_InsertEffect(IMFPMediaPlayer
*iface
, IUnknown
*effect
,
1562 FIXME("%p, %p, %d.\n", iface
, effect
, optional
);
1567 static HRESULT WINAPI
media_player_RemoveEffect(IMFPMediaPlayer
*iface
, IUnknown
*effect
)
1569 FIXME("%p, %p.\n", iface
, effect
);
1574 static HRESULT WINAPI
media_player_RemoveAllEffects(IMFPMediaPlayer
*iface
)
1576 FIXME("%p.\n", iface
);
1581 static HRESULT WINAPI
media_player_Shutdown(IMFPMediaPlayer
*iface
)
1583 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1585 TRACE("%p.\n", iface
);
1587 EnterCriticalSection(&player
->cs
);
1588 media_player_set_state(player
, MFP_MEDIAPLAYER_STATE_SHUTDOWN
);
1591 IMFPMediaItem_Release(player
->item
);
1592 player
->item
= NULL
;
1594 LeaveCriticalSection(&player
->cs
);
1599 static const IMFPMediaPlayerVtbl media_player_vtbl
=
1601 media_player_QueryInterface
,
1602 media_player_AddRef
,
1603 media_player_Release
,
1607 media_player_FrameStep
,
1608 media_player_SetPosition
,
1609 media_player_GetPosition
,
1610 media_player_GetDuration
,
1611 media_player_SetRate
,
1612 media_player_GetRate
,
1613 media_player_GetSupportedRates
,
1614 media_player_GetState
,
1615 media_player_CreateMediaItemFromURL
,
1616 media_player_CreateMediaItemFromObject
,
1617 media_player_SetMediaItem
,
1618 media_player_ClearMediaItem
,
1619 media_player_GetMediaItem
,
1620 media_player_GetVolume
,
1621 media_player_SetVolume
,
1622 media_player_GetBalance
,
1623 media_player_SetBalance
,
1624 media_player_GetMute
,
1625 media_player_SetMute
,
1626 media_player_GetNativeVideoSize
,
1627 media_player_GetIdealVideoSize
,
1628 media_player_SetVideoSourceRect
,
1629 media_player_GetVideoSourceRect
,
1630 media_player_SetAspectRatioMode
,
1631 media_player_GetAspectRatioMode
,
1632 media_player_GetVideoWindow
,
1633 media_player_UpdateVideo
,
1634 media_player_SetBorderColor
,
1635 media_player_GetBorderColor
,
1636 media_player_InsertEffect
,
1637 media_player_RemoveEffect
,
1638 media_player_RemoveAllEffects
,
1639 media_player_Shutdown
,
1642 static HRESULT WINAPI
media_player_propstore_QueryInterface(IPropertyStore
*iface
,
1643 REFIID riid
, void **obj
)
1645 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1646 return IMFPMediaPlayer_QueryInterface(&player
->IMFPMediaPlayer_iface
, riid
, obj
);
1649 static ULONG WINAPI
media_player_propstore_AddRef(IPropertyStore
*iface
)
1651 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1652 return IMFPMediaPlayer_AddRef(&player
->IMFPMediaPlayer_iface
);
1655 static ULONG WINAPI
media_player_propstore_Release(IPropertyStore
*iface
)
1657 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1658 return IMFPMediaPlayer_Release(&player
->IMFPMediaPlayer_iface
);
1661 static HRESULT WINAPI
media_player_propstore_GetCount(IPropertyStore
*iface
, DWORD
*count
)
1663 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1665 TRACE("%p, %p.\n", iface
, count
);
1667 return IPropertyStore_GetCount(player
->propstore
, count
);
1670 static HRESULT WINAPI
media_player_propstore_GetAt(IPropertyStore
*iface
, DWORD prop
, PROPERTYKEY
*key
)
1672 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1674 TRACE("%p, %u, %p.\n", iface
, prop
, key
);
1676 return IPropertyStore_GetAt(player
->propstore
, prop
, key
);
1679 static HRESULT WINAPI
media_player_propstore_GetValue(IPropertyStore
*iface
, REFPROPERTYKEY key
, PROPVARIANT
*value
)
1681 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1683 TRACE("%p, %p, %p.\n", iface
, key
, value
);
1685 return IPropertyStore_GetValue(player
->propstore
, key
, value
);
1688 static HRESULT WINAPI
media_player_propstore_SetValue(IPropertyStore
*iface
, REFPROPERTYKEY key
, REFPROPVARIANT value
)
1690 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1692 TRACE("%p, %p, %p.\n", iface
, key
, value
);
1694 return IPropertyStore_SetValue(player
->propstore
, key
, value
);
1697 static HRESULT WINAPI
media_player_propstore_Commit(IPropertyStore
*iface
)
1699 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1701 TRACE("%p.\n", iface
);
1703 return IPropertyStore_Commit(player
->propstore
);
1706 static const IPropertyStoreVtbl media_player_propstore_vtbl
=
1708 media_player_propstore_QueryInterface
,
1709 media_player_propstore_AddRef
,
1710 media_player_propstore_Release
,
1711 media_player_propstore_GetCount
,
1712 media_player_propstore_GetAt
,
1713 media_player_propstore_GetValue
,
1714 media_player_propstore_SetValue
,
1715 media_player_propstore_Commit
,
1718 static HRESULT WINAPI
media_player_callback_QueryInterface(IMFAsyncCallback
*iface
,
1719 REFIID riid
, void **obj
)
1721 if (IsEqualIID(riid
, &IID_IMFAsyncCallback
) ||
1722 IsEqualIID(riid
, &IID_IUnknown
))
1725 IMFAsyncCallback_AddRef(iface
);
1730 return E_NOINTERFACE
;
1733 static ULONG WINAPI
media_player_resolver_callback_AddRef(IMFAsyncCallback
*iface
)
1735 struct media_player
*player
= impl_from_resolver_IMFAsyncCallback(iface
);
1736 return IMFPMediaPlayer_AddRef(&player
->IMFPMediaPlayer_iface
);
1739 static ULONG WINAPI
media_player_resolver_callback_Release(IMFAsyncCallback
*iface
)
1741 struct media_player
*player
= impl_from_resolver_IMFAsyncCallback(iface
);
1742 return IMFPMediaPlayer_Release(&player
->IMFPMediaPlayer_iface
);
1745 static HRESULT WINAPI
media_player_callback_GetParameters(IMFAsyncCallback
*iface
, DWORD
*flags
,
1751 static HRESULT WINAPI
media_player_resolver_callback_Invoke(IMFAsyncCallback
*iface
, IMFAsyncResult
*result
)
1753 struct media_player
*player
= impl_from_resolver_IMFAsyncCallback(iface
);
1754 struct media_event
*event
;
1755 IUnknown
*object
, *state
;
1756 MF_OBJECT_TYPE obj_type
;
1757 struct media_item
*item
;
1760 if (FAILED(IMFAsyncResult_GetState(result
, &state
)))
1763 item
= impl_from_IMFPMediaItem((IMFPMediaItem
*)state
);
1767 if (FAILED(hr
= IUnknown_QueryInterface(item
->object
, &IID_IMFMediaSource
, (void **)&object
)))
1768 hr
= IMFSourceResolver_EndCreateObjectFromByteStream(player
->resolver
, result
, &obj_type
, &object
);
1771 hr
= IMFSourceResolver_EndCreateObjectFromURL(player
->resolver
, result
, &obj_type
, &object
);
1775 hr
= media_item_set_source(item
, object
);
1776 IUnknown_Release(object
);
1780 WARN("Failed to set media source, hr %#x.\n", hr
);
1782 if (FAILED(media_event_create(player
, MFP_EVENT_TYPE_MEDIAITEM_CREATED
, hr
,
1783 &item
->IMFPMediaItem_iface
, &event
)))
1785 WARN("Failed to create event object.\n");
1786 IUnknown_Release(state
);
1789 event
->u
.item_created
.dwUserData
= item
->user_data
;
1791 media_player_queue_event(player
, event
);
1793 IUnknown_Release(&event
->IUnknown_iface
);
1794 IUnknown_Release(state
);
1799 static const IMFAsyncCallbackVtbl media_player_resolver_callback_vtbl
=
1801 media_player_callback_QueryInterface
,
1802 media_player_resolver_callback_AddRef
,
1803 media_player_resolver_callback_Release
,
1804 media_player_callback_GetParameters
,
1805 media_player_resolver_callback_Invoke
,
1808 static ULONG WINAPI
media_player_events_callback_AddRef(IMFAsyncCallback
*iface
)
1810 struct media_player
*player
= impl_from_events_IMFAsyncCallback(iface
);
1811 return IMFPMediaPlayer_AddRef(&player
->IMFPMediaPlayer_iface
);
1814 static ULONG WINAPI
media_player_events_callback_Release(IMFAsyncCallback
*iface
)
1816 struct media_player
*player
= impl_from_events_IMFAsyncCallback(iface
);
1817 return IMFPMediaPlayer_Release(&player
->IMFPMediaPlayer_iface
);
1820 static HRESULT WINAPI
media_player_events_callback_Invoke(IMFAsyncCallback
*iface
, IMFAsyncResult
*result
)
1822 struct media_player
*player
= impl_from_events_IMFAsyncCallback(iface
);
1823 struct media_event
*event
;
1826 if (FAILED(IMFAsyncResult_GetState(result
, &state
)))
1829 event
= impl_event_from_IUnknown(state
);
1831 if (player
->callback
)
1832 IMFPMediaPlayerCallback_OnMediaPlayerEvent(player
->callback
, &event
->u
.header
);
1834 IUnknown_Release(state
);
1839 static const IMFAsyncCallbackVtbl media_player_events_callback_vtbl
=
1841 media_player_callback_QueryInterface
,
1842 media_player_events_callback_AddRef
,
1843 media_player_events_callback_Release
,
1844 media_player_callback_GetParameters
,
1845 media_player_events_callback_Invoke
,
1848 static ULONG WINAPI
media_player_session_events_callback_AddRef(IMFAsyncCallback
*iface
)
1850 struct media_player
*player
= impl_from_session_events_IMFAsyncCallback(iface
);
1851 return IMFPMediaPlayer_AddRef(&player
->IMFPMediaPlayer_iface
);
1854 static ULONG WINAPI
media_player_session_events_callback_Release(IMFAsyncCallback
*iface
)
1856 struct media_player
*player
= impl_from_session_events_IMFAsyncCallback(iface
);
1857 return IMFPMediaPlayer_Release(&player
->IMFPMediaPlayer_iface
);
1860 static void media_player_change_state(struct media_player
*player
, MFP_MEDIAPLAYER_STATE state
,
1861 HRESULT event_status
, struct media_event
**event
)
1863 MFP_EVENT_TYPE event_type
;
1865 EnterCriticalSection(&player
->cs
);
1867 if (state
== MFP_MEDIAPLAYER_STATE_PLAYING
)
1868 event_type
= MFP_EVENT_TYPE_PLAY
;
1869 else if (state
== MFP_MEDIAPLAYER_STATE_PAUSED
)
1870 event_type
= MFP_EVENT_TYPE_PAUSE
;
1872 event_type
= MFP_EVENT_TYPE_STOP
;
1874 media_player_set_state(player
, state
);
1875 media_event_create(player
, event_type
, event_status
, player
->item
, event
);
1877 LeaveCriticalSection(&player
->cs
);
1880 static void media_player_set_item(struct media_player
*player
, IMFTopology
*topology
, HRESULT event_status
,
1881 struct media_event
**event
)
1883 IMFPMediaItem
*item
;
1885 if (FAILED(IMFTopology_GetUnknown(topology
, &_MF_TOPO_MEDIA_ITEM
, &IID_IMFPMediaItem
, (void **)&item
)))
1888 EnterCriticalSection(&player
->cs
);
1891 IMFPMediaItem_Release(player
->item
);
1892 player
->item
= item
;
1893 IMFPMediaItem_AddRef(player
->item
);
1895 media_event_create(player
, MFP_EVENT_TYPE_MEDIAITEM_SET
, event_status
, item
, event
);
1897 LeaveCriticalSection(&player
->cs
);
1899 IMFPMediaItem_Release(item
);
1902 static void media_player_clear_item(struct media_player
*player
, HRESULT event_status
,
1903 struct media_event
**event
)
1905 IMFPMediaItem
*item
;
1907 EnterCriticalSection(&player
->cs
);
1909 item
= player
->item
;
1910 player
->item
= NULL
;
1912 media_event_create(player
, MFP_EVENT_TYPE_MEDIAITEM_SET
, event_status
, item
, event
);
1914 LeaveCriticalSection(&player
->cs
);
1917 static void media_player_create_forward_event(struct media_player
*player
, HRESULT event_status
, IMFMediaEvent
*session_event
,
1918 struct media_event
**event
)
1920 EnterCriticalSection(&player
->cs
);
1922 if (SUCCEEDED(media_event_create(player
, MFP_EVENT_TYPE_MF
, event_status
, player
->item
, event
)))
1924 IMFMediaEvent_GetType(session_event
, &(*event
)->u
.event
.MFEventType
);
1925 (*event
)->u
.event
.pMFMediaEvent
= session_event
;
1926 IMFMediaEvent_AddRef((*event
)->u
.event
.pMFMediaEvent
);
1929 LeaveCriticalSection(&player
->cs
);
1932 static HRESULT WINAPI
media_player_session_events_callback_Invoke(IMFAsyncCallback
*iface
,
1933 IMFAsyncResult
*result
)
1935 struct media_player
*player
= impl_from_session_events_IMFAsyncCallback(iface
);
1936 MediaEventType session_event_type
= MEUnknown
;
1937 struct media_event
*event
= NULL
;
1938 IMFMediaEvent
*session_event
;
1939 MFP_MEDIAPLAYER_STATE state
;
1940 HRESULT hr
, event_status
;
1941 IMFTopology
*topology
;
1942 unsigned int status
;
1945 if (FAILED(hr
= IMFMediaSession_EndGetEvent(player
->session
, result
, &session_event
)))
1948 IMFMediaEvent_GetType(session_event
, &session_event_type
);
1949 IMFMediaEvent_GetStatus(session_event
, &event_status
);
1951 switch (session_event_type
)
1953 case MESessionStarted
:
1954 case MESessionStopped
:
1955 case MESessionPaused
:
1957 if (session_event_type
== MESessionStarted
)
1958 state
= MFP_MEDIAPLAYER_STATE_PLAYING
;
1959 else if (session_event_type
== MESessionPaused
)
1960 state
= MFP_MEDIAPLAYER_STATE_PAUSED
;
1962 state
= MFP_MEDIAPLAYER_STATE_STOPPED
;
1964 media_player_change_state(player
, state
, event_status
, &event
);
1968 case MESessionTopologySet
:
1970 value
.vt
= VT_EMPTY
;
1971 if (SUCCEEDED(IMFMediaEvent_GetValue(session_event
, &value
)))
1973 if (value
.vt
== VT_EMPTY
)
1975 media_player_clear_item(player
, event_status
, &event
);
1977 else if (value
.vt
== VT_UNKNOWN
&& value
.punkVal
&&
1978 SUCCEEDED(IUnknown_QueryInterface(value
.punkVal
, &IID_IMFTopology
, (void **)&topology
)))
1980 media_player_set_item(player
, topology
, event_status
, &event
);
1981 IMFTopology_Release(topology
);
1983 PropVariantClear(&value
);
1988 case MESessionTopologyStatus
:
1990 if (SUCCEEDED(IMFMediaEvent_GetUINT32(session_event
, &MF_EVENT_TOPOLOGY_STATUS
, &status
)) &&
1991 status
== MF_TOPOSTATUS_ENDED
)
1993 media_event_create(player
, MFP_EVENT_TYPE_PLAYBACK_ENDED
, event_status
, player
->item
, &event
);
1998 case MEBufferingStarted
:
1999 case MEBufferingStopped
:
2000 case MEExtendedType
:
2001 case MEReconnectStart
:
2002 case MEReconnectEnd
:
2003 case MERendererEvent
:
2004 case MEStreamSinkFormatChanged
:
2006 media_player_create_forward_event(player
, event_status
, session_event
, &event
);
2012 media_event_create(player
, MFP_EVENT_TYPE_ERROR
, event_status
, NULL
, &event
);
2022 media_player_queue_event(player
, event
);
2023 IUnknown_Release(&event
->IUnknown_iface
);
2026 IMFMediaSession_BeginGetEvent(player
->session
, &player
->session_events_callback
, NULL
);
2027 IMFMediaEvent_Release(session_event
);
2032 static const IMFAsyncCallbackVtbl media_player_session_events_callback_vtbl
=
2034 media_player_callback_QueryInterface
,
2035 media_player_session_events_callback_AddRef
,
2036 media_player_session_events_callback_Release
,
2037 media_player_callback_GetParameters
,
2038 media_player_session_events_callback_Invoke
,
2041 /***********************************************************************
2042 * MFPCreateMediaPlayer (mfplay.@)
2044 HRESULT WINAPI
MFPCreateMediaPlayer(const WCHAR
*url
, BOOL start_playback
, MFP_CREATION_OPTIONS options
,
2045 IMFPMediaPlayerCallback
*callback
, HWND window
, IMFPMediaPlayer
**player
)
2047 struct media_player
*object
;
2048 IMFPMediaItem
*item
;
2051 TRACE("%s, %d, %#x, %p, %p, %p.\n", debugstr_w(url
), start_playback
, options
, callback
, window
, player
);
2058 if (!url
&& start_playback
)
2059 return E_INVALIDARG
;
2061 if (!(object
= calloc(1, sizeof(*object
))))
2062 return E_OUTOFMEMORY
;
2066 object
->IMFPMediaPlayer_iface
.lpVtbl
= &media_player_vtbl
;
2067 object
->IPropertyStore_iface
.lpVtbl
= &media_player_propstore_vtbl
;
2068 object
->resolver_callback
.lpVtbl
= &media_player_resolver_callback_vtbl
;
2069 object
->events_callback
.lpVtbl
= &media_player_events_callback_vtbl
;
2070 object
->session_events_callback
.lpVtbl
= &media_player_session_events_callback_vtbl
;
2071 object
->refcount
= 1;
2072 object
->callback
= callback
;
2073 if (object
->callback
)
2074 IMFPMediaPlayerCallback_AddRef(object
->callback
);
2075 object
->options
= options
;
2076 object
->output_window
= window
;
2077 InitializeCriticalSection(&object
->cs
);
2078 if (FAILED(hr
= CreatePropertyStore(&object
->propstore
)))
2080 if (FAILED(hr
= MFCreateSourceResolver(&object
->resolver
)))
2082 if (FAILED(hr
= MFCreateMediaSession(NULL
, &object
->session
)))
2084 if (FAILED(hr
= IMFMediaSession_BeginGetEvent(object
->session
, &object
->session_events_callback
, NULL
)))
2086 if (!(object
->options
& MFP_OPTION_FREE_THREADED_CALLBACK
))
2088 object
->event_window
= CreateWindowW(eventclassW
, NULL
, 0, 0, 0, 0, 0, HWND_MESSAGE
,
2089 0, mfplay_instance
, NULL
);
2094 if (FAILED(hr
= media_player_create_item_from_url(object
, url
, TRUE
, 0, &item
)))
2096 WARN("Failed to create media item, hr %#x.\n", hr
);
2100 hr
= IMFPMediaPlayer_SetMediaItem(&object
->IMFPMediaPlayer_iface
, item
);
2101 IMFPMediaItem_Release(item
);
2104 WARN("Failed to set media item, hr %#x.\n", hr
);
2109 IMFPMediaPlayer_Play(&object
->IMFPMediaPlayer_iface
);
2112 *player
= &object
->IMFPMediaPlayer_iface
;
2118 IMFPMediaPlayer_Release(&object
->IMFPMediaPlayer_iface
);
2123 static void media_player_register_window_class(void)
2125 WNDCLASSW cls
= { 0 };
2127 cls
.lpfnWndProc
= media_player_event_proc
;
2128 cls
.hInstance
= mfplay_instance
;
2129 cls
.lpszClassName
= eventclassW
;
2131 RegisterClassW(&cls
);
2134 BOOL WINAPI
DllMain(HINSTANCE instance
, DWORD reason
, void *reserved
)
2138 case DLL_PROCESS_ATTACH
:
2139 mfplay_instance
= instance
;
2140 DisableThreadLibraryCalls(instance
);
2141 media_player_register_window_class();
2143 case DLL_PROCESS_DETACH
:
2144 if (reserved
) break;
2145 UnregisterClassW(eventclassW
, instance
);