Commit 7a678903 authored by Rémi Bernon's avatar Rémi Bernon Committed by Alexandre Julliard

dmime: Implement IDirectMusicPerformance_GetNotificationPMsg.

parent 3de1bc03
......@@ -52,8 +52,6 @@ struct performance
BOOL audio_paths_enabled;
IDirectMusicAudioPath *pDefaultPath;
HANDLE hNotification;
REFERENCE_TIME rtMinimum;
REFERENCE_TIME rtLatencyTime;
DWORD dwBumperLength;
DWORD dwPrepareTime;
......@@ -67,6 +65,9 @@ struct performance
REFERENCE_TIME init_time;
struct list messages;
struct list notifications;
REFERENCE_TIME notification_timeout;
HANDLE notification_event;
BOOL notification_performance;
BOOL notification_segment;
};
......@@ -702,62 +703,84 @@ static HRESULT WINAPI performance_SetGraph(IDirectMusicPerformance8 *iface, IDir
}
static HRESULT WINAPI performance_SetNotificationHandle(IDirectMusicPerformance8 *iface,
HANDLE hNotification, REFERENCE_TIME rtMinimum)
HANDLE notification_event, REFERENCE_TIME minimum_time)
{
struct performance *This = impl_from_IDirectMusicPerformance8(iface);
TRACE("(%p, %p, 0x%s)\n", This, hNotification, wine_dbgstr_longlong(rtMinimum));
TRACE("(%p, %p, %I64d)\n", This, notification_event, minimum_time);
This->notification_event = notification_event;
if (minimum_time)
This->notification_timeout = minimum_time;
else if (!This->notification_timeout)
This->notification_timeout = 20000000; /* 2 seconds */
This->hNotification = hNotification;
if (rtMinimum)
This->rtMinimum = rtMinimum;
else if (!This->rtMinimum)
This->rtMinimum = 20000000; /* 2 seconds */
return S_OK;
}
static HRESULT WINAPI performance_GetNotificationPMsg(IDirectMusicPerformance8 *iface,
DMUS_NOTIFICATION_PMSG **ppNotificationPMsg)
DMUS_NOTIFICATION_PMSG **ret_msg)
{
struct performance *This = impl_from_IDirectMusicPerformance8(iface);
struct performance *This = impl_from_IDirectMusicPerformance8(iface);
struct list *entry;
FIXME("(%p, %p): stub\n", This, ppNotificationPMsg);
if (NULL == ppNotificationPMsg) {
return E_POINTER;
}
TRACE("(%p, %p)\n", This, ret_msg);
if (!ret_msg) return E_POINTER;
return S_FALSE;
/*return S_OK;*/
EnterCriticalSection(&This->safe);
if ((entry = list_head(&This->notifications)))
{
struct message *message = LIST_ENTRY(entry, struct message, entry);
list_remove(&message->entry);
list_init(&message->entry);
*ret_msg = (DMUS_NOTIFICATION_PMSG *)&message->msg;
}
LeaveCriticalSection(&This->safe);
return entry ? S_OK : S_FALSE;
}
static HRESULT WINAPI performance_AddNotificationType(IDirectMusicPerformance8 *iface, REFGUID type)
{
struct performance *This = impl_from_IDirectMusicPerformance8(iface);
HRESULT hr = S_OK;
FIXME("(%p, %s): stub\n", This, debugstr_dmguid(type));
if (IsEqualGUID(type, &GUID_NOTIFICATION_PERFORMANCE))
{
hr = This->notification_performance ? S_FALSE : S_OK;
This->notification_performance = TRUE;
}
if (IsEqualGUID(type, &GUID_NOTIFICATION_SEGMENT))
{
hr = This->notification_segment ? S_FALSE : S_OK;
This->notification_segment = TRUE;
}
return S_OK;
return hr;
}
static HRESULT WINAPI performance_RemoveNotificationType(IDirectMusicPerformance8 *iface, REFGUID type)
{
struct performance *This = impl_from_IDirectMusicPerformance8(iface);
HRESULT hr = S_FALSE;
FIXME("(%p, %s): stub\n", This, debugstr_dmguid(type));
if (IsEqualGUID(type, &GUID_NOTIFICATION_PERFORMANCE))
{
hr = This->notification_performance ? S_OK : S_FALSE;
This->notification_performance = FALSE;
}
if (IsEqualGUID(type, &GUID_NOTIFICATION_SEGMENT))
{
hr = This->notification_segment ? S_OK : S_FALSE;
This->notification_segment = FALSE;
}
return S_OK;
return hr;
}
static HRESULT perf_dmport_create(struct performance *perf, DMUS_PORTPARAMS *params)
......@@ -1021,6 +1044,9 @@ static HRESULT WINAPI performance_CloseDown(IDirectMusicPerformance8 *iface)
CloseHandle(This->procThread);
}
This->notification_performance = FALSE;
This->notification_segment = FALSE;
LIST_FOR_EACH_ENTRY_SAFE(message, next, &This->messages, struct message, entry)
{
list_remove(&message->entry);
......@@ -1030,6 +1056,15 @@ static HRESULT WINAPI performance_CloseDown(IDirectMusicPerformance8 *iface)
WARN("Failed to free message %p, hr %#lx\n", message, hr);
}
LIST_FOR_EACH_ENTRY_SAFE(message, next, &This->notifications, struct message, entry)
{
list_remove(&message->entry);
list_init(&message->entry);
if (FAILED(hr = IDirectMusicPerformance8_FreePMsg(iface, &message->msg)))
WARN("Failed to free message %p, hr %#lx\n", message, hr);
}
if (This->master_clock)
{
IReferenceClock_Release(This->master_clock);
......@@ -1586,14 +1621,40 @@ static HRESULT WINAPI performance_tool_ProcessPMsg(IDirectMusicTool *iface,
IDirectMusicPerformance *performance, DMUS_PMSG *msg)
{
struct performance *This = impl_from_IDirectMusicTool(iface);
struct message *message = message_from_DMUS_PMSG(msg);
FIXME("(%p, %p, %p): semi-stub\n", This, performance, msg);
switch (msg->dwType)
{
case DMUS_PMSGT_NOTIFICATION:
SetEvent(This->hNotification);
/* fallthrough */
{
DMUS_NOTIFICATION_PMSG *notif = (DMUS_NOTIFICATION_PMSG *)msg;
struct message *previous;
BOOL enabled = FALSE;
HRESULT hr;
if (IsEqualGUID(&notif->guidNotificationType, &GUID_NOTIFICATION_PERFORMANCE))
enabled = This->notification_performance;
if (IsEqualGUID(&notif->guidNotificationType, &GUID_NOTIFICATION_SEGMENT))
enabled = This->notification_segment;
if (!enabled) return DMUS_S_FREE;
list_add_tail(&This->notifications, &message->entry);
/* discard old notification messages */
do
{
previous = LIST_ENTRY(list_head(&This->notifications), struct message, entry);
if (message->msg.rtTime - previous->msg.rtTime <= This->notification_timeout) break;
list_remove(&previous->entry);
list_init(&previous->entry);
} while (SUCCEEDED(hr = IDirectMusicPerformance_FreePMsg(performance, &previous->msg)));
SetEvent(This->notification_event);
return S_OK;
}
default:
FIXME("Unhandled message type %#lx\n", msg->dwType);
break;
......@@ -1644,6 +1705,7 @@ HRESULT create_dmperformance(REFIID iid, void **ret_iface)
wine_rb_init(&obj->pchannels, pchannel_block_compare);
list_init(&obj->messages);
list_init(&obj->notifications);
obj->rtLatencyTime = 100; /* 100 ms TO FIX */
obj->dwBumperLength = 50; /* 50 ms default */
......
......@@ -3102,7 +3102,7 @@ static void test_notification_pmsg(void)
hr = IDirectMusicPerformance_AddNotificationType(performance, &GUID_NOTIFICATION_SEGMENT);
ok(hr == S_OK, "got %#lx\n", hr);
hr = IDirectMusicPerformance_AddNotificationType(performance, &GUID_NOTIFICATION_SEGMENT);
todo_wine ok(hr == S_FALSE, "got %#lx\n", hr);
ok(hr == S_FALSE, "got %#lx\n", hr);
hr = IDirectMusicPerformance_PlaySegment(performance, segment, 0, 0, NULL);
ok(hr == S_OK, "got %#lx\n", hr);
......@@ -3162,49 +3162,34 @@ static void test_notification_pmsg(void)
/* notification messages are also queued for direct access */
hr = IDirectMusicPerformance_GetNotificationPMsg(performance, &notif);
todo_wine ok(hr == S_OK, "got %#lx\n", hr);
if (hr == S_OK)
{
ok(hr == S_OK, "got %#lx\n", hr);
check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_PERFORMANCE, DMUS_NOTIFICATION_MUSICSTARTED);
hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
ok(hr == S_OK, "got %#lx\n", hr);
}
hr = IDirectMusicPerformance_GetNotificationPMsg(performance, &notif);
todo_wine ok(hr == S_OK, "got %#lx\n", hr);
if (hr == S_OK)
{
ok(hr == S_OK, "got %#lx\n", hr);
check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGSTART);
hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
ok(hr == S_OK, "got %#lx\n", hr);
}
hr = IDirectMusicPerformance_GetNotificationPMsg(performance, &notif);
todo_wine ok(hr == S_OK, "got %#lx\n", hr);
if (hr == S_OK)
{
ok(hr == S_OK, "got %#lx\n", hr);
check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGEND);
hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
ok(hr == S_OK, "got %#lx\n", hr);
}
hr = IDirectMusicPerformance_GetNotificationPMsg(performance, &notif);
todo_wine ok(hr == S_OK, "got %#lx\n", hr);
if (hr == S_OK)
{
ok(hr == S_OK, "got %#lx\n", hr);
check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGALMOSTEND);
hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
ok(hr == S_OK, "got %#lx\n", hr);
}
hr = IDirectMusicPerformance_GetNotificationPMsg(performance, &notif);
todo_wine ok(hr == S_OK, "got %#lx\n", hr);
if (hr == S_OK)
{
ok(hr == S_OK, "got %#lx\n", hr);
check_dmus_notification_pmsg(notif, &GUID_NOTIFICATION_PERFORMANCE, DMUS_NOTIFICATION_MUSICSTOPPED);
hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif);
ok(hr == S_OK, "got %#lx\n", hr);
}
hr = IDirectMusicPerformance_GetNotificationPMsg(performance, &notif);
ok(hr == S_FALSE, "got %#lx\n", hr);
......@@ -3213,7 +3198,7 @@ static void test_notification_pmsg(void)
/* RemoveNotificationType returns S_FALSE if already removed */
hr = IDirectMusicPerformance_RemoveNotificationType(performance, &GUID_NOTIFICATION_PERFORMANCE);
todo_wine ok(hr == S_FALSE, "got %#lx\n", hr);
ok(hr == S_FALSE, "got %#lx\n", hr);
/* CloseDown removes all notifications and notification messages */
......@@ -3232,7 +3217,7 @@ static void test_notification_pmsg(void)
hr = IDirectMusicPerformance_CloseDown(performance);
ok(hr == S_OK, "got %#lx\n", hr);
hr = IDirectMusicPerformance_RemoveNotificationType(performance, &GUID_NOTIFICATION_SEGMENT);
todo_wine ok(hr == S_FALSE, "got %#lx\n", hr);
ok(hr == S_FALSE, "got %#lx\n", hr);
IDirectMusicSegment_Release(segment);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment