From: Eric Pouech epouech@codeweavers.com
When playing a loop, and if no end of loop point has been defined (meaning = play whole segment), don't rely on segment's length for wave tracks as their length is always. Actual loop length in this case is computed by using segment state's internal graph as a proxy to grab this information.
Signed-off-by: Eric Pouech epouech@codeweavers.com --- dlls/dmime/segmentstate.c | 37 ++++++++++++++++++++++++++++++++++++- dlls/dmime/tests/dmime.c | 18 +++++++++++------- dlls/dmime/wavetrack.c | 6 +++--- 3 files changed, 50 insertions(+), 11 deletions(-)
diff --git a/dlls/dmime/segmentstate.c b/dlls/dmime/segmentstate.c index 0deb396d384..4fece4181e1 100644 --- a/dlls/dmime/segmentstate.c +++ b/dlls/dmime/segmentstate.c @@ -54,6 +54,10 @@ struct segment_state MUSIC_TIME start_point; MUSIC_TIME end_point; MUSIC_TIME played; + + REFERENCE_TIME actual_duration; + MUSIC_TIME actual_end_point; + BOOL auto_download; DWORD repeats, actual_repeats; DWORD track_flags; @@ -227,12 +231,29 @@ static ULONG WINAPI segment_state_graph_Release(IDirectMusicGraph *iface) static HRESULT WINAPI segment_state_graph_StampPMsg(IDirectMusicGraph *iface, DMUS_PMSG *msg) { struct segment_state *This = impl_from_IDirectMusicGraph(iface); + HRESULT hr;
TRACE("(%p, %p)\n", This, msg);
if (!msg) return E_POINTER;
- return IDirectMusicGraph_StampPMsg(This->parent_graph, msg); + hr = IDirectMusicGraph_StampPMsg(This->parent_graph, msg); + if (SUCCEEDED(hr)) + { + switch (msg->dwType) + { + case DMUS_PMSGT_WAVE: + if (msg->dwFlags & (DMUS_PMSGF_REFTIME | DMUS_PMSGF_MUSICTIME)) + { + if (((DMUS_WAVE_PMSG *)msg)->rtDuration > This->actual_duration) + This->actual_duration = ((DMUS_WAVE_PMSG *)msg)->rtDuration; + } + break; + default: ; + } + } + + return hr; }
static HRESULT WINAPI segment_state_graph_InsertTool(IDirectMusicGraph *iface, IDirectMusicTool *tool, @@ -373,6 +394,9 @@ static HRESULT segment_state_play_until(struct segment_state *This, IDirectMusic
played = min(end_time - This->start_time, This->end_point - This->start_point);
+ if (This->track_flags & DMUS_TRACKF_DIRTY) + This->actual_duration = 0; + LIST_FOR_EACH_ENTRY(entry, &This->tracks, struct track_entry, entry) { if (FAILED(hr = IDirectMusicTrack_Play(entry->track, entry->state_data, @@ -424,6 +448,17 @@ static HRESULT segment_state_play_chunk(struct segment_state *This, IDirectMusic if (FAILED(hr = IDirectMusicSegment_GetLoopPoints(This->segment, &This->played, &This->end_point))) break; + if (!This->played && !This->end_point) + { + if (!This->actual_end_point && This->actual_duration) + { + IDirectMusicPerformance_ReferenceToMusicTime(performance, time + This->actual_duration, &This->actual_end_point); + This->actual_end_point -= This->start_time + This->played; + } + This->end_point = This->actual_end_point; + if (next_time < This->start_time + This->end_point) + next_time += This->end_point - This->start_point; + } This->start_time += This->end_point - This->start_point; This->actual_repeats--; This->track_flags |= DMUS_TRACKF_LOOP | DMUS_TRACKF_SEEK; diff --git a/dlls/dmime/tests/dmime.c b/dlls/dmime/tests/dmime.c index 8ae62b38670..4fff7ba7588 100644 --- a/dlls/dmime/tests/dmime.c +++ b/dlls/dmime/tests/dmime.c @@ -3660,11 +3660,17 @@ static void test_wave_pmsg(unsigned num_repeats)
for (i = 0; i <= num_repeats; i++) { - ret = test_tool_wait_message(tool, 500, (DMUS_PMSG **)&wave); - todo_wine_if(num_repeats && ret) - ok(!ret, "got %#lx\n", ret); - if (ret) continue; - ok(wave->dwType == DMUS_PMSGT_WAVE, "got %p\n", wave); + /* Wine's implement queues very less play time at once compared to windows.. + * Discard Wine's internal messages, until next chunk has started. + */ + do + { + ret = test_tool_wait_message(tool, 2000, (DMUS_PMSG **)&wave); + ok(!ret, "got %#lx\n", ret); + } while (num_repeats && !ret && (wave->dwType >= 0x10 || wave->dwType == DMUS_PMSGT_DIRTY)); + if (ret) break; + + ok(wave->dwType == DMUS_PMSGT_WAVE, "got %p %lu\n", wave, wave->dwType); ok(wave->dwSize == sizeof(*wave), "got %lu\n", wave->dwSize); ok(!!wave->punkUser, "got %p\n", wave->punkUser); ok((wave->dwFlags & DMUS_PMSGF_REFTIME) && (wave->dwFlags & DMUS_PMSGF_MUSICTIME), @@ -3672,7 +3678,6 @@ static void test_wave_pmsg(unsigned num_repeats) if (i == 0) mt_start_ref = wave->mtTime; else - todo_wine ok(wave->mtTime == mt_start_ref + length * i, "got %lu (%lu,%lu)\n", wave->mtTime, mt_start_ref, i * length); ok(wave->rtStartOffset == 0, "got %I64d\n", wave->rtStartOffset); ok(wave->rtDuration == 1000000, "got %I64d\n", wave->rtDuration); @@ -3685,7 +3690,6 @@ static void test_wave_pmsg(unsigned num_repeats) }
ret = test_tool_wait_message(tool, 500, &msg); - todo_wine_if(num_repeats) ok(!ret, "got %#lx\n", ret); if (!ret) { diff --git a/dlls/dmime/wavetrack.c b/dlls/dmime/wavetrack.c index 3d64e6e84c5..64480c6422f 100644 --- a/dlls/dmime/wavetrack.c +++ b/dlls/dmime/wavetrack.c @@ -160,11 +160,11 @@ static HRESULT WINAPI wave_track_Play(IDirectMusicTrack8 *iface, void *state_dat
if (track_flags & ~handled_track_flags) FIXME("track_flags %#lx not implemented\n", track_flags & ~handled_track_flags); - if (segment_state) FIXME("segment_state %p not implemented\n", segment_state); - if (!(track_flags & (DMUS_TRACKF_START | DMUS_TRACKF_LOOP))) return S_OK;
- if (FAILED(hr = IDirectMusicPerformance_QueryInterface(performance, + if (FAILED(hr = IDirectMusicSegmentState_QueryInterface(segment_state, + &IID_IDirectMusicGraph, (void **)&graph)) && + FAILED(hr = IDirectMusicPerformance_QueryInterface(performance, &IID_IDirectMusicGraph, (void **)&graph))) return hr;