+++ /dev/null
-/*
- * 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;
-}
-