The segment end change will be useful to better handle segment end and stop. Using the notification messages makes it unpredictable and more difficult to test, as they are asynchronously sent, added and removed.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/dmime_private.h | 6 +++--- dlls/dmime/performance.c | 7 ++++--- dlls/dmime/segmentstate.c | 12 ++++++------ 3 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/dlls/dmime/dmime_private.h b/dlls/dmime/dmime_private.h index 7f1937eaa0f..860b4ef385c 100644 --- a/dlls/dmime/dmime_private.h +++ b/dlls/dmime/dmime_private.h @@ -73,9 +73,9 @@ extern void set_audiopath_dsound_buffer(IDirectMusicAudioPath*,IDirectSoundBuffe extern void set_audiopath_primary_dsound_buffer(IDirectMusicAudioPath*,IDirectSoundBuffer*);
extern HRESULT segment_state_create(IDirectMusicSegment *segment, MUSIC_TIME start_time, - IDirectMusicPerformance *performance, IDirectMusicSegmentState **ret_iface); -extern HRESULT segment_state_play(IDirectMusicSegmentState *iface, IDirectMusicPerformance *performance); -extern HRESULT segment_state_end_play(IDirectMusicSegmentState *iface, IDirectMusicPerformance *performance); + IDirectMusicPerformance8 *performance, IDirectMusicSegmentState **ret_iface); +extern HRESULT segment_state_play(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); diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index e0da0516c79..8459de00b3f 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -1196,7 +1196,7 @@ static HRESULT WINAPI performance_PlaySegmentEx(IDirectMusicPerformance8 *iface,
if (FAILED(hr = IUnknown_QueryInterface(source, &IID_IDirectMusicSegment, (void **)&segment))) return hr; - if (FAILED(hr = segment_state_create(segment, start_time, (IDirectMusicPerformance *)iface, &state))) + if (FAILED(hr = segment_state_create(segment, start_time, iface, &state))) { IDirectMusicSegment_Release(segment); return hr; @@ -1213,7 +1213,7 @@ static HRESULT WINAPI performance_PlaySegmentEx(IDirectMusicPerformance8 *iface, hr = performance_send_dirty_pmsg(This, start_time);
if (SUCCEEDED(hr)) - hr = segment_state_play(state, (IDirectMusicPerformance *)iface); + hr = segment_state_play(state, iface);
if (SUCCEEDED(hr)) hr = performance_send_notification_pmsg(This, start_time + length, This->notification_segment, @@ -1767,7 +1767,8 @@ static HRESULT WINAPI performance_tool_ProcessPMsg(IDirectMusicTool *iface, if (IsEqualGUID(¬if->guidNotificationType, &GUID_NOTIFICATION_SEGMENT) && notif->dwNotificationOption == DMUS_NOTIFICATION_SEGEND) { - if (FAILED(hr = segment_state_end_play((IDirectMusicSegmentState *)notif->punkUser, performance))) + if (FAILED(hr = segment_state_end_play((IDirectMusicSegmentState *)notif->punkUser, + (IDirectMusicPerformance8 *)performance))) WARN("Failed to end segment state %p, hr %#lx\n", notif->punkUser, hr); }
diff --git a/dlls/dmime/segmentstate.c b/dlls/dmime/segmentstate.c index c43d833fedd..89534f7342d 100644 --- a/dlls/dmime/segmentstate.c +++ b/dlls/dmime/segmentstate.c @@ -209,7 +209,7 @@ HRESULT create_dmsegmentstate(REFIID riid, void **ret_iface) }
HRESULT segment_state_create(IDirectMusicSegment *segment, MUSIC_TIME start_time, - IDirectMusicPerformance *performance, IDirectMusicSegmentState **ret_iface) + IDirectMusicPerformance8 *performance, IDirectMusicSegmentState **ret_iface) { IDirectMusicSegmentState *iface; struct segment_state *This; @@ -225,7 +225,7 @@ HRESULT segment_state_create(IDirectMusicSegment *segment, MUSIC_TIME start_time This->segment = segment; IDirectMusicSegment_AddRef(This->segment);
- if (SUCCEEDED(hr = IDirectMusicPerformance_GetGlobalParam(performance, &GUID_PerfAutoDownload, + if (SUCCEEDED(hr = IDirectMusicPerformance8_GetGlobalParam(performance, &GUID_PerfAutoDownload, &This->auto_download, sizeof(This->auto_download))) && This->auto_download) hr = IDirectMusicSegment_SetParam(segment, &GUID_DownloadToAudioPath, -1, DMUS_SEG_ALLTRACKS, 0, performance); @@ -247,7 +247,7 @@ HRESULT segment_state_create(IDirectMusicSegment *segment, MUSIC_TIME start_time
if (!(entry = malloc(sizeof(*entry)))) hr = E_OUTOFMEMORY; - else if (SUCCEEDED(hr = IDirectMusicTrack_InitPlay(track, iface, performance, + else if (SUCCEEDED(hr = IDirectMusicTrack_InitPlay(track, iface, (IDirectMusicPerformance *)performance, &entry->state_data, track_id, 0))) { entry->track = track; @@ -268,7 +268,7 @@ HRESULT segment_state_create(IDirectMusicSegment *segment, MUSIC_TIME start_time return hr; }
-HRESULT segment_state_play(IDirectMusicSegmentState *iface, IDirectMusicPerformance *performance) +HRESULT segment_state_play(IDirectMusicSegmentState *iface, IDirectMusicPerformance8 *performance) { struct segment_state *This = impl_from_IDirectMusicSegmentState8((IDirectMusicSegmentState8 *)iface); DWORD track_flags = DMUS_TRACKF_DIRTY | DMUS_TRACKF_START | DMUS_TRACKF_SEEK; @@ -279,7 +279,7 @@ HRESULT segment_state_play(IDirectMusicSegmentState *iface, IDirectMusicPerforma 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))) + end_time, 0, track_flags, (IDirectMusicPerformance *)performance, iface, entry->track_id))) { WARN("Failed to play track %p, hr %#lx\n", entry->track, hr); break; @@ -289,7 +289,7 @@ HRESULT segment_state_play(IDirectMusicSegmentState *iface, IDirectMusicPerforma return hr; }
-HRESULT segment_state_end_play(IDirectMusicSegmentState *iface, IDirectMusicPerformance *performance) +HRESULT segment_state_end_play(IDirectMusicSegmentState *iface, IDirectMusicPerformance8 *performance) { struct segment_state *This = impl_from_IDirectMusicSegmentState8((IDirectMusicSegmentState8 *)iface); struct track_entry *entry, *next;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/segmentstate.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/dlls/dmime/segmentstate.c b/dlls/dmime/segmentstate.c index 89534f7342d..b4bb784de0d 100644 --- a/dlls/dmime/segmentstate.c +++ b/dlls/dmime/segmentstate.c @@ -278,8 +278,8 @@ HRESULT segment_state_play(IDirectMusicSegmentState *iface, IDirectMusicPerforma
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, (IDirectMusicPerformance *)performance, iface, entry->track_id))) + 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))) { WARN("Failed to play track %p, hr %#lx\n", entry->track, hr); break;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmband/bandtrack.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/dlls/dmband/bandtrack.c b/dlls/dmband/bandtrack.c index 0ec14483c33..f2a40c21751 100644 --- a/dlls/dmband/bandtrack.c +++ b/dlls/dmband/bandtrack.c @@ -174,7 +174,6 @@ static HRESULT WINAPI band_track_Play(IDirectMusicTrack8 *iface, void *state_dat
if (start_time != 0) FIXME("start_time %ld not implemented\n", start_time); if (end_time != -1) FIXME("end_time %ld not implemented\n", end_time); - if (time_offset != 0) FIXME("time_offset %ld not implemented\n", time_offset); if (segment_flags) FIXME("segment_flags %#lx not implemented\n", segment_flags); if (segment_state) FIXME("segment_state %p not implemented\n", segment_state);
@@ -184,8 +183,9 @@ static HRESULT WINAPI band_track_Play(IDirectMusicTrack8 *iface, void *state_dat
LIST_FOR_EACH_ENTRY(entry, &This->bands, struct band_entry, entry) { - if (FAILED(hr = band_send_messages(entry->band, performance, graph, - entry->head.lBandTimeLogical, track_id))) + MUSIC_TIME music_time = entry->head.lBandTimeLogical; + if (music_time != -1) music_time += time_offset; + if (FAILED(hr = band_send_messages(entry->band, performance, graph, music_time, track_id))) break; }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/seqtrack.c | 5 ++--- dlls/dmime/wavetrack.c | 3 +-- 2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/dlls/dmime/seqtrack.c b/dlls/dmime/seqtrack.c index b532fc48ca6..56c61c02576 100644 --- a/dlls/dmime/seqtrack.c +++ b/dlls/dmime/seqtrack.c @@ -122,7 +122,6 @@ static HRESULT WINAPI sequence_track_Play(IDirectMusicTrack8 *iface, void *state
if (start_time != 0) FIXME("start_time %ld not implemented\n", start_time); if (end_time != -1) FIXME("end_time %ld not implemented\n", end_time); - if (time_offset != 0) FIXME("time_offset %ld not implemented\n", time_offset); if (segment_flags) FIXME("segment_flags %#lx not implemented\n", segment_flags); if (segment_state) FIXME("segment_state %p not implemented\n", segment_state);
@@ -139,7 +138,7 @@ static HRESULT WINAPI sequence_track_Play(IDirectMusicTrack8 *iface, void *state (DMUS_PMSG **)&msg))) break;
- msg->mtTime = item->mtTime; + msg->mtTime = item->mtTime + time_offset; msg->dwFlags = DMUS_PMSGF_MUSICTIME; msg->dwPChannel = item->dwPChannel; msg->dwVirtualTrackID = track_id; @@ -169,7 +168,7 @@ static HRESULT WINAPI sequence_track_Play(IDirectMusicTrack8 *iface, void *state (DMUS_PMSG **)&msg))) break;
- msg->mtTime = item->mtStart; + msg->mtTime = item->mtStart + time_offset; msg->dwFlags = DMUS_PMSGF_MUSICTIME; msg->dwPChannel = item->dwPChannel; msg->dwVirtualTrackID = track_id; diff --git a/dlls/dmime/wavetrack.c b/dlls/dmime/wavetrack.c index 5ba9fb675f5..974e656cfe5 100644 --- a/dlls/dmime/wavetrack.c +++ b/dlls/dmime/wavetrack.c @@ -159,7 +159,6 @@ static HRESULT WINAPI wave_track_Play(IDirectMusicTrack8 *iface, void *state_dat
if (start_time != 0) FIXME("start_time %ld not implemented\n", start_time); if (end_time != -1) FIXME("end_time %ld not implemented\n", end_time); - if (time_offset != 0) FIXME("time_offset %ld not implemented\n", time_offset); if (segment_flags) FIXME("segment_flags %#lx not implemented\n", segment_flags); if (segment_state) FIXME("segment_state %p not implemented\n", segment_state);
@@ -181,7 +180,7 @@ static HRESULT WINAPI wave_track_Play(IDirectMusicTrack8 *iface, void *state_dat (DMUS_PMSG **)&msg))) break;
- msg->mtTime = item->header.rtTime; + msg->mtTime = item->header.rtTime + time_offset; msg->dwFlags = DMUS_PMSGF_MUSICTIME; msg->dwPChannel = part->header.dwPChannel; msg->dwVirtualTrackID = track_id;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dmime/dmime_private.h | 2 ++ dlls/dmime/performance.c | 50 ++++++++++++++++++++++++++------------ dlls/dmime/segmentstate.c | 5 +++- 3 files changed, 40 insertions(+), 17 deletions(-)
diff --git a/dlls/dmime/dmime_private.h b/dlls/dmime/dmime_private.h index 860b4ef385c..28836694ed9 100644 --- a/dlls/dmime/dmime_private.h +++ b/dlls/dmime/dmime_private.h @@ -81,6 +81,8 @@ extern HRESULT wave_track_create_from_chunk(IStream *stream, struct chunk_entry IDirectMusicTrack8 **ret_iface);
extern HRESULT performance_get_dsound(IDirectMusicPerformance8 *iface, IDirectSound **dsound); +extern HRESULT performance_send_segment_end(IDirectMusicPerformance8 *iface, MUSIC_TIME music_time, + IDirectMusicSegmentState *state);
/***************************************************************************** * Auxiliary definitions diff --git a/dlls/dmime/performance.c b/dlls/dmime/performance.c index 8459de00b3f..942452d353e 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -24,6 +24,12 @@
WINE_DEFAULT_DEBUG_CHANNEL(dmime);
+enum dmus_internal_message_type +{ + DMUS_PMSGT_INTERNAL_FIRST = 0x10, + DMUS_PMSGT_INTERNAL_SEGMENT_END = DMUS_PMSGT_INTERNAL_FIRST, +}; + struct pchannel_block { DWORD block_num; /* Block 0 is PChannels 0-15, Block 1 is PChannels 16-31, etc */ struct { @@ -158,7 +164,8 @@ static DWORD WINAPI message_thread_proc(void *args) return 0; }
-static HRESULT performance_send_dirty_pmsg(struct performance *This, MUSIC_TIME music_time) +static HRESULT performance_send_pmsg(struct performance *This, MUSIC_TIME music_time, DWORD flags, + DWORD type, IUnknown *object) { IDirectMusicPerformance8 *performance = &This->IDirectMusicPerformance8_iface; IDirectMusicGraph *graph = &This->IDirectMusicGraph_iface; @@ -169,10 +176,11 @@ static HRESULT performance_send_dirty_pmsg(struct performance *This, MUSIC_TIME return hr;
msg->mtTime = music_time; - msg->dwFlags = DMUS_PMSGF_MUSICTIME | DMUS_PMSGF_TOOL_QUEUE; - msg->dwType = DMUS_PMSGT_DIRTY; + msg->dwFlags = DMUS_PMSGF_MUSICTIME | flags; + msg->dwType = type; + if ((msg->punkUser = object)) IUnknown_AddRef(object);
- if (FAILED(hr = IDirectMusicGraph_StampPMsg(graph, msg)) + if ((type < DMUS_PMSGT_INTERNAL_FIRST && FAILED(hr = IDirectMusicGraph_StampPMsg(graph, msg))) || FAILED(hr = IDirectMusicPerformance8_SendPMsg(performance, msg))) IDirectMusicPerformance8_FreePMsg(performance, msg);
@@ -252,6 +260,19 @@ static inline struct performance *impl_from_IDirectMusicPerformance8(IDirectMusi return CONTAINING_RECORD(iface, struct performance, IDirectMusicPerformance8_iface); }
+HRESULT performance_send_segment_end(IDirectMusicPerformance8 *iface, MUSIC_TIME music_time, + IDirectMusicSegmentState *state) +{ + struct performance *This = impl_from_IDirectMusicPerformance8(iface); + HRESULT hr; + + if (FAILED(hr = performance_send_pmsg(This, music_time, DMUS_PMSGF_TOOL_ATTIME, + DMUS_PMSGT_INTERNAL_SEGMENT_END, (IUnknown *)state))) + return hr; + + return S_OK; +} + /* IDirectMusicPerformance8 IUnknown part: */ static HRESULT WINAPI performance_QueryInterface(IDirectMusicPerformance8 *iface, REFIID riid, void **ret_iface) { @@ -1050,8 +1071,7 @@ static HRESULT WINAPI performance_CloseDown(IDirectMusicPerformance8 *iface) list_remove(&message->entry); list_init(&message->entry);
- /* process notifications to end any pending segment states */ - if (message->msg.dwType == DMUS_PMSGT_NOTIFICATION) + if (message->msg.dwType == DMUS_PMSGT_INTERNAL_SEGMENT_END) hr = IDirectMusicTool_ProcessPMsg(&This->IDirectMusicTool_iface, (IDirectMusicPerformance *)iface, &message->msg); else @@ -1210,7 +1230,7 @@ static HRESULT WINAPI performance_PlaySegmentEx(IDirectMusicPerformance8 *iface, hr = performance_send_notification_pmsg(This, start_time, This->notification_segment, GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGSTART, (IUnknown *)state); if (SUCCEEDED(hr)) - hr = performance_send_dirty_pmsg(This, start_time); + hr = performance_send_pmsg(This, start_time, DMUS_PMSGF_TOOL_QUEUE, DMUS_PMSGT_DIRTY, NULL);
if (SUCCEEDED(hr)) hr = segment_state_play(state, iface); @@ -1222,7 +1242,7 @@ static HRESULT WINAPI performance_PlaySegmentEx(IDirectMusicPerformance8 *iface, hr = performance_send_notification_pmsg(This, start_time + length, This->notification_segment, GUID_NOTIFICATION_SEGMENT, DMUS_NOTIFICATION_SEGALMOSTEND, (IUnknown *)state); if (SUCCEEDED(hr)) - hr = performance_send_dirty_pmsg(This, start_time + length); + hr = performance_send_pmsg(This, start_time + length, DMUS_PMSGF_TOOL_QUEUE, DMUS_PMSGT_DIRTY, NULL); if (SUCCEEDED(hr)) hr = performance_send_notification_pmsg(This, start_time + length, This->notification_performance, GUID_NOTIFICATION_PERFORMANCE, DMUS_NOTIFICATION_MUSICSTOPPED, NULL); @@ -1764,14 +1784,6 @@ static HRESULT WINAPI performance_tool_ProcessPMsg(IDirectMusicTool *iface, struct message *previous; BOOL enabled = FALSE;
- if (IsEqualGUID(¬if->guidNotificationType, &GUID_NOTIFICATION_SEGMENT) - && notif->dwNotificationOption == DMUS_NOTIFICATION_SEGEND) - { - if (FAILED(hr = segment_state_end_play((IDirectMusicSegmentState *)notif->punkUser, - (IDirectMusicPerformance8 *)performance))) - WARN("Failed to end segment state %p, hr %#lx\n", notif->punkUser, hr); - } - if (IsEqualGUID(¬if->guidNotificationType, &GUID_NOTIFICATION_PERFORMANCE)) enabled = This->notification_performance; if (IsEqualGUID(¬if->guidNotificationType, &GUID_NOTIFICATION_SEGMENT)) @@ -1799,6 +1811,12 @@ static HRESULT WINAPI performance_tool_ProcessPMsg(IDirectMusicTool *iface, WARN("Failed to play wave buffer, hr %#lx\n", hr); break;
+ case DMUS_PMSGT_INTERNAL_SEGMENT_END: + if (FAILED(hr = segment_state_end_play((IDirectMusicSegmentState *)msg->punkUser, + (IDirectMusicPerformance8 *)performance))) + WARN("Failed to end segment state %p, hr %#lx\n", msg->punkUser, hr); + break; + default: FIXME("Unhandled message type %#lx\n", msg->dwType); break; diff --git a/dlls/dmime/segmentstate.c b/dlls/dmime/segmentstate.c index b4bb784de0d..21b98ccc14c 100644 --- a/dlls/dmime/segmentstate.c +++ b/dlls/dmime/segmentstate.c @@ -214,8 +214,8 @@ HRESULT segment_state_create(IDirectMusicSegment *segment, MUSIC_TIME start_time IDirectMusicSegmentState *iface; struct segment_state *This; IDirectMusicTrack *track; + UINT i, duration; HRESULT hr; - UINT i;
TRACE("(%p, %lu, %p)\n", segment, start_time, ret_iface);
@@ -263,6 +263,9 @@ HRESULT segment_state_create(IDirectMusicSegment *segment, MUSIC_TIME start_time } }
+ duration = This->end_point - This->start_point; + if (SUCCEEDED(hr)) hr = performance_send_segment_end(performance, start_time + duration, iface); + if (SUCCEEDED(hr)) *ret_iface = iface; else IDirectMusicSegmentState_Release(iface); return hr;
Test failures are unrelated in ddraw1.c and win.c
This merge request was approved by Michael Stefaniuc.