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

dmime: Call IDirectMusicTrack_(Init|End)Play from the segment state.

parent 7a678903
...@@ -71,7 +71,9 @@ extern void set_audiopath_dsound_buffer(IDirectMusicAudioPath*,IDirectSoundBuffe ...@@ -71,7 +71,9 @@ extern void set_audiopath_dsound_buffer(IDirectMusicAudioPath*,IDirectSoundBuffe
extern void set_audiopath_primary_dsound_buffer(IDirectMusicAudioPath*,IDirectSoundBuffer*); extern void set_audiopath_primary_dsound_buffer(IDirectMusicAudioPath*,IDirectSoundBuffer*);
extern HRESULT segment_state_create(IDirectMusicSegment *segment, MUSIC_TIME start_time, extern HRESULT segment_state_create(IDirectMusicSegment *segment, MUSIC_TIME start_time,
IDirectMusicSegmentState **ret_iface); IDirectMusicPerformance *performance, IDirectMusicSegmentState **ret_iface);
extern HRESULT segment_state_play(IDirectMusicSegmentState *iface, IDirectMusicPerformance *performance);
extern HRESULT segment_state_end_play(IDirectMusicSegmentState *iface);
/***************************************************************************** /*****************************************************************************
* Auxiliary definitions * Auxiliary definitions
......
...@@ -1052,7 +1052,14 @@ static HRESULT WINAPI performance_CloseDown(IDirectMusicPerformance8 *iface) ...@@ -1052,7 +1052,14 @@ static HRESULT WINAPI performance_CloseDown(IDirectMusicPerformance8 *iface)
list_remove(&message->entry); list_remove(&message->entry);
list_init(&message->entry); list_init(&message->entry);
if (FAILED(hr = IDirectMusicPerformance8_FreePMsg(iface, &message->msg))) /* process notifications to end any pending segment states */
if (message->msg.dwType == DMUS_PMSGT_NOTIFICATION)
hr = IDirectMusicTool_ProcessPMsg(&This->IDirectMusicTool_iface,
(IDirectMusicPerformance *)iface, &message->msg);
else
hr = DMUS_S_FREE;
if (hr == DMUS_S_FREE && FAILED(hr = IDirectMusicPerformance8_FreePMsg(iface, &message->msg)))
WARN("Failed to free message %p, hr %#lx\n", message, hr); WARN("Failed to free message %p, hr %#lx\n", message, hr);
} }
...@@ -1191,7 +1198,7 @@ static HRESULT WINAPI performance_PlaySegmentEx(IDirectMusicPerformance8 *iface, ...@@ -1191,7 +1198,7 @@ static HRESULT WINAPI performance_PlaySegmentEx(IDirectMusicPerformance8 *iface,
if (FAILED(hr = IUnknown_QueryInterface(source, &IID_IDirectMusicSegment, (void **)&segment))) if (FAILED(hr = IUnknown_QueryInterface(source, &IID_IDirectMusicSegment, (void **)&segment)))
return hr; return hr;
if (FAILED(hr = segment_state_create(segment, start_time, &state))) if (FAILED(hr = segment_state_create(segment, start_time, (IDirectMusicPerformance *)iface, &state)))
{ {
IDirectMusicSegment_Release(segment); IDirectMusicSegment_Release(segment);
return hr; return hr;
...@@ -1208,6 +1215,9 @@ static HRESULT WINAPI performance_PlaySegmentEx(IDirectMusicPerformance8 *iface, ...@@ -1208,6 +1215,9 @@ static HRESULT WINAPI performance_PlaySegmentEx(IDirectMusicPerformance8 *iface,
hr = performance_send_dirty_pmsg(This, start_time); hr = performance_send_dirty_pmsg(This, start_time);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
hr = segment_state_play(state, (IDirectMusicPerformance *)iface);
if (SUCCEEDED(hr))
hr = performance_send_notification_pmsg(This, start_time + length, This->notification_segment, hr = performance_send_notification_pmsg(This, start_time + length, This->notification_segment,
GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGEND, (IUnknown *)state); GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGEND, (IUnknown *)state);
if (SUCCEEDED(hr)) if (SUCCEEDED(hr))
...@@ -1634,6 +1644,13 @@ static HRESULT WINAPI performance_tool_ProcessPMsg(IDirectMusicTool *iface, ...@@ -1634,6 +1644,13 @@ static HRESULT WINAPI performance_tool_ProcessPMsg(IDirectMusicTool *iface,
BOOL enabled = FALSE; BOOL enabled = FALSE;
HRESULT hr; HRESULT hr;
if (IsEqualGUID(&notif->guidNotificationType, &GUID_NOTIFICATION_SEGMENT)
&& notif->dwNotificationOption == DMUS_NOTIFICATION_SEGEND)
{
if (FAILED(hr = segment_state_end_play((IDirectMusicSegmentState *)notif->punkUser)))
WARN("Failed to end segment state %p, hr %#lx\n", notif->punkUser, hr);
}
if (IsEqualGUID(&notif->guidNotificationType, &GUID_NOTIFICATION_PERFORMANCE)) if (IsEqualGUID(&notif->guidNotificationType, &GUID_NOTIFICATION_PERFORMANCE))
enabled = This->notification_performance; enabled = This->notification_performance;
if (IsEqualGUID(&notif->guidNotificationType, &GUID_NOTIFICATION_SEGMENT)) if (IsEqualGUID(&notif->guidNotificationType, &GUID_NOTIFICATION_SEGMENT))
......
...@@ -21,14 +21,39 @@ ...@@ -21,14 +21,39 @@
WINE_DEFAULT_DEBUG_CHANNEL(dmime); WINE_DEFAULT_DEBUG_CHANNEL(dmime);
static DWORD next_track_id;
struct track_entry
{
struct list entry;
IDirectMusicTrack *track;
void *state_data;
DWORD track_id;
};
static void track_entry_destroy(struct track_entry *entry)
{
HRESULT hr;
if (FAILED(hr = IDirectMusicTrack_EndPlay(entry->track, entry->state_data)))
WARN("track %p EndPlay failed, hr %#lx\n", entry->track, hr);
IDirectMusicTrack_Release(entry->track);
free(entry);
}
struct segment_state struct segment_state
{ {
IDirectMusicSegmentState8 IDirectMusicSegmentState8_iface; IDirectMusicSegmentState8 IDirectMusicSegmentState8_iface;
LONG ref; LONG ref;
IDirectMusicSegment *segment; IDirectMusicSegment *segment;
MUSIC_TIME start_point;
MUSIC_TIME start_time; MUSIC_TIME start_time;
MUSIC_TIME start_point;
MUSIC_TIME end_point;
struct list tracks;
}; };
static inline struct segment_state *impl_from_IDirectMusicSegmentState8(IDirectMusicSegmentState8 *iface) static inline struct segment_state *impl_from_IDirectMusicSegmentState8(IDirectMusicSegmentState8 *iface)
...@@ -79,6 +104,7 @@ static ULONG WINAPI segment_state_Release(IDirectMusicSegmentState8 *iface) ...@@ -79,6 +104,7 @@ static ULONG WINAPI segment_state_Release(IDirectMusicSegmentState8 *iface)
if (!ref) if (!ref)
{ {
segment_state_end_play((IDirectMusicSegmentState *)iface);
if (This->segment) IDirectMusicSegment_Release(This->segment); if (This->segment) IDirectMusicSegment_Release(This->segment);
free(This); free(This);
} }
...@@ -174,6 +200,7 @@ HRESULT create_dmsegmentstate(REFIID riid, void **ret_iface) ...@@ -174,6 +200,7 @@ HRESULT create_dmsegmentstate(REFIID riid, void **ret_iface)
obj->IDirectMusicSegmentState8_iface.lpVtbl = &segment_state_vtbl; obj->IDirectMusicSegmentState8_iface.lpVtbl = &segment_state_vtbl;
obj->ref = 1; obj->ref = 1;
obj->start_time = -1; obj->start_time = -1;
list_init(&obj->tracks);
TRACE("Created IDirectMusicSegmentState %p\n", obj); TRACE("Created IDirectMusicSegmentState %p\n", obj);
hr = IDirectMusicSegmentState8_QueryInterface(&obj->IDirectMusicSegmentState8_iface, riid, ret_iface); hr = IDirectMusicSegmentState8_QueryInterface(&obj->IDirectMusicSegmentState8_iface, riid, ret_iface);
...@@ -182,11 +209,13 @@ HRESULT create_dmsegmentstate(REFIID riid, void **ret_iface) ...@@ -182,11 +209,13 @@ HRESULT create_dmsegmentstate(REFIID riid, void **ret_iface)
} }
HRESULT segment_state_create(IDirectMusicSegment *segment, MUSIC_TIME start_time, HRESULT segment_state_create(IDirectMusicSegment *segment, MUSIC_TIME start_time,
IDirectMusicSegmentState **ret_iface) IDirectMusicPerformance *performance, IDirectMusicSegmentState **ret_iface)
{ {
IDirectMusicSegmentState *iface; IDirectMusicSegmentState *iface;
struct segment_state *This; struct segment_state *This;
IDirectMusicTrack *track;
HRESULT hr; HRESULT hr;
UINT i;
TRACE("(%p, %lu, %p)\n", segment, start_time, ret_iface); TRACE("(%p, %lu, %p)\n", segment, start_time, ret_iface);
...@@ -198,8 +227,73 @@ HRESULT segment_state_create(IDirectMusicSegment *segment, MUSIC_TIME start_time ...@@ -198,8 +227,73 @@ HRESULT segment_state_create(IDirectMusicSegment *segment, MUSIC_TIME start_time
This->start_time = start_time; This->start_time = start_time;
hr = IDirectMusicSegment_GetStartPoint(segment, &This->start_point); hr = IDirectMusicSegment_GetStartPoint(segment, &This->start_point);
if (SUCCEEDED(hr)) hr = IDirectMusicSegment_GetLength(segment, &This->end_point);
for (i = 0; SUCCEEDED(hr); i++)
{
DWORD track_id = ++next_track_id;
struct track_entry *entry;
if ((hr = IDirectMusicSegment_GetTrack(segment, &GUID_NULL, -1, i, &track)) != S_OK)
{
if (hr == DMUS_E_NOT_FOUND) hr = S_OK;
break;
}
if (!(entry = malloc(sizeof(*entry))))
hr = E_OUTOFMEMORY;
else if (SUCCEEDED(hr = IDirectMusicTrack_InitPlay(track, iface, performance,
&entry->state_data, track_id, 0)))
{
entry->track = track;
entry->track_id = track_id;
list_add_tail(&This->tracks, &entry->entry);
}
if (FAILED(hr))
{
WARN("Failed to initialize track %p, hr %#lx\n", track, hr);
IDirectMusicTrack_Release(track);
free(entry);
}
}
if (SUCCEEDED(hr)) *ret_iface = iface; if (SUCCEEDED(hr)) *ret_iface = iface;
else IDirectMusicSegmentState_Release(iface); else IDirectMusicSegmentState_Release(iface);
return hr; return hr;
} }
HRESULT segment_state_play(IDirectMusicSegmentState *iface, IDirectMusicPerformance *performance)
{
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;
struct track_entry *entry;
HRESULT hr = S_OK;
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, 0, track_flags, performance, iface, entry->track_id)))
{
WARN("Failed to play track %p, hr %#lx\n", entry->track, hr);
break;
}
}
return hr;
}
HRESULT segment_state_end_play(IDirectMusicSegmentState *iface)
{
struct segment_state *This = impl_from_IDirectMusicSegmentState8((IDirectMusicSegmentState8 *)iface);
struct track_entry *entry, *next;
LIST_FOR_EACH_ENTRY_SAFE(entry, next, &This->tracks, struct track_entry, entry)
{
list_remove(&entry->entry);
track_entry_destroy(entry);
}
return S_OK;
}
...@@ -662,7 +662,7 @@ static HRESULT WINAPI test_track_Play(IDirectMusicTrack *iface, void *state_data ...@@ -662,7 +662,7 @@ static HRESULT WINAPI test_track_Play(IDirectMusicTrack *iface, void *state_data
ok(state_data == &This->data, "got %p\n", state_data); ok(state_data == &This->data, "got %p\n", state_data);
ok(start_time == 50, "got %lu\n", start_time); ok(start_time == 50, "got %lu\n", start_time);
ok(end_time == 100, "got %lu\n", end_time); ok(end_time == 100, "got %lu\n", end_time);
ok(time_offset < 0, "got %lu\n", time_offset); todo_wine ok(time_offset < 0, "got %lu\n", time_offset);
ok(segment_flags == (DMUS_TRACKF_DIRTY|DMUS_TRACKF_START|DMUS_TRACKF_SEEK), ok(segment_flags == (DMUS_TRACKF_DIRTY|DMUS_TRACKF_START|DMUS_TRACKF_SEEK),
"got %#lx\n", segment_flags); "got %#lx\n", segment_flags);
ok(!!performance, "got %p\n", performance); ok(!!performance, "got %p\n", performance);
...@@ -3990,7 +3990,7 @@ static void test_segment_state(void) ...@@ -3990,7 +3990,7 @@ static void test_segment_state(void)
IDirectMusicSegmentState_Release(tmp_state); IDirectMusicSegmentState_Release(tmp_state);
check_track_state(track, downloaded, FALSE); check_track_state(track, downloaded, FALSE);
todo_wine check_track_state(track, initialized, TRUE); check_track_state(track, initialized, TRUE);
/* The track can be removed from the segment */ /* The track can be removed from the segment */
...@@ -4001,10 +4001,10 @@ static void test_segment_state(void) ...@@ -4001,10 +4001,10 @@ static void test_segment_state(void)
/* This might be timing dependent and if PlaySegment is already /* This might be timing dependent and if PlaySegment is already
* late, the tracks are played synchronously and right away. * late, the tracks are played synchronously and right away.
*/ */
check_track_state(track, playing, FALSE); todo_wine check_track_state(track, playing, FALSE);
ret = test_track_wait_playing(track, 50); ret = test_track_wait_playing(track, 50);
todo_wine ok(ret == 0, "got %#lx\n", ret); ok(ret == 0, "got %#lx\n", ret);
tmp_segment = (void *)0xdeadbeef; tmp_segment = (void *)0xdeadbeef;
...@@ -4064,14 +4064,14 @@ static void test_segment_state(void) ...@@ -4064,14 +4064,14 @@ static void test_segment_state(void)
check_track_state(track, downloaded, FALSE); check_track_state(track, downloaded, FALSE);
todo_wine check_track_state(track, initialized, TRUE); check_track_state(track, initialized, TRUE);
todo_wine check_track_state(track, playing, TRUE); check_track_state(track, playing, TRUE);
hr = IDirectMusicPerformance_CloseDown(performance); hr = IDirectMusicPerformance_CloseDown(performance);
ok(hr == S_OK, "got %#lx\n", hr); ok(hr == S_OK, "got %#lx\n", hr);
check_track_state(track, downloaded, FALSE); check_track_state(track, downloaded, FALSE);
todo_wine check_track_state(track, initialized, TRUE); check_track_state(track, initialized, TRUE);
check_track_state(track, playing, FALSE); check_track_state(track, playing, FALSE);
......
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