[ros-diffs] [silverblade] 34323: Implemented threaded wave device buffer writing, along with test code. Some hacks present to aid in ensuring things are done in the correct order. Under NT4 with its own SNDBLST.SYS, this can successfully queue a wave buffer of white-noise, have it played, and call the I/O completion routine. Result is audible in NT4 within VirtualBox. More work required before actually usable.

silverblade at svn.reactos.org silverblade at svn.reactos.org
Sun Jul 6 12:22:42 CEST 2008


Author: silverblade
Date: Sun Jul  6 05:22:42 2008
New Revision: 34323

URL: http://svn.reactos.org/svn/reactos?rev=34323&view=rev
Log:
Implemented threaded wave device buffer writing, along with test code. Some
hacks present to aid in ensuring things are done in the correct order. Under
NT4 with its own SNDBLST.SYS, this can successfully queue a wave buffer of
white-noise, have it played, and call the I/O completion routine. Result is
audible in NT4 within VirtualBox. More work required before actually usable.


Modified:
    branches/silverblade-audio/include/reactos/libs/sound/mmebuddy.h
    branches/silverblade-audio/lib/drivers/sound/mmebuddy/devices.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/testing.c
    branches/silverblade-audio/lib/drivers/sound/mmebuddy/thread.c
    branches/silverblade-audio/lib/drivers/sound/mmebuddy/wave/wavethread.c

Modified: branches/silverblade-audio/include/reactos/libs/sound/mmebuddy.h
URL: http://svn.reactos.org/svn/reactos/branches/silverblade-audio/include/reactos/libs/sound/mmebuddy.h?rev=34323&r1=34322&r2=34323&view=diff
==============================================================================
--- 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 05:22:42 2008
@@ -21,6 +21,24 @@
 
 #define SOUND_DEBUG(x) \
     MessageBox(0, x, L"Debug", MB_OK | MB_TASKMODAL);
+
+#define SOUND_DEBUG_HEX(x) \
+    { \
+        WCHAR dbgmsg[1024], dbgtitle[1024]; \
+        wsprintf(dbgtitle, L"%hS[%d]", __FILE__, __LINE__); \
+        wsprintf(dbgmsg, L"%hS == %x", #x, x); \
+        MessageBox(0, dbgmsg, dbgtitle, MB_OK | MB_TASKMODAL); \
+    }
+
+#define SOUND_ASSERT(x) \
+    { \
+        if ( ! ( x ) ) \
+        { \
+            WCHAR dbgmsg[1024], dbgtitle[1024]; \
+            wsprintf(dbgtitle, L"%hS[%d]", __FILE__, __LINE__); \
+            wsprintf(dbgmsg, L"ASSERT FAILED:\n%hS", #x); \
+        } \
+    }
 
 
 /*
@@ -112,11 +130,16 @@
     IN  HANDLE Handle);
 
 typedef MMRESULT (*MMGETCAPS_FUNC)(
-    IN  struct _SOUND_DEVICE* SoundDevice,
+    IN  struct _SOUND_DEVICE* Device,
     OUT PUNIVERSAL_CAPS Capabilities);
 
-typedef MMRESULT (*MMWAVEFORMAT_FUNC)(
-    IN  struct _SOUND_DEVICE* SoundDevice,
+typedef MMRESULT (*MMWAVEQUERYFORMAT_FUNC)(
+    IN  struct _SOUND_DEVICE* Device,
+    IN  PWAVEFORMATEX WaveFormat,
+    IN  DWORD WaveFormatSize);
+
+typedef MMRESULT (*MMWAVESETFORMAT_FUNC)(
+    IN  struct _SOUND_DEVICE_INSTANCE* Instance,
     IN  PWAVEFORMATEX WaveFormat,
     IN  DWORD WaveFormatSize);
 
@@ -126,8 +149,8 @@
     MMCLOSE_FUNC            Close;
     MMGETCAPS_FUNC          GetCapabilities;
 
-    MMWAVEFORMAT_FUNC       QueryWaveFormat;
-    MMWAVEFORMAT_FUNC       SetWaveFormat;
+    MMWAVEQUERYFORMAT_FUNC  QueryWaveFormat;
+    MMWAVESETFORMAT_FUNC    SetWaveFormat;
 } MMFUNCTION_TABLE, *PMMFUNCTION_TABLE;
 
 
@@ -155,7 +178,29 @@
     struct _SOUND_DEVICE_INSTANCE* Next;
     PSOUND_DEVICE Device;
     PSOUND_THREAD Thread;
+
+    /* 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;
+
+
+/*
+    Thread requests
+*/
+
+#define THREADREQUEST_EXIT              0
+#define WAVEREQUEST_QUEUE_BUFFER        1
 
 
 /*
@@ -285,6 +330,13 @@
     LPDWORD BytesReturned,
     LPOVERLAPPED Overlapped);
 
+MMRESULT
+WriteSoundDeviceBuffer(
+    PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
+    LPVOID Buffer,
+    DWORD BufferSize,
+    LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine);
+
 
 /*
     utility.c
@@ -344,15 +396,20 @@
 
 MMRESULT
 SetWaveDeviceFormat(
-    IN  PSOUND_DEVICE Device,
+    IN  PSOUND_DEVICE_INSTANCE Instance,
     IN  PWAVEFORMATEX WaveFormat,
     IN  DWORD WaveFormatSize);
 
 MMRESULT
 DefaultSetWaveDeviceFormat(
-    IN  PSOUND_DEVICE Device,
-    IN  PWAVEFORMATEX WaveFormat,
-    IN  DWORD WaveFormatSize);
+    IN  PSOUND_DEVICE_INSTANCE Instance,
+    IN  PWAVEFORMATEX WaveFormat,
+    IN  DWORD WaveFormatSize);
+
+MMRESULT
+QueueWaveDeviceBuffer(
+    IN  PSOUND_DEVICE_INSTANCE Instance,
+    IN  PWAVEHDR BufferHeader);
 
 
 /*

Modified: branches/silverblade-audio/lib/drivers/sound/mmebuddy/devices.c
URL: http://svn.reactos.org/svn/reactos/branches/silverblade-audio/lib/drivers/sound/mmebuddy/devices.c?rev=34323&r1=34322&r2=34323&view=diff
==============================================================================
--- branches/silverblade-audio/lib/drivers/sound/mmebuddy/devices.c [iso-8859-1] (original)
+++ branches/silverblade-audio/lib/drivers/sound/mmebuddy/devices.c [iso-8859-1] Sun Jul  6 05:22:42 2008
@@ -10,6 +10,7 @@
 
     History:
         4 July 2008 - Created
+        5 July 2008 - Implemented format support
 */
 
 
@@ -431,7 +432,7 @@
         return MMSYSERR_INVALPARAM;
 
     /* Make sure we have a wave device */
-    if ( IS_WAVE_DEVICE_TYPE(Device->DeviceType) )
+    if ( ! IS_WAVE_DEVICE_TYPE(Device->DeviceType) )
     {
         return MMSYSERR_INVALPARAM;
     }
@@ -448,11 +449,11 @@
 
 MMRESULT
 SetWaveDeviceFormat(
-    IN  PSOUND_DEVICE Device,
+    IN  PSOUND_DEVICE_INSTANCE Instance,
     IN  PWAVEFORMATEX WaveFormat,
     IN  DWORD WaveFormatSize)
 {
-    if ( ! Device )
+    if ( ! Instance )
         return MMSYSERR_INVALPARAM;
 
     if ( ! WaveFormat )
@@ -460,31 +461,31 @@
 
     /* TODO: Should we check the size? */
 
-    return Device->Functions.SetWaveFormat(Device, WaveFormat, WaveFormatSize);
+    return Instance->Device->Functions.SetWaveFormat(Instance, WaveFormat, WaveFormatSize);
 }
 
 MMRESULT
 DefaultSetWaveDeviceFormat(
-    IN  PSOUND_DEVICE Device,
+    IN  PSOUND_DEVICE_INSTANCE Instance,
     IN  PWAVEFORMATEX WaveFormat,
     IN  DWORD WaveFormatSize)
 {
     MMRESULT Result;
     DWORD BytesReturned = 0;
 
-    if ( ! Device )
+    if ( ! Instance )
         return MMSYSERR_INVALPARAM;
 
     if ( ! WaveFormat )
         return MMSYSERR_INVALPARAM;
 
     /* Make sure we have a wave device */
-    if ( IS_WAVE_DEVICE_TYPE(Device->DeviceType) )
-    {
-        return MMSYSERR_INVALPARAM;
-    }
-
-    Result = WriteSoundDevice(Device,
+    if ( ! IS_WAVE_DEVICE_TYPE(Instance->Device->DeviceType) )
+    {
+        return MMSYSERR_INVALPARAM;
+    }
+
+    Result = WriteSoundDevice(Instance->Device,
                               IOCTL_WAVE_SET_FORMAT,
                               (LPVOID) WaveFormat,
                               WaveFormatSize,
@@ -494,3 +495,34 @@
     return Result;
 }
 
+MMRESULT
+QueueWaveDeviceBuffer(
+    IN  PSOUND_DEVICE_INSTANCE Instance,
+    IN  PWAVEHDR BufferHeader)
+{
+    MMRESULT Result;
+
+    if ( ! Instance )
+        return MMSYSERR_INVALPARAM;
+
+    if ( ! BufferHeader )
+        return MMSYSERR_INVALPARAM;
+
+    if ( ! BufferHeader->lpData )
+        return MMSYSERR_INVALPARAM;
+
+    if ( ! BufferHeader->dwBufferLength )
+        return MMSYSERR_INVALPARAM;
+
+    if ( ! (BufferHeader->dwFlags & WHDR_PREPARED ) )
+        return WAVERR_UNPREPARED;
+
+    /* TODO: WHDR_INQUEUE */
+
+    BufferHeader->dwFlags &= ~WHDR_DONE;
+    BufferHeader->lpNext = NULL;
+
+    Result = CallSoundThread(Instance, WAVEREQUEST_QUEUE_BUFFER, BufferHeader);
+
+    return Result;
+}

Modified: branches/silverblade-audio/lib/drivers/sound/mmebuddy/kernel.c
URL: http://svn.reactos.org/svn/reactos/branches/silverblade-audio/lib/drivers/sound/mmebuddy/kernel.c?rev=34323&r1=34322&r2=34323&view=diff
==============================================================================
--- 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 05:22:42 2008
@@ -30,11 +30,13 @@
 
     if ( ! Handle )
     {
+        MessageBox(0, L"Failed handle", L"kernel.c", MB_OK | MB_TASKMODAL);
         return MMSYSERR_INVALPARAM;
     }
 
     if ( ! DeviceName )
     {
+        MessageBox(0, L"Failed devname", L"kernel.c", MB_OK | MB_TASKMODAL);
         return MMSYSERR_INVALPARAM;
     }
 
@@ -70,7 +72,16 @@
     MMRESULT Result;
 
     if ( ! SoundDevice )
-        return MMSYSERR_INVALPARAM;
+    {
+        SOUND_DEBUG(L"No sound device specified");
+        return MMSYSERR_INVALPARAM;
+    }
+
+    if ( SoundDevice->Handle != INVALID_HANDLE_VALUE )
+    {
+        SOUND_DEBUG(L"Already open?");
+        return MMSYSERR_ERROR; /*MMSYSERR_ALLOC;*/
+    }
 
     Result = OpenKernelSoundDeviceByName(SoundDevice->DevicePath,
                                          AccessRights,
@@ -179,3 +190,33 @@
                                 BytesReturned,
                                 Overlapped);
 }
+
+MMRESULT
+WriteSoundDeviceBuffer(
+    PSOUND_DEVICE_INSTANCE SoundDeviceInstance,
+    LPVOID Buffer,
+    DWORD BufferSize,
+    LPOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine)
+{
+    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);
+
+    if ( ! WriteFileEx(SoundDeviceInstance->Device->Handle,
+                       Buffer,
+                       BufferSize,
+                       &SoundDeviceInstance->Overlapped,
+                       CompletionRoutine) )
+    {
+        wsprintf(msg, L"Win32 Error %d", GetLastError());
+        SOUND_DEBUG(msg);
+        return Win32ErrorToMmResult(GetLastError());
+    }
+
+    return MMSYSERR_NOERROR;
+}

Modified: branches/silverblade-audio/lib/drivers/sound/mmebuddy/mme/wodMessage.c
URL: http://svn.reactos.org/svn/reactos/branches/silverblade-audio/lib/drivers/sound/mmebuddy/mme/wodMessage.c?rev=34323&r1=34322&r2=34323&view=diff
==============================================================================
--- 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 05:22:42 2008
@@ -30,6 +30,7 @@
 {
     MMRESULT Result = MMSYSERR_NOERROR;
     PSOUND_DEVICE Device = NULL;
+    PSOUND_DEVICE_INSTANCE Instance = NULL;
     DPRINT("wodMessageStub called\n");
 
     switch ( message )
@@ -55,10 +56,43 @@
         }
 
         case WODM_OPEN :
-            /*
-                OpenSoundDevice();
-            */
-            return MMSYSERR_BADDEVICEID;
+        {
+            WAVEOPENDESC* OpenParameters = (WAVEOPENDESC*) parameter1;
+
+            Result = GetSoundDevice(WAVE_OUT_DEVICE_TYPE, device_id, &Device);
+            if ( Result != MMSYSERR_NOERROR )
+                return Result;
+
+/*
+            if ( parameter2 & WAVE_FORMAT_QUERY )
+            {
+                Result = QueryWaveDeviceFormat(Device,
+                                               OpenParameters->lpFormat,
+                                               sizeof(WAVEFORMATEX));
+
+                return Result;
+            }
+*/
+
+            Result = CreateSoundDeviceInstance(Device, &Instance);
+            if ( Result != MMSYSERR_NOERROR )
+                return Result;
+
+            Result = SetWaveDeviceFormat(Instance,
+                                         OpenParameters->lpFormat,
+                                         sizeof(WAVEFORMATEX));
+
+            if ( Result != MMSYSERR_NOERROR )
+            {
+                DestroySoundDeviceInstance(Instance);
+                return Result;
+            }
+
+
+            /* TODO: Send callback... */
+
+            return MMSYSERR_NOERROR;
+        }
 
         case WODM_CLOSE :
             /* CloseSoundDevice() */

Modified: branches/silverblade-audio/lib/drivers/sound/mmebuddy/testing.c
URL: http://svn.reactos.org/svn/reactos/branches/silverblade-audio/lib/drivers/sound/mmebuddy/testing.c?rev=34323&r1=34322&r2=34323&view=diff
==============================================================================
--- branches/silverblade-audio/lib/drivers/sound/mmebuddy/testing.c [iso-8859-1] (original)
+++ branches/silverblade-audio/lib/drivers/sound/mmebuddy/testing.c [iso-8859-1] Sun Jul  6 05:22:42 2008
@@ -17,12 +17,19 @@
 #include <ntddsnd.h>
 #include <debug.h>
 
+#include <ntddk.h>
 #include <mmebuddy.h>
 
 
 /*
     **** TESTING CODE ONLY ****
 */
+
+PSOUND_DEVICE Device;
+PSOUND_DEVICE_INSTANCE Instance;
+WAVEHDR waveheader;
+WORD JunkBuffer[65536];
+
 
 #define IDS_WAVEOUT_PNAME   0x68
 
@@ -159,6 +166,92 @@
 }
 
 
+VOID CALLBACK
+OverlappedCallback(
+    IN  DWORD dwErrorCode,
+    IN  DWORD dwNumberOfBytesTransferred,
+    IN  LPOVERLAPPED lpOverlapped)
+{
+    MessageBox(0, L"Job done!", L"File IO Callback", MB_OK | MB_TASKMODAL);
+}
+
+
+VOID
+TestPlaybackHackingly()
+{
+    WCHAR msg[1024];
+    MMRESULT Result;
+    WAVEFORMATEX fmt;
+    ULONG i;
+
+    for ( i = 0; i < 65536; ++ i )
+        JunkBuffer[i] = rand();
+
+    AddSoundDevice(WAVE_OUT_DEVICE_TYPE, L"\\\\.\\SBWaveOut0");
+    Result = GetSoundDevice(WAVE_OUT_DEVICE_TYPE, 0, &Device);
+
+    if ( Result != MMSYSERR_NOERROR )
+    {
+        MessageBox(0, L"Fail 1", L"Fail", MB_OK | MB_TASKMODAL);
+        return;
+    }
+
+    Result = OpenKernelSoundDevice(Device, GENERIC_READ | GENERIC_WRITE);
+    if ( Result != MMSYSERR_NOERROR )
+    {
+        MessageBox(0, L"Fail open", L"Fail", MB_OK | MB_TASKMODAL);
+        return;
+    }
+    wsprintf(msg, L"Opened handle %x", Device->Handle);
+    MessageBox(0, msg, L"Result", MB_OK | MB_TASKMODAL);
+
+    Result = CreateSoundDeviceInstance(Device, &Instance);
+    if ( Result != MMSYSERR_NOERROR )
+    {
+        MessageBox(0, L"Fail 2", L"Fail 2", MB_OK | MB_TASKMODAL);
+        return;
+    }
+
+    /* Request a valid format */
+    fmt.wFormatTag = WAVE_FORMAT_PCM;
+    fmt.nChannels = 1;
+    fmt.nSamplesPerSec = 22050;
+    fmt.wBitsPerSample = 16;
+    fmt.nBlockAlign = fmt.nChannels * (fmt.wBitsPerSample / 8);
+    fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign;
+    fmt.cbSize = 0;
+
+    Result = SetWaveDeviceFormat(Instance, &fmt, sizeof(WAVEFORMATEX));
+
+    wsprintf(msg, L"Format support set result: %d\nClick to play!", Result);
+    MessageBox(0, msg, L"Result", MB_OK | MB_TASKMODAL);
+
+    //SOUND_DEBUG_HEX(Instance->Device->Handle);
+
+    Result = StartWaveThread(Instance);
+    if ( Result != MMSYSERR_NOERROR )
+    {
+        MessageBox(0, L"Failed to start thread", L"Fail 3", MB_OK | MB_TASKMODAL);
+        return;
+    }
+
+    //SOUND_DEBUG_HEX(Instance->Device->Handle);
+
+    waveheader.lpData = (PVOID) JunkBuffer;
+    waveheader.dwBufferLength = 65536;
+    waveheader.dwFlags = WHDR_PREPARED;
+
+    Result = QueueWaveDeviceBuffer(Instance, &waveheader);
+//    CallSoundThread(Instance, WAVEREQUEST_QUEUE_BUFFER, &waveheader);
+/*
+    Result = WriteSoundDeviceBuffer(Instance,
+                                    JunkBuffer, 65535, OverlappedCallback);
+*/
+    wsprintf(msg, L"Play result: %d", Result);
+    MessageBox(0, msg, L"Result", MB_OK | MB_TASKMODAL);
+}
+
+
 APIENTRY VOID
 TestDevEnum()
 {
@@ -225,7 +318,8 @@
     LPWSTR lpCmdLine,
     int nCmdShow)
 {
-    TestFormatQuery();
+//    TestFormatQuery();
+    TestPlaybackHackingly();
 //    TestDevEnum();
 /*
     TestThreading();

Modified: branches/silverblade-audio/lib/drivers/sound/mmebuddy/thread.c
URL: http://svn.reactos.org/svn/reactos/branches/silverblade-audio/lib/drivers/sound/mmebuddy/thread.c?rev=34323&r1=34322&r2=34323&view=diff
==============================================================================
--- 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 05:22:42 2008
@@ -49,38 +49,34 @@
 
     while ( Thread->Running )
     {
-        /* Wait for some work */
-        WaitForSingleObject(Thread->RequestEvent, INFINITE);
-
-        /* Do the work (request 0 kills the thread) */
-        Thread->Request.Result =
-            Thread->RequestHandler(Instance,
-                                   Thread->Request.RequestId,
-                                   Thread->Request.Data);
-
-        if ( Thread->Request.RequestId == 0 )
+        DWORD WaitResult;
+
+        /* Wait for some work, or I/O completion */
+        WaitResult = WaitForSingleObjectEx(Thread->RequestEvent, INFINITE, TRUE);
+
+        if ( WaitResult == WAIT_OBJECT_0 )
         {
-            Thread->Running = FALSE;
-            Thread->Request.Result = MMSYSERR_NOERROR;
+            /* Do the work (request 0 kills the thread) */
+            Thread->Request.Result =
+                Thread->RequestHandler(Instance,
+                                       Thread->Request.RequestId,
+                                       Thread->Request.Data);
+
+            if ( Thread->Request.RequestId == 0 )
+            {
+                Thread->Running = FALSE;
+                Thread->Request.Result = MMSYSERR_NOERROR;
+            }
+
+            /* Notify the caller that the work is done */
+            SetEvent(Thread->ReadyEvent);
+            SetEvent(Thread->DoneEvent);
         }
-
-        /* Notify the caller that the work is done */
-        SetEvent(Thread->ReadyEvent);
-        SetEvent(Thread->DoneEvent);
-
-/*
-        DWORD Signalled = 0;
-
-        Signalled = WaitForMultipleObjects(2, Events, FALSE, INFINITE);
-
-        if ( Signalled == WAIT_OBJECT_0 )
+        else if ( WaitResult == WAIT_IO_COMPLETION )
         {
-            Thread->Running = FALSE;
+            /* This gets called after I/O completion */
+            /* Do we need to do anything special here? */
         }
-        else if ( Signalled == WAIT_OBJECT_0 + 1 )
-        {
-        }
-*/
     }
 
     /*MessageBox(0, L"Bye from thread!", L"Bye!", MB_OK | MB_TASKMODAL);*/
@@ -226,7 +222,7 @@
 
     /* Wait for the thread to exit */
     WaitForSingleObject(Instance->Thread->Handle, INFINITE);
- 
+
     /* Finish with the thread */
     CloseHandle(Instance->Thread->Handle);
     Instance->Thread->Handle = INVALID_HANDLE_VALUE;

Modified: branches/silverblade-audio/lib/drivers/sound/mmebuddy/wave/wavethread.c
URL: http://svn.reactos.org/svn/reactos/branches/silverblade-audio/lib/drivers/sound/mmebuddy/wave/wavethread.c?rev=34323&r1=34322&r2=34323&view=diff
==============================================================================
--- 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 05:22:42 2008
@@ -10,12 +10,68 @@
 
     History:
         4 July 2008 - Created
+
+    TODO:
+        Track if a buffer has already been inserted?
 */
 
 #include <windows.h>
 #include <mmsystem.h>
 
 #include <mmebuddy.h>
+
+VOID CALLBACK
+WaveBufferCompleted(
+    IN  DWORD dwErrorCode,
+    IN  DWORD dwNumberOfBytesTransferred,
+    IN  LPOVERLAPPED lpOverlapped)
+{
+    MessageBox(0, L"Job done!", L"File IO Callback", MB_OK | MB_TASKMODAL);
+}
+
+/* Internal dispatch routines */
+
+MMRESULT
+SubmitWaveBuffer(
+    IN  PSOUND_DEVICE_INSTANCE Instance,
+    IN  PWAVEHDR Buffer)
+{
+    MMRESULT Result;
+
+    SOUND_ASSERT(Instance != NULL);
+    SOUND_ASSERT(Buffer != NULL);
+
+    /* Set the head of the buffer list if this is the first buffer */
+    if ( ! Instance->Wave.FirstBuffer )
+    {
+        Instance->Wave.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;
+    }
+
+    /* Update our record of the last buffer */
+    Instance->Wave.LastBuffer = Buffer;
+
+    /* Increment the number of buffers queued */
+    ++ Instance->Wave.BufferCount;
+
+    /* HACK */
+    Instance->Wave.CurrentBuffer = Instance->Wave.FirstBuffer;
+
+    Result = WriteSoundDeviceBuffer(Instance,
+                                    Instance->Wave.CurrentBuffer->lpData,
+                                    Instance->Wave.CurrentBuffer->dwBufferLength,
+                                    WaveBufferCompleted);
+
+    return MMSYSERR_NOERROR;
+}
+
+
+/* Thread callback */
 
 MMRESULT
 ProcessWaveThreadRequest(
@@ -29,6 +85,18 @@
 
     MessageBox(0, msg, L"Request", MB_OK | MB_TASKMODAL);
 
+    SOUND_ASSERT(Instance != NULL);
+
+    switch ( RequestId )
+    {
+        case WAVEREQUEST_QUEUE_BUFFER :
+        {
+            PWAVEHDR Buffer = (PWAVEHDR) Data;
+
+            return SubmitWaveBuffer(Instance, Buffer);
+        }
+    }
+
     return MMSYSERR_NOTSUPPORTED;
 }
 
@@ -40,6 +108,12 @@
 
     if ( ! Instance )
         return MMSYSERR_INVALPARAM;
+
+    /* Initialise our data */
+    Instance->Wave.CurrentBuffer = NULL;
+    Instance->Wave.FirstBuffer = NULL;
+    Instance->Wave.LastBuffer = NULL;
+    Instance->Wave.BufferCount = 0;
 
     /* Kick off the thread */
     Result = StartSoundThread(Instance, ProcessWaveThreadRequest);



More information about the Ros-diffs mailing list