mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 18:12:58 +00:00
Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers into modules, and delete rossubsys.
This commit is contained in:
parent
b94e2d8ca0
commit
c2c66aff7d
24198 changed files with 0 additions and 37285 deletions
300
sdk/lib/drivers/sound/mmebuddy/thread.c
Normal file
300
sdk/lib/drivers/sound/mmebuddy/thread.c
Normal file
|
@ -0,0 +1,300 @@
|
|||
/*
|
||||
* PROJECT: ReactOS Sound System "MME Buddy" Library
|
||||
* LICENSE: GPL - See COPYING in the top level directory
|
||||
* FILE: lib/drivers/sound/mmebuddy/thread.c
|
||||
*
|
||||
* PURPOSE: Multimedia thread management
|
||||
*
|
||||
* PROGRAMMERS: Andrew Greenwood (silverblade@reactos.org)
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
DWORD WINAPI
|
||||
SoundThreadMain(
|
||||
IN LPVOID lpParameter OPTIONAL)
|
||||
{
|
||||
PSOUND_THREAD Thread = (PSOUND_THREAD) lpParameter;
|
||||
|
||||
SND_TRACE(L"SoundThread running :)\n");
|
||||
|
||||
/* Callers will wait for us to be ready */
|
||||
Thread->Running = TRUE;
|
||||
SetEvent(Thread->Events.Ready);
|
||||
|
||||
while ( Thread->Running )
|
||||
{
|
||||
DWORD WaitResult;
|
||||
|
||||
/* Wait for a request, or an I/O completion */
|
||||
WaitResult = WaitForSingleObjectEx(Thread->Events.Request, INFINITE, TRUE);
|
||||
SND_TRACE(L"SoundThread - Came out of waiting\n");
|
||||
|
||||
if ( WaitResult == WAIT_OBJECT_0 )
|
||||
{
|
||||
SND_TRACE(L"SoundThread - Processing request\n");
|
||||
|
||||
if ( Thread->Request.Handler )
|
||||
{
|
||||
Thread->Request.Result = Thread->Request.Handler(Thread->Request.SoundDeviceInstance,
|
||||
Thread->Request.Parameter);
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread->Request.Result = MMSYSERR_ERROR;
|
||||
}
|
||||
|
||||
/* Announce completion of the request */
|
||||
SetEvent(Thread->Events.Done);
|
||||
/* Accept new requests */
|
||||
SetEvent(Thread->Events.Ready);
|
||||
}
|
||||
else if ( WaitResult == WAIT_IO_COMPLETION )
|
||||
{
|
||||
SND_TRACE(L"SoundThread - Processing IO completion\n");
|
||||
/* TODO? What do we do here? Stream stuff? */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This should not happen! */
|
||||
SND_ASSERT(FALSE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SND_TRACE(L"Sound thread terminated\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MMRESULT
|
||||
CallSoundThread(
|
||||
IN PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
|
||||
IN SOUND_THREAD_REQUEST_HANDLER RequestHandler,
|
||||
IN PVOID Parameter OPTIONAL)
|
||||
{
|
||||
PSOUND_THREAD Thread;
|
||||
|
||||
VALIDATE_MMSYS_PARAMETER( IsValidSoundDeviceInstance(SoundDeviceInstance) );
|
||||
VALIDATE_MMSYS_PARAMETER( RequestHandler );
|
||||
|
||||
Thread = SoundDeviceInstance->Thread;
|
||||
|
||||
SND_TRACE(L"Waiting for READY event\n");
|
||||
WaitForSingleObject(Thread->Events.Ready, INFINITE);
|
||||
|
||||
Thread->Request.Result = MMSYSERR_NOTSUPPORTED;
|
||||
Thread->Request.Handler = RequestHandler;
|
||||
Thread->Request.SoundDeviceInstance = SoundDeviceInstance;
|
||||
Thread->Request.Parameter = Parameter;
|
||||
|
||||
/* Notify the thread it has work to do */
|
||||
SND_TRACE(L"Setting REQUEST event\n");
|
||||
SetEvent(Thread->Events.Request);
|
||||
|
||||
/* Wait for the work to be done */
|
||||
SND_TRACE(L"Waiting for DONE event\n");
|
||||
WaitForSingleObject(Thread->Events.Done, INFINITE);
|
||||
|
||||
return Thread->Request.Result;
|
||||
}
|
||||
|
||||
|
||||
MMRESULT
|
||||
SoundThreadTerminator(
|
||||
IN PSOUND_DEVICE_INSTANCE Instance,
|
||||
IN PVOID Parameter)
|
||||
{
|
||||
PSOUND_THREAD Thread = (PSOUND_THREAD) Parameter;
|
||||
|
||||
SND_TRACE(L"Sound thread terminator routine called\n");
|
||||
SND_ASSERT( Thread );
|
||||
|
||||
Thread->Running = FALSE;
|
||||
|
||||
return MMSYSERR_NOERROR;
|
||||
}
|
||||
|
||||
MMRESULT
|
||||
TerminateSoundThread(
|
||||
IN PSOUND_THREAD Thread)
|
||||
{
|
||||
DWORD WaitResult;
|
||||
|
||||
SND_ASSERT( Thread );
|
||||
|
||||
SND_TRACE(L"Waiting for READY event\n");
|
||||
WaitForSingleObject(Thread->Events.Ready, INFINITE);
|
||||
|
||||
Thread->Request.Result = MMSYSERR_NOTSUPPORTED;
|
||||
Thread->Request.Handler = SoundThreadTerminator;
|
||||
Thread->Request.SoundDeviceInstance = NULL;
|
||||
Thread->Request.Parameter = (PVOID) Thread;
|
||||
|
||||
/* Notify the thread it has work to do */
|
||||
SND_TRACE(L"Setting REQUEST event\n");
|
||||
SetEvent(Thread->Events.Request);
|
||||
|
||||
/* Wait for the work to be done */
|
||||
SND_TRACE(L"Waiting for DONE event\n");
|
||||
WaitForSingleObject(Thread->Events.Done, INFINITE);
|
||||
|
||||
/* Wait for the thread to actually end */
|
||||
WaitResult = WaitForSingleObject(Thread->Handle, INFINITE);
|
||||
SND_ASSERT( WaitResult == WAIT_OBJECT_0 );
|
||||
|
||||
return MMSYSERR_NOERROR;
|
||||
}
|
||||
|
||||
|
||||
MMRESULT
|
||||
CreateSoundThreadEvents(
|
||||
OUT HANDLE* ReadyEvent,
|
||||
OUT HANDLE* RequestEvent,
|
||||
OUT HANDLE* DoneEvent)
|
||||
{
|
||||
BOOL ok;
|
||||
|
||||
VALIDATE_MMSYS_PARAMETER( ReadyEvent );
|
||||
VALIDATE_MMSYS_PARAMETER( RequestEvent );
|
||||
VALIDATE_MMSYS_PARAMETER( DoneEvent );
|
||||
|
||||
SND_TRACE(L"Creating thread events\n");
|
||||
|
||||
/* Initialise these so we can identify them upon failure */
|
||||
*ReadyEvent = *RequestEvent = *DoneEvent = INVALID_HANDLE_VALUE;
|
||||
|
||||
ok = (*ReadyEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) != INVALID_HANDLE_VALUE;
|
||||
ok &= (*RequestEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) != INVALID_HANDLE_VALUE;
|
||||
ok &= (*DoneEvent = CreateEvent(NULL, FALSE, FALSE, NULL)) != INVALID_HANDLE_VALUE;
|
||||
|
||||
/* If something went wrong, clean up */
|
||||
if ( ! ok )
|
||||
{
|
||||
if ( *ReadyEvent != INVALID_HANDLE_VALUE )
|
||||
CloseHandle(*ReadyEvent);
|
||||
|
||||
if ( *RequestEvent != INVALID_HANDLE_VALUE )
|
||||
CloseHandle(*RequestEvent);
|
||||
|
||||
if ( *DoneEvent != INVALID_HANDLE_VALUE )
|
||||
CloseHandle(*DoneEvent);
|
||||
|
||||
return MMSYSERR_NOMEM;
|
||||
}
|
||||
|
||||
return MMSYSERR_NOERROR;
|
||||
}
|
||||
|
||||
MMRESULT
|
||||
DestroySoundThreadEvents(
|
||||
IN HANDLE ReadyEvent,
|
||||
IN HANDLE RequestEvent,
|
||||
IN HANDLE DoneEvent)
|
||||
{
|
||||
VALIDATE_MMSYS_PARAMETER( ReadyEvent != INVALID_HANDLE_VALUE );
|
||||
VALIDATE_MMSYS_PARAMETER( RequestEvent != INVALID_HANDLE_VALUE );
|
||||
VALIDATE_MMSYS_PARAMETER( DoneEvent != INVALID_HANDLE_VALUE );
|
||||
|
||||
SND_TRACE(L"Destroying thread events\n");
|
||||
|
||||
CloseHandle(ReadyEvent);
|
||||
CloseHandle(RequestEvent);
|
||||
CloseHandle(DoneEvent);
|
||||
|
||||
return MMSYSERR_NOERROR;
|
||||
}
|
||||
|
||||
MMRESULT
|
||||
CreateSoundThread(
|
||||
OUT PSOUND_THREAD* Thread)
|
||||
{
|
||||
MMRESULT Result;
|
||||
PSOUND_THREAD NewThread;
|
||||
|
||||
VALIDATE_MMSYS_PARAMETER( Thread );
|
||||
|
||||
NewThread = AllocateStruct(SOUND_THREAD);
|
||||
if ( ! NewThread )
|
||||
return MMSYSERR_NOMEM;
|
||||
|
||||
/* Prepare the events we'll be using to sync. everything */
|
||||
Result = CreateSoundThreadEvents(&NewThread->Events.Ready,
|
||||
&NewThread->Events.Request,
|
||||
&NewThread->Events.Done);
|
||||
|
||||
if ( ! MMSUCCESS(Result) )
|
||||
{
|
||||
FreeMemory(NewThread);
|
||||
return TranslateInternalMmResult(Result);
|
||||
}
|
||||
|
||||
SND_TRACE(L"Creating a sound thread\n");
|
||||
NewThread->Handle = CreateThread(NULL,
|
||||
0,
|
||||
&SoundThreadMain,
|
||||
(LPVOID) NewThread,
|
||||
CREATE_SUSPENDED,
|
||||
NULL);
|
||||
|
||||
/* Something went wrong, bail out! */
|
||||
if ( NewThread->Handle == INVALID_HANDLE_VALUE )
|
||||
{
|
||||
SND_ERR(L"Sound thread creation failed!\n");
|
||||
DestroySoundThreadEvents(NewThread->Events.Ready,
|
||||
NewThread->Events.Request,
|
||||
NewThread->Events.Done);
|
||||
|
||||
FreeMemory(NewThread);
|
||||
|
||||
return Win32ErrorToMmResult(GetLastError());
|
||||
}
|
||||
|
||||
/* Wake the thread up */
|
||||
if ( ResumeThread(NewThread->Handle) == -1 )
|
||||
{
|
||||
SND_ERR(L"Failed to resume thread!\n");
|
||||
CloseHandle(NewThread->Handle);
|
||||
DestroySoundThreadEvents(NewThread->Events.Ready,
|
||||
NewThread->Events.Request,
|
||||
NewThread->Events.Done);
|
||||
|
||||
FreeMemory(NewThread);
|
||||
return Win32ErrorToMmResult(GetLastError());
|
||||
}
|
||||
|
||||
/* If all is well we can now give the thread to the caller */
|
||||
*Thread = NewThread;
|
||||
return MMSYSERR_NOERROR;
|
||||
}
|
||||
|
||||
MMRESULT
|
||||
DestroySoundThread(
|
||||
IN PSOUND_THREAD Thread)
|
||||
{
|
||||
VALIDATE_MMSYS_PARAMETER( Thread );
|
||||
SND_ASSERT( Thread->Handle != INVALID_HANDLE_VALUE );
|
||||
|
||||
SND_TRACE(L"Terminating sound thread\n");
|
||||
|
||||
/* Tell the thread to terminate itself */
|
||||
TerminateSoundThread(Thread);
|
||||
|
||||
SND_TRACE(L"Sound thread terminated, performing cleanup of thread resources\n");
|
||||
|
||||
CloseHandle(Thread->Handle); /* Is this needed? */
|
||||
Thread->Handle = INVALID_HANDLE_VALUE;
|
||||
|
||||
DestroySoundThreadEvents(Thread->Events.Ready,
|
||||
Thread->Events.Request,
|
||||
Thread->Events.Done);
|
||||
|
||||
/* Wipe and free the memory used for the thread */
|
||||
ZeroMemory(Thread, sizeof(SOUND_THREAD));
|
||||
FreeMemory(Thread);
|
||||
|
||||
SND_TRACE(L"Finished thread cleanup\n");
|
||||
|
||||
return MMSYSERR_NOERROR;
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue