Skip to content

Commit 5f04740

Browse files
rbernonjulliard
authored andcommitted
dmime: Pass the DMUS_PMSG through the performance graph.
1 parent 0a93c69 commit 5f04740

File tree

2 files changed

+133
-112
lines changed

2 files changed

+133
-112
lines changed

dlls/dmime/performance.c

+114-89
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,10 @@ struct performance
6262
DWORD procThreadId;
6363
BOOL procThreadTicStarted;
6464
CRITICAL_SECTION safe;
65-
struct list immediate_messages;
66-
struct list queued_messages;
6765

6866
IReferenceClock *master_clock;
6967
REFERENCE_TIME init_time;
68+
struct list messages;
7069
};
7170

7271
struct message
@@ -80,99 +79,109 @@ static inline struct message *message_from_DMUS_PMSG(DMUS_PMSG *msg)
8079
return msg ? CONTAINING_RECORD(msg, struct message, msg) : NULL;
8180
}
8281

82+
static HRESULT performance_process_message(struct performance *This, DMUS_PMSG *msg, DWORD *timeout)
83+
{
84+
static const DWORD delivery_flags = DMUS_PMSGF_TOOL_IMMEDIATE | DMUS_PMSGF_TOOL_QUEUE | DMUS_PMSGF_TOOL_ATTIME;
85+
IDirectMusicPerformance *performance = (IDirectMusicPerformance *)&This->IDirectMusicPerformance8_iface;
86+
HRESULT hr;
87+
88+
do
89+
{
90+
REFERENCE_TIME current, offset = 0;
91+
IDirectMusicTool *tool;
92+
93+
if (FAILED(hr = IDirectMusicPerformance_GetTime(performance, &current, NULL))) return hr;
94+
if (!(tool = msg->pTool)) tool = &This->IDirectMusicTool_iface;
95+
96+
switch (msg->dwFlags & delivery_flags)
97+
{
98+
default:
99+
WARN("No delivery flag found for message %p\n", msg);
100+
/* fallthrough */
101+
case DMUS_PMSGF_TOOL_IMMEDIATE:
102+
hr = IDirectMusicTool_ProcessPMsg(tool, performance, msg);
103+
break;
104+
case DMUS_PMSGF_TOOL_QUEUE:
105+
offset = This->dwBumperLength * 10000;
106+
/* fallthrough */
107+
case DMUS_PMSGF_TOOL_ATTIME:
108+
if (msg->rtTime >= offset && msg->rtTime - offset >= current)
109+
{
110+
if (timeout) *timeout = (msg->rtTime - offset - current) / 10000;
111+
return DMUS_S_REQUEUE;
112+
}
113+
114+
hr = IDirectMusicTool_ProcessPMsg(tool, performance, msg);
115+
break;
116+
}
117+
} while (hr == DMUS_S_REQUEUE);
118+
119+
if (hr == DMUS_S_FREE) hr = IDirectMusicPerformance_FreePMsg(performance, msg);
120+
if (FAILED(hr)) WARN("Failed to process message, hr %#lx\n", hr);
121+
return hr;
122+
}
123+
83124
#define PROCESSMSG_START (WM_APP + 0)
84125
#define PROCESSMSG_EXIT (WM_APP + 1)
85126
#define PROCESSMSG_REMOVE (WM_APP + 2)
86127
#define PROCESSMSG_ADD (WM_APP + 4)
87128

129+
static DWORD WINAPI ProcessMsgThread(LPVOID lpParam)
130+
{
131+
struct performance *This = lpParam;
132+
DWORD timeout = INFINITE;
133+
MSG msg;
134+
HRESULT hr;
135+
struct message *message, *next;
88136

89-
static struct message *ProceedMsg(struct performance *This, struct message *cur)
90-
{
91-
if (cur->msg.dwType == DMUS_PMSGT_NOTIFICATION) {
92-
SetEvent(This->hNotification);
93-
}
94-
list_remove(&cur->entry);
95-
list_init(&cur->entry);
96-
switch (cur->msg.dwType) {
97-
case DMUS_PMSGT_WAVE:
98-
case DMUS_PMSGT_TEMPO:
99-
case DMUS_PMSGT_STOP:
100-
default:
101-
FIXME("Unhandled PMsg Type: %#lx\n", cur->msg.dwType);
102-
break;
103-
}
104-
return cur;
105-
}
137+
while (TRUE)
138+
{
139+
if (timeout > 0) MsgWaitForMultipleObjects(0, NULL, FALSE, timeout, QS_POSTMESSAGE | QS_SENDMESSAGE | QS_TIMER);
140+
timeout = INFINITE;
106141

107-
static DWORD WINAPI ProcessMsgThread(LPVOID lpParam) {
108-
struct performance *This = lpParam;
109-
DWORD timeOut = INFINITE;
110-
MSG msg;
111-
HRESULT hr;
112-
REFERENCE_TIME rtCurTime;
113-
struct message *message, *next;
114-
struct message *cur = NULL;
142+
EnterCriticalSection(&This->safe);
115143

116-
while (TRUE) {
117-
DWORD dwDec = This->rtLatencyTime + This->dwBumperLength;
144+
LIST_FOR_EACH_ENTRY_SAFE(message, next, &This->messages, struct message, entry)
145+
{
146+
list_remove(&message->entry);
147+
list_init(&message->entry);
118148

119-
if (timeOut > 0) MsgWaitForMultipleObjects(0, NULL, FALSE, timeOut, QS_POSTMESSAGE|QS_SENDMESSAGE|QS_TIMER);
120-
timeOut = INFINITE;
149+
hr = performance_process_message(This, &message->msg, &timeout);
150+
if (hr == DMUS_S_REQUEUE) list_add_before(&next->entry, &message->entry);
151+
if (hr != S_OK) break;
152+
}
121153

122-
EnterCriticalSection(&This->safe);
123-
hr = IDirectMusicPerformance8_GetTime(&This->IDirectMusicPerformance8_iface, &rtCurTime, NULL);
124-
if (FAILED(hr)) {
125-
goto outrefresh;
126-
}
127-
128-
LIST_FOR_EACH_ENTRY_SAFE(message, next, &This->immediate_messages, struct message, entry)
129-
{
130-
cur = ProceedMsg(This, message);
131-
free(cur);
132-
}
154+
LeaveCriticalSection(&This->safe);
133155

134-
LIST_FOR_EACH_ENTRY_SAFE(message, next, &This->queued_messages, struct message, entry)
135-
{
136-
timeOut = (message->msg.rtTime - rtCurTime) + This->rtLatencyTime;
137-
if (message->msg.rtTime >= rtCurTime + dwDec) break;
138-
cur = ProceedMsg(This, message);
139-
free(cur);
140-
}
156+
while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
157+
{
158+
/** if hwnd we suppose that is a windows event ... */
159+
if (NULL != msg.hwnd)
160+
{
161+
TranslateMessage(&msg);
162+
DispatchMessageA(&msg);
163+
}
164+
else
165+
{
166+
switch (msg.message)
167+
{
168+
case WM_QUIT:
169+
case PROCESSMSG_EXIT: goto outofthread;
170+
case PROCESSMSG_START: break;
171+
case PROCESSMSG_ADD: break;
172+
case PROCESSMSG_REMOVE: break;
173+
default: ERR("Unhandled message %u. Critical Path\n", msg.message); break;
174+
}
175+
}
176+
}
141177

142-
outrefresh:
143-
LeaveCriticalSection(&This->safe);
144-
145-
while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) {
146-
/** if hwnd we suppose that is a windows event ... */
147-
if (NULL != msg.hwnd) {
148-
TranslateMessage(&msg);
149-
DispatchMessageA(&msg);
150-
} else {
151-
switch (msg.message) {
152-
case WM_QUIT:
153-
case PROCESSMSG_EXIT:
154-
goto outofthread;
155-
case PROCESSMSG_START:
156-
break;
157-
case PROCESSMSG_ADD:
158-
break;
159-
case PROCESSMSG_REMOVE:
160-
break;
161-
default:
162-
ERR("Unhandled message %u. Critical Path\n", msg.message);
163-
break;
164-
}
165-
}
178+
/** here we should run a little of current AudioPath */
166179
}
167180

168-
/** here we should run a little of current AudioPath */
169-
170-
}
171-
172181
outofthread:
173-
TRACE("(%p): Exiting\n", This);
174-
175-
return 0;
182+
TRACE("(%p): Exiting\n", This);
183+
184+
return 0;
176185
}
177186

178187
static BOOL PostMessageToProcessMsgThread(struct performance *This, UINT iMsg) {
@@ -389,9 +398,9 @@ static HRESULT WINAPI performance_GetBumperLength(IDirectMusicPerformance8 *ifac
389398

390399
static HRESULT WINAPI performance_SendPMsg(IDirectMusicPerformance8 *iface, DMUS_PMSG *msg)
391400
{
401+
const DWORD delivery_flags = DMUS_PMSGF_TOOL_IMMEDIATE | DMUS_PMSGF_TOOL_QUEUE | DMUS_PMSGF_TOOL_ATTIME;
392402
struct performance *This = impl_from_IDirectMusicPerformance8(iface);
393403
struct message *message, *next;
394-
struct list *queue;
395404
HRESULT hr;
396405

397406
FIXME("(%p, %p): semi-stub\n", This, msg);
@@ -400,15 +409,13 @@ static HRESULT WINAPI performance_SendPMsg(IDirectMusicPerformance8 *iface, DMUS
400409
if (!This->dmusic) return DMUS_E_NO_MASTER_CLOCK;
401410
if (!(msg->dwFlags & (DMUS_PMSGF_MUSICTIME | DMUS_PMSGF_REFTIME))) return E_INVALIDARG;
402411

403-
if (msg->dwFlags & DMUS_PMSGF_TOOL_IMMEDIATE) queue = &This->immediate_messages;
404-
else queue = &This->queued_messages;
405-
406412
EnterCriticalSection(&This->safe);
407413

408414
if (!list_empty(&message->entry))
409415
hr = DMUS_E_ALREADY_SENT;
410416
else
411417
{
418+
if (!(msg->dwFlags & delivery_flags)) msg->dwFlags |= DMUS_PMSGF_TOOL_IMMEDIATE;
412419
if (!(msg->dwFlags & DMUS_PMSGF_MUSICTIME))
413420
{
414421
if (FAILED(hr = IDirectMusicPerformance8_ReferenceToMusicTime(iface,
@@ -424,9 +431,16 @@ static HRESULT WINAPI performance_SendPMsg(IDirectMusicPerformance8 *iface, DMUS
424431
msg->dwFlags |= DMUS_PMSGF_REFTIME;
425432
}
426433

427-
LIST_FOR_EACH_ENTRY(next, queue, struct message, entry)
434+
if (msg->dwFlags & DMUS_PMSGF_TOOL_IMMEDIATE)
435+
{
436+
hr = performance_process_message(This, &message->msg, NULL);
437+
if (hr != DMUS_S_REQUEUE) goto done;
438+
}
439+
440+
LIST_FOR_EACH_ENTRY(next, &This->messages, struct message, entry)
428441
if (next->msg.rtTime >= message->msg.rtTime) break;
429442
list_add_before(&next->entry, &message->entry);
443+
PostThreadMessageW(This->procThreadId, PROCESSMSG_ADD, 0, 0);
430444

431445
hr = S_OK;
432446
}
@@ -1440,8 +1454,20 @@ static HRESULT WINAPI performance_tool_ProcessPMsg(IDirectMusicTool *iface,
14401454
IDirectMusicPerformance *performance, DMUS_PMSG *msg)
14411455
{
14421456
struct performance *This = impl_from_IDirectMusicTool(iface);
1443-
FIXME("(%p, %p, %p): stub\n", This, performance, msg);
1444-
return E_NOTIMPL;
1457+
1458+
FIXME("(%p, %p, %p): semi-stub\n", This, performance, msg);
1459+
1460+
switch (msg->dwType)
1461+
{
1462+
case DMUS_PMSGT_NOTIFICATION:
1463+
SetEvent(This->hNotification);
1464+
/* fallthrough */
1465+
default:
1466+
FIXME("Unhandled message type %#lx\n", msg->dwType);
1467+
break;
1468+
}
1469+
1470+
return DMUS_S_FREE;
14451471
}
14461472

14471473
static HRESULT WINAPI performance_tool_Flush(IDirectMusicTool *iface,
@@ -1485,8 +1511,7 @@ HRESULT create_dmperformance(REFIID iid, void **ret_iface)
14851511
obj->safe.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": performance->safe");
14861512
wine_rb_init(&obj->pchannels, pchannel_block_compare);
14871513

1488-
list_init(&obj->immediate_messages);
1489-
list_init(&obj->queued_messages);
1514+
list_init(&obj->messages);
14901515

14911516
obj->rtLatencyTime = 100; /* 100 ms TO FIX */
14921517
obj->dwBumperLength = 50; /* 50 ms default */

dlls/dmime/tests/dmime.c

+19-23
Original file line numberDiff line numberDiff line change
@@ -1506,7 +1506,7 @@ static void test_performance_tool(void)
15061506
hr = IDirectMusicTool_GetMediaTypes(tool, (DWORD **)&types, 64);
15071507
ok(hr == E_NOTIMPL, "got %#lx\n", hr);
15081508
hr = IDirectMusicTool_ProcessPMsg(tool, performance, &msg);
1509-
todo_wine ok(hr == DMUS_S_FREE, "got %#lx\n", hr);
1509+
ok(hr == DMUS_S_FREE, "got %#lx\n", hr);
15101510
hr = IDirectMusicTool_Flush(tool, performance, &msg, 0);
15111511
todo_wine ok(hr == S_OK, "got %#lx\n", hr);
15121512

@@ -1859,19 +1859,18 @@ static void test_performance_pmsg(void)
18591859
ok(hr == S_OK, "got %#lx\n", hr);
18601860

18611861
ret = test_tool_wait_message(tool, 50, &msg);
1862-
todo_wine ok(!ret, "got %#lx\n", ret);
1863-
todo_wine ok(msg != NULL, "got %p\n", msg);
1864-
if (!msg) goto skip_rtime;
1862+
ok(!ret, "got %#lx\n", ret);
1863+
ok(msg != NULL, "got %p\n", msg);
18651864

18661865
time = 0xdeadbeef;
18671866
hr = IDirectMusicPerformance_MusicToReferenceTime(performance, msg->mtTime, &time);
18681867
ok(hr == S_OK, "got %#lx\n", hr);
18691868
ok(msg->dwSize == sizeof(DMUS_PMSG), "got %ld\n", msg->dwSize);
1870-
todo_wine ok(msg->rtTime == time, "got %I64d\n", msg->rtTime);
1869+
ok(msg->rtTime == time, "got %I64d\n", msg->rtTime);
18711870
ok(msg->mtTime == 500, "got %ld\n", msg->mtTime);
1872-
todo_wine ok(msg->dwFlags & DMUS_PMSGF_REFTIME, "got %#lx\n", msg->dwFlags);
1873-
todo_wine ok(msg->dwFlags & DMUS_PMSGF_MUSICTIME, "got %#lx\n", msg->dwFlags);
1874-
todo_wine ok(msg->dwFlags & (DMUS_PMSGF_TOOL_QUEUE | DMUS_PMSGF_TOOL_IMMEDIATE), "got %#lx\n", msg->dwFlags);
1871+
ok(msg->dwFlags & DMUS_PMSGF_REFTIME, "got %#lx\n", msg->dwFlags);
1872+
ok(msg->dwFlags & DMUS_PMSGF_MUSICTIME, "got %#lx\n", msg->dwFlags);
1873+
ok(msg->dwFlags & (DMUS_PMSGF_TOOL_QUEUE | DMUS_PMSGF_TOOL_IMMEDIATE), "got %#lx\n", msg->dwFlags);
18751874
ok(!msg->dwPChannel, "got %ld\n", msg->dwPChannel);
18761875
ok(!msg->dwVirtualTrackID, "got %ld\n", msg->dwVirtualTrackID);
18771876
ok(msg->pTool == tool, "got %p\n", msg->pTool);
@@ -1885,7 +1884,6 @@ static void test_performance_pmsg(void)
18851884
ok(hr == S_OK, "got %#lx\n", hr);
18861885

18871886

1888-
skip_rtime:
18891887
/* SendPMsg converts reference time to music time if it is missing */
18901888

18911889
hr = IDirectMusicPerformance_GetTime(performance, &time, &music_time);
@@ -1903,19 +1901,18 @@ static void test_performance_pmsg(void)
19031901
ok(hr == S_OK, "got %#lx\n", hr);
19041902

19051903
ret = test_tool_wait_message(tool, 50, &msg);
1906-
todo_wine ok(!ret, "got %#lx\n", ret);
1907-
todo_wine ok(msg != NULL, "got %p\n", msg);
1908-
if (!msg) goto skip_mtime;
1904+
ok(!ret, "got %#lx\n", ret);
1905+
ok(msg != NULL, "got %p\n", msg);
19091906

19101907
music_time = 0xdeadbeef;
19111908
hr = IDirectMusicPerformance_ReferenceToMusicTime(performance, msg->rtTime, &music_time);
19121909
ok(hr == S_OK, "got %#lx\n", hr);
19131910
ok(msg->dwSize == sizeof(DMUS_PMSG), "got %ld\n", msg->dwSize);
1914-
todo_wine ok(msg->rtTime == time, "got %I64d\n", msg->rtTime);
1915-
todo_wine ok(msg->mtTime == music_time, "got %ld\n", msg->mtTime);
1916-
todo_wine ok(msg->dwFlags & DMUS_PMSGF_REFTIME, "got %#lx\n", msg->dwFlags);
1917-
todo_wine ok(msg->dwFlags & DMUS_PMSGF_MUSICTIME, "got %#lx\n", msg->dwFlags);
1918-
todo_wine ok(msg->dwFlags & (DMUS_PMSGF_TOOL_QUEUE | DMUS_PMSGF_TOOL_IMMEDIATE), "got %#lx\n", msg->dwFlags);
1911+
ok(msg->rtTime == time, "got %I64d\n", msg->rtTime);
1912+
ok(msg->mtTime == music_time, "got %ld\n", msg->mtTime);
1913+
ok(msg->dwFlags & DMUS_PMSGF_REFTIME, "got %#lx\n", msg->dwFlags);
1914+
ok(msg->dwFlags & DMUS_PMSGF_MUSICTIME, "got %#lx\n", msg->dwFlags);
1915+
ok(msg->dwFlags & (DMUS_PMSGF_TOOL_QUEUE | DMUS_PMSGF_TOOL_IMMEDIATE), "got %#lx\n", msg->dwFlags);
19191916
ok(!msg->dwPChannel, "got %ld\n", msg->dwPChannel);
19201917
ok(!msg->dwVirtualTrackID, "got %ld\n", msg->dwVirtualTrackID);
19211918
ok(msg->pTool == tool, "got %p\n", msg->pTool);
@@ -1929,7 +1926,6 @@ static void test_performance_pmsg(void)
19291926
ok(hr == S_OK, "got %#lx\n", hr);
19301927

19311928

1932-
skip_mtime:
19331929
for (i = 0; i < ARRAY_SIZE(delivery_flags); i++)
19341930
{
19351931
DWORD duration = 0;
@@ -1953,18 +1949,18 @@ static void test_performance_pmsg(void)
19531949
ok(hr == S_OK, "got %#lx\n", hr);
19541950
msg = NULL;
19551951
ret = test_tool_wait_message(tool, 1000, &msg);
1956-
todo_wine ok(!ret, "got %#lx\n", ret);
1957-
todo_wine ok(msg != NULL, "got %p\n", msg);
1952+
ok(!ret, "got %#lx\n", ret);
1953+
ok(msg != NULL, "got %p\n", msg);
19581954
duration += GetTickCount();
19591955

19601956
if (msg) hr = IDirectMusicPerformance_FreePMsg(performance, msg);
19611957
ok(hr == S_OK, "got %#lx\n", hr);
19621958

19631959
switch (delivery_flags[i])
19641960
{
1965-
case DMUS_PMSGF_TOOL_IMMEDIATE: todo_wine ok(duration <= 50, "got %lu\n", duration); break;
1966-
case DMUS_PMSGF_TOOL_QUEUE: todo_wine ok(duration >= 50 && duration <= 125, "got %lu\n", duration); break;
1967-
case DMUS_PMSGF_TOOL_ATTIME: todo_wine ok(duration >= 125 && duration <= 500, "got %lu\n", duration); break;
1961+
case DMUS_PMSGF_TOOL_IMMEDIATE: ok(duration <= 50, "got %lu\n", duration); break;
1962+
case DMUS_PMSGF_TOOL_QUEUE: ok(duration >= 50 && duration <= 125, "got %lu\n", duration); break;
1963+
case DMUS_PMSGF_TOOL_ATTIME: ok(duration >= 125 && duration <= 500, "got %lu\n", duration); break;
19681964
}
19691965
}
19701966

0 commit comments

Comments
 (0)