-- v5: dmime: Implement segment state repeat and looping. dmime: Split segment_state_play_chunk helper. dmsynth: Reset synthesizer defaults on MIDI_SYSTEM_RESET. dmime: Send MIDI_SYSTEM_RESET message on performance reset. dmime: Clear all pending messages in IDirectMusicPerformance_Stop. dmime/tests: Test that IDirectMusicPerformance_Stop clears messages. dmime/tests: Avoid discarding old notifications in test.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/tests/dmime.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/dlls/dmime/tests/dmime.c b/dlls/dmime/tests/dmime.c index 7613b82c893..e181a6b1299 100644 --- a/dlls/dmime/tests/dmime.c +++ b/dlls/dmime/tests/dmime.c @@ -3176,6 +3176,10 @@ static void test_notification_pmsg(void) hr = IDirectMusicPerformance_AddNotificationType(performance, &GUID_NOTIFICATION_SEGMENT); ok(hr == S_FALSE, "got %#lx\n", hr);
+ /* avoid discarding older notifications */ + hr = IDirectMusicPerformance_SetNotificationHandle(performance, 0, 100000000); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IDirectMusicPerformance_PlaySegment(performance, segment, 0, 0, &state); ok(hr == S_OK, "got %#lx\n", hr); hr = IDirectMusicPerformance_GetTime(performance, NULL, &music_time);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/tests/dmime.c | 49 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+)
diff --git a/dlls/dmime/tests/dmime.c b/dlls/dmime/tests/dmime.c index e181a6b1299..e70fbfd5f1b 100644 --- a/dlls/dmime/tests/dmime.c +++ b/dlls/dmime/tests/dmime.c @@ -3294,6 +3294,55 @@ static void test_notification_pmsg(void) ok(hr == S_FALSE, "got %#lx\n", hr);
+ /* Stop finishes segment immediately and skips notification messages */ + + hr = IDirectMusicPerformance_AddNotificationType(performance, &GUID_NOTIFICATION_SEGMENT); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IDirectMusicPerformance_PlaySegment(performance, segment, 0, 0, &state); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IDirectMusicPerformance_GetTime(performance, NULL, &music_time); + ok(hr == S_OK, "got %#lx\n", hr); + + ret = test_tool_wait_message(tool, 50, (DMUS_PMSG **)¬if); + ok(!ret, "got %#lx\n", ret); + check_dmus_notification_pmsg(notif, music_time, DMUS_PMSGF_TOOL_IMMEDIATE, &GUID_NOTIFICATION_SEGMENT, + DMUS_NOTIFICATION_SEGSTART, state); + hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif); + ok(hr == S_OK, "got %#lx\n", hr); + + hr = IDirectMusicPerformance_Stop(performance, NULL, NULL, 0, DMUS_SEGF_DEFAULT); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IDirectMusicPerformance_RemoveNotificationType(performance, &GUID_NOTIFICATION_SEGMENT); + ok(hr == S_OK, "got %#lx\n", hr); + + ret = test_tool_wait_message(tool, 50, &msg); + 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, 50, (DMUS_PMSG **)¬if); + todo_wine ok(!ret, "got %#lx\n", ret); + if (!ret) + { + check_dmus_notification_pmsg(notif, music_time, DMUS_PMSGF_TOOL_IMMEDIATE, &GUID_NOTIFICATION_SEGMENT, + DMUS_NOTIFICATION_SEGABORT, state); + hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif); + ok(hr == S_OK, "got %#lx\n", hr); + } + + ret = test_tool_wait_message(tool, 500, &msg); + ok(!ret, "got %#lx\n", ret); + ok(msg->dwType == DMUS_PMSGT_DIRTY, "got dwType %#lx\n", msg->dwType); + 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); + + IDirectMusicSegmentState_Release(state); + + /* CloseDown removes all notifications and notification messages */
hr = IDirectMusicPerformance_AddNotificationType(performance, &GUID_NOTIFICATION_SEGMENT);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/dmime_private.h | 4 +- dlls/dmime/performance.c | 165 +++++++++++++++++++++++++++++-------- dlls/dmime/segmentstate.c | 23 +++++- dlls/dmime/tests/dmime.c | 5 +- 4 files changed, 158 insertions(+), 39 deletions(-)
diff --git a/dlls/dmime/dmime_private.h b/dlls/dmime/dmime_private.h index 3c7fc1e332b..ed1589ece1a 100644 --- a/dlls/dmime/dmime_private.h +++ b/dlls/dmime/dmime_private.h @@ -76,8 +76,10 @@ extern HRESULT segment_state_create(IDirectMusicSegment *segment, MUSIC_TIME sta IDirectMusicPerformance8 *performance, IDirectMusicSegmentState **ret_iface); extern HRESULT segment_state_play(IDirectMusicSegmentState *iface, IDirectMusicPerformance8 *performance); extern HRESULT segment_state_tick(IDirectMusicSegmentState *iface, IDirectMusicPerformance8 *performance); +extern HRESULT segment_state_stop(IDirectMusicSegmentState *iface, IDirectMusicPerformance8 *performance); extern HRESULT segment_state_end_play(IDirectMusicSegmentState *iface, IDirectMusicPerformance8 *performance); extern BOOL segment_state_has_segment(IDirectMusicSegmentState *iface, IDirectMusicSegment *segment); +extern BOOL segment_state_has_track(IDirectMusicSegmentState *iface, DWORD track_id);
extern HRESULT wave_track_create_from_chunk(IStream *stream, struct chunk_entry *parent, IDirectMusicTrack8 **ret_iface); @@ -88,7 +90,7 @@ extern HRESULT performance_send_segment_start(IDirectMusicPerformance8 *iface, M extern HRESULT performance_send_segment_tick(IDirectMusicPerformance8 *iface, MUSIC_TIME music_time, IDirectMusicSegmentState *state); extern HRESULT performance_send_segment_end(IDirectMusicPerformance8 *iface, MUSIC_TIME music_time, - IDirectMusicSegmentState *state); + IDirectMusicSegmentState *state, BOOL abort);
/***************************************************************************** * Auxiliary definitions diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index 94d7d8aeea3..494f9acbe1d 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -318,24 +318,28 @@ HRESULT performance_send_segment_tick(IDirectMusicPerformance8 *iface, MUSIC_TIM }
HRESULT performance_send_segment_end(IDirectMusicPerformance8 *iface, MUSIC_TIME music_time, - IDirectMusicSegmentState *state) + IDirectMusicSegmentState *state, BOOL abort) { struct performance *This = impl_from_IDirectMusicPerformance8(iface); HRESULT hr;
- if (FAILED(hr = performance_send_notification_pmsg(This, music_time - 1450, This->notification_segment, - GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGALMOSTEND, (IUnknown *)state))) - return hr; - if (FAILED(hr = performance_send_notification_pmsg(This, music_time, This->notification_segment, - GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGEND, (IUnknown *)state))) - return hr; + if (!abort) + { + if (FAILED(hr = performance_send_notification_pmsg(This, music_time - 1450, This->notification_segment, + GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGALMOSTEND, (IUnknown *)state))) + return hr; + if (FAILED(hr = performance_send_notification_pmsg(This, music_time, This->notification_segment, + GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGEND, (IUnknown *)state))) + return hr; + } + if (FAILED(hr = performance_send_pmsg(This, music_time, DMUS_PMSGF_TOOL_IMMEDIATE, DMUS_PMSGT_DIRTY, NULL))) return hr; if (FAILED(hr = performance_send_notification_pmsg(This, music_time, This->notification_performance, GUID_NOTIFICATION_PERFORMANCE, DMUS_NOTIFICATION_MUSICSTOPPED, NULL))) return hr; - if (FAILED(hr = performance_send_pmsg(This, music_time, DMUS_PMSGF_TOOL_ATTIME, + if (FAILED(hr = performance_send_pmsg(This, music_time, abort ? DMUS_PMSGF_TOOL_IMMEDIATE : DMUS_PMSGF_TOOL_ATTIME, DMUS_PMSGT_INTERNAL_SEGMENT_END, (IUnknown *)state))) return hr;
@@ -539,13 +543,118 @@ static void enum_segment_states(struct performance *This, IDirectMusicSegment *s } }
-static HRESULT WINAPI performance_Stop(IDirectMusicPerformance8 *iface, IDirectMusicSegment *pSegment, - IDirectMusicSegmentState *pSegmentState, MUSIC_TIME mtTime, DWORD dwFlags) +static BOOL message_needs_flushing(struct message *message, IDirectMusicSegmentState *state) { - struct performance *This = impl_from_IDirectMusicPerformance8(iface); + if (!state) return TRUE;
- FIXME("(%p, %p, %p, %ld, %ld): stub\n", This, pSegment, pSegmentState, mtTime, dwFlags); - return S_OK; + switch (message->msg.dwType) + { + case DMUS_PMSGT_MIDI: + case DMUS_PMSGT_NOTE: + case DMUS_PMSGT_CURVE: + case DMUS_PMSGT_PATCH: + case DMUS_PMSGT_WAVE: + if (!segment_state_has_track(state, message->msg.dwVirtualTrackID)) return FALSE; + break; + + case DMUS_PMSGT_NOTIFICATION: + { + DMUS_NOTIFICATION_PMSG *notif = (DMUS_NOTIFICATION_PMSG *)&message->msg; + if (!IsEqualGUID(¬if->guidNotificationType, &GUID_NOTIFICATION_SEGMENT)) return FALSE; + if ((IDirectMusicSegmentState *)message->msg.punkUser != state) return FALSE; + break; + } + + case DMUS_PMSGT_INTERNAL_SEGMENT_TICK: + case DMUS_PMSGT_INTERNAL_SEGMENT_END: + if ((IDirectMusicSegmentState *)message->msg.punkUser != state) return FALSE; + break; + + default: + FIXME("Unhandled message type %#lx\n", message->msg.dwType); + break; + } + + return TRUE; +} + +static void performance_flush_messages(struct performance *This, IDirectMusicSegmentState *state) +{ + IDirectMusicPerformance *iface = (IDirectMusicPerformance *)&This->IDirectMusicPerformance8_iface; + struct message *message, *next; + HRESULT hr; + + LIST_FOR_EACH_ENTRY_SAFE(message, next, &This->messages, struct message, entry) + { + if (!message_needs_flushing(message, state)) continue; + + list_remove(&message->entry); + list_init(&message->entry); + + if (FAILED(hr = IDirectMusicPerformance8_FreePMsg(iface, &message->msg))) + ERR("Failed to free message %p, hr %#lx\n", message, hr); + } + + LIST_FOR_EACH_ENTRY_SAFE(message, next, &This->notifications, struct message, entry) + { + if (!message_needs_flushing(message, state)) continue; + + list_remove(&message->entry); + list_init(&message->entry); + + if (FAILED(hr = IDirectMusicPerformance8_FreePMsg(iface, &message->msg))) + ERR("Failed to free message %p, hr %#lx\n", message, hr); + } +} + +static HRESULT WINAPI performance_Stop(IDirectMusicPerformance8 *iface, IDirectMusicSegment *segment, + IDirectMusicSegmentState *state, MUSIC_TIME music_time, DWORD flags) +{ + struct performance *This = impl_from_IDirectMusicPerformance8(iface); + struct list states = LIST_INIT(states); + struct state_entry *entry, *next; + HRESULT hr; + + FIXME("(%p, %p, %p, %ld, %ld): semi-stub\n", This, segment, state, music_time, flags); + + if (music_time) FIXME("time parameter %lu not implemented\n", music_time); + if (flags != DMUS_SEGF_DEFAULT) FIXME("flags parameter %#lx not implemented\n", flags); + + if (!music_time && FAILED(hr = IDirectMusicPerformance8_GetTime(iface, NULL, &music_time))) + return hr; + + EnterCriticalSection(&This->safe); + + if (!state) + enum_segment_states(This, segment, &states); + else if ((entry = malloc(sizeof(*entry)))) + { + entry->state = state; + IDirectMusicSegmentState_AddRef(entry->state); + list_add_tail(&states, &entry->entry); + } + + if (!segment && !state) + performance_flush_messages(This, NULL); + else LIST_FOR_EACH_ENTRY(entry, &states, struct state_entry, entry) + performance_flush_messages(This, entry->state); + + LIST_FOR_EACH_ENTRY_SAFE(entry, next, &states, struct state_entry, entry) + { + if (FAILED(hr = performance_send_notification_pmsg(This, music_time, This->notification_segment, + GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGABORT, (IUnknown *)entry->state))) + ERR("Failed to send DMUS_NOTIFICATION_SEGABORT, hr %#lx\n", hr); + if (FAILED(hr = segment_state_stop(entry->state, iface))) + ERR("Failed to stop segment state, hr %#lx\n", hr); + + IDirectMusicSegmentState_Release(entry->state); + list_remove(&entry->entry); + free(entry); + } + + LeaveCriticalSection(&This->safe); + + return S_OK; }
static HRESULT WINAPI performance_GetSegmentState(IDirectMusicPerformance8 *iface, @@ -1234,7 +1343,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; + struct list states = LIST_INIT(states); + struct state_entry *entry, *next; HANDLE message_thread; HRESULT hr;
@@ -1254,28 +1364,17 @@ static HRESULT WINAPI performance_CloseDown(IDirectMusicPerformance8 *iface) This->notification_performance = FALSE; This->notification_segment = FALSE;
- LIST_FOR_EACH_ENTRY_SAFE(message, next, &This->messages, struct message, entry) - { - list_remove(&message->entry); - list_init(&message->entry); - - if (message->msg.dwType == DMUS_PMSGT_INTERNAL_SEGMENT_END) - hr = IDirectMusicTool_ProcessPMsg(&This->IDirectMusicTool_iface, - (IDirectMusicPerformance *)iface, &message->msg); - else - hr = DMUS_S_FREE; + enum_segment_states(This, NULL, &states); + performance_flush_messages(This, NULL);
- if (hr == DMUS_S_FREE && FAILED(hr = IDirectMusicPerformance8_FreePMsg(iface, &message->msg))) - WARN("Failed to free message %p, hr %#lx\n", message, hr); - } - - LIST_FOR_EACH_ENTRY_SAFE(message, next, &This->notifications, struct message, entry) + LIST_FOR_EACH_ENTRY_SAFE(entry, next, &states, struct state_entry, entry) { - list_remove(&message->entry); - list_init(&message->entry); + if (FAILED(hr = segment_state_end_play(entry->state, iface))) + ERR("Failed to stop segment state, hr %#lx\n", hr);
- if (FAILED(hr = IDirectMusicPerformance8_FreePMsg(iface, &message->msg))) - WARN("Failed to free message %p, hr %#lx\n", message, hr); + IDirectMusicSegmentState_Release(entry->state); + list_remove(&entry->entry); + free(entry); }
performance_set_primary_segment(This, NULL); diff --git a/dlls/dmime/segmentstate.c b/dlls/dmime/segmentstate.c index 3e13687254e..544620b0045 100644 --- a/dlls/dmime/segmentstate.c +++ b/dlls/dmime/segmentstate.c @@ -303,7 +303,7 @@ static HRESULT segment_state_play_chunk(struct segment_state *This, IDirectMusic { MUSIC_TIME end_time = This->start_time + This->played;
- if (FAILED(hr = performance_send_segment_end(performance, end_time, iface))) + if (FAILED(hr = performance_send_segment_end(performance, end_time, iface, FALSE))) { ERR("Failed to send segment end, hr %#lx\n", hr); return hr; @@ -345,6 +345,16 @@ HRESULT segment_state_tick(IDirectMusicSegmentState *iface, IDirectMusicPerforma return segment_state_play_chunk(This, performance, 10000000, 0); }
+HRESULT segment_state_stop(IDirectMusicSegmentState *iface, IDirectMusicPerformance8 *performance) +{ + struct segment_state *This = impl_from_IDirectMusicSegmentState8((IDirectMusicSegmentState8 *)iface); + + TRACE("%p %p\n", iface, performance); + + This->played = This->end_point - This->start_point; + return performance_send_segment_end(performance, This->start_time + This->played, iface, TRUE); +} + HRESULT segment_state_end_play(IDirectMusicSegmentState *iface, IDirectMusicPerformance8 *performance) { struct segment_state *This = impl_from_IDirectMusicSegmentState8((IDirectMusicSegmentState8 *)iface); @@ -369,3 +379,14 @@ BOOL segment_state_has_segment(IDirectMusicSegmentState *iface, IDirectMusicSegm struct segment_state *This = impl_from_IDirectMusicSegmentState8((IDirectMusicSegmentState8 *)iface); return !segment || This->segment == segment; } + +BOOL segment_state_has_track(IDirectMusicSegmentState *iface, DWORD track_id) +{ + struct segment_state *This = impl_from_IDirectMusicSegmentState8((IDirectMusicSegmentState8 *)iface); + struct track_entry *entry; + + LIST_FOR_EACH_ENTRY(entry, &This->tracks, struct track_entry, entry) + if (entry->track_id == track_id) return TRUE; + + return FALSE; +} diff --git a/dlls/dmime/tests/dmime.c b/dlls/dmime/tests/dmime.c index e70fbfd5f1b..bfb41d322e8 100644 --- a/dlls/dmime/tests/dmime.c +++ b/dlls/dmime/tests/dmime.c @@ -3322,14 +3322,11 @@ static void test_notification_pmsg(void) ok(hr == S_OK, "got %#lx\n", hr);
ret = test_tool_wait_message(tool, 50, (DMUS_PMSG **)¬if); - todo_wine ok(!ret, "got %#lx\n", ret); - if (!ret) - { + ok(!ret, "got %#lx\n", ret); check_dmus_notification_pmsg(notif, music_time, DMUS_PMSGF_TOOL_IMMEDIATE, &GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGABORT, state); hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)notif); ok(hr == S_OK, "got %#lx\n", hr); - }
ret = test_tool_wait_message(tool, 500, &msg); ok(!ret, "got %#lx\n", ret);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/performance.c | 71 +++++++++++++++++++++++---------------- dlls/dmusic/dmusic_midi.h | 1 + 2 files changed, 43 insertions(+), 29 deletions(-)
diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index 494f9acbe1d..23aa2f23d3b 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -454,6 +454,35 @@ static HRESULT performance_init_dmusic(struct performance *This, IDirectSound *d return hr; }
+static HRESULT performance_send_midi_pmsg(struct performance *This, DMUS_PMSG *msg, UINT flags, + BYTE status, BYTE byte1, BYTE byte2) +{ + IDirectMusicPerformance8 *performance = &This->IDirectMusicPerformance8_iface; + DMUS_MIDI_PMSG *midi; + HRESULT hr; + + if (FAILED(hr = IDirectMusicPerformance8_AllocPMsg(performance, sizeof(*midi), + (DMUS_PMSG **)&midi))) + return hr; + + if (flags & DMUS_PMSGF_REFTIME) midi->rtTime = msg->rtTime; + if (flags & DMUS_PMSGF_MUSICTIME) midi->mtTime = msg->mtTime; + midi->dwFlags = flags; + midi->dwPChannel = msg->dwPChannel; + midi->dwVirtualTrackID = msg->dwVirtualTrackID; + midi->dwVoiceID = msg->dwVoiceID; + midi->dwGroupID = msg->dwGroupID; + midi->dwType = DMUS_PMSGT_MIDI; + midi->bStatus = status; + midi->bByte1 = byte1; + midi->bByte2 = byte2; + + if (FAILED(hr = IDirectMusicPerformance8_SendPMsg(performance, (DMUS_PMSG *)midi))) + IDirectMusicPerformance8_FreePMsg(performance, (DMUS_PMSG *)midi); + + return hr; +} + static HRESULT WINAPI performance_Init(IDirectMusicPerformance8 *iface, IDirectMusic **dmusic, IDirectSound *dsound, HWND hwnd) { @@ -613,6 +642,7 @@ static HRESULT WINAPI performance_Stop(IDirectMusicPerformance8 *iface, IDirectM struct performance *This = impl_from_IDirectMusicPerformance8(iface); struct list states = LIST_INIT(states); struct state_entry *entry, *next; + DMUS_PMSG msg = {.mtTime = -1}; HRESULT hr;
FIXME("(%p, %p, %p, %ld, %ld): semi-stub\n", This, segment, state, music_time, flags); @@ -652,6 +682,13 @@ static HRESULT WINAPI performance_Stop(IDirectMusicPerformance8 *iface, IDirectM free(entry); }
+ if (!state && !segment) + { + if (FAILED(hr = performance_send_midi_pmsg(This, &msg, DMUS_PMSGF_MUSICTIME | DMUS_PMSGF_TOOL_IMMEDIATE, + MIDI_SYSTEM_RESET, 0, 0))) + ERR("Failed to send MIDI_SYSTEM_RESET message, hr %#lx\n", hr); + } + LeaveCriticalSection(&This->safe);
return S_OK; @@ -1345,6 +1382,7 @@ static HRESULT WINAPI performance_CloseDown(IDirectMusicPerformance8 *iface) struct performance *This = impl_from_IDirectMusicPerformance8(iface); struct list states = LIST_INIT(states); struct state_entry *entry, *next; + DMUS_PMSG msg = {.mtTime = -1}; HANDLE message_thread; HRESULT hr;
@@ -1377,6 +1415,10 @@ static HRESULT WINAPI performance_CloseDown(IDirectMusicPerformance8 *iface) free(entry); }
+ if (FAILED(hr = performance_send_midi_pmsg(This, &msg, DMUS_PMSGF_MUSICTIME | DMUS_PMSGF_TOOL_IMMEDIATE, + MIDI_SYSTEM_RESET, 0, 0))) + ERR("Failed to send MIDI_SYSTEM_RESET message, hr %#lx\n", hr); + performance_set_primary_segment(This, NULL); performance_set_control_segment(This, NULL);
@@ -1930,35 +1972,6 @@ static HRESULT WINAPI performance_tool_GetMediaTypes(IDirectMusicTool *iface, DW return E_NOTIMPL; }
-static HRESULT performance_send_midi_pmsg(struct performance *This, DMUS_PMSG *msg, UINT flags, - BYTE status, BYTE byte1, BYTE byte2) -{ - IDirectMusicPerformance8 *performance = &This->IDirectMusicPerformance8_iface; - DMUS_MIDI_PMSG *midi; - HRESULT hr; - - if (FAILED(hr = IDirectMusicPerformance8_AllocPMsg(performance, sizeof(*midi), - (DMUS_PMSG **)&midi))) - return hr; - - if (flags & DMUS_PMSGF_REFTIME) midi->rtTime = msg->rtTime; - if (flags & DMUS_PMSGF_MUSICTIME) midi->mtTime = msg->mtTime; - midi->dwFlags = flags; - midi->dwPChannel = msg->dwPChannel; - midi->dwVirtualTrackID = msg->dwVirtualTrackID; - midi->dwVoiceID = msg->dwVoiceID; - midi->dwGroupID = msg->dwGroupID; - midi->dwType = DMUS_PMSGT_MIDI; - midi->bStatus = status; - midi->bByte1 = byte1; - midi->bByte2 = byte2; - - if (FAILED(hr = IDirectMusicPerformance8_SendPMsg(performance, (DMUS_PMSG *)midi))) - IDirectMusicPerformance8_FreePMsg(performance, (DMUS_PMSG *)midi); - - return hr; -} - static HRESULT WINAPI performance_tool_ProcessPMsg(IDirectMusicTool *iface, IDirectMusicPerformance *performance, DMUS_PMSG *msg) { diff --git a/dlls/dmusic/dmusic_midi.h b/dlls/dmusic/dmusic_midi.h index e545bcaf8cb..574961c12d0 100644 --- a/dlls/dmusic/dmusic_midi.h +++ b/dlls/dmusic/dmusic_midi.h @@ -31,6 +31,7 @@ enum midi_message MIDI_PROGRAM_CHANGE = 0xc0, MIDI_CHANNEL_PRESSURE = 0xd0, MIDI_PITCH_BEND_CHANGE = 0xe0, + MIDI_SYSTEM_RESET = 0xff, };
enum midi_control
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmsynth/synth.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/dlls/dmsynth/synth.c b/dlls/dmsynth/synth.c index 410fb59089e..51271e48b2a 100644 --- a/dlls/dmsynth/synth.c +++ b/dlls/dmsynth/synth.c @@ -1125,7 +1125,9 @@ static HRESULT WINAPI synth_Render(IDirectMusicSynth8 *iface, short *buffer,
TRACE("status %#x chan %#x midi %#x %#x\n", status, chan, event->midi[1], event->midi[2]);
- switch (status) + if (event->midi[0] == MIDI_SYSTEM_RESET) + synth_reset_default_values(This); + else switch (status) { case MIDI_NOTE_OFF: fluid_synth_noteoff(This->fluid_synth, chan, event->midi[1]);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/segmentstate.c | 46 +++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 21 deletions(-)
diff --git a/dlls/dmime/segmentstate.c b/dlls/dmime/segmentstate.c index 544620b0045..6391f44fd9a 100644 --- a/dlls/dmime/segmentstate.c +++ b/dlls/dmime/segmentstate.c @@ -269,22 +269,15 @@ HRESULT segment_state_create(IDirectMusicSegment *segment, MUSIC_TIME start_time return hr; }
-static HRESULT segment_state_play_chunk(struct segment_state *This, IDirectMusicPerformance8 *performance, - REFERENCE_TIME duration, DWORD track_flags) +static HRESULT segment_state_play_until(struct segment_state *This, IDirectMusicPerformance8 *performance, + MUSIC_TIME end_time, DWORD track_flags) { IDirectMusicSegmentState *iface = (IDirectMusicSegmentState *)&This->IDirectMusicSegmentState8_iface; - MUSIC_TIME next_time, played; struct track_entry *entry; - REFERENCE_TIME time; HRESULT hr = S_OK; + MUSIC_TIME played;
- if (FAILED(hr = IDirectMusicPerformance8_MusicToReferenceTime(performance, - This->start_time + This->played, &time))) - return hr; - if (FAILED(hr = IDirectMusicPerformance8_ReferenceToMusicTime(performance, - time + duration, &next_time))) - return hr; - played = min(next_time - This->start_time, This->end_point - This->start_point); + played = min(end_time - This->start_time, This->end_point - This->start_point);
LIST_FOR_EACH_ENTRY(entry, &This->tracks, struct track_entry, entry) { @@ -299,20 +292,31 @@ static HRESULT segment_state_play_chunk(struct segment_state *This, IDirectMusic }
This->played = played; - if (This->start_point + This->played >= This->end_point) - { - MUSIC_TIME end_time = This->start_time + This->played; + return This->start_point + This->played >= This->end_point ? S_FALSE : S_OK; +}
- if (FAILED(hr = performance_send_segment_end(performance, end_time, iface, FALSE))) - { - ERR("Failed to send segment end, hr %#lx\n", hr); - return hr; - } +static HRESULT segment_state_play_chunk(struct segment_state *This, IDirectMusicPerformance8 *performance, + REFERENCE_TIME duration, DWORD track_flags) +{ + IDirectMusicSegmentState *iface = (IDirectMusicSegmentState *)&This->IDirectMusicSegmentState8_iface; + MUSIC_TIME next_time; + REFERENCE_TIME time; + HRESULT hr; + + if (FAILED(hr = IDirectMusicPerformance8_MusicToReferenceTime(performance, + This->start_time + This->played, &time))) + return hr; + if (FAILED(hr = IDirectMusicPerformance8_ReferenceToMusicTime(performance, + time + duration, &next_time))) + return hr;
- return S_FALSE; + if ((hr = segment_state_play_until(This, performance, next_time, track_flags)) == S_FALSE) + { + MUSIC_TIME end_time = This->start_time + This->played; + return performance_send_segment_end(performance, end_time, iface, FALSE); }
- return S_OK; + return hr; }
HRESULT segment_state_play(IDirectMusicSegmentState *iface, IDirectMusicPerformance8 *performance)
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/segmentstate.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/dlls/dmime/segmentstate.c b/dlls/dmime/segmentstate.c index 6391f44fd9a..d2377807c43 100644 --- a/dlls/dmime/segmentstate.c +++ b/dlls/dmime/segmentstate.c @@ -53,6 +53,7 @@ struct segment_state MUSIC_TIME end_point; MUSIC_TIME played; BOOL auto_download; + DWORD repeats;
struct list tracks; }; @@ -234,6 +235,7 @@ HRESULT segment_state_create(IDirectMusicSegment *segment, MUSIC_TIME start_time This->start_time = start_time; if (SUCCEEDED(hr)) hr = IDirectMusicSegment_GetStartPoint(segment, &This->start_point); if (SUCCEEDED(hr)) hr = IDirectMusicSegment_GetLength(segment, &This->end_point); + if (SUCCEEDED(hr)) hr = IDirectMusicSegment_GetRepeats(segment, &This->repeats);
for (i = 0; SUCCEEDED(hr); i++) { @@ -310,10 +312,21 @@ static HRESULT segment_state_play_chunk(struct segment_state *This, IDirectMusic time + duration, &next_time))) return hr;
- if ((hr = segment_state_play_until(This, performance, next_time, track_flags)) == S_FALSE) + while ((hr = segment_state_play_until(This, performance, next_time, track_flags)) == S_FALSE) { - MUSIC_TIME end_time = This->start_time + This->played; - return performance_send_segment_end(performance, end_time, iface, FALSE); + if (!This->repeats) + { + MUSIC_TIME end_time = This->start_time + This->played; + return performance_send_segment_end(performance, end_time, iface, FALSE); + } + + if (FAILED(hr = IDirectMusicSegment_GetLoopPoints(This->segment, &This->played, + &This->end_point))) + break; + This->start_time += This->end_point - This->start_point; + This->repeats--; + + if (next_time <= This->start_time || This->end_point <= This->start_point) break; }
return hr;
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=139803
Your paranoid android.
=== debian11 (32 bit report) ===
dmime: dmime.c:3268: Test failed: got mtTime 88 dmime.c:3268: Test failed: got punkUser 033C0978 dmime.c:3268: Test failed: got dwNotificationOption 0x2 dmime.c:3275: Test failed: got mtTime 1538 dmime.c:3275: Test failed: got punkUser 033C0978 dmime.c:3275: Test failed: got guidNotificationType {d2ac2899-b39b-11d1-8704-00600893b1bd} dmime.c:3308: Test failed: got mtTime 1538 dmime.c:3308: Test failed: got punkUser 033C0978 dmime.c:3308: Test failed: got dwNotificationOption 0x1 dmime.c:3326: Test failed: got mtTime 1538 dmime.c:3326: Test failed: got punkUser 00000000 dmime.c:3326: Test failed: got guidNotificationType {81f75bc5-4e5d-11d2-bcc7-00a0c922e6eb} dmime.c:3326: Test failed: got dwNotificationOption 0x1 dmime.c:3333: Test failed: got dwType 0x3 dmime.c:3354: Test failed: got punkUser 033C09B8 dmime.c:3354: Test failed: got dwNotificationOption 0x4 dmime.c:3368: Test failed: got mtTime 1924
=== debian11 (32 bit ar:MA report) ===
dmime: dmime.c:3268: Test failed: got mtTime 88 dmime.c:3268: Test failed: got punkUser 033DF810 dmime.c:3268: Test failed: got dwNotificationOption 0x2 dmime.c:3275: Test failed: got mtTime 1538 dmime.c:3275: Test failed: got punkUser 033DF810 dmime.c:3275: Test failed: got guidNotificationType {d2ac2899-b39b-11d1-8704-00600893b1bd} dmime.c:3308: Test failed: got mtTime 1538 dmime.c:3308: Test failed: got punkUser 033DF810 dmime.c:3308: Test failed: got dwNotificationOption 0x1 dmime.c:3326: Test failed: got mtTime 1538 dmime.c:3326: Test failed: got punkUser 00000000 dmime.c:3326: Test failed: got guidNotificationType {81f75bc5-4e5d-11d2-bcc7-00a0c922e6eb} dmime.c:3326: Test failed: got dwNotificationOption 0x1 dmime.c:3333: Test failed: got dwType 0x3 dmime.c:3354: Test failed: got punkUser 033DF850 dmime.c:3354: Test failed: got dwNotificationOption 0x4 dmime.c:3368: Test failed: got mtTime 1923
=== debian11 (32 bit de report) ===
dmime: dmime.c:3268: Test failed: got mtTime 87 dmime.c:3268: Test failed: got punkUser 033DFFE8 dmime.c:3268: Test failed: got dwNotificationOption 0x2 dmime.c:3275: Test failed: got mtTime 1537 dmime.c:3275: Test failed: got punkUser 033DFFE8 dmime.c:3275: Test failed: got guidNotificationType {d2ac2899-b39b-11d1-8704-00600893b1bd} dmime.c:3308: Test failed: got mtTime 1537 dmime.c:3308: Test failed: got punkUser 033DFFE8 dmime.c:3308: Test failed: got dwNotificationOption 0x1 dmime.c:3326: Test failed: got mtTime 1537 dmime.c:3326: Test failed: got punkUser 00000000 dmime.c:3326: Test failed: got guidNotificationType {81f75bc5-4e5d-11d2-bcc7-00a0c922e6eb} dmime.c:3326: Test failed: got dwNotificationOption 0x1 dmime.c:3333: Test failed: got dwType 0x3 dmime.c:3354: Test failed: got punkUser 033E0028 dmime.c:3354: Test failed: got dwNotificationOption 0x4 dmime.c:3368: Test failed: got mtTime 1922
=== debian11 (32 bit fr report) ===
dmime: dmime.c:3268: Test failed: got mtTime 87 dmime.c:3268: Test failed: got punkUser 033E0978 dmime.c:3268: Test failed: got dwNotificationOption 0x2 dmime.c:3275: Test failed: got mtTime 1537 dmime.c:3275: Test failed: got punkUser 033E0978 dmime.c:3275: Test failed: got guidNotificationType {d2ac2899-b39b-11d1-8704-00600893b1bd} dmime.c:3308: Test failed: got mtTime 1537 dmime.c:3308: Test failed: got punkUser 033E0978 dmime.c:3308: Test failed: got dwNotificationOption 0x1 dmime.c:3326: Test failed: got mtTime 1537 dmime.c:3326: Test failed: got punkUser 00000000 dmime.c:3326: Test failed: got guidNotificationType {81f75bc5-4e5d-11d2-bcc7-00a0c922e6eb} dmime.c:3326: Test failed: got dwNotificationOption 0x1 dmime.c:3333: Test failed: got dwType 0x3 dmime.c:3354: Test failed: got punkUser 033E09B8 dmime.c:3354: Test failed: got dwNotificationOption 0x4 dmime.c:3368: Test failed: got mtTime 1922
=== debian11 (32 bit he:IL report) ===
dmime: dmime.c:3268: Test failed: got mtTime 88 dmime.c:3268: Test failed: got punkUser 033DF738 dmime.c:3268: Test failed: got dwNotificationOption 0x2 dmime.c:3275: Test failed: got mtTime 1538 dmime.c:3275: Test failed: got punkUser 033DF738 dmime.c:3275: Test failed: got guidNotificationType {d2ac2899-b39b-11d1-8704-00600893b1bd} dmime.c:3308: Test failed: got mtTime 1538 dmime.c:3308: Test failed: got punkUser 033DF738 dmime.c:3308: Test failed: got dwNotificationOption 0x1 dmime.c:3326: Test failed: got mtTime 1538 dmime.c:3326: Test failed: got punkUser 00000000 dmime.c:3326: Test failed: got guidNotificationType {81f75bc5-4e5d-11d2-bcc7-00a0c922e6eb} dmime.c:3326: Test failed: got dwNotificationOption 0x1 dmime.c:3333: Test failed: got dwType 0x3 dmime.c:3354: Test failed: got punkUser 033DF778 dmime.c:3354: Test failed: got dwNotificationOption 0x4 dmime.c:3368: Test failed: got mtTime 1924
=== debian11 (32 bit hi:IN report) ===
dmime: dmime.c:3268: Test failed: got mtTime 87 dmime.c:3268: Test failed: got punkUser 0339F738 dmime.c:3268: Test failed: got dwNotificationOption 0x2 dmime.c:3275: Test failed: got mtTime 1537 dmime.c:3275: Test failed: got punkUser 0339F738 dmime.c:3275: Test failed: got guidNotificationType {d2ac2899-b39b-11d1-8704-00600893b1bd} dmime.c:3308: Test failed: got mtTime 1537 dmime.c:3308: Test failed: got punkUser 0339F738 dmime.c:3308: Test failed: got dwNotificationOption 0x1 dmime.c:3326: Test failed: got mtTime 1537 dmime.c:3326: Test failed: got punkUser 00000000 dmime.c:3326: Test failed: got guidNotificationType {81f75bc5-4e5d-11d2-bcc7-00a0c922e6eb} dmime.c:3326: Test failed: got dwNotificationOption 0x1 dmime.c:3333: Test failed: got dwType 0x3 dmime.c:3354: Test failed: got punkUser 0339F778 dmime.c:3354: Test failed: got dwNotificationOption 0x4 dmime.c:3368: Test failed: got mtTime 1922
=== debian11 (32 bit ja:JP report) ===
dmime: dmime.c:3268: Test failed: got mtTime 87 dmime.c:3268: Test failed: got punkUser 034EF810 dmime.c:3268: Test failed: got dwNotificationOption 0x2 dmime.c:3275: Test failed: got mtTime 1537 dmime.c:3275: Test failed: got punkUser 034EF810 dmime.c:3275: Test failed: got guidNotificationType {d2ac2899-b39b-11d1-8704-00600893b1bd} dmime.c:3308: Test failed: got mtTime 1537 dmime.c:3308: Test failed: got punkUser 034EF810 dmime.c:3308: Test failed: got dwNotificationOption 0x1 dmime.c:3326: Test failed: got mtTime 1537 dmime.c:3326: Test failed: got punkUser 00000000 dmime.c:3326: Test failed: got guidNotificationType {81f75bc5-4e5d-11d2-bcc7-00a0c922e6eb} dmime.c:3326: Test failed: got dwNotificationOption 0x1 dmime.c:3333: Test failed: got dwType 0x3 dmime.c:3354: Test failed: got punkUser 034EF850 dmime.c:3354: Test failed: got dwNotificationOption 0x4 dmime.c:3368: Test failed: got mtTime 1923
=== debian11 (32 bit zh:CN report) ===
dmime: dmime.c:3268: Test failed: got mtTime 87 dmime.c:3268: Test failed: got punkUser 0340F810 dmime.c:3268: Test failed: got dwNotificationOption 0x2 dmime.c:3275: Test failed: got mtTime 1537 dmime.c:3275: Test failed: got punkUser 0340F810 dmime.c:3275: Test failed: got guidNotificationType {d2ac2899-b39b-11d1-8704-00600893b1bd} dmime.c:3308: Test failed: got mtTime 1537 dmime.c:3308: Test failed: got punkUser 0340F810 dmime.c:3308: Test failed: got dwNotificationOption 0x1 dmime.c:3326: Test failed: got mtTime 1537 dmime.c:3326: Test failed: got punkUser 00000000 dmime.c:3326: Test failed: got guidNotificationType {81f75bc5-4e5d-11d2-bcc7-00a0c922e6eb} dmime.c:3326: Test failed: got dwNotificationOption 0x1 dmime.c:3333: Test failed: got dwType 0x3 dmime.c:3354: Test failed: got punkUser 0340F850 dmime.c:3354: Test failed: got dwNotificationOption 0x4 dmime.c:3368: Test failed: got mtTime 1922
=== debian11b (32 bit WoW report) ===
dmime: dmime.c:3268: Test failed: got mtTime 88 dmime.c:3268: Test failed: got punkUser 03CDF460 dmime.c:3268: Test failed: got dwNotificationOption 0x2 dmime.c:3275: Test failed: got mtTime 1538 dmime.c:3275: Test failed: got punkUser 03CDF460 dmime.c:3275: Test failed: got guidNotificationType {d2ac2899-b39b-11d1-8704-00600893b1bd} dmime.c:3308: Test failed: got mtTime 1538 dmime.c:3308: Test failed: got punkUser 03CDF460 dmime.c:3308: Test failed: got dwNotificationOption 0x1 dmime.c:3326: Test failed: got mtTime 1538 dmime.c:3326: Test failed: got punkUser 00000000 dmime.c:3326: Test failed: got guidNotificationType {81f75bc5-4e5d-11d2-bcc7-00a0c922e6eb} dmime.c:3326: Test failed: got dwNotificationOption 0x1 dmime.c:3333: Test failed: got dwType 0x3 dmime.c:3354: Test failed: got punkUser 03CDF4A0 dmime.c:3354: Test failed: got dwNotificationOption 0x4 dmime.c:3368: Test failed: got mtTime 1924
=== debian11b (64 bit WoW report) ===
dmime: dmime.c:3268: Test failed: got mtTime 88 dmime.c:3268: Test failed: got punkUser 00007F8055D0F3F0 dmime.c:3268: Test failed: got dwNotificationOption 0x2 dmime.c:3275: Test failed: got mtTime 1538 dmime.c:3275: Test failed: got punkUser 00007F8055D0F3F0 dmime.c:3275: Test failed: got guidNotificationType {d2ac2899-b39b-11d1-8704-00600893b1bd} dmime.c:3308: Test failed: got mtTime 1538 dmime.c:3308: Test failed: got punkUser 00007F8055D0F3F0 dmime.c:3308: Test failed: got dwNotificationOption 0x1 dmime.c:3326: Test failed: got mtTime 1538 dmime.c:3326: Test failed: got punkUser 0000000000000000 dmime.c:3326: Test failed: got guidNotificationType {81f75bc5-4e5d-11d2-bcc7-00a0c922e6eb} dmime.c:3326: Test failed: got dwNotificationOption 0x1 dmime.c:3333: Test failed: got dwType 0x3 dmime.c:3354: Test failed: got punkUser 00007F8055D0F440 dmime.c:3354: Test failed: got dwNotificationOption 0x4 dmime.c:3368: Test failed: got mtTime 1925