Commit 36d6fe59 authored by Eric Pouech's avatar Eric Pouech Committed by Alexandre Julliard

dmime: Use sent duration in loop's playback.

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 1. Compute segment length in this case by grabbing each track's playback length in segment state's internal graph. This feature is only activated for messages generated by wave tracks, but could be extended if needed to other types of messages. Signed-off-by: 's avatarEric Pouech <epouech@codeweavers.com>
parent ef2830b6
......@@ -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;
......
......@@ -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)
/* 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);
if (ret) continue;
ok(wave->dwType == DMUS_PMSGT_WAVE, "got %p\n", wave);
} 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)
{
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment