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 7613b82c893..62f43c3c5f5 100644 --- a/dlls/dmime/tests/dmime.c +++ b/dlls/dmime/tests/dmime.c @@ -3290,6 +3290,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); + check_dmus_dirty_pmsg(msg, music_time + length); + 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 62f43c3c5f5..b731bf001e0 100644 --- a/dlls/dmime/tests/dmime.c +++ b/dlls/dmime/tests/dmime.c @@ -3318,14 +3318,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 | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
diff --git a/dlls/dmime/segmentstate.c b/dlls/dmime/segmentstate.c index 544620b0045..39a8874c724 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++) { @@ -284,6 +286,7 @@ static HRESULT segment_state_play_chunk(struct segment_state *This, IDirectMusic if (FAILED(hr = IDirectMusicPerformance8_ReferenceToMusicTime(performance, time + duration, &next_time))) return hr; +play_more: played = min(next_time - This->start_time, This->end_point - This->start_point);
LIST_FOR_EACH_ENTRY(entry, &This->tracks, struct track_entry, entry) @@ -303,6 +306,21 @@ static HRESULT segment_state_play_chunk(struct segment_state *This, IDirectMusic { MUSIC_TIME end_time = This->start_time + This->played;
+ if (This->repeats) + { + if (FAILED(hr = IDirectMusicSegment_GetLoopPoints(This->segment, + &This->played, &This->end_point))) + { + ERR("Failed to get segment loop points, hr %#lx\n", hr); + return hr; + } + This->start_time += This->end_point - This->start_point; + This->repeats--; + + if (next_time - This->start_time > 0 && This->end_point - This->start_point > 0) goto play_more; + return S_OK; + } + if (FAILED(hr = performance_send_segment_end(performance, end_time, iface, FALSE))) { ERR("Failed to send segment end, hr %#lx\n", 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=139747
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
dmime: dmime.c:3243: Test failed: got mtTime 1840 dmime.c:3243: Test failed: got punkUser 00D420D0 dmime.c:3250: Test failed: got mtTime 1840
=== w7u_adm (32 bit report) ===
dmime: dmime.c:3243: Test failed: got mtTime 1838 dmime.c:3243: Test failed: got punkUser 01702058 dmime.c:3250: Test failed: got mtTime 1838
=== w7u_el (32 bit report) ===
dmime: dmime.c:3243: Test failed: got punkUser 008B5128
=== w1064v1809 (32 bit report) ===
dmime: dmime.c:3243: Test failed: got mtTime 463 dmime.c:3243: Test failed: got punkUser 04125958 dmime.c:3250: Test failed: got mtTime 1845 dmime.c:3257: Test failed: got mtTime 1845
=== w1064_tsign (32 bit report) ===
dmime: dmime.c:3243: Test failed: got mtTime 463 dmime.c:3243: Test failed: got punkUser 04462888 dmime.c:3250: Test failed: got mtTime 1845 dmime.c:3257: Test failed: got mtTime 1845
=== w10pro64_en_AE_u8 (32 bit report) ===
dmime: dmime.c:3243: Test failed: got mtTime 464 dmime.c:3243: Test failed: got punkUser 044398B8
Looks like the tests don't pass on Windows, sorry, will fix.