Parse MIDI meta set tempo events, and create a tempotrack for it.
From: Yuxuan Shui yshui@codeweavers.com
Preparation for supporting setting TempoParam on tempotracks. --- dlls/dmime/tempotrack.c | 74 +++++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 25 deletions(-)
diff --git a/dlls/dmime/tempotrack.c b/dlls/dmime/tempotrack.c index 028ebc8879c..1f338b8f40d 100644 --- a/dlls/dmime/tempotrack.c +++ b/dlls/dmime/tempotrack.c @@ -27,12 +27,16 @@ WINE_DECLARE_DEBUG_CHANNEL(dmfile); * IDirectMusicTempoTrack implementation */
+struct tempo_entry { + struct list entry; + DMUS_IO_TEMPO_ITEM item; +}; + typedef struct IDirectMusicTempoTrack { IDirectMusicTrack8 IDirectMusicTrack8_iface; struct dmobject dmobj; /* IPersistStream only */ LONG ref; - DMUS_IO_TEMPO_ITEM *items; - unsigned int count; + struct list items; } IDirectMusicTempoTrack;
/* IDirectMusicTempoTrack IDirectMusicTrack8 part: */ @@ -82,7 +86,11 @@ static ULONG WINAPI tempo_track_Release(IDirectMusicTrack8 *iface) TRACE("(%p) ref=%ld\n", This, ref);
if (!ref) { - free(This->items); + struct tempo_entry *item, *next_item; + LIST_FOR_EACH_ENTRY_SAFE(item, next_item, &This->items, struct tempo_entry, entry) { + list_remove(&item->entry); + free(item); + } free(This); }
@@ -141,31 +149,34 @@ static HRESULT WINAPI tempo_track_Play(IDirectMusicTrack8 *iface, void *pStateDa }
static HRESULT WINAPI tempo_track_GetParam(IDirectMusicTrack8 *iface, REFGUID type, MUSIC_TIME music_time, - MUSIC_TIME *next_time, void *param) + MUSIC_TIME *out_next_time, void *param) { IDirectMusicTempoTrack *This = impl_from_IDirectMusicTrack8(iface); - DMUS_IO_TEMPO_ITEM *item = This->items, *end = item + This->count; + struct tempo_entry *item, *next_item; DMUS_TEMPO_PARAM *tempo = param; + MUSIC_TIME next_time = 0;
- TRACE("(%p, %s, %ld, %p, %p)\n", This, debugstr_dmguid(type), music_time, next_time, param); + TRACE("(%p, %s, %ld, %p, %p)\n", This, debugstr_dmguid(type), music_time, out_next_time, param);
if (!param) return E_POINTER; if (!IsEqualGUID(type, &GUID_TempoParam)) return DMUS_E_GET_UNSUPPORTED; - if (item == end) return DMUS_E_NOT_FOUND; - - tempo->mtTime = item->lTime - music_time; - tempo->dblTempo = item->dblTempo; - - for (; item < end; item++) + if (list_empty(&This->items)) return DMUS_E_NOT_FOUND; + + /* if music_time is before the first item, we return the first item. */ + LIST_FOR_EACH_ENTRY_SAFE(item, next_item, &This->items, struct tempo_entry, entry) { - MUSIC_TIME time = item->lTime - music_time; - if (next_time) *next_time = item->lTime - music_time; - if (time > 0) break; - tempo->mtTime = time; - tempo->dblTempo = item->dblTempo; + tempo->mtTime = item->item.lTime - music_time; + tempo->dblTempo = item->item.dblTempo; + + next_time = tempo->mtTime; + if (next_time > 0) break; + next_time = 0; + if (item->entry.next == &This->items) break; + next_time = next_item->item.lTime - music_time; + if (next_time > 0) break; }
- if (next_time && item == end) *next_time = 0; + if (out_next_time) *out_next_time = next_time; return S_OK; }
@@ -315,8 +326,10 @@ static HRESULT WINAPI tempo_IPersistStream_Load(IPersistStream *iface, IStream * { IDirectMusicTempoTrack *This = impl_from_IPersistStream(iface); struct chunk_entry chunk = {0}; - unsigned int i; + DMUS_IO_TEMPO_ITEM *items; + ULONG i = 0; HRESULT hr; + UINT count;
TRACE("%p, %p\n", This, stream);
@@ -328,18 +341,28 @@ static HRESULT WINAPI tempo_IPersistStream_Load(IPersistStream *iface, IStream * if (chunk.id != DMUS_FOURCC_TEMPO_TRACK) return DMUS_E_UNSUPPORTED_STREAM;
- hr = stream_chunk_get_array(stream, &chunk, (void **)&This->items, &This->count, + hr = stream_chunk_get_array(stream, &chunk, (void **)&items, &count, sizeof(DMUS_IO_TEMPO_ITEM)); if (FAILED(hr)) return hr;
- for (i = 0; i < This->count; i++) { - TRACE_(dmfile)("DMUS_IO_TEMPO_ITEM #%u\n", i); - TRACE_(dmfile)(" - lTime = %lu\n", This->items[i].lTime); - TRACE_(dmfile)(" - dblTempo = %g\n", This->items[i].dblTempo); + for (i = 0; i < count; i++) + { + struct tempo_entry *entry = calloc(1, sizeof(*entry)); + if (!entry) hr = E_OUTOFMEMORY; + else + { + entry->item = items[i]; + list_add_tail(&This->items, &entry->entry); + } + + TRACE_(dmfile)("DMUS_IO_TEMPO_ITEM #%lu\n", i); + TRACE_(dmfile)(" - lTime = %lu\n", items[i].lTime); + TRACE_(dmfile)(" - dblTempo = %g\n", items[i].dblTempo); }
- return S_OK; + free(items); + return hr; }
static const IPersistStreamVtbl persiststream_vtbl = { @@ -366,6 +389,7 @@ HRESULT create_dmtempotrack(REFIID lpcGUID, void **ppobj) dmobject_init(&track->dmobj, &CLSID_DirectMusicTempoTrack, (IUnknown *)&track->IDirectMusicTrack8_iface); track->dmobj.IPersistStream_iface.lpVtbl = &persiststream_vtbl; + list_init(&track->items);
hr = IDirectMusicTrack8_QueryInterface(&track->IDirectMusicTrack8_iface, lpcGUID, ppobj); IDirectMusicTrack8_Release(&track->IDirectMusicTrack8_iface);
From: Yuxuan Shui yshui@codeweavers.com
And add some tests. --- dlls/dmime/tempotrack.c | 19 +++++++++++++++- dlls/dmime/tests/dmime.c | 49 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-)
diff --git a/dlls/dmime/tempotrack.c b/dlls/dmime/tempotrack.c index 1f338b8f40d..d44b5f4b3e6 100644 --- a/dlls/dmime/tempotrack.c +++ b/dlls/dmime/tempotrack.c @@ -200,9 +200,26 @@ static HRESULT WINAPI tempo_track_SetParam(IDirectMusicTrack8 *iface, REFGUID ty return S_OK; } if (IsEqualGUID(type, &GUID_TempoParam)) { + struct tempo_entry *item, *next_item; + DMUS_TEMPO_PARAM *tempo_param = param; + struct tempo_entry *entry; if (!param) return E_POINTER; - FIXME("GUID_TempoParam not handled yet\n"); + if (!(entry = calloc(1, sizeof(*entry)))) + return E_OUTOFMEMORY; + entry->item.lTime = time; + entry->item.dblTempo = tempo_param->dblTempo; + if (list_empty(&This->items)) + list_add_tail(&This->items, &entry->entry); + else + { + LIST_FOR_EACH_ENTRY_SAFE(item, next_item, &This->items, struct tempo_entry, entry) + if (item->entry.next == &This->items || next_item->item.lTime > time) + { + list_add_after(&item->entry, &entry->entry); + break; + } + } return S_OK; }
diff --git a/dlls/dmime/tests/dmime.c b/dlls/dmime/tests/dmime.c index 97a6088936e..69d8cf09605 100644 --- a/dlls/dmime/tests/dmime.c +++ b/dlls/dmime/tests/dmime.c @@ -4456,6 +4456,54 @@ static void check_dmus_tempo_pmsg_(int line, DMUS_TEMPO_PMSG *msg, MUSIC_TIME ti ok_(__FILE__, line)(msg->dblTempo == tempo, "got tempo %f\n", msg->dblTempo); }
+static void test_tempo_track(void) +{ + HRESULT hr; + IDirectMusicTrack *track; + DMUS_TEMPO_PARAM param; + MUSIC_TIME next; + hr = CoCreateInstance(&CLSID_DirectMusicTempoTrack, NULL, CLSCTX_INPROC_SERVER, + &IID_IDirectMusicTrack, (void **)&track); + ok(hr == S_OK, "got %#lx\n", hr); + + hr = IDirectMusicTrack_GetParam(track, &GUID_TempoParam, 0, &next, ¶m); + ok(hr == DMUS_E_NOT_FOUND, "got %#lx\n", hr); + + param.dblTempo = 150; + param.mtTime = 10; + hr = IDirectMusicTrack_SetParam(track, &GUID_TempoParam, 10, ¶m); + ok(hr == S_OK, "got %#lx\n", hr); + + hr = IDirectMusicTrack_GetParam(track, &GUID_TempoParam, 0, &next, ¶m); + ok(hr == S_OK, "got %#lx\n", hr); + ok(param.dblTempo == 150, "got %f, expected 150\n", param.dblTempo); + ok(param.mtTime == 10, "got %lu, expected 10\n", param.mtTime); + ok(next == 10, "got %lu, expected 10\n", next); + + hr = IDirectMusicTrack_GetParam(track, &GUID_TempoParam, 10, &next, ¶m); + ok(hr == S_OK, "got %#lx\n", hr); + ok(param.dblTempo == 150, "got %f, expected 150\n", param.dblTempo); + ok(param.mtTime == 0, "got %lu, expected 0\n", param.mtTime); + ok(next == 0, "got %lu, expected 0\n", next); + + hr = IDirectMusicTrack_GetParam(track, &GUID_TempoParam, 11, &next, ¶m); + ok(hr == S_OK, "got %#lx\n", hr); + ok(param.dblTempo == 150, "got %f, expected 150\n", param.dblTempo); + ok(param.mtTime == -1, "got %lu, expected 0\n", param.mtTime); + ok(next == 0, "got %lu, expected 0\n", next); + + param.dblTempo = 180; + param.mtTime = 20; + hr = IDirectMusicTrack_SetParam(track, &GUID_TempoParam, 20, ¶m); + ok(hr == S_OK, "got %#lx\n", hr); + + hr = IDirectMusicTrack_GetParam(track, &GUID_TempoParam, 11, &next, ¶m); + ok(hr == S_OK, "got %#lx\n", hr); + ok(param.dblTempo == 150, "got %f, expected 150\n", param.dblTempo); + ok(param.mtTime == -1, "got %ld, expected -1\n", param.mtTime); + ok(next == 9, "got %lu, expected 9\n", next); +} + static void test_tempo_track_play(void) { static const DWORD message_types[] = @@ -5045,6 +5093,7 @@ START_TEST(dmime) test_wave_pmsg(0); test_wave_pmsg(10); test_sequence_track(); + test_tempo_track(); test_band_track_play(); test_tempo_track_play(); test_connect_to_collection();
From: Yuxuan Shui yshui@codeweavers.com
--- dlls/dmime/midi.c | 80 ++++++++++++++++++++++++++++++++++++---- dlls/dmime/tests/dmime.c | 18 ++++++++- 2 files changed, 88 insertions(+), 10 deletions(-)
diff --git a/dlls/dmime/midi.c b/dlls/dmime/midi.c index 647ef1d123c..b509394927e 100644 --- a/dlls/dmime/midi.c +++ b/dlls/dmime/midi.c @@ -35,18 +35,49 @@ struct midi_event { MUSIC_TIME delta_time; BYTE status; - BYTE data[2]; + union + { + struct + { + BYTE data[2]; + }; + struct + { + BYTE meta_type; + ULONG tempo; + }; + }; };
struct midi_parser { IDirectMusicTrack *chordtrack; IDirectMusicTrack *bandtrack; + IDirectMusicTrack *tempotrack; MUSIC_TIME time; IStream *stream; DWORD division; };
+enum meta_event_type +{ + MIDI_META_SEQUENCE_NUMBER = 0x00, + MIDI_META_TEXT_EVENT = 0x01, + MIDI_META_COPYRIGHT_NOTICE = 0x02, + MIDI_META_TRACK_NAME = 0x03, + MIDI_META_INSTRUMENT_NAME = 0x04, + MIDI_META_LYRIC = 0x05, + MIDI_META_MARKER = 0x06, + MIDI_META_CUE_POINT = 0x07, + MIDI_META_CHANNEL_PREFIX_ASSIGNMENT = 0x20, + MIDI_META_END_OF_TRACK = 0x2f, + MIDI_META_SET_TEMPO = 0x51, + MIDI_META_SMPTE_OFFSET = 0x54, + MIDI_META_TIME_SIGNATURE = 0x58, + MIDI_META_KEY_SIGNATURE = 0x59, + MIDI_META_SEQUENCER_SPECIFIC = 0x7f, +}; + static HRESULT stream_read_at_most(IStream *stream, void *buffer, ULONG size, ULONG *bytes_left) { HRESULT hr; @@ -76,8 +107,9 @@ static HRESULT read_variable_length_number(IStream *stream, DWORD *out, ULONG *b
static HRESULT read_midi_event(IStream *stream, struct midi_event *event, BYTE *last_status, ULONG *bytes_left) { - BYTE byte, status_type, meta_type; + BYTE byte, status_type; DWORD length; + BYTE data[3]; LARGE_INTEGER offset; HRESULT hr = S_OK; DWORD delta_time; @@ -96,21 +128,31 @@ static HRESULT read_midi_event(IStream *stream, struct midi_event *event, BYTE *
if (event->status == MIDI_META) { - meta_type = byte; + event->meta_type = byte;
if ((hr = read_variable_length_number(stream, &length, bytes_left)) != S_OK) return hr;
- switch (meta_type) + switch (event->meta_type) { + case MIDI_META_SET_TEMPO: + if (length != 3) + { + ERR("Invalid MIDI meta event length %lu for set tempo event.\n", length); + return E_FAIL; + } + if (FAILED(hr = stream_read_at_most(stream, data, 3, bytes_left))) return hr; + event->tempo = (data[0] << 16) | (data[1] << 8) | data[2]; + break; default: if (*bytes_left < length) return S_FALSE; offset.QuadPart = length; if (FAILED(hr = IStream_Seek(stream, offset, STREAM_SEEK_CUR, NULL))) return hr; - FIXME("MIDI meta event type %#02x, length %lu, time +%lu. not supported\n", meta_type, - length, delta_time); + FIXME("MIDI meta event type %#02x, length %lu, time +%lu. not supported\n", + event->meta_type, length, delta_time); *bytes_left -= length; + event->tempo = 0; } - TRACE("MIDI meta event type %#02x, length %lu, time +%lu\n", meta_type, length, delta_time); + TRACE("MIDI meta event type %#02x, length %lu, time +%lu\n", event->meta_type, length, delta_time); return S_OK; } else if (event->status == MIDI_SYSEX1 || event->status == MIDI_SYSEX2) @@ -148,6 +190,23 @@ static HRESULT read_midi_event(IStream *stream, struct midi_event *event, BYTE * return S_OK; }
+static HRESULT midi_parser_handle_set_tempo(struct midi_parser *parser, struct midi_event *event) +{ + DMUS_TEMPO_PARAM tempo; + MUSIC_TIME dmusic_time = (ULONGLONG)parser->time * DMUS_PPQ / parser->division; + HRESULT hr; + if (!parser->tempotrack) + { + if (FAILED(hr = CoCreateInstance(&CLSID_DirectMusicTempoTrack, NULL, CLSCTX_INPROC_SERVER, + &IID_IDirectMusicTrack, (void **)&parser->tempotrack))) + return hr; + } + tempo.mtTime = dmusic_time; + tempo.dblTempo = 60 * 1000000.0 / event->tempo; + TRACE("Adding tempo at time %lu, tempo %f\n", dmusic_time, tempo.dblTempo); + return IDirectMusicTrack_SetParam(parser->tempotrack, &GUID_TempoParam, dmusic_time, &tempo); +} + static HRESULT midi_parser_handle_program_change(struct midi_parser *parser, struct midi_event *event) { HRESULT hr; @@ -206,7 +265,9 @@ static HRESULT midi_parser_parse(struct midi_parser *parser, IDirectMusicSegment while ((hr = read_midi_event(parser->stream, &event, &last_status, &length)) == S_OK) { parser->time += event.delta_time; - if ((event.status & 0xf0) == MIDI_PROGRAM_CHANGE) + if (event.status == 0xff && event.meta_type == MIDI_META_SET_TEMPO) + hr = midi_parser_handle_set_tempo(parser, &event); + else if ((event.status & 0xf0) == MIDI_PROGRAM_CHANGE) hr = midi_parser_handle_program_change(parser, &event); if (FAILED(hr)) break; } @@ -223,6 +284,8 @@ static HRESULT midi_parser_parse(struct midi_parser *parser, IDirectMusicSegment if (SUCCEEDED(hr)) hr = IDirectMusicSegment8_SetLength(segment, music_length); if (SUCCEEDED(hr)) hr = IDirectMusicSegment8_InsertTrack(segment, parser->bandtrack, 0xffff); if (SUCCEEDED(hr)) hr = IDirectMusicSegment8_InsertTrack(segment, parser->chordtrack, 0xffff); + if (SUCCEEDED(hr) && parser->tempotrack) + hr = IDirectMusicSegment8_InsertTrack(segment, parser->tempotrack, 0xffff);
return hr; } @@ -232,6 +295,7 @@ static void midi_parser_destroy(struct midi_parser *parser) IStream_Release(parser->stream); if (parser->bandtrack) IDirectMusicTrack_Release(parser->bandtrack); if (parser->chordtrack) IDirectMusicTrack_Release(parser->chordtrack); + if (parser->tempotrack) IDirectMusicTrack_Release(parser->tempotrack); free(parser); }
diff --git a/dlls/dmime/tests/dmime.c b/dlls/dmime/tests/dmime.c index 69d8cf09605..87f89b04e4b 100644 --- a/dlls/dmime/tests/dmime.c +++ b/dlls/dmime/tests/dmime.c @@ -1646,8 +1646,10 @@ static void test_midi(void) WCHAR test_mid[MAX_PATH], bogus_mid[MAX_PATH]; HRESULT hr; ULONG ret; + MUSIC_TIME next; DMUS_PMSG *msg; DMUS_PATCH_PMSG *patch; + DMUS_TEMPO_PARAM tempo_param; #include <pshpack1.h> struct { @@ -1682,7 +1684,7 @@ static void test_midi(void)
expect_track(segment, BandTrack, -1, 0); expect_track(segment, ChordTrack, -1, 1); - todo_wine expect_track(segment, TempoTrack, -1, 2); + expect_track(segment, TempoTrack, -1, 2); todo_wine expect_track(segment, TimeSigTrack, -1, 3); todo_wine expect_track(segment, SeqTrack, -1, 4); /* no more tracks */ @@ -1760,8 +1762,20 @@ static void test_midi(void) IStream_Release(stream); expect_track(segment, BandTrack, -1, 0); expect_track(segment, ChordTrack, -1, 1); - todo_wine expect_track(segment, TempoTrack, -1, 2); + expect_track(segment, TempoTrack, -1, 2); todo_wine expect_track(segment, SeqTrack, -1, 3); + + hr = IDirectMusicSegment_GetParam(segment, &GUID_TempoParam, -1, DMUS_SEG_ALLTRACKS, 0, &next, &tempo_param); + ok(hr == S_OK, "got %#lx\n", hr); + ok(next == 24, "got %ld, expected 24\n", next); + ok(tempo_param.mtTime == 24, "got %ld, expected 24\n", tempo_param.mtTime); + ok(tempo_param.dblTempo == 300.0, "got %f, expected 300.0\n", tempo_param.dblTempo); + + hr = IDirectMusicSegment_GetParam(segment, &GUID_TempoParam, -1, DMUS_SEG_ALLTRACKS, 26, &next, &tempo_param); + ok(hr == S_OK, "got %#lx\n", hr); + ok(next == 0, "got %ld, expected 24\n", next); + ok(tempo_param.mtTime == -2, "got %ld, expected -6\n", tempo_param.mtTime); + ok(tempo_param.dblTempo == 300.0, "got %f, expected 300.0\n", tempo_param.dblTempo); IDirectMusicSegment_Release(segment);
/* parse MIDI file with a track with 0 length, but has an event. */
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 full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=143542
Your paranoid android.
=== build (build log) ===
error: patch failed: dlls/dmime/midi.c:35 error: patch failed: dlls/dmime/tests/dmime.c:1646 Task: Patch failed to apply
=== debian11 (build log) ===
error: patch failed: dlls/dmime/midi.c:35 error: patch failed: dlls/dmime/tests/dmime.c:1646 Task: Patch failed to apply
=== debian11b (build log) ===
error: patch failed: dlls/dmime/midi.c:35 error: patch failed: dlls/dmime/tests/dmime.c:1646 Task: Patch failed to apply
Rémi Bernon (@rbernon) commented about dlls/dmime/tempotrack.c:
- IDirectMusicTempoTrack implementation
*/
+struct tempo_entry {
```suggestion:-0+0 struct tempo_entry { ```
Rémi Bernon (@rbernon) commented about dlls/dmime/tempotrack.c:
TRACE("(%p) ref=%ld\n", This, ref); if (!ref) {
free(This->items);
struct tempo_entry *item, *next_item;
LIST_FOR_EACH_ENTRY_SAFE(item, next_item, &This->items, struct tempo_entry, entry) {
```suggestion:-3+0
if (!ref) { struct tempo_entry *item, *next_item;
LIST_FOR_EACH_ENTRY_SAFE(item, next_item, &This->items, struct tempo_entry, entry) { ```
Lets fix those braces instead.
Rémi Bernon (@rbernon) commented about dlls/dmime/midi.c:
+static HRESULT midi_parser_handle_set_tempo(struct midi_parser *parser, struct midi_event *event) +{
- DMUS_TEMPO_PARAM tempo;
- MUSIC_TIME dmusic_time = (ULONGLONG)parser->time * DMUS_PPQ / parser->division;
- HRESULT hr;
- if (!parser->tempotrack)
- {
if (FAILED(hr = CoCreateInstance(&CLSID_DirectMusicTempoTrack, NULL, CLSCTX_INPROC_SERVER,
&IID_IDirectMusicTrack, (void **)&parser->tempotrack)))
return hr;
- }
- tempo.mtTime = dmusic_time;
- tempo.dblTempo = 60 * 1000000.0 / event->tempo;
- TRACE("Adding tempo at time %lu, tempo %f\n", dmusic_time, tempo.dblTempo);
- return IDirectMusicTrack_SetParam(parser->tempotrack, &GUID_TempoParam, dmusic_time, &tempo);
I would say the same here for instance, adding blank lines here and there helps making things more readable.
```suggestion:-12+0 DMUS_TEMPO_PARAM tempo; MUSIC_TIME dmusic_time = (ULONGLONG)parser->time * DMUS_PPQ / parser->division; HRESULT hr;
if (!parser->tempotrack) { if (FAILED(hr = CoCreateInstance(&CLSID_DirectMusicTempoTrack, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectMusicTrack, (void **)&parser->tempotrack))) return hr; }
tempo.mtTime = dmusic_time; tempo.dblTempo = 60 * 1000000.0 / event->tempo; TRACE("Adding tempo at time %lu, tempo %f\n", dmusic_time, tempo.dblTempo); return IDirectMusicTrack_SetParam(parser->tempotrack, &GUID_TempoParam, dmusic_time, &tempo); ```
IMO you could also combine the two ifs.
Rémi Bernon (@rbernon) commented about dlls/dmime/tempotrack.c:
return DMUS_E_UNSUPPORTED_STREAM;
- hr = stream_chunk_get_array(stream, &chunk, (void **)&This->items, &This->count,
- hr = stream_chunk_get_array(stream, &chunk, (void **)&items, &count, sizeof(DMUS_IO_TEMPO_ITEM)); if (FAILED(hr)) return hr;
- for (i = 0; i < This->count; i++) {
TRACE_(dmfile)("DMUS_IO_TEMPO_ITEM #%u\n", i);
TRACE_(dmfile)(" - lTime = %lu\n", This->items[i].lTime);
TRACE_(dmfile)(" - dblTempo = %g\n", This->items[i].dblTempo);
- for (i = 0; i < count; i++)
- {
struct tempo_entry *entry = calloc(1, sizeof(*entry));
if (!entry) hr = E_OUTOFMEMORY;
You should break probably here, or add SUCCEEDED(hr) to the loop conditions.
Rémi Bernon (@rbernon) commented about dlls/dmime/tests/dmime.c:
- ok(hr == S_OK, "got %#lx\n", hr);
- ok(param.dblTempo == 150, "got %f, expected 150\n", param.dblTempo);
- ok(param.mtTime == -1, "got %lu, expected 0\n", param.mtTime);
- ok(next == 0, "got %lu, expected 0\n", next);
- param.dblTempo = 180;
- param.mtTime = 20;
- hr = IDirectMusicTrack_SetParam(track, &GUID_TempoParam, 20, ¶m);
- ok(hr == S_OK, "got %#lx\n", hr);
- hr = IDirectMusicTrack_GetParam(track, &GUID_TempoParam, 11, &next, ¶m);
- ok(hr == S_OK, "got %#lx\n", hr);
- ok(param.dblTempo == 150, "got %f, expected 150\n", param.dblTempo);
- ok(param.mtTime == -1, "got %ld, expected -1\n", param.mtTime);
- ok(next == 9, "got %lu, expected 9\n", next);
+}
You're leaking the track here.