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..218dc01045d 100644 --- a/dlls/dmime/tests/dmime.c +++ b/dlls/dmime/tests/dmime.c @@ -3660,11 +3660,21 @@ 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); + /* Both native and builtin dmime queue messages for a given amount of time, + * then wait for these messages to be processed before queuing additional messages. + * However, Wine "wait" time is way smaller than native, and is hit before the 10 + * reiterations in loop here. + * And moreover, Wine uses internal messages for this "wait" operation. + * Discard Wine's internal messages to be on par with native. + */ + 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 +3682,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 +3694,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;