From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmband/bandtrack.c | 4 ++-- dlls/dmime/dmime_private.h | 2 +- dlls/dmime/performance.c | 2 +- dlls/dmime/segmentstate.c | 17 ++++++++++++++--- 4 files changed, 18 insertions(+), 7 deletions(-)
diff --git a/dlls/dmband/bandtrack.c b/dlls/dmband/bandtrack.c index e0acb6ff62d..5229204b284 100644 --- a/dlls/dmband/bandtrack.c +++ b/dlls/dmband/bandtrack.c @@ -234,7 +234,7 @@ static HRESULT WINAPI band_track_SetParam(IDirectMusicTrack8 *iface, REFGUID typ band_connect_to_collection(entry->band, param); } else if (IsEqualGUID(type, &GUID_Disable_Auto_Download)) - FIXME("GUID_Disable_Auto_Download not handled yet\n"); + This->header.bAutoDownload = FALSE; else if (IsEqualGUID(type, &GUID_Download)) FIXME("GUID_Download not handled yet\n"); else if (IsEqualGUID(type, &GUID_DownloadToAudioPath)) @@ -265,7 +265,7 @@ static HRESULT WINAPI band_track_SetParam(IDirectMusicTrack8 *iface, REFGUID typ IDirectMusicPerformance_Release(performance); } else if (IsEqualGUID(type, &GUID_Enable_Auto_Download)) - FIXME("GUID_Enable_Auto_Download not handled yet\n"); + This->header.bAutoDownload = TRUE; else if (IsEqualGUID(type, &GUID_IDirectMusicBand)) FIXME("GUID_IDirectMusicBand not handled yet\n"); else if (IsEqualGUID(type, &GUID_StandardMIDIFile)) diff --git a/dlls/dmime/dmime_private.h b/dlls/dmime/dmime_private.h index c1f777f3949..7f1937eaa0f 100644 --- a/dlls/dmime/dmime_private.h +++ b/dlls/dmime/dmime_private.h @@ -75,7 +75,7 @@ extern void set_audiopath_primary_dsound_buffer(IDirectMusicAudioPath*,IDirectSo extern HRESULT segment_state_create(IDirectMusicSegment *segment, MUSIC_TIME start_time, IDirectMusicPerformance *performance, IDirectMusicSegmentState **ret_iface); extern HRESULT segment_state_play(IDirectMusicSegmentState *iface, IDirectMusicPerformance *performance); -extern HRESULT segment_state_end_play(IDirectMusicSegmentState *iface); +extern HRESULT segment_state_end_play(IDirectMusicSegmentState *iface, IDirectMusicPerformance *performance);
extern HRESULT wave_track_create_from_chunk(IStream *stream, struct chunk_entry *parent, IDirectMusicTrack8 **ret_iface); diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index dc6ef575713..ea2a3cc52dd 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -1740,7 +1740,7 @@ static HRESULT WINAPI performance_tool_ProcessPMsg(IDirectMusicTool *iface, if (IsEqualGUID(¬if->guidNotificationType, &GUID_NOTIFICATION_SEGMENT) && notif->dwNotificationOption == DMUS_NOTIFICATION_SEGEND) { - if (FAILED(hr = segment_state_end_play((IDirectMusicSegmentState *)notif->punkUser))) + if (FAILED(hr = segment_state_end_play((IDirectMusicSegmentState *)notif->punkUser, performance))) WARN("Failed to end segment state %p, hr %#lx\n", notif->punkUser, hr); }
diff --git a/dlls/dmime/segmentstate.c b/dlls/dmime/segmentstate.c index 1cb9daac69a..c43d833fedd 100644 --- a/dlls/dmime/segmentstate.c +++ b/dlls/dmime/segmentstate.c @@ -51,6 +51,7 @@ struct segment_state MUSIC_TIME start_time; MUSIC_TIME start_point; MUSIC_TIME end_point; + BOOL auto_download;
struct list tracks; }; @@ -103,7 +104,7 @@ static ULONG WINAPI segment_state_Release(IDirectMusicSegmentState8 *iface)
if (!ref) { - segment_state_end_play((IDirectMusicSegmentState *)iface); + segment_state_end_play((IDirectMusicSegmentState *)iface, NULL); if (This->segment) IDirectMusicSegment_Release(This->segment); free(This); } @@ -224,8 +225,13 @@ HRESULT segment_state_create(IDirectMusicSegment *segment, MUSIC_TIME start_time This->segment = segment; IDirectMusicSegment_AddRef(This->segment);
+ if (SUCCEEDED(hr = IDirectMusicPerformance_GetGlobalParam(performance, &GUID_PerfAutoDownload, + &This->auto_download, sizeof(This->auto_download))) && This->auto_download) + hr = IDirectMusicSegment_SetParam(segment, &GUID_DownloadToAudioPath, -1, + DMUS_SEG_ALLTRACKS, 0, performance); + This->start_time = start_time; - hr = IDirectMusicSegment_GetStartPoint(segment, &This->start_point); + if (SUCCEEDED(hr)) hr = IDirectMusicSegment_GetStartPoint(segment, &This->start_point); if (SUCCEEDED(hr)) hr = IDirectMusicSegment_GetLength(segment, &This->end_point);
for (i = 0; SUCCEEDED(hr); i++) @@ -283,10 +289,11 @@ HRESULT segment_state_play(IDirectMusicSegmentState *iface, IDirectMusicPerforma return hr; }
-HRESULT segment_state_end_play(IDirectMusicSegmentState *iface) +HRESULT segment_state_end_play(IDirectMusicSegmentState *iface, IDirectMusicPerformance *performance) { struct segment_state *This = impl_from_IDirectMusicSegmentState8((IDirectMusicSegmentState8 *)iface); struct track_entry *entry, *next; + HRESULT hr;
LIST_FOR_EACH_ENTRY_SAFE(entry, next, &This->tracks, struct track_entry, entry) { @@ -294,5 +301,9 @@ HRESULT segment_state_end_play(IDirectMusicSegmentState *iface) track_entry_destroy(entry); }
+ if (performance && This->auto_download && FAILED(hr = IDirectMusicSegment_SetParam(This->segment, + &GUID_UnloadFromAudioPath, -1, DMUS_SEG_ALLTRACKS, 0, performance))) + ERR("Failed to unload segment from performance, hr %#lx\n", hr); + return S_OK; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmband/band.c | 8 ++++++++ 1 file changed, 8 insertions(+)
diff --git a/dlls/dmband/band.c b/dlls/dmband/band.c index 456bb20143e..4c593741516 100644 --- a/dlls/dmband/band.c +++ b/dlls/dmband/band.c @@ -496,6 +496,7 @@ HRESULT band_send_messages(IDirectMusicBand *iface, IDirectMusicPerformance *per
LIST_FOR_EACH_ENTRY_REV(entry, &This->instruments, struct instrument_entry, entry) { + DWORD patch = entry->instrument.dwPatch; DMUS_PATCH_PMSG *msg;
if (FAILED(hr = IDirectMusicPerformance_AllocPMsg(performance, sizeof(*msg), @@ -510,6 +511,13 @@ HRESULT band_send_messages(IDirectMusicBand *iface, IDirectMusicPerformance *per msg->dwGroupID = 1; msg->byInstrument = entry->instrument.dwPatch;
+ msg->byInstrument = patch & 0x7F; + patch >>= 8; + msg->byLSB = patch & 0x7f; + patch >>= 8; + msg->byMSB = patch & 0x7f; + patch >>= 8; + if (FAILED(hr = IDirectMusicGraph_StampPMsg(graph, (DMUS_PMSG *)msg)) || FAILED(hr = IDirectMusicPerformance_SendPMsg(performance, (DMUS_PMSG *)msg))) {
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/segment.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/dlls/dmime/segment.c b/dlls/dmime/segment.c index fc277ba73f9..280abaa004c 100644 --- a/dlls/dmime/segment.c +++ b/dlls/dmime/segment.c @@ -403,8 +403,11 @@ static HRESULT WINAPI segment_SetParam(IDirectMusicSegment8 *iface, REFGUID type
LIST_FOR_EACH_ENTRY(entry, &This->tracks, struct track_entry, entry) { - if (group != -1 && !(group & entry->dwGroupBits)) continue; - if (index != DMUS_SEG_ALLTRACKS && index--) continue; + if (group != -1) + { + if (!(group & entry->dwGroupBits)) continue; + if (index != DMUS_SEG_ALLTRACKS && index--) continue; + }
hr = IDirectMusicTrack_IsParamSupported(entry->pTrack, type); if (hr == DMUS_E_TYPE_UNSUPPORTED) continue;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/segment.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/dlls/dmime/segment.c b/dlls/dmime/segment.c index 280abaa004c..d7402911f00 100644 --- a/dlls/dmime/segment.c +++ b/dlls/dmime/segment.c @@ -409,11 +409,9 @@ static HRESULT WINAPI segment_SetParam(IDirectMusicSegment8 *iface, REFGUID type if (index != DMUS_SEG_ALLTRACKS && index--) continue; }
- hr = IDirectMusicTrack_IsParamSupported(entry->pTrack, type); - if (hr == DMUS_E_TYPE_UNSUPPORTED) continue; - - hr = IDirectMusicTrack_SetParam(entry->pTrack, type, music_time, param); - if (FAILED(hr)) break; + if (SUCCEEDED(hr = IDirectMusicTrack_IsParamSupported(entry->pTrack, type)) + && FAILED(hr = IDirectMusicTrack_SetParam(entry->pTrack, type, music_time, param))) + WARN("SetParam for track %p failed, hr %#lx\n", entry->pTrack, hr); }
return S_OK;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/performance.c | 1 + 1 file changed, 1 insertion(+)
diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index ea2a3cc52dd..8ea01b168d7 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -1700,6 +1700,7 @@ 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_REFTIME | DMUS_PMSGF_MUSICTIME | DMUS_PMSGF_TOOL_IMMEDIATE, 0x90 /* NOTE_ON */, note->bMidiValue, note->bVelocity))) WARN("Failed to translate message to MIDI, hr %#lx\n", hr);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/performance.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)
diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index f120cc6f0a9..815e8295ed8 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -1714,6 +1714,27 @@ static HRESULT WINAPI performance_tool_ProcessPMsg(IDirectMusicTool *iface, break; }
+ case DMUS_PMSGT_CURVE: + { + DMUS_CURVE_PMSG *curve = (DMUS_CURVE_PMSG *)msg; + + msg->mtTime += curve->nOffset; + switch (curve->dwType) + { + case DMUS_CURVET_CCCURVE: + if (FAILED(hr = performance_send_midi_pmsg(This, msg, DMUS_PMSGF_MUSICTIME | DMUS_PMSGF_TOOL_IMMEDIATE, + MIDI_CONTROL_CHANGE, curve->bCCData, curve->nStartValue))) + WARN("Failed to translate message to MIDI, hr %#lx\n", hr); + break; + case DMUS_CURVET_RPNCURVE: + case DMUS_CURVET_NRPNCURVE: + FIXME("Unhandled curve type %#lx\n", curve->dwType); + break; + } + + break; + } + case DMUS_PMSGT_PATCH: { DMUS_PATCH_PMSG *patch = (DMUS_PATCH_PMSG *)msg;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/performance.c | 11 ++++++----- dlls/dmsynth/Makefile.in | 1 + dlls/dmsynth/synth.c | 9 +++++---- dlls/dmusic/dmusic_midi.h | 40 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 9 deletions(-) create mode 100644 dlls/dmusic/dmusic_midi.h
diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index 8ea01b168d7..f120cc6f0a9 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -19,6 +19,7 @@ */
#include "dmime_private.h" +#include "dmusic_midi.h" #include "wine/rbtree.h"
WINE_DEFAULT_DEBUG_CHANNEL(dmime); @@ -1702,12 +1703,12 @@ static HRESULT WINAPI performance_tool_ProcessPMsg(IDirectMusicTool *iface,
msg->mtTime += note->nOffset; if (FAILED(hr = performance_send_midi_pmsg(This, msg, DMUS_PMSGF_REFTIME | DMUS_PMSGF_MUSICTIME | DMUS_PMSGF_TOOL_IMMEDIATE, - 0x90 /* NOTE_ON */, note->bMidiValue, note->bVelocity))) + 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, - 0x80 /* NOTE_OFF */, note->bMidiValue, 0))) + MIDI_NOTE_OFF, note->bMidiValue, 0))) WARN("Failed to translate message to MIDI, hr %#lx\n", hr);
break; @@ -1718,15 +1719,15 @@ static HRESULT WINAPI performance_tool_ProcessPMsg(IDirectMusicTool *iface, DMUS_PATCH_PMSG *patch = (DMUS_PATCH_PMSG *)msg;
if (FAILED(hr = performance_send_midi_pmsg(This, msg, DMUS_PMSGF_REFTIME | DMUS_PMSGF_MUSICTIME | DMUS_PMSGF_TOOL_IMMEDIATE, - 0xb0 /* Control Change */, 0x00 /* CC: Bank MSB */, patch->byMSB))) + MIDI_CONTROL_CHANGE, MIDI_CC_BANK_MSB, patch->byMSB))) WARN("Failed to translate message to MIDI, hr %#lx\n", hr);
if (FAILED(hr = performance_send_midi_pmsg(This, msg, DMUS_PMSGF_REFTIME | DMUS_PMSGF_MUSICTIME | DMUS_PMSGF_TOOL_IMMEDIATE, - 0xb0 /* Control Change */, 0x20 /* CC: Bank LSB */, patch->byLSB))) + MIDI_CONTROL_CHANGE, MIDI_CC_BANK_LSB, patch->byLSB))) WARN("Failed to translate message to MIDI, hr %#lx\n", hr);
if (FAILED(hr = performance_send_midi_pmsg(This, msg, DMUS_PMSGF_REFTIME | DMUS_PMSGF_MUSICTIME | DMUS_PMSGF_TOOL_IMMEDIATE, - 0xc0 /* Program Change */, patch->byInstrument, 0))) + MIDI_PROGRAM_CHANGE, patch->byInstrument, 0))) WARN("Failed to translate message to MIDI, hr %#lx\n", hr);
break; diff --git a/dlls/dmsynth/Makefile.in b/dlls/dmsynth/Makefile.in index 7c6d2db721b..85cac5912ac 100644 --- a/dlls/dmsynth/Makefile.in +++ b/dlls/dmsynth/Makefile.in @@ -1,6 +1,7 @@ MODULE = dmsynth.dll IMPORTS = $(FLUIDSYNTH_PE_LIBS) dxguid uuid ole32 advapi32 user32 EXTRAINCL = $(FLUIDSYNTH_PE_CFLAGS) +PARENTSRC = ../dmusic
C_SRCS = \ dmsynth_main.c \ diff --git a/dlls/dmsynth/synth.c b/dlls/dmsynth/synth.c index 941fc465d17..db45dd1e231 100644 --- a/dlls/dmsynth/synth.c +++ b/dlls/dmsynth/synth.c @@ -25,6 +25,7 @@ #include "dmksctrl.h"
#include "dmsynth_private.h" +#include "dmusic_midi.h" #include "dls2.h"
#include <fluidsynth.h> @@ -1009,16 +1010,16 @@ static HRESULT WINAPI synth_Render(IDirectMusicSynth8 *iface, short *buffer,
switch (status) { - case 0x80: + case MIDI_NOTE_OFF: fluid_synth_noteoff(This->fluid_synth, chan, event->midi[1]); break; - case 0x90: + case MIDI_NOTE_ON: fluid_synth_noteon(This->fluid_synth, chan, event->midi[1], event->midi[2]); break; - case 0xb0: + case MIDI_CONTROL_CHANGE: fluid_synth_cc(This->fluid_synth, chan, event->midi[1], event->midi[2]); break; - case 0xc0: + case MIDI_PROGRAM_CHANGE: fluid_synth_program_change(This->fluid_synth, chan, event->midi[1]); break; default: diff --git a/dlls/dmusic/dmusic_midi.h b/dlls/dmusic/dmusic_midi.h new file mode 100644 index 00000000000..e545bcaf8cb --- /dev/null +++ b/dlls/dmusic/dmusic_midi.h @@ -0,0 +1,40 @@ +/* + * Copyright 2023 Rémi Bernon for CodeWeavers + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "stdarg.h" +#include "stddef.h" + +#include "windef.h" +#include "winbase.h" + +enum midi_message +{ + MIDI_NOTE_OFF = 0x80, + MIDI_NOTE_ON = 0x90, + MIDI_KEY_PRESSURE = 0xa0, + MIDI_CONTROL_CHANGE = 0xb0, + MIDI_PROGRAM_CHANGE = 0xc0, + MIDI_CHANNEL_PRESSURE = 0xd0, + MIDI_PITCH_BEND_CHANGE = 0xe0, +}; + +enum midi_control +{ + MIDI_CC_BANK_MSB = 0x00, + MIDI_CC_BANK_LSB = 0x20, +};
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/performance.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index 815e8295ed8..a8fcd869331 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -468,7 +468,7 @@ static HRESULT WINAPI performance_SendPMsg(IDirectMusicPerformance8 *iface, DMUS struct message *message, *next; HRESULT hr;
- FIXME("(%p, %p): semi-stub\n", This, msg); + TRACE("(%p, %p)\n", This, msg);
if (!(message = message_from_DMUS_PMSG(msg))) return E_POINTER; if (!This->dmusic) return DMUS_E_NO_MASTER_CLOCK; @@ -519,9 +519,11 @@ done: static HRESULT WINAPI performance_MusicToReferenceTime(IDirectMusicPerformance8 *iface, MUSIC_TIME music_time, REFERENCE_TIME *time) { + static int once; struct performance *This = impl_from_IDirectMusicPerformance8(iface);
- FIXME("(%p, %ld, %p): semi-stub\n", This, music_time, time); + if (!once++) FIXME("(%p, %ld, %p): semi-stub\n", This, music_time, time); + else TRACE("(%p, %ld, %p)\n", This, music_time, time);
if (!time) return E_POINTER; *time = 0; @@ -538,9 +540,11 @@ static HRESULT WINAPI performance_MusicToReferenceTime(IDirectMusicPerformance8 static HRESULT WINAPI performance_ReferenceToMusicTime(IDirectMusicPerformance8 *iface, REFERENCE_TIME time, MUSIC_TIME *music_time) { + static int once; struct performance *This = impl_from_IDirectMusicPerformance8(iface);
- FIXME("(%p, %I64d, %p): semi-stub\n", This, time, music_time); + if (!once++) FIXME("(%p, %I64d, %p): semi-stub\n", This, time, music_time); + else TRACE("(%p, %I64d, %p)\n", This, time, music_time);
if (!music_time) return E_POINTER; *music_time = 0; @@ -1657,7 +1661,7 @@ static HRESULT WINAPI performance_tool_ProcessPMsg(IDirectMusicTool *iface, struct message *message = message_from_DMUS_PMSG(msg); HRESULT hr;
- FIXME("(%p, %p, %p): semi-stub\n", This, performance, msg); + TRACE("(%p, %p, %p)\n", This, performance, msg);
switch (msg->dwType) {
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=138849
Your paranoid android.
=== debian11b (64 bit WoW report) ===
user32: msg.c:6908: Test failed: SetFocus(hwnd) on a button: 4: the msg 0x0007 was expected, but got msg 0x030f instead msg.c:6908: Test failed: SetFocus(hwnd) on a button: 4: the msg 0x0007 was expected, but got msg 0x001c instead msg.c:6908: Test failed: SetFocus(hwnd) on a button: 4: the msg 0x0007 was expected, but got msg 0x0086 instead msg.c:6908: Test failed: SetFocus(hwnd) on a button: 4: the msg 0x0007 was expected, but got msg 0x0006 instead msg.c:6908: Test failed: SetFocus(hwnd) on a button: 4: the msg 0x0007 was expected, but got hook 0x0009 instead msg.c:6908: Test failed: SetFocus(hwnd) on a button: 4: the msg 0x0007 should NOT have been sent by DefWindowProc msg.c:6908: Test failed: SetFocus(hwnd) on a button: 4: the msg 0x0007 was expected in child msg.c:6908: Test failed: SetFocus(hwnd) on a button: 5: the msg 0x0138 was expected, but got msg 0x0008 instead msg.c:6908: Test failed: SetFocus(hwnd) on a button: 5: the msg 0x0138 was expected, but got winevent_hook 0x8005 instead msg.c:6908: Test failed: SetFocus(hwnd) on a button: 5: the msg 0x0138 was expected, but got msg 0x0007 instead
This merge request was approved by Michael Stefaniuc.
Unrelated test failure aka the usual domdoc and filtergraph.