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
28 #include "wine/debug.h"
29 #include "wine/heap.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(mfplat
);
33 static const WCHAR eventclassW
[] = L
"MediaPlayerEventCallbackClass";
35 static LONG startup_refcount
;
36 static HINSTANCE mfplay_instance
;
38 static void platform_startup(void)
40 if (InterlockedIncrement(&startup_refcount
) == 1)
41 MFStartup(MF_VERSION
, MFSTARTUP_FULL
);
44 static void platform_shutdown(void)
46 if (InterlockedDecrement(&startup_refcount
) == 0)
52 IMFPMediaItem IMFPMediaItem_iface
;
54 IMFPMediaPlayer
*player
;
55 IMFMediaSource
*source
;
56 IMFPresentationDescriptor
*pd
;
62 IMFPMediaPlayer IMFPMediaPlayer_iface
;
63 IPropertyStore IPropertyStore_iface
;
64 IMFAsyncCallback resolver_callback
;
65 IMFAsyncCallback events_callback
;
66 IMFAsyncCallback session_events_callback
;
68 IMFPMediaPlayerCallback
*callback
;
69 IPropertyStore
*propstore
;
70 IMFSourceResolver
*resolver
;
71 IMFMediaSession
*session
;
72 MFP_CREATION_OPTIONS options
;
73 MFP_MEDIAPLAYER_STATE state
;
81 MFP_EVENT_HEADER header
;
87 IUnknown IUnknown_iface
;
91 MFP_EVENT_HEADER header
;
92 struct generic_event generic
;
94 MFP_PAUSE_EVENT pause
;
96 MFP_POSITION_SET_EVENT position_set
;
97 MFP_RATE_SET_EVENT rate_set
;
98 MFP_MEDIAITEM_CREATED_EVENT item_created
;
99 MFP_MEDIAITEM_SET_EVENT item_set
;
100 MFP_MEDIAITEM_CLEARED_EVENT item_cleared
;
102 MFP_ERROR_EVENT error
;
103 MFP_PLAYBACK_ENDED_EVENT ended
;
104 MFP_ACQUIRE_USER_CREDENTIAL_EVENT acquire_creds
;
108 static struct media_player
*impl_from_IMFPMediaPlayer(IMFPMediaPlayer
*iface
)
110 return CONTAINING_RECORD(iface
, struct media_player
, IMFPMediaPlayer_iface
);
113 static struct media_player
*impl_from_IPropertyStore(IPropertyStore
*iface
)
115 return CONTAINING_RECORD(iface
, struct media_player
, IPropertyStore_iface
);
118 static struct media_player
*impl_from_resolver_IMFAsyncCallback(IMFAsyncCallback
*iface
)
120 return CONTAINING_RECORD(iface
, struct media_player
, resolver_callback
);
123 static struct media_player
*impl_from_events_IMFAsyncCallback(IMFAsyncCallback
*iface
)
125 return CONTAINING_RECORD(iface
, struct media_player
, events_callback
);
128 static struct media_player
*impl_from_session_events_IMFAsyncCallback(IMFAsyncCallback
*iface
)
130 return CONTAINING_RECORD(iface
, struct media_player
, session_events_callback
);
133 static struct media_item
*impl_from_IMFPMediaItem(IMFPMediaItem
*iface
)
135 return CONTAINING_RECORD(iface
, struct media_item
, IMFPMediaItem_iface
);
138 static struct media_event
*impl_event_from_IUnknown(IUnknown
*iface
)
140 return CONTAINING_RECORD(iface
, struct media_event
, IUnknown_iface
);
143 static HRESULT WINAPI
media_event_QueryInterface(IUnknown
*iface
, REFIID riid
, void **obj
)
145 if (IsEqualIID(riid
, &IID_IUnknown
))
148 IUnknown_AddRef(iface
);
153 return E_NOINTERFACE
;
156 static ULONG WINAPI
media_event_AddRef(IUnknown
*iface
)
158 struct media_event
*event
= impl_event_from_IUnknown(iface
);
159 ULONG refcount
= InterlockedIncrement(&event
->refcount
);
161 TRACE("%p, refcount %u.\n", iface
, refcount
);
166 static ULONG WINAPI
media_event_Release(IUnknown
*iface
)
168 struct media_event
*event
= impl_event_from_IUnknown(iface
);
169 ULONG refcount
= InterlockedDecrement(&event
->refcount
);
171 TRACE("%p, refcount %u.\n", iface
, refcount
);
175 if (event
->u
.header
.pMediaPlayer
)
176 IMFPMediaPlayer_Release(event
->u
.header
.pMediaPlayer
);
177 if (event
->u
.header
.pPropertyStore
)
178 IPropertyStore_Release(event
->u
.header
.pPropertyStore
);
180 switch (event
->u
.header
.eEventType
)
182 /* Most types share same layout. */
183 case MFP_EVENT_TYPE_PLAY
:
184 case MFP_EVENT_TYPE_PAUSE
:
185 case MFP_EVENT_TYPE_STOP
:
186 case MFP_EVENT_TYPE_POSITION_SET
:
187 case MFP_EVENT_TYPE_RATE_SET
:
188 case MFP_EVENT_TYPE_MEDIAITEM_CREATED
:
189 case MFP_EVENT_TYPE_MEDIAITEM_SET
:
190 case MFP_EVENT_TYPE_FRAME_STEP
:
191 case MFP_EVENT_TYPE_MEDIAITEM_CLEARED
:
192 case MFP_EVENT_TYPE_PLAYBACK_ENDED
:
193 if (event
->u
.generic
.item
)
194 IMFPMediaItem_Release(event
->u
.generic
.item
);
196 case MFP_EVENT_TYPE_MF
:
197 if (event
->u
.event
.pMFMediaEvent
)
198 IMFMediaEvent_Release(event
->u
.event
.pMFMediaEvent
);
199 if (event
->u
.event
.pMediaItem
)
200 IMFPMediaItem_Release(event
->u
.event
.pMediaItem
);
203 FIXME("Unsupported event %u.\n", event
->u
.header
.eEventType
);
213 static const IUnknownVtbl media_event_vtbl
=
215 media_event_QueryInterface
,
220 static HRESULT
media_event_create(struct media_player
*player
, MFP_EVENT_TYPE event_type
,
221 HRESULT hr
, struct media_event
**event
)
223 struct media_event
*object
;
225 if (!(object
= heap_alloc_zero(sizeof(*object
))))
226 return E_OUTOFMEMORY
;
228 object
->IUnknown_iface
.lpVtbl
= &media_event_vtbl
;
229 object
->refcount
= 1;
230 object
->u
.header
.eEventType
= event_type
;
231 object
->u
.header
.hrEvent
= hr
;
232 object
->u
.header
.pMediaPlayer
= &player
->IMFPMediaPlayer_iface
;
233 IMFPMediaPlayer_AddRef(object
->u
.header
.pMediaPlayer
);
234 object
->u
.header
.eState
= player
->state
;
235 /* FIXME: set properties for some events? */
242 static LRESULT WINAPI
media_player_event_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
244 struct media_event
*event
= (void *)lparam
;
245 struct media_player
*player
;
249 player
= impl_from_IMFPMediaPlayer(event
->u
.header
.pMediaPlayer
);
250 if (player
->callback
)
251 IMFPMediaPlayerCallback_OnMediaPlayerEvent(player
->callback
, &event
->u
.header
);
252 IUnknown_Release(&event
->IUnknown_iface
);
256 return DefWindowProcW(hwnd
, msg
, wparam
, lparam
);
259 static void media_player_set_state(struct media_player
*player
, MFP_MEDIAPLAYER_STATE state
)
261 if (player
->state
!= MFP_MEDIAPLAYER_STATE_SHUTDOWN
)
263 if (state
== MFP_MEDIAPLAYER_STATE_SHUTDOWN
)
264 IMFMediaSession_Shutdown(player
->session
);
265 player
->state
= state
;
269 static HRESULT WINAPI
media_item_QueryInterface(IMFPMediaItem
*iface
, REFIID riid
, void **obj
)
271 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
273 if (IsEqualIID(riid
, &IID_IMFPMediaItem
) ||
274 IsEqualIID(riid
, &IID_IUnknown
))
277 IMFPMediaItem_AddRef(iface
);
281 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
283 return E_NOINTERFACE
;
286 static ULONG WINAPI
media_item_AddRef(IMFPMediaItem
*iface
)
288 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
289 ULONG refcount
= InterlockedIncrement(&item
->refcount
);
291 TRACE("%p, refcount %u.\n", iface
, refcount
);
296 static ULONG WINAPI
media_item_Release(IMFPMediaItem
*iface
)
298 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
299 ULONG refcount
= InterlockedDecrement(&item
->refcount
);
301 TRACE("%p, refcount %u.\n", iface
, refcount
);
306 IMFPMediaPlayer_Release(item
->player
);
308 IMFMediaSource_Release(item
->source
);
310 IMFPresentationDescriptor_Release(item
->pd
);
317 static HRESULT WINAPI
media_item_GetMediaPlayer(IMFPMediaItem
*iface
,
318 IMFPMediaPlayer
**player
)
320 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
322 TRACE("%p, %p.\n", iface
, player
);
324 *player
= item
->player
;
325 IMFPMediaPlayer_AddRef(*player
);
330 static HRESULT WINAPI
media_item_GetURL(IMFPMediaItem
*iface
, LPWSTR
*url
)
332 FIXME("%p, %p.\n", iface
, url
);
337 static HRESULT WINAPI
media_item_GetObject(IMFPMediaItem
*iface
, IUnknown
**obj
)
339 FIXME("%p, %p.\n", iface
, obj
);
344 static HRESULT WINAPI
media_item_GetUserData(IMFPMediaItem
*iface
, DWORD_PTR
*user_data
)
346 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
348 TRACE("%p, %p.\n", iface
, user_data
);
350 *user_data
= item
->user_data
;
355 static HRESULT WINAPI
media_item_SetUserData(IMFPMediaItem
*iface
, DWORD_PTR user_data
)
357 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
359 TRACE("%p, %lx.\n", iface
, user_data
);
361 item
->user_data
= user_data
;
366 static HRESULT WINAPI
media_item_GetStartStopPosition(IMFPMediaItem
*iface
, GUID
*start_format
,
367 PROPVARIANT
*start_position
, GUID
*stop_format
, PROPVARIANT
*stop_position
)
369 FIXME("%p, %p, %p, %p, %p.\n", iface
, start_format
, start_position
, stop_format
, stop_position
);
374 static HRESULT WINAPI
media_item_SetStartStopPosition(IMFPMediaItem
*iface
, const GUID
*start_format
,
375 const PROPVARIANT
*start_position
, const GUID
*stop_format
, const PROPVARIANT
*stop_position
)
377 FIXME("%p, %s, %p, %s, %p.\n", iface
, debugstr_guid(start_format
), start_position
,
378 debugstr_guid(stop_format
), stop_position
);
383 static HRESULT WINAPI
media_item_HasVideo(IMFPMediaItem
*iface
, BOOL
*has_video
, BOOL
*selected
)
385 FIXME("%p, %p, %p.\n", iface
, has_video
, selected
);
390 static HRESULT WINAPI
media_item_HasAudio(IMFPMediaItem
*iface
, BOOL
*has_audio
, BOOL
*selected
)
392 FIXME("%p, %p, %p.\n", iface
, has_audio
, selected
);
397 static HRESULT WINAPI
media_item_IsProtected(IMFPMediaItem
*iface
, BOOL
*protected)
399 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
401 TRACE("%p, %p.\n", iface
, protected);
403 *protected = MFRequireProtectedEnvironment(item
->pd
) == S_OK
;
408 static HRESULT WINAPI
media_item_GetDuration(IMFPMediaItem
*iface
, REFGUID format
, PROPVARIANT
*value
)
410 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
412 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(format
), value
);
414 return IMFPresentationDescriptor_GetItem(item
->pd
, &MF_PD_DURATION
, value
);
417 static HRESULT WINAPI
media_item_GetNumberOfStreams(IMFPMediaItem
*iface
, DWORD
*count
)
419 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
421 TRACE("%p, %p.\n", iface
, count
);
423 return IMFPresentationDescriptor_GetStreamDescriptorCount(item
->pd
, count
);
426 static HRESULT WINAPI
media_item_GetStreamSelection(IMFPMediaItem
*iface
, DWORD index
, BOOL
*selected
)
428 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
429 IMFStreamDescriptor
*sd
;
432 TRACE("%p, %u, %p.\n", iface
, index
, selected
);
434 if (SUCCEEDED(hr
= IMFPresentationDescriptor_GetStreamDescriptorByIndex(item
->pd
, index
, selected
, &sd
)))
435 IMFStreamDescriptor_Release(sd
);
440 static HRESULT WINAPI
media_item_SetStreamSelection(IMFPMediaItem
*iface
, DWORD index
, BOOL select
)
442 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
444 TRACE("%p, %u, %d.\n", iface
, index
, select
);
446 return select
? IMFPresentationDescriptor_SelectStream(item
->pd
, index
) :
447 IMFPresentationDescriptor_DeselectStream(item
->pd
, index
);
450 static HRESULT WINAPI
media_item_GetStreamAttribute(IMFPMediaItem
*iface
, DWORD index
, REFGUID key
,
453 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
454 IMFStreamDescriptor
*sd
;
458 TRACE("%p, %u, %s, %p.\n", iface
, index
, debugstr_guid(key
), value
);
460 if (SUCCEEDED(hr
= IMFPresentationDescriptor_GetStreamDescriptorByIndex(item
->pd
, index
, &selected
, &sd
)))
462 hr
= IMFStreamDescriptor_GetItem(sd
, key
, value
);
463 IMFStreamDescriptor_Release(sd
);
469 static HRESULT WINAPI
media_item_GetPresentationAttribute(IMFPMediaItem
*iface
, REFGUID key
,
472 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
474 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
476 return IMFPresentationDescriptor_GetItem(item
->pd
, key
, value
);
479 static HRESULT WINAPI
media_item_GetCharacteristics(IMFPMediaItem
*iface
, MFP_MEDIAITEM_CHARACTERISTICS
*flags
)
481 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
484 TRACE("%p, %p.\n", iface
, flags
);
488 if (SUCCEEDED(hr
= IMFMediaSource_GetCharacteristics(item
->source
, flags
)))
490 *flags
&= (MFP_MEDIAITEM_IS_LIVE
| MFP_MEDIAITEM_CAN_SEEK
|
491 MFP_MEDIAITEM_CAN_PAUSE
| MFP_MEDIAITEM_HAS_SLOW_SEEK
);
497 static HRESULT WINAPI
media_item_SetStreamSink(IMFPMediaItem
*iface
, DWORD index
, IUnknown
*sink
)
499 FIXME("%p, %u, %p.\n", iface
, index
, sink
);
504 static HRESULT WINAPI
media_item_GetMetadata(IMFPMediaItem
*iface
, IPropertyStore
**metadata
)
506 struct media_item
*item
= impl_from_IMFPMediaItem(iface
);
508 TRACE("%p, %p.\n", iface
, metadata
);
510 return MFGetService((IUnknown
*)item
->source
, &MF_PROPERTY_HANDLER_SERVICE
,
511 &IID_IPropertyStore
, (void **)&metadata
);
514 static const IMFPMediaItemVtbl media_item_vtbl
=
516 media_item_QueryInterface
,
519 media_item_GetMediaPlayer
,
521 media_item_GetObject
,
522 media_item_GetUserData
,
523 media_item_SetUserData
,
524 media_item_GetStartStopPosition
,
525 media_item_SetStartStopPosition
,
528 media_item_IsProtected
,
529 media_item_GetDuration
,
530 media_item_GetNumberOfStreams
,
531 media_item_GetStreamSelection
,
532 media_item_SetStreamSelection
,
533 media_item_GetStreamAttribute
,
534 media_item_GetPresentationAttribute
,
535 media_item_GetCharacteristics
,
536 media_item_SetStreamSink
,
537 media_item_GetMetadata
,
540 static HRESULT
create_media_item(IMFPMediaPlayer
*player
, DWORD_PTR user_data
, struct media_item
**item
)
542 struct media_item
*object
;
544 if (!(object
= heap_alloc_zero(sizeof(*object
))))
545 return E_OUTOFMEMORY
;
547 object
->IMFPMediaItem_iface
.lpVtbl
= &media_item_vtbl
;
548 object
->refcount
= 1;
549 object
->user_data
= user_data
;
550 object
->player
= player
;
551 IMFPMediaPlayer_AddRef(object
->player
);
558 static HRESULT
media_item_set_source(struct media_item
*item
, IUnknown
*object
)
560 IMFPresentationDescriptor
*pd
;
561 IMFMediaSource
*source
;
564 if (FAILED(hr
= IUnknown_QueryInterface(object
, &IID_IMFMediaSource
, (void **)&source
)))
567 if (FAILED(hr
= IMFMediaSource_CreatePresentationDescriptor(source
, &pd
)))
569 WARN("Failed to get presentation descriptor, hr %#x.\n", hr
);
570 IMFMediaSource_Release(source
);
574 item
->source
= source
;
580 static void media_player_queue_event(struct media_player
*player
, struct media_event
*event
)
582 if (player
->options
& MFP_OPTION_FREE_THREADED_CALLBACK
)
584 MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_MULTITHREADED
, &player
->events_callback
, &event
->IUnknown_iface
);
588 IUnknown_AddRef(&event
->IUnknown_iface
);
589 PostMessageW(player
->event_window
, WM_USER
, 0, (LPARAM
)event
);
593 static HRESULT WINAPI
media_player_QueryInterface(IMFPMediaPlayer
*iface
, REFIID riid
, void **obj
)
595 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
597 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
599 if (IsEqualIID(riid
, &IID_IMFPMediaPlayer
) ||
600 IsEqualIID(riid
, &IID_IUnknown
))
602 *obj
= &player
->IMFPMediaPlayer_iface
;
604 else if (IsEqualIID(riid
, &IID_IPropertyStore
))
606 *obj
= &player
->IPropertyStore_iface
;
610 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
613 return E_NOINTERFACE
;
616 IUnknown_AddRef((IUnknown
*)*obj
);
620 static ULONG WINAPI
media_player_AddRef(IMFPMediaPlayer
*iface
)
622 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
623 ULONG refcount
= InterlockedIncrement(&player
->refcount
);
625 TRACE("%p, refcount %u.\n", iface
, refcount
);
630 static ULONG WINAPI
media_player_Release(IMFPMediaPlayer
*iface
)
632 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
633 ULONG refcount
= InterlockedDecrement(&player
->refcount
);
635 TRACE("%p, refcount %u.\n", iface
, refcount
);
639 if (player
->callback
)
640 IMFPMediaPlayerCallback_Release(player
->callback
);
641 if (player
->propstore
)
642 IPropertyStore_Release(player
->propstore
);
643 if (player
->resolver
)
644 IMFSourceResolver_Release(player
->resolver
);
646 IMFMediaSession_Release(player
->session
);
647 DestroyWindow(player
->event_window
);
648 DeleteCriticalSection(&player
->cs
);
657 static HRESULT WINAPI
media_player_Play(IMFPMediaPlayer
*iface
)
659 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
662 TRACE("%p.\n", iface
);
665 return IMFMediaSession_Start(player
->session
, &GUID_NULL
, &pos
);
668 static HRESULT WINAPI
media_player_Pause(IMFPMediaPlayer
*iface
)
670 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
672 TRACE("%p.\n", iface
);
674 return IMFMediaSession_Pause(player
->session
);
677 static HRESULT WINAPI
media_player_Stop(IMFPMediaPlayer
*iface
)
679 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
681 TRACE("%p.\n", iface
);
683 return IMFMediaSession_Stop(player
->session
);
686 static HRESULT WINAPI
media_player_FrameStep(IMFPMediaPlayer
*iface
)
688 FIXME("%p.\n", iface
);
693 static HRESULT WINAPI
media_player_SetPosition(IMFPMediaPlayer
*iface
, REFGUID postype
, const PROPVARIANT
*position
)
695 FIXME("%p, %s, %p.\n", iface
, debugstr_guid(postype
), position
);
700 static HRESULT WINAPI
media_player_GetPosition(IMFPMediaPlayer
*iface
, REFGUID postype
, PROPVARIANT
*position
)
702 FIXME("%p, %s, %p.\n", iface
, debugstr_guid(postype
), position
);
707 static HRESULT WINAPI
media_player_GetDuration(IMFPMediaPlayer
*iface
, REFGUID postype
, PROPVARIANT
*position
)
709 FIXME("%p, %s, %p.\n", iface
, debugstr_guid(postype
), position
);
714 static HRESULT WINAPI
media_player_SetRate(IMFPMediaPlayer
*iface
, float rate
)
716 FIXME("%p, %f.\n", iface
, rate
);
721 static HRESULT WINAPI
media_player_GetRate(IMFPMediaPlayer
*iface
, float *rate
)
723 FIXME("%p, %p.\n", iface
, rate
);
728 static HRESULT WINAPI
media_player_GetSupportedRates(IMFPMediaPlayer
*iface
, BOOL forward
,
729 float *slowest_rate
, float *fastest_rate
)
731 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
735 TRACE("%p, %d, %p, %p.\n", iface
, forward
, slowest_rate
, fastest_rate
);
737 if (SUCCEEDED(hr
= MFGetService((IUnknown
*)player
->session
, &MF_RATE_CONTROL_SERVICE
, &IID_IMFRateSupport
, (void **)&rs
)))
739 if (SUCCEEDED(hr
= IMFRateSupport_GetSlowestRate(rs
, forward
? MFRATE_FORWARD
: MFRATE_REVERSE
, FALSE
, slowest_rate
)))
740 hr
= IMFRateSupport_GetFastestRate(rs
, forward
? MFRATE_FORWARD
: MFRATE_REVERSE
, FALSE
, fastest_rate
);
741 IMFRateSupport_Release(rs
);
747 static HRESULT WINAPI
media_player_GetState(IMFPMediaPlayer
*iface
, MFP_MEDIAPLAYER_STATE
*state
)
749 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
751 TRACE("%p, %p.\n", iface
, state
);
753 *state
= player
->state
;
758 static HRESULT WINAPI
media_player_CreateMediaItemFromURL(IMFPMediaPlayer
*iface
,
759 const WCHAR
*url
, BOOL sync
, DWORD_PTR user_data
, IMFPMediaItem
**ret
)
761 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
762 struct media_item
*item
;
763 MF_OBJECT_TYPE obj_type
;
767 TRACE("%p, %s, %d, %lx, %p.\n", iface
, debugstr_w(url
), sync
, user_data
, ret
);
769 if (FAILED(hr
= create_media_item(iface
, user_data
, &item
)))
776 if (SUCCEEDED(hr
= IMFSourceResolver_CreateObjectFromURL(player
->resolver
, url
, MF_RESOLUTION_MEDIASOURCE
,
777 player
->propstore
, &obj_type
, &object
)))
779 hr
= media_item_set_source(item
, object
);
780 IUnknown_Release(object
);
784 *ret
= &item
->IMFPMediaItem_iface
;
790 hr
= IMFSourceResolver_BeginCreateObjectFromURL(player
->resolver
, url
, MF_RESOLUTION_MEDIASOURCE
,
791 player
->propstore
, NULL
, &player
->resolver_callback
, (IUnknown
*)&item
->IMFPMediaItem_iface
);
793 IMFPMediaItem_Release(&item
->IMFPMediaItem_iface
);
799 static HRESULT WINAPI
media_player_CreateMediaItemFromObject(IMFPMediaPlayer
*iface
,
800 IUnknown
*object
, BOOL sync
, DWORD_PTR user_data
, IMFPMediaItem
**item
)
802 FIXME("%p, %p, %d, %lx, %p.\n", iface
, object
, sync
, user_data
, item
);
807 static HRESULT WINAPI
media_player_SetMediaItem(IMFPMediaPlayer
*iface
, IMFPMediaItem
*item
)
809 FIXME("%p, %p.\n", iface
, item
);
814 static HRESULT WINAPI
media_player_ClearMediaItem(IMFPMediaPlayer
*iface
)
816 FIXME("%p.\n", iface
);
821 static HRESULT WINAPI
media_player_GetMediaItem(IMFPMediaPlayer
*iface
, IMFPMediaItem
**item
)
823 FIXME("%p, %p.\n", iface
, item
);
828 static HRESULT WINAPI
media_player_GetVolume(IMFPMediaPlayer
*iface
, float *volume
)
830 FIXME("%p, %p.\n", iface
, volume
);
835 static HRESULT WINAPI
media_player_SetVolume(IMFPMediaPlayer
*iface
, float volume
)
837 FIXME("%p, %.8e.\n", iface
, volume
);
842 static HRESULT WINAPI
media_player_GetBalance(IMFPMediaPlayer
*iface
, float *balance
)
844 FIXME("%p, %p.\n", iface
, balance
);
849 static HRESULT WINAPI
media_player_SetBalance(IMFPMediaPlayer
*iface
, float balance
)
851 FIXME("%p, %.8e.\n", iface
, balance
);
856 static HRESULT WINAPI
media_player_GetMute(IMFPMediaPlayer
*iface
, BOOL
*mute
)
858 FIXME("%p, %p.\n", iface
, mute
);
863 static HRESULT WINAPI
media_player_SetMute(IMFPMediaPlayer
*iface
, BOOL mute
)
865 FIXME("%p, %d.\n", iface
, mute
);
870 static HRESULT WINAPI
media_player_GetNativeVideoSize(IMFPMediaPlayer
*iface
,
871 SIZE
*video
, SIZE
*arvideo
)
873 FIXME("%p, %p, %p.\n", iface
, video
, arvideo
);
878 static HRESULT WINAPI
media_player_GetIdealVideoSize(IMFPMediaPlayer
*iface
,
879 SIZE
*min_size
, SIZE
*max_size
)
881 FIXME("%p, %p, %p.\n", iface
, min_size
, max_size
);
886 static HRESULT WINAPI
media_player_SetVideoSourceRect(IMFPMediaPlayer
*iface
,
887 MFVideoNormalizedRect
const *rect
)
889 FIXME("%p, %p.\n", iface
, rect
);
894 static HRESULT WINAPI
media_player_GetVideoSourceRect(IMFPMediaPlayer
*iface
,
895 MFVideoNormalizedRect
*rect
)
897 FIXME("%p, %p.\n", iface
, rect
);
902 static HRESULT WINAPI
media_player_SetAspectRatioMode(IMFPMediaPlayer
*iface
, DWORD mode
)
904 FIXME("%p, %u.\n", iface
, mode
);
909 static HRESULT WINAPI
media_player_GetAspectRatioMode(IMFPMediaPlayer
*iface
,
912 FIXME("%p, %p.\n", iface
, mode
);
917 static HRESULT WINAPI
media_player_GetVideoWindow(IMFPMediaPlayer
*iface
, HWND
*window
)
919 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
921 TRACE("%p, %p.\n", iface
, window
);
923 *window
= player
->output_window
;
928 static HRESULT WINAPI
media_player_UpdateVideo(IMFPMediaPlayer
*iface
)
930 FIXME("%p.\n", iface
);
935 static HRESULT WINAPI
media_player_SetBorderColor(IMFPMediaPlayer
*iface
, COLORREF color
)
937 FIXME("%p, %#x.\n", iface
, color
);
942 static HRESULT WINAPI
media_player_GetBorderColor(IMFPMediaPlayer
*iface
, COLORREF
*color
)
944 FIXME("%p, %p.\n", iface
, color
);
949 static HRESULT WINAPI
media_player_InsertEffect(IMFPMediaPlayer
*iface
, IUnknown
*effect
,
952 FIXME("%p, %p, %d.\n", iface
, effect
, optional
);
957 static HRESULT WINAPI
media_player_RemoveEffect(IMFPMediaPlayer
*iface
, IUnknown
*effect
)
959 FIXME("%p, %p.\n", iface
, effect
);
964 static HRESULT WINAPI
media_player_RemoveAllEffects(IMFPMediaPlayer
*iface
)
966 FIXME("%p.\n", iface
);
971 static HRESULT WINAPI
media_player_Shutdown(IMFPMediaPlayer
*iface
)
973 struct media_player
*player
= impl_from_IMFPMediaPlayer(iface
);
975 TRACE("%p.\n", iface
);
977 EnterCriticalSection(&player
->cs
);
978 media_player_set_state(player
, MFP_MEDIAPLAYER_STATE_SHUTDOWN
);
979 LeaveCriticalSection(&player
->cs
);
984 static const IMFPMediaPlayerVtbl media_player_vtbl
=
986 media_player_QueryInterface
,
988 media_player_Release
,
992 media_player_FrameStep
,
993 media_player_SetPosition
,
994 media_player_GetPosition
,
995 media_player_GetDuration
,
996 media_player_SetRate
,
997 media_player_GetRate
,
998 media_player_GetSupportedRates
,
999 media_player_GetState
,
1000 media_player_CreateMediaItemFromURL
,
1001 media_player_CreateMediaItemFromObject
,
1002 media_player_SetMediaItem
,
1003 media_player_ClearMediaItem
,
1004 media_player_GetMediaItem
,
1005 media_player_GetVolume
,
1006 media_player_SetVolume
,
1007 media_player_GetBalance
,
1008 media_player_SetBalance
,
1009 media_player_GetMute
,
1010 media_player_SetMute
,
1011 media_player_GetNativeVideoSize
,
1012 media_player_GetIdealVideoSize
,
1013 media_player_SetVideoSourceRect
,
1014 media_player_GetVideoSourceRect
,
1015 media_player_SetAspectRatioMode
,
1016 media_player_GetAspectRatioMode
,
1017 media_player_GetVideoWindow
,
1018 media_player_UpdateVideo
,
1019 media_player_SetBorderColor
,
1020 media_player_GetBorderColor
,
1021 media_player_InsertEffect
,
1022 media_player_RemoveEffect
,
1023 media_player_RemoveAllEffects
,
1024 media_player_Shutdown
,
1027 static HRESULT WINAPI
media_player_propstore_QueryInterface(IPropertyStore
*iface
,
1028 REFIID riid
, void **obj
)
1030 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1031 return IMFPMediaPlayer_QueryInterface(&player
->IMFPMediaPlayer_iface
, riid
, obj
);
1034 static ULONG WINAPI
media_player_propstore_AddRef(IPropertyStore
*iface
)
1036 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1037 return IMFPMediaPlayer_AddRef(&player
->IMFPMediaPlayer_iface
);
1040 static ULONG WINAPI
media_player_propstore_Release(IPropertyStore
*iface
)
1042 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1043 return IMFPMediaPlayer_Release(&player
->IMFPMediaPlayer_iface
);
1046 static HRESULT WINAPI
media_player_propstore_GetCount(IPropertyStore
*iface
, DWORD
*count
)
1048 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1050 TRACE("%p, %p.\n", iface
, count
);
1052 return IPropertyStore_GetCount(player
->propstore
, count
);
1055 static HRESULT WINAPI
media_player_propstore_GetAt(IPropertyStore
*iface
, DWORD prop
, PROPERTYKEY
*key
)
1057 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1059 TRACE("%p, %u, %p.\n", iface
, prop
, key
);
1061 return IPropertyStore_GetAt(player
->propstore
, prop
, key
);
1064 static HRESULT WINAPI
media_player_propstore_GetValue(IPropertyStore
*iface
, REFPROPERTYKEY key
, PROPVARIANT
*value
)
1066 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1068 TRACE("%p, %p, %p.\n", iface
, key
, value
);
1070 return IPropertyStore_GetValue(player
->propstore
, key
, value
);
1073 static HRESULT WINAPI
media_player_propstore_SetValue(IPropertyStore
*iface
, REFPROPERTYKEY key
, REFPROPVARIANT value
)
1075 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1077 TRACE("%p, %p, %p.\n", iface
, key
, value
);
1079 return IPropertyStore_SetValue(player
->propstore
, key
, value
);
1082 static HRESULT WINAPI
media_player_propstore_Commit(IPropertyStore
*iface
)
1084 struct media_player
*player
= impl_from_IPropertyStore(iface
);
1086 TRACE("%p.\n", iface
);
1088 return IPropertyStore_Commit(player
->propstore
);
1091 static const IPropertyStoreVtbl media_player_propstore_vtbl
=
1093 media_player_propstore_QueryInterface
,
1094 media_player_propstore_AddRef
,
1095 media_player_propstore_Release
,
1096 media_player_propstore_GetCount
,
1097 media_player_propstore_GetAt
,
1098 media_player_propstore_GetValue
,
1099 media_player_propstore_SetValue
,
1100 media_player_propstore_Commit
,
1103 static HRESULT WINAPI
media_player_callback_QueryInterface(IMFAsyncCallback
*iface
,
1104 REFIID riid
, void **obj
)
1106 if (IsEqualIID(riid
, &IID_IMFAsyncCallback
) ||
1107 IsEqualIID(riid
, &IID_IUnknown
))
1110 IMFAsyncCallback_AddRef(iface
);
1115 return E_NOINTERFACE
;
1118 static ULONG WINAPI
media_player_resolver_callback_AddRef(IMFAsyncCallback
*iface
)
1120 struct media_player
*player
= impl_from_resolver_IMFAsyncCallback(iface
);
1121 return IMFPMediaPlayer_AddRef(&player
->IMFPMediaPlayer_iface
);
1124 static ULONG WINAPI
media_player_resolver_callback_Release(IMFAsyncCallback
*iface
)
1126 struct media_player
*player
= impl_from_resolver_IMFAsyncCallback(iface
);
1127 return IMFPMediaPlayer_Release(&player
->IMFPMediaPlayer_iface
);
1130 static HRESULT WINAPI
media_player_callback_GetParameters(IMFAsyncCallback
*iface
, DWORD
*flags
,
1136 static HRESULT WINAPI
media_player_resolver_callback_Invoke(IMFAsyncCallback
*iface
, IMFAsyncResult
*result
)
1138 struct media_player
*player
= impl_from_resolver_IMFAsyncCallback(iface
);
1139 struct media_event
*event
;
1140 IUnknown
*object
, *state
;
1141 MF_OBJECT_TYPE obj_type
;
1142 struct media_item
*item
;
1145 if (FAILED(IMFAsyncResult_GetState(result
, &state
)))
1148 item
= impl_from_IMFPMediaItem((IMFPMediaItem
*)state
);
1150 if (SUCCEEDED(hr
= IMFSourceResolver_EndCreateObjectFromURL(player
->resolver
, result
, &obj_type
, &object
)))
1152 hr
= media_item_set_source(item
, object
);
1153 IUnknown_Release(object
);
1157 WARN("Failed to set media source, hr %#x.\n", hr
);
1159 if (FAILED(media_event_create(player
, MFP_EVENT_TYPE_MEDIAITEM_CREATED
, hr
, &event
)))
1161 WARN("Failed to create event object.\n");
1162 IUnknown_Release(state
);
1168 event
->u
.item_created
.pMediaItem
= &item
->IMFPMediaItem_iface
;
1169 IMFPMediaItem_AddRef(event
->u
.item_created
.pMediaItem
);
1171 event
->u
.item_created
.dwUserData
= item
->user_data
;
1173 media_player_queue_event(player
, event
);
1175 IUnknown_Release(&event
->IUnknown_iface
);
1176 IUnknown_Release(state
);
1181 static const IMFAsyncCallbackVtbl media_player_resolver_callback_vtbl
=
1183 media_player_callback_QueryInterface
,
1184 media_player_resolver_callback_AddRef
,
1185 media_player_resolver_callback_Release
,
1186 media_player_callback_GetParameters
,
1187 media_player_resolver_callback_Invoke
,
1190 static ULONG WINAPI
media_player_events_callback_AddRef(IMFAsyncCallback
*iface
)
1192 struct media_player
*player
= impl_from_events_IMFAsyncCallback(iface
);
1193 return IMFPMediaPlayer_AddRef(&player
->IMFPMediaPlayer_iface
);
1196 static ULONG WINAPI
media_player_events_callback_Release(IMFAsyncCallback
*iface
)
1198 struct media_player
*player
= impl_from_events_IMFAsyncCallback(iface
);
1199 return IMFPMediaPlayer_Release(&player
->IMFPMediaPlayer_iface
);
1202 static HRESULT WINAPI
media_player_events_callback_Invoke(IMFAsyncCallback
*iface
, IMFAsyncResult
*result
)
1204 struct media_player
*player
= impl_from_events_IMFAsyncCallback(iface
);
1205 struct media_event
*event
;
1208 if (FAILED(IMFAsyncResult_GetState(result
, &state
)))
1211 event
= impl_event_from_IUnknown(state
);
1213 if (player
->callback
)
1214 IMFPMediaPlayerCallback_OnMediaPlayerEvent(player
->callback
, &event
->u
.header
);
1216 IUnknown_Release(state
);
1221 static const IMFAsyncCallbackVtbl media_player_events_callback_vtbl
=
1223 media_player_callback_QueryInterface
,
1224 media_player_events_callback_AddRef
,
1225 media_player_events_callback_Release
,
1226 media_player_callback_GetParameters
,
1227 media_player_events_callback_Invoke
,
1230 static ULONG WINAPI
media_player_session_events_callback_AddRef(IMFAsyncCallback
*iface
)
1232 struct media_player
*player
= impl_from_session_events_IMFAsyncCallback(iface
);
1233 return IMFPMediaPlayer_AddRef(&player
->IMFPMediaPlayer_iface
);
1236 static ULONG WINAPI
media_player_session_events_callback_Release(IMFAsyncCallback
*iface
)
1238 struct media_player
*player
= impl_from_session_events_IMFAsyncCallback(iface
);
1239 return IMFPMediaPlayer_Release(&player
->IMFPMediaPlayer_iface
);
1242 static HRESULT WINAPI
media_player_session_events_callback_Invoke(IMFAsyncCallback
*iface
,
1243 IMFAsyncResult
*result
)
1245 struct media_player
*player
= impl_from_session_events_IMFAsyncCallback(iface
);
1246 MediaEventType session_event_type
= MEUnknown
;
1247 struct media_event
*event
= NULL
;
1248 IMFMediaEvent
*session_event
;
1249 MFP_MEDIAPLAYER_STATE state
;
1250 MFP_EVENT_TYPE event_type
;
1251 HRESULT hr
, event_status
;
1253 if (FAILED(hr
= IMFMediaSession_EndGetEvent(player
->session
, result
, &session_event
)))
1256 IMFMediaEvent_GetType(session_event
, &session_event_type
);
1257 IMFMediaEvent_GetStatus(session_event
, &event_status
);
1259 switch (session_event_type
)
1261 case MESessionStarted
:
1262 case MESessionStopped
:
1263 case MESessionPaused
:
1264 if (session_event_type
== MESessionStarted
)
1266 event_type
= MFP_EVENT_TYPE_PLAY
;
1267 state
= MFP_MEDIAPLAYER_STATE_PLAYING
;
1269 else if (session_event_type
== MESessionStopped
)
1271 event_type
= MFP_EVENT_TYPE_STOP
;
1272 state
= MFP_MEDIAPLAYER_STATE_STOPPED
;
1276 event_type
= MFP_EVENT_TYPE_PAUSE
;
1277 state
= MFP_MEDIAPLAYER_STATE_PAUSED
;
1280 EnterCriticalSection(&player
->cs
);
1281 media_player_set_state(player
, state
);
1282 media_event_create(player
, event_type
, event_status
, &event
);
1283 LeaveCriticalSection(&player
->cs
);
1285 /* FIXME: set pMediaItem */
1286 media_player_queue_event(player
, event
);
1287 IUnknown_Release(&event
->IUnknown_iface
);
1296 IUnknown_Release(&event
->IUnknown_iface
);
1299 IMFMediaSession_BeginGetEvent(player
->session
, &player
->session_events_callback
, NULL
);
1300 IMFMediaEvent_Release(session_event
);
1305 static const IMFAsyncCallbackVtbl media_player_session_events_callback_vtbl
=
1307 media_player_callback_QueryInterface
,
1308 media_player_session_events_callback_AddRef
,
1309 media_player_session_events_callback_Release
,
1310 media_player_callback_GetParameters
,
1311 media_player_session_events_callback_Invoke
,
1314 HRESULT WINAPI
MFPCreateMediaPlayer(const WCHAR
*url
, BOOL start_playback
, MFP_CREATION_OPTIONS options
,
1315 IMFPMediaPlayerCallback
*callback
, HWND window
, IMFPMediaPlayer
**player
)
1317 struct media_player
*object
;
1320 TRACE("%s, %d, %#x, %p, %p, %p.\n", debugstr_w(url
), start_playback
, options
, callback
, window
, player
);
1322 if (!(object
= heap_alloc_zero(sizeof(*object
))))
1323 return E_OUTOFMEMORY
;
1327 object
->IMFPMediaPlayer_iface
.lpVtbl
= &media_player_vtbl
;
1328 object
->IPropertyStore_iface
.lpVtbl
= &media_player_propstore_vtbl
;
1329 object
->resolver_callback
.lpVtbl
= &media_player_resolver_callback_vtbl
;
1330 object
->events_callback
.lpVtbl
= &media_player_events_callback_vtbl
;
1331 object
->session_events_callback
.lpVtbl
= &media_player_session_events_callback_vtbl
;
1332 object
->refcount
= 1;
1333 object
->callback
= callback
;
1334 if (object
->callback
)
1335 IMFPMediaPlayerCallback_AddRef(object
->callback
);
1336 object
->options
= options
;
1337 object
->output_window
= window
;
1338 InitializeCriticalSection(&object
->cs
);
1339 if (FAILED(hr
= CreatePropertyStore(&object
->propstore
)))
1341 if (FAILED(hr
= MFCreateSourceResolver(&object
->resolver
)))
1343 if (FAILED(hr
= MFCreateMediaSession(NULL
, &object
->session
)))
1345 if (FAILED(hr
= IMFMediaSession_BeginGetEvent(object
->session
, &object
->session_events_callback
, NULL
)))
1347 if (!(object
->options
& MFP_OPTION_FREE_THREADED_CALLBACK
))
1349 object
->event_window
= CreateWindowW(eventclassW
, NULL
, 0, 0, 0, 0, 0, HWND_MESSAGE
,
1350 0, mfplay_instance
, NULL
);
1353 *player
= &object
->IMFPMediaPlayer_iface
;
1359 IMFPMediaPlayer_Release(&object
->IMFPMediaPlayer_iface
);
1364 static void media_player_register_window_class(void)
1366 WNDCLASSW cls
= { 0 };
1368 cls
.lpfnWndProc
= media_player_event_proc
;
1369 cls
.hInstance
= mfplay_instance
;
1370 cls
.lpszClassName
= eventclassW
;
1372 RegisterClassW(&cls
);
1375 BOOL WINAPI
DllMain(HINSTANCE instance
, DWORD reason
, void *reserved
)
1379 case DLL_PROCESS_ATTACH
:
1380 mfplay_instance
= instance
;
1381 DisableThreadLibraryCalls(instance
);
1382 media_player_register_window_class();
1384 case DLL_PROCESS_DETACH
:
1385 if (reserved
) break;
1386 UnregisterClassW(eventclassW
, instance
);