Commit 56043971 authored by Rémi Bernon's avatar Rémi Bernon Committed by Alexandre Julliard

dmime: Implement segment state chunked playback.

parent 63661495
......@@ -75,12 +75,15 @@ extern void set_audiopath_primary_dsound_buffer(IDirectMusicAudioPath*,IDirectSo
extern HRESULT segment_state_create(IDirectMusicSegment *segment, MUSIC_TIME start_time,
IDirectMusicPerformance8 *performance, IDirectMusicSegmentState **ret_iface);
extern HRESULT segment_state_play(IDirectMusicSegmentState *iface, IDirectMusicPerformance8 *performance);
extern HRESULT segment_state_tick(IDirectMusicSegmentState *iface, IDirectMusicPerformance8 *performance);
extern HRESULT segment_state_end_play(IDirectMusicSegmentState *iface, IDirectMusicPerformance8 *performance);
extern HRESULT wave_track_create_from_chunk(IStream *stream, struct chunk_entry *parent,
IDirectMusicTrack8 **ret_iface);
extern HRESULT performance_get_dsound(IDirectMusicPerformance8 *iface, IDirectSound **dsound);
extern HRESULT performance_send_segment_tick(IDirectMusicPerformance8 *iface, MUSIC_TIME music_time,
IDirectMusicSegmentState *state);
extern HRESULT performance_send_segment_end(IDirectMusicPerformance8 *iface, MUSIC_TIME music_time,
IDirectMusicSegmentState *state);
......
......@@ -28,6 +28,7 @@ enum dmus_internal_message_type
{
DMUS_PMSGT_INTERNAL_FIRST = 0x10,
DMUS_PMSGT_INTERNAL_SEGMENT_END = DMUS_PMSGT_INTERNAL_FIRST,
DMUS_PMSGT_INTERNAL_SEGMENT_TICK,
};
struct pchannel_block {
......@@ -275,6 +276,43 @@ static inline struct performance *impl_from_IDirectMusicPerformance8(IDirectMusi
return CONTAINING_RECORD(iface, struct performance, IDirectMusicPerformance8_iface);
}
static HRESULT performance_send_segment_start(IDirectMusicPerformance8 *iface, MUSIC_TIME music_time,
IDirectMusicSegmentState *state)
{
struct performance *This = impl_from_IDirectMusicPerformance8(iface);
HRESULT hr;
if (FAILED(hr = performance_send_notification_pmsg(This, music_time, This->notification_performance,
GUID_NOTIFICATION_PERFORMANCE, DMUS_NOTIFICATION_MUSICSTARTED, NULL)))
return hr;
if (FAILED(hr = performance_send_notification_pmsg(This, music_time, This->notification_segment,
GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGSTART, (IUnknown *)state)))
return hr;
if (FAILED(hr = performance_send_pmsg(This, music_time, DMUS_PMSGF_TOOL_IMMEDIATE,
DMUS_PMSGT_DIRTY, NULL)))
return hr;
return S_OK;
}
HRESULT performance_send_segment_tick(IDirectMusicPerformance8 *iface, MUSIC_TIME music_time,
IDirectMusicSegmentState *state)
{
struct performance *This = impl_from_IDirectMusicPerformance8(iface);
REFERENCE_TIME time;
HRESULT hr;
if (FAILED(hr = IDirectMusicPerformance8_MusicToReferenceTime(iface, music_time, &time)))
return hr;
if (FAILED(hr = IDirectMusicPerformance8_ReferenceToMusicTime(iface, time + 2000000, &music_time)))
return hr;
if (FAILED(hr = performance_send_pmsg(This, music_time, DMUS_PMSGF_TOOL_QUEUE,
DMUS_PMSGT_INTERNAL_SEGMENT_TICK, (IUnknown *)state)))
return hr;
return S_OK;
}
HRESULT performance_send_segment_end(IDirectMusicPerformance8 *iface, MUSIC_TIME music_time,
IDirectMusicSegmentState *state)
{
......@@ -1235,16 +1273,11 @@ static HRESULT WINAPI performance_PlaySegmentEx(IDirectMusicPerformance8 *iface,
return hr;
}
EnterCriticalSection(&This->safe);
hr = IDirectMusicSegment_GetLength(segment, &length);
if (SUCCEEDED(hr))
hr = performance_send_notification_pmsg(This, music_time, This->notification_performance,
GUID_NOTIFICATION_PERFORMANCE, DMUS_NOTIFICATION_MUSICSTARTED, NULL);
if (SUCCEEDED(hr))
hr = performance_send_notification_pmsg(This, music_time, This->notification_segment,
GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGSTART, (IUnknown *)state);
if (SUCCEEDED(hr))
hr = performance_send_pmsg(This, music_time, DMUS_PMSGF_TOOL_IMMEDIATE, DMUS_PMSGT_DIRTY, NULL);
hr = performance_send_segment_start(iface, music_time, state);
if (SUCCEEDED(hr))
hr = segment_state_play(state, iface);
......@@ -1266,6 +1299,8 @@ static HRESULT WINAPI performance_PlaySegmentEx(IDirectMusicPerformance8 *iface,
IDirectMusicSegmentState_AddRef(state);
}
LeaveCriticalSection(&This->safe);
IDirectMusicSegmentState_Release(state);
IDirectMusicSegment_Release(segment);
return hr;
......@@ -1839,6 +1874,21 @@ static HRESULT WINAPI performance_tool_ProcessPMsg(IDirectMusicTool *iface,
WARN("Failed to play wave buffer, hr %#lx\n", hr);
break;
case DMUS_PMSGT_INTERNAL_SEGMENT_TICK:
msg->rtTime += 10000000;
msg->dwFlags &= ~DMUS_PMSGF_MUSICTIME;
/* re-send the tick message until segment_state_tick returns S_FALSE */
if (FAILED(hr = segment_state_tick((IDirectMusicSegmentState *)msg->punkUser,
(IDirectMusicPerformance8 *)performance)))
ERR("Failed to tick segment state %p, hr %#lx\n", msg->punkUser, hr);
else if (hr == S_FALSE)
return DMUS_S_FREE; /* done ticking */
else if (FAILED(hr = IDirectMusicPerformance_SendPMsg(performance, msg)))
ERR("Failed to queue tick for segment state %p, hr %#lx\n", msg->punkUser, hr);
return S_OK;
case DMUS_PMSGT_INTERNAL_SEGMENT_END:
if (FAILED(hr = segment_state_end_play((IDirectMusicSegmentState *)msg->punkUser,
(IDirectMusicPerformance8 *)performance)))
......
......@@ -51,6 +51,7 @@ struct segment_state
MUSIC_TIME start_time;
MUSIC_TIME start_point;
MUSIC_TIME end_point;
MUSIC_TIME played;
BOOL auto_download;
struct list tracks;
......@@ -271,25 +272,63 @@ HRESULT segment_state_create(IDirectMusicSegment *segment, MUSIC_TIME start_time
return hr;
}
HRESULT segment_state_play(IDirectMusicSegmentState *iface, IDirectMusicPerformance8 *performance)
static HRESULT segment_state_play_chunk(struct segment_state *This, IDirectMusicPerformance8 *performance,
REFERENCE_TIME duration, DWORD track_flags)
{
struct segment_state *This = impl_from_IDirectMusicSegmentState8((IDirectMusicSegmentState8 *)iface);
DWORD track_flags = DMUS_TRACKF_DIRTY | DMUS_TRACKF_START | DMUS_TRACKF_SEEK;
MUSIC_TIME start_time = This->start_point, end_time = This->end_point;
IDirectMusicSegmentState *iface = (IDirectMusicSegmentState *)&This->IDirectMusicSegmentState8_iface;
MUSIC_TIME next_time, played;
struct track_entry *entry;
REFERENCE_TIME time;
HRESULT hr = S_OK;
if (FAILED(hr = IDirectMusicPerformance8_MusicToReferenceTime(performance,
This->start_time + This->played, &time)))
return hr;
if (FAILED(hr = IDirectMusicPerformance8_ReferenceToMusicTime(performance,
time + duration, &next_time)))
return hr;
played = min(next_time - This->start_time, This->end_point - This->start_point);
LIST_FOR_EACH_ENTRY(entry, &This->tracks, struct track_entry, entry)
{
if (FAILED(hr = IDirectMusicTrack_Play(entry->track, entry->state_data, start_time, end_time,
This->start_time, track_flags, (IDirectMusicPerformance *)performance, iface, entry->track_id)))
if (FAILED(hr = IDirectMusicTrack_Play(entry->track, entry->state_data,
This->start_point + This->played, This->start_point + played,
This->start_time, track_flags, (IDirectMusicPerformance *)performance,
iface, entry->track_id)))
{
WARN("Failed to play track %p, hr %#lx\n", entry->track, hr);
break;
}
}
return hr;
This->played = played;
if (This->start_point + This->played >= This->end_point)
return S_FALSE;
return S_OK;
}
HRESULT segment_state_play(IDirectMusicSegmentState *iface, IDirectMusicPerformance8 *performance)
{
struct segment_state *This = impl_from_IDirectMusicSegmentState8((IDirectMusicSegmentState8 *)iface);
HRESULT hr;
TRACE("%p %p\n", iface, performance);
if (FAILED(hr = segment_state_play_chunk(This, performance, 10000000,
DMUS_TRACKF_START | DMUS_TRACKF_SEEK | DMUS_TRACKF_DIRTY)))
return hr;
if (hr == S_FALSE) return S_OK;
return performance_send_segment_tick(performance, This->start_time, iface);
}
HRESULT segment_state_tick(IDirectMusicSegmentState *iface, IDirectMusicPerformance8 *performance)
{
struct segment_state *This = impl_from_IDirectMusicSegmentState8((IDirectMusicSegmentState8 *)iface);
TRACE("%p %p\n", iface, performance);
return segment_state_play_chunk(This, performance, 10000000, 0);
}
HRESULT segment_state_end_play(IDirectMusicSegmentState *iface, IDirectMusicPerformance8 *performance)
......
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