-- v3: dmsynth: Use time instead of position to order events. dmsynth: Preserve event order when positions are equal. dmime: Requeue the note message instead of directly queueing MIDI note-off.
From: Anton Baskanov baskanov@gmail.com
--- dlls/dmime/performance.c | 68 ++++++++++++++++++++++++++++++---------- 1 file changed, 51 insertions(+), 17 deletions(-)
diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index f4504c4d36f..eccc1f83683 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -110,7 +110,44 @@ static void performance_queue_message(struct performance *This, struct message * list_add_after(&prev->entry, &message->entry); }
-static HRESULT performance_process_message(struct performance *This, DMUS_PMSG *msg, DWORD *timeout) +static struct message *performance_get_message(struct performance *This, DWORD *timeout) +{ + static const DWORD delivery_flags = DMUS_PMSGF_TOOL_IMMEDIATE | DMUS_PMSGF_TOOL_QUEUE | DMUS_PMSGF_TOOL_ATTIME; + IDirectMusicPerformance *performance = (IDirectMusicPerformance *)&This->IDirectMusicPerformance8_iface; + REFERENCE_TIME latency, offset = 0; + struct message *message; + struct list *ptr; + + if (!(ptr = list_head(&This->messages))) + return NULL; + message = LIST_ENTRY(ptr, struct message, entry); + + if (FAILED(IDirectMusicPerformance_GetLatencyTime(performance, &latency))) + return NULL; + + switch (message->msg.dwFlags & delivery_flags) + { + default: + WARN("No delivery flag found for message %p\n", &message->msg); + /* fallthrough */ + case DMUS_PMSGF_TOOL_IMMEDIATE: + break; + case DMUS_PMSGF_TOOL_QUEUE: + offset = This->dwBumperLength * 10000; + /* fallthrough */ + case DMUS_PMSGF_TOOL_ATTIME: + if (message->msg.rtTime >= offset && message->msg.rtTime - offset >= latency) + { + *timeout = (message->msg.rtTime - offset - latency) / 10000; + return NULL; + } + break; + } + + return message; +} + +static HRESULT performance_process_message(struct performance *This, DMUS_PMSG *msg) { static const DWORD delivery_flags = DMUS_PMSGF_TOOL_IMMEDIATE | DMUS_PMSGF_TOOL_QUEUE | DMUS_PMSGF_TOOL_ATTIME; IDirectMusicPerformance *performance = (IDirectMusicPerformance *)&This->IDirectMusicPerformance8_iface; @@ -137,10 +174,7 @@ static HRESULT performance_process_message(struct performance *This, DMUS_PMSG * /* fallthrough */ case DMUS_PMSGF_TOOL_ATTIME: if (msg->rtTime >= offset && msg->rtTime - offset >= latency) - { - if (timeout) *timeout = (msg->rtTime - offset - latency) / 10000; return DMUS_S_REQUEUE; - }
hr = IDirectMusicTool_ProcessPMsg(tool, performance, msg); break; @@ -155,8 +189,7 @@ static HRESULT performance_process_message(struct performance *This, DMUS_PMSG * static DWORD WINAPI message_thread_proc(void *args) { struct performance *This = args; - HRESULT hr = DMUS_S_REQUEUE; - struct list *ptr; + HRESULT hr;
TRACE("performance %p message thread\n", This); SetThreadDescription(GetCurrentThread(), L"wine_dmime_message"); @@ -166,20 +199,21 @@ static DWORD WINAPI message_thread_proc(void *args) while (This->message_thread) { DWORD timeout = INFINITE; + struct message *message; + struct list *next;
- while ((ptr = list_head(&This->messages))) + if (!(message = performance_get_message(This, &timeout))) { - struct message *message = LIST_ENTRY(ptr, struct message, entry); - struct list *next = ptr->next; - list_remove(&message->entry); - list_init(&message->entry); - - hr = performance_process_message(This, &message->msg, &timeout); - if (hr == DMUS_S_REQUEUE) performance_queue_message(This, message, next); - if (hr != S_OK) break; + SleepConditionVariableCS(&This->cond, &This->safe, timeout); + continue; } + next = message->entry.next; + + list_remove(&message->entry); + list_init(&message->entry);
- SleepConditionVariableCS(&This->cond, &This->safe, timeout); + hr = performance_process_message(This, &message->msg); + if (hr == DMUS_S_REQUEUE) performance_queue_message(This, message, next); }
LeaveCriticalSection(&This->safe); @@ -824,7 +858,7 @@ static HRESULT WINAPI performance_SendPMsg(IDirectMusicPerformance8 *iface, DMUS
if (msg->dwFlags & DMUS_PMSGF_TOOL_IMMEDIATE) { - hr = performance_process_message(This, &message->msg, NULL); + hr = performance_process_message(This, &message->msg); if (hr != DMUS_S_REQUEUE) goto done; }
From: Anton Baskanov baskanov@gmail.com
--- dlls/dmime/performance.c | 59 ++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 26 deletions(-)
diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index eccc1f83683..58a95e825d4 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -97,19 +97,6 @@ static inline struct message *message_from_DMUS_PMSG(DMUS_PMSG *msg) return msg ? CONTAINING_RECORD(msg, struct message, msg) : NULL; }
-static void performance_queue_message(struct performance *This, struct message *message, struct list *hint) -{ - struct message *prev; - - LIST_FOR_EACH_ENTRY_REV(prev, hint ? hint : &This->messages, struct message, entry) - { - if (&prev->entry == &This->messages) break; - if (prev->msg.rtTime <= message->msg.rtTime) break; - } - - list_add_after(&prev->entry, &message->entry); -} - static struct message *performance_get_message(struct performance *This, DWORD *timeout) { static const DWORD delivery_flags = DMUS_PMSGF_TOOL_IMMEDIATE | DMUS_PMSGF_TOOL_QUEUE | DMUS_PMSGF_TOOL_ATTIME; @@ -127,11 +114,6 @@ static struct message *performance_get_message(struct performance *This, DWORD *
switch (message->msg.dwFlags & delivery_flags) { - default: - WARN("No delivery flag found for message %p\n", &message->msg); - /* fallthrough */ - case DMUS_PMSGF_TOOL_IMMEDIATE: - break; case DMUS_PMSGF_TOOL_QUEUE: offset = This->dwBumperLength * 10000; /* fallthrough */ @@ -186,6 +168,38 @@ static HRESULT performance_process_message(struct performance *This, DMUS_PMSG * return hr; }
+static HRESULT performance_queue_message(struct performance *This, struct message *message, struct list *hint) +{ + static const DWORD delivery_flags = DMUS_PMSGF_TOOL_IMMEDIATE | DMUS_PMSGF_TOOL_QUEUE | DMUS_PMSGF_TOOL_ATTIME; + struct message *prev; + HRESULT hr; + + for (;;) + { + if ((message->msg.dwFlags & delivery_flags) == DMUS_PMSGF_TOOL_QUEUE) + break; + if ((message->msg.dwFlags & delivery_flags) == DMUS_PMSGF_TOOL_ATTIME) + break; + if ((message->msg.dwFlags & delivery_flags) != DMUS_PMSGF_TOOL_IMMEDIATE) + WARN("No delivery flag found for message %p\n", &message->msg); + + hr = performance_process_message(This, &message->msg); + if (hr == DMUS_S_REQUEUE) + continue; + return hr; + } + + LIST_FOR_EACH_ENTRY_REV(prev, hint ? hint : &This->messages, struct message, entry) + { + if (&prev->entry == &This->messages) break; + if (prev->msg.rtTime <= message->msg.rtTime) break; + } + + list_add_after(&prev->entry, &message->entry); + + return S_OK; +} + static DWORD WINAPI message_thread_proc(void *args) { struct performance *This = args; @@ -856,14 +870,7 @@ static HRESULT WINAPI performance_SendPMsg(IDirectMusicPerformance8 *iface, DMUS msg->dwFlags |= DMUS_PMSGF_REFTIME; }
- if (msg->dwFlags & DMUS_PMSGF_TOOL_IMMEDIATE) - { - hr = performance_process_message(This, &message->msg); - if (hr != DMUS_S_REQUEUE) goto done; - } - - performance_queue_message(This, message, NULL); - hr = S_OK; + hr = performance_queue_message(This, message, NULL); }
done:
From: Anton Baskanov baskanov@gmail.com
--- dlls/dmime/performance.c | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-)
diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index 58a95e825d4..35e6b90b74e 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -131,37 +131,13 @@ static struct message *performance_get_message(struct performance *This, DWORD *
static HRESULT performance_process_message(struct performance *This, DMUS_PMSG *msg) { - static const DWORD delivery_flags = DMUS_PMSGF_TOOL_IMMEDIATE | DMUS_PMSGF_TOOL_QUEUE | DMUS_PMSGF_TOOL_ATTIME; IDirectMusicPerformance *performance = (IDirectMusicPerformance *)&This->IDirectMusicPerformance8_iface; + IDirectMusicTool *tool; HRESULT hr;
- do - { - REFERENCE_TIME latency, offset = 0; - IDirectMusicTool *tool; - - if (FAILED(hr = IDirectMusicPerformance_GetLatencyTime(performance, &latency))) return hr; - if (!(tool = msg->pTool)) tool = &This->IDirectMusicTool_iface; + if (!(tool = msg->pTool)) tool = &This->IDirectMusicTool_iface;
- switch (msg->dwFlags & delivery_flags) - { - default: - WARN("No delivery flag found for message %p\n", msg); - /* fallthrough */ - case DMUS_PMSGF_TOOL_IMMEDIATE: - hr = IDirectMusicTool_ProcessPMsg(tool, performance, msg); - break; - case DMUS_PMSGF_TOOL_QUEUE: - offset = This->dwBumperLength * 10000; - /* fallthrough */ - case DMUS_PMSGF_TOOL_ATTIME: - if (msg->rtTime >= offset && msg->rtTime - offset >= latency) - return DMUS_S_REQUEUE; - - hr = IDirectMusicTool_ProcessPMsg(tool, performance, msg); - break; - } - } while (hr == DMUS_S_REQUEUE); + hr = IDirectMusicTool_ProcessPMsg(tool, performance, msg);
if (hr == DMUS_S_FREE) hr = IDirectMusicPerformance_FreePMsg(performance, msg); if (FAILED(hr)) WARN("Failed to process message, hr %#lx\n", hr);
From: Anton Baskanov baskanov@gmail.com
--- dlls/dmime/performance.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index 35e6b90b74e..01e0bad51b3 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -144,7 +144,7 @@ static HRESULT performance_process_message(struct performance *This, DMUS_PMSG * return hr; }
-static HRESULT performance_queue_message(struct performance *This, struct message *message, struct list *hint) +static HRESULT performance_queue_message(struct performance *This, struct message *message) { static const DWORD delivery_flags = DMUS_PMSGF_TOOL_IMMEDIATE | DMUS_PMSGF_TOOL_QUEUE | DMUS_PMSGF_TOOL_ATTIME; struct message *prev; @@ -165,7 +165,7 @@ static HRESULT performance_queue_message(struct performance *This, struct messag return hr; }
- LIST_FOR_EACH_ENTRY_REV(prev, hint ? hint : &This->messages, struct message, entry) + LIST_FOR_EACH_ENTRY_REV(prev, &This->messages, struct message, entry) { if (&prev->entry == &This->messages) break; if (prev->msg.rtTime <= message->msg.rtTime) break; @@ -190,20 +190,18 @@ static DWORD WINAPI message_thread_proc(void *args) { DWORD timeout = INFINITE; struct message *message; - struct list *next;
if (!(message = performance_get_message(This, &timeout))) { SleepConditionVariableCS(&This->cond, &This->safe, timeout); continue; } - next = message->entry.next;
list_remove(&message->entry); list_init(&message->entry);
hr = performance_process_message(This, &message->msg); - if (hr == DMUS_S_REQUEUE) performance_queue_message(This, message, next); + if (hr == DMUS_S_REQUEUE) performance_queue_message(This, message); }
LeaveCriticalSection(&This->safe); @@ -846,7 +844,7 @@ static HRESULT WINAPI performance_SendPMsg(IDirectMusicPerformance8 *iface, DMUS msg->dwFlags |= DMUS_PMSGF_REFTIME; }
- hr = performance_queue_message(This, message, NULL); + hr = performance_queue_message(This, message); }
done:
From: Anton Baskanov baskanov@gmail.com
--- dlls/dmime/tests/dmime.c | 70 ++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 35 deletions(-)
diff --git a/dlls/dmime/tests/dmime.c b/dlls/dmime/tests/dmime.c index e1d88c11d62..16a9a46df81 100644 --- a/dlls/dmime/tests/dmime.c +++ b/dlls/dmime/tests/dmime.c @@ -59,6 +59,41 @@ static void check_interface_(unsigned int line, void *iface_ptr, REFIID iid, BOO } }
+static double scale_music_time(MUSIC_TIME time, double tempo) +{ + return (600000000.0 * time) / (tempo * 768.0); +} + +#define check_dmus_note_pmsg(a, b, c, d, e, f) check_dmus_note_pmsg_(__LINE__, a, b, c, d, e, f) +static void check_dmus_note_pmsg_(int line, DMUS_NOTE_PMSG *msg, MUSIC_TIME time, UINT chan, + UINT duration, UINT key, UINT vel) +{ + ok_(__FILE__, line)(msg->dwSize == sizeof(*msg), "got dwSize %lu\n", msg->dwSize); + ok_(__FILE__, line)(!!msg->rtTime, "got rtTime %I64u\n", msg->rtTime); + ok_(__FILE__, line)(abs(msg->mtTime - time) < 10, "got mtTime %lu\n", msg->mtTime); + ok_(__FILE__, line)(msg->dwPChannel == chan, "got dwPChannel %lu\n", msg->dwPChannel); + ok_(__FILE__, line)(!!msg->dwVirtualTrackID, "got dwVirtualTrackID %lu\n", msg->dwVirtualTrackID); + ok_(__FILE__, line)(msg->dwType == DMUS_PMSGT_NOTE, "got %#lx\n", msg->dwType); + ok_(__FILE__, line)(!msg->dwVoiceID, "got dwVoiceID %lu\n", msg->dwVoiceID); + ok_(__FILE__, line)(msg->dwGroupID == 1, "got dwGroupID %lu\n", msg->dwGroupID); + ok_(__FILE__, line)(!msg->punkUser, "got punkUser %p\n", msg->punkUser); + ok_(__FILE__, line)(msg->mtDuration == duration, "got mtDuration %lu\n", msg->mtDuration); + ok_(__FILE__, line)(msg->wMusicValue == key, "got wMusicValue %u\n", msg->wMusicValue); + ok_(__FILE__, line)(!msg->wMeasure, "got wMeasure %u\n", msg->wMeasure); + /* FIXME: ok_(__FILE__, line)(!msg->nOffset, "got nOffset %u\n", msg->nOffset); */ + /* FIXME: ok_(__FILE__, line)(!msg->bBeat, "got bBeat %u\n", msg->bBeat); */ + /* FIXME: ok_(__FILE__, line)(!msg->bGrid, "got bGrid %u\n", msg->bGrid); */ + ok_(__FILE__, line)(msg->bVelocity == vel, "got bVelocity %u\n", msg->bVelocity); + ok_(__FILE__, line)(msg->bFlags == 1, "got bFlags %#x\n", msg->bFlags); + ok_(__FILE__, line)(!msg->bTimeRange, "got bTimeRange %u\n", msg->bTimeRange); + ok_(__FILE__, line)(!msg->bDurRange, "got bDurRange %u\n", msg->bDurRange); + ok_(__FILE__, line)(!msg->bVelRange, "got bVelRange %u\n", msg->bVelRange); + ok_(__FILE__, line)(!msg->bPlayModeFlags, "got bPlayModeFlags %#x\n", msg->bPlayModeFlags); + ok_(__FILE__, line)(!msg->bSubChordLevel, "got bSubChordLevel %u\n", msg->bSubChordLevel); + ok_(__FILE__, line)(msg->bMidiValue == key, "got bMidiValue %u\n", msg->bMidiValue); + ok_(__FILE__, line)(!msg->cTranspose, "got cTranspose %u\n", msg->cTranspose); +} + static void load_resource(const WCHAR *name, WCHAR *filename) { static WCHAR path[MAX_PATH]; @@ -2671,11 +2706,6 @@ static void test_performance_graph(void) IDirectMusicTool_Release(tool); }
-static double scale_music_time(MUSIC_TIME time, double tempo) -{ - return (600000000.0 * time) / (tempo * 768.0); -} - #define check_music_time(a, b) check_music_time_(__LINE__, a, b) static void check_music_time_(int line, MUSIC_TIME time, MUSIC_TIME expect) { @@ -3510,36 +3540,6 @@ static void test_wave_pmsg(void) IDirectMusicTool_Release(tool); }
-#define check_dmus_note_pmsg(a, b, c, d, e, f) check_dmus_note_pmsg_(__LINE__, a, b, c, d, e, f) -static void check_dmus_note_pmsg_(int line, DMUS_NOTE_PMSG *msg, MUSIC_TIME time, UINT chan, - UINT duration, UINT key, UINT vel) -{ - ok_(__FILE__, line)(msg->dwSize == sizeof(*msg), "got dwSize %lu\n", msg->dwSize); - ok_(__FILE__, line)(!!msg->rtTime, "got rtTime %I64u\n", msg->rtTime); - ok_(__FILE__, line)(abs(msg->mtTime - time) < 10, "got mtTime %lu\n", msg->mtTime); - ok_(__FILE__, line)(msg->dwPChannel == chan, "got dwPChannel %lu\n", msg->dwPChannel); - ok_(__FILE__, line)(!!msg->dwVirtualTrackID, "got dwVirtualTrackID %lu\n", msg->dwVirtualTrackID); - ok_(__FILE__, line)(msg->dwType == DMUS_PMSGT_NOTE, "got %#lx\n", msg->dwType); - ok_(__FILE__, line)(!msg->dwVoiceID, "got dwVoiceID %lu\n", msg->dwVoiceID); - ok_(__FILE__, line)(msg->dwGroupID == 1, "got dwGroupID %lu\n", msg->dwGroupID); - ok_(__FILE__, line)(!msg->punkUser, "got punkUser %p\n", msg->punkUser); - ok_(__FILE__, line)(msg->mtDuration == duration, "got mtDuration %lu\n", msg->mtDuration); - ok_(__FILE__, line)(msg->wMusicValue == key, "got wMusicValue %u\n", msg->wMusicValue); - ok_(__FILE__, line)(!msg->wMeasure, "got wMeasure %u\n", msg->wMeasure); - /* FIXME: ok_(__FILE__, line)(!msg->nOffset, "got nOffset %u\n", msg->nOffset); */ - /* FIXME: ok_(__FILE__, line)(!msg->bBeat, "got bBeat %u\n", msg->bBeat); */ - /* FIXME: ok_(__FILE__, line)(!msg->bGrid, "got bGrid %u\n", msg->bGrid); */ - ok_(__FILE__, line)(msg->bVelocity == vel, "got bVelocity %u\n", msg->bVelocity); - ok_(__FILE__, line)(msg->bFlags == 1, "got bFlags %#x\n", msg->bFlags); - ok_(__FILE__, line)(!msg->bTimeRange, "got bTimeRange %u\n", msg->bTimeRange); - ok_(__FILE__, line)(!msg->bDurRange, "got bDurRange %u\n", msg->bDurRange); - ok_(__FILE__, line)(!msg->bVelRange, "got bVelRange %u\n", msg->bVelRange); - ok_(__FILE__, line)(!msg->bPlayModeFlags, "got bPlayModeFlags %#x\n", msg->bPlayModeFlags); - ok_(__FILE__, line)(!msg->bSubChordLevel, "got bSubChordLevel %u\n", msg->bSubChordLevel); - ok_(__FILE__, line)(msg->bMidiValue == key, "got bMidiValue %u\n", msg->bMidiValue); - ok_(__FILE__, line)(!msg->cTranspose, "got cTranspose %u\n", msg->cTranspose); -} - static void test_sequence_track(void) { static const DWORD message_types[] =
From: Anton Baskanov baskanov@gmail.com
--- dlls/dmime/performance.c | 23 +++++++++++++++++----- dlls/dmime/tests/dmime.c | 42 ++++++++++++++++++++-------------------- 2 files changed, 39 insertions(+), 26 deletions(-)
diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index 01e0bad51b3..0e780e8fe8c 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -2062,12 +2062,25 @@ static HRESULT WINAPI performance_tool_ProcessPMsg(IDirectMusicTool *iface, DMUS_NOTE_PMSG *note = (DMUS_NOTE_PMSG *)msg;
msg->mtTime += note->nOffset; - if (FAILED(hr = performance_send_midi_pmsg(This, msg, DMUS_PMSGF_MUSICTIME | DMUS_PMSGF_TOOL_IMMEDIATE, - MIDI_NOTE_ON, note->bMidiValue, note->bVelocity))) - WARN("Failed to translate message to MIDI, hr %#lx\n", hr);
- msg->mtTime += note->mtDuration; - if (FAILED(hr = performance_send_midi_pmsg(This, msg, DMUS_PMSGF_MUSICTIME | DMUS_PMSGF_TOOL_QUEUE, + if (note->bFlags & DMUS_NOTEF_NOTEON) + { + if (FAILED(hr = performance_send_midi_pmsg(This, msg, DMUS_PMSGF_MUSICTIME | DMUS_PMSGF_TOOL_IMMEDIATE, + MIDI_NOTE_ON, note->bMidiValue, note->bVelocity))) + WARN("Failed to translate message to MIDI, hr %#lx\n", hr); + + if (note->mtDuration) + { + msg->mtTime -= note->nOffset; + msg->mtTime += max(1, note->mtDuration - 1); + if (FAILED(hr = IDirectMusicPerformance8_MusicToReferenceTime(performance, msg->mtTime, &msg->rtTime))) + return hr; + note->bFlags &= ~DMUS_NOTEF_NOTEON; + return DMUS_S_REQUEUE; + } + } + + if (FAILED(hr = performance_send_midi_pmsg(This, msg, DMUS_PMSGF_MUSICTIME | DMUS_PMSGF_TOOL_IMMEDIATE, MIDI_NOTE_OFF, note->bMidiValue, 0))) WARN("Failed to translate message to MIDI, hr %#lx\n", hr);
diff --git a/dlls/dmime/tests/dmime.c b/dlls/dmime/tests/dmime.c index 94f781d2796..b4b6d848fdc 100644 --- a/dlls/dmime/tests/dmime.c +++ b/dlls/dmime/tests/dmime.c @@ -65,13 +65,13 @@ static double scale_music_time(MUSIC_TIME time, double tempo) return (600000000.0 * time) / (tempo * 768.0); }
-#define check_dmus_note_pmsg(a, b, c, d, e, f, g, h, i) check_dmus_note_pmsg_(__LINE__, a, b, c, d, e, f, g, h, i) +#define check_dmus_note_pmsg(a, b, c, d, e, f, g) check_dmus_note_pmsg_(__LINE__, a, b, c, d, e, f, g) static void check_dmus_note_pmsg_(int line, DMUS_NOTE_PMSG *msg, MUSIC_TIME time, UINT chan, - UINT duration, UINT key, UINT vel, UINT flags, BOOL time_todo, BOOL flags_todo) + UINT duration, UINT key, UINT vel, UINT flags) { ok_(__FILE__, line)(msg->dwSize == sizeof(*msg), "got dwSize %lu\n", msg->dwSize); ok_(__FILE__, line)(!!msg->rtTime, "got rtTime %I64u\n", msg->rtTime); - todo_wine_if(time_todo) ok_(__FILE__, line)(abs(msg->mtTime - time) < 10, "got mtTime %lu\n", msg->mtTime); + ok_(__FILE__, line)(abs(msg->mtTime - time) < 10, "got mtTime %lu\n", msg->mtTime); ok_(__FILE__, line)(msg->dwPChannel == chan, "got dwPChannel %lu\n", msg->dwPChannel); ok_(__FILE__, line)(!!msg->dwVirtualTrackID, "got dwVirtualTrackID %lu\n", msg->dwVirtualTrackID); ok_(__FILE__, line)(msg->dwType == DMUS_PMSGT_NOTE, "got %#lx\n", msg->dwType); @@ -85,7 +85,7 @@ static void check_dmus_note_pmsg_(int line, DMUS_NOTE_PMSG *msg, MUSIC_TIME time /* FIXME: ok_(__FILE__, line)(!msg->bBeat, "got bBeat %u\n", msg->bBeat); */ /* FIXME: ok_(__FILE__, line)(!msg->bGrid, "got bGrid %u\n", msg->bGrid); */ ok_(__FILE__, line)(msg->bVelocity == vel, "got bVelocity %u\n", msg->bVelocity); - todo_wine_if(flags_todo) ok_(__FILE__, line)(msg->bFlags == flags, "got bFlags %#x\n", msg->bFlags); + ok_(__FILE__, line)(msg->bFlags == flags, "got bFlags %#x\n", msg->bFlags); ok_(__FILE__, line)(!msg->bTimeRange, "got bTimeRange %u\n", msg->bTimeRange); ok_(__FILE__, line)(!msg->bDurRange, "got bDurRange %u\n", msg->bDurRange); ok_(__FILE__, line)(!msg->bVelRange, "got bVelRange %u\n", msg->bVelRange); @@ -2633,11 +2633,11 @@ static void test_performance_tool(void)
*note = note60; hr = IDirectMusicTool_ProcessPMsg(tool, performance, (DMUS_PMSG *)note); - todo_wine ok(hr == DMUS_S_REQUEUE, "got %#lx\n", hr); - todo_wine ok(fabs(note->rtTime - note60.rtTime - scale_music_time(999, 120.0)) < 10.0, + ok(hr == DMUS_S_REQUEUE, "got %#lx\n", hr); + ok(fabs(note->rtTime - note60.rtTime - scale_music_time(999, 120.0)) < 10.0, "got %I64d\n", note->rtTime - note60.rtTime); - todo_wine ok(note->mtTime - note60.mtTime == 999, "got %ld\n", note->mtTime - note60.mtTime); - check_dmus_note_pmsg(note, note60.mtTime + 999, 0, 1000, 60, 127, 0, FALSE, TRUE); + ok(note->mtTime - note60.mtTime == 999, "got %ld\n", note->mtTime - note60.mtTime); + check_dmus_note_pmsg(note, note60.mtTime + 999, 0, 1000, 60, 127, 0);
hr = IDirectMusicPerformance_GetTime(performance, NULL, ¬e60.mtTime); ok(hr == S_OK, "got %#lx\n", hr); @@ -2647,11 +2647,11 @@ static void test_performance_tool(void) *note = note60; note->nOffset = 1000; hr = IDirectMusicTool_ProcessPMsg(tool, performance, (DMUS_PMSG *)note); - todo_wine ok(hr == DMUS_S_REQUEUE, "got %#lx\n", hr); - todo_wine ok(fabs(note->rtTime - note60.rtTime - scale_music_time(999, 120.0)) < 10.0, + ok(hr == DMUS_S_REQUEUE, "got %#lx\n", hr); + ok(fabs(note->rtTime - note60.rtTime - scale_music_time(999, 120.0)) < 10.0, "got %I64d\n", note->rtTime - note60.rtTime); - todo_wine ok(note->mtTime - note60.mtTime == 999, "got %ld\n", note->mtTime - note60.mtTime); - check_dmus_note_pmsg(note, note60.mtTime + 999, 0, 1000, 60, 127, 0, TRUE, TRUE); + ok(note->mtTime - note60.mtTime == 999, "got %ld\n", note->mtTime - note60.mtTime); + check_dmus_note_pmsg(note, note60.mtTime + 999, 0, 1000, 60, 127, 0);
hr = IDirectMusicPerformance_GetTime(performance, NULL, ¬e60.mtTime); ok(hr == S_OK, "got %#lx\n", hr); @@ -2661,11 +2661,11 @@ static void test_performance_tool(void) *note = note60; note->mtDuration = 2; hr = IDirectMusicTool_ProcessPMsg(tool, performance, (DMUS_PMSG *)note); - todo_wine ok(hr == DMUS_S_REQUEUE, "got %#lx\n", hr); - todo_wine ok(fabs(note->rtTime - note60.rtTime - scale_music_time(1, 120.0)) < 10.0, + ok(hr == DMUS_S_REQUEUE, "got %#lx\n", hr); + ok(fabs(note->rtTime - note60.rtTime - scale_music_time(1, 120.0)) < 10.0, "got %I64d\n", note->rtTime - note60.rtTime); - todo_wine ok(note->mtTime - note60.mtTime == 1, "got %ld\n", note->mtTime - note60.mtTime); - check_dmus_note_pmsg(note, note60.mtTime + 1, 0, 2, 60, 127, 0, FALSE, TRUE); + ok(note->mtTime - note60.mtTime == 1, "got %ld\n", note->mtTime - note60.mtTime); + check_dmus_note_pmsg(note, note60.mtTime + 1, 0, 2, 60, 127, 0);
hr = IDirectMusicPerformance_GetTime(performance, NULL, ¬e60.mtTime); ok(hr == S_OK, "got %#lx\n", hr); @@ -2675,11 +2675,11 @@ static void test_performance_tool(void) *note = note60; note->mtDuration = 1; hr = IDirectMusicTool_ProcessPMsg(tool, performance, (DMUS_PMSG *)note); - todo_wine ok(hr == DMUS_S_REQUEUE, "got %#lx\n", hr); - todo_wine ok(fabs(note->rtTime - note60.rtTime - scale_music_time(1, 120.0)) < 10.0, + ok(hr == DMUS_S_REQUEUE, "got %#lx\n", hr); + ok(fabs(note->rtTime - note60.rtTime - scale_music_time(1, 120.0)) < 10.0, "got %I64d\n", note->rtTime - note60.rtTime); ok(note->mtTime - note60.mtTime == 1, "got %ld\n", note->mtTime - note60.mtTime); - check_dmus_note_pmsg(note, note60.mtTime + 1, 0, 1, 60, 127, 0, FALSE, TRUE); + check_dmus_note_pmsg(note, note60.mtTime + 1, 0, 1, 60, 127, 0);
hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)note); ok(hr == S_OK, "got %#lx\n", hr); @@ -3763,13 +3763,13 @@ static void test_sequence_track(void)
ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)¬e); ok(!ret, "got %#lx\n", ret); - check_dmus_note_pmsg(note, 0, 0, 500, 60, 120, DMUS_NOTEF_NOTEON, FALSE, FALSE); + check_dmus_note_pmsg(note, 0, 0, 500, 60, 120, DMUS_NOTEF_NOTEON); 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); ok(!ret, "got %#lx\n", ret); - check_dmus_note_pmsg(note, 1000, 1, 200, 50, 100, DMUS_NOTEF_NOTEON, FALSE, FALSE); + check_dmus_note_pmsg(note, 1000, 1, 200, 50, 100, DMUS_NOTEF_NOTEON); hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)note); ok(hr == S_OK, "got %#lx\n", hr);
From: Anton Baskanov baskanov@gmail.com
--- dlls/dmime/tests/dmime.c | 118 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 112 insertions(+), 6 deletions(-)
diff --git a/dlls/dmime/tests/dmime.c b/dlls/dmime/tests/dmime.c index 16a9a46df81..94f781d2796 100644 --- a/dlls/dmime/tests/dmime.c +++ b/dlls/dmime/tests/dmime.c @@ -19,6 +19,7 @@ #define COBJMACROS
#include <stdarg.h> +#include <math.h> #include <windef.h> #include <wine/test.h> #include <initguid.h> @@ -64,13 +65,13 @@ static double scale_music_time(MUSIC_TIME time, double tempo) return (600000000.0 * time) / (tempo * 768.0); }
-#define check_dmus_note_pmsg(a, b, c, d, e, f) check_dmus_note_pmsg_(__LINE__, a, b, c, d, e, f) +#define check_dmus_note_pmsg(a, b, c, d, e, f, g, h, i) check_dmus_note_pmsg_(__LINE__, a, b, c, d, e, f, g, h, i) static void check_dmus_note_pmsg_(int line, DMUS_NOTE_PMSG *msg, MUSIC_TIME time, UINT chan, - UINT duration, UINT key, UINT vel) + UINT duration, UINT key, UINT vel, UINT flags, BOOL time_todo, BOOL flags_todo) { ok_(__FILE__, line)(msg->dwSize == sizeof(*msg), "got dwSize %lu\n", msg->dwSize); ok_(__FILE__, line)(!!msg->rtTime, "got rtTime %I64u\n", msg->rtTime); - ok_(__FILE__, line)(abs(msg->mtTime - time) < 10, "got mtTime %lu\n", msg->mtTime); + todo_wine_if(time_todo) ok_(__FILE__, line)(abs(msg->mtTime - time) < 10, "got mtTime %lu\n", msg->mtTime); ok_(__FILE__, line)(msg->dwPChannel == chan, "got dwPChannel %lu\n", msg->dwPChannel); ok_(__FILE__, line)(!!msg->dwVirtualTrackID, "got dwVirtualTrackID %lu\n", msg->dwVirtualTrackID); ok_(__FILE__, line)(msg->dwType == DMUS_PMSGT_NOTE, "got %#lx\n", msg->dwType); @@ -84,7 +85,7 @@ static void check_dmus_note_pmsg_(int line, DMUS_NOTE_PMSG *msg, MUSIC_TIME time /* FIXME: ok_(__FILE__, line)(!msg->bBeat, "got bBeat %u\n", msg->bBeat); */ /* FIXME: ok_(__FILE__, line)(!msg->bGrid, "got bGrid %u\n", msg->bGrid); */ ok_(__FILE__, line)(msg->bVelocity == vel, "got bVelocity %u\n", msg->bVelocity); - ok_(__FILE__, line)(msg->bFlags == 1, "got bFlags %#x\n", msg->bFlags); + todo_wine_if(flags_todo) ok_(__FILE__, line)(msg->bFlags == flags, "got bFlags %#x\n", msg->bFlags); ok_(__FILE__, line)(!msg->bTimeRange, "got bTimeRange %u\n", msg->bTimeRange); ok_(__FILE__, line)(!msg->bDurRange, "got bDurRange %u\n", msg->bDurRange); ok_(__FILE__, line)(!msg->bVelRange, "got bVelRange %u\n", msg->bVelRange); @@ -2546,10 +2547,25 @@ static void test_performance_pchannel(void)
static void test_performance_tool(void) { + DMUS_NOTE_PMSG note60 = + { + .dwSize = sizeof(DMUS_NOTE_PMSG), + .dwFlags = DMUS_PMSGF_REFTIME | DMUS_PMSGF_MUSICTIME | DMUS_PMSGF_TOOL_QUEUE, + .dwVirtualTrackID = 1, + .dwType = DMUS_PMSGT_NOTE, + .dwGroupID = 1, + .mtDuration = 1000, + .wMusicValue = 60, + .bVelocity = 127, + .bFlags = DMUS_NOTEF_NOTEON, + .bPlayModeFlags = DMUS_PLAYMODE_FIXED, + .bMidiValue = 60, + }; IDirectMusicPerformance *performance; IDirectMusicGraph *graph; IDirectMusicTool *tool; DWORD value, types[1]; + DMUS_NOTE_PMSG *note; DMUS_PMSG msg = {0}; HRESULT hr;
@@ -2581,6 +2597,96 @@ static void test_performance_tool(void) hr = IDirectMusicTool_Flush(tool, performance, &msg, 0); todo_wine ok(hr == S_OK, "got %#lx\n", hr);
+ hr = IDirectMusicPerformance_Init(performance, NULL, NULL, NULL); + ok(hr == S_OK, "got %#lx\n", hr); + + hr = IDirectMusicPerformance_AddPort(performance, NULL); + ok(hr == S_OK, "got %#lx\n", hr); + + hr = IDirectMusicPerformance_AllocPMsg(performance, sizeof(DMUS_NOTE_PMSG), (DMUS_PMSG **)¬e); + ok(hr == S_OK, "got %#lx\n", hr); + + hr = IDirectMusicPerformance_GetTime(performance, NULL, ¬e60.mtTime); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IDirectMusicPerformance_MusicToReferenceTime(performance, note60.mtTime, ¬e60.rtTime); + ok(hr == S_OK, "got %#lx\n", hr); + + *note = note60; + note->bFlags = 0; + hr = IDirectMusicTool_ProcessPMsg(tool, performance, (DMUS_PMSG *)note); + ok(hr == DMUS_S_FREE, "got %#lx\n", hr); + + hr = IDirectMusicPerformance_GetTime(performance, NULL, ¬e60.mtTime); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IDirectMusicPerformance_MusicToReferenceTime(performance, note60.mtTime, ¬e60.rtTime); + ok(hr == S_OK, "got %#lx\n", hr); + + *note = note60; + note->mtDuration = 0; + hr = IDirectMusicTool_ProcessPMsg(tool, performance, (DMUS_PMSG *)note); + ok(hr == DMUS_S_FREE, "got %#lx\n", hr); + + hr = IDirectMusicPerformance_GetTime(performance, NULL, ¬e60.mtTime); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IDirectMusicPerformance_MusicToReferenceTime(performance, note60.mtTime, ¬e60.rtTime); + ok(hr == S_OK, "got %#lx\n", hr); + + *note = note60; + hr = IDirectMusicTool_ProcessPMsg(tool, performance, (DMUS_PMSG *)note); + todo_wine ok(hr == DMUS_S_REQUEUE, "got %#lx\n", hr); + todo_wine ok(fabs(note->rtTime - note60.rtTime - scale_music_time(999, 120.0)) < 10.0, + "got %I64d\n", note->rtTime - note60.rtTime); + todo_wine ok(note->mtTime - note60.mtTime == 999, "got %ld\n", note->mtTime - note60.mtTime); + check_dmus_note_pmsg(note, note60.mtTime + 999, 0, 1000, 60, 127, 0, FALSE, TRUE); + + hr = IDirectMusicPerformance_GetTime(performance, NULL, ¬e60.mtTime); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IDirectMusicPerformance_MusicToReferenceTime(performance, note60.mtTime, ¬e60.rtTime); + ok(hr == S_OK, "got %#lx\n", hr); + + *note = note60; + note->nOffset = 1000; + hr = IDirectMusicTool_ProcessPMsg(tool, performance, (DMUS_PMSG *)note); + todo_wine ok(hr == DMUS_S_REQUEUE, "got %#lx\n", hr); + todo_wine ok(fabs(note->rtTime - note60.rtTime - scale_music_time(999, 120.0)) < 10.0, + "got %I64d\n", note->rtTime - note60.rtTime); + todo_wine ok(note->mtTime - note60.mtTime == 999, "got %ld\n", note->mtTime - note60.mtTime); + check_dmus_note_pmsg(note, note60.mtTime + 999, 0, 1000, 60, 127, 0, TRUE, TRUE); + + hr = IDirectMusicPerformance_GetTime(performance, NULL, ¬e60.mtTime); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IDirectMusicPerformance_MusicToReferenceTime(performance, note60.mtTime, ¬e60.rtTime); + ok(hr == S_OK, "got %#lx\n", hr); + + *note = note60; + note->mtDuration = 2; + hr = IDirectMusicTool_ProcessPMsg(tool, performance, (DMUS_PMSG *)note); + todo_wine ok(hr == DMUS_S_REQUEUE, "got %#lx\n", hr); + todo_wine ok(fabs(note->rtTime - note60.rtTime - scale_music_time(1, 120.0)) < 10.0, + "got %I64d\n", note->rtTime - note60.rtTime); + todo_wine ok(note->mtTime - note60.mtTime == 1, "got %ld\n", note->mtTime - note60.mtTime); + check_dmus_note_pmsg(note, note60.mtTime + 1, 0, 2, 60, 127, 0, FALSE, TRUE); + + hr = IDirectMusicPerformance_GetTime(performance, NULL, ¬e60.mtTime); + ok(hr == S_OK, "got %#lx\n", hr); + hr = IDirectMusicPerformance_MusicToReferenceTime(performance, note60.mtTime, ¬e60.rtTime); + ok(hr == S_OK, "got %#lx\n", hr); + + *note = note60; + note->mtDuration = 1; + hr = IDirectMusicTool_ProcessPMsg(tool, performance, (DMUS_PMSG *)note); + todo_wine ok(hr == DMUS_S_REQUEUE, "got %#lx\n", hr); + todo_wine ok(fabs(note->rtTime - note60.rtTime - scale_music_time(1, 120.0)) < 10.0, + "got %I64d\n", note->rtTime - note60.rtTime); + ok(note->mtTime - note60.mtTime == 1, "got %ld\n", note->mtTime - note60.mtTime); + check_dmus_note_pmsg(note, note60.mtTime + 1, 0, 1, 60, 127, 0, FALSE, TRUE); + + hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)note); + ok(hr == S_OK, "got %#lx\n", hr); + + hr = IDirectMusicPerformance_CloseDown(performance); + ok(hr == S_OK, "got %#lx\n", hr); + IDirectMusicGraph_Release(graph); IDirectMusicTool_Release(tool);
@@ -3657,13 +3763,13 @@ static void test_sequence_track(void)
ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)¬e); ok(!ret, "got %#lx\n", ret); - check_dmus_note_pmsg(note, 0, 0, 500, 60, 120); + check_dmus_note_pmsg(note, 0, 0, 500, 60, 120, DMUS_NOTEF_NOTEON, FALSE, FALSE); 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); ok(!ret, "got %#lx\n", ret); - check_dmus_note_pmsg(note, 1000, 1, 200, 50, 100); + check_dmus_note_pmsg(note, 1000, 1, 200, 50, 100, DMUS_NOTEF_NOTEON, FALSE, FALSE); hr = IDirectMusicPerformance_FreePMsg(performance, (DMUS_PMSG *)note); ok(hr == S_OK, "got %#lx\n", hr);
From: Anton Baskanov baskanov@gmail.com
Fixes hanging notes that occur when noteon gets reordered with noteoff. --- dlls/dmsynth/synth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/dmsynth/synth.c b/dlls/dmsynth/synth.c index bbe77e43cc9..222481c8769 100644 --- a/dlls/dmsynth/synth.c +++ b/dlls/dmsynth/synth.c @@ -977,7 +977,7 @@ static HRESULT WINAPI synth_PlayBuffer(IDirectMusicSynth8 *iface,
EnterCriticalSection(&This->cs); LIST_FOR_EACH_ENTRY(next_event, &This->events, struct event, entry) - if (next_event->position >= event->position) break; + if (next_event->position > event->position) break; list_add_before(&next_event->entry, &event->entry); LeaveCriticalSection(&This->cs); }
From: Anton Baskanov baskanov@gmail.com
Different time values can map to the same position. --- 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 222481c8769..3eed05f35a0 100644 --- a/dlls/dmsynth/synth.c +++ b/dlls/dmsynth/synth.c @@ -322,6 +322,7 @@ struct preset struct event { struct list entry; + REFERENCE_TIME time; LONGLONG position; BYTE midi[3]; }; @@ -973,11 +974,12 @@ static HRESULT WINAPI synth_PlayBuffer(IDirectMusicSynth8 *iface, { if (!(event = calloc(1, sizeof(*event)))) return E_OUTOFMEMORY; memcpy(event->midi, data, head->cbEvent); + event->time = time + head->rtDelta; event->position = position;
EnterCriticalSection(&This->cs); LIST_FOR_EACH_ENTRY(next_event, &This->events, struct event, entry) - if (next_event->position > event->position) break; + if (next_event->time > event->time) break; list_add_before(&next_event->entry, &event->entry); LeaveCriticalSection(&This->cs); }
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=140164
Your paranoid android.
=== w8 (32 bit report) ===
dmime: dmime.c:3469: Test failed: got dwType 0x3 dmime.c:3490: Test failed: got mtTime 3402 dmime.c:3490: Test failed: got punkUser 036067C0 dmime.c:3504: Test failed: got mtTime 4938
Rémi Bernon (@rbernon) commented about dlls/dmime/performance.c:
+static HRESULT performance_queue_message(struct performance *This, struct message *message, struct list *hint) +{
- static const DWORD delivery_flags = DMUS_PMSGF_TOOL_IMMEDIATE | DMUS_PMSGF_TOOL_QUEUE | DMUS_PMSGF_TOOL_ATTIME;
- struct message *prev;
- HRESULT hr;
- for (;;)
- {
if ((message->msg.dwFlags & delivery_flags) == DMUS_PMSGF_TOOL_QUEUE)
break;
if ((message->msg.dwFlags & delivery_flags) == DMUS_PMSGF_TOOL_ATTIME)
break;
if ((message->msg.dwFlags & delivery_flags) != DMUS_PMSGF_TOOL_IMMEDIATE)
WARN("No delivery flag found for message %p\n", &message->msg);
```suggestion:-6+0 if ((message->msg.dwFlags & delivery_flags) != DMUS_PMSGF_TOOL_IMMEDIATE) break; ```
(I'm not sure the WARN really matter here, but if it does maybe it could go into the performance_get_message switch?)
Looks good otherwise.