The last change adds a todo_wine for the time offset check, because we don't implement it. It wasn't necessary before becase InitPlay wasn't called yet.
It also adds a todo_wine for the playing state, because we don't implement start_time yet, and the segment start should be delayed instead of starting right away. Same, it wasn't necessary before because we were not calling Play.
We use notification messages to carry segment state and extend its lifetime for the entire play time, even though notifications might not be actually enabled. When notifications aren't enabled, we don't stamp the messages, so they are directly delivered to the performance output tool, and we then won't queue them to the notification message list. I don't think it matters very much, though we could alternatively use some internal message types instead.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/tests/dmime.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/dlls/dmime/tests/dmime.c b/dlls/dmime/tests/dmime.c index 87d938a9015..c892f25c884 100644 --- a/dlls/dmime/tests/dmime.c +++ b/dlls/dmime/tests/dmime.c @@ -3107,6 +3107,8 @@ static void test_notification_pmsg(void) ok(hr == S_OK, "got %#lx\n", hr); 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);
hr = IDirectMusicPerformance_PlaySegment(performance, segment, 0, 0, NULL); ok(hr == S_OK, "got %#lx\n", hr); @@ -3178,8 +3180,6 @@ static void test_notification_pmsg(void) ok(ret == WAIT_TIMEOUT, "got %#lx\n", ret); ok(!msg, "got %p\n", msg);
- IDirectMusicSegment_Release(segment); - hr = IDirectMusicPerformance_RemoveNotificationType(performance, &GUID_NOTIFICATION_PERFORMANCE); ok(hr == S_OK, "got %#lx\n", hr); hr = IDirectMusicPerformance_RemoveNotificationType(performance, &GUID_NOTIFICATION_SEGMENT); @@ -3237,8 +3237,34 @@ static void test_notification_pmsg(void) ok(hr == S_FALSE, "got %#lx\n", hr);
+ /* RemoveNotificationType returns S_FALSE if already removed */ + + hr = IDirectMusicPerformance_RemoveNotificationType(performance, &GUID_NOTIFICATION_PERFORMANCE); + todo_wine ok(hr == S_FALSE, "got %#lx\n", hr); + + + /* CloseDown removes all notifications and notification messages */ + + hr = IDirectMusicPerformance_AddNotificationType(performance, &GUID_NOTIFICATION_SEGMENT); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IDirectMusicPerformance_PlaySegment(performance, segment, 0, 0, NULL); + ok(hr == S_OK, "got %#lx\n", hr); + + ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)¬if); + todo_wine ok(!ret, "got %#lx\n", ret); + if (!ret) + { + 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_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); + IDirectMusicSegment_Release(segment); +
IDirectMusicPerformance_Release(performance); IDirectMusicTool_Release(tool);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/performance.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index 9f293358ca6..a5655f4b2df 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -497,7 +497,7 @@ static HRESULT WINAPI performance_SendPMsg(IDirectMusicPerformance8 *iface, DMUS }
LIST_FOR_EACH_ENTRY(next, &This->messages, struct message, entry) - if (next->msg.rtTime >= message->msg.rtTime) break; + if (next->msg.rtTime > message->msg.rtTime) break; list_add_before(&next->entry, &message->entry); PostThreadMessageW(This->procThreadId, PROCESSMSG_ADD, 0, 0);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/performance.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index a5655f4b2df..5c3e1f17a97 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -948,6 +948,8 @@ static HRESULT WINAPI performance_AdjustTime(IDirectMusicPerformance8 *iface, RE static HRESULT WINAPI performance_CloseDown(IDirectMusicPerformance8 *iface) { struct performance *This = impl_from_IDirectMusicPerformance8(iface); + struct message *message, *next; + HRESULT hr;
FIXME("(%p): semi-stub\n", This);
@@ -956,6 +958,16 @@ static HRESULT WINAPI performance_CloseDown(IDirectMusicPerformance8 *iface) This->procThreadTicStarted = FALSE; CloseHandle(This->procThread); } + + LIST_FOR_EACH_ENTRY_SAFE(message, next, &This->messages, 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);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/performance.c | 37 ++++++++++++++++++++-- dlls/dmime/tests/dmime.c | 67 ++++++++++++++-------------------------- 2 files changed, 58 insertions(+), 46 deletions(-)
diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index 5c3e1f17a97..0215b19a23c 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -204,6 +204,27 @@ static BOOL PostMessageToProcessMsgThread(struct performance *This, UINT iMsg) { return PostThreadMessageA(This->procThreadId, iMsg, 0, 0); }
+static HRESULT performance_send_dirty_pmsg(struct performance *This, MUSIC_TIME music_time) +{ + IDirectMusicPerformance8 *performance = &This->IDirectMusicPerformance8_iface; + IDirectMusicGraph *graph = &This->IDirectMusicGraph_iface; + DMUS_PMSG *msg; + HRESULT hr; + + if (FAILED(hr = IDirectMusicPerformance8_AllocPMsg(performance, sizeof(*msg), &msg))) + return hr; + + msg->mtTime = music_time; + msg->dwFlags = DMUS_PMSGF_MUSICTIME | DMUS_PMSGF_TOOL_QUEUE; + msg->dwType = DMUS_PMSGT_DIRTY; + + if (FAILED(hr = IDirectMusicGraph_StampPMsg(graph, msg)) + || FAILED(hr = IDirectMusicPerformance8_SendPMsg(performance, msg))) + IDirectMusicPerformance8_FreePMsg(performance, msg); + + return hr; +} + static int pchannel_block_compare(const void *key, const struct wine_rb_entry *entry) { const struct pchannel_block *b = WINE_RB_ENTRY_VALUE(entry, const struct pchannel_block, entry); @@ -1082,20 +1103,32 @@ static HRESULT WINAPI performance_PlaySegmentEx(IDirectMusicPerformance8 *iface, struct performance *This = impl_from_IDirectMusicPerformance8(iface); IDirectMusicSegmentState *state; IDirectMusicSegment *segment; + MUSIC_TIME length; HRESULT hr;
FIXME("(%p, %p, %s, %p, %#lx, %I64d, %p, %p, %p): stub\n", This, source, debugstr_w(segment_name), transition, segment_flags, start_time, segment_state, from, audio_path);
+ /* NOTE: The time is in music time unless the DMUS_SEGF_REFTIME flag is set. */ + if (segment_flags) FIXME("flags %#lx not implemented\n", segment_flags); + if (start_time) FIXME("start_time %I64d not implemented\n", start_time); + if (FAILED(hr = IUnknown_QueryInterface(source, &IID_IDirectMusicSegment, (void **)&segment))) return hr; - if (FAILED(hr = segment_state_create((IDirectMusicSegment *)segment, start_time, &state))) + if (FAILED(hr = segment_state_create(segment, start_time, &state))) { IDirectMusicSegment_Release(segment); return hr; }
- if (segment_state) + hr = IDirectMusicSegment_GetLength(segment, &length); + if (SUCCEEDED(hr)) + hr = performance_send_dirty_pmsg(This, start_time); + + if (SUCCEEDED(hr)) + hr = performance_send_dirty_pmsg(This, start_time + length); + + if (SUCCEEDED(hr) && segment_state) { *segment_state = state; IDirectMusicSegmentState_AddRef(state); diff --git a/dlls/dmime/tests/dmime.c b/dlls/dmime/tests/dmime.c index c892f25c884..88e779e75a1 100644 --- a/dlls/dmime/tests/dmime.c +++ b/dlls/dmime/tests/dmime.c @@ -3079,22 +3079,16 @@ static void test_notification_pmsg(void) ok(hr == S_OK, "got %#lx\n", hr);
ret = test_tool_wait_message(tool, 500, &msg); - todo_wine ok(!ret, "got %#lx\n", ret); - if (!ret) - { + ok(!ret, "got %#lx\n", ret); ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %#lx\n", msg->dwType); hr = IDirectMusicPerformance_FreePMsg(performance, msg); ok(hr == S_OK, "got %#lx\n", hr); - }
ret = test_tool_wait_message(tool, 500, &msg); - todo_wine ok(!ret, "got %#lx\n", ret); - if (!ret) - { + ok(!ret, "got %#lx\n", ret); ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %#lx\n", msg->dwType); hr = IDirectMusicPerformance_FreePMsg(performance, msg); - todo_wine ok(hr == S_OK, "got %#lx\n", hr); - } + ok(hr == S_OK, "got %#lx\n", hr);
ret = test_tool_wait_message(tool, 100, &msg); ok(ret == WAIT_TIMEOUT, "got %#lx\n", ret); @@ -3114,22 +3108,22 @@ static void test_notification_pmsg(void) ok(hr == S_OK, "got %#lx\n", hr);
ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)¬if); - todo_wine ok(!ret, "got %#lx\n", ret); - if (!ret) + ok(!ret, "got %#lx\n", ret); + if (notif->dwType == DMUS_PMSGT_NOTIFICATION) { 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); - }
ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)¬if); - todo_wine ok(!ret, "got %#lx\n", ret); - if (!ret) + ok(!ret, "got %#lx\n", ret); + if (notif->dwType == DMUS_PMSGT_NOTIFICATION) { 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); - }
ret = test_tool_wait_message(tool, 500, &msg); todo_wine ok(!ret, "got %#lx\n", ret); @@ -3333,22 +3327,16 @@ static void test_wave_pmsg(void) ok(hr == S_OK, "got %#lx\n", hr);
ret = test_tool_wait_message(tool, 500, &msg); - todo_wine ok(!ret, "got %#lx\n", ret); - if (!ret) - { + ok(!ret, "got %#lx\n", ret); ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %p\n", msg); hr = IDirectMusicPerformance_FreePMsg(performance, msg); ok(hr == S_OK, "got %#lx\n", hr); - }
ret = test_tool_wait_message(tool, 500, &msg); - todo_wine ok(!ret, "got %#lx\n", ret); - if (!ret) - { + ok(!ret, "got %#lx\n", ret); ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %p\n", msg); hr = IDirectMusicPerformance_FreePMsg(performance, msg); ok(hr == S_OK, "got %#lx\n", hr); - }
ret = test_tool_wait_message(tool, 100, &msg); ok(ret == WAIT_TIMEOUT, "got %#lx\n", ret); @@ -3364,17 +3352,14 @@ static void test_wave_pmsg(void) ok(hr == S_OK, "got %#lx\n", hr);
ret = test_tool_wait_message(tool, 500, &msg); - todo_wine ok(!ret, "got %#lx\n", ret); - if (!ret) - { + ok(!ret, "got %#lx\n", ret); ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %p\n", msg); hr = IDirectMusicPerformance_FreePMsg(performance, msg); ok(hr == S_OK, "got %#lx\n", hr); - }
ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)&wave); - todo_wine ok(!ret, "got %#lx\n", ret); - if (!ret) + ok(!ret, "got %#lx\n", ret); + if (wave->dwType == DMUS_PMSGT_WAVE) { ok(wave->dwType == DMUS_PMSGT_WAVE, "got %p\n", wave); ok(!!wave->punkUser, "got %p\n", wave->punkUser); @@ -3384,9 +3369,9 @@ static void test_wave_pmsg(void) ok(wave->lVolume == 0, "got %lu\n", wave->lVolume); ok(wave->lPitch == 0, "got %lu\n", wave->lPitch); ok(wave->bFlags == 0, "got %#x\n", wave->bFlags); + } hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)wave); ok(hr == S_OK, "got %#lx\n", hr); - }
ret = test_tool_wait_message(tool, 500, &msg); todo_wine ok(!ret, "got %#lx\n", ret); @@ -3555,22 +3540,19 @@ static void test_sequence_track(void) ok(hr == S_OK, "got %#lx\n", hr);
ret = test_tool_wait_message(tool, 500, &msg); - todo_wine ok(!ret, "got %#lx\n", ret); - if (!ret) - { + ok(!ret, "got %#lx\n", ret); ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %#lx\n", msg->dwType); hr = IDirectMusicPerformance_FreePMsg(performance, msg); ok(hr == S_OK, "got %#lx\n", hr); - }
ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)¬e); - todo_wine ok(!ret, "got %#lx\n", ret); - if (!ret) + ok(!ret, "got %#lx\n", ret); + if (note->dwType == DMUS_PMSGT_NOTE) { check_dmus_note_pmsg(note, 0, 0, 500, 60, 120); + } hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)note); ok(hr == S_OK, "got %#lx\n", hr); - }
ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)¬e); todo_wine ok(!ret, "got %#lx\n", ret); @@ -3821,22 +3803,19 @@ static void test_band_track_play(void) ok(hr == S_OK, "got %#lx\n", hr);
ret = test_tool_wait_message(tool, 500, &msg); - todo_wine ok(!ret, "got %#lx\n", ret); - if (!ret) - { + ok(!ret, "got %#lx\n", ret); ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %#lx\n", msg->dwType); hr = IDirectMusicPerformance_FreePMsg(performance, msg); ok(hr == S_OK, "got %#lx\n", hr); - }
ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)&patch); - todo_wine ok(!ret, "got %#lx\n", ret); - if (!ret) + ok(!ret, "got %#lx\n", ret); + if (patch->dwType == DMUS_PMSGT_PATCH) { check_dmus_patch_pmsg(patch, 0, 1, 0, 1); + } hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)patch); ok(hr == S_OK, "got %#lx\n", hr); - }
ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)&patch); todo_wine ok(!ret, "got %#lx\n", ret);
From: Rémi Bernon rbernon@codeweavers.com
Keeping the segment state referenced until its playback ends. --- dlls/dmime/performance.c | 72 +++++++++++++++++++++++++++++++++++----- dlls/dmime/tests/dmime.c | 36 ++++---------------- 2 files changed, 70 insertions(+), 38 deletions(-)
diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index 0215b19a23c..40a78bc40ce 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -66,6 +66,9 @@ struct performance IReferenceClock *master_clock; REFERENCE_TIME init_time; struct list messages; + + BOOL notification_performance; + BOOL notification_segment; };
struct message @@ -225,6 +228,32 @@ static HRESULT performance_send_dirty_pmsg(struct performance *This, MUSIC_TIME return hr; }
+static HRESULT performance_send_notification_pmsg(struct performance *This, MUSIC_TIME music_time, BOOL stamp, + GUID type, DWORD option, IUnknown *object) +{ + IDirectMusicPerformance8 *performance = &This->IDirectMusicPerformance8_iface; + IDirectMusicGraph *graph = &This->IDirectMusicGraph_iface; + DMUS_NOTIFICATION_PMSG *msg; + HRESULT hr; + + if (FAILED(hr = IDirectMusicPerformance8_AllocPMsg(performance, sizeof(*msg), (DMUS_PMSG **)&msg))) + return hr; + + msg->mtTime = music_time; + msg->dwFlags = DMUS_PMSGF_MUSICTIME | DMUS_PMSGF_TOOL_QUEUE; + msg->dwType = DMUS_PMSGT_NOTIFICATION; + if ((msg->punkUser = object)) IUnknown_AddRef(object); + msg->guidNotificationType = type; + msg->dwNotificationOption = option; + + /* only stamp the message if notifications are enabled, otherwise send them directly to the output tool */ + if ((stamp && FAILED(hr = IDirectMusicGraph_StampPMsg(graph, (DMUS_PMSG *)msg))) + || FAILED(hr = IDirectMusicPerformance8_SendPMsg(performance, (DMUS_PMSG *)msg))) + IDirectMusicPerformance8_FreePMsg(performance, (DMUS_PMSG *)msg); + + return hr; +} + static int pchannel_block_compare(const void *key, const struct wine_rb_entry *entry) { const struct pchannel_block *b = WINE_RB_ENTRY_VALUE(entry, const struct pchannel_block, entry); @@ -703,20 +732,32 @@ static HRESULT WINAPI performance_GetNotificationPMsg(IDirectMusicPerformance8 * /*return S_OK;*/ }
-static HRESULT WINAPI performance_AddNotificationType(IDirectMusicPerformance8 *iface, REFGUID rguidNotificationType) +static HRESULT WINAPI performance_AddNotificationType(IDirectMusicPerformance8 *iface, REFGUID type) { - struct performance *This = impl_from_IDirectMusicPerformance8(iface); + struct performance *This = impl_from_IDirectMusicPerformance8(iface);
- FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType)); - return S_OK; + FIXME("(%p, %s): stub\n", This, debugstr_dmguid(type)); + + if (IsEqualGUID(type, &GUID_NOTIFICATION_PERFORMANCE)) + This->notification_performance = TRUE; + if (IsEqualGUID(type, &GUID_NOTIFICATION_SEGMENT)) + This->notification_segment = TRUE; + + return S_OK; }
-static HRESULT WINAPI performance_RemoveNotificationType(IDirectMusicPerformance8 *iface, REFGUID rguidNotificationType) +static HRESULT WINAPI performance_RemoveNotificationType(IDirectMusicPerformance8 *iface, REFGUID type) { - struct performance *This = impl_from_IDirectMusicPerformance8(iface); + struct performance *This = impl_from_IDirectMusicPerformance8(iface);
- FIXME("(%p, %s): stub\n", This, debugstr_dmguid(rguidNotificationType)); - return S_OK; + FIXME("(%p, %s): stub\n", This, debugstr_dmguid(type)); + + if (IsEqualGUID(type, &GUID_NOTIFICATION_PERFORMANCE)) + This->notification_performance = FALSE; + if (IsEqualGUID(type, &GUID_NOTIFICATION_SEGMENT)) + This->notification_segment = FALSE; + + return S_OK; }
static HRESULT perf_dmport_create(struct performance *perf, DMUS_PORTPARAMS *params) @@ -1122,11 +1163,26 @@ static HRESULT WINAPI performance_PlaySegmentEx(IDirectMusicPerformance8 *iface, }
hr = IDirectMusicSegment_GetLength(segment, &length); + if (SUCCEEDED(hr)) + hr = performance_send_notification_pmsg(This, start_time, This->notification_performance, + GUID_NOTIFICATION_PERFORMANCE, DMUS_NOTIFICATION_MUSICSTARTED, NULL); + if (SUCCEEDED(hr)) + hr = performance_send_notification_pmsg(This, start_time, This->notification_segment, + GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGSTART, (IUnknown *)state); if (SUCCEEDED(hr)) hr = performance_send_dirty_pmsg(This, start_time);
+ if (SUCCEEDED(hr)) + hr = performance_send_notification_pmsg(This, start_time + length, This->notification_segment, + GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGEND, (IUnknown *)state); + if (SUCCEEDED(hr)) + hr = performance_send_notification_pmsg(This, start_time + length, This->notification_segment, + GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGALMOSTEND, (IUnknown *)state); if (SUCCEEDED(hr)) hr = performance_send_dirty_pmsg(This, start_time + length); + if (SUCCEEDED(hr)) + hr = performance_send_notification_pmsg(This, start_time + length, This->notification_performance, + GUID_NOTIFICATION_PERFORMANCE, DMUS_NOTIFICATION_MUSICSTOPPED, NULL);
if (SUCCEEDED(hr) && segment_state) { diff --git a/dlls/dmime/tests/dmime.c b/dlls/dmime/tests/dmime.c index 88e779e75a1..c8c330860a8 100644 --- a/dlls/dmime/tests/dmime.c +++ b/dlls/dmime/tests/dmime.c @@ -3109,66 +3109,45 @@ static void test_notification_pmsg(void)
ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)¬if); ok(!ret, "got %#lx\n", ret); - if (notif->dwType == DMUS_PMSGT_NOTIFICATION) - { 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);
ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)¬if); ok(!ret, "got %#lx\n", ret); - if (notif->dwType == DMUS_PMSGT_NOTIFICATION) - { 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);
ret = test_tool_wait_message(tool, 500, &msg); - todo_wine ok(!ret, "got %#lx\n", ret); - if (!ret) - { + ok(!ret, "got %#lx\n", ret); ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %#lx\n", msg->dwType); hr = IDirectMusicPerformance_FreePMsg(performance, msg); ok(hr == S_OK, "got %#lx\n", hr); - }
ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)¬if); - todo_wine ok(!ret, "got %#lx\n", ret); - if (!ret) - { + ok(!ret, "got %#lx\n", ret); 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); - }
ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)¬if); - todo_wine ok(!ret, "got %#lx\n", ret); - if (!ret) - { + ok(!ret, "got %#lx\n", ret); 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); - }
ret = test_tool_wait_message(tool, 500, &msg); - todo_wine ok(!ret, "got %#lx\n", ret); - if (!ret) - { + ok(!ret, "got %#lx\n", ret); ok(msg->dwType == DMUS_PMSGT_DIRTY, "got %#lx\n", msg->dwType); hr = IDirectMusicPerformance_FreePMsg(performance, msg); ok(hr == S_OK, "got %#lx\n", hr); - }
ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)¬if); - todo_wine ok(!ret, "got %#lx\n", ret); - if (!ret) - { + ok(!ret, "got %#lx\n", ret); 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); - }
ret = test_tool_wait_message(tool, 100, &msg); ok(ret == WAIT_TIMEOUT, "got %#lx\n", ret); @@ -3245,13 +3224,10 @@ static void test_notification_pmsg(void) ok(hr == S_OK, "got %#lx\n", hr);
ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)¬if); - todo_wine ok(!ret, "got %#lx\n", ret); - if (!ret) - { + ok(!ret, "got %#lx\n", ret); 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_CloseDown(performance); ok(hr == S_OK, "got %#lx\n", hr);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/performance.c | 108 ++++++++++++++++++++++++++++++--------- dlls/dmime/tests/dmime.c | 31 +++-------- 2 files changed, 93 insertions(+), 46 deletions(-)
diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index 40a78bc40ce..3d53d754d11 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -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(¬if->guidNotificationType, &GUID_NOTIFICATION_PERFORMANCE)) + enabled = This->notification_performance; + if (IsEqualGUID(¬if->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 */ diff --git a/dlls/dmime/tests/dmime.c b/dlls/dmime/tests/dmime.c index c8c330860a8..f9143176594 100644 --- a/dlls/dmime/tests/dmime.c +++ b/dlls/dmime/tests/dmime.c @@ -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, ¬if); - 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, ¬if); - 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, ¬if); - 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, ¬if); - 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, ¬if); - 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, ¬if); 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);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/dmime_private.h | 4 +- dlls/dmime/performance.c | 21 +++++++- dlls/dmime/segmentstate.c | 98 +++++++++++++++++++++++++++++++++++++- dlls/dmime/tests/dmime.c | 14 +++--- 4 files changed, 125 insertions(+), 12 deletions(-)
diff --git a/dlls/dmime/dmime_private.h b/dlls/dmime/dmime_private.h index c35c52eb066..e67797def30 100644 --- a/dlls/dmime/dmime_private.h +++ b/dlls/dmime/dmime_private.h @@ -71,7 +71,9 @@ extern void set_audiopath_dsound_buffer(IDirectMusicAudioPath*,IDirectSoundBuffe extern void set_audiopath_primary_dsound_buffer(IDirectMusicAudioPath*,IDirectSoundBuffer*);
extern HRESULT segment_state_create(IDirectMusicSegment *segment, MUSIC_TIME start_time, - IDirectMusicSegmentState **ret_iface); + IDirectMusicPerformance *performance, IDirectMusicSegmentState **ret_iface); +extern HRESULT segment_state_play(IDirectMusicSegmentState *iface, IDirectMusicPerformance *performance); +extern HRESULT segment_state_end_play(IDirectMusicSegmentState *iface);
/***************************************************************************** * Auxiliary definitions diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index 3d53d754d11..7d077db16cb 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -1052,7 +1052,14 @@ static HRESULT WINAPI performance_CloseDown(IDirectMusicPerformance8 *iface) list_remove(&message->entry); list_init(&message->entry);
- if (FAILED(hr = IDirectMusicPerformance8_FreePMsg(iface, &message->msg))) + /* process notifications to end any pending segment states */ + if (message->msg.dwType == DMUS_PMSGT_NOTIFICATION) + hr = IDirectMusicTool_ProcessPMsg(&This->IDirectMusicTool_iface, + (IDirectMusicPerformance *)iface, &message->msg); + else + hr = DMUS_S_FREE; + + if (hr == DMUS_S_FREE && FAILED(hr = IDirectMusicPerformance8_FreePMsg(iface, &message->msg))) WARN("Failed to free message %p, hr %#lx\n", message, hr); }
@@ -1191,7 +1198,7 @@ static HRESULT WINAPI performance_PlaySegmentEx(IDirectMusicPerformance8 *iface,
if (FAILED(hr = IUnknown_QueryInterface(source, &IID_IDirectMusicSegment, (void **)&segment))) return hr; - if (FAILED(hr = segment_state_create(segment, start_time, &state))) + if (FAILED(hr = segment_state_create(segment, start_time, (IDirectMusicPerformance *)iface, &state))) { IDirectMusicSegment_Release(segment); return hr; @@ -1207,6 +1214,9 @@ static HRESULT WINAPI performance_PlaySegmentEx(IDirectMusicPerformance8 *iface, if (SUCCEEDED(hr)) hr = performance_send_dirty_pmsg(This, start_time);
+ if (SUCCEEDED(hr)) + hr = segment_state_play(state, (IDirectMusicPerformance *)iface); + if (SUCCEEDED(hr)) hr = performance_send_notification_pmsg(This, start_time + length, This->notification_segment, GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGEND, (IUnknown *)state); @@ -1634,6 +1644,13 @@ static HRESULT WINAPI performance_tool_ProcessPMsg(IDirectMusicTool *iface, BOOL enabled = FALSE; HRESULT hr;
+ if (IsEqualGUID(¬if->guidNotificationType, &GUID_NOTIFICATION_SEGMENT) + && notif->dwNotificationOption == DMUS_NOTIFICATION_SEGEND) + { + if (FAILED(hr = segment_state_end_play((IDirectMusicSegmentState *)notif->punkUser))) + WARN("Failed to end segment state %p, hr %#lx\n", notif->punkUser, hr); + } + if (IsEqualGUID(¬if->guidNotificationType, &GUID_NOTIFICATION_PERFORMANCE)) enabled = This->notification_performance; if (IsEqualGUID(¬if->guidNotificationType, &GUID_NOTIFICATION_SEGMENT)) diff --git a/dlls/dmime/segmentstate.c b/dlls/dmime/segmentstate.c index 1a09bed5dd3..de47d85e9b8 100644 --- a/dlls/dmime/segmentstate.c +++ b/dlls/dmime/segmentstate.c @@ -21,14 +21,39 @@
WINE_DEFAULT_DEBUG_CHANNEL(dmime);
+static DWORD next_track_id; + +struct track_entry +{ + struct list entry; + + IDirectMusicTrack *track; + void *state_data; + DWORD track_id; +}; + +static void track_entry_destroy(struct track_entry *entry) +{ + HRESULT hr; + + if (FAILED(hr = IDirectMusicTrack_EndPlay(entry->track, entry->state_data))) + WARN("track %p EndPlay failed, hr %#lx\n", entry->track, hr); + + IDirectMusicTrack_Release(entry->track); + free(entry); +} + struct segment_state { IDirectMusicSegmentState8 IDirectMusicSegmentState8_iface; LONG ref;
IDirectMusicSegment *segment; - MUSIC_TIME start_point; MUSIC_TIME start_time; + MUSIC_TIME start_point; + MUSIC_TIME end_point; + + struct list tracks; };
static inline struct segment_state *impl_from_IDirectMusicSegmentState8(IDirectMusicSegmentState8 *iface) @@ -79,6 +104,7 @@ static ULONG WINAPI segment_state_Release(IDirectMusicSegmentState8 *iface)
if (!ref) { + segment_state_end_play((IDirectMusicSegmentState *)iface); if (This->segment) IDirectMusicSegment_Release(This->segment); free(This); } @@ -174,6 +200,7 @@ HRESULT create_dmsegmentstate(REFIID riid, void **ret_iface) obj->IDirectMusicSegmentState8_iface.lpVtbl = &segment_state_vtbl; obj->ref = 1; obj->start_time = -1; + list_init(&obj->tracks);
TRACE("Created IDirectMusicSegmentState %p\n", obj); hr = IDirectMusicSegmentState8_QueryInterface(&obj->IDirectMusicSegmentState8_iface, riid, ret_iface); @@ -182,11 +209,13 @@ HRESULT create_dmsegmentstate(REFIID riid, void **ret_iface) }
HRESULT segment_state_create(IDirectMusicSegment *segment, MUSIC_TIME start_time, - IDirectMusicSegmentState **ret_iface) + IDirectMusicPerformance *performance, IDirectMusicSegmentState **ret_iface) { IDirectMusicSegmentState *iface; struct segment_state *This; + IDirectMusicTrack *track; HRESULT hr; + UINT i;
TRACE("(%p, %lu, %p)\n", segment, start_time, ret_iface);
@@ -198,8 +227,73 @@ HRESULT segment_state_create(IDirectMusicSegment *segment, MUSIC_TIME start_time
This->start_time = start_time; hr = IDirectMusicSegment_GetStartPoint(segment, &This->start_point); + if (SUCCEEDED(hr)) hr = IDirectMusicSegment_GetLength(segment, &This->end_point); + + for (i = 0; SUCCEEDED(hr); i++) + { + DWORD track_id = ++next_track_id; + struct track_entry *entry; + + if ((hr = IDirectMusicSegment_GetTrack(segment, &GUID_NULL, -1, i, &track)) != S_OK) + { + if (hr == DMUS_E_NOT_FOUND) hr = S_OK; + break; + } + + if (!(entry = malloc(sizeof(*entry)))) + hr = E_OUTOFMEMORY; + else if (SUCCEEDED(hr = IDirectMusicTrack_InitPlay(track, iface, performance, + &entry->state_data, track_id, 0))) + { + entry->track = track; + entry->track_id = track_id; + list_add_tail(&This->tracks, &entry->entry); + } + + if (FAILED(hr)) + { + WARN("Failed to initialize track %p, hr %#lx\n", track, hr); + IDirectMusicTrack_Release(track); + free(entry); + } + }
if (SUCCEEDED(hr)) *ret_iface = iface; else IDirectMusicSegmentState_Release(iface); return hr; } + +HRESULT segment_state_play(IDirectMusicSegmentState *iface, IDirectMusicPerformance *performance) +{ + struct segment_state *This = impl_from_IDirectMusicSegmentState8((IDirectMusicSegmentState8 *)iface); + DWORD track_flags = DMUS_TRACKF_DIRTY | DMUS_TRACKF_START | DMUS_TRACKF_SEEK; + MUSIC_TIME start_time = This->start_point, end_time = This->end_point; + struct track_entry *entry; + HRESULT hr = S_OK; + + LIST_FOR_EACH_ENTRY(entry, &This->tracks, struct track_entry, entry) + { + if (FAILED(hr = IDirectMusicTrack_Play(entry->track, entry->state_data, start_time, + end_time, 0, track_flags, performance, iface, entry->track_id))) + { + WARN("Failed to play track %p, hr %#lx\n", entry->track, hr); + break; + } + } + + return hr; +} + +HRESULT segment_state_end_play(IDirectMusicSegmentState *iface) +{ + struct segment_state *This = impl_from_IDirectMusicSegmentState8((IDirectMusicSegmentState8 *)iface); + struct track_entry *entry, *next; + + LIST_FOR_EACH_ENTRY_SAFE(entry, next, &This->tracks, struct track_entry, entry) + { + list_remove(&entry->entry); + track_entry_destroy(entry); + } + + return S_OK; +} diff --git a/dlls/dmime/tests/dmime.c b/dlls/dmime/tests/dmime.c index f9143176594..cb35ef64ead 100644 --- a/dlls/dmime/tests/dmime.c +++ b/dlls/dmime/tests/dmime.c @@ -662,7 +662,7 @@ static HRESULT WINAPI test_track_Play(IDirectMusicTrack *iface, void *state_data ok(state_data == &This->data, "got %p\n", state_data); ok(start_time == 50, "got %lu\n", start_time); ok(end_time == 100, "got %lu\n", end_time); - ok(time_offset < 0, "got %lu\n", time_offset); + todo_wine ok(time_offset < 0, "got %lu\n", time_offset); ok(segment_flags == (DMUS_TRACKF_DIRTY|DMUS_TRACKF_START|DMUS_TRACKF_SEEK), "got %#lx\n", segment_flags); ok(!!performance, "got %p\n", performance); @@ -3990,7 +3990,7 @@ static void test_segment_state(void) IDirectMusicSegmentState_Release(tmp_state);
check_track_state(track, downloaded, FALSE); - todo_wine check_track_state(track, initialized, TRUE); + check_track_state(track, initialized, TRUE);
/* The track can be removed from the segment */ @@ -4001,10 +4001,10 @@ static void test_segment_state(void) /* This might be timing dependent and if PlaySegment is already * late, the tracks are played synchronously and right away. */ - check_track_state(track, playing, FALSE); + todo_wine check_track_state(track, playing, FALSE);
ret = test_track_wait_playing(track, 50); - todo_wine ok(ret == 0, "got %#lx\n", ret); + ok(ret == 0, "got %#lx\n", ret);
tmp_segment = (void *)0xdeadbeef; @@ -4064,14 +4064,14 @@ static void test_segment_state(void)
check_track_state(track, downloaded, FALSE); - todo_wine check_track_state(track, initialized, TRUE); - todo_wine check_track_state(track, playing, TRUE); + check_track_state(track, initialized, TRUE); + check_track_state(track, playing, TRUE);
hr = IDirectMusicPerformance_CloseDown(performance); ok(hr == S_OK, "got %#lx\n", hr);
check_track_state(track, downloaded, FALSE); - todo_wine check_track_state(track, initialized, TRUE); + check_track_state(track, initialized, TRUE); check_track_state(track, playing, FALSE);
The tests fail on `dmime: Send DMUS_PMSGT_DIRTY messages from the performance.` but succeed with the full MR: ``` dmime.c:3248: Test succeeded inside todo block: got 0 dmime.c:3251: Test failed: got dwType 0xb dmime.c:3251: Test failed: got guidNotificationType {00000009-0000-0075-68d3-b50068d3b500} dmime.c:3251: Test failed: got dwNotificationOption 0x38 dmime.c:3251: Test failed: got dwField2 4258472269 ... make: *** [Makefile:87556: dlls/dmime/tests/i386-windows/dmime.ok] Error 5 ```
On Fri Oct 6 21:35:40 2023 +0000, Michael Stefaniuc wrote:
The tests fail on `dmime: Send DMUS_PMSGT_DIRTY messages from the performance.` but succeed with the full MR:
dmime.c:3248: Test succeeded inside todo block: got 0 dmime.c:3251: Test failed: got dwType 0xb dmime.c:3251: Test failed: got guidNotificationType {00000009-0000-0075-68d3-b50068d3b500} dmime.c:3251: Test failed: got dwNotificationOption 0x38 dmime.c:3251: Test failed: got dwField2 4258472269 ... make: *** [Makefile:87556: dlls/dmime/tests/i386-windows/dmime.ok] Error 5
Oof oof, I was sure I tried every change but then probably changed more things last minute. Thanks for catching it.