Author: silverblade
Date: Sun Jul  6 13:57:26 2008
New Revision: 34340
URL: 
http://svn.reactos.org/svn/reactos?rev=34340&view=rev
Log:
Some restructuring to avoid SOUND_DEVICE_INSTANCE containing members only
relevant to the a wave device thread. Now there are separate structures for
device, device instance, thread, and anything relevant to a wave thread.
Extended overlapped I/O structure so that the completion routine can identify
the device instance, completed wave buffer and thread-specific data.
The completion routine re-submits the same buffer repeatedly at present.
Modified:
    branches/silverblade-audio/dll/win32/sndblst/sndblst.c
    branches/silverblade-audio/include/reactos/libs/sound/mmebuddy.h
    branches/silverblade-audio/lib/drivers/sound/mmebuddy/instances.c
    branches/silverblade-audio/lib/drivers/sound/mmebuddy/kernel.c
    branches/silverblade-audio/lib/drivers/sound/mmebuddy/mme/wodMessage.c
    branches/silverblade-audio/lib/drivers/sound/mmebuddy/thread.c
    branches/silverblade-audio/lib/drivers/sound/mmebuddy/wave/wavethread.c
Modified: branches/silverblade-audio/dll/win32/sndblst/sndblst.c
URL:
http://svn.reactos.org/svn/reactos/branches/silverblade-audio/dll/win32/snd…
==============================================================================
--- branches/silverblade-audio/dll/win32/sndblst/sndblst.c [iso-8859-1] (original)
+++ branches/silverblade-audio/dll/win32/sndblst/sndblst.c [iso-8859-1] Sun Jul  6
13:57:26 2008
@@ -132,6 +132,10 @@
     WAVEFORMATEX Format;
     MMRESULT Result;
     PVOID InstanceData;
+    int i;
+
+    for ( i = 0; i < 65536; ++ i )
+        Buffer[i] = rand();
     /* DRV_LOAD */
     DriverProc(0, 0, DRV_LOAD, 0, 0);
Modified: branches/silverblade-audio/include/reactos/libs/sound/mmebuddy.h
URL:
http://svn.reactos.org/svn/reactos/branches/silverblade-audio/include/react…
==============================================================================
--- branches/silverblade-audio/include/reactos/libs/sound/mmebuddy.h [iso-8859-1]
(original)
+++ branches/silverblade-audio/include/reactos/libs/sound/mmebuddy.h [iso-8859-1] Sun Jul
6 13:57:26 2008
@@ -101,18 +101,17 @@
     MMRESULT Result;
 } THREAD_REQUEST, *PTHREAD_REQUEST;
-
-/*
-    Thread helper operations
-*/
 typedef MMRESULT (*SOUND_THREAD_REQUEST_HANDLER)(
     IN  struct _SOUND_DEVICE_INSTANCE* Instance,
+    IN  PVOID PrivateThreadData,
     IN  DWORD RequestId,
     IN  PVOID Data);
 typedef struct _SOUND_THREAD
 {
+    /* Thread management */
     HANDLE Handle;
+    PVOID PrivateData;
     BOOLEAN Running;
     SOUND_THREAD_REQUEST_HANDLER RequestHandler;
     HANDLE ReadyEvent;      /* Thread waiting for a request */
@@ -123,8 +122,30 @@
 /*
+    Wave thread
+*/
+
+typedef struct _WAVE_OVERLAPPED
+{
+    OVERLAPPED General;
+    struct _SOUND_DEVICE_INSTANCE* SoundDeviceInstance;
+    struct _WAVE_THREAD_DATA* ThreadData;
+    PWAVEHDR Header;
+} WAVE_OVERLAPPED, *PWAVE_OVERLAPPED;
+
+typedef struct _WAVE_THREAD_DATA
+{
+    /* Wave thread specific */
+    WAVE_OVERLAPPED Overlapped;
+
+    DWORD BufferCount;
+    PWAVEHDR CurrentBuffer;
+    PWAVEHDR FirstBuffer;
+    PWAVEHDR LastBuffer;
+} WAVE_THREAD_DATA, *PWAVE_THREAD_DATA;
+
+/*
     Audio device function table
-    TODO - create/destroy instance need to work
 */
 typedef MMRESULT (*MMCREATEINSTANCE_FUNC)(
@@ -193,20 +214,6 @@
     {
         DWORD ClientCallback;
     } WinMM;
-
-    /* Everything below this is used by the worker thread only */
-    OVERLAPPED Overlapped;
-
-    union
-    {
-        struct
-        {
-            DWORD BufferCount;
-            PWAVEHDR CurrentBuffer;
-            PWAVEHDR FirstBuffer;
-            PWAVEHDR LastBuffer;
-        } Wave;
-    };
 } SOUND_DEVICE_INSTANCE, *PSOUND_DEVICE_INSTANCE;
@@ -359,7 +366,8 @@
     IN  PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
     IN  LPVOID Buffer,
     IN  DWORD BufferSize,
-    IN  LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine);
+    IN  LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine,
+    LPOVERLAPPED Overlapped);
 /*
@@ -467,7 +475,8 @@
 MMRESULT
 StartSoundThread(
     IN  PSOUND_DEVICE_INSTANCE Instance,
-    IN  SOUND_THREAD_REQUEST_HANDLER RequestHandler);
+    IN  SOUND_THREAD_REQUEST_HANDLER RequestHandler,
+    IN  PVOID Data);
 MMRESULT
 StopSoundThread(
@@ -478,6 +487,11 @@
     IN  PSOUND_DEVICE_INSTANCE Instance,
     IN  DWORD RequestId,
     IN  PVOID RequestData);
+
+MMRESULT
+GetSoundThreadPrivateData(
+    IN  PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
+    OUT PVOID* PrivateData);
Modified: branches/silverblade-audio/lib/drivers/sound/mmebuddy/instances.c
URL:
http://svn.reactos.org/svn/reactos/branches/silverblade-audio/lib/drivers/s…
==============================================================================
--- branches/silverblade-audio/lib/drivers/sound/mmebuddy/instances.c [iso-8859-1]
(original)
+++ branches/silverblade-audio/lib/drivers/sound/mmebuddy/instances.c [iso-8859-1] Sun Jul
6 13:57:26 2008
@@ -31,6 +31,7 @@
     SoundDeviceInstance->Next = NULL;
     SoundDeviceInstance->Device = NULL;
     SoundDeviceInstance->Thread = NULL;
+    /* TODO: WinMM callback entry */
 }
 PSOUND_DEVICE_INSTANCE
Modified: branches/silverblade-audio/lib/drivers/sound/mmebuddy/kernel.c
URL:
http://svn.reactos.org/svn/reactos/branches/silverblade-audio/lib/drivers/s…
==============================================================================
--- branches/silverblade-audio/lib/drivers/sound/mmebuddy/kernel.c [iso-8859-1] (original)
+++ branches/silverblade-audio/lib/drivers/sound/mmebuddy/kernel.c [iso-8859-1] Sun Jul  6
13:57:26 2008
@@ -212,13 +212,12 @@
     PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
     LPVOID Buffer,
     DWORD BufferSize,
-    LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine)
+    LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine,
+    LPOVERLAPPED Overlapped)
 {
     WCHAR msg[128];
     if ( ( ! SoundDeviceInstance ) || ( ! Buffer ) || ( BufferSize == 0 ) )
         return MMSYSERR_INVALPARAM;
-
-    ZeroMemory(&SoundDeviceInstance->Overlapped, sizeof(OVERLAPPED));
     wsprintf(msg, L"Writing to handle %x",
SoundDeviceInstance->Device->Handle);
     SOUND_DEBUG(msg);
@@ -226,7 +225,7 @@
     if ( ! WriteFileEx(SoundDeviceInstance->Device->Handle,
                        Buffer,
                        BufferSize,
-                       &SoundDeviceInstance->Overlapped,
+                       Overlapped,
                        CompletionRoutine) )
     {
         wsprintf(msg, L"Win32 Error %d", GetLastError());
Modified: branches/silverblade-audio/lib/drivers/sound/mmebuddy/mme/wodMessage.c
URL:
http://svn.reactos.org/svn/reactos/branches/silverblade-audio/lib/drivers/s…
==============================================================================
--- branches/silverblade-audio/lib/drivers/sound/mmebuddy/mme/wodMessage.c [iso-8859-1]
(original)
+++ branches/silverblade-audio/lib/drivers/sound/mmebuddy/mme/wodMessage.c [iso-8859-1]
Sun Jul  6 13:57:26 2008
@@ -124,6 +124,8 @@
             Result = DestroySoundDeviceInstance(Instance);
             SOUND_DEBUG_HEX(Result);
+            /* TODO: When do we send the callback? */
+
             return Result;
             /* CloseSoundDevice() */
         }
Modified: branches/silverblade-audio/lib/drivers/sound/mmebuddy/thread.c
URL:
http://svn.reactos.org/svn/reactos/branches/silverblade-audio/lib/drivers/s…
==============================================================================
--- branches/silverblade-audio/lib/drivers/sound/mmebuddy/thread.c [iso-8859-1] (original)
+++ branches/silverblade-audio/lib/drivers/sound/mmebuddy/thread.c [iso-8859-1] Sun Jul  6
13:57:26 2008
@@ -59,6 +59,7 @@
             /* Do the work (request 0 kills the thread) */
             Thread->Request.Result =
                 Thread->RequestHandler(Instance,
+                                       Thread->PrivateData,
                                        Thread->Request.RequestId,
                                        Thread->Request.Data);
@@ -139,7 +140,8 @@
 MMRESULT
 StartSoundThread(
     IN  PSOUND_DEVICE_INSTANCE Instance,
-    IN  SOUND_THREAD_REQUEST_HANDLER RequestHandler)
+    IN  SOUND_THREAD_REQUEST_HANDLER RequestHandler,
+    IN  LPVOID PrivateThreadData)
 {
     PSOUND_THREAD SoundThread = NULL;
@@ -161,6 +163,7 @@
         return MMSYSERR_NOMEM;
     /* Initialise */
+    SoundThread->PrivateData = PrivateThreadData;
     SoundThread->Running = FALSE;
     SoundThread->Handle = INVALID_HANDLE_VALUE;
     SoundThread->RequestHandler = RequestHandler;
@@ -239,35 +242,54 @@
 MMRESULT
 CallSoundThread(
-    IN  PSOUND_DEVICE_INSTANCE Instance,
+    IN  PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
     IN  DWORD RequestId,
     IN  PVOID RequestData)
 {
     MMRESULT Result;
-    if ( ! Instance )
-        return MMSYSERR_INVALPARAM;
-
-    if ( ! Instance->Thread )
+    if ( ! SoundDeviceInstance )
+        return MMSYSERR_INVALPARAM;
+
+    if ( ! SoundDeviceInstance->Thread )
         return MMSYSERR_ERROR;
     /* Wait for the thread to be ready */
-    WaitForSingleObject(Instance->Thread->ReadyEvent, INFINITE);
+    WaitForSingleObject(SoundDeviceInstance->Thread->ReadyEvent, INFINITE);
     /* Load the request */
-    Instance->Thread->Request.DeviceInstance = Instance;
-    Instance->Thread->Request.RequestId = RequestId;
-    Instance->Thread->Request.Data = RequestData;
-    Instance->Thread->Request.Result = MMSYSERR_NOTSUPPORTED;
+    SoundDeviceInstance->Thread->Request.DeviceInstance = SoundDeviceInstance;
+    SoundDeviceInstance->Thread->Request.RequestId = RequestId;
+    SoundDeviceInstance->Thread->Request.Data = RequestData;
+    SoundDeviceInstance->Thread->Request.Result = MMSYSERR_NOTSUPPORTED;
     /* Notify the thread that there's a request to be processed */
-    SetEvent(Instance->Thread->RequestEvent);
+    SetEvent(SoundDeviceInstance->Thread->RequestEvent);
     /* Wait for the thread to be ready (request complete) */
-    WaitForSingleObject(Instance->Thread->DoneEvent, INFINITE);
+    WaitForSingleObject(SoundDeviceInstance->Thread->DoneEvent, INFINITE);
     /* Grab the result */
-    Result = Instance->Thread->Request.Result;
+    Result = SoundDeviceInstance->Thread->Request.Result;
     return Result;
 }
+
+MMRESULT
+GetSoundThreadPrivateData(
+    IN  PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
+    OUT PVOID* PrivateData)
+{
+    if ( ! SoundDeviceInstance )
+        return MMSYSERR_INVALPARAM;
+
+    if ( ! SoundDeviceInstance->Thread )
+        return MMSYSERR_ERROR;
+
+    if ( ! PrivateData )
+        return MMSYSERR_INVALPARAM;
+
+    *PrivateData = SoundDeviceInstance->Thread->PrivateData;
+
+    return MMSYSERR_NOERROR;
+}
Modified: branches/silverblade-audio/lib/drivers/sound/mmebuddy/wave/wavethread.c
URL:
http://svn.reactos.org/svn/reactos/branches/silverblade-audio/lib/drivers/s…
==============================================================================
--- branches/silverblade-audio/lib/drivers/sound/mmebuddy/wave/wavethread.c [iso-8859-1]
(original)
+++ branches/silverblade-audio/lib/drivers/sound/mmebuddy/wave/wavethread.c [iso-8859-1]
Sun Jul  6 13:57:26 2008
@@ -19,6 +19,14 @@
 #include <mmsystem.h>
 #include <mmebuddy.h>
+
+MMRESULT
+WriteWaveBufferToSoundDevice(
+    IN  PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
+    IN  PWAVE_THREAD_DATA ThreadData,
+    IN  PWAVEHDR WaveHeader);
+
+
 VOID CALLBACK
 WaveBufferCompleted(
@@ -26,47 +34,91 @@
     IN  DWORD dwNumberOfBytesTransferred,
     IN  LPOVERLAPPED lpOverlapped)
 {
-    MessageBox(0, L"Job done!", L"File IO Callback", MB_OK |
MB_TASKMODAL);
-}
+    PWAVE_OVERLAPPED WaveOverlapped = (PWAVE_OVERLAPPED) lpOverlapped;
+    /*PWAVE_THREAD_DATA ThreadData = WaveOverlapped->ThreadData;*/
+    WCHAR msg[1024];
+
+    wsprintf(msg, L"Buffer %x done\nWrote %d bytes\nErrCode %d",
+             WaveOverlapped->Header,
+             dwNumberOfBytesTransferred,
+             dwErrorCode);
+
+    MessageBox(0, msg, L"File IO Callback", MB_OK | MB_TASKMODAL);
+
+    WriteWaveBufferToSoundDevice(WaveOverlapped->SoundDeviceInstance,
+                                 WaveOverlapped->ThreadData,
+                                 WaveOverlapped->Header);
+}
+
+MMRESULT
+WriteWaveBufferToSoundDevice(
+    IN  PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
+    IN  PWAVE_THREAD_DATA ThreadData,
+    IN  PWAVEHDR WaveHeader)
+{
+    SOUND_ASSERT(SoundDeviceInstance);
+    SOUND_ASSERT(ThreadData);
+    SOUND_ASSERT(WaveHeader);
+
+    /* Prepare our overlapped data */
+    ZeroMemory(&ThreadData->Overlapped, sizeof(WAVE_OVERLAPPED));
+    ThreadData->Overlapped.SoundDeviceInstance = SoundDeviceInstance;
+    ThreadData->Overlapped.ThreadData = ThreadData;
+    ThreadData->Overlapped.Header = WaveHeader;
+
+    return WriteSoundDeviceBuffer(SoundDeviceInstance,
+                                  WaveHeader->lpData,
+                                  WaveHeader->dwBufferLength,
+                                  WaveBufferCompleted,
+                                  (LPOVERLAPPED) &ThreadData->Overlapped);
+}
+
 /* Internal dispatch routines */
 MMRESULT
 SubmitWaveBuffer(
     IN  PSOUND_DEVICE_INSTANCE Instance,
+    IN  PWAVE_THREAD_DATA ThreadData,
     IN  PWAVEHDR Buffer)
 {
-    MMRESULT Result;
-
     SOUND_ASSERT(Instance != NULL);
     SOUND_ASSERT(Buffer != NULL);
+    SOUND_ASSERT(Instance->Thread != NULL);
+
+    /* Store the device instance */
+    Buffer->reserved = (DWORD) Instance;
     /* Set the head of the buffer list if this is the first buffer */
-    if ( ! Instance->Wave.FirstBuffer )
-    {
-        Instance->Wave.FirstBuffer = Buffer;
+    if ( ! ThreadData->FirstBuffer )
+    {
+        ThreadData->FirstBuffer = Buffer;
     }
     /* Attach the buffer to the end of the list, unless this is the first */
-    if ( Instance->Wave.LastBuffer )
-    {
-        Instance->Wave.LastBuffer->lpNext = Buffer;
+    if ( ThreadData->LastBuffer )
+    {
+        ThreadData->LastBuffer->lpNext = Buffer;
     }
     /* Update our record of the last buffer */
-    Instance->Wave.LastBuffer = Buffer;
+    ThreadData->LastBuffer = Buffer;
     /* Increment the number of buffers queued */
-    ++ Instance->Wave.BufferCount;
+    ++ ThreadData->BufferCount;
     /* HACK */
-    Instance->Wave.CurrentBuffer = Instance->Wave.FirstBuffer;
-
+    ThreadData->CurrentBuffer = ThreadData->FirstBuffer;
+
+    WriteWaveBufferToSoundDevice(Instance, ThreadData, Buffer);
+
+/*
     Result = WriteSoundDeviceBuffer(Instance,
-                                    Instance->Wave.CurrentBuffer->lpData,
-                                    Instance->Wave.CurrentBuffer->dwBufferLength,
-                                    WaveBufferCompleted);
-
+                                    ThreadData->CurrentBuffer->lpData,
+                                    ThreadData->CurrentBuffer->dwBufferLength,
+                                    WaveBufferCompleted,
+                                    (LPOVERLAPPED) &Thread->Wave.Overlapped);
+*/
     return MMSYSERR_NOERROR;
 }
@@ -76,9 +128,13 @@
 MMRESULT
 ProcessWaveThreadRequest(
     IN  PSOUND_DEVICE_INSTANCE Instance,
+    IN  PVOID PrivateThreadData,
     IN  DWORD RequestId,
     IN  PVOID Data)
 {
+    PWAVE_THREAD_DATA WaveThreadData =
+        (PWAVE_THREAD_DATA) PrivateThreadData;
+
     /* Just some temporary testing code for now */
     WCHAR msg[128];
     wsprintf(msg, L"Request %d received", RequestId);
@@ -93,7 +149,7 @@
         {
             PWAVEHDR Buffer = (PWAVEHDR) Data;
-            return SubmitWaveBuffer(Instance, Buffer);
+            return SubmitWaveBuffer(Instance, WaveThreadData, Buffer);
         }
     }
@@ -105,20 +161,30 @@
     IN  PSOUND_DEVICE_INSTANCE Instance)
 {
     MMRESULT Result = MMSYSERR_NOERROR;
+    PWAVE_THREAD_DATA WaveThreadData = NULL;
     if ( ! Instance )
         return MMSYSERR_INVALPARAM;
+    WaveThreadData = AllocateMemoryFor(WAVE_THREAD_DATA);
+
+    if ( ! WaveThreadData )
+        return MMSYSERR_NOMEM;
+
     /* Initialise our data */
-    Instance->Wave.CurrentBuffer = NULL;
-    Instance->Wave.FirstBuffer = NULL;
-    Instance->Wave.LastBuffer = NULL;
-    Instance->Wave.BufferCount = 0;
+    WaveThreadData->CurrentBuffer = NULL;
+    WaveThreadData->FirstBuffer = NULL;
+    WaveThreadData->LastBuffer = NULL;
+    WaveThreadData->BufferCount = 0;
+    /* TODO: More */
     /* Kick off the thread */
-    Result = StartSoundThread(Instance, ProcessWaveThreadRequest);
+    Result = StartSoundThread(Instance,
+                              ProcessWaveThreadRequest,
+                              WaveThreadData);
     if ( Result != MMSYSERR_NOERROR )
     {
+        FreeMemory(WaveThreadData);
         return Result;
     }
@@ -130,8 +196,20 @@
 StopWaveThread(
     IN  PSOUND_DEVICE_INSTANCE Instance)
 {
+    MMRESULT Result;
+    PWAVE_THREAD_DATA WaveThreadData = NULL;
+
     if ( ! Instance )
         return MMSYSERR_INVALPARAM;
-    return StopSoundThread(Instance);
-}
+    Result = GetSoundThreadPrivateData(Instance, (PVOID*) &WaveThreadData);
+    SOUND_ASSERT( Result == MMSYSERR_NOERROR );
+
+    /* This shouldn't fail... */
+    Result = StopSoundThread(Instance);
+    SOUND_ASSERT( Result == MMSYSERR_NOERROR );
+
+    FreeMemory(WaveThreadData);
+
+    return MMSYSERR_NOERROR;
+}