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)
56 static inline const char *debugstr_normalized_rect(const MFVideoNormalizedRect
*rect
)
58 if (!rect
) return "(null)";
59 return wine_dbg_sprintf("(%.8e,%.8e)-(%.8e,%.8e)", rect
->left
, rect
->top
, rect
->right
, rect
->bottom
);
66 MEDIA_ITEM_SOURCE_NEEDS_SHUTDOWN
= 0x1,
71 IMFPMediaItem IMFPMediaItem_iface
;
73 struct media_player
*player
;
74 IMFMediaSource
*source
;
75 IMFPresentationDescriptor
*pd
;
79 LONGLONG start_position
;
80 LONGLONG stop_position
;
86 IMFPMediaPlayer IMFPMediaPlayer_iface
;
87 IPropertyStore IPropertyStore_iface
;
88 IMFAsyncCallback resolver_callback
;
89 IMFAsyncCallback events_callback
;
90 IMFAsyncCallback session_events_callback
;
92 IMFPMediaPlayerCallback
*callback
;
93 IPropertyStore
*propstore
;
94 IMFSourceResolver
*resolver
;
95 IMFMediaSession
*session
;
97 MFP_CREATION_OPTIONS options
;
98 MFP_MEDIAPLAYER_STATE state
;
106 MFP_EVENT_HEADER header
;
112 IUnknown IUnknown_iface
;
116 MFP_EVENT_HEADER header
;
117 struct generic_event generic
;
119 MFP_PAUSE_EVENT pause
;
121 MFP_POSITION_SET_EVENT position_set
;
122 MFP_RATE_SET_EVENT rate_set
;
123 MFP_MEDIAITEM_CREATED_EVENT item_created
;
124 MFP_MEDIAITEM_SET_EVENT item_set
;
125 MFP_MEDIAITEM_CLEARED_EVENT item_cleared
;
127 MFP_ERROR_EVENT error
;
128 MFP_PLAYBACK_ENDED_EVENT ended
;
129 MFP_ACQUIRE_USER_CREDENTIAL_EVENT acquire_creds
;
133 static struct media_player
*impl_from_IMFPMediaPlayer(IMFPMediaPlayer
*iface
)
135 return CONTAINING_RECORD(iface
, struct media_player
, IMFPMediaPlayer_iface
);
138 static struct media_player
*impl_from_IPropertyStore(IPropertyStore
*iface
)
140 return CONTAINING_RECORD(iface
, struct media_player
, IPropertyStore_iface
);
143 static struct media_player
*impl_from_resolver_IMFAsyncCallback(IMFAsyncCallback
*iface
)
145 return CONTAINING_RECORD(iface
, struct media_player
, resolver_callback
);
148 static struct media_player
*impl_from_events_IMFAsyncCallback(IMFAsyncCallback
*iface
)
150 return CONTAINING_RECORD(iface
, struct media_player
, events_callback
);
153 static struct media_player
*impl_from_session_events_IMFAsyncCallback(IMFAsyncCallback
*iface
)
155 return CONTAINING_RECORD(iface
, struct media_player
, session_events_callback
);
158 static struct media_item
*impl_from_IMFPMediaItem(IMFPMediaItem
*iface
)
160 return CONTAINING_RECORD(iface
, struct media_item
, IMFPMediaItem_iface
);
163 static struct media_event
*impl_event_from_IUnknown(IUnknown
*iface
)
165 return CONTAINING_RECORD(iface
, struct media_event
, IUnknown_iface
);
168 static HRESULT WINAPI
media_event_QueryInterface(IUnknown
*iface
, REFIID riid
, void **obj
)
170 if (IsEqualIID(riid
, &IID_IUnknown
))
173 IUnknown_AddRef(iface
);
178 return E_NOINTERFACE
;
181 static ULONG WINAPI
media_event_AddRef(IUnknown
*iface
)
183 struct media_event
*event
= impl_event_from_IUnknown(iface
);
184 ULONG refcount
= InterlockedIncrement(&event
->refcount
);
186 TRACE("%p, refcount %lu.\n", iface
, refcount
);
191 static ULONG WINAPI
media_event_Release(IUnknown
*iface
)
193 struct media_event
*event
= impl_event_from_IUnknown(iface
);
194 ULONG refcount
= InterlockedDecrement(&event
->refcount
);
196 TRACE("%p, refcount %lu.\n", iface
, refcount
);
200 if (event
->u
.header
.pMediaPlayer
)
201 IMFPMediaPlayer_Release(event
->u
.header
.pMediaPlayer
);
202 if (event
->u
.header
.pPropertyStore
)
203 IPropertyStore_Release(event
->u
.header
.pPropertyStore
);
205 switch (event
->u
.header
.eEventType
)
207 /* Most types share same layout. */
208 case MFP_EVENT_TYPE_PLAY
:
209 case MFP_EVENT_TYPE_PAUSE
:
210 case MFP_EVENT_TYPE_STOP
:
211 case MFP_EVENT_TYPE_POSITION_SET
:
212 case MFP_EVENT_TYPE_RATE_SET
:
213 case MFP_EVENT_TYPE_MEDIAITEM_CREATED
:
214 case MFP_EVENT_TYPE_MEDIAITEM_SET
:
215 case MFP_EVENT_TYPE_FRAME_STEP
:
216 case MFP_EVENT_TYPE_MEDIAITEM_CLEARED
:
217 case MFP_EVENT_TYPE_PLAYBACK_ENDED
:
218 if (event
->u
.generic
.item
)
219 IMFPMediaItem_Release(event
->u
.generic
.item
);
221 case MFP_EVENT_TYPE_MF
:
222 if (event
->u
.event
.pMFMediaEvent
)
223 IMFMediaEvent_Release(event
->u
.event
.pMFMediaEvent
);
224 if (event
->u
.event
.pMediaItem
)
225 IMFPMediaItem_Release(event
->u
.event
.pMediaItem
);
228 FIXME("Unsupported event %u.\n", event
->u
.header
.eEventType
);
238 static const IUnknownVtbl media_event_vtbl
=
240 media_event_QueryInterface
,
245 static HRESULT
media_event_create(struct media_player
*player
, MFP_EVENT_TYPE event_type
,
246 HRESULT hr
, IMFPMediaItem
*item
, struct media_event
**event
)
248 struct media_event
*object
;
250 if (!(object
= calloc(1, sizeof(*object
))))
251 return E_OUTOFMEMORY
;
253 object
->IUnknown_iface
.lpVtbl
= &media_event_vtbl
;
254 object
->refcount
= 1;
255 object
->u
.header
.eEventType
= event_type
;
256 object
->u
.header
.hrEvent
= hr
;
257 object
->u
.header
.pMediaPlayer
= &player
->IMFPMediaPlayer_iface
;
258 IMFPMediaPlayer_AddRef(object
->u
.header
.pMediaPlayer
);
259 object
->u
.header
.eState
= player
->state
;
262 case MFP_EVENT_TYPE_PLAY
:
263 case MFP_EVENT_TYPE_PAUSE
:
264 case MFP_EVENT_TYPE_STOP
:
265 case MFP_EVENT_TYPE_POSITION_SET
:
266 case MFP_EVENT_TYPE_RATE_SET
:
267 case MFP_EVENT_TYPE_MEDIAITEM_CREATED
:
268 case MFP_EVENT_TYPE_MEDIAITEM_SET
:
269 case MFP_EVENT_TYPE_FRAME_STEP
:
270 case MFP_EVENT_TYPE_MEDIAITEM_CLEARED
:
271 case MFP_EVENT_TYPE_PLAYBACK_ENDED
:
272 object
->u
.generic
.item
= item
;
273 if (object
->u
.generic
.item
)
274 IMFPMediaItem_AddRef(object
->u
.generic
.item
);
276 case MFP_EVENT_TYPE_MF
:
277 object
->u
.event
.pMediaItem
= item
;
278 if (object
->u
.event
.pMediaItem
)
279 IMFPMediaItem_AddRef(object
->u
.event
.pMediaItem
);
285 /* FIXME: set properties for some events? */
292 static LRESULT WINAPI
media_player_event_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
294 struct media_event
*event
= (void *)lparam
;
295 struct media_player
*player
;
299 player
= impl_from_IMFPMediaPlayer(event
->u
.header
.pMediaPlayer
);
300 if (player
->callback
)
301 IMFPMediaPlayerCallback_OnMediaPlayerEvent(player
->callback
, &event
->u
.header
);
302 IUnknown_Release(&event
->IUnknown_iface
);
306 return DefWindowProcW(hwnd
, msg
, wparam
, lparam
);
309 static void media_player_set_state(struct media_player
*player
, MFP_MEDIAPLAYER_STATE state
)
311 if (player
->state
!= MFP_MEDIAPLAYER_STATE_SHUTDOWN
)
313 if (state
== MFP_MEDIAPLAYER_STATE_SHUTDOWN
)
314 IMFMediaSession_Shutdown(player
->session
);
315 player
->state
= state
;
319 static HRESULT
media_item_get_pd(const struct media_item
*item
, IMFPresentationDescriptor
**pd
)
321 if (item
->player
->state
== MFP_MEDIAPLAYER_STATE_SHUTDOWN
)
322 return MF_E_SHUTDOWN
;
325 IMFPresentationDescriptor_AddRef(*pd
);
329 static HRESULT WINAPI
media_item_QueryInterface(IMFPMediaItem
*iface
, REFIID riid
, void **obj
)
331 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
333 if (IsEqualIID(riid
, &IID_IMFPMediaItem
) ||
334 IsEqualIID(riid
, &IID_IUnknown
))
337 IMFPMediaItem_AddRef(iface
);
341 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
343 return E_NOINTERFACE
;
346 static ULONG WINAPI
media_item_AddRef(IMFPMediaItem
*iface
)
348 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
349 ULONG refcount
= InterlockedIncrement(&item
->refcount
);
351 TRACE("%p, refcount %lu.\n", iface
, refcount
);
356 static ULONG WINAPI
media_item_Release(IMFPMediaItem
*iface
)
358 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
359 ULONG refcount
= InterlockedDecrement(&item
->refcount
);
361 TRACE("%p, refcount %lu.\n", iface
, refcount
);
366 IMFPMediaPlayer_Release(&item
->player
->IMFPMediaPlayer_iface
);
369 if (item
->flags
& MEDIA_ITEM_SOURCE_NEEDS_SHUTDOWN
)
370 IMFMediaSource_Shutdown(item
->source
);
371 IMFMediaSource_Release(item
->source
);
374 IMFPresentationDescriptor_Release(item
->pd
);
376 IUnknown_Release(item
->object
);
384 static HRESULT WINAPI
media_item_GetMediaPlayer(IMFPMediaItem
*iface
,
385 IMFPMediaPlayer
**player
)
387 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
390 TRACE("%p, %p.\n", iface
, player
);
392 EnterCriticalSection(&item
->player
->cs
);
393 if (item
->player
->state
== MFP_MEDIAPLAYER_STATE_SHUTDOWN
)
400 *player
= &item
->player
->IMFPMediaPlayer_iface
;
401 IMFPMediaPlayer_AddRef(*player
);
403 LeaveCriticalSection(&item
->player
->cs
);
408 static HRESULT WINAPI
media_item_GetURL(IMFPMediaItem
*iface
, LPWSTR
*url
)
410 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
413 TRACE("%p, %p.\n", iface
, url
);
415 EnterCriticalSection(&item
->player
->cs
);
416 if (item
->player
->state
== MFP_MEDIAPLAYER_STATE_SHUTDOWN
)
422 if (!(*url
= CoTaskMemAlloc((wcslen(item
->url
) + 1) * sizeof(*item
->url
))))
425 wcscpy(*url
, item
->url
);
427 LeaveCriticalSection(&item
->player
->cs
);
432 static HRESULT WINAPI
media_item_GetObject(IMFPMediaItem
*iface
, IUnknown
**object
)
434 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
437 TRACE("%p, %p.\n", iface
, object
);
439 EnterCriticalSection(&item
->player
->cs
);
440 if (item
->player
->state
== MFP_MEDIAPLAYER_STATE_SHUTDOWN
)
442 else if (!item
->object
)
446 *object
= item
->object
;
447 IUnknown_AddRef(*object
);
449 LeaveCriticalSection(&item
->player
->cs
);
454 static HRESULT WINAPI
media_item_GetUserData(IMFPMediaItem
*iface
, DWORD_PTR
*user_data
)
456 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
458 TRACE("%p, %p.\n", iface
, user_data
);
460 *user_data
= item
->user_data
;
465 static HRESULT WINAPI
media_item_SetUserData(IMFPMediaItem
*iface
, DWORD_PTR user_data
)
467 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
469 TRACE("%p, %Ix.\n", iface
, user_data
);
471 item
->user_data
= user_data
;
476 static HRESULT
media_item_set_position(const GUID
*format
, const PROPVARIANT
*position
, LARGE_INTEGER
*ret
)
480 if (format
&& !IsEqualGUID(format
, &MFP_POSITIONTYPE_100NS
))
483 if ((format
!= NULL
) ^ (position
!= NULL
))
486 if (position
&& position
->vt
!= VT_EMPTY
&& position
->vt
!= VT_I8
)
489 if ((!format
&& !position
) || position
->vt
== VT_EMPTY
)
492 if (position
->hVal
.QuadPart
== 0)
493 return MF_E_OUT_OF_RANGE
;
495 ret
->QuadPart
= position
->hVal
.QuadPart
;
500 static void media_item_get_position(LONGLONG value
, GUID
*format
, PROPVARIANT
*position
)
505 memcpy(format
, &MFP_POSITIONTYPE_100NS
, sizeof(*format
));
509 position
->vt
= VT_I8
;
510 position
->hVal
.QuadPart
= value
;
514 static HRESULT WINAPI
media_item_GetStartStopPosition(IMFPMediaItem
*iface
, GUID
*start_format
,
515 PROPVARIANT
*start_position
, GUID
*stop_format
, PROPVARIANT
*stop_position
)
517 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
519 TRACE("%p, %p, %p, %p, %p.\n", iface
, start_format
, start_position
, stop_format
, stop_position
);
522 start_position
->vt
= VT_EMPTY
;
524 stop_position
->vt
= VT_EMPTY
;
526 if (((start_format
!= NULL
) ^ (start_position
!= NULL
)) ||
527 ((stop_format
!= NULL
) ^ (stop_position
!= NULL
)))
532 media_item_get_position(item
->start_position
, start_format
, start_position
);
533 media_item_get_position(item
->stop_position
, stop_format
, stop_position
);
538 static HRESULT WINAPI
media_item_SetStartStopPosition(IMFPMediaItem
*iface
, const GUID
*start_format
,
539 const PROPVARIANT
*start_position
, const GUID
*stop_format
, const PROPVARIANT
*stop_position
)
541 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
542 LARGE_INTEGER start
, stop
;
545 TRACE("%p, %s, %p, %s, %p.\n", iface
, debugstr_guid(start_format
), start_position
,
546 debugstr_guid(stop_format
), stop_position
);
548 hr
= media_item_set_position(start_format
, start_position
, &start
);
550 hr
= media_item_set_position(stop_format
, stop_position
, &stop
);
555 if (start
.QuadPart
> stop
.QuadPart
)
556 return MF_E_OUT_OF_RANGE
;
558 item
->start_position
= start
.QuadPart
;
559 item
->stop_position
= stop
.QuadPart
;
564 static HRESULT
media_item_get_stream_type(IMFStreamDescriptor
*sd
, GUID
*major
)
566 IMFMediaTypeHandler
*handler
;
569 if (SUCCEEDED(hr
= IMFStreamDescriptor_GetMediaTypeHandler(sd
, &handler
)))
571 hr
= IMFMediaTypeHandler_GetMajorType(handler
, major
);
572 IMFMediaTypeHandler_Release(handler
);
578 static HRESULT
media_item_has_stream(struct media_item
*item
, const GUID
*major
, BOOL
*has_stream
, BOOL
*is_selected
)
580 IMFPresentationDescriptor
*pd
;
581 IMFStreamDescriptor
*sd
;
582 unsigned int idx
= 0;
587 EnterCriticalSection(&item
->player
->cs
);
589 if (SUCCEEDED(hr
= media_item_get_pd(item
, &pd
)))
591 *has_stream
= *is_selected
= FALSE
;
593 while (SUCCEEDED(IMFPresentationDescriptor_GetStreamDescriptorByIndex(pd
, idx
++, &selected
, &sd
)))
595 if (SUCCEEDED(media_item_get_stream_type(sd
, &guid
)) && IsEqualGUID(&guid
, major
))
598 *is_selected
= selected
;
601 IMFStreamDescriptor_Release(sd
);
603 if (*has_stream
&& *is_selected
)
606 IMFPresentationDescriptor_Release(pd
);
609 LeaveCriticalSection(&item
->player
->cs
);
614 static HRESULT WINAPI
media_item_HasVideo(IMFPMediaItem
*iface
, BOOL
*has_video
, BOOL
*selected
)
616 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
618 TRACE("%p, %p, %p.\n", iface
, has_video
, selected
);
620 return media_item_has_stream(item
, &MFMediaType_Video
, has_video
, selected
);
623 static HRESULT WINAPI
media_item_HasAudio(IMFPMediaItem
*iface
, BOOL
*has_audio
, BOOL
*selected
)
625 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
627 TRACE("%p, %p, %p.\n", iface
, has_audio
, selected
);
629 return media_item_has_stream(item
, &MFMediaType_Audio
, has_audio
, selected
);
632 static HRESULT WINAPI
media_item_IsProtected(IMFPMediaItem
*iface
, BOOL
*protected)
634 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
635 IMFPresentationDescriptor
*pd
;
638 TRACE("%p, %p.\n", iface
, protected);
643 EnterCriticalSection(&item
->player
->cs
);
644 if (SUCCEEDED(hr
= media_item_get_pd(item
, &pd
)))
646 *protected = (hr
= MFRequireProtectedEnvironment(pd
)) == S_OK
;
647 IMFPresentationDescriptor_Release(pd
);
649 LeaveCriticalSection(&item
->player
->cs
);
654 static HRESULT WINAPI
media_item_GetDuration(IMFPMediaItem
*iface
, REFGUID format
, PROPVARIANT
*value
)
656 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
657 IMFPresentationDescriptor
*pd
;
660 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(format
), value
);
662 EnterCriticalSection(&item
->player
->cs
);
663 if (SUCCEEDED(hr
= media_item_get_pd(item
, &pd
)))
665 hr
= IMFPresentationDescriptor_GetItem(pd
, &MF_PD_DURATION
, value
);
666 IMFPresentationDescriptor_Release(pd
);
668 LeaveCriticalSection(&item
->player
->cs
);
673 static HRESULT WINAPI
media_item_GetNumberOfStreams(IMFPMediaItem
*iface
, DWORD
*count
)
675 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
676 IMFPresentationDescriptor
*pd
;
679 TRACE("%p, %p.\n", iface
, count
);
681 EnterCriticalSection(&item
->player
->cs
);
682 if (SUCCEEDED(hr
= media_item_get_pd(item
, &pd
)))
684 hr
= IMFPresentationDescriptor_GetStreamDescriptorCount(pd
, count
);
685 IMFPresentationDescriptor_Release(pd
);
687 LeaveCriticalSection(&item
->player
->cs
);
692 static HRESULT WINAPI
media_item_GetStreamSelection(IMFPMediaItem
*iface
, DWORD index
, BOOL
*selected
)
694 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
695 IMFPresentationDescriptor
*pd
;
696 IMFStreamDescriptor
*sd
;
699 TRACE("%p, %lu, %p.\n", iface
, index
, selected
);
701 EnterCriticalSection(&item
->player
->cs
);
702 if (SUCCEEDED(hr
= media_item_get_pd(item
, &pd
)))
704 if (SUCCEEDED(hr
= IMFPresentationDescriptor_GetStreamDescriptorByIndex(pd
, index
, selected
, &sd
)))
705 IMFStreamDescriptor_Release(sd
);
706 IMFPresentationDescriptor_Release(pd
);
708 LeaveCriticalSection(&item
->player
->cs
);
713 static HRESULT WINAPI
media_item_SetStreamSelection(IMFPMediaItem
*iface
, DWORD index
, BOOL select
)
715 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
716 IMFPresentationDescriptor
*pd
;
719 TRACE("%p, %lu, %d.\n", iface
, index
, select
);
721 EnterCriticalSection(&item
->player
->cs
);
722 if (SUCCEEDED(hr
= media_item_get_pd(item
, &pd
)))
724 hr
= select
? IMFPresentationDescriptor_SelectStream(pd
, index
) :
725 IMFPresentationDescriptor_DeselectStream(pd
, index
);
726 IMFPresentationDescriptor_Release(pd
);
728 LeaveCriticalSection(&item
->player
->cs
);
733 static HRESULT WINAPI
media_item_GetStreamAttribute(IMFPMediaItem
*iface
, DWORD index
, REFGUID key
,
736 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
737 IMFPresentationDescriptor
*pd
;
738 IMFStreamDescriptor
*sd
;
742 TRACE("%p, %lu, %s, %p.\n", iface
, index
, debugstr_guid(key
), value
);
744 EnterCriticalSection(&item
->player
->cs
);
745 if (SUCCEEDED(hr
= media_item_get_pd(item
, &pd
)))
747 if (SUCCEEDED(hr
= IMFPresentationDescriptor_GetStreamDescriptorByIndex(pd
, index
, &selected
, &sd
)))
749 hr
= IMFStreamDescriptor_GetItem(sd
, key
, value
);
750 IMFStreamDescriptor_Release(sd
);
752 IMFPresentationDescriptor_Release(pd
);
754 LeaveCriticalSection(&item
->player
->cs
);
759 static HRESULT WINAPI
media_item_GetPresentationAttribute(IMFPMediaItem
*iface
, REFGUID key
,
762 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
763 IMFPresentationDescriptor
*pd
;
766 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
768 EnterCriticalSection(&item
->player
->cs
);
769 if (SUCCEEDED(hr
= media_item_get_pd(item
, &pd
)))
771 hr
= IMFPresentationDescriptor_GetItem(pd
, key
, value
);
772 IMFPresentationDescriptor_Release(pd
);
774 LeaveCriticalSection(&item
->player
->cs
);
779 static HRESULT WINAPI
media_item_GetCharacteristics(IMFPMediaItem
*iface
, MFP_MEDIAITEM_CHARACTERISTICS
*flags
)
781 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
785 TRACE("%p, %p.\n", iface
, flags
);
789 EnterCriticalSection(&item
->player
->cs
);
790 if (item
->player
->state
== MFP_MEDIAPLAYER_STATE_SHUTDOWN
)
794 if (SUCCEEDED(hr
= IMFMediaSource_GetCharacteristics(item
->source
, &value
)))
796 *flags
= value
& (MFP_MEDIAITEM_IS_LIVE
| MFP_MEDIAITEM_CAN_SEEK
797 | MFP_MEDIAITEM_CAN_PAUSE
| MFP_MEDIAITEM_HAS_SLOW_SEEK
);
800 LeaveCriticalSection(&item
->player
->cs
);
805 static HRESULT WINAPI
media_item_SetStreamSink(IMFPMediaItem
*iface
, DWORD index
, IUnknown
*sink
)
807 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
808 IMFStreamDescriptor
*sd
;
809 IUnknown
*sink_object
;
813 TRACE("%p, %lu, %p.\n", iface
, index
, sink
);
815 if (FAILED(hr
= IMFPresentationDescriptor_GetStreamDescriptorByIndex(item
->pd
, index
, &selected
, &sd
)))
820 if (FAILED(hr
= IUnknown_QueryInterface(sink
, &IID_IMFStreamSink
, (void **)&sink_object
)))
821 hr
= IUnknown_QueryInterface(sink
, &IID_IMFActivate
, (void **)&sink_object
);
825 hr
= IMFStreamDescriptor_SetUnknown(sd
, &_MF_CUSTOM_SINK
, sink_object
);
826 IUnknown_Release(sink_object
);
830 IMFStreamDescriptor_DeleteItem(sd
, &_MF_CUSTOM_SINK
);
832 IMFStreamDescriptor_Release(sd
);
837 static HRESULT WINAPI
media_item_GetMetadata(IMFPMediaItem
*iface
, IPropertyStore
**metadata
)
839 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
841 TRACE("%p, %p.\n", iface
, metadata
);
843 return MFGetService((IUnknown
*)item
->source
, &MF_PROPERTY_HANDLER_SERVICE
,
844 &IID_IPropertyStore
, (void **)metadata
);
847 static const IMFPMediaItemVtbl media_item_vtbl
=
849 media_item_QueryInterface
,
852 media_item_GetMediaPlayer
,
854 media_item_GetObject
,
855 media_item_GetUserData
,
856 media_item_SetUserData
,
857 media_item_GetStartStopPosition
,
858 media_item_SetStartStopPosition
,
861 media_item_IsProtected
,
862 media_item_GetDuration
,
863 media_item_GetNumberOfStreams
,
864 media_item_GetStreamSelection
,
865 media_item_SetStreamSelection
,
866 media_item_GetStreamAttribute
,
867 media_item_GetPresentationAttribute
,
868 media_item_GetCharacteristics
,
869 media_item_SetStreamSink
,
870 media_item_GetMetadata
,
873 static struct media_item
*unsafe_impl_from_IMFPMediaItem(IMFPMediaItem
*iface
)
877 assert(iface
->lpVtbl
== (IMFPMediaItemVtbl
*)&media_item_vtbl
);
878 return CONTAINING_RECORD(iface
, struct media_item
, IMFPMediaItem_iface
);
881 static HRESULT
create_media_item(struct media_player
*player
, DWORD_PTR user_data
, struct media_item
**item
)
883 struct media_item
*object
;
885 if (!(object
= calloc(1, sizeof(*object
))))
886 return E_OUTOFMEMORY
;
888 object
->IMFPMediaItem_iface
.lpVtbl
= &media_item_vtbl
;
889 object
->refcount
= 1;
890 object
->user_data
= user_data
;
891 object
->player
= player
;
892 IMFPMediaPlayer_AddRef(&object
->player
->IMFPMediaPlayer_iface
);
899 static HRESULT
media_item_set_source(struct media_item
*item
, IUnknown
*object
)
901 IMFPresentationDescriptor
*pd
;
902 IMFMediaSource
*source
;
905 if (FAILED(hr
= IUnknown_QueryInterface(object
, &IID_IMFMediaSource
, (void **)&source
)))
908 if (FAILED(hr
= IMFMediaSource_CreatePresentationDescriptor(source
, &pd
)))
910 WARN("Failed to get presentation descriptor, hr %#lx.\n", hr
);
911 IMFMediaSource_Release(source
);
915 item
->source
= source
;
921 static void media_player_queue_event(struct media_player
*player
, struct media_event
*event
)
923 if (player
->options
& MFP_OPTION_FREE_THREADED_CALLBACK
)
925 MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_MULTITHREADED
, &player
->events_callback
, &event
->IUnknown_iface
);
929 IUnknown_AddRef(&event
->IUnknown_iface
);
930 PostMessageW(player
->event_window
, WM_USER
, 0, (LPARAM
)event
);
934 static HRESULT WINAPI
media_player_QueryInterface(IMFPMediaPlayer
*iface
, REFIID riid
, void **obj
)
936 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
938 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
940 if (IsEqualIID(riid
, &IID_IMFPMediaPlayer
) ||
941 IsEqualIID(riid
, &IID_IUnknown
))
943 *obj
= &player
->IMFPMediaPlayer_iface
;
945 else if (IsEqualIID(riid
, &IID_IPropertyStore
))
947 *obj
= &player
->IPropertyStore_iface
;
951 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
954 return E_NOINTERFACE
;
957 IUnknown_AddRef((IUnknown
*)*obj
);
961 static ULONG WINAPI
media_player_AddRef(IMFPMediaPlayer
*iface
)
963 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
964 ULONG refcount
= InterlockedIncrement(&player
->refcount
);
966 TRACE("%p, refcount %lu.\n", iface
, refcount
);
971 static ULONG WINAPI
media_player_Release(IMFPMediaPlayer
*iface
)
973 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
974 ULONG refcount
= InterlockedDecrement(&player
->refcount
);
976 TRACE("%p, refcount %lu.\n", iface
, refcount
);
980 if (player
->callback
)
981 IMFPMediaPlayerCallback_Release(player
->callback
);
982 if (player
->propstore
)
983 IPropertyStore_Release(player
->propstore
);
984 if (player
->resolver
)
985 IMFSourceResolver_Release(player
->resolver
);
987 IMFMediaSession_Release(player
->session
);
988 DestroyWindow(player
->event_window
);
989 DeleteCriticalSection(&player
->cs
);
998 static HRESULT WINAPI
media_player_Play(IMFPMediaPlayer
*iface
)
1000 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1003 TRACE("%p.\n", iface
);
1006 return IMFMediaSession_Start(player
->session
, &GUID_NULL
, &pos
);
1009 static HRESULT WINAPI
media_player_Pause(IMFPMediaPlayer
*iface
)
1011 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1013 TRACE("%p.\n", iface
);
1015 return IMFMediaSession_Pause(player
->session
);
1018 static HRESULT WINAPI
media_player_Stop(IMFPMediaPlayer
*iface
)
1020 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1022 TRACE("%p.\n", iface
);
1024 return IMFMediaSession_Stop(player
->session
);
1027 static HRESULT WINAPI
media_player_FrameStep(IMFPMediaPlayer
*iface
)
1029 FIXME("%p.\n", iface
);
1034 static HRESULT WINAPI
media_player_SetPosition(IMFPMediaPlayer
*iface
, REFGUID postype
, const PROPVARIANT
*position
)
1036 FIXME("%p, %s, %p.\n", iface
, debugstr_guid(postype
), position
);
1041 static HRESULT WINAPI
media_player_GetPosition(IMFPMediaPlayer
*iface
, REFGUID postype
, PROPVARIANT
*position
)
1043 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1044 IMFPresentationClock
*presentation_clock
;
1048 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(postype
), position
);
1053 if (!IsEqualGUID(postype
, &MFP_POSITIONTYPE_100NS
))
1054 return E_INVALIDARG
;
1056 EnterCriticalSection(&player
->cs
);
1057 if (player
->state
== MFP_MEDIAPLAYER_STATE_SHUTDOWN
)
1059 else if (!player
->item
)
1060 hr
= MF_E_INVALIDREQUEST
;
1063 if (SUCCEEDED(hr
= IMFMediaSession_GetClock(player
->session
, &clock
)))
1065 if (SUCCEEDED(hr
= IMFClock_QueryInterface(clock
, &IID_IMFPresentationClock
, (void **)&presentation_clock
)))
1067 position
->vt
= VT_UI8
;
1068 hr
= IMFPresentationClock_GetTime(presentation_clock
, (MFTIME
*)&position
->uhVal
.QuadPart
);
1069 IMFPresentationClock_Release(presentation_clock
);
1071 IMFClock_Release(clock
);
1074 LeaveCriticalSection(&player
->cs
);
1079 static HRESULT WINAPI
media_player_GetDuration(IMFPMediaPlayer
*iface
, REFGUID postype
, PROPVARIANT
*duration
)
1081 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1084 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(postype
), duration
);
1089 if (!IsEqualGUID(postype
, &MFP_POSITIONTYPE_100NS
))
1090 return E_INVALIDARG
;
1092 EnterCriticalSection(&player
->cs
);
1093 if (player
->state
== MFP_MEDIAPLAYER_STATE_SHUTDOWN
)
1095 else if (!player
->item
)
1096 hr
= MF_E_INVALIDREQUEST
;
1098 /* FIXME: use start/stop markers for resulting duration */
1099 hr
= IMFPMediaItem_GetDuration(player
->item
, postype
, duration
);
1100 LeaveCriticalSection(&player
->cs
);
1105 static HRESULT WINAPI
media_player_SetRate(IMFPMediaPlayer
*iface
, float rate
)
1107 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1108 IMFRateControl
*rate_control
;
1111 TRACE("%p, %f.\n", iface
, rate
);
1114 return MF_E_OUT_OF_RANGE
;
1116 if (SUCCEEDED(hr
= MFGetService((IUnknown
*)player
->session
, &MF_RATE_CONTROL_SERVICE
, &IID_IMFRateControl
,
1117 (void **)&rate_control
)))
1119 hr
= IMFRateControl_SetRate(rate_control
, FALSE
, rate
);
1120 IMFRateControl_Release(rate_control
);
1126 static HRESULT WINAPI
media_player_GetRate(IMFPMediaPlayer
*iface
, float *rate
)
1128 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1129 IMFRateControl
*rate_control
;
1132 TRACE("%p, %p.\n", iface
, rate
);
1137 if (SUCCEEDED(hr
= MFGetService((IUnknown
*)player
->session
, &MF_RATE_CONTROL_SERVICE
, &IID_IMFRateControl
,
1138 (void **)&rate_control
)))
1140 hr
= IMFRateControl_GetRate(rate_control
, NULL
, rate
);
1141 IMFRateControl_Release(rate_control
);
1147 static HRESULT WINAPI
media_player_GetSupportedRates(IMFPMediaPlayer
*iface
, BOOL forward
,
1148 float *slowest_rate
, float *fastest_rate
)
1150 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1154 TRACE("%p, %d, %p, %p.\n", iface
, forward
, slowest_rate
, fastest_rate
);
1156 if (SUCCEEDED(hr
= MFGetService((IUnknown
*)player
->session
, &MF_RATE_CONTROL_SERVICE
, &IID_IMFRateSupport
, (void **)&rs
)))
1158 if (SUCCEEDED(hr
= IMFRateSupport_GetSlowestRate(rs
, forward
? MFRATE_FORWARD
: MFRATE_REVERSE
, FALSE
, slowest_rate
)))
1159 hr
= IMFRateSupport_GetFastestRate(rs
, forward
? MFRATE_FORWARD
: MFRATE_REVERSE
, FALSE
, fastest_rate
);
1160 IMFRateSupport_Release(rs
);
1166 static HRESULT WINAPI
media_player_GetState(IMFPMediaPlayer
*iface
, MFP_MEDIAPLAYER_STATE
*state
)
1168 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1170 TRACE("%p, %p.\n", iface
, state
);
1172 *state
= player
->state
;
1177 static HRESULT
media_player_create_item_from_url(struct media_player
*player
,
1178 const WCHAR
*url
, BOOL sync
, DWORD_PTR user_data
, IMFPMediaItem
**ret
)
1180 struct media_item
*item
;
1181 MF_OBJECT_TYPE obj_type
;
1188 if (!sync
&& !player
->callback
)
1190 WARN("Asynchronous item creation is not supported without user callback.\n");
1191 return MF_E_INVALIDREQUEST
;
1194 if (FAILED(hr
= create_media_item(player
, user_data
, &item
)))
1197 if (url
&& !(item
->url
= wcsdup(url
)))
1199 IMFPMediaItem_Release(&item
->IMFPMediaItem_iface
);
1200 return E_OUTOFMEMORY
;
1202 item
->flags
|= MEDIA_ITEM_SOURCE_NEEDS_SHUTDOWN
;
1208 if (SUCCEEDED(hr
= IMFSourceResolver_CreateObjectFromURL(player
->resolver
, url
, MF_RESOLUTION_MEDIASOURCE
1209 | MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE
, player
->propstore
, &obj_type
, &object
)))
1211 hr
= media_item_set_source(item
, object
);
1212 IUnknown_Release(object
);
1217 *ret
= &item
->IMFPMediaItem_iface
;
1218 IMFPMediaItem_AddRef(*ret
);
1221 IMFPMediaItem_Release(&item
->IMFPMediaItem_iface
);
1225 if (ret
) *ret
= NULL
;
1227 hr
= IMFSourceResolver_BeginCreateObjectFromURL(player
->resolver
, url
, MF_RESOLUTION_MEDIASOURCE
1228 | MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE
, player
->propstore
, NULL
,
1229 &player
->resolver_callback
, (IUnknown
*)&item
->IMFPMediaItem_iface
);
1231 IMFPMediaItem_Release(&item
->IMFPMediaItem_iface
);
1237 static HRESULT WINAPI
media_player_CreateMediaItemFromURL(IMFPMediaPlayer
*iface
,
1238 const WCHAR
*url
, BOOL sync
, DWORD_PTR user_data
, IMFPMediaItem
**item
)
1240 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1243 TRACE("%p, %s, %d, %Ix, %p.\n", iface
, debugstr_w(url
), sync
, user_data
, item
);
1245 EnterCriticalSection(&player
->cs
);
1246 if (player
->state
== MFP_MEDIAPLAYER_STATE_SHUTDOWN
)
1249 hr
= media_player_create_item_from_url(player
, url
, sync
, user_data
, item
);
1250 LeaveCriticalSection(&player
->cs
);
1255 static HRESULT
media_player_create_item_from_object(struct media_player
*player
,
1256 IUnknown
*object
, BOOL sync
, DWORD_PTR user_data
, IMFPMediaItem
**ret
)
1258 IMFMediaSource
*source
= NULL
;
1259 IMFByteStream
*stream
= NULL
;
1260 struct media_item
*item
;
1261 MF_OBJECT_TYPE obj_type
;
1266 if (FAILED(hr
= create_media_item(player
, user_data
, &item
)))
1269 item
->object
= object
;
1270 IUnknown_AddRef(item
->object
);
1272 if (FAILED(IUnknown_QueryInterface(object
, &IID_IMFMediaSource
, (void **)&source
)))
1273 IUnknown_QueryInterface(object
, &IID_IMFByteStream
, (void **)&stream
);
1275 if (!source
&& !stream
)
1277 WARN("Unsupported object type.\n");
1278 IMFPMediaItem_Release(&item
->IMFPMediaItem_iface
);
1279 return E_UNEXPECTED
;
1283 item
->flags
|= MEDIA_ITEM_SOURCE_NEEDS_SHUTDOWN
;
1288 hr
= IMFSourceResolver_CreateObjectFromByteStream(player
->resolver
, stream
, NULL
, MF_RESOLUTION_MEDIASOURCE
1289 | MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE
, player
->propstore
, &obj_type
, &object
);
1291 IUnknown_AddRef(object
);
1294 hr
= media_item_set_source(item
, object
);
1296 IUnknown_Release(object
);
1300 *ret
= &item
->IMFPMediaItem_iface
;
1301 IMFPMediaItem_AddRef(*ret
);
1304 IMFPMediaItem_Release(&item
->IMFPMediaItem_iface
);
1310 hr
= IMFSourceResolver_BeginCreateObjectFromByteStream(player
->resolver
, stream
, NULL
, MF_RESOLUTION_MEDIASOURCE
1311 | MF_RESOLUTION_CONTENT_DOES_NOT_HAVE_TO_MATCH_EXTENSION_OR_MIME_TYPE
, player
->propstore
, NULL
,
1312 &player
->resolver_callback
, (IUnknown
*)&item
->IMFPMediaItem_iface
);
1316 /* Resolver callback will check again if item's object is a source. */
1317 hr
= MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_MULTITHREADED
, &player
->resolver_callback
,
1318 (IUnknown
*)&item
->IMFPMediaItem_iface
);
1321 IMFPMediaItem_Release(&item
->IMFPMediaItem_iface
);
1325 IMFMediaSource_Release(source
);
1327 IMFByteStream_Release(stream
);
1332 static HRESULT WINAPI
media_player_CreateMediaItemFromObject(IMFPMediaPlayer
*iface
,
1333 IUnknown
*object
, BOOL sync
, DWORD_PTR user_data
, IMFPMediaItem
**item
)
1335 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1338 TRACE("%p, %p, %d, %Ix, %p.\n", iface
, object
, sync
, user_data
, item
);
1340 EnterCriticalSection(&player
->cs
);
1341 if (player
->state
== MFP_MEDIAPLAYER_STATE_SHUTDOWN
)
1344 hr
= media_player_create_item_from_object(player
, object
, sync
, user_data
, item
);
1345 LeaveCriticalSection(&player
->cs
);
1350 static HRESULT
media_item_create_source_node(struct media_item
*item
, IMFStreamDescriptor
*sd
,
1351 IMFTopologyNode
**node
)
1355 if (SUCCEEDED(hr
= MFCreateTopologyNode(MF_TOPOLOGY_SOURCESTREAM_NODE
, node
)))
1357 IMFTopologyNode_SetUnknown(*node
, &MF_TOPONODE_SOURCE
, (IUnknown
*)item
->source
);
1358 IMFTopologyNode_SetUnknown(*node
, &MF_TOPONODE_PRESENTATION_DESCRIPTOR
, (IUnknown
*)item
->pd
);
1359 IMFTopologyNode_SetUnknown(*node
, &MF_TOPONODE_STREAM_DESCRIPTOR
, (IUnknown
*)sd
);
1360 if (item
->start_position
)
1361 IMFTopologyNode_SetUINT64(*node
, &MF_TOPONODE_MEDIASTART
, item
->start_position
);
1362 if (item
->stop_position
)
1363 IMFTopologyNode_SetUINT64(*node
, &MF_TOPONODE_MEDIASTOP
, item
->stop_position
);
1369 static HRESULT
media_item_create_sink_node(IUnknown
*sink
, IMFTopologyNode
**node
)
1373 if (SUCCEEDED(hr
= MFCreateTopologyNode(MF_TOPOLOGY_OUTPUT_NODE
, node
)))
1374 IMFTopologyNode_SetObject(*node
, sink
);
1379 static HRESULT
media_item_create_topology(struct media_player
*player
, struct media_item
*item
, IMFTopology
**out
)
1381 BOOL selected
, video_added
= FALSE
;
1382 IMFStreamDescriptor
*sd
;
1383 IMFTopology
*topology
;
1389 if (FAILED(hr
= MFCreateTopology(&topology
)))
1392 /* Set up branches for all selected streams. */
1395 while (SUCCEEDED(IMFPresentationDescriptor_GetStreamDescriptorByIndex(item
->pd
, idx
++, &selected
, &sd
)))
1397 if (!selected
|| FAILED(media_item_get_stream_type(sd
, &major
)))
1399 IMFStreamDescriptor_Release(sd
);
1405 if (SUCCEEDED(IMFStreamDescriptor_GetUnknown(sd
, &_MF_CUSTOM_SINK
, &IID_IUnknown
, (void **)&sink
)))
1407 /* User sink is attached as-is. */
1409 else if (IsEqualGUID(&major
, &MFMediaType_Audio
))
1411 if (FAILED(hr
= MFCreateAudioRendererActivate((IMFActivate
**)&sink
)))
1412 WARN("Failed to create SAR activation object, hr %#lx.\n", hr
);
1414 else if (IsEqualGUID(&major
, &MFMediaType_Video
) && player
->output_window
&& !video_added
)
1416 if (FAILED(hr
= MFCreateVideoRendererActivate(player
->output_window
, (IMFActivate
**)&sink
)))
1417 WARN("Failed to create EVR activation object, hr %#lx.\n", hr
);
1418 video_added
= SUCCEEDED(hr
);
1423 IMFTopologyNode
*src_node
= NULL
, *sink_node
= NULL
;
1425 hr
= media_item_create_source_node(item
, sd
, &src_node
);
1427 hr
= media_item_create_sink_node(sink
, &sink_node
);
1431 IMFTopology_AddNode(topology
, src_node
);
1432 IMFTopology_AddNode(topology
, sink_node
);
1433 IMFTopologyNode_ConnectOutput(src_node
, 0, sink_node
, 0);
1437 IMFTopologyNode_Release(src_node
);
1439 IMFTopologyNode_Release(sink_node
);
1441 IUnknown_Release(sink
);
1444 IMFStreamDescriptor_Release(sd
);
1447 IMFTopology_SetUINT32(topology
, &MF_TOPOLOGY_ENUMERATE_SOURCE_TYPES
, TRUE
);
1454 static HRESULT WINAPI
media_player_SetMediaItem(IMFPMediaPlayer
*iface
, IMFPMediaItem
*item_iface
)
1456 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1457 struct media_item
*item
;
1458 IMFTopology
*topology
;
1461 TRACE("%p, %p.\n", iface
, item_iface
);
1466 item
= unsafe_impl_from_IMFPMediaItem(item_iface
);
1467 if (item
->player
!= player
)
1468 return E_INVALIDARG
;
1470 if (FAILED(hr
= media_item_create_topology(player
, item
, &topology
)))
1473 IMFTopology_SetUnknown(topology
, &_MF_TOPO_MEDIA_ITEM
, (IUnknown
*)item_iface
);
1474 hr
= IMFMediaSession_SetTopology(player
->session
, MFSESSION_SETTOPOLOGY_IMMEDIATE
, topology
);
1475 IMFTopology_Release(topology
);
1480 static HRESULT WINAPI
media_player_ClearMediaItem(IMFPMediaPlayer
*iface
)
1482 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1484 TRACE("%p.\n", iface
);
1486 return IMFMediaSession_SetTopology(player
->session
, MFSESSION_SETTOPOLOGY_CLEAR_CURRENT
, NULL
);
1489 static HRESULT WINAPI
media_player_GetMediaItem(IMFPMediaPlayer
*iface
, IMFPMediaItem
**item
)
1491 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1494 TRACE("%p, %p.\n", iface
, item
);
1499 EnterCriticalSection(&player
->cs
);
1500 if (player
->state
== MFP_MEDIAPLAYER_STATE_SHUTDOWN
)
1502 else if (!player
->item
)
1503 hr
= MF_E_NOT_FOUND
;
1506 *item
= player
->item
;
1507 IMFPMediaItem_AddRef(player
->item
);
1509 LeaveCriticalSection(&player
->cs
);
1514 static HRESULT WINAPI
media_player_GetVolume(IMFPMediaPlayer
*iface
, float *volume
)
1516 FIXME("%p, %p.\n", iface
, volume
);
1521 static HRESULT WINAPI
media_player_SetVolume(IMFPMediaPlayer
*iface
, float volume
)
1523 FIXME("%p, %.8e.\n", iface
, volume
);
1528 static HRESULT WINAPI
media_player_GetBalance(IMFPMediaPlayer
*iface
, float *balance
)
1530 FIXME("%p, %p.\n", iface
, balance
);
1535 static HRESULT WINAPI
media_player_SetBalance(IMFPMediaPlayer
*iface
, float balance
)
1537 FIXME("%p, %.8e.\n", iface
, balance
);
1542 static HRESULT WINAPI
media_player_GetMute(IMFPMediaPlayer
*iface
, BOOL
*mute
)
1544 FIXME("%p, %p.\n", iface
, mute
);
1549 static HRESULT WINAPI
media_player_SetMute(IMFPMediaPlayer
*iface
, BOOL mute
)
1551 FIXME("%p, %d.\n", iface
, mute
);
1556 static HRESULT
media_player_get_display_control(const struct media_player
*player
,
1557 IMFVideoDisplayControl
**display_control
)
1559 HRESULT hr
= MFGetService((IUnknown
*)player
->session
, &MR_VIDEO_RENDER_SERVICE
,
1560 &IID_IMFVideoDisplayControl
, (void **)display_control
);
1561 if (SUCCEEDED(hr
)) return hr
;
1562 return hr
== MF_E_SHUTDOWN
? hr
: MF_E_INVALIDREQUEST
;
1565 static HRESULT WINAPI
media_player_GetNativeVideoSize(IMFPMediaPlayer
*iface
,
1566 SIZE
*video
, SIZE
*arvideo
)
1568 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1569 IMFVideoDisplayControl
*display_control
;
1572 TRACE("%p, %p, %p.\n", iface
, video
, arvideo
);
1574 if (SUCCEEDED(hr
= media_player_get_display_control(player
, &display_control
)))
1576 hr
= IMFVideoDisplayControl_GetNativeVideoSize(display_control
, video
, arvideo
);
1577 IMFVideoDisplayControl_Release(display_control
);
1583 static HRESULT WINAPI
media_player_GetIdealVideoSize(IMFPMediaPlayer
*iface
,
1584 SIZE
*min_size
, SIZE
*max_size
)
1586 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1587 IMFVideoDisplayControl
*display_control
;
1590 TRACE("%p, %p, %p.\n", iface
, min_size
, max_size
);
1592 if (SUCCEEDED(hr
= media_player_get_display_control(player
, &display_control
)))
1594 hr
= IMFVideoDisplayControl_GetIdealVideoSize(display_control
, min_size
, max_size
);
1595 IMFVideoDisplayControl_Release(display_control
);
1601 static HRESULT WINAPI
media_player_SetVideoSourceRect(IMFPMediaPlayer
*iface
,
1602 MFVideoNormalizedRect
const *rect
)
1604 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1605 IMFVideoDisplayControl
*display_control
;
1609 TRACE("%p, %s.\n", iface
, debugstr_normalized_rect(rect
));
1611 if (!GetClientRect(player
->output_window
, &dst_rect
))
1612 hr
= HRESULT_FROM_WIN32(GetLastError());
1613 else if (SUCCEEDED(hr
= media_player_get_display_control(player
, &display_control
)))
1615 hr
= IMFVideoDisplayControl_SetVideoPosition(display_control
, rect
, &dst_rect
);
1616 IMFVideoDisplayControl_Release(display_control
);
1622 static HRESULT WINAPI
media_player_GetVideoSourceRect(IMFPMediaPlayer
*iface
,
1623 MFVideoNormalizedRect
*rect
)
1625 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1626 IMFVideoDisplayControl
*display_control
;
1630 TRACE("%p, %p.\n", iface
, rect
);
1632 if (SUCCEEDED(hr
= media_player_get_display_control(player
, &display_control
)))
1634 hr
= IMFVideoDisplayControl_GetVideoPosition(display_control
, rect
, &dest
);
1635 IMFVideoDisplayControl_Release(display_control
);
1641 static HRESULT WINAPI
media_player_SetAspectRatioMode(IMFPMediaPlayer
*iface
, DWORD mode
)
1643 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1644 IMFVideoDisplayControl
*display_control
;
1647 TRACE("%p, %lu.\n", iface
, mode
);
1649 if (SUCCEEDED(hr
= media_player_get_display_control(player
, &display_control
)))
1651 hr
= IMFVideoDisplayControl_SetAspectRatioMode(display_control
, mode
);
1652 IMFVideoDisplayControl_Release(display_control
);
1658 static HRESULT WINAPI
media_player_GetAspectRatioMode(IMFPMediaPlayer
*iface
,
1661 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1662 IMFVideoDisplayControl
*display_control
;
1665 TRACE("%p, %p.\n", iface
, mode
);
1667 if (SUCCEEDED(hr
= media_player_get_display_control(player
, &display_control
)))
1669 hr
= IMFVideoDisplayControl_GetAspectRatioMode(display_control
, mode
);
1670 IMFVideoDisplayControl_Release(display_control
);
1676 static HRESULT WINAPI
media_player_GetVideoWindow(IMFPMediaPlayer
*iface
, HWND
*window
)
1678 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1680 TRACE("%p, %p.\n", iface
, window
);
1682 *window
= player
->output_window
;
1687 static HRESULT WINAPI
media_player_UpdateVideo(IMFPMediaPlayer
*iface
)
1689 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1690 IMFVideoDisplayControl
*display_control
;
1694 TRACE("%p.\n", iface
);
1696 if (SUCCEEDED(hr
= media_player_get_display_control(player
, &display_control
)))
1698 if (GetClientRect(player
->output_window
, &rect
))
1699 hr
= IMFVideoDisplayControl_SetVideoPosition(display_control
, NULL
, &rect
);
1701 hr
= IMFVideoDisplayControl_RepaintVideo(display_control
);
1702 IMFVideoDisplayControl_Release(display_control
);
1708 static HRESULT WINAPI
media_player_SetBorderColor(IMFPMediaPlayer
*iface
, COLORREF color
)
1710 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1711 IMFVideoDisplayControl
*display_control
;
1714 TRACE("%p, %#lx.\n", iface
, color
);
1716 if (SUCCEEDED(hr
= media_player_get_display_control(player
, &display_control
)))
1718 hr
= IMFVideoDisplayControl_SetBorderColor(display_control
, color
);
1719 IMFVideoDisplayControl_Release(display_control
);
1725 static HRESULT WINAPI
media_player_GetBorderColor(IMFPMediaPlayer
*iface
, COLORREF
*color
)
1727 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1728 IMFVideoDisplayControl
*display_control
;
1731 TRACE("%p, %p.\n", iface
, color
);
1733 if (SUCCEEDED(hr
= media_player_get_display_control(player
, &display_control
)))
1735 hr
= IMFVideoDisplayControl_GetBorderColor(display_control
, color
);
1736 IMFVideoDisplayControl_Release(display_control
);
1742 static HRESULT WINAPI
media_player_InsertEffect(IMFPMediaPlayer
*iface
, IUnknown
*effect
,
1745 FIXME("%p, %p, %d.\n", iface
, effect
, optional
);
1750 static HRESULT WINAPI
media_player_RemoveEffect(IMFPMediaPlayer
*iface
, IUnknown
*effect
)
1752 FIXME("%p, %p.\n", iface
, effect
);
1757 static HRESULT WINAPI
media_player_RemoveAllEffects(IMFPMediaPlayer
*iface
)
1759 FIXME("%p.\n", iface
);
1764 static HRESULT WINAPI
media_player_Shutdown(IMFPMediaPlayer
*iface
)
1766 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
1768 TRACE("%p.\n", iface
);
1770 EnterCriticalSection(&player
->cs
);
1771 media_player_set_state(player
, MFP_MEDIAPLAYER_STATE_SHUTDOWN
);
1774 IMFPMediaItem_Release(player
->item
);
1775 player
->item
= NULL
;
1777 LeaveCriticalSection(&player
->cs
);
1782 static const IMFPMediaPlayerVtbl media_player_vtbl
=
1784 media_player_QueryInterface
,
1785 media_player_AddRef
,
1786 media_player_Release
,
1790 media_player_FrameStep
,
1791 media_player_SetPosition
,
1792 media_player_GetPosition
,
1793 media_player_GetDuration
,
1794 media_player_SetRate
,
1795 media_player_GetRate
,
1796 media_player_GetSupportedRates
,
1797 media_player_GetState
,
1798 media_player_CreateMediaItemFromURL
,
1799 media_player_CreateMediaItemFromObject
,
1800 media_player_SetMediaItem
,
1801 media_player_ClearMediaItem
,
1802 media_player_GetMediaItem
,
1803 media_player_GetVolume
,
1804 media_player_SetVolume
,
1805 media_player_GetBalance
,
1806 media_player_SetBalance
,
1807 media_player_GetMute
,
1808 media_player_SetMute
,
1809 media_player_GetNativeVideoSize
,
1810 media_player_GetIdealVideoSize
,
1811 media_player_SetVideoSourceRect
,
1812 media_player_GetVideoSourceRect
,
1813 media_player_SetAspectRatioMode
,
1814 media_player_GetAspectRatioMode
,
1815 media_player_GetVideoWindow
,
1816 media_player_UpdateVideo
,
1817 media_player_SetBorderColor
,
1818 media_player_GetBorderColor
,
1819 media_player_InsertEffect
,
1820 media_player_RemoveEffect
,
1821 media_player_RemoveAllEffects
,
1822 media_player_Shutdown
,
1825 static HRESULT WINAPI
media_player_propstore_QueryInterface(IPropertyStore
*iface
,
1826 REFIID riid
, void **obj
)
1828 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1829 return IMFPMediaPlayer_QueryInterface(&player
->IMFPMediaPlayer_iface
, riid
, obj
);
1832 static ULONG WINAPI
media_player_propstore_AddRef(IPropertyStore
*iface
)
1834 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1835 return IMFPMediaPlayer_AddRef(&player
->IMFPMediaPlayer_iface
);
1838 static ULONG WINAPI
media_player_propstore_Release(IPropertyStore
*iface
)
1840 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1841 return IMFPMediaPlayer_Release(&player
->IMFPMediaPlayer_iface
);
1844 static HRESULT WINAPI
media_player_propstore_GetCount(IPropertyStore
*iface
, DWORD
*count
)
1846 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1848 TRACE("%p, %p.\n", iface
, count
);
1850 return IPropertyStore_GetCount(player
->propstore
, count
);
1853 static HRESULT WINAPI
media_player_propstore_GetAt(IPropertyStore
*iface
, DWORD prop
, PROPERTYKEY
*key
)
1855 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1857 TRACE("%p, %lu, %p.\n", iface
, prop
, key
);
1859 return IPropertyStore_GetAt(player
->propstore
, prop
, key
);
1862 static HRESULT WINAPI
media_player_propstore_GetValue(IPropertyStore
*iface
, REFPROPERTYKEY key
, PROPVARIANT
*value
)
1864 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1866 TRACE("%p, %p, %p.\n", iface
, key
, value
);
1868 return IPropertyStore_GetValue(player
->propstore
, key
, value
);
1871 static HRESULT WINAPI
media_player_propstore_SetValue(IPropertyStore
*iface
, REFPROPERTYKEY key
, REFPROPVARIANT value
)
1873 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1875 TRACE("%p, %p, %p.\n", iface
, key
, value
);
1877 return IPropertyStore_SetValue(player
->propstore
, key
, value
);
1880 static HRESULT WINAPI
media_player_propstore_Commit(IPropertyStore
*iface
)
1882 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1884 TRACE("%p.\n", iface
);
1886 return IPropertyStore_Commit(player
->propstore
);
1889 static const IPropertyStoreVtbl media_player_propstore_vtbl
=
1891 media_player_propstore_QueryInterface
,
1892 media_player_propstore_AddRef
,
1893 media_player_propstore_Release
,
1894 media_player_propstore_GetCount
,
1895 media_player_propstore_GetAt
,
1896 media_player_propstore_GetValue
,
1897 media_player_propstore_SetValue
,
1898 media_player_propstore_Commit
,
1901 static HRESULT WINAPI
media_player_callback_QueryInterface(IMFAsyncCallback
*iface
,
1902 REFIID riid
, void **obj
)
1904 if (IsEqualIID(riid
, &IID_IMFAsyncCallback
) ||
1905 IsEqualIID(riid
, &IID_IUnknown
))
1908 IMFAsyncCallback_AddRef(iface
);
1913 return E_NOINTERFACE
;
1916 static ULONG WINAPI
media_player_resolver_callback_AddRef(IMFAsyncCallback
*iface
)
1918 struct media_player
*player
= impl_from_resolver_IMFAsyncCallback(iface
);
1919 return IMFPMediaPlayer_AddRef(&player
->IMFPMediaPlayer_iface
);
1922 static ULONG WINAPI
media_player_resolver_callback_Release(IMFAsyncCallback
*iface
)
1924 struct media_player
*player
= impl_from_resolver_IMFAsyncCallback(iface
);
1925 return IMFPMediaPlayer_Release(&player
->IMFPMediaPlayer_iface
);
1928 static HRESULT WINAPI
media_player_callback_GetParameters(IMFAsyncCallback
*iface
, DWORD
*flags
,
1934 static HRESULT WINAPI
media_player_resolver_callback_Invoke(IMFAsyncCallback
*iface
, IMFAsyncResult
*result
)
1936 struct media_player
*player
= impl_from_resolver_IMFAsyncCallback(iface
);
1937 struct media_event
*event
;
1938 IUnknown
*object
, *state
;
1939 MF_OBJECT_TYPE obj_type
;
1940 struct media_item
*item
;
1943 if (FAILED(IMFAsyncResult_GetState(result
, &state
)))
1946 item
= impl_from_IMFPMediaItem((IMFPMediaItem
*)state
);
1950 if (FAILED(hr
= IUnknown_QueryInterface(item
->object
, &IID_IMFMediaSource
, (void **)&object
)))
1951 hr
= IMFSourceResolver_EndCreateObjectFromByteStream(player
->resolver
, result
, &obj_type
, &object
);
1954 hr
= IMFSourceResolver_EndCreateObjectFromURL(player
->resolver
, result
, &obj_type
, &object
);
1958 hr
= media_item_set_source(item
, object
);
1959 IUnknown_Release(object
);
1963 WARN("Failed to set media source, hr %#lx.\n", hr
);
1965 if (FAILED(media_event_create(player
, MFP_EVENT_TYPE_MEDIAITEM_CREATED
, hr
,
1966 &item
->IMFPMediaItem_iface
, &event
)))
1968 WARN("Failed to create event object.\n");
1969 IUnknown_Release(state
);
1972 event
->u
.item_created
.dwUserData
= item
->user_data
;
1974 media_player_queue_event(player
, event
);
1976 IUnknown_Release(&event
->IUnknown_iface
);
1977 IUnknown_Release(state
);
1982 static const IMFAsyncCallbackVtbl media_player_resolver_callback_vtbl
=
1984 media_player_callback_QueryInterface
,
1985 media_player_resolver_callback_AddRef
,
1986 media_player_resolver_callback_Release
,
1987 media_player_callback_GetParameters
,
1988 media_player_resolver_callback_Invoke
,
1991 static ULONG WINAPI
media_player_events_callback_AddRef(IMFAsyncCallback
*iface
)
1993 struct media_player
*player
= impl_from_events_IMFAsyncCallback(iface
);
1994 return IMFPMediaPlayer_AddRef(&player
->IMFPMediaPlayer_iface
);
1997 static ULONG WINAPI
media_player_events_callback_Release(IMFAsyncCallback
*iface
)
1999 struct media_player
*player
= impl_from_events_IMFAsyncCallback(iface
);
2000 return IMFPMediaPlayer_Release(&player
->IMFPMediaPlayer_iface
);
2003 static HRESULT WINAPI
media_player_events_callback_Invoke(IMFAsyncCallback
*iface
, IMFAsyncResult
*result
)
2005 struct media_player
*player
= impl_from_events_IMFAsyncCallback(iface
);
2006 struct media_event
*event
;
2009 if (FAILED(IMFAsyncResult_GetState(result
, &state
)))
2012 event
= impl_event_from_IUnknown(state
);
2014 if (player
->callback
)
2015 IMFPMediaPlayerCallback_OnMediaPlayerEvent(player
->callback
, &event
->u
.header
);
2017 IUnknown_Release(state
);
2022 static const IMFAsyncCallbackVtbl media_player_events_callback_vtbl
=
2024 media_player_callback_QueryInterface
,
2025 media_player_events_callback_AddRef
,
2026 media_player_events_callback_Release
,
2027 media_player_callback_GetParameters
,
2028 media_player_events_callback_Invoke
,
2031 static ULONG WINAPI
media_player_session_events_callback_AddRef(IMFAsyncCallback
*iface
)
2033 struct media_player
*player
= impl_from_session_events_IMFAsyncCallback(iface
);
2034 return IMFPMediaPlayer_AddRef(&player
->IMFPMediaPlayer_iface
);
2037 static ULONG WINAPI
media_player_session_events_callback_Release(IMFAsyncCallback
*iface
)
2039 struct media_player
*player
= impl_from_session_events_IMFAsyncCallback(iface
);
2040 return IMFPMediaPlayer_Release(&player
->IMFPMediaPlayer_iface
);
2043 static void media_player_change_state(struct media_player
*player
, MFP_MEDIAPLAYER_STATE state
,
2044 HRESULT event_status
, struct media_event
**event
)
2046 MFP_EVENT_TYPE event_type
;
2048 EnterCriticalSection(&player
->cs
);
2050 if (state
== MFP_MEDIAPLAYER_STATE_PLAYING
)
2051 event_type
= MFP_EVENT_TYPE_PLAY
;
2052 else if (state
== MFP_MEDIAPLAYER_STATE_PAUSED
)
2053 event_type
= MFP_EVENT_TYPE_PAUSE
;
2055 event_type
= MFP_EVENT_TYPE_STOP
;
2057 media_player_set_state(player
, state
);
2058 media_event_create(player
, event_type
, event_status
, player
->item
, event
);
2060 LeaveCriticalSection(&player
->cs
);
2063 static void media_player_set_item(struct media_player
*player
, IMFTopology
*topology
, HRESULT event_status
,
2064 struct media_event
**event
)
2066 IMFPMediaItem
*item
;
2068 if (FAILED(IMFTopology_GetUnknown(topology
, &_MF_TOPO_MEDIA_ITEM
, &IID_IMFPMediaItem
, (void **)&item
)))
2071 EnterCriticalSection(&player
->cs
);
2074 IMFPMediaItem_Release(player
->item
);
2075 player
->item
= item
;
2076 IMFPMediaItem_AddRef(player
->item
);
2078 media_event_create(player
, MFP_EVENT_TYPE_MEDIAITEM_SET
, event_status
, item
, event
);
2080 LeaveCriticalSection(&player
->cs
);
2082 IMFPMediaItem_Release(item
);
2085 static void media_player_clear_item(struct media_player
*player
, HRESULT event_status
,
2086 struct media_event
**event
)
2088 IMFPMediaItem
*item
;
2090 EnterCriticalSection(&player
->cs
);
2092 item
= player
->item
;
2093 player
->item
= NULL
;
2095 media_event_create(player
, MFP_EVENT_TYPE_MEDIAITEM_SET
, event_status
, item
, event
);
2097 LeaveCriticalSection(&player
->cs
);
2100 static void media_player_create_forward_event(struct media_player
*player
, HRESULT event_status
, IMFMediaEvent
*session_event
,
2101 struct media_event
**event
)
2103 EnterCriticalSection(&player
->cs
);
2105 if (SUCCEEDED(media_event_create(player
, MFP_EVENT_TYPE_MF
, event_status
, player
->item
, event
)))
2107 IMFMediaEvent_GetType(session_event
, &(*event
)->u
.event
.MFEventType
);
2108 (*event
)->u
.event
.pMFMediaEvent
= session_event
;
2109 IMFMediaEvent_AddRef((*event
)->u
.event
.pMFMediaEvent
);
2112 LeaveCriticalSection(&player
->cs
);
2115 static void media_player_playback_ended(struct media_player
*player
, HRESULT event_status
,
2116 struct media_event
**event
)
2118 EnterCriticalSection(&player
->cs
);
2120 media_player_set_state(player
, MFP_MEDIAPLAYER_STATE_STOPPED
);
2121 media_event_create(player
, MFP_EVENT_TYPE_PLAYBACK_ENDED
, event_status
, player
->item
, event
);
2123 LeaveCriticalSection(&player
->cs
);
2126 static void media_player_rate_changed(struct media_player
*player
, HRESULT event_status
,
2127 float rate
, struct media_event
**event
)
2129 EnterCriticalSection(&player
->cs
);
2131 if (SUCCEEDED(media_event_create(player
, MFP_EVENT_TYPE_RATE_SET
, event_status
, player
->item
, event
)))
2132 (*event
)->u
.rate_set
.flRate
= rate
;
2134 LeaveCriticalSection(&player
->cs
);
2137 static HRESULT WINAPI
media_player_session_events_callback_Invoke(IMFAsyncCallback
*iface
,
2138 IMFAsyncResult
*result
)
2140 struct media_player
*player
= impl_from_session_events_IMFAsyncCallback(iface
);
2141 MediaEventType session_event_type
= MEUnknown
;
2142 struct media_event
*event
= NULL
;
2143 IMFMediaEvent
*session_event
;
2144 MFP_MEDIAPLAYER_STATE state
;
2145 HRESULT hr
, event_status
;
2146 IMFTopology
*topology
;
2147 unsigned int status
;
2151 if (FAILED(hr
= IMFMediaSession_EndGetEvent(player
->session
, result
, &session_event
)))
2154 IMFMediaEvent_GetType(session_event
, &session_event_type
);
2155 IMFMediaEvent_GetStatus(session_event
, &event_status
);
2157 switch (session_event_type
)
2159 case MESessionStarted
:
2160 case MESessionStopped
:
2161 case MESessionPaused
:
2163 if (session_event_type
== MESessionStarted
)
2164 state
= MFP_MEDIAPLAYER_STATE_PLAYING
;
2165 else if (session_event_type
== MESessionPaused
)
2166 state
= MFP_MEDIAPLAYER_STATE_PAUSED
;
2168 state
= MFP_MEDIAPLAYER_STATE_STOPPED
;
2170 media_player_change_state(player
, state
, event_status
, &event
);
2174 case MESessionTopologySet
:
2176 value
.vt
= VT_EMPTY
;
2177 if (SUCCEEDED(IMFMediaEvent_GetValue(session_event
, &value
)))
2179 if (value
.vt
== VT_EMPTY
)
2181 media_player_clear_item(player
, event_status
, &event
);
2183 else if (value
.vt
== VT_UNKNOWN
&& value
.punkVal
&&
2184 SUCCEEDED(IUnknown_QueryInterface(value
.punkVal
, &IID_IMFTopology
, (void **)&topology
)))
2186 media_player_set_item(player
, topology
, event_status
, &event
);
2187 IMFTopology_Release(topology
);
2189 PropVariantClear(&value
);
2194 case MESessionTopologyStatus
:
2196 if (SUCCEEDED(IMFMediaEvent_GetUINT32(session_event
, &MF_EVENT_TOPOLOGY_STATUS
, &status
)) &&
2197 status
== MF_TOPOSTATUS_ENDED
)
2199 media_player_playback_ended(player
, event_status
, &event
);
2204 case MESessionRateChanged
:
2207 if (SUCCEEDED(IMFMediaEvent_GetValue(session_event
, &value
)))
2209 if (value
.vt
== VT_R4
)
2210 rate
= value
.fltVal
;
2211 PropVariantClear(&value
);
2214 media_player_rate_changed(player
, event_status
, rate
, &event
);
2218 case MEBufferingStarted
:
2219 case MEBufferingStopped
:
2220 case MEExtendedType
:
2221 case MEReconnectStart
:
2222 case MEReconnectEnd
:
2223 case MERendererEvent
:
2224 case MEStreamSinkFormatChanged
:
2226 media_player_create_forward_event(player
, event_status
, session_event
, &event
);
2232 media_event_create(player
, MFP_EVENT_TYPE_ERROR
, event_status
, NULL
, &event
);
2242 media_player_queue_event(player
, event
);
2243 IUnknown_Release(&event
->IUnknown_iface
);
2246 IMFMediaSession_BeginGetEvent(player
->session
, &player
->session_events_callback
, NULL
);
2247 IMFMediaEvent_Release(session_event
);
2252 static const IMFAsyncCallbackVtbl media_player_session_events_callback_vtbl
=
2254 media_player_callback_QueryInterface
,
2255 media_player_session_events_callback_AddRef
,
2256 media_player_session_events_callback_Release
,
2257 media_player_callback_GetParameters
,
2258 media_player_session_events_callback_Invoke
,
2261 /***********************************************************************
2262 * MFPCreateMediaPlayer (mfplay.@)
2264 HRESULT WINAPI
MFPCreateMediaPlayer(const WCHAR
*url
, BOOL start_playback
, MFP_CREATION_OPTIONS options
,
2265 IMFPMediaPlayerCallback
*callback
, HWND window
, IMFPMediaPlayer
**player
)
2267 struct media_player
*object
;
2268 IMFPMediaItem
*item
;
2271 TRACE("%s, %d, %#x, %p, %p, %p.\n", debugstr_w(url
), start_playback
, options
, callback
, window
, player
);
2278 if (!url
&& start_playback
)
2279 return E_INVALIDARG
;
2281 if (!(object
= calloc(1, sizeof(*object
))))
2282 return E_OUTOFMEMORY
;
2286 object
->IMFPMediaPlayer_iface
.lpVtbl
= &media_player_vtbl
;
2287 object
->IPropertyStore_iface
.lpVtbl
= &media_player_propstore_vtbl
;
2288 object
->resolver_callback
.lpVtbl
= &media_player_resolver_callback_vtbl
;
2289 object
->events_callback
.lpVtbl
= &media_player_events_callback_vtbl
;
2290 object
->session_events_callback
.lpVtbl
= &media_player_session_events_callback_vtbl
;
2291 object
->refcount
= 1;
2292 object
->callback
= callback
;
2293 if (object
->callback
)
2294 IMFPMediaPlayerCallback_AddRef(object
->callback
);
2295 object
->options
= options
;
2296 object
->output_window
= window
;
2297 InitializeCriticalSection(&object
->cs
);
2298 if (FAILED(hr
= CreatePropertyStore(&object
->propstore
)))
2300 if (FAILED(hr
= MFCreateSourceResolver(&object
->resolver
)))
2302 if (FAILED(hr
= MFCreateMediaSession(NULL
, &object
->session
)))
2304 if (FAILED(hr
= IMFMediaSession_BeginGetEvent(object
->session
, &object
->session_events_callback
, NULL
)))
2306 if (!(object
->options
& MFP_OPTION_FREE_THREADED_CALLBACK
))
2308 object
->event_window
= CreateWindowW(eventclassW
, NULL
, 0, 0, 0, 0, 0, HWND_MESSAGE
,
2309 0, mfplay_instance
, NULL
);
2314 if (FAILED(hr
= media_player_create_item_from_url(object
, url
, TRUE
, 0, &item
)))
2316 WARN("Failed to create media item, hr %#lx.\n", hr
);
2320 hr
= IMFPMediaPlayer_SetMediaItem(&object
->IMFPMediaPlayer_iface
, item
);
2321 IMFPMediaItem_Release(item
);
2324 WARN("Failed to set media item, hr %#lx.\n", hr
);
2329 IMFPMediaPlayer_Play(&object
->IMFPMediaPlayer_iface
);
2332 *player
= &object
->IMFPMediaPlayer_iface
;
2338 IMFPMediaPlayer_Release(&object
->IMFPMediaPlayer_iface
);
2343 static void media_player_register_window_class(void)
2345 WNDCLASSW cls
= { 0 };
2347 cls
.lpfnWndProc
= media_player_event_proc
;
2348 cls
.hInstance
= mfplay_instance
;
2349 cls
.lpszClassName
= eventclassW
;
2351 RegisterClassW(&cls
);
2354 BOOL WINAPI
DllMain(HINSTANCE instance
, DWORD reason
, void *reserved
)
2358 case DLL_PROCESS_ATTACH
:
2359 mfplay_instance
= instance
;
2360 DisableThreadLibraryCalls(instance
);
2361 media_player_register_window_class();
2363 case DLL_PROCESS_DETACH
:
2364 if (reserved
) break;
2365 UnregisterClassW(eventclassW
, instance
);