Module: wine Branch: master Commit: f13fa16f01d919d6fd10ef5acfe3887bbf99e2ad URL: https://gitlab.winehq.org/wine/wine/-/commit/f13fa16f01d919d6fd10ef5acfe3887...
Author: Rémi Bernon rbernon@codeweavers.com Date: Tue Oct 24 23:27:57 2023 +0200
dmime: Implement IDirectMusicPerformance_GetSegmentState semi-stub.
---
dlls/dmime/dmime_private.h | 1 + dlls/dmime/performance.c | 91 +++++++++++++++++++++++++++++++++++++++++++--- dlls/dmime/segmentstate.c | 6 +++ dlls/dmime/tests/dmime.c | 12 +++--- 4 files changed, 98 insertions(+), 12 deletions(-)
diff --git a/dlls/dmime/dmime_private.h b/dlls/dmime/dmime_private.h index e1a2374facf..3c7fc1e332b 100644 --- a/dlls/dmime/dmime_private.h +++ b/dlls/dmime/dmime_private.h @@ -77,6 +77,7 @@ extern HRESULT segment_state_create(IDirectMusicSegment *segment, MUSIC_TIME sta 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 BOOL segment_state_has_segment(IDirectMusicSegmentState *iface, IDirectMusicSegment *segment);
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 a08c00502d9..17fbe772f5b 100644 --- a/dlls/dmime/performance.c +++ b/dlls/dmime/performance.c @@ -76,6 +76,8 @@ struct performance HANDLE notification_event; BOOL notification_performance; BOOL notification_segment; + + IDirectMusicSegment *primary_segment; };
struct message @@ -338,6 +340,12 @@ HRESULT performance_send_segment_end(IDirectMusicPerformance8 *iface, MUSIC_TIME return S_OK; }
+static void performance_set_primary_segment(struct performance *This, IDirectMusicSegment *segment) +{ + if (This->primary_segment) IDirectMusicSegment_Release(This->primary_segment); + if ((This->primary_segment = segment)) IDirectMusicSegment_AddRef(This->primary_segment); +} + /* IDirectMusicPerformance8 IUnknown part: */ static HRESULT WINAPI performance_QueryInterface(IDirectMusicPerformance8 *iface, REFIID riid, void **ret_iface) { @@ -487,6 +495,42 @@ static HRESULT WINAPI performance_PlaySegment(IDirectMusicPerformance8 *iface, I segment_flags, start_time, ret_state, NULL, NULL); }
+struct state_entry +{ + struct list entry; + IDirectMusicSegmentState *state; +}; + +static void state_entry_destroy(struct state_entry *entry) +{ + list_remove(&entry->entry); + IDirectMusicSegmentState_Release(entry->state); + free(entry); +} + +static void enum_segment_states(struct performance *This, IDirectMusicSegment *segment, struct list *list) +{ + struct state_entry *entry; + struct message *message; + + LIST_FOR_EACH_ENTRY(message, &This->messages, struct message, entry) + { + IDirectMusicSegmentState *message_state; + + if (message->msg.dwType != DMUS_PMSGT_INTERNAL_SEGMENT_TICK + && message->msg.dwType != DMUS_PMSGT_INTERNAL_SEGMENT_END) + continue; + + message_state = (IDirectMusicSegmentState *)message->msg.punkUser; + if (segment && !segment_state_has_segment(message_state, segment)) continue; + + if (!(entry = malloc(sizeof(*entry)))) return; + entry->state = message_state; + IDirectMusicSegmentState_AddRef(entry->state); + list_add_tail(list, &entry->entry); + } +} + static HRESULT WINAPI performance_Stop(IDirectMusicPerformance8 *iface, IDirectMusicSegment *pSegment, IDirectMusicSegmentState *pSegmentState, MUSIC_TIME mtTime, DWORD dwFlags) { @@ -497,12 +541,36 @@ static HRESULT WINAPI performance_Stop(IDirectMusicPerformance8 *iface, IDirectM }
static HRESULT WINAPI performance_GetSegmentState(IDirectMusicPerformance8 *iface, - IDirectMusicSegmentState **ppSegmentState, MUSIC_TIME mtTime) + IDirectMusicSegmentState **state, MUSIC_TIME time) { - struct performance *This = impl_from_IDirectMusicPerformance8(iface); + struct performance *This = impl_from_IDirectMusicPerformance8(iface); + struct list *ptr, states = LIST_INIT(states); + struct state_entry *entry, *next; + HRESULT hr = S_OK;
- FIXME("(%p,%p, %ld): stub\n", This, ppSegmentState, mtTime); - return S_OK; + TRACE("(%p, %p, %ld)\n", This, state, time); + + if (!state) return E_POINTER; + + EnterCriticalSection(&This->safe); + + enum_segment_states(This, This->primary_segment, &states); + + if (!(ptr = list_head(&states))) hr = DMUS_E_NOT_FOUND; + else + { + entry = LIST_ENTRY(ptr, struct state_entry, entry); + + *state = entry->state; + IDirectMusicSegmentState_AddRef(entry->state); + + LIST_FOR_EACH_ENTRY_SAFE(entry, next, &states, struct state_entry, entry) + state_entry_destroy(entry); + } + + LeaveCriticalSection(&This->safe); + + return hr; }
static HRESULT WINAPI performance_SetPrepareTime(IDirectMusicPerformance8 *iface, DWORD dwMilliSeconds) @@ -1152,6 +1220,8 @@ static HRESULT WINAPI performance_CloseDown(IDirectMusicPerformance8 *iface) WARN("Failed to free message %p, hr %#lx\n", message, hr); }
+ performance_set_primary_segment(This, NULL); + if (This->master_clock) { IReferenceClock_Release(This->master_clock); @@ -1278,17 +1348,26 @@ static HRESULT WINAPI performance_PlaySegmentEx(IDirectMusicPerformance8 *iface,
if (FAILED(hr = IUnknown_QueryInterface(source, &IID_IDirectMusicSegment, (void **)&segment))) return hr; + + EnterCriticalSection(&This->safe); + + performance_set_primary_segment(This, segment); + if ((!(music_time = start_time) && FAILED(hr = IDirectMusicPerformance8_GetTime(iface, NULL, &music_time))) || FAILED(hr = segment_state_create(segment, music_time, iface, &state))) { + performance_set_primary_segment(This, NULL); + LeaveCriticalSection(&This->safe); + IDirectMusicSegment_Release(segment); return hr; }
- EnterCriticalSection(&This->safe); - if (FAILED(hr = segment_state_play(state, iface))) + { ERR("Failed to play segment state, hr %#lx\n", hr); + performance_set_primary_segment(This, NULL); + } else if (segment_state) { *segment_state = state; diff --git a/dlls/dmime/segmentstate.c b/dlls/dmime/segmentstate.c index f2f895de881..3e13687254e 100644 --- a/dlls/dmime/segmentstate.c +++ b/dlls/dmime/segmentstate.c @@ -363,3 +363,9 @@ HRESULT segment_state_end_play(IDirectMusicSegmentState *iface, IDirectMusicPerf
return S_OK; } + +BOOL segment_state_has_segment(IDirectMusicSegmentState *iface, IDirectMusicSegment *segment) +{ + struct segment_state *This = impl_from_IDirectMusicSegmentState8((IDirectMusicSegmentState8 *)iface); + return !segment || This->segment == segment; +} diff --git a/dlls/dmime/tests/dmime.c b/dlls/dmime/tests/dmime.c index b15c3a1ac37..7d2dd912237 100644 --- a/dlls/dmime/tests/dmime.c +++ b/dlls/dmime/tests/dmime.c @@ -4054,9 +4054,9 @@ static void test_segment_state(void) check_track_state(track, playing, FALSE);
hr = IDirectMusicPerformance_GetSegmentState(performance, NULL, 0); - todo_wine ok(hr == E_POINTER, "got %#lx\n", hr); + ok(hr == E_POINTER, "got %#lx\n", hr); hr = IDirectMusicPerformance_GetSegmentState(performance, &tmp_state, 0); - todo_wine ok(hr == DMUS_E_NOT_FOUND, "got %#lx\n", hr); + ok(hr == DMUS_E_NOT_FOUND, "got %#lx\n", hr);
tmp_state = state; @@ -4071,14 +4071,14 @@ static void test_segment_state(void) tmp_state = (void *)0xdeadbeef; hr = IDirectMusicPerformance_GetSegmentState(performance, &tmp_state, 0); ok(hr == S_OK, "got %#lx\n", hr); - todo_wine ok(state == tmp_state, "got %p\n", state); - if (tmp_state != (void *)0xdeadbeef) IDirectMusicSegmentState_Release(tmp_state); + ok(state == tmp_state, "got %p\n", state); + IDirectMusicSegmentState_Release(tmp_state);
tmp_state = (void *)0xdeadbeef; hr = IDirectMusicPerformance_GetSegmentState(performance, &tmp_state, 69); ok(hr == S_OK, "got %#lx\n", hr); - todo_wine ok(state == tmp_state, "got %p\n", state); - if (tmp_state != (void *)0xdeadbeef) IDirectMusicSegmentState_Release(tmp_state); + ok(state == tmp_state, "got %p\n", state); + IDirectMusicSegmentState_Release(tmp_state);
hr = IDirectMusicPerformance_GetSegmentState(performance, &tmp_state, 70); todo_wine ok(hr == DMUS_E_NOT_FOUND, "got %#lx\n", hr);