mfplay: Add support for same-thread event callback.
[wine.git] / dlls / mfplay / player.c
blob246704c279940afb406679593381c0e20974e3e9
1 /*
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
19 #define COBJMACROS
21 #include <stdarg.h>
23 #include "windef.h"
24 #include "winbase.h"
25 #include "mfapi.h"
26 #include "mfplay.h"
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)
47 MFShutdown();
50 struct media_item
52 IMFPMediaItem IMFPMediaItem_iface;
53 LONG refcount;
54 IMFPMediaPlayer *player;
55 IMFMediaSource *source;
56 IMFPresentationDescriptor *pd;
57 DWORD_PTR user_data;
60 struct media_player
62 IMFPMediaPlayer IMFPMediaPlayer_iface;
63 IPropertyStore IPropertyStore_iface;
64 IMFAsyncCallback resolver_callback;
65 IMFAsyncCallback events_callback;
66 LONG refcount;
67 IMFPMediaPlayerCallback *callback;
68 IPropertyStore *propstore;
69 IMFSourceResolver *resolver;
70 MFP_CREATION_OPTIONS options;
71 HWND event_window;
74 struct generic_event
76 MFP_EVENT_HEADER header;
77 IMFPMediaItem *item;
80 struct media_event
82 IUnknown IUnknown_iface;
83 LONG refcount;
84 union
86 MFP_EVENT_HEADER header;
87 struct generic_event generic;
88 MFP_PLAY_EVENT play;
89 MFP_PAUSE_EVENT pause;
90 MFP_STOP_EVENT stop;
91 MFP_POSITION_SET_EVENT position_set;
92 MFP_RATE_SET_EVENT rate_set;
93 MFP_MEDIAITEM_CREATED_EVENT item_created;
94 MFP_MEDIAITEM_SET_EVENT item_set;
95 MFP_MEDIAITEM_CLEARED_EVENT item_cleared;
96 MFP_MF_EVENT event;
97 MFP_ERROR_EVENT error;
98 MFP_PLAYBACK_ENDED_EVENT ended;
99 MFP_ACQUIRE_USER_CREDENTIAL_EVENT acquire_creds;
100 } u;
103 static struct media_player *impl_from_IMFPMediaPlayer(IMFPMediaPlayer *iface)
105 return CONTAINING_RECORD(iface, struct media_player, IMFPMediaPlayer_iface);
108 static struct media_player *impl_from_IPropertyStore(IPropertyStore *iface)
110 return CONTAINING_RECORD(iface, struct media_player, IPropertyStore_iface);
113 static struct media_player *impl_from_resolver_IMFAsyncCallback(IMFAsyncCallback *iface)
115 return CONTAINING_RECORD(iface, struct media_player, resolver_callback);
118 static struct media_player *impl_from_events_IMFAsyncCallback(IMFAsyncCallback *iface)
120 return CONTAINING_RECORD(iface, struct media_player, events_callback);
123 static struct media_item *impl_from_IMFPMediaItem(IMFPMediaItem *iface)
125 return CONTAINING_RECORD(iface, struct media_item, IMFPMediaItem_iface);
128 static struct media_event *impl_event_from_IUnknown(IUnknown *iface)
130 return CONTAINING_RECORD(iface, struct media_event, IUnknown_iface);
133 static HRESULT WINAPI media_event_QueryInterface(IUnknown *iface, REFIID riid, void **obj)
135 if (IsEqualIID(riid, &IID_IUnknown))
137 *obj = iface;
138 IUnknown_AddRef(iface);
139 return S_OK;
142 *obj = NULL;
143 return E_NOINTERFACE;
146 static ULONG WINAPI media_event_AddRef(IUnknown *iface)
148 struct media_event *event = impl_event_from_IUnknown(iface);
149 ULONG refcount = InterlockedIncrement(&event->refcount);
151 TRACE("%p, refcount %u.\n", iface, refcount);
153 return refcount;
156 static ULONG WINAPI media_event_Release(IUnknown *iface)
158 struct media_event *event = impl_event_from_IUnknown(iface);
159 ULONG refcount = InterlockedDecrement(&event->refcount);
161 TRACE("%p, refcount %u.\n", iface, refcount);
163 if (!refcount)
165 if (event->u.header.pMediaPlayer)
166 IMFPMediaPlayer_Release(event->u.header.pMediaPlayer);
167 if (event->u.header.pPropertyStore)
168 IPropertyStore_Release(event->u.header.pPropertyStore);
170 switch (event->u.header.eEventType)
172 /* Most types share same layout. */
173 case MFP_EVENT_TYPE_PLAY:
174 case MFP_EVENT_TYPE_PAUSE:
175 case MFP_EVENT_TYPE_STOP:
176 case MFP_EVENT_TYPE_POSITION_SET:
177 case MFP_EVENT_TYPE_RATE_SET:
178 case MFP_EVENT_TYPE_MEDIAITEM_CREATED:
179 case MFP_EVENT_TYPE_MEDIAITEM_SET:
180 case MFP_EVENT_TYPE_FRAME_STEP:
181 case MFP_EVENT_TYPE_MEDIAITEM_CLEARED:
182 case MFP_EVENT_TYPE_PLAYBACK_ENDED:
183 if (event->u.generic.item)
184 IMFPMediaItem_Release(event->u.generic.item);
185 break;
186 case MFP_EVENT_TYPE_MF:
187 if (event->u.event.pMFMediaEvent)
188 IMFMediaEvent_Release(event->u.event.pMFMediaEvent);
189 if (event->u.event.pMediaItem)
190 IMFPMediaItem_Release(event->u.event.pMediaItem);
191 break;
192 default:
193 FIXME("Unsupported event %u.\n", event->u.header.eEventType);
194 break;
197 heap_free(event);
200 return refcount;
203 static const IUnknownVtbl media_event_vtbl =
205 media_event_QueryInterface,
206 media_event_AddRef,
207 media_event_Release,
210 static HRESULT media_event_create(MFP_EVENT_TYPE event_type, HRESULT hr,
211 IMFPMediaPlayer *player, struct media_event **event)
213 struct media_event *object;
215 if (!(object = heap_alloc_zero(sizeof(*object))))
216 return E_OUTOFMEMORY;
218 object->IUnknown_iface.lpVtbl = &media_event_vtbl;
219 object->refcount = 1;
220 object->u.header.eEventType = event_type;
221 object->u.header.hrEvent = hr;
222 object->u.header.pMediaPlayer = player;
223 IMFPMediaPlayer_AddRef(object->u.header.pMediaPlayer);
224 /* FIXME: set player state field */
225 /* FIXME: set properties for some events? */
227 *event = object;
229 return S_OK;
232 static LRESULT WINAPI media_player_event_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
234 struct media_event *event = (void *)lparam;
235 struct media_player *player;
237 if (msg == WM_USER)
239 player = impl_from_IMFPMediaPlayer(event->u.header.pMediaPlayer);
240 if (player->callback)
241 IMFPMediaPlayerCallback_OnMediaPlayerEvent(player->callback, &event->u.header);
242 IUnknown_Release(&event->IUnknown_iface);
243 return 0;
246 return DefWindowProcW(hwnd, msg, wparam, lparam);
249 static HRESULT WINAPI media_item_QueryInterface(IMFPMediaItem *iface, REFIID riid, void **obj)
251 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
253 if (IsEqualIID(riid, &IID_IMFPMediaItem) ||
254 IsEqualIID(riid, &IID_IUnknown))
256 *obj = iface;
257 IMFPMediaItem_AddRef(iface);
258 return S_OK;
261 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
262 *obj = NULL;
263 return E_NOINTERFACE;
266 static ULONG WINAPI media_item_AddRef(IMFPMediaItem *iface)
268 struct media_item *item = impl_from_IMFPMediaItem(iface);
269 ULONG refcount = InterlockedIncrement(&item->refcount);
271 TRACE("%p, refcount %u.\n", iface, refcount);
273 return refcount;
276 static ULONG WINAPI media_item_Release(IMFPMediaItem *iface)
278 struct media_item *item = impl_from_IMFPMediaItem(iface);
279 ULONG refcount = InterlockedDecrement(&item->refcount);
281 TRACE("%p, refcount %u.\n", iface, refcount);
283 if (!refcount)
285 if (item->player)
286 IMFPMediaPlayer_Release(item->player);
287 if (item->source)
288 IMFMediaSource_Release(item->source);
289 if (item->pd)
290 IMFPresentationDescriptor_Release(item->pd);
291 heap_free(item);
294 return refcount;
297 static HRESULT WINAPI media_item_GetMediaPlayer(IMFPMediaItem *iface,
298 IMFPMediaPlayer **player)
300 struct media_item *item = impl_from_IMFPMediaItem(iface);
302 TRACE("%p, %p.\n", iface, player);
304 *player = item->player;
305 IMFPMediaPlayer_AddRef(*player);
307 return S_OK;
310 static HRESULT WINAPI media_item_GetURL(IMFPMediaItem *iface, LPWSTR *url)
312 FIXME("%p, %p.\n", iface, url);
314 return E_NOTIMPL;
317 static HRESULT WINAPI media_item_GetObject(IMFPMediaItem *iface, IUnknown **obj)
319 FIXME("%p, %p.\n", iface, obj);
321 return E_NOTIMPL;
324 static HRESULT WINAPI media_item_GetUserData(IMFPMediaItem *iface, DWORD_PTR *user_data)
326 struct media_item *item = impl_from_IMFPMediaItem(iface);
328 TRACE("%p, %p.\n", iface, user_data);
330 *user_data = item->user_data;
332 return S_OK;
335 static HRESULT WINAPI media_item_SetUserData(IMFPMediaItem *iface, DWORD_PTR user_data)
337 struct media_item *item = impl_from_IMFPMediaItem(iface);
339 TRACE("%p, %lx.\n", iface, user_data);
341 item->user_data = user_data;
343 return S_OK;
346 static HRESULT WINAPI media_item_GetStartStopPosition(IMFPMediaItem *iface, GUID *start_format,
347 PROPVARIANT *start_position, GUID *stop_format, PROPVARIANT *stop_position)
349 FIXME("%p, %p, %p, %p, %p.\n", iface, start_format, start_position, stop_format, stop_position);
351 return E_NOTIMPL;
354 static HRESULT WINAPI media_item_SetStartStopPosition(IMFPMediaItem *iface, const GUID *start_format,
355 const PROPVARIANT *start_position, const GUID *stop_format, const PROPVARIANT *stop_position)
357 FIXME("%p, %s, %p, %s, %p.\n", iface, debugstr_guid(start_format), start_position,
358 debugstr_guid(stop_format), stop_position);
360 return E_NOTIMPL;
363 static HRESULT WINAPI media_item_HasVideo(IMFPMediaItem *iface, BOOL *has_video, BOOL *selected)
365 FIXME("%p, %p, %p.\n", iface, has_video, selected);
367 return E_NOTIMPL;
370 static HRESULT WINAPI media_item_HasAudio(IMFPMediaItem *iface, BOOL *has_audio, BOOL *selected)
372 FIXME("%p, %p, %p.\n", iface, has_audio, selected);
374 return E_NOTIMPL;
377 static HRESULT WINAPI media_item_IsProtected(IMFPMediaItem *iface, BOOL *protected)
379 struct media_item *item = impl_from_IMFPMediaItem(iface);
381 TRACE("%p, %p.\n", iface, protected);
383 *protected = MFRequireProtectedEnvironment(item->pd) == S_OK;
385 return S_OK;
388 static HRESULT WINAPI media_item_GetDuration(IMFPMediaItem *iface, REFGUID format, PROPVARIANT *value)
390 FIXME("%p, %s, %p.\n", iface, debugstr_guid(format), value);
392 return E_NOTIMPL;
395 static HRESULT WINAPI media_item_GetNumberOfStreams(IMFPMediaItem *iface, DWORD *count)
397 struct media_item *item = impl_from_IMFPMediaItem(iface);
399 TRACE("%p, %p.\n", iface, count);
401 return IMFPresentationDescriptor_GetStreamDescriptorCount(item->pd, count);
404 static HRESULT WINAPI media_item_GetStreamSelection(IMFPMediaItem *iface, DWORD index, BOOL *selected)
406 struct media_item *item = impl_from_IMFPMediaItem(iface);
407 IMFStreamDescriptor *sd;
408 HRESULT hr;
410 TRACE("%p, %u, %p.\n", iface, index, selected);
412 if (SUCCEEDED(hr = IMFPresentationDescriptor_GetStreamDescriptorByIndex(item->pd, index, selected, &sd)))
413 IMFStreamDescriptor_Release(sd);
415 return hr;
418 static HRESULT WINAPI media_item_SetStreamSelection(IMFPMediaItem *iface, DWORD index, BOOL select)
420 struct media_item *item = impl_from_IMFPMediaItem(iface);
422 TRACE("%p, %u, %d.\n", iface, index, select);
424 return select ? IMFPresentationDescriptor_SelectStream(item->pd, index) :
425 IMFPresentationDescriptor_DeselectStream(item->pd, index);
428 static HRESULT WINAPI media_item_GetStreamAttribute(IMFPMediaItem *iface, DWORD index, REFGUID key,
429 PROPVARIANT *value)
431 struct media_item *item = impl_from_IMFPMediaItem(iface);
432 IMFStreamDescriptor *sd;
433 BOOL selected;
434 HRESULT hr;
436 TRACE("%p, %u, %s, %p.\n", iface, index, debugstr_guid(key), value);
438 if (SUCCEEDED(hr = IMFPresentationDescriptor_GetStreamDescriptorByIndex(item->pd, index, &selected, &sd)))
440 hr = IMFStreamDescriptor_GetItem(sd, key, value);
441 IMFStreamDescriptor_Release(sd);
444 return hr;
447 static HRESULT WINAPI media_item_GetPresentationAttribute(IMFPMediaItem *iface, REFGUID key,
448 PROPVARIANT *value)
450 struct media_item *item = impl_from_IMFPMediaItem(iface);
452 TRACE("%p, %s, %p.\n", iface, debugstr_guid(key), value);
454 return IMFPresentationDescriptor_GetItem(item->pd, key, value);
457 static HRESULT WINAPI media_item_GetCharacteristics(IMFPMediaItem *iface, MFP_MEDIAITEM_CHARACTERISTICS *flags)
459 struct media_item *item = impl_from_IMFPMediaItem(iface);
460 HRESULT hr;
462 TRACE("%p, %p.\n", iface, flags);
464 *flags = 0;
466 if (SUCCEEDED(hr = IMFMediaSource_GetCharacteristics(item->source, flags)))
468 *flags &= (MFP_MEDIAITEM_IS_LIVE | MFP_MEDIAITEM_CAN_SEEK |
469 MFP_MEDIAITEM_CAN_PAUSE | MFP_MEDIAITEM_HAS_SLOW_SEEK);
472 return hr;
475 static HRESULT WINAPI media_item_SetStreamSink(IMFPMediaItem *iface, DWORD index, IUnknown *sink)
477 FIXME("%p, %u, %p.\n", iface, index, sink);
479 return E_NOTIMPL;
482 static HRESULT WINAPI media_item_GetMetadata(IMFPMediaItem *iface, IPropertyStore **metadata)
484 FIXME("%p, %p.\n", iface, metadata);
486 return E_NOTIMPL;
489 static const IMFPMediaItemVtbl media_item_vtbl =
491 media_item_QueryInterface,
492 media_item_AddRef,
493 media_item_Release,
494 media_item_GetMediaPlayer,
495 media_item_GetURL,
496 media_item_GetObject,
497 media_item_GetUserData,
498 media_item_SetUserData,
499 media_item_GetStartStopPosition,
500 media_item_SetStartStopPosition,
501 media_item_HasVideo,
502 media_item_HasAudio,
503 media_item_IsProtected,
504 media_item_GetDuration,
505 media_item_GetNumberOfStreams,
506 media_item_GetStreamSelection,
507 media_item_SetStreamSelection,
508 media_item_GetStreamAttribute,
509 media_item_GetPresentationAttribute,
510 media_item_GetCharacteristics,
511 media_item_SetStreamSink,
512 media_item_GetMetadata,
515 static HRESULT create_media_item(IMFPMediaPlayer *player, DWORD_PTR user_data, struct media_item **item)
517 struct media_item *object;
519 if (!(object = heap_alloc_zero(sizeof(*object))))
520 return E_OUTOFMEMORY;
522 object->IMFPMediaItem_iface.lpVtbl = &media_item_vtbl;
523 object->refcount = 1;
524 object->user_data = user_data;
525 object->player = player;
526 IMFPMediaPlayer_AddRef(object->player);
528 *item = object;
530 return S_OK;
533 static HRESULT media_item_set_source(struct media_item *item, IUnknown *object)
535 IMFPresentationDescriptor *pd;
536 IMFMediaSource *source;
537 HRESULT hr;
539 if (FAILED(hr = IUnknown_QueryInterface(object, &IID_IMFMediaSource, (void **)&source)))
540 return hr;
542 if (FAILED(hr = IMFMediaSource_CreatePresentationDescriptor(source, &pd)))
544 WARN("Failed to get presentation descriptor, hr %#x.\n", hr);
545 IMFMediaSource_Release(source);
546 return hr;
549 item->source = source;
550 item->pd = pd;
552 return hr;
555 static void media_player_queue_event(struct media_player *player, struct media_event *event)
557 if (player->options & MFP_OPTION_FREE_THREADED_CALLBACK)
559 MFPutWorkItem(MFASYNC_CALLBACK_QUEUE_MULTITHREADED, &player->events_callback, &event->IUnknown_iface);
561 else
563 IUnknown_AddRef(&event->IUnknown_iface);
564 PostMessageW(player->event_window, WM_USER, 0, (LPARAM)event);
568 static HRESULT WINAPI media_player_QueryInterface(IMFPMediaPlayer *iface, REFIID riid, void **obj)
570 struct media_player *player = impl_from_IMFPMediaPlayer(iface);
572 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
574 if (IsEqualIID(riid, &IID_IMFPMediaPlayer) ||
575 IsEqualIID(riid, &IID_IUnknown))
577 *obj = &player->IMFPMediaPlayer_iface;
579 else if (IsEqualIID(riid, &IID_IPropertyStore))
581 *obj = &player->IPropertyStore_iface;
583 else
585 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
586 *obj = NULL;
588 return E_NOINTERFACE;
591 IUnknown_AddRef((IUnknown *)*obj);
592 return S_OK;
595 static ULONG WINAPI media_player_AddRef(IMFPMediaPlayer *iface)
597 struct media_player *player = impl_from_IMFPMediaPlayer(iface);
598 ULONG refcount = InterlockedIncrement(&player->refcount);
600 TRACE("%p, refcount %u.\n", iface, refcount);
602 return refcount;
605 static ULONG WINAPI media_player_Release(IMFPMediaPlayer *iface)
607 struct media_player *player = impl_from_IMFPMediaPlayer(iface);
608 ULONG refcount = InterlockedDecrement(&player->refcount);
610 TRACE("%p, refcount %u.\n", iface, refcount);
612 if (!refcount)
614 if (player->callback)
615 IMFPMediaPlayerCallback_Release(player->callback);
616 if (player->propstore)
617 IPropertyStore_Release(player->propstore);
618 if (player->resolver)
619 IMFSourceResolver_Release(player->resolver);
620 DestroyWindow(player->event_window);
621 heap_free(player);
623 platform_shutdown();
626 return refcount;
629 static HRESULT WINAPI media_player_Play(IMFPMediaPlayer *iface)
631 FIXME("%p.\n", iface);
633 return E_NOTIMPL;
636 static HRESULT WINAPI media_player_Pause(IMFPMediaPlayer *iface)
638 FIXME("%p.\n", iface);
640 return E_NOTIMPL;
643 static HRESULT WINAPI media_player_Stop(IMFPMediaPlayer *iface)
645 FIXME("%p.\n", iface);
647 return E_NOTIMPL;
650 static HRESULT WINAPI media_player_FrameStep(IMFPMediaPlayer *iface)
652 FIXME("%p.\n", iface);
654 return E_NOTIMPL;
657 static HRESULT WINAPI media_player_SetPosition(IMFPMediaPlayer *iface, REFGUID postype, const PROPVARIANT *position)
659 FIXME("%p, %s, %p.\n", iface, debugstr_guid(postype), position);
661 return E_NOTIMPL;
664 static HRESULT WINAPI media_player_GetPosition(IMFPMediaPlayer *iface, REFGUID postype, PROPVARIANT *position)
666 FIXME("%p, %s, %p.\n", iface, debugstr_guid(postype), position);
668 return E_NOTIMPL;
671 static HRESULT WINAPI media_player_GetDuration(IMFPMediaPlayer *iface, REFGUID postype, PROPVARIANT *position)
673 FIXME("%p, %s, %p.\n", iface, debugstr_guid(postype), position);
675 return E_NOTIMPL;
678 static HRESULT WINAPI media_player_SetRate(IMFPMediaPlayer *iface, float rate)
680 FIXME("%p, %f.\n", iface, rate);
682 return E_NOTIMPL;
685 static HRESULT WINAPI media_player_GetRate(IMFPMediaPlayer *iface, float *rate)
687 FIXME("%p, %p.\n", iface, rate);
689 return E_NOTIMPL;
692 static HRESULT WINAPI media_player_GetSupportedRates(IMFPMediaPlayer *iface, BOOL forward, float *slowest_rate, float *fastest_rate)
694 FIXME("%p, %d, %p, %p.\n", iface, forward, slowest_rate, fastest_rate);
696 return E_NOTIMPL;
699 static HRESULT WINAPI media_player_GetState(IMFPMediaPlayer *iface, MFP_MEDIAPLAYER_STATE *state)
701 FIXME("%p, %p.\n", iface, state);
703 return E_NOTIMPL;
706 static HRESULT WINAPI media_player_CreateMediaItemFromURL(IMFPMediaPlayer *iface,
707 const WCHAR *url, BOOL sync, DWORD_PTR user_data, IMFPMediaItem **ret)
709 struct media_player *player = impl_from_IMFPMediaPlayer(iface);
710 struct media_item *item;
711 MF_OBJECT_TYPE obj_type;
712 IUnknown *object;
713 HRESULT hr;
715 TRACE("%p, %s, %d, %lx, %p.\n", iface, debugstr_w(url), sync, user_data, ret);
717 if (FAILED(hr = create_media_item(iface, user_data, &item)))
718 return hr;
720 if (sync)
722 *ret = NULL;
724 if (SUCCEEDED(hr = IMFSourceResolver_CreateObjectFromURL(player->resolver, url, MF_RESOLUTION_MEDIASOURCE,
725 player->propstore, &obj_type, &object)))
727 hr = media_item_set_source(item, object);
728 IUnknown_Release(object);
731 if (SUCCEEDED(hr))
732 *ret = &item->IMFPMediaItem_iface;
734 return hr;
736 else
738 hr = IMFSourceResolver_BeginCreateObjectFromURL(player->resolver, url, MF_RESOLUTION_MEDIASOURCE,
739 player->propstore, NULL, &player->resolver_callback, (IUnknown *)&item->IMFPMediaItem_iface);
741 IMFPMediaItem_Release(&item->IMFPMediaItem_iface);
744 return hr;
747 static HRESULT WINAPI media_player_CreateMediaItemFromObject(IMFPMediaPlayer *iface,
748 IUnknown *object, BOOL sync, DWORD_PTR user_data, IMFPMediaItem **item)
750 FIXME("%p, %p, %d, %lx, %p.\n", iface, object, sync, user_data, item);
752 return E_NOTIMPL;
755 static HRESULT WINAPI media_player_SetMediaItem(IMFPMediaPlayer *iface, IMFPMediaItem *item)
757 FIXME("%p, %p.\n", iface, item);
759 return E_NOTIMPL;
762 static HRESULT WINAPI media_player_ClearMediaItem(IMFPMediaPlayer *iface)
764 FIXME("%p.\n", iface);
766 return E_NOTIMPL;
769 static HRESULT WINAPI media_player_GetMediaItem(IMFPMediaPlayer *iface, IMFPMediaItem **item)
771 FIXME("%p, %p.\n", iface, item);
773 return E_NOTIMPL;
776 static HRESULT WINAPI media_player_GetVolume(IMFPMediaPlayer *iface, float *volume)
778 FIXME("%p, %p.\n", iface, volume);
780 return E_NOTIMPL;
783 static HRESULT WINAPI media_player_SetVolume(IMFPMediaPlayer *iface, float volume)
785 FIXME("%p, %.8e.\n", iface, volume);
787 return E_NOTIMPL;
790 static HRESULT WINAPI media_player_GetBalance(IMFPMediaPlayer *iface, float *balance)
792 FIXME("%p, %p.\n", iface, balance);
794 return E_NOTIMPL;
797 static HRESULT WINAPI media_player_SetBalance(IMFPMediaPlayer *iface, float balance)
799 FIXME("%p, %.8e.\n", iface, balance);
801 return E_NOTIMPL;
804 static HRESULT WINAPI media_player_GetMute(IMFPMediaPlayer *iface, BOOL *mute)
806 FIXME("%p, %p.\n", iface, mute);
808 return E_NOTIMPL;
811 static HRESULT WINAPI media_player_SetMute(IMFPMediaPlayer *iface, BOOL mute)
813 FIXME("%p, %d.\n", iface, mute);
815 return E_NOTIMPL;
818 static HRESULT WINAPI media_player_GetNativeVideoSize(IMFPMediaPlayer *iface,
819 SIZE *video, SIZE *arvideo)
821 FIXME("%p, %p, %p.\n", iface, video, arvideo);
823 return E_NOTIMPL;
826 static HRESULT WINAPI media_player_GetIdealVideoSize(IMFPMediaPlayer *iface,
827 SIZE *min_size, SIZE *max_size)
829 FIXME("%p, %p, %p.\n", iface, min_size, max_size);
831 return E_NOTIMPL;
834 static HRESULT WINAPI media_player_SetVideoSourceRect(IMFPMediaPlayer *iface,
835 MFVideoNormalizedRect const *rect)
837 FIXME("%p, %p.\n", iface, rect);
839 return E_NOTIMPL;
842 static HRESULT WINAPI media_player_GetVideoSourceRect(IMFPMediaPlayer *iface,
843 MFVideoNormalizedRect *rect)
845 FIXME("%p, %p.\n", iface, rect);
847 return E_NOTIMPL;
850 static HRESULT WINAPI media_player_SetAspectRatioMode(IMFPMediaPlayer *iface, DWORD mode)
852 FIXME("%p, %u.\n", iface, mode);
854 return E_NOTIMPL;
857 static HRESULT WINAPI media_player_GetAspectRatioMode(IMFPMediaPlayer *iface,
858 DWORD *mode)
860 FIXME("%p, %p.\n", iface, mode);
862 return E_NOTIMPL;
865 static HRESULT WINAPI media_player_GetVideoWindow(IMFPMediaPlayer *iface, HWND *hwnd)
867 FIXME("%p, %p.\n", iface, hwnd);
869 return E_NOTIMPL;
872 static HRESULT WINAPI media_player_UpdateVideo(IMFPMediaPlayer *iface)
874 FIXME("%p.\n", iface);
876 return E_NOTIMPL;
879 static HRESULT WINAPI media_player_SetBorderColor(IMFPMediaPlayer *iface, COLORREF color)
881 FIXME("%p, %#x.\n", iface, color);
883 return E_NOTIMPL;
886 static HRESULT WINAPI media_player_GetBorderColor(IMFPMediaPlayer *iface, COLORREF *color)
888 FIXME("%p, %p.\n", iface, color);
890 return E_NOTIMPL;
893 static HRESULT WINAPI media_player_InsertEffect(IMFPMediaPlayer *iface, IUnknown *effect,
894 BOOL optional)
896 FIXME("%p, %p, %d.\n", iface, effect, optional);
898 return E_NOTIMPL;
901 static HRESULT WINAPI media_player_RemoveEffect(IMFPMediaPlayer *iface, IUnknown *effect)
903 FIXME("%p, %p.\n", iface, effect);
905 return E_NOTIMPL;
908 static HRESULT WINAPI media_player_RemoveAllEffects(IMFPMediaPlayer *iface)
910 FIXME("%p.\n", iface);
912 return E_NOTIMPL;
915 static HRESULT WINAPI media_player_Shutdown(IMFPMediaPlayer *iface)
917 FIXME("%p.\n", iface);
919 return E_NOTIMPL;
922 static const IMFPMediaPlayerVtbl media_player_vtbl =
924 media_player_QueryInterface,
925 media_player_AddRef,
926 media_player_Release,
927 media_player_Play,
928 media_player_Pause,
929 media_player_Stop,
930 media_player_FrameStep,
931 media_player_SetPosition,
932 media_player_GetPosition,
933 media_player_GetDuration,
934 media_player_SetRate,
935 media_player_GetRate,
936 media_player_GetSupportedRates,
937 media_player_GetState,
938 media_player_CreateMediaItemFromURL,
939 media_player_CreateMediaItemFromObject,
940 media_player_SetMediaItem,
941 media_player_ClearMediaItem,
942 media_player_GetMediaItem,
943 media_player_GetVolume,
944 media_player_SetVolume,
945 media_player_GetBalance,
946 media_player_SetBalance,
947 media_player_GetMute,
948 media_player_SetMute,
949 media_player_GetNativeVideoSize,
950 media_player_GetIdealVideoSize,
951 media_player_SetVideoSourceRect,
952 media_player_GetVideoSourceRect,
953 media_player_SetAspectRatioMode,
954 media_player_GetAspectRatioMode,
955 media_player_GetVideoWindow,
956 media_player_UpdateVideo,
957 media_player_SetBorderColor,
958 media_player_GetBorderColor,
959 media_player_InsertEffect,
960 media_player_RemoveEffect,
961 media_player_RemoveAllEffects,
962 media_player_Shutdown,
965 static HRESULT WINAPI media_player_propstore_QueryInterface(IPropertyStore *iface,
966 REFIID riid, void **obj)
968 struct media_player *player = impl_from_IPropertyStore(iface);
969 return IMFPMediaPlayer_QueryInterface(&player->IMFPMediaPlayer_iface, riid, obj);
972 static ULONG WINAPI media_player_propstore_AddRef(IPropertyStore *iface)
974 struct media_player *player = impl_from_IPropertyStore(iface);
975 return IMFPMediaPlayer_AddRef(&player->IMFPMediaPlayer_iface);
978 static ULONG WINAPI media_player_propstore_Release(IPropertyStore *iface)
980 struct media_player *player = impl_from_IPropertyStore(iface);
981 return IMFPMediaPlayer_Release(&player->IMFPMediaPlayer_iface);
984 static HRESULT WINAPI media_player_propstore_GetCount(IPropertyStore *iface, DWORD *count)
986 struct media_player *player = impl_from_IPropertyStore(iface);
988 TRACE("%p, %p.\n", iface, count);
990 return IPropertyStore_GetCount(player->propstore, count);
993 static HRESULT WINAPI media_player_propstore_GetAt(IPropertyStore *iface, DWORD prop, PROPERTYKEY *key)
995 struct media_player *player = impl_from_IPropertyStore(iface);
997 TRACE("%p, %u, %p.\n", iface, prop, key);
999 return IPropertyStore_GetAt(player->propstore, prop, key);
1002 static HRESULT WINAPI media_player_propstore_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value)
1004 struct media_player *player = impl_from_IPropertyStore(iface);
1006 TRACE("%p, %p, %p.\n", iface, key, value);
1008 return IPropertyStore_GetValue(player->propstore, key, value);
1011 static HRESULT WINAPI media_player_propstore_SetValue(IPropertyStore *iface, REFPROPERTYKEY key, REFPROPVARIANT value)
1013 struct media_player *player = impl_from_IPropertyStore(iface);
1015 TRACE("%p, %p, %p.\n", iface, key, value);
1017 return IPropertyStore_SetValue(player->propstore, key, value);
1020 static HRESULT WINAPI media_player_propstore_Commit(IPropertyStore *iface)
1022 struct media_player *player = impl_from_IPropertyStore(iface);
1024 TRACE("%p.\n", iface);
1026 return IPropertyStore_Commit(player->propstore);
1029 static const IPropertyStoreVtbl media_player_propstore_vtbl =
1031 media_player_propstore_QueryInterface,
1032 media_player_propstore_AddRef,
1033 media_player_propstore_Release,
1034 media_player_propstore_GetCount,
1035 media_player_propstore_GetAt,
1036 media_player_propstore_GetValue,
1037 media_player_propstore_SetValue,
1038 media_player_propstore_Commit,
1041 static HRESULT WINAPI media_player_callback_QueryInterface(IMFAsyncCallback *iface,
1042 REFIID riid, void **obj)
1044 if (IsEqualIID(riid, &IID_IMFAsyncCallback) ||
1045 IsEqualIID(riid, &IID_IUnknown))
1047 *obj = iface;
1048 IMFAsyncCallback_AddRef(iface);
1049 return S_OK;
1052 *obj = NULL;
1053 return E_NOINTERFACE;
1056 static ULONG WINAPI media_player_resolver_callback_AddRef(IMFAsyncCallback *iface)
1058 struct media_player *player = impl_from_resolver_IMFAsyncCallback(iface);
1059 return IMFPMediaPlayer_AddRef(&player->IMFPMediaPlayer_iface);
1062 static ULONG WINAPI media_player_resolver_callback_Release(IMFAsyncCallback *iface)
1064 struct media_player *player = impl_from_resolver_IMFAsyncCallback(iface);
1065 return IMFPMediaPlayer_Release(&player->IMFPMediaPlayer_iface);
1068 static HRESULT WINAPI media_player_callback_GetParameters(IMFAsyncCallback *iface, DWORD *flags,
1069 DWORD *queue)
1071 return E_NOTIMPL;
1074 static HRESULT WINAPI media_player_resolver_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
1076 struct media_player *player = impl_from_resolver_IMFAsyncCallback(iface);
1077 struct media_event *event;
1078 IUnknown *object, *state;
1079 MF_OBJECT_TYPE obj_type;
1080 struct media_item *item;
1081 HRESULT hr;
1083 if (FAILED(IMFAsyncResult_GetState(result, &state)))
1084 return S_OK;
1086 item = impl_from_IMFPMediaItem((IMFPMediaItem *)state);
1088 if (SUCCEEDED(hr = IMFSourceResolver_EndCreateObjectFromURL(player->resolver, result, &obj_type, &object)))
1090 hr = media_item_set_source(item, object);
1091 IUnknown_Release(object);
1094 if (FAILED(hr))
1095 WARN("Failed to set media source, hr %#x.\n", hr);
1097 if (FAILED(media_event_create(MFP_EVENT_TYPE_MEDIAITEM_CREATED, hr, &player->IMFPMediaPlayer_iface, &event)))
1099 WARN("Failed to create event object.\n");
1100 IUnknown_Release(state);
1101 return S_OK;
1104 if (SUCCEEDED(hr))
1106 event->u.item_created.pMediaItem = &item->IMFPMediaItem_iface;
1107 IMFPMediaItem_AddRef(event->u.item_created.pMediaItem);
1109 event->u.item_created.dwUserData = item->user_data;
1111 media_player_queue_event(player, event);
1113 IUnknown_Release(&event->IUnknown_iface);
1114 IUnknown_Release(state);
1116 return S_OK;
1119 static const IMFAsyncCallbackVtbl media_player_resolver_callback_vtbl =
1121 media_player_callback_QueryInterface,
1122 media_player_resolver_callback_AddRef,
1123 media_player_resolver_callback_Release,
1124 media_player_callback_GetParameters,
1125 media_player_resolver_callback_Invoke,
1128 static ULONG WINAPI media_player_events_callback_AddRef(IMFAsyncCallback *iface)
1130 struct media_player *player = impl_from_events_IMFAsyncCallback(iface);
1131 return IMFPMediaPlayer_AddRef(&player->IMFPMediaPlayer_iface);
1134 static ULONG WINAPI media_player_events_callback_Release(IMFAsyncCallback *iface)
1136 struct media_player *player = impl_from_events_IMFAsyncCallback(iface);
1137 return IMFPMediaPlayer_Release(&player->IMFPMediaPlayer_iface);
1140 static HRESULT WINAPI media_player_events_callback_Invoke(IMFAsyncCallback *iface, IMFAsyncResult *result)
1142 struct media_player *player = impl_from_events_IMFAsyncCallback(iface);
1143 struct media_event *event;
1144 IUnknown *state;
1146 if (FAILED(IMFAsyncResult_GetState(result, &state)))
1147 return S_OK;
1149 event = impl_event_from_IUnknown(state);
1151 if (player->callback)
1152 IMFPMediaPlayerCallback_OnMediaPlayerEvent(player->callback, &event->u.header);
1154 IUnknown_Release(state);
1156 return S_OK;
1159 static const IMFAsyncCallbackVtbl media_player_events_callback_vtbl =
1161 media_player_callback_QueryInterface,
1162 media_player_events_callback_AddRef,
1163 media_player_events_callback_Release,
1164 media_player_callback_GetParameters,
1165 media_player_events_callback_Invoke,
1168 HRESULT WINAPI MFPCreateMediaPlayer(const WCHAR *url, BOOL start_playback, MFP_CREATION_OPTIONS options,
1169 IMFPMediaPlayerCallback *callback, HWND hwnd, IMFPMediaPlayer **player)
1171 struct media_player *object;
1172 HRESULT hr;
1174 TRACE("%s, %d, %#x, %p, %p, %p.\n", debugstr_w(url), start_playback, options, callback, hwnd, player);
1176 if (!(object = heap_alloc_zero(sizeof(*object))))
1177 return E_OUTOFMEMORY;
1179 platform_startup();
1181 object->IMFPMediaPlayer_iface.lpVtbl = &media_player_vtbl;
1182 object->IPropertyStore_iface.lpVtbl = &media_player_propstore_vtbl;
1183 object->resolver_callback.lpVtbl = &media_player_resolver_callback_vtbl;
1184 object->events_callback.lpVtbl = &media_player_events_callback_vtbl;
1185 object->refcount = 1;
1186 object->callback = callback;
1187 object->options = options;
1188 if (object->callback)
1189 IMFPMediaPlayerCallback_AddRef(object->callback);
1190 if (FAILED(hr = CreatePropertyStore(&object->propstore)))
1191 goto failed;
1192 if (FAILED(hr = MFCreateSourceResolver(&object->resolver)))
1193 goto failed;
1194 if (!(object->options & MFP_OPTION_FREE_THREADED_CALLBACK))
1196 object->event_window = CreateWindowW(eventclassW, NULL, 0, 0, 0, 0, 0, HWND_MESSAGE,
1197 0, mfplay_instance, NULL);
1200 *player = &object->IMFPMediaPlayer_iface;
1202 return S_OK;
1204 failed:
1206 IMFPMediaPlayer_Release(&object->IMFPMediaPlayer_iface);
1208 return hr;
1211 static void media_player_register_window_class(void)
1213 WNDCLASSW cls = { 0 };
1215 cls.lpfnWndProc = media_player_event_proc;
1216 cls.hInstance = mfplay_instance;
1217 cls.lpszClassName = eventclassW;
1219 RegisterClassW(&cls);
1222 BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved)
1224 switch (reason)
1226 case DLL_PROCESS_ATTACH:
1227 mfplay_instance = instance;
1228 DisableThreadLibraryCalls(instance);
1229 media_player_register_window_class();
1230 break;
1231 case DLL_PROCESS_DETACH:
1232 if (reserved) break;
1233 UnregisterClassW(eventclassW, instance);
1234 break;
1237 return TRUE;