[PATCH 3/7] mfplay: Rework session event handler.
Nikolay Sivov
nsivov at codeweavers.com
Tue Apr 13 01:03:30 CDT 2021
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/mfplay/player.c | 181 ++++++++++++++++++++++++++++++++-----------
1 file changed, 137 insertions(+), 44 deletions(-)
diff --git a/dlls/mfplay/player.c b/dlls/mfplay/player.c
index 2f868ce3b61..146c50fc755 100644
--- a/dlls/mfplay/player.c
+++ b/dlls/mfplay/player.c
@@ -75,6 +75,7 @@ struct media_player
IPropertyStore *propstore;
IMFSourceResolver *resolver;
IMFMediaSession *session;
+ IMFPMediaItem *item;
MFP_CREATION_OPTIONS options;
MFP_MEDIAPLAYER_STATE state;
HWND event_window;
@@ -224,7 +225,7 @@ static const IUnknownVtbl media_event_vtbl =
};
static HRESULT media_event_create(struct media_player *player, MFP_EVENT_TYPE event_type,
- HRESULT hr, struct media_event **event)
+ HRESULT hr, IMFPMediaItem *item, struct media_event **event)
{
struct media_event *object;
@@ -238,6 +239,31 @@ static HRESULT media_event_create(struct media_player *player, MFP_EVENT_TYPE ev
object->u.header.pMediaPlayer = &player->IMFPMediaPlayer_iface;
IMFPMediaPlayer_AddRef(object->u.header.pMediaPlayer);
object->u.header.eState = player->state;
+ switch (event_type)
+ {
+ case MFP_EVENT_TYPE_PLAY:
+ case MFP_EVENT_TYPE_PAUSE:
+ case MFP_EVENT_TYPE_STOP:
+ case MFP_EVENT_TYPE_POSITION_SET:
+ case MFP_EVENT_TYPE_RATE_SET:
+ case MFP_EVENT_TYPE_MEDIAITEM_CREATED:
+ case MFP_EVENT_TYPE_MEDIAITEM_SET:
+ case MFP_EVENT_TYPE_FRAME_STEP:
+ case MFP_EVENT_TYPE_MEDIAITEM_CLEARED:
+ case MFP_EVENT_TYPE_PLAYBACK_ENDED:
+ object->u.generic.item = item;
+ if (object->u.generic.item)
+ IMFPMediaItem_AddRef(object->u.generic.item);
+ break;
+ case MFP_EVENT_TYPE_MF:
+ object->u.event.pMediaItem = item;
+ if (object->u.event.pMediaItem)
+ IMFPMediaItem_AddRef(object->u.event.pMediaItem);
+ break;
+ default:
+ ;
+ }
+
/* FIXME: set properties for some events? */
*event = object;
@@ -939,16 +965,34 @@ static HRESULT WINAPI media_player_SetMediaItem(IMFPMediaPlayer *iface, IMFPMedi
static HRESULT WINAPI media_player_ClearMediaItem(IMFPMediaPlayer *iface)
{
- FIXME("%p.\n", iface);
+ struct media_player *player = impl_from_IMFPMediaPlayer(iface);
- return E_NOTIMPL;
+ TRACE("%p.\n", iface);
+
+ return IMFMediaSession_SetTopology(player->session, MFSESSION_SETTOPOLOGY_CLEAR_CURRENT, NULL);
}
static HRESULT WINAPI media_player_GetMediaItem(IMFPMediaPlayer *iface, IMFPMediaItem **item)
{
- FIXME("%p, %p.\n", iface, item);
+ struct media_player *player = impl_from_IMFPMediaPlayer(iface);
+ HRESULT hr = S_OK;
- return E_NOTIMPL;
+ TRACE("%p, %p.\n", iface, item);
+
+ if (!item)
+ return E_POINTER;
+
+ EnterCriticalSection(&player->cs);
+ if (!player->item)
+ hr = MF_E_NOT_FOUND;
+ else
+ {
+ *item = player->item;
+ IMFPMediaItem_AddRef(player->item);
+ }
+ LeaveCriticalSection(&player->cs);
+
+ return hr;
}
static HRESULT WINAPI media_player_GetVolume(IMFPMediaPlayer *iface, float *volume)
@@ -1102,6 +1146,11 @@ static HRESULT WINAPI media_player_Shutdown(IMFPMediaPlayer *iface)
EnterCriticalSection(&player->cs);
media_player_set_state(player, MFP_MEDIAPLAYER_STATE_SHUTDOWN);
+ if (player->item)
+ {
+ IMFPMediaItem_Release(player->item);
+ player->item = NULL;
+ }
LeaveCriticalSection(&player->cs);
return S_OK;
@@ -1282,18 +1331,13 @@ static HRESULT WINAPI media_player_resolver_callback_Invoke(IMFAsyncCallback *if
if (FAILED(hr))
WARN("Failed to set media source, hr %#x.\n", hr);
- if (FAILED(media_event_create(player, MFP_EVENT_TYPE_MEDIAITEM_CREATED, hr, &event)))
+ if (FAILED(media_event_create(player, MFP_EVENT_TYPE_MEDIAITEM_CREATED, hr,
+ &item->IMFPMediaItem_iface, &event)))
{
WARN("Failed to create event object.\n");
IUnknown_Release(state);
return S_OK;
}
-
- if (SUCCEEDED(hr))
- {
- event->u.item_created.pMediaItem = &item->IMFPMediaItem_iface;
- IMFPMediaItem_AddRef(event->u.item_created.pMediaItem);
- }
event->u.item_created.dwUserData = item->user_data;
media_player_queue_event(player, event);
@@ -1365,6 +1409,63 @@ static ULONG WINAPI media_player_session_events_callback_Release(IMFAsyncCallbac
return IMFPMediaPlayer_Release(&player->IMFPMediaPlayer_iface);
}
+static void media_player_change_state(struct media_player *player, MFP_MEDIAPLAYER_STATE state,
+ HRESULT event_status, struct media_event **event)
+{
+ MFP_EVENT_TYPE event_type;
+
+ EnterCriticalSection(&player->cs);
+
+ if (state == MFP_MEDIAPLAYER_STATE_PLAYING)
+ event_type = MFP_EVENT_TYPE_PLAY;
+ else if (state == MFP_MEDIAPLAYER_STATE_PAUSED)
+ event_type = MFP_EVENT_TYPE_PAUSE;
+ else
+ event_type = MFP_EVENT_TYPE_STOP;
+
+ media_player_set_state(player, state);
+ media_event_create(player, event_type, event_status, player->item, event);
+
+ LeaveCriticalSection(&player->cs);
+}
+
+static void media_player_set_item(struct media_player *player, IMFTopology *topology, HRESULT event_status,
+ struct media_event **event)
+{
+ IMFPMediaItem *item;
+
+ if (FAILED(IMFTopology_GetUnknown(topology, &_MF_TOPO_MEDIA_ITEM, &IID_IMFPMediaItem, (void **)&item)))
+ return;
+
+ EnterCriticalSection(&player->cs);
+
+ if (player->item)
+ IMFPMediaItem_Release(player->item);
+ player->item = item;
+ IMFPMediaItem_AddRef(player->item);
+
+ media_event_create(player, MFP_EVENT_TYPE_MEDIAITEM_SET, event_status, item, event);
+
+ LeaveCriticalSection(&player->cs);
+
+ IMFPMediaItem_Release(item);
+}
+
+static void media_player_clear_item(struct media_player *player, HRESULT event_status,
+ struct media_event **event)
+{
+ IMFPMediaItem *item;
+
+ EnterCriticalSection(&player->cs);
+
+ item = player->item;
+ player->item = NULL;
+
+ media_event_create(player, MFP_EVENT_TYPE_MEDIAITEM_SET, event_status, item, event);
+
+ LeaveCriticalSection(&player->cs);
+}
+
static HRESULT WINAPI media_player_session_events_callback_Invoke(IMFAsyncCallback *iface,
IMFAsyncResult *result)
{
@@ -1373,10 +1474,10 @@ static HRESULT WINAPI media_player_session_events_callback_Invoke(IMFAsyncCallba
struct media_event *event = NULL;
IMFMediaEvent *session_event;
MFP_MEDIAPLAYER_STATE state;
- MFP_EVENT_TYPE event_type;
HRESULT hr, event_status;
IMFPMediaItem *item = NULL;
IMFTopology *topology;
+ PROPVARIANT value;
if (FAILED(hr = IMFMediaSession_EndGetEvent(player->session, result, &session_event)))
return S_OK;
@@ -1384,51 +1485,40 @@ static HRESULT WINAPI media_player_session_events_callback_Invoke(IMFAsyncCallba
IMFMediaEvent_GetType(session_event, &session_event_type);
IMFMediaEvent_GetStatus(session_event, &event_status);
- if (SUCCEEDED(IMFMediaSession_GetFullTopology(player->session, MFSESSION_GETFULLTOPOLOGY_CURRENT, 0, &topology)))
- {
- IMFTopology_GetUnknown(topology, &_MF_TOPO_MEDIA_ITEM, &IID_IMFPMediaItem, (void **)&item);
- IMFTopology_Release(topology);
- }
-
switch (session_event_type)
{
case MESessionStarted:
case MESessionStopped:
case MESessionPaused:
+
if (session_event_type == MESessionStarted)
- {
- event_type = MFP_EVENT_TYPE_PLAY;
state = MFP_MEDIAPLAYER_STATE_PLAYING;
- }
- else if (session_event_type == MESessionStopped)
- {
- event_type = MFP_EVENT_TYPE_STOP;
- state = MFP_MEDIAPLAYER_STATE_STOPPED;
- }
- else
- {
- event_type = MFP_EVENT_TYPE_PAUSE;
+ else if (session_event_type == MESessionPaused)
state = MFP_MEDIAPLAYER_STATE_PAUSED;
- }
+ else
+ state = MFP_MEDIAPLAYER_STATE_STOPPED;
- EnterCriticalSection(&player->cs);
- media_player_set_state(player, state);
- media_event_create(player, event_type, event_status, &event);
- LeaveCriticalSection(&player->cs);
- event->u.generic.item = item;
- if (event->u.generic.item)
- IMFPMediaItem_AddRef(event->u.generic.item);
- media_player_queue_event(player, event);
+ media_player_change_state(player, state, event_status, &event);
break;
case MESessionTopologySet:
- media_event_create(player, MFP_EVENT_TYPE_MEDIAITEM_SET, event_status, &event);
- event->u.generic.item = item;
- if (event->u.generic.item)
- IMFPMediaItem_AddRef(event->u.generic.item);
- media_player_queue_event(player, event);
+ value.vt = VT_EMPTY;
+ if (SUCCEEDED(IMFMediaEvent_GetValue(session_event, &value)))
+ {
+ if (value.vt == VT_EMPTY)
+ {
+ media_player_clear_item(player, event_status, &event);
+ }
+ else if (value.vt == VT_UNKNOWN && value.punkVal &&
+ SUCCEEDED(IUnknown_QueryInterface(value.punkVal, &IID_IMFTopology, (void **)&topology)))
+ {
+ media_player_set_item(player, topology, event_status, &event);
+ IMFTopology_Release(topology);
+ }
+ PropVariantClear(&value);
+ }
break;
default:
@@ -1439,7 +1529,10 @@ static HRESULT WINAPI media_player_session_events_callback_Invoke(IMFAsyncCallba
IMFPMediaItem_Release(item);
if (event)
+ {
+ media_player_queue_event(player, event);
IUnknown_Release(&event->IUnknown_iface);
+ }
IMFMediaSession_BeginGetEvent(player->session, &player->session_events_callback, NULL);
IMFMediaEvent_Release(session_event);
--
2.30.2
More information about the wine-devel
mailing list