@@ -62,11 +62,10 @@ struct performance
62
62
DWORD procThreadId ;
63
63
BOOL procThreadTicStarted ;
64
64
CRITICAL_SECTION safe ;
65
- struct list immediate_messages ;
66
- struct list queued_messages ;
67
65
68
66
IReferenceClock * master_clock ;
69
67
REFERENCE_TIME init_time ;
68
+ struct list messages ;
70
69
};
71
70
72
71
struct message
@@ -80,99 +79,109 @@ static inline struct message *message_from_DMUS_PMSG(DMUS_PMSG *msg)
80
79
return msg ? CONTAINING_RECORD (msg , struct message , msg ) : NULL ;
81
80
}
82
81
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
+
83
124
#define PROCESSMSG_START (WM_APP + 0)
84
125
#define PROCESSMSG_EXIT (WM_APP + 1)
85
126
#define PROCESSMSG_REMOVE (WM_APP + 2)
86
127
#define PROCESSMSG_ADD (WM_APP + 4)
87
128
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 ;
88
136
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 ;
106
141
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 );
115
143
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 );
118
148
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
+ }
121
153
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 );
133
155
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
+ }
141
177
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 */
166
179
}
167
180
168
- /** here we should run a little of current AudioPath */
169
-
170
- }
171
-
172
181
outofthread :
173
- TRACE ("(%p): Exiting\n" , This );
174
-
175
- return 0 ;
182
+ TRACE ("(%p): Exiting\n" , This );
183
+
184
+ return 0 ;
176
185
}
177
186
178
187
static BOOL PostMessageToProcessMsgThread (struct performance * This , UINT iMsg ) {
@@ -389,9 +398,9 @@ static HRESULT WINAPI performance_GetBumperLength(IDirectMusicPerformance8 *ifac
389
398
390
399
static HRESULT WINAPI performance_SendPMsg (IDirectMusicPerformance8 * iface , DMUS_PMSG * msg )
391
400
{
401
+ const DWORD delivery_flags = DMUS_PMSGF_TOOL_IMMEDIATE | DMUS_PMSGF_TOOL_QUEUE | DMUS_PMSGF_TOOL_ATTIME ;
392
402
struct performance * This = impl_from_IDirectMusicPerformance8 (iface );
393
403
struct message * message , * next ;
394
- struct list * queue ;
395
404
HRESULT hr ;
396
405
397
406
FIXME ("(%p, %p): semi-stub\n" , This , msg );
@@ -400,15 +409,13 @@ static HRESULT WINAPI performance_SendPMsg(IDirectMusicPerformance8 *iface, DMUS
400
409
if (!This -> dmusic ) return DMUS_E_NO_MASTER_CLOCK ;
401
410
if (!(msg -> dwFlags & (DMUS_PMSGF_MUSICTIME | DMUS_PMSGF_REFTIME ))) return E_INVALIDARG ;
402
411
403
- if (msg -> dwFlags & DMUS_PMSGF_TOOL_IMMEDIATE ) queue = & This -> immediate_messages ;
404
- else queue = & This -> queued_messages ;
405
-
406
412
EnterCriticalSection (& This -> safe );
407
413
408
414
if (!list_empty (& message -> entry ))
409
415
hr = DMUS_E_ALREADY_SENT ;
410
416
else
411
417
{
418
+ if (!(msg -> dwFlags & delivery_flags )) msg -> dwFlags |= DMUS_PMSGF_TOOL_IMMEDIATE ;
412
419
if (!(msg -> dwFlags & DMUS_PMSGF_MUSICTIME ))
413
420
{
414
421
if (FAILED (hr = IDirectMusicPerformance8_ReferenceToMusicTime (iface ,
@@ -424,9 +431,16 @@ static HRESULT WINAPI performance_SendPMsg(IDirectMusicPerformance8 *iface, DMUS
424
431
msg -> dwFlags |= DMUS_PMSGF_REFTIME ;
425
432
}
426
433
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 )
428
441
if (next -> msg .rtTime >= message -> msg .rtTime ) break ;
429
442
list_add_before (& next -> entry , & message -> entry );
443
+ PostThreadMessageW (This -> procThreadId , PROCESSMSG_ADD , 0 , 0 );
430
444
431
445
hr = S_OK ;
432
446
}
@@ -1440,8 +1454,20 @@ static HRESULT WINAPI performance_tool_ProcessPMsg(IDirectMusicTool *iface,
1440
1454
IDirectMusicPerformance * performance , DMUS_PMSG * msg )
1441
1455
{
1442
1456
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 ;
1445
1471
}
1446
1472
1447
1473
static HRESULT WINAPI performance_tool_Flush (IDirectMusicTool * iface ,
@@ -1485,8 +1511,7 @@ HRESULT create_dmperformance(REFIID iid, void **ret_iface)
1485
1511
obj -> safe .DebugInfo -> Spare [0 ] = (DWORD_PTR )(__FILE__ ": performance->safe" );
1486
1512
wine_rb_init (& obj -> pchannels , pchannel_block_compare );
1487
1513
1488
- list_init (& obj -> immediate_messages );
1489
- list_init (& obj -> queued_messages );
1514
+ list_init (& obj -> messages );
1490
1515
1491
1516
obj -> rtLatencyTime = 100 ; /* 100 ms TO FIX */
1492
1517
obj -> dwBumperLength = 50 ; /* 50 ms default */
0 commit comments