2 * PROJECT: ReactOS Sound System "MME Buddy" Library
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: lib/drivers/sound/mmebuddy/thread.c
6 * PURPOSE: Multimedia thread management
8 * PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org)
19 IN LPVOID lpParameter OPTIONAL
)
21 PSOUND_THREAD Thread
= (PSOUND_THREAD
) lpParameter
;
23 SND_TRACE(L
"SoundThread running :)\n");
25 /* Callers will wait for us to be ready */
26 Thread
->Running
= TRUE
;
27 SetEvent(Thread
->Events
.Ready
);
29 while ( Thread
->Running
)
33 /* Wait for a request, or an I/O completion */
34 WaitResult
= WaitForSingleObjectEx(Thread
->Events
.Request
, INFINITE
, TRUE
);
35 SND_TRACE(L
"SoundThread - Came out of waiting\n");
37 if ( WaitResult
== WAIT_OBJECT_0
)
39 SND_TRACE(L
"SoundThread - Processing request\n");
41 if ( Thread
->Request
.Handler
)
43 Thread
->Request
.Result
= Thread
->Request
.Handler(Thread
->Request
.SoundDeviceInstance
,
44 Thread
->Request
.Parameter
);
48 Thread
->Request
.Result
= MMSYSERR_ERROR
;
51 /* Announce completion of the request */
52 SetEvent(Thread
->Events
.Done
);
53 /* Accept new requests */
54 SetEvent(Thread
->Events
.Ready
);
56 else if ( WaitResult
== WAIT_IO_COMPLETION
)
58 SND_TRACE(L
"SoundThread - Processing IO completion\n");
63 /* This should not happen! */
73 CreateSoundThreadEvents(
74 OUT HANDLE
* ReadyEvent
,
75 OUT HANDLE
* RequestEvent
,
76 OUT HANDLE
* DoneEvent
)
80 VALIDATE_MMSYS_PARAMETER( ReadyEvent
);
81 VALIDATE_MMSYS_PARAMETER( RequestEvent
);
82 VALIDATE_MMSYS_PARAMETER( DoneEvent
);
84 SND_TRACE(L
"Creating thread events\n");
86 /* Initialise these so we can identify them upon failure */
87 *ReadyEvent
= *RequestEvent
= *DoneEvent
= INVALID_HANDLE_VALUE
;
89 ok
= (*ReadyEvent
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
)) != INVALID_HANDLE_VALUE
;
90 ok
&= (*RequestEvent
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
)) != INVALID_HANDLE_VALUE
;
91 ok
&= (*DoneEvent
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
)) != INVALID_HANDLE_VALUE
;
93 /* If something went wrong, clean up */
96 if ( *ReadyEvent
!= INVALID_HANDLE_VALUE
)
97 CloseHandle(*ReadyEvent
);
99 if ( *RequestEvent
!= INVALID_HANDLE_VALUE
)
100 CloseHandle(*RequestEvent
);
102 if ( *DoneEvent
!= INVALID_HANDLE_VALUE
)
103 CloseHandle(*DoneEvent
);
105 return MMSYSERR_NOMEM
;
108 return MMSYSERR_NOERROR
;
112 DestroySoundThreadEvents(
113 IN HANDLE ReadyEvent
,
114 IN HANDLE RequestEvent
,
117 VALIDATE_MMSYS_PARAMETER( ReadyEvent
!= INVALID_HANDLE_VALUE
);
118 VALIDATE_MMSYS_PARAMETER( RequestEvent
!= INVALID_HANDLE_VALUE
);
119 VALIDATE_MMSYS_PARAMETER( DoneEvent
!= INVALID_HANDLE_VALUE
);
121 SND_TRACE(L
"Destroying thread events\n");
123 CloseHandle(ReadyEvent
);
124 CloseHandle(RequestEvent
);
125 CloseHandle(DoneEvent
);
127 return MMSYSERR_NOERROR
;
132 OUT PSOUND_THREAD
* Thread
)
135 PSOUND_THREAD NewThread
;
137 VALIDATE_MMSYS_PARAMETER( Thread
);
139 NewThread
= AllocateStruct(SOUND_THREAD
);
141 return MMSYSERR_NOMEM
;
143 /* Prepare the events we'll be using to sync. everything */
144 Result
= CreateSoundThreadEvents(&NewThread
->Events
.Ready
,
145 &NewThread
->Events
.Request
,
146 &NewThread
->Events
.Done
);
148 if ( ! MMSUCCESS(Result
) )
150 FreeMemory(NewThread
);
151 return TranslateInternalMmResult(Result
);
154 SND_TRACE(L
"Creating a sound thread\n");
155 NewThread
->Handle
= CreateThread(NULL
,
162 /* Something went wrong, bail out! */
163 if ( NewThread
->Handle
== INVALID_HANDLE_VALUE
)
165 SND_ERR(L
"Sound thread creation failed!\n");
166 DestroySoundThreadEvents(NewThread
->Events
.Ready
,
167 NewThread
->Events
.Request
,
168 NewThread
->Events
.Done
);
170 FreeMemory(NewThread
);
172 return Win32ErrorToMmResult(GetLastError());
175 /* Wake the thread up */
176 if ( ResumeThread(NewThread
->Handle
) == -1 )
178 CloseHandle(NewThread
->Handle
);
179 DestroySoundThreadEvents(NewThread
->Events
.Ready
,
180 NewThread
->Events
.Request
,
181 NewThread
->Events
.Done
);
183 FreeMemory(NewThread
);
184 return Win32ErrorToMmResult(GetLastError());
187 /* If all is well we can now give the thread to the caller */
189 return MMSYSERR_NOERROR
;
194 IN PSOUND_THREAD Thread
)
196 /* TODO: Implement me! */
197 return MMSYSERR_NOTSUPPORTED
;
202 IN PSOUND_THREAD Thread
,
203 IN SOUND_THREAD_REQUEST_HANDLER RequestHandler
,
204 IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance OPTIONAL
,
205 IN PVOID Parameter OPTIONAL
)
207 VALIDATE_MMSYS_PARAMETER( Thread
);
208 VALIDATE_MMSYS_PARAMETER( RequestHandler
);
210 SND_TRACE(L
"Waiting for READY event\n");
211 WaitForSingleObject(Thread
->Events
.Ready
, INFINITE
);
213 Thread
->Request
.Result
= MMSYSERR_NOTSUPPORTED
;
214 Thread
->Request
.Handler
= RequestHandler
;
215 Thread
->Request
.SoundDeviceInstance
= SoundDeviceInstance
;
216 Thread
->Request
.Parameter
= Parameter
;
218 /* Notify the thread it has work to do */
219 SND_TRACE(L
"Setting REQUEST event\n");
220 SetEvent(Thread
->Events
.Request
);
222 /* Wait for the work to be done */
223 SND_TRACE(L
"Waiting for DONE event\n");
224 WaitForSingleObject(Thread
->Events
.Done
, INFINITE
);
226 return Thread
->Request
.Result
;