Index: trunk/src/winmm/WINMM.DEF
===================================================================
--- trunk/src/winmm/WINMM.DEF	(revision 21357)
+++ trunk/src/winmm/WINMM.DEF	(revision 21358)
@@ -202,2 +202,6 @@
 ;    winmmf_ThunkData32         = _winmmf_ThunkData32@??      @184
 ;    winmmsl_ThunkData32        = _winmmsl_ThunkData32@??     @185
+; ODIN-specific
+    ODIN_IsFlashAudioEnabled   = _ODIN_IsFlashAudioEnabled@0 @186
+    ODIN_EnableFlashAudio      = _ODIN_EnableFlashAudio@4    @187
+
Index: trunk/src/winmm/WINMMDBG.DEF
===================================================================
--- trunk/src/winmm/WINMMDBG.DEF	(revision 21357)
+++ trunk/src/winmm/WINMMDBG.DEF	(revision 21358)
@@ -202,2 +202,6 @@
 ;    winmmf_ThunkData32         = _Dbgwinmmf_ThunkData32@??      @184
 ;    winmmsl_ThunkData32        = _Dbgwinmmsl_ThunkData32@??     @185
+; ODIN-specific
+    ODIN_IsFlashAudioEnabled   = _DbgODIN_IsFlashAudioEnabled@0 @186
+    ODIN_EnableFlashAudio      = _DbgODIN_EnableFlashAudio@4    @187
+
Index: trunk/src/winmm/dbglocal.cpp
===================================================================
--- trunk/src/winmm/dbglocal.cpp	(revision 21357)
+++ trunk/src/winmm/dbglocal.cpp	(revision 21358)
@@ -43,5 +43,6 @@
 "waveoutdaud",
 "waveoutbase",
-"waveinoutbase"
+"waveinoutbase",
+"waveoutflash"
 };
 //******************************************************************************
Index: trunk/src/winmm/dbglocal.h
===================================================================
--- trunk/src/winmm/dbglocal.h	(revision 21357)
+++ trunk/src/winmm/dbglocal.h	(revision 21358)
@@ -43,5 +43,6 @@
 #define DBG_waveoutbase     21
 #define DBG_waveinoutbase   22
-#define DBG_MAXFILES        23
+#define DBG_waveoutflash    23
+#define DBG_MAXFILES        24
 
 extern USHORT DbgEnabledWINMM[DBG_MAXFILES];
Index: trunk/src/winmm/dbgwrap.cpp
===================================================================
--- trunk/src/winmm/dbgwrap.cpp	(revision 21357)
+++ trunk/src/winmm/dbgwrap.cpp	(revision 21358)
@@ -206,4 +206,6 @@
 DEBUGWRAP12(waveOutUnprepareHeader)
 DEBUGWRAP12(waveOutWrite)
+DEBUGWRAP0(ODIN_IsFlashAudioEnabled)
+DEBUGWRAP4(ODIN_EnableFlashAudio)
 
 #undef DBG_LOCALLOG
Index: trunk/src/winmm/initwinmm.cpp
===================================================================
--- trunk/src/winmm/initwinmm.cpp	(revision 21357)
+++ trunk/src/winmm/initwinmm.cpp	(revision 21358)
@@ -126,5 +126,5 @@
             // try to load the MDM library, not MMPM directly!!!
             if (DosLoadModule(szError, sizeof(szError),
-                              "MDM.DLL", &MMPMLibraryHandle) != NO_ERROR)
+                              "MDM", &MMPMLibraryHandle) != NO_ERROR)
             {
                 // this system has no MMPM :-(
Index: trunk/src/winmm/wavein.cpp
===================================================================
--- trunk/src/winmm/wavein.cpp	(revision 21357)
+++ trunk/src/winmm/wavein.cpp	(revision 21358)
@@ -14,8 +14,7 @@
  */
 
-
-/****************************************************************************
- * Includes                                                                 *
- ****************************************************************************/
+/******************************************************************************/
+// Includes
+/******************************************************************************/
 
 #include <os2win.h>
@@ -34,5 +33,4 @@
 #include "dbglocal.h"
 
-
 /******************************************************************************/
 /******************************************************************************/
@@ -47,12 +45,10 @@
         return(WAVERR_BADFORMAT);
 
-    if(fdwOpen & WAVE_FORMAT_QUERY)
-    {
+    if(fdwOpen & WAVE_FORMAT_QUERY) {
         if(DartWaveIn::queryFormat(pwfx->wFormatTag, pwfx->nChannels, pwfx->nSamplesPerSec,
                                    pwfx->wBitsPerSample) == TRUE)
-        {
              return(MMSYSERR_NOERROR);
-        }
-        else return(WAVERR_BADFORMAT);
+
+        return(WAVERR_BADFORMAT);
     }
 
@@ -62,9 +58,8 @@
     *phwi = (HWAVEOUT)new DartWaveIn(pwfx, fdwOpen, dwCallback, dwInstance);
 
-    if(*phwi == NULL) {
+    if(*phwi == NULL)
         return(MMSYSERR_NODRIVER);
-    }
-
-    rc = ((DartWaveIn *)*phwi)->getError();
+
+    rc = ((DartWaveIn *)*phwi)->open();
     if(rc != MMSYSERR_NOERROR) {
         delete (DartWaveIn *)*phwi;
Index: trunk/src/winmm/waveindart.cpp
===================================================================
--- trunk/src/winmm/waveindart.cpp	(revision 21357)
+++ trunk/src/winmm/waveindart.cpp	(revision 21358)
@@ -10,13 +10,9 @@
  * Project Odin Software License can be found in LICENSE.TXT
  *
- *
  */
 
-
-/****************************************************************************
- * Includes                                                                 *
- ****************************************************************************/
-
-
+/******************************************************************************/
+// Includes
+/******************************************************************************/
 
 #define  INCL_BASE
@@ -41,19 +37,18 @@
 #endif
 
-#ifndef max
-#define max(a, b) ((a > b) ? a : b)
-#endif
-
 LONG APIENTRY WaveInHandler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags);
 
+/******************************************************************************/
+/******************************************************************************/
+
 static BOOL fwaveInFixedBuffers = FALSE;
 
-//******************************************************************************
+/******************************************************************************/
+/******************************************************************************/
 // ODIN_waveInSetFixedBuffers
 //
 // Tell WINMM to use DART buffers of the same size as the first buffer delivered
 // by waveInAddBuffer
-//
-//******************************************************************************
+
 void WIN32API ODIN_waveInSetFixedBuffers()
 {
@@ -65,51 +60,91 @@
               : WaveInOut(pwfx, fdwOpen, nCallback, dwInstance)
 {
- MCI_GENERIC_PARMS  GenericParms;
- MCI_AMP_OPEN_PARMS AmpOpenParms;
- APIRET rc;
-
-    fOverrun        = FALSE;
+    DeviceId      = 0;
+    ulBufSize     = DART_BUFSIZE_REC;
     fMixerSetup   = FALSE;
+    fOverrun      = FALSE;
+    mixHandle     = 0;
+    pmixReadProc  = NULL;
+    MixBuffer     = NULL;
+    BufferParms   = NULL;
+
+    dprintf(("DartWaveIn: samplerate %d, numChan %d bps %d (%d), format %x",
+            SampleRate, nChannels, BitsPerSample, pwfx->nBlockAlign, pwfx->wFormatTag));
+}
+
+/******************************************************************************/
+/******************************************************************************/
+MMRESULT DartWaveIn::open()
+{
+    MCI_AMP_OPEN_PARMS AmpOpenParms;
+    MCI_GENERIC_PARMS  GenericParms = {0};
+    MCI_MIXSETUP_PARMS MixSetupParms;
+    APIRET rc;
 
     MixBuffer     = (MCI_MIX_BUFFER *)malloc(PREFILLBUF_DART_REC*sizeof(MCI_MIX_BUFFER));
-    MixSetupParms = (MCI_MIXSETUP_PARMS *)malloc(sizeof(MCI_MIXSETUP_PARMS));
     BufferParms   = (MCI_BUFFER_PARMS *)malloc(sizeof(MCI_BUFFER_PARMS));
-    if(!MixBuffer || !MixSetupParms || !BufferParms) {
+    if(!MixBuffer || !BufferParms) {
         dprintf(("ERROR: malloc failed!!"));
-        ulError = MMSYSERR_NOMEM;
-        return;
-    }
-
-    ulBufSize       = DART_BUFSIZE_REC;
-
-    dprintf(("waveInOpen: samplerate %d, numChan %d bps %d (%d), format %x", SampleRate, nChannels, BitsPerSample, pwfx->nBlockAlign, pwfx->wFormatTag));
+        return MMSYSERR_NOMEM;
+    }
+
     // Setup the open structure, pass the playlist and tell MCI_OPEN to use it
-    memset(&AmpOpenParms,0,sizeof(AmpOpenParms));
-
-    AmpOpenParms.usDeviceID = ( USHORT ) 0;
-    AmpOpenParms.pszDeviceType = ( PSZ ) MCI_DEVTYPE_AUDIO_AMPMIX;
-
-    rc = mymciSendCommand(0, MCI_OPEN, MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
+    memset(&AmpOpenParms, 0, sizeof(AmpOpenParms));
+    AmpOpenParms.usDeviceID = 0;
+    AmpOpenParms.pszDeviceType = (PSZ)MCI_DEVTYPE_AUDIO_AMPMIX;
+
+    rc = mymciSendCommand(0, MCI_OPEN,
+                          MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
                           (PVOID) &AmpOpenParms, 0);
-    DeviceId = AmpOpenParms.usDeviceID;
     if(rc) {
         dprintf(("MCI_OPEN failed\n"));
         mciError(rc);
-        ulError = MMSYSERR_NODRIVER;
-    }
-    if(rc == 0) {
-        //Grab exclusive rights to device instance (NOT entire device)
-        GenericParms.hwndCallback = 0;  //Not needed, so set to 0
-        rc = mymciSendCommand(DeviceId, MCI_ACQUIREDEVICE, MCI_EXCLUSIVE_INSTANCE,
-                            (PVOID)&GenericParms, 0);
-        if(rc) {
-            dprintf(("MCI_ACQUIREDEVICE failed\n"));
-            mciError(rc);
-            ulError = MMSYSERR_NOTENABLED;
-        }
-    }
-
-    if(!ulError)
-        callback(WIM_OPEN, 0, 0);
+        return MMSYSERR_NODRIVER;
+    }
+
+    DeviceId = AmpOpenParms.usDeviceID;
+
+    //Grab exclusive rights to device instance (NOT entire device)
+    rc = mymciSendCommand(DeviceId, MCI_ACQUIREDEVICE,
+                          MCI_EXCLUSIVE_INSTANCE,
+                          (PVOID)&GenericParms, 0);
+    if(rc) {
+        dprintf(("MCI_ACQUIREDEVICE failed\n"));
+        mciError(rc);
+        return MMSYSERR_NOTENABLED;
+    }
+
+    dprintf(("device acquired\n"));
+    dprintf(("bps %d, sps %d chan %d\n", BitsPerSample, SampleRate, nChannels));
+
+    // Set the MixSetupParms data structure
+    memset(&MixSetupParms, 0, sizeof(MCI_MIXSETUP_PARMS));
+    MixSetupParms.ulBitsPerSample = BitsPerSample;
+    MixSetupParms.ulSamplesPerSec = SampleRate;
+    MixSetupParms.ulFormatTag     = MCI_WAVE_FORMAT_PCM;
+    MixSetupParms.ulChannels      = nChannels;
+    MixSetupParms.ulFormatMode    = MCI_RECORD;
+    MixSetupParms.ulDeviceType    = MCI_DEVTYPE_WAVEFORM_AUDIO;
+    MixSetupParms.pmixEvent       = WaveInHandler;
+
+    rc = mymciSendCommand(DeviceId, MCI_MIXSETUP,
+                          MCI_WAIT | MCI_MIXSETUP_INIT,
+                          (PVOID)&MixSetupParms, 0);
+    if ( rc != MCIERR_SUCCESS ) {
+        mymciSendCommand(DeviceId, MCI_RELEASEDEVICE,
+                         MCI_WAIT,
+                         (PVOID)&GenericParms, 0);
+        mciError(rc);
+        return MMSYSERR_NOTSUPPORTED;
+    }
+
+    // Save the mixer handle & the ptr to the read proc.
+    mixHandle    = MixSetupParms.ulMixHandle;
+    pmixReadProc = MixSetupParms.pmixRead;
+
+
+    callback(WIM_OPEN, 0, 0);
+
+    return MMSYSERR_NOERROR;
 }
 /******************************************************************************/
@@ -117,30 +152,24 @@
 DartWaveIn::~DartWaveIn()
 {
-   MCI_GENERIC_PARMS    GenericParms;
+   MCI_GENERIC_PARMS    GenericParms = {0};
 
    State = STATE_STOPPED;
 
-    if(!ulError)
+    if (DeviceId)
     {
-        // Generic parameters
-        GenericParms.hwndCallback = 0;   //hwndFrame
-
         // Stop recording.
-        mymciSendCommand(DeviceId, MCI_STOP,MCI_WAIT, (PVOID)&GenericParms,0);
-
-        mymciSendCommand(DeviceId,
-                      MCI_BUFFER,
-                      MCI_WAIT | MCI_DEALLOCATE_MEMORY,
-                      (PVOID)&BufferParms,
-                      0);
-
-        // Generic parameters
-        GenericParms.hwndCallback = 0;   //hwndFrame
+        mymciSendCommand(DeviceId, MCI_STOP,
+                         MCI_WAIT, (PVOID)&GenericParms, 0);
+
+        if (fMixerSetup)
+            mymciSendCommand(DeviceId, MCI_BUFFER,
+                             MCI_WAIT | MCI_DEALLOCATE_MEMORY,
+                             (PVOID)&BufferParms, 0);
 
         // Close the device
-        mymciSendCommand(DeviceId, MCI_CLOSE, MCI_WAIT, (PVOID)&GenericParms, 0);
-    }
-    if(!ulError)
-    {
+        mymciSendCommand(DeviceId, MCI_CLOSE,
+                         MCI_WAIT,
+                         (PVOID)&GenericParms, 0);
+
         callback(WIM_CLOSE, 0, 0);
     }
@@ -148,6 +177,4 @@
     if(MixBuffer)
         free(MixBuffer);
-    if(MixSetupParms)
-        free(MixSetupParms);
     if(BufferParms)
         free(BufferParms);
@@ -180,33 +207,4 @@
     if(fMixerSetup == FALSE)
     {
-        dprintf(("device acquired\n"));
-        /* Set the MixSetupParms data structure to match the loaded file.
-         * This is a global that is used to setup the mixer.
-         */
-        memset(MixSetupParms, 0, sizeof( MCI_MIXSETUP_PARMS ) );
-
-        MixSetupParms->ulBitsPerSample = BitsPerSample;
-        MixSetupParms->ulSamplesPerSec = SampleRate;
-        MixSetupParms->ulFormatTag     = MCI_WAVE_FORMAT_PCM;
-        MixSetupParms->ulChannels      = nChannels;
-
-        dprintf(("bps %d, sps %d chan %d\n", BitsPerSample, SampleRate, nChannels));
-
-        /* Setup the mixer for recording of wave data
-         */
-        MixSetupParms->ulFormatMode = MCI_RECORD;
-        MixSetupParms->ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
-        MixSetupParms->pmixEvent    = WaveInHandler;
-
-        rc = mymciSendCommand(DeviceId, MCI_MIXSETUP, MCI_WAIT | MCI_MIXSETUP_INIT,
-                              (PVOID)MixSetupParms, 0);
-
-        if ( rc != MCIERR_SUCCESS ) {
-            mciError(rc);
-            mymciSendCommand(DeviceId, MCI_RELEASEDEVICE, MCI_WAIT,
-                           (PVOID)&GenericParms, 0);
-            return(MMSYSERR_NOTSUPPORTED);
-        }
-
         /*
          * Set up the BufferParms data structure and allocate
@@ -227,5 +225,4 @@
             {
                 dprintf(("mix setup %d, %d\n", pwh->dwBufferLength, pwh->dwBufferLength));
-    
                 ulBufSize = pwh->dwBufferLength/2;
             }
@@ -237,8 +234,6 @@
         else ulBufSize = minbufsize;
 
-        MixSetupParms->ulBufferSize = ulBufSize;
-
         BufferParms->ulNumBuffers = PREFILLBUF_DART_REC;
-        BufferParms->ulBufferSize = MixSetupParms->ulBufferSize;
+        BufferParms->ulBufferSize = ulBufSize;
         BufferParms->pBufList     = MixBuffer;
 
@@ -247,15 +242,14 @@
         }
 
-        rc = mymciSendCommand(DeviceId,
-                            MCI_BUFFER,
-                            MCI_WAIT | MCI_ALLOCATE_MEMORY,
-                            (PVOID)BufferParms,
-                            0);
+        rc = mymciSendCommand(DeviceId, MCI_BUFFER,
+                              MCI_WAIT | MCI_ALLOCATE_MEMORY,
+                              (PVOID)BufferParms, 0);
 
         if(ULONG_LOWD(rc) != MCIERR_SUCCESS) {
             mciError(rc);
-            mymciSendCommand(DeviceId, MCI_RELEASEDEVICE, MCI_WAIT,
-                          (PVOID)&GenericParms, 0);
-            return(MMSYSERR_NOTSUPPORTED);
+            mymciSendCommand(DeviceId, MCI_RELEASEDEVICE,
+                             MCI_WAIT,
+                             (PVOID)&GenericParms, 0);
+            return MMSYSERR_NOTSUPPORTED;
         }
 
@@ -263,20 +257,18 @@
         //(until we really support the mixer extensions anyway)
         /* Set the connector to 'microphone' */
-        memset( &ConnectorParms, '\0', sizeof( MCI_CONNECTOR_PARMS ) );
+        memset(&ConnectorParms, 0, sizeof(MCI_CONNECTOR_PARMS));
         ConnectorParms.ulConnectorType = MCI_MICROPHONE_CONNECTOR;
-        rc = mymciSendCommand(DeviceId, MCI_CONNECTOR, MCI_WAIT |
-                              MCI_ENABLE_CONNECTOR | MCI_CONNECTOR_TYPE,
-                              ( PVOID ) &ConnectorParms, 0 );
+        rc = mymciSendCommand(DeviceId, MCI_CONNECTOR,
+                              MCI_WAIT | MCI_ENABLE_CONNECTOR | MCI_CONNECTOR_TYPE,
+                              (PVOID)&ConnectorParms, 0 );
 
         /* Allow the user to hear what is being recorded
          * by turning the monitor on
          */
-        memset( &AmpSetParms, '\0', sizeof( MCI_AMP_SET_PARMS ) );
+        memset(&AmpSetParms, 0, sizeof( MCI_AMP_SET_PARMS ) );
         AmpSetParms.ulItem = MCI_AMP_SET_MONITOR;
-        rc = mymciSendCommand(DeviceId,
-                            MCI_SET,
-                            MCI_WAIT | MCI_SET_ON | MCI_SET_ITEM,
-                            ( PVOID ) &AmpSetParms,
-                            0 );
+        rc = mymciSendCommand(DeviceId, MCI_SET,
+                              MCI_WAIT | MCI_SET_ON | MCI_SET_ITEM,
+                              (PVOID)&AmpSetParms, 0);
 
         wmutex.enter();
@@ -284,10 +276,9 @@
     }
 
-    for(i=0;i<PREFILLBUF_DART_REC;i++) {
+    for(i=0; i< PREFILLBUF_DART_REC; i++) {
         memset(MixBuffer[i].pBuffer, 0, MixBuffer[i].ulBufferLength);
     }
     dprintf(("Dart opened, bufsize = %d\n", MixBuffer[0].ulBufferLength));
 
-    dprintf(("MixSetupParms = %X\n", MixSetupParms));
     State    = STATE_RECORDING;
     fOverrun = FALSE;
@@ -298,5 +289,5 @@
     // Start recording.
     USHORT selTIB = RestoreOS2FS(); // save current FS selector
-    MixSetupParms->pmixRead(MixSetupParms->ulMixHandle, &MixBuffer[0], PREFILLBUF_DART_REC);
+    pmixReadProc(mixHandle, &MixBuffer[0], PREFILLBUF_DART_REC);
     SetFS(selTIB);           // switch back to the saved FS selector
 
@@ -506,10 +497,10 @@
 /******************************************************************************/
 /******************************************************************************/
-void DartWaveIn::mciError(ULONG ulError)
+void DartWaveIn::mciError(ULONG rc)
 {
 #ifdef DEBUG
     char szError[256] = "";
 
-    mymciGetErrorString(ulError, szError, sizeof(szError));
+    mymciGetErrorString(rc, szError, sizeof(szError));
     dprintf(("WINMM: DartWaveIn: %s\n", szError));
 #endif
@@ -586,5 +577,5 @@
     // MCI_MIXSETUP_PARMS->pMixWrite does alter FS: selector!
     USHORT selTIB = RestoreOS2FS(); // save current FS selector
-    MixSetupParms->pmixRead(MixSetupParms->ulMixHandle, pBuffer, 1);
+    pmixReadProc(mixHandle, pBuffer, 1);
     SetFS(selTIB);           // switch back to the saved FS selector
 }
Index: trunk/src/winmm/waveindart.h
===================================================================
--- trunk/src/winmm/waveindart.h	(revision 21357)
+++ trunk/src/winmm/waveindart.h	(revision 21358)
@@ -6,4 +6,5 @@
  * Project Odin Software License can be found in LICENSE.TXT
  */
+
 #ifndef __DWAVEIN_H__
 #define __DWAVEIN_H__
@@ -27,42 +28,43 @@
 #endif
 
+// this should be defined in some #included .h file, but it isn't
+typedef LONG (APIENTRY MIXERPROC)(ULONG ulHandle, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags);
+
 class DartWaveIn : public WaveInOut
 {
 public:
-              DartWaveIn(LPWAVEFORMATEX pwfx, DWORD fdwOpen, ULONG nCallback, ULONG dwInstance);
-     virtual ~DartWaveIn();
+                     DartWaveIn(LPWAVEFORMATEX pwfx, DWORD fdwOpen,
+                                ULONG nCallback, ULONG dwInstance);
+  virtual            ~DartWaveIn();
 
-     MMRESULT addBuffer(LPWAVEHDR pwh, UINT cbwh);
-     MMRESULT start();
-     MMRESULT stop();
-     int      getState()        { return State; };
-     MMRESULT reset();
-     ULONG    getPosition();
+          MMRESULT   open();
+          MMRESULT   addBuffer(LPWAVEHDR pwh, UINT cbwh);
+          MMRESULT   start();
+          MMRESULT   stop();
+          MMRESULT   reset();
+          ULONG      getPosition();
 
-
-  static int  getNumDevices();
-
-  static BOOL queryFormat(ULONG formatTag, ULONG nChannels,
-                          ULONG nSamplesPerSec, ULONG sampleSize);
+   static int        getNumDevices();
+   static BOOL       queryFormat(ULONG formatTag, ULONG nChannels,
+                                 ULONG nSamplesPerSec, ULONG sampleSize);
 
 protected:
-  static void mciError(ULONG ulError);
-         void handler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags);
+   static void       mciError(ULONG rc);
+          void       handler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer,
+                             ULONG ulFlags);
 
 private:
-        USHORT DeviceId;
-        ULONG  ulBufferCount;             /* Current file buffer     */
-        ULONG  ulBufSize;
-
-    MCI_MIX_BUFFER     *MixBuffer;          /* Device buffers          */
-    MCI_MIXSETUP_PARMS *MixSetupParms;          /* Mixer parameters        */
-    MCI_BUFFER_PARMS   *BufferParms;                /* Device buffer parms     */
-
-
-    BOOL      fMixerSetup;
-    BOOL      fOverrun;
+          USHORT     DeviceId;
+          ULONG      ulBufSize;
+          BOOL       fMixerSetup;
+          BOOL       fOverrun;
+          ULONG      mixHandle;
+         MIXERPROC * pmixReadProc;
+    MCI_MIX_BUFFER * MixBuffer;
+  MCI_BUFFER_PARMS * BufferParms;
 
 #ifndef _OS2WIN_H
-    friend    LONG APIENTRY WaveInHandler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags);
+   friend LONG APIENTRY WaveInHandler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer,
+                                      ULONG ulFlags);
 #endif
 };
Index: trunk/src/winmm/waveinoutbase.cpp
===================================================================
--- trunk/src/winmm/waveinoutbase.cpp	(revision 21357)
+++ trunk/src/winmm/waveinoutbase.cpp	(revision 21358)
@@ -12,10 +12,7 @@
  */
 
-
-/****************************************************************************
- * Includes                                                                 *
- ****************************************************************************/
-
-
+/******************************************************************************/
+// Includes
+/******************************************************************************/
 
 #define  INCL_BASE
@@ -35,5 +32,9 @@
 #include "dbglocal.h"
 
-VMutex wavemutex;
+/******************************************************************************/
+/******************************************************************************/
+
+VMutex      wavemutex;
+WaveInOut * WaveInOut::head = NULL;
 
 /******************************************************************************/
@@ -41,18 +42,16 @@
 WaveInOut::WaveInOut(LPWAVEFORMATEX pwfx, ULONG fdwOpen, ULONG nCallback, ULONG dwInstance)
 {
-    next            = NULL;
-    wavehdr         = NULL;
-    curhdr          = NULL;
-    ulError         = 0;
-    State           = STATE_STOPPED;
-    queuedbuffers   = 0;
-
-    BitsPerSample   = pwfx->wBitsPerSample;
-    SampleRate      = pwfx->nSamplesPerSec;
-    this->nChannels = pwfx->nChannels;
+    SampleRate    = pwfx->nSamplesPerSec;
+    BitsPerSample = pwfx->wBitsPerSample;
+    nChannels     = pwfx->nChannels;
+    OpenFlags     = fdwOpen;
+    Callback      = nCallback;
+    Instance      = dwInstance;
+    State         = STATE_STOPPED;
+    queuedbuffers = 0;
+    wavehdr       = NULL;
+    next          = NULL;
 
     dprintf(("WaveInOutOpen: samplerate %d, numChan %d bps %d (%d), format %x", SampleRate, nChannels, BitsPerSample, pwfx->nBlockAlign, pwfx->wFormatTag));
-
-    State    = STATE_STOPPED;
 
     wavemutex.enter();
@@ -70,8 +69,4 @@
     }
     wavemutex.leave();
-
-    this->fdwOpen = fdwOpen;
-    dwCallback    = nCallback;
-    this->dwInstance = dwInstance;
 }
 /******************************************************************************/
@@ -101,13 +96,13 @@
 {
     dprintf(("WINMM:WaveInOut::callback type %x, callback 0x%x (HDRVR h=%08xh, UINT uMessage=%08xh, DWORD dwUser=%08xh, DWORD dw1=%08xh, DWORD dw2=%08xh)",
-             fdwOpen, dwCallback, this, uMessage, dwInstance, dw1, dw2));
+             OpenFlags, Callback, this, uMessage, Instance, dw1, dw2));
 
-    switch(fdwOpen & CALLBACK_TYPEMASK) {
+    switch(OpenFlags & CALLBACK_TYPEMASK) {
     case CALLBACK_WINDOW:
-        PostMessageA((HWND)dwCallback, uMessage, (WPARAM)this, dw1);
+        PostMessageA((HWND)Callback, uMessage, (WPARAM)this, dw1);
         break;
 
     case CALLBACK_TASK: // == CALLBACK_THREAD
-        PostThreadMessageA(dwCallback, uMessage, (WPARAM)this, dw1);
+        PostThreadMessageA(Callback, uMessage, (WPARAM)this, dw1);
         break;
 
@@ -116,5 +111,5 @@
         USHORT selTIB = GetFS(); // save current FS selector
         USHORT selCallback;
-        LPDRVCALLBACK mthdCallback = (LPDRVCALLBACK)dwCallback;
+        LPDRVCALLBACK mthdCallback = (LPDRVCALLBACK)Callback;
 
         if(selTIB == SELECTOR_OS2_FS) {
@@ -130,5 +125,5 @@
             //@@@PH 1999/12/28 Shockwave Flash seem to make assumptions on a
             // specific stack layout. Do we have the correct calling convention here?
-            mthdCallback((HDRVR)this, uMessage, dwInstance, dw1, dw2);
+            mthdCallback((HDRVR)this, uMessage, Instance, dw1, dw2);
             SetFS(selTIB);           // switch back to the saved FS selector
         }
@@ -140,5 +135,5 @@
 
     case CALLBACK_EVENT:
-        SetEvent((HANDLE)dwCallback);
+        SetEvent((HANDLE)Callback);
         break;
 
@@ -147,5 +142,5 @@
 
     default:
-        dprintf(("WARNING: Unknown callback type %x %x", fdwOpen, dwCallback));
+        dprintf(("WARNING: Unknown callback type %x %x", OpenFlags, Callback));
         break;
     } //switch
@@ -187,4 +182,3 @@
 /******************************************************************************/
 /******************************************************************************/
-WaveInOut *WaveInOut::head = NULL;
 
Index: trunk/src/winmm/waveinoutbase.h
===================================================================
--- trunk/src/winmm/waveinoutbase.h	(revision 21357)
+++ trunk/src/winmm/waveinoutbase.h	(revision 21358)
@@ -8,4 +8,5 @@
  * Project Odin Software License can be found in LICENSE.TXT
  */
+
 #ifndef __WAVEINOUTBASE_H__
 #define __WAVEINOUTBASE_H__
@@ -25,43 +26,34 @@
 {
 public:
-              WaveInOut(LPWAVEFORMATEX pwfx, DWORD fdwOpen, ULONG nCallback, ULONG dwInstance);
-     virtual ~WaveInOut();
+                    WaveInOut(LPWAVEFORMATEX pwfx, DWORD fdwOpen,
+                              ULONG nCallback, ULONG dwInstance);
+  virtual           ~WaveInOut();
 
-              int      getState()               { return State; };
-              MMRESULT getError()               { return ulError; };
-              ULONG    getSampleRate()          { return SampleRate; };
-              ULONG    getBitsPerSample()       { return BitsPerSample; };
-              ULONG    getnumChannels()         { return nChannels; };
-              ULONG    getAvgBytesPerSecond()   { return (BitsPerSample/8) * nChannels * SampleRate; };
+          int       getState()               { return State; };
+          ULONG     getSampleRate()          { return SampleRate; };
+          ULONG     getBitsPerSample()       { return BitsPerSample; };
+          ULONG     getnumChannels()         { return nChannels; };
+          ULONG     getAvgBytesPerSecond()   { return (BitsPerSample/8) * nChannels * SampleRate; };
 
-  static BOOL find(WaveInOut *wave);
-  static void shutdown();
+   static BOOL      find(WaveInOut *wave);
+   static void      shutdown();
 
 protected:
+          void      callback(UINT uMessage, DWORD dw1, DWORD dw2);
 
-    ULONG       ulError, State;
-
-    int         SampleRate;
-    int         BitsPerSample;
-    int         nChannels;
-
-    int         queuedbuffers;
-
-    // callback interface
-    void        callback(UINT uMessage, DWORD dw1, DWORD dw2);
-
-    DWORD       fdwOpen;
-    DWORD       dwCallback;
-    DWORD       dwInstance;
-
-    WAVEHDR    *wavehdr,
-               *curhdr;
-
-         VMutex wmutex;
+          int       SampleRate;
+          int       BitsPerSample;
+          int       nChannels;
+          DWORD     OpenFlags;
+          DWORD     Callback;
+          DWORD     Instance;
+          ULONG     State;
+          int       queuedbuffers;
+          WAVEHDR * wavehdr;
+          VMutex    wmutex;
 
 private:
-                                          // Linked list management
-                WaveInOut *next;          // Next wave class
-    static      WaveInOut *head;          // List of wave classes 
+ static WaveInOut * head;          // List of wave classes 
+        WaveInOut * next;          // Next wave class
 };
 
Index: trunk/src/winmm/waveout.cpp
===================================================================
--- trunk/src/winmm/waveout.cpp	(revision 21357)
+++ trunk/src/winmm/waveout.cpp	(revision 21358)
@@ -1,4 +1,4 @@
 /* $Id: waveout.cpp,v 1.27 2003-07-16 15:47:24 sandervl Exp $ */
-//#undef DEBUG
+
 /*
  * Wave out MM apis
@@ -13,8 +13,7 @@
  */
 
-
-/****************************************************************************
- * Includes                                                                 *
- ****************************************************************************/
+/******************************************************************************/
+// Includes
+/******************************************************************************/
 
 #include <os2win.h>
@@ -29,4 +28,5 @@
 #include "waveoutdart.h"
 #include "waveoutdaud.h"
+#include "waveoutflash.h"
 #include "misc.h"
 #include "winmm.h"
@@ -36,5 +36,4 @@
 #include "dbglocal.h"
 
-
 /******************************************************************************/
 /******************************************************************************/
@@ -42,38 +41,40 @@
                             DWORD dwCallback, DWORD dwInstance, DWORD fdwOpen)
 {
-  MMRESULT rc;
-
-    if(fMMPMAvailable == FALSE) return MMSYSERR_NODRIVER;
-
-    if(pwfx == NULL)
+    MMRESULT rc;
+
+    if (fMMPMAvailable == FALSE)
+        return MMSYSERR_NODRIVER;
+
+    if (pwfx == NULL)
         return(WAVERR_BADFORMAT);
 
-    if(fdwOpen & WAVE_FORMAT_QUERY)
-    {
-        if(DartWaveOut::queryFormat(pwfx->wFormatTag, pwfx->nChannels, pwfx->nSamplesPerSec,
-                                    pwfx->wBitsPerSample) == TRUE) {
-                return(MMSYSERR_NOERROR);
-        }
-        else    return(WAVERR_BADFORMAT);
-    }
-
-    if(phwo == NULL)
+    if (fdwOpen & WAVE_FORMAT_QUERY) {
+        if (WaveOut::queryFormat(pwfx->wFormatTag, pwfx->nChannels,
+                                 pwfx->nSamplesPerSec,
+                                 pwfx->wBitsPerSample) == TRUE) {
+            return (MMSYSERR_NOERROR);
+        }
+        return (WAVERR_BADFORMAT);
+    }
+
+    if (phwo == NULL)
         return(MMSYSERR_INVALPARAM);
 
-    if(DAudioWaveOut::isDirectAudioAvailable()) {
-         *phwo = (HWAVEOUT)new DAudioWaveOut(pwfx, fdwOpen, dwCallback, dwInstance);
-    }
-    else *phwo = (HWAVEOUT)new DartWaveOut(pwfx, fdwOpen, dwCallback, dwInstance);
-
-    if(*phwo == NULL) {
+    if (ODIN_IsFlashAudioEnabled())
+        *phwo = (HWAVEOUT)new FlashWaveOut(pwfx, fdwOpen, dwCallback, dwInstance);
+    else
+    if (DAudioWaveOut::isDirectAudioAvailable())
+        *phwo = (HWAVEOUT)new DAudioWaveOut(pwfx, fdwOpen, dwCallback, dwInstance);
+    else
+        *phwo = (HWAVEOUT)new DartWaveOut(pwfx, fdwOpen, dwCallback, dwInstance);
+
+    if(*phwo == NULL)
         return(MMSYSERR_NODRIVER);
-    }
-
-    rc = ((WaveOut *)*phwo)->getError();
-    if(rc != MMSYSERR_NOERROR) {
+
+    rc = ((WaveOut *)*phwo)->open();
+    if (rc != MMSYSERR_NOERROR)
         delete (WaveOut *)*phwo;
-        return(rc);
-    }
-    return(MMSYSERR_NOERROR);
+
+    return rc;
 }
 /******************************************************************************/
Index: trunk/src/winmm/waveoutbase.cpp
===================================================================
--- trunk/src/winmm/waveoutbase.cpp	(revision 21357)
+++ trunk/src/winmm/waveoutbase.cpp	(revision 21358)
@@ -14,10 +14,7 @@
  */
 
-
-/****************************************************************************
- * Includes                                                                 *
- ****************************************************************************/
-
-
+/******************************************************************************/
+// Includes
+/******************************************************************************/
 
 #define  INCL_BASE
@@ -38,13 +35,9 @@
 #include "dbglocal.h"
 
-#ifndef min
-#define min(a, b) ((a > b) ? b : a)
-#endif
+/******************************************************************************/
+/******************************************************************************/
 
-#ifndef max
-#define max(a, b) ((a > b) ? a : b)
-#endif
+ULONG WaveOut::defvolume = 0xFFFFFFFF;
 
-//TODO: mulaw, alaw & adpcm
 /******************************************************************************/
 /******************************************************************************/
@@ -52,6 +45,4 @@
            : WaveInOut(pwfx, fdwOpen, nCallback, dwInstance)
 {
-    bytesPlayed = bytesCopied = bytesReturned = 0;
-
     volume = defvolume;
 
@@ -67,35 +58,95 @@
 int WaveOut::getNumDevices()
 {
- MCI_GENERIC_PARMS  GenericParms;
- MCI_AMP_OPEN_PARMS AmpOpenParms;
- APIRET rc;
+    MCI_AMP_OPEN_PARMS AmpOpenParms;
+    MCI_GENERIC_PARMS  GenericParms = {0};
+    APIRET rc;
 
-   // Setup the open structure, pass the playlist and tell MCI_OPEN to use it
-   memset(&AmpOpenParms,0,sizeof(AmpOpenParms));
+    // Try to open the device to see if it's there
+    memset(&AmpOpenParms, 0, sizeof(AmpOpenParms));
+    AmpOpenParms.usDeviceID = 0;
+    AmpOpenParms.pszDeviceType = (PSZ)MCI_DEVTYPE_AUDIO_AMPMIX;
 
-   AmpOpenParms.usDeviceID = ( USHORT ) 0;
-   AmpOpenParms.pszDeviceType = ( PSZ ) MCI_DEVTYPE_AUDIO_AMPMIX;
+    rc = mymciSendCommand(0, MCI_OPEN,
+                          MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
+                          (PVOID) &AmpOpenParms, 0);
 
-   rc = mymciSendCommand(0, MCI_OPEN,
-                       MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
-                       (PVOID) &AmpOpenParms,
-                       0);
+    if (LOUSHORT(rc) != MCIERR_SUCCESS)
+        return 0;
 
-   if(rc) {
-        return 0; //no devices present
-   }
+    // Close the device
+    mymciSendCommand(AmpOpenParms.usDeviceID, MCI_CLOSE,
+                     MCI_WAIT,
+                     (PVOID)&GenericParms, 0);
 
-   // Generic parameters
-   GenericParms.hwndCallback = 0;   //hwndFrame
-
-   // Close the device
-   mymciSendCommand(AmpOpenParms.usDeviceID, MCI_CLOSE, MCI_WAIT, (PVOID)&GenericParms, 0);
-
-   return 1;
+    return 1;
 }
 /******************************************************************************/
-//Called if waveOutSetVolume is called by the application with waveout handle NULL
-//Sets the default volume of each waveout stream (until it's volume is changed
-//with an appropriate waveOutSetVolume call)
+/******************************************************************************/
+BOOL WaveOut::queryFormat(ULONG formatTag, ULONG nChannels,
+                          ULONG nSamplesPerSec, ULONG wBitsPerSample)
+{
+    APIRET  rc;
+    BOOL    winrc = TRUE;
+    MCI_OPEN_PARMS            OpenParms;
+    MCI_WAVE_GETDEVCAPS_PARMS DevCapsParms;
+    MCI_GENERIC_PARMS         GenericParms = {0};
+#ifdef DEBUG
+    char szError[64] = "";
+#endif
+
+    dprintf(("WINMM: WaveOut::queryFormat %x srate=%d, nchan=%d, bps=%d", formatTag, nSamplesPerSec, nChannels, wBitsPerSample));
+
+    // Open the device.
+    memset(&OpenParms, 0, sizeof(OpenParms));
+    OpenParms.pszDeviceType = (PSZ)MCI_DEVTYPE_WAVEFORM_AUDIO;
+
+    rc = mymciSendCommand(0, MCI_OPEN,
+                          MCI_WAIT | MCI_OPEN_TYPE_ID,
+                          (PVOID)&OpenParms, 0);
+    if (LOUSHORT(rc) != MCIERR_SUCCESS) {
+        #ifdef DEBUG
+        mymciGetErrorString(rc, szError, sizeof(szError));
+        dprintf(("WINMM: WaveOut::queryFormat: %s\n", szError));
+        #endif
+        return FALSE;
+    }
+
+    // See if the device can handle the specified format.
+    memset(&DevCapsParms, 0, sizeof(MCI_WAVE_GETDEVCAPS_PARMS));
+    DevCapsParms.ulBitsPerSample = wBitsPerSample;
+    DevCapsParms.ulFormatTag     = DATATYPE_WAVEFORM;
+    DevCapsParms.ulSamplesPerSec = nSamplesPerSec;
+    DevCapsParms.ulChannels      = nChannels;
+    DevCapsParms.ulFormatMode    = MCI_PLAY;
+    DevCapsParms.ulItem          = MCI_GETDEVCAPS_WAVE_FORMAT;
+
+    rc = mymciSendCommand(OpenParms.usDeviceID, MCI_GETDEVCAPS,
+                          MCI_WAIT | MCI_GETDEVCAPS_EXTENDED | MCI_GETDEVCAPS_ITEM,
+                          (PVOID)&DevCapsParms, 0);
+    if (LOUSHORT(rc) != MCIERR_SUCCESS) {
+        #ifdef DEBUG
+        mymciGetErrorString(rc, szError, sizeof(szError));
+        dprintf(("WINMM: WaveOut::queryFormat: %s\n", szError));
+        #endif
+        winrc = FALSE;
+    }
+
+    // Close the device
+    rc = mymciSendCommand(OpenParms.usDeviceID, MCI_CLOSE,
+                          MCI_WAIT, (PVOID)&GenericParms, 0);
+    if (LOUSHORT(rc) != MCIERR_SUCCESS) {
+        #ifdef DEBUG
+        mymciGetErrorString(rc, szError, sizeof(szError));
+        dprintf(("WINMM: WaveOut::queryFormat: %s\n", szError));
+        #endif
+        winrc = FALSE;
+    }
+
+    return winrc;
+}
+/******************************************************************************/
+// Called if waveOutSetVolume is called by the application with waveout handle NULL
+// Sets the default volume of each waveout stream (until it's volume is changed
+// with an appropriate waveOutSetVolume call)
 /******************************************************************************/
 void WaveOut::setDefaultVolume(ULONG volume)
@@ -112,4 +163,3 @@
 /******************************************************************************/
 /******************************************************************************/
-ULONG WaveOut::defvolume = 0xFFFFFFFF;
 
Index: trunk/src/winmm/waveoutbase.h
===================================================================
--- trunk/src/winmm/waveoutbase.h	(revision 21357)
+++ trunk/src/winmm/waveoutbase.h	(revision 21358)
@@ -8,9 +8,9 @@
  * Project Odin Software License can be found in LICENSE.TXT
  */
+
 #ifndef __DWAVEOUTBASE_H__
 #define __DWAVEOUTBASE_H__
 
 #include "waveinoutbase.h"
-
 #ifdef OS2_ONLY
 #include "winmmtype.h"
@@ -21,30 +21,27 @@
 {
 public:
-              WaveOut(LPWAVEFORMATEX pwfx, DWORD fdwOpen, ULONG nCallback, ULONG dwInstance);
-     virtual ~WaveOut();
+          WaveOut(LPWAVEFORMATEX pwfx, DWORD fdwOpen, ULONG nCallback, ULONG dwInstance);
+  virtual ~WaveOut();
 
-     virtual  MMRESULT write(LPWAVEHDR pwh, UINT cbwh) = 0;
-     virtual  MMRESULT pause() = 0;
-     virtual  MMRESULT stop() = 0;
-     virtual  MMRESULT resume() = 0;
-     virtual  MMRESULT reset() = 0;
-     virtual  ULONG    getPosition() = 0;
-     virtual  MMRESULT setVolume(ULONG ulVol) = 0;
-              ULONG    getVolume()              { return volume; };
+  virtual MMRESULT  open() = 0;
+  virtual MMRESULT  write(LPWAVEHDR pwh, UINT cbwh) = 0;
+  virtual MMRESULT  pause() = 0;
+  virtual MMRESULT  stop() = 0;
+  virtual MMRESULT  resume() = 0;
+  virtual MMRESULT  reset() = 0;
+  virtual ULONG     getPosition() = 0;
+  virtual MMRESULT  setVolume(ULONG ulVol) = 0;
 
-  static int  getNumDevices();
-
-  static void setDefaultVolume(ULONG volume);
- static DWORD getDefaultVolume();
+   static int       getNumDevices();
+   static BOOL      queryFormat(ULONG formatTag, ULONG nChannels,
+                                ULONG nSamplesPerSec, ULONG sampleSize);
+   static void      setDefaultVolume(ULONG volume);
+   static DWORD     getDefaultVolume();
+          ULONG     getVolume() { return volume; };
 
 protected:
-
-    ULONG       bytesPlayed, bytesCopied, bytesReturned;
-    ULONG       volume;                        // Volume state
-
-    static      ULONG    defvolume;  //default volume for streams (if waveOutSetVolume called with NULL stream)
-
-private:
-
+          ULONG     volume;
+   static ULONG     defvolume;  // default volume for streams
+                                // (if waveOutSetVolume called with NULL stream)
 };
 
Index: trunk/src/winmm/waveoutdart.cpp
===================================================================
--- trunk/src/winmm/waveoutdart.cpp	(revision 21357)
+++ trunk/src/winmm/waveoutdart.cpp	(revision 21358)
@@ -15,10 +15,7 @@
  */
 
-
-/****************************************************************************
- * Includes                                                                 *
- ****************************************************************************/
-
-
+/******************************************************************************/
+// Includes
+/******************************************************************************/
 
 #define  INCL_BASE
@@ -41,4 +38,6 @@
 #include "dbglocal.h"
 
+/******************************************************************************/
+
 #ifndef min
 #define min(a, b) ((a > b) ? b : a)
@@ -51,5 +50,8 @@
 LONG APIENTRY WaveOutHandler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags);
 
-static BOOL fFixedWaveBufferSize = FALSE;
+#define DART_BUFCNT     64
+#define DART_BUFSIZE    4096
+
+/******************************************************************************/
 
 //#define DEBUG_DUMP_PCM
@@ -67,5 +69,9 @@
 #endif
 
-//******************************************************************************
+/******************************************************************************/
+
+static BOOL fFixedWaveBufferSize = FALSE;
+
+/******************************************************************************/
 // ODIN_waveOutSetFixedBuffers
 //
@@ -76,302 +82,302 @@
 //       purpose solution.
 // 
-//******************************************************************************
+/******************************************************************************/
+
 void WIN32API ODIN_waveOutSetFixedBuffers()
 {
     fFixedWaveBufferSize = TRUE;
 }
-/******************************************************************************/
-/******************************************************************************/
+
+/******************************************************************************/
+/******************************************************************************/
+
 DartWaveOut::DartWaveOut(LPWAVEFORMATEX pwfx, ULONG fdwOpen, ULONG nCallback, ULONG dwInstance)
                   : WaveOut(pwfx, fdwOpen, nCallback, dwInstance)
 {
-    MCI_GENERIC_PARMS  GenericParms;
+    DeviceId        = 0;
+    fMixerSetup     = FALSE;
+    fUnderrun       = FALSE;
+    curFillBuf      = 0;
+    curPlayBuf      = 0;
+    curFillPos      = 0;
+    curPlayPos      = 0;
+    ulBufSize       = DART_BUFSIZE;
+    ulBufCount      = DART_BUFCNT;
+    bytesPlayed     = 0;
+    bytesCopied     = 0;
+    bytesReturned   = 0;
+    ulUnderrunBase  = 0;
+    mixHandle       = 0;
+    curhdr          = NULL;
+    pmixWriteProc   = 0;
+    MixBuffer       = 0;
+    BufferParms     = 0;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
+DartWaveOut::~DartWaveOut()
+{
+    MCI_GENERIC_PARMS GenericParms = {0};
+
+    State = STATE_STOPPED;
+
+#ifdef DEBUG_DUMP_PCM
+    if (pcmfile) fclose(pcmfile);
+#endif
+
+    if (DeviceId) {
+        // Stop the playback.
+        mymciSendCommand(DeviceId, MCI_STOP,
+                         MCI_WAIT,
+                         (PVOID)&GenericParms,0);
+
+        if (fMixerSetup)
+            mymciSendCommand(DeviceId, MCI_BUFFER,
+                             MCI_WAIT | MCI_DEALLOCATE_MEMORY,
+                             (PVOID)&BufferParms, 0);
+
+        // Close the device
+        mymciSendCommand(DeviceId, MCI_CLOSE,
+                         MCI_WAIT,
+                         (PVOID)&GenericParms, 0);
+
+        callback(WOM_CLOSE, 0, 0);
+    }
+
+    if (MixBuffer)
+        free(MixBuffer);
+    if (BufferParms)
+        free(BufferParms);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
+MMRESULT DartWaveOut::open()
+{
     MCI_AMP_OPEN_PARMS AmpOpenParms;
+    MCI_GENERIC_PARMS  GenericParms = {0};
+    MCI_MIXSETUP_PARMS MixSetupParms;
     APIRET rc;
 
-    curPlayBuf = curFillBuf = curFillPos = curPlayPos = 0;
-    fMixerSetup   = FALSE;
-    fUnderrun     = FALSE;
-    ulUnderrunBase= 0;
-
-    ulBufSize     = DART_BUFSIZE;
-
-    MixBuffer     = (MCI_MIX_BUFFER *)malloc(PREFILLBUF_DART*sizeof(MCI_MIX_BUFFER));
-    MixSetupParms = (MCI_MIXSETUP_PARMS *)malloc(sizeof(MCI_MIXSETUP_PARMS));
+    MixBuffer     = (MCI_MIX_BUFFER *)malloc(ulBufCount*sizeof(MCI_MIX_BUFFER));
     BufferParms   = (MCI_BUFFER_PARMS *)malloc(sizeof(MCI_BUFFER_PARMS));
-    if(!MixBuffer || !MixSetupParms || !BufferParms) {
+    if (!MixBuffer || !BufferParms) {
         dprintf(("ERROR: malloc failed!!"));
-        ulError = MMSYSERR_NOMEM;
-        return;
-    }
-
-    // Setup the open structure, pass the playlist and tell MCI_OPEN to use it
-    memset(&AmpOpenParms,0,sizeof(AmpOpenParms));
-
-    AmpOpenParms.usDeviceID = ( USHORT ) 0;
-    AmpOpenParms.pszDeviceType = ( PSZ ) MCI_DEVTYPE_AUDIO_AMPMIX;
-
-    rc = mymciSendCommand(0, MCI_OPEN, MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
-                       (PVOID) &AmpOpenParms, 0);
-
-    DeviceId = AmpOpenParms.usDeviceID;
-    if(rc) {
+        return MMSYSERR_NOMEM;
+    }
+
+    // Setup the open structure, then open the device
+    memset(&AmpOpenParms, 0, sizeof(AmpOpenParms));
+    AmpOpenParms.usDeviceID = 0;
+    AmpOpenParms.pszDeviceType = (PSZ)MCI_DEVTYPE_AUDIO_AMPMIX;
+
+    rc = mymciSendCommand(0, MCI_OPEN,
+                          MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
+                          (PVOID)&AmpOpenParms, 0);
+    if (LOUSHORT(rc) != MCIERR_SUCCESS) {
         dprintf(("MCI_OPEN failed\n"));
         mciError(rc);
-        ulError = MMSYSERR_NODRIVER;
-    }
-    if(rc == 0) {
-        //Grab exclusive rights to device instance (NOT entire device)
-        GenericParms.hwndCallback = 0;  //Not needed, so set to 0
-        rc = mymciSendCommand(DeviceId, MCI_ACQUIREDEVICE, MCI_EXCLUSIVE_INSTANCE,
-                            (PVOID)&GenericParms, 0);
-        if(rc) {
-            dprintf(("MCI_ACQUIREDEVICE failed\n"));
-            mciError(rc);
-            ulError = MMSYSERR_NOTENABLED;
+        return MMSYSERR_NODRIVER;
+    }
+    DeviceId = AmpOpenParms.usDeviceID;
+
+    // Grab exclusive rights to device instance (NOT entire device)
+    rc = mymciSendCommand(DeviceId, MCI_ACQUIREDEVICE,
+                          MCI_EXCLUSIVE_INSTANCE,
+                          (PVOID)&GenericParms, 0);
+    if (LOUSHORT(rc) != MCIERR_SUCCESS) {
+        dprintf(("MCI_ACQUIREDEVICE failed\n"));
+        mciError(rc);
+        return MMSYSERR_NOTENABLED;
+    }
+    dprintf(("device acquired\n"));
+    dprintf(("bps %d, sps %d chan %d\n", BitsPerSample, SampleRate, nChannels));
+
+    // Setup the mixer for playback of wave data
+    memset(&MixSetupParms, 0, sizeof(MixSetupParms));
+    MixSetupParms.ulBitsPerSample = BitsPerSample;
+    MixSetupParms.ulSamplesPerSec = SampleRate;
+    MixSetupParms.ulFormatTag     = MCI_WAVE_FORMAT_PCM;
+    MixSetupParms.ulChannels      = nChannels;
+    MixSetupParms.ulFormatMode    = MCI_PLAY;
+    MixSetupParms.ulDeviceType    = MCI_DEVTYPE_WAVEFORM_AUDIO;
+    MixSetupParms.pmixEvent       = WaveOutHandler;
+
+    rc = mymciSendCommand(DeviceId, MCI_MIXSETUP,
+                          MCI_WAIT | MCI_MIXSETUP_INIT,
+                          (PVOID)&MixSetupParms, 0);
+
+    if (LOUSHORT(rc) != MCIERR_SUCCESS) {
+        mciError(rc);
+        mymciSendCommand(DeviceId, MCI_RELEASEDEVICE,
+                         MCI_WAIT,
+                         (PVOID)&GenericParms, 0);
+        return MMSYSERR_NOTSUPPORTED;
+    }
+
+    // Save the mixer handle & the ptr to the write proc.
+    mixHandle     = MixSetupParms.ulMixHandle;
+    pmixWriteProc = MixSetupParms.pmixWrite;
+
+#ifdef DEBUG_DUMP_PCM
+    REC_STRUCT recinfo;
+
+    pcmfile = fopen("dartpcm.dat", "wb");
+    recinfo.bits = BitsPerSample;
+    recinfo.rate = SampleRate;
+    recinfo.format = MCI_WAVE_FORMAT_PCM;
+    recinfo.numchan = nChannels;
+    fwrite(&recinfo, sizeof(recinfo), 1, pcmfile);
+#endif
+
+    setVolume(volume);
+    callback(WOM_OPEN, 0, 0);
+
+    return MMSYSERR_NOERROR;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
+MMRESULT DartWaveOut::write(LPWAVEHDR pwh, UINT cbwh)
+{
+    APIRET rc;
+
+    queuedbuffers++;
+    pwh->lpNext = NULL;
+    pwh->reserved = 0;
+
+    // Set up the BufferParms data structure and allocate
+    // device buffers from the Amp-Mixer
+    if (fMixerSetup == FALSE)
+    {
+        ulBufSize = pwh->dwBufferLength;
+        if (!ulBufSize || ulBufSize > 0x10000)
+            return MMSYSERR_INVALPARAM;
+
+        rc = initBuffers();
+        if (rc != MMSYSERR_NOERROR)
+            return rc;
+
+        curhdr = pwh;
+        fMixerSetup = TRUE;
+    }
+
+    wmutex.enter();
+
+    if (wavehdr) {
+        WAVEHDR *chdr = wavehdr;
+        while (chdr->lpNext) {
+#ifdef DEBUG
+            if (chdr == pwh) dprintf(("adding already present buffer!!!!!"));
+#endif
+            chdr = chdr->lpNext;
         }
-    }
-    setVolume(volume);
-
-    if(!ulError)
-        callback(WOM_OPEN, 0, 0);
-}
-/******************************************************************************/
-/******************************************************************************/
-DartWaveOut::~DartWaveOut()
-{
-    MCI_GENERIC_PARMS GenericParms;
-
-    State = STATE_STOPPED;
-
-#ifdef DEBUG_DUMP_PCM
-    if(pcmfile) fclose(pcmfile);
-#endif
-
-    if(!ulError) {
-        // Generic parameters
-        GenericParms.hwndCallback = 0;   //hwndFrame
-
-        // Stop the playback.
-        mymciSendCommand(DeviceId, MCI_STOP,MCI_WAIT, (PVOID)&GenericParms,0);
-
-        mymciSendCommand(DeviceId, MCI_BUFFER,
-                       MCI_WAIT | MCI_DEALLOCATE_MEMORY,
-                       (PVOID)&BufferParms, 0);
-
-        // Generic parameters
-        GenericParms.hwndCallback = 0;   //hwndFrame
-
-        // Close the device
-        mymciSendCommand(DeviceId, MCI_CLOSE, MCI_WAIT, (PVOID)&GenericParms, 0);
-    }
-
-    if(!ulError)
+        chdr->lpNext = pwh;
+    }
+    else wavehdr = pwh;
+
+    //don't start playback if paused
+    if (!fUnderrun && State != STATE_STOPPED) {
+       	//write new data to the DART buffers (if there's any room left)
+        if (State == STATE_PLAYING)
+            writeBuffer();  //must be called before (re)starting playback
+        wmutex.leave();
+        return MMSYSERR_NOERROR;
+    }
+
+    writeBuffer();  //must be called before (re)starting playback
+    State     = STATE_PLAYING;
+    fUnderrun = FALSE;
+    wmutex.leave();
+
+    //write buffers to DART; starts playback
+    dprintf(("WINMM: transfer all buffers to DART"));
+
+    USHORT selTIB = RestoreOS2FS(); // save current FS selector
+    pmixWriteProc(mixHandle, MixBuffer, ulBufCount);
+    SetFS(selTIB);           // switch back to the saved FS selector
+
+    dprintf(("Dart playing\n"));
+
+    return MMSYSERR_NOERROR;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
+MMRESULT DartWaveOut::initBuffers()
+{
+    APIRET rc;
+    MCI_GENERIC_PARMS  GenericParms = {0};
+    int orgbufsize = ulBufSize;  // on entry, ulBufSize == pwh->dwBufferLength
+
+#if 1
+    //by default we need to select a small enough buffer
+    //to be able to signal buffer completion in time 
+    if (fFixedWaveBufferSize == FALSE) 
     {
-        callback(WOM_CLOSE, 0, 0);
-    }
-
-    if(MixBuffer)
-        free(MixBuffer);
-    if(MixSetupParms)
-        free(MixSetupParms);
-    if(BufferParms)
-        free(BufferParms);
-}
-/******************************************************************************/
-/******************************************************************************/
-MMRESULT DartWaveOut::write(LPWAVEHDR pwh, UINT cbwh)
-{
-    MCI_GENERIC_PARMS GenericParms = {0};
-    APIRET rc;
-    int i, buflength;
-
-    queuedbuffers++;
-    if(fMixerSetup == FALSE)
-    {
-        dprintf(("device acquired\n"));
-        /* Set the MixSetupParms data structure to match the loaded file.
-         * This is a global that is used to setup the mixer.
-         */
-        memset(MixSetupParms, 0, sizeof( MCI_MIXSETUP_PARMS ) );
-
-        MixSetupParms->ulBitsPerSample = BitsPerSample;
-        MixSetupParms->ulSamplesPerSec = SampleRate;
-        MixSetupParms->ulFormatTag     = MCI_WAVE_FORMAT_PCM;
-        MixSetupParms->ulChannels      = nChannels;
-
-        dprintf(("bps %d, sps %d chan %d\n", BitsPerSample, SampleRate, nChannels));
-
-#ifdef DEBUG_DUMP_PCM
-        REC_STRUCT recinfo;
-
-        pcmfile = fopen("dartpcm.dat", "wb");
-        recinfo.bits = BitsPerSample;
-        recinfo.rate = SampleRate;
-        recinfo.format = MCI_WAVE_FORMAT_PCM;
-        recinfo.numchan = nChannels;
-        fwrite(&recinfo, sizeof(recinfo), 1, pcmfile);
-#endif
-        /* Setup the mixer for playback of wave data
-         */
-        MixSetupParms->ulFormatMode = MCI_PLAY;
-        MixSetupParms->ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
-        MixSetupParms->pmixEvent    = WaveOutHandler;
-
-        rc = mymciSendCommand(DeviceId,
-                            MCI_MIXSETUP,
-                            MCI_WAIT | MCI_MIXSETUP_INIT,
-                            (PVOID)MixSetupParms,
-                            0);
-
-        if ( rc != MCIERR_SUCCESS ) {
-            mciError(rc);
-            mymciSendCommand(DeviceId, MCI_RELEASEDEVICE, MCI_WAIT,
-                           (PVOID)&GenericParms, 0);
-            return(MMSYSERR_NOTSUPPORTED);
+        int consumerate = getAvgBytesPerSecond();
+        int minbufsize = consumerate/32;
+
+        ulBufSize /= 2;
+        if (ulBufSize > minbufsize) {
+            dprintf(("set buffer size to %d bytes (org size = %d)", minbufsize, orgbufsize));
+            ulBufSize = minbufsize;
         }
-
-        /*
-         * Set up the BufferParms data structure and allocate
-         * device buffers from the Amp-Mixer
-         */
-        dprintf(("mix setup %d, %d\n", pwh->dwBufferLength, pwh->dwBufferLength));
-
-#if 1
-        if(fFixedWaveBufferSize == FALSE) 
-        {//by default we need to select a small enough buffer to be able to
-         //signal buffer completion in time 
-            int consumerate = getAvgBytesPerSecond();
-            int minbufsize = consumerate/32;
-
-            ulBufSize = pwh->dwBufferLength/2;
-            if(ulBufSize > minbufsize) {
-                dprintf(("set buffer size to %d bytes (org size = %d)", minbufsize, pwh->dwBufferLength));
-                ulBufSize = minbufsize;
-            }
-        }
-        else ulBufSize = pwh->dwBufferLength;
+    }
 #else
-        if(pwh->dwBufferLength >= 512 && pwh->dwBufferLength <= 1024)
-                ulBufSize = pwh->dwBufferLength;
-        else    ulBufSize = 1024;
-#endif
-        MixSetupParms->ulBufferSize = ulBufSize;
-
-        BufferParms->ulNumBuffers = PREFILLBUF_DART;
-        BufferParms->ulBufferSize = MixSetupParms->ulBufferSize;
-        BufferParms->pBufList     = MixBuffer;
-
-        for(i=0;i<PREFILLBUF_DART;i++) {
-            MixBuffer[i].ulUserParm = (ULONG)this;
-        }
-
-        rc = mymciSendCommand(DeviceId,
-                            MCI_BUFFER,
-                            MCI_WAIT | MCI_ALLOCATE_MEMORY,
-                            (PVOID)BufferParms,
-                            0);
-
-        if(ULONG_LOWD(rc) != MCIERR_SUCCESS) {
-            mciError(rc);
-            mymciSendCommand(DeviceId, MCI_RELEASEDEVICE, MCI_WAIT,
-                          (PVOID)&GenericParms, 0);
-            return(MMSYSERR_NOTSUPPORTED);
-        }
-
-        wmutex.enter();
-        fMixerSetup = TRUE;
-
-        curPlayBuf = curFillBuf = curFillPos = curPlayPos = 0;
-        bytesPlayed = bytesCopied = bytesReturned = 0;
-
-        for(i=0;i<PREFILLBUF_DART;i++) {
-            memset(MixBuffer[i].pBuffer, 0, MixBuffer[i].ulBufferLength);
-        }
-        dprintf(("Dart opened, bufsize = %d\n", MixBuffer[0].ulBufferLength));
-
-        wavehdr     = pwh;
-        curhdr      = pwh;
-        pwh->lpNext = NULL;
-        pwh->reserved = 0;
-
-        if(State != STATE_STOPPED) {//don't start playback if paused
-            wmutex.leave();
-            return(MMSYSERR_NOERROR);
-        }
-
-        writeBuffer();  //must be called before (re)starting playback
-
-        dprintf(("MixSetupParms = %X\n", MixSetupParms));
-        State     = STATE_PLAYING;
-        fUnderrun = FALSE;
-        wmutex.leave();
-
-        //write buffers to DART; starts playback
-        dprintf(("WINMM: transfer all buffers to DART"));
-        USHORT selTIB = RestoreOS2FS(); // save current FS selector
-
-        MixSetupParms->pmixWrite(MixSetupParms->ulMixHandle,
-                                 MixBuffer,
-                                 PREFILLBUF_DART);
-        SetFS(selTIB);           // switch back to the saved FS selector
-        dprintf(("Dart playing\n"));
-    }
-    else
-    {
-        pwh->lpNext   = NULL;
-        pwh->reserved = 0;
-        wmutex.enter();
-        if(wavehdr) {
-            WAVEHDR *chdr = wavehdr;
-            while(chdr->lpNext) {
-#ifdef DEBUG
-                if(chdr == pwh) dprintf(("adding already present buffer!!!!!"));
-#endif
-                chdr = chdr->lpNext;
-            }
-            chdr->lpNext = pwh;
-        }
-        else wavehdr = pwh;
-
-        if(!fUnderrun && State != STATE_STOPPED) {//don't start playback if paused
-   	    //write new data to the DART buffers (if there's any room left)
-            if(State == STATE_PLAYING) {
-                writeBuffer();  //must be called before (re)starting playback
-            }
-            wmutex.leave();
-            return(MMSYSERR_NOERROR);
-        }
-        writeBuffer();  //must be called before (re)starting playback
-        State     = STATE_PLAYING;
-        fUnderrun = FALSE;
-        wmutex.leave();
-
-        //write buffers to DART; starts playback
-        dprintf(("WINMM: transfer all buffers to DART"));
-        USHORT selTIB = RestoreOS2FS(); // save current FS selector
-
-        MixSetupParms->pmixWrite(MixSetupParms->ulMixHandle,
-                                 MixBuffer,
-                                 PREFILLBUF_DART);
-        SetFS(selTIB);           // switch back to the saved FS selector
-
-        dprintf(("Dart playing\n"));
-    }
-    return(MMSYSERR_NOERROR);
-}
-/******************************************************************************/
-/******************************************************************************/
+    if (ulBufSize < 512 || ulBufSize > 1024)
+        ulBufSize = 1024;
+#endif
+
+    dprintf(("buffer setup - WAVE size = %d, DART size = %d\n",
+             orgbufsize, ulBufSize));
+
+    BufferParms->ulNumBuffers = ulBufCount;
+    BufferParms->ulBufferSize = ulBufSize;
+    BufferParms->pBufList     = MixBuffer;
+
+    rc = mymciSendCommand(DeviceId, MCI_BUFFER,
+                        MCI_WAIT | MCI_ALLOCATE_MEMORY,
+                        (PVOID)BufferParms, 0);
+
+    if (LOUSHORT(rc) != MCIERR_SUCCESS) {
+        mciError(rc);
+        mymciSendCommand(DeviceId, MCI_RELEASEDEVICE,
+                         MCI_WAIT,
+                         (PVOID)&GenericParms, 0);
+        return MMSYSERR_NOTSUPPORTED;
+    }
+
+    // DART may not have allocated all the buffers requested.
+    ulBufCount = BufferParms->ulNumBuffers;
+
+    for (int i = 0; i < ulBufCount; i++) {
+        MixBuffer[i].ulUserParm = (ULONG)this;
+        memset(MixBuffer[i].pBuffer, 0, MixBuffer[i].ulBufferLength);
+    }
+    dprintf(("Dart opened, bufsize = %d\n", MixBuffer[0].ulBufferLength));
+
+    return MMSYSERR_NOERROR;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
 MMRESULT DartWaveOut::pause()
 {
-    MCI_GENERIC_PARMS Params;
+    MCI_GENERIC_PARMS  GenericParms = {0};
 
     dprintf(("WINMM: DartWaveOut::pause"));
 
     wmutex.enter();
-    if(State != STATE_PLAYING) {
+    if (State != STATE_PLAYING) {
         State = STATE_PAUSED;
         wmutex.leave();
-        return(MMSYSERR_NOERROR);
+        return MMSYSERR_NOERROR;
     }
 
@@ -379,16 +385,17 @@
     wmutex.leave();
 
-    memset(&Params, 0, sizeof(Params));
-
     // Pause playback.
-    mymciSendCommand(DeviceId, MCI_PAUSE, MCI_WAIT, (PVOID)&Params, 0);
-
-    return(MMSYSERR_NOERROR);
-}
-/******************************************************************************/
-/******************************************************************************/
+    mymciSendCommand(DeviceId, MCI_PAUSE,
+                     MCI_WAIT,
+                     (PVOID)&GenericParms, 0);
+
+    return MMSYSERR_NOERROR;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
 MMRESULT DartWaveOut::resume()
 {
-    MCI_GENERIC_PARMS Params;
     int i, curbuf;
 
@@ -396,7 +403,7 @@
     
     wmutex.enter();
-    if(State != STATE_PAUSED) {
+    if (State != STATE_PAUSED) {
         wmutex.leave();
-        return(MMSYSERR_NOERROR);
+        return MMSYSERR_NOERROR;
     }
     State = STATE_PLAYING;
@@ -405,41 +412,41 @@
     //Only write buffers to dart if mixer has been initialized; if not, then
     //the first buffer write will do this for us.
-    if(fMixerSetup == TRUE)
+    if (fMixerSetup == TRUE)
     {
         wmutex.enter();
         State     = STATE_PLAYING;
         fUnderrun = FALSE;
-        curbuf = curPlayBuf;
+        curbuf    = curPlayBuf;
         writeBuffer();  //must be called before (re)starting playback
         wmutex.leave();
 
-        // MCI_MIXSETUP_PARMS->pMixWrite does alter FS: selector!
         USHORT selTIB = GetFS(); // save current FS selector
-
-        for(i=0;i<PREFILLBUF_DART;i++)
+        for (i = 0; i < ulBufCount; i++)
         {
             dprintf(("restart: write buffer at %x size %d", MixBuffer[curbuf].pBuffer, MixBuffer[curbuf].ulBufferLength));
-            MixSetupParms->pmixWrite(MixSetupParms->ulMixHandle, &MixBuffer[curbuf], 1);
-            if(++curbuf == PREFILLBUF_DART)
+            pmixWriteProc(mixHandle, &MixBuffer[curbuf], 1);
+            if (++curbuf == ulBufCount)
                 curbuf = 0;
         }
         SetFS(selTIB);           // switch back to the saved FS selector
     }
-    return(MMSYSERR_NOERROR);
-}
-/******************************************************************************/
-/******************************************************************************/
+    return MMSYSERR_NOERROR;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
 MMRESULT DartWaveOut::stop()
 {
-    MCI_GENERIC_PARMS Params;
+    MCI_GENERIC_PARMS  GenericParms = {0};
 
     dprintf(("DartWaveOut::stop %s", (State == STATE_PLAYING) ? "playing" : "stopped"));
-    if(State != STATE_PLAYING)
-        return(MMSYSERR_HANDLEBUSY);
-
-    memset(&Params, 0, sizeof(Params));
+    if (State != STATE_PLAYING)
+        return MMSYSERR_HANDLEBUSY;
 
     // Stop the playback.
-    mymciSendCommand(DeviceId, MCI_STOP, MCI_WAIT, (PVOID)&Params, 0);
+    mymciSendCommand(DeviceId, MCI_STOP,
+                     MCI_WAIT,
+                     (PVOID)&GenericParms, 0);
 
     State     = STATE_STOPPED;
@@ -449,18 +456,18 @@
     bytesPlayed = bytesCopied = bytesReturned = 0;
 
-    return(MMSYSERR_NOERROR);
-}
-/******************************************************************************/
-/******************************************************************************/
+    return MMSYSERR_NOERROR;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
 MMRESULT DartWaveOut::reset()
 {
-    MCI_GENERIC_PARMS Params;
+    MCI_GENERIC_PARMS  GenericParms = {0};
     LPWAVEHDR tmpwavehdr;
 
     dprintf(("DartWaveOut::reset %s", (State == STATE_PLAYING) ? "playing" : "stopped"));
-    if(State != STATE_PLAYING)
-        return(MMSYSERR_HANDLEBUSY);
-
-    memset(&Params, 0, sizeof(Params));
+    if (State != STATE_PLAYING)
+        return MMSYSERR_HANDLEBUSY;
 
     wmutex.enter();
@@ -469,8 +476,10 @@
 
     // Stop the playback.
-    mymciSendCommand(DeviceId, MCI_STOP, MCI_WAIT, (PVOID)&Params, 0);
+    mymciSendCommand(DeviceId, MCI_STOP,
+                     MCI_WAIT,
+                     (PVOID)&GenericParms, 0);
 
     wmutex.enter();
-    while(wavehdr)
+    while (wavehdr)
     {
         wavehdr->dwFlags  |= WHDR_DONE;
@@ -494,105 +503,99 @@
 
     wmutex.leave();
-    return(MMSYSERR_NOERROR);
-}
-/******************************************************************************/
-/******************************************************************************/
+    return MMSYSERR_NOERROR;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
 ULONG DartWaveOut::getPosition()
 {
- MCI_STATUS_PARMS mciStatus = {0};
- ULONG rc, nrbytes;
-
-    if(State == STATE_STOPPED) {
+    MCI_STATUS_PARMS StatusParms = {0};
+    ULONG rc, nrbytes;
+
+    if (State == STATE_STOPPED) {
         dprintf(("Not playing; return 0 position"));
         return ulUnderrunBase;
     }
 
-    mciStatus.ulItem = MCI_STATUS_POSITION;
-    rc = mymciSendCommand(DeviceId, MCI_STATUS, MCI_STATUS_ITEM|MCI_WAIT, (PVOID)&mciStatus, 0);
-    if((rc & 0xFFFF) == MCIERR_SUCCESS) {
-        nrbytes = (ULONG)(((double)mciStatus.ulReturn * (double)getAvgBytesPerSecond())/1000.0);
-        return ulUnderrunBase+nrbytes;
-    }
-    mciError(rc);
-    return 0xFFFFFFFF;
-}
-/******************************************************************************/
-/******************************************************************************/
-BOOL DartWaveOut::queryFormat(ULONG formatTag, ULONG nChannels,
-                              ULONG nSamplesPerSec, ULONG wBitsPerSample)
-{
- MCI_WAVE_GETDEVCAPS_PARMS mciAudioCaps;
- MCI_GENERIC_PARMS    GenericParms;
- MCI_OPEN_PARMS       mciOpenParms;         /* open parms for MCI_OPEN             */
- int i, freqbits = 0;
- ULONG rc, DeviceId;
- BOOL winrc;
-
-    dprintf(("DartWaveOut::queryFormat %x srate=%d, nchan=%d, bps=%d", formatTag, nSamplesPerSec, nChannels, wBitsPerSample));
-
-    memset(&mciOpenParms,            /* Object to fill with zeros.       */
-           0,                        /* Value to place into the object.  */
-           sizeof( mciOpenParms ) ); /* How many zero's to use.          */
-
-    mciOpenParms.pszDeviceType = (PSZ)MCI_DEVTYPE_WAVEFORM_AUDIO;
-
-    rc = mymciSendCommand( (USHORT) 0,
-                        MCI_OPEN,
-                        MCI_WAIT | MCI_OPEN_TYPE_ID,
-                        (PVOID) &mciOpenParms,
-                        0);
-    if((rc & 0xFFFF) != MCIERR_SUCCESS) {
+    StatusParms.ulItem = MCI_STATUS_POSITION;
+    rc = mymciSendCommand(DeviceId, MCI_STATUS,
+                          MCI_STATUS_ITEM|MCI_WAIT,
+                          (PVOID)&StatusParms, 0);
+    if (LOUSHORT(rc) != MCIERR_SUCCESS) {
         mciError(rc);
-        return(FALSE);
-    }
-    DeviceId = mciOpenParms.usDeviceID;
-
-    memset( &mciAudioCaps , 0, sizeof(MCI_WAVE_GETDEVCAPS_PARMS));
-
-    mciAudioCaps.ulBitsPerSample = wBitsPerSample;
-    mciAudioCaps.ulFormatTag     = DATATYPE_WAVEFORM;
-    mciAudioCaps.ulSamplesPerSec = nSamplesPerSec;
-    mciAudioCaps.ulChannels      = nChannels;
-    mciAudioCaps.ulFormatMode    = MCI_PLAY;
-    mciAudioCaps.ulItem          = MCI_GETDEVCAPS_WAVE_FORMAT;
-
-    rc = mymciSendCommand(DeviceId,   /* Device ID    */
-                        MCI_GETDEVCAPS,
-                        MCI_WAIT | MCI_GETDEVCAPS_EXTENDED | MCI_GETDEVCAPS_ITEM,
-                        (PVOID) &mciAudioCaps,
-                        0);
-    if((rc & 0xFFFF) != MCIERR_SUCCESS) {
+        return 0xFFFFFFFF;
+    }
+
+    nrbytes = (ULONG)(((double)StatusParms.ulReturn * (double)getAvgBytesPerSecond())/1000.0);
+    return (ulUnderrunBase + nrbytes);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
+MMRESULT DartWaveOut::setVolume(ULONG ulVol)
+{
+    APIRET  rc;
+    ULONG   ulVolR   = ((ulVol >> 16)    * 100) / 0xFFFF;
+    ULONG   ulVolL   = ((ulVol & 0xffff) * 100) / 0xFFFF;
+    MCI_SET_PARMS SetParms = {0};
+
+    dprintf(("DartWaveOut::setVolume %d %d", ulVolL, ulVolR));
+    volume = ulVol;
+
+// Some drivers can't set left & right volumes independently
+#ifdef GOOD_AUDIO_CARD_DRIVER
+    SetParms.ulAudio = MCI_SET_AUDIO_LEFT;
+    SetParms.ulLevel = ulVolL;
+
+    rc = mymciSendCommand(DeviceId, MCI_SET,
+                          MCI_WAIT | MCI_SET_AUDIO | MCI_SET_VOLUME,
+                          &SetParms, 0);
+    if (LOUSHORT(rc) != MCIERR_SUCCESS)
         mciError(rc);
-        winrc = FALSE;
-    }
-    else  winrc = TRUE;
-
-    // Close the device
-    mymciSendCommand(DeviceId,MCI_CLOSE,MCI_WAIT,(PVOID)&GenericParms,0);
-    return(winrc);
-}
-/******************************************************************************/
-/******************************************************************************/
-void DartWaveOut::mciError(ULONG ulError)
+
+    SetParms.ulAudio = MCI_SET_AUDIO_RIGHT;
+    SetParms.ulLevel = ulVolR;
+#else
+    SetParms.ulAudio = MCI_SET_AUDIO_ALL;
+    SetParms.ulLevel = (ulVolR + ulVolL) / 2;
+#endif
+
+    rc = mymciSendCommand(DeviceId, MCI_SET,
+                          MCI_WAIT | MCI_SET_AUDIO | MCI_SET_VOLUME,
+                          &SetParms, 0);
+    if (LOUSHORT(rc) != MCIERR_SUCCESS)
+        mciError(rc);
+
+    return MMSYSERR_NOERROR;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
+void DartWaveOut::mciError(ULONG rc)
 {
 #ifdef DEBUG
     char szError[256] = "";
 
-    mymciGetErrorString(ulError, szError, sizeof(szError));
+    mymciGetErrorString(rc, szError, sizeof(szError));
     dprintf(("WINMM: DartWaveOut: %s\n", szError));
 #endif
 }
+
 //******************************************************************************
 //******************************************************************************
+
 void DartWaveOut::handler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags)
 {
- ULONG    buflength;
- WAVEHDR *whdr, *prevhdr = NULL;
+    ULONG    buflength;
+    WAVEHDR *whdr, *prevhdr = NULL;
 
     dprintf2(("WINMM: handler %d; buffers left %d", curPlayBuf, queuedbuffers));
-    if(ulFlags == MIX_STREAM_ERROR) {
-        if(ulStatus == ERROR_DEVICE_UNDERRUN) {
+    if (ulFlags == MIX_STREAM_ERROR) {
+        if (ulStatus == ERROR_DEVICE_UNDERRUN) {
             dprintf(("WINMM: WaveOut handler UNDERRUN! state %s", (State == STATE_PLAYING) ? "playing" : "stopped"));
-            if(State == STATE_PLAYING) {
+            if (State == STATE_PLAYING) {
                 fUnderrun = TRUE;
                 //save current position for when we continue later
@@ -605,7 +608,6 @@
         return;
     }
-    if(State != STATE_PLAYING) {
+    if (State != STATE_PLAYING)
         return;
-    }
 
     wmutex.enter();
@@ -613,41 +615,38 @@
     bytesPlayed += MixBuffer[curPlayBuf].ulBufferLength;
 
-    //update our buffer index
-    if(curPlayBuf == PREFILLBUF_DART-1)
-         curPlayBuf = 0;
-    else curPlayBuf++;
+    // update our buffer index
+    if (++curPlayBuf >= ulBufCount)
+        curPlayBuf = 0;
 
     fUnderrun = FALSE;
 
     whdr = wavehdr;
-    while(whdr) {
-        if(whdr->reserved == WHDR_DONE)
-        {
-            if(bytesPlayed < bytesReturned + whdr->dwBufferLength) {
-                dprintf2(("Buffer marked done, but not yet played completely (play %d/%d, cop %d, ret %d)", bytesPlayed, getPosition(), bytesCopied, bytesReturned));
-                break;  //not yet done
-            }
-
-            dprintf2(("WINMM: handler buf %X done (play %d/%d, cop %d, ret %d)", whdr, bytesPlayed, getPosition(), bytesCopied, bytesReturned));
-            queuedbuffers--;
-
-            whdr->dwFlags  &= ~WHDR_INQUEUE;
-            whdr->dwFlags  |= WHDR_DONE;
-            whdr->reserved  = 0;
-
-            if(prevhdr == NULL)
-                 wavehdr = whdr->lpNext;
-            else prevhdr->lpNext = whdr->lpNext;
-
-            whdr->lpNext = NULL;
-
-            bytesReturned += whdr->dwBufferLength;
-            wmutex.leave();
-
-            callback(WOM_DONE, (ULONG)whdr, 0);
-
-            wmutex.enter();
+    while (whdr) {
+        if (whdr->reserved != WHDR_DONE)
+            break;
+
+        if (bytesPlayed < bytesReturned + whdr->dwBufferLength) {
+            dprintf2(("Buffer marked done, but not yet played completely (play %d/%d, cop %d, ret %d)", bytesPlayed, getPosition(), bytesCopied, bytesReturned));
+            break;  //not yet done
         }
-        else break;
+
+        dprintf2(("WINMM: handler buf %X done (play %d/%d, cop %d, ret %d)", whdr, bytesPlayed, getPosition(), bytesCopied, bytesReturned));
+        queuedbuffers--;
+
+        whdr->dwFlags  &= ~WHDR_INQUEUE;
+        whdr->dwFlags  |= WHDR_DONE;
+        whdr->reserved  = 0;
+
+        if (prevhdr == NULL)
+             wavehdr = whdr->lpNext;
+        else prevhdr->lpNext = whdr->lpNext;
+
+        whdr->lpNext = NULL;
+
+        bytesReturned += whdr->dwBufferLength;
+
+        wmutex.leave();
+        callback(WOM_DONE, (ULONG)whdr, 0);
+        wmutex.enter();
 
         prevhdr = whdr;
@@ -655,8 +654,8 @@
     }
 
-    if(wavehdr == NULL) {
-        //last buffer played -> no new ones -> return now
+    if (wavehdr == NULL) {
+        // last buffer played -> no new ones -> return now
         dprintf(("WINMM: WaveOut handler LAST BUFFER PLAYED! state %s (play %d (%d), cop %d, ret %d)", (State == STATE_PLAYING) ? "playing" : "stopped", bytesPlayed, getPosition(), bytesCopied, bytesReturned));
-        if(getPosition() > bytesPlayed) {
+        if (getPosition() > bytesPlayed) {
             dprintf(("WINMM: WaveOut handler UNDERRUN! state %s", (State == STATE_PLAYING) ? "playing" : "stopped"));
             //save current position for when we continue later
@@ -671,5 +670,4 @@
     writeBuffer();
 
-sendbuffer:
     wmutex.leave();
 
@@ -677,32 +675,33 @@
     dprintf2(("WINMM: handler transfer buffer %d", pBuffer - MixBuffer));
     USHORT selTIB = RestoreOS2FS(); // save current FS selector
-    MixSetupParms->pmixWrite(MixSetupParms->ulMixHandle, pBuffer, 1);
+    pmixWriteProc(mixHandle, pBuffer, 1);
     SetFS(selTIB);           // switch back to the saved FS selector
 
     dprintf2(("WINMM: handler DONE"));
 }
-/******************************************************************************/
-/******************************************************************************/
+
+/******************************************************************************/
+/******************************************************************************/
+
 void DartWaveOut::writeBuffer()
 {
     ULONG buflength;
 
-    if(!fUnderrun && State == STATE_PLAYING && wavehdr == NULL && curFillBuf == curPlayBuf) {
+    if (!fUnderrun && State == STATE_PLAYING && wavehdr == NULL && curFillBuf == curPlayBuf) {
         dprintf2(("writeBuffer: no more room for more audio data"));
         return; //no room left
     }
 
-    if(curhdr == NULL)
+    if (curhdr == NULL)
         curhdr = wavehdr;
 
-    while(curhdr && (curhdr->reserved == WHDR_DONE))  {
+    while (curhdr && (curhdr->reserved == WHDR_DONE))  {
         curhdr = curhdr->lpNext;
     }
 
-    if(curhdr == NULL) {
+    if (curhdr == NULL)
         return;     //no unprocessed buffers left
-    }
-
-    if(State == STATE_PLAYING && curFillBuf == curPlayBuf)
+
+    if (State == STATE_PLAYING && curFillBuf == curPlayBuf)
     {
         dprintf(("curFillBuf == curPlayBuf; no more room (%d,%d)", curFillBuf, curPlayBuf));
@@ -712,5 +711,5 @@
     dprintf2(("WINMM: handler cur (%d,%d), fill (%d,%d)\n", curPlayBuf, curPlayPos, curFillBuf, curFillPos));
 
-    while(curhdr) {
+    while (curhdr) {
         buflength = min((ULONG)MixBuffer[curFillBuf].ulBufferLength - curPlayPos,
                         (ULONG)curhdr->dwBufferLength - curFillPos);
@@ -727,5 +726,5 @@
         bytesCopied += buflength;
 
-        if(curFillPos == curhdr->dwBufferLength) {
+        if (curFillPos == curhdr->dwBufferLength) {
             dprintf2(("Buffer %d done ptr %x size %d %x %x %x %x %x %x", curFillBuf, curhdr->lpData, curhdr->dwBufferLength, curhdr->dwBytesRecorded, curhdr->dwUser, curhdr->dwFlags, curhdr->dwLoops, curhdr->lpNext, curhdr->reserved));
 
@@ -733,20 +732,22 @@
             curhdr->reserved = WHDR_DONE;
             //search for next unprocessed buffer
-            while(curhdr && (curhdr->reserved == WHDR_DONE))
+            while (curhdr && (curhdr->reserved == WHDR_DONE))
                 curhdr = curhdr->lpNext;
         }
-        if(curPlayPos == MixBuffer[curFillBuf].ulBufferLength) {
+        if (curPlayPos == MixBuffer[curFillBuf].ulBufferLength) {
             curPlayPos = 0;
 
-            if(++curFillBuf == PREFILLBUF_DART) {
+            if (++curFillBuf >= ulBufCount)
                 curFillBuf = 0;
-            }
-            if(curFillBuf == curPlayBuf)
+
+            if (curFillBuf == curPlayBuf)
                 break;  //no more room left
         }
     }
 }
-/******************************************************************************/
-/******************************************************************************/
+
+/******************************************************************************/
+/******************************************************************************/
+
 LONG APIENTRY WaveOutHandler(ULONG ulStatus,
                              PMCI_MIX_BUFFER pBuffer,
@@ -759,5 +760,5 @@
 
     ptib2 = (PTIB2)_getTIBvalue(offsetof(TIB, tib_ptib2));
-    if(ptib2 && HIBYTE(ptib2->tib2_ulpri) != PRTYC_TIMECRITICAL && 
+    if (ptib2 && HIBYTE(ptib2->tib2_ulpri) != PRTYC_TIMECRITICAL && 
        LOBYTE(ptib2->tib2_ulpri) != PRTYD_MAXIMUM) 
     {
@@ -765,49 +766,13 @@
         DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM, 0);
     }
-    if(pBuffer && pBuffer->ulUserParm)
+    if (pBuffer && pBuffer->ulUserParm)
     {
         dwave = (DartWaveOut *)pBuffer->ulUserParm;
         dwave->handler(ulStatus, pBuffer, ulFlags);
     }
-    return(TRUE);
-}
-
-/******************************************************************************/
-/******************************************************************************/
-MMRESULT DartWaveOut::setVolume(ULONG ulVol)
-{
-  ULONG ulVolR     = (((ulVol & 0xffff0000) >> 16 )*100)/0xFFFF; // Right Volume
-  ULONG ulVolL      = ((ulVol& 0x0000ffff)*100)/0xFFFF;          // Left Volume
-  MCI_SET_PARMS msp = {0};
-
-  dprintf(("DartWaveOut::setVolume %d %d", ulVolL, ulVolR));
-  volume = ulVol;
-
-// PD: My card (ESS 1868 PnP) driver can't change only
-//     one channel Left or Right :-(
-//
-#ifdef GOOD_AUDIO_CARD_DRIVER
-
-  msp.ulAudio = MCI_SET_AUDIO_LEFT;
-  msp.ulLevel = ulVolL;
-
-  mymciSendCommand(DeviceId, MCI_SET,
-                 MCI_WAIT | MCI_SET_AUDIO | MCI_SET_VOLUME,
-                 &msp, 0);
-
-  msp.ulAudio = MCI_SET_AUDIO_RIGHT;
-  msp.ulLevel = ulVolR;
-
-#else
-  msp.ulAudio = MCI_SET_AUDIO_ALL;
-  msp.ulLevel = max(ulVolR,ulVolL);
-#endif
-
-  mymciSendCommand(DeviceId, MCI_SET,
-                 MCI_WAIT | MCI_SET_AUDIO | MCI_SET_VOLUME,
-                 &msp, 0);
-  return 0;
-}
-/******************************************************************************/
-/******************************************************************************/
-
+    return TRUE;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
Index: trunk/src/winmm/waveoutdart.h
===================================================================
--- trunk/src/winmm/waveoutdart.h	(revision 21357)
+++ trunk/src/winmm/waveoutdart.h	(revision 21358)
@@ -8,11 +8,9 @@
  * Project Odin Software License can be found in LICENSE.TXT
  */
+
 #ifndef __DWAVEOUT_H__
 #define __DWAVEOUT_H__
 
 #include "waveoutbase.h"
-
-#define PREFILLBUF_DART 64
-#define DART_BUFSIZE    4096
 
 #ifdef OS2_ONLY
@@ -29,47 +27,51 @@
 #endif
 
+// this should be defined in some #included .h file, but it isn't
+typedef LONG (APIENTRY MIXERPROC)(ULONG ulHandle, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags);
+
 class DartWaveOut : public WaveOut
 {
 public:
-              DartWaveOut(LPWAVEFORMATEX pwfx, DWORD fdwOpen, ULONG nCallback, ULONG dwInstance);
-     virtual ~DartWaveOut();
+                    DartWaveOut(LPWAVEFORMATEX pwfx, DWORD fdwOpen,
+                                ULONG nCallback, ULONG dwInstance);
+  virtual           ~DartWaveOut();
 
-     virtual  MMRESULT write(LPWAVEHDR pwh, UINT cbwh);
-     virtual  MMRESULT pause();
-     virtual  MMRESULT stop();
-     virtual  MMRESULT resume();
-     virtual  MMRESULT setVolume(ULONG ulVol);
-     virtual  MMRESULT reset();
-     virtual  ULONG    getPosition();
-
-  static BOOL queryFormat(ULONG formatTag, ULONG nChannels,
-                          ULONG nSamplesPerSec, ULONG sampleSize);
+  virtual MMRESULT  open();
+  virtual MMRESULT  write(LPWAVEHDR pwh, UINT cbwh);
+  virtual MMRESULT  pause();
+  virtual MMRESULT  stop();
+  virtual MMRESULT  resume();
+  virtual MMRESULT  setVolume(ULONG ulVol);
+  virtual MMRESULT  reset();
+  virtual ULONG     getPosition();
 
 protected:
-  static void mciError(ULONG ulError);
-         void Init(LPWAVEFORMATEX pwfx);
-         void handler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags);
+          MMRESULT  initBuffers();
+          void      writeBuffer();
+   static void      mciError(ULONG rc);
+          void      handler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags);
 
 private:
-         void writeBuffer();
+          USHORT    DeviceId;
+          BOOL      fMixerSetup;
+          BOOL      fUnderrun;
+          int       curFillBuf;
+          int       curPlayBuf;
+          ULONG     curFillPos;
+          ULONG     curPlayPos;
+          ULONG     ulBufSize;
+          ULONG     ulBufCount;
+          ULONG     bytesPlayed;
+          ULONG     bytesCopied;
+          ULONG     bytesReturned;
+          ULONG     ulUnderrunBase;
+          ULONG     mixHandle;
+          WAVEHDR * curhdr;
+        MIXERPROC * pmixWriteProc;
+   MCI_MIX_BUFFER * MixBuffer;
+ MCI_BUFFER_PARMS * BufferParms;
 
-        USHORT          DeviceId;
-        ULONG           ulBufferCount;             /* Current file buffer     */
-        ULONG           ulBufSize;
-
-  MCI_MIX_BUFFER       *MixBuffer;          /* Device buffers          */
-  MCI_MIXSETUP_PARMS   *MixSetupParms;          /* Mixer parameters        */
-  MCI_BUFFER_PARMS     *BufferParms;                /* Device buffer parms     */
-
-        int             curPlayBuf, curFillBuf;
-        ULONG           curFillPos, curPlayPos; //fillpos == pos in os2 mix buffer, bufpos == pos in win buffer
-
-        BOOL            fMixerSetup;
-        BOOL            fUnderrun;
-        ULONG           ulUnderrunBase;
-
-#ifndef _OS2WIN_H
-        friend LONG APIENTRY WaveOutHandler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags);
-#endif
+  friend LONG APIENTRY WaveOutHandler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer,
+                                      ULONG ulFlags);
 };
 
Index: trunk/src/winmm/waveoutdaud.cpp
===================================================================
--- trunk/src/winmm/waveoutdaud.cpp	(revision 21357)
+++ trunk/src/winmm/waveoutdaud.cpp	(revision 21358)
@@ -12,10 +12,7 @@
  */
 
-
-/****************************************************************************
- * Includes                                                                 *
- ****************************************************************************/
-
-
+/******************************************************************************/
+// Includes
+/******************************************************************************/
 
 #define  INCL_BASE
@@ -57,4 +54,36 @@
                   : WaveOut(pwfx, fdwOpen, nCallback, dwInstance)
 {
+    hSem = 0;
+    hDAudioDrv = 0;
+    hThread = 0;
+    dwThreadID = 0;
+    bytesReturned = 0;
+    fUnderrun = 0;
+}
+/******************************************************************************/
+/******************************************************************************/
+DAudioWaveOut::~DAudioWaveOut()
+{
+    DAUDIO_CMD cmd;
+
+    if(hThread)
+        callback(WOM_CLOSE, 0, 0);
+
+    if(hDAudioDrv) {
+        cmd.Thread.hSemaphore = hSem;
+        sendIOCTL(DAUDIO_DEREGISTER_THREAD, &cmd);
+        sendIOCTL(DAUDIO_CLOSE, &cmd);
+        DosClose(hDAudioDrv);
+        hDAudioDrv = 0;
+    }
+    if(hSem) {
+        DosPostEventSem(hSem);
+        DosCloseEventSem(hSem);
+    }
+}
+/******************************************************************************/
+/******************************************************************************/
+MMRESULT DAudioWaveOut::open()
+{
     APIRET          rc;
     ULONG           action;
@@ -64,8 +93,5 @@
     ULONG           ParmLength = 0, DataLength;
 
-    fUnderrun = FALSE;
-    hSem      = 0;
-
-    dprintf(("DAudioWaveOut::DAudioWaveOut"));
+    dprintf(("DAudioWaveOut::open"));
 
     rc = DosOpen(szPDDName, &hDAudioDrv, &action, 0,
@@ -75,13 +101,12 @@
     if(rc) {
         dprintf(("DosOpen failed with error %d\n", rc));
-        ulError = MMSYSERR_NODRIVER;
-        goto fail;
+        return MMSYSERR_NODRIVER;
     }
 
     DataLength = sizeof(init);
 
-    init.lSRate         = pwfx->nSamplesPerSec;
-    init.lBitsPerSRate  = pwfx->wBitsPerSample;
-    init.sChannels      = pwfx->nChannels;
+    init.lSRate         = SampleRate;
+    init.lBitsPerSRate  = BitsPerSample;
+    init.sChannels      = nChannels;
     init.sMode          = PCM;  //todo!!
 
@@ -90,11 +115,9 @@
     if(rc) {
         dprintf(("DosDevIOCtl failed with error %d\n", rc));
-        ulError = MMSYSERR_NODRIVER;
-        goto fail;
+        return MMSYSERR_NODRIVER;
     }
     if(init.sReturnCode != 0) {
         dprintf(("init.sReturnCode = %d\n", init.sReturnCode));
-        ulError = MMSYSERR_NODRIVER;
-        goto fail;
+        return MMSYSERR_NODRIVER;
     }
 
@@ -102,6 +125,5 @@
     if(rc) {
         dprintf(("DosCreateEventSem failed with error %d\n", rc));
-        ulError = MMSYSERR_NODRIVER;
-        goto fail;
+        return MMSYSERR_NODRIVER;
     }
     cmd.Thread.hSemaphore = hSem;
@@ -110,39 +132,18 @@
     if(rc) {
         dprintf(("DosDevIOCtl failed with error %d\n", rc));
-        ulError = MMSYSERR_NODRIVER;
-        goto fail;
+        return MMSYSERR_NODRIVER;
     }
 
     hThread = CreateThread(NULL, 0x4000, (LPTHREAD_START_ROUTINE)DAudioThreadHandler,
                            (LPVOID)this, 0, &dwThreadID);
+    if (!hThread) {
+        dprintf(("CreateThread failed\n"));
+        return MMSYSERR_NODRIVER;
+    }
 
     setVolume(volume);
-
-    if(!ulError)
-        callback(WOM_OPEN, 0, 0);
-
-fail:
-    return;
-}
-/******************************************************************************/
-/******************************************************************************/
-DAudioWaveOut::~DAudioWaveOut()
-{
-    DAUDIO_CMD cmd;
-
-    if(!ulError)
-        callback(WOM_CLOSE, 0, 0);
-
-    if(hDAudioDrv) {
-        cmd.Thread.hSemaphore = hSem;
-        sendIOCTL(DAUDIO_DEREGISTER_THREAD, &cmd);
-        sendIOCTL(DAUDIO_CLOSE, &cmd);
-        DosClose(hDAudioDrv);
-        hDAudioDrv = 0;
-    }
-    if(hSem) {
-        DosPostEventSem(hSem);
-        DosCloseEventSem(hSem);
-    }
+    callback(WOM_OPEN, 0, 0);
+
+    return(MMSYSERR_NOERROR);
 }
 /******************************************************************************/
@@ -235,5 +236,5 @@
     fUnderrun = FALSE;
 
-    bytesPlayed = bytesCopied = bytesReturned = 0;
+    bytesReturned = 0;
 
     return rc;
@@ -271,5 +272,5 @@
     fUnderrun = FALSE;
 
-    bytesPlayed = bytesCopied = bytesReturned = 0;
+    bytesReturned = 0;
     queuedbuffers = 0;
 
@@ -409,5 +410,5 @@
  LPWAVEHDR whdr = wavehdr;
 
-    dprintf2(("WINMM: handler buf %X done (play %d/%d, cop %d, ret %d)", whdr, bytesPlayed, getPosition(), bytesCopied, bytesReturned));
+    dprintf2(("WINMM: handler buf %X done (play %d, ret %d)", whdr, getPosition(), bytesReturned));
 
     if(State != STATE_PLAYING || whdr == NULL)
Index: trunk/src/winmm/waveoutdaud.h
===================================================================
--- trunk/src/winmm/waveoutdaud.h	(revision 21357)
+++ trunk/src/winmm/waveoutdaud.h	(revision 21358)
@@ -8,4 +8,5 @@
  * Project Odin Software License can be found in LICENSE.TXT
  */
+
 #ifndef __DWAVEOUTEX_H__
 #define __DWAVEOUTEX_H__
@@ -24,39 +25,35 @@
 {
 public:
-               DAudioWaveOut(LPWAVEFORMATEX pwfx, ULONG fdwOpen, ULONG nCallback, ULONG dwInstance);
-     virtual  ~DAudioWaveOut();
+                    DAudioWaveOut(LPWAVEFORMATEX pwfx, ULONG fdwOpen,
+                                  ULONG nCallback, ULONG dwInstance);
+  virtual           ~DAudioWaveOut();
 
-     virtual  MMRESULT write(LPWAVEHDR pwh, UINT cbwh);
-     virtual  MMRESULT pause();
-     virtual  MMRESULT stop();
-     virtual  MMRESULT resume();
-     virtual  MMRESULT setVolume(ULONG ulVol);
-     virtual  MMRESULT reset();
-     virtual  ULONG    getPosition();
+  virtual MMRESULT  open();
+  virtual MMRESULT  write(LPWAVEHDR pwh, UINT cbwh);
+  virtual MMRESULT  pause();
+  virtual MMRESULT  stop();
+  virtual MMRESULT  resume();
+  virtual MMRESULT  setVolume(ULONG ulVol);
+  virtual MMRESULT  reset();
+  virtual ULONG     getPosition();
 
-     static   BOOL     queryFormat(ULONG formatTag, ULONG nChannels,
-                                   ULONG nSamplesPerSec, ULONG sampleSize);
-
-
-     static   BOOL     isDirectAudioAvailable();
+   static BOOL      queryFormat(ULONG formatTag, ULONG nChannels,
+                                ULONG nSamplesPerSec, ULONG sampleSize);
+   static BOOL      isDirectAudioAvailable();
 
 protected:
 
 private:
-       BOOL     handler();
-       MMRESULT sendIOCTL(ULONG cmd, DAUDIO_CMD *pDataPacket);
+          BOOL      handler();
+          MMRESULT  sendIOCTL(ULONG cmd, DAUDIO_CMD *pDataPacket);
 
-        HEV     hSem;
+          HEV       hSem;
+          HFILE     hDAudioDrv;
+          HANDLE    hThread;
+          DWORD     dwThreadID;
+          ULONG     bytesReturned;
+          BOOL      fUnderrun;
 
-        ULONG   bytesPlayed, bytesReturned;
-        int     queuedbuffers;
-
-        BOOL    fUnderrun;
-        HANDLE  hThread;
-        DWORD   dwThreadID;
-
-        HFILE   hDAudioDrv;
-
-        friend  DWORD WIN32API DAudioThreadHandler(LPVOID pUserData);
+  friend  DWORD WIN32API DAudioThreadHandler(LPVOID pUserData);
 };
 
Index: trunk/src/winmm/waveoutflash.cpp
===================================================================
--- trunk/src/winmm/waveoutflash.cpp	(revision 21358)
+++ trunk/src/winmm/waveoutflash.cpp	(revision 21358)
@@ -0,0 +1,812 @@
+/* $Id: waveoutflash.cpp,v 1.00 2010-02-20 12:00:00 rlwalsh Exp $ */
+
+/*
+ * Wave playback class (DART for Flash10)
+ *
+ * Copyright 1998-2001 Sander van Leeuwen (sandervl@xs4all.nl)
+ * Copyright 2010 Richard L Walsh (rich@e-vertise.com)
+ *
+ * Project Odin Software License can be found in LICENSE.TXT
+ *
+ */
+
+/******************************************************************************/
+// Includes
+/******************************************************************************/
+
+#define  INCL_BASE
+#define  INCL_OS2MM
+#define  INCL_DOSPROCESS
+#include <os2wrap.h>   //Odin32 OS/2 api wrappers
+#include <os2mewrap.h> //Odin32 OS/2 MMPM/2 api wrappers
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#define  OS2_ONLY
+#include <win32api.h>
+#include <wprocess.h>
+#include <options.h>
+#include "misc.h"
+#include "waveoutflash.h"
+#include "initwinmm.h"
+
+#define DBG_LOCALLOG    DBG_waveoutflash
+#include "dbglocal.h"
+
+/******************************************************************************/
+
+// number of DART buffers to allocate
+#define FLASH_BUFCNT    8
+
+// number of buffers to fill before writing when state == STOPPED or PAUSED
+#define FLASH_PREFILL   3
+
+// used to attach additional info to the MCI_MIX_BUFFERs
+typedef struct {
+    FlashWaveOut *      pThis;
+    volatile LPWAVEHDR  pwh;
+} MIX_EXTRA;
+
+// a deprecated but useful function implemented in kernel32\thread.cpp
+USHORT WIN32API ODIN_ThreadEnterOdinContext(void *pExceptionRegRec, BOOL fForceFSSwitch);
+
+// debug info
+void    showWriteMsg(LPWAVEHDR pwh, int free, int queued, BOOL fInit);
+
+/******************************************************************************/
+// Query/Enable/Disable use of FlashWaveOut
+/******************************************************************************/
+
+static BOOL useFlashAudio = FALSE;
+
+/******************************************************************************/
+/******************************************************************************/
+
+BOOL WIN32API ODIN_IsFlashAudioEnabled()
+{
+    // Except for the first call, this is the same as 'return useFlashAudio'.
+    return ODIN_EnableFlashAudio(useFlashAudio);
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
+BOOL WIN32API ODIN_EnableFlashAudio(BOOL enable)
+{
+    static int forceFlashAudio = -1;
+
+    // If the ini hasn't been checked yet, do so now.
+    // If there's an entry, it will override the default & app setting.
+    if (forceFlashAudio == -1) {
+        int i = PROFILE_GetOdinIniInt(WINMM_SECTION, KEY_FLASHAUDIO, -1);
+        if (i == -1)
+            forceFlashAudio = 0;
+        else {
+            forceFlashAudio = 1;
+            useFlashAudio = i ? TRUE : FALSE;
+        }
+    }
+
+    // If FlashAudio hasn't been forced on or off, update the setting.
+    if (!forceFlashAudio)
+        useFlashAudio = enable ? TRUE : FALSE;
+
+    return useFlashAudio;
+}
+
+/******************************************************************************/
+// FlashWaveOut implementation
+/******************************************************************************/
+
+// event sem used to serialize ownership of the audio device
+HEV FlashWaveOut::deviceSem = 0;
+
+/******************************************************************************/
+/******************************************************************************/
+
+FlashWaveOut::FlashWaveOut(LPWAVEFORMATEX pwfx, ULONG fdwOpen,
+                           ULONG nCallback, ULONG dwInstance)
+                    : WaveOut(pwfx, fdwOpen, nCallback, dwInstance)
+{
+    deviceId      = 0;
+    waveOffs      = 0;
+    dartBufInit   = FALSE;
+    dartBufSize   = 0;
+    dartBufCnt    = FLASH_BUFCNT;
+    dartFreeCnt   = FLASH_BUFCNT;
+    dartFreeNdx   = 0;
+    dartPlayed    = 0;
+    readyCnt      = 0;
+    readyNdx      = 0;
+    mixHandle     = 0;
+    pmixWriteProc = 0;
+    pmixBuffers   = 0;
+
+    dprintf(("FlashWaveOut - sps= %d  bps= %d  chan= %d",
+             SampleRate, BitsPerSample, nChannels));
+
+    return;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
+MMRESULT FlashWaveOut::open()
+{
+    APIRET      rc;
+    MIX_EXTRA * pmixExtra;
+    MCI_AMP_OPEN_PARMS AmpOpenParms;
+    MCI_GENERIC_PARMS  GenericParms = {0};
+    MCI_MIXSETUP_PARMS MixSetupParms;
+
+    // Wait for the device to become available.
+    if (!getDeviceSem(TRUE))
+        return MMSYSERR_NOTENABLED;
+
+    // Open the ampmix device in shared mode.
+    memset(&AmpOpenParms, 0, sizeof(AmpOpenParms));
+    AmpOpenParms.pszDeviceType = (PSZ)MCI_DEVTYPE_AUDIO_AMPMIX;
+
+    rc = mymciSendCommand(0, MCI_OPEN,
+                          MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
+                          (PVOID)&AmpOpenParms, 0);
+    if (LOUSHORT(rc) != MCIERR_SUCCESS) {
+        mciError("FlashWaveOut::open - MCI_OPEN", rc);
+        return MMSYSERR_NODRIVER;
+    }
+
+    // Save the device ID
+    deviceId = AmpOpenParms.usDeviceID;
+
+    // Get exclusive rights to this device instance (not entire device).
+    rc = mymciSendCommand(deviceId, MCI_ACQUIREDEVICE,
+                          MCI_WAIT | MCI_EXCLUSIVE_INSTANCE,
+                          (PVOID)&GenericParms, 0);
+    if (LOUSHORT(rc) != MCIERR_SUCCESS) {
+        mciError("FlashWaveOut::open - MCI_ACQUIREDEVICE", rc);
+        return MMSYSERR_NOTENABLED;
+    }
+
+    // Setup the Amp-Mixer to play wave data.
+    memset(&MixSetupParms, 0, sizeof(MixSetupParms));
+    MixSetupParms.ulBitsPerSample  = BitsPerSample;
+    MixSetupParms.ulFormatTag      = MCI_WAVE_FORMAT_PCM;
+    MixSetupParms.ulSamplesPerSec  = SampleRate;
+    MixSetupParms.ulChannels       = nChannels;
+    MixSetupParms.ulFormatMode     = MCI_PLAY;
+    MixSetupParms.ulDeviceType     = MCI_DEVTYPE_WAVEFORM_AUDIO;
+    MixSetupParms.pmixEvent        = FlashWaveOutHandler;
+
+    rc = mymciSendCommand(deviceId, MCI_MIXSETUP,
+                          MCI_WAIT | MCI_MIXSETUP_INIT,
+                          (PVOID)&MixSetupParms, 0);
+    if (LOUSHORT(rc) != MCIERR_SUCCESS) {
+        mciError("FlashWaveOut::open - MCI_MIXSETUP", rc);
+        mymciSendCommand(deviceId, MCI_RELEASEDEVICE,
+                         MCI_WAIT, (PVOID)&GenericParms, 0);
+        return MMSYSERR_NOTSUPPORTED;
+    }
+
+    // Save the mixer handle & the ptr to the write proc.
+    mixHandle     = MixSetupParms.ulMixHandle;
+    pmixWriteProc = MixSetupParms.pmixWrite;
+
+    // Allocate mixbuffer structures - the actual buffers
+    // will be allocated the first time ::write() is called.
+    int    cnt = dartBufCnt * (sizeof(MCI_MIX_BUFFER) + sizeof(MIX_EXTRA));
+    void * ptr = malloc(cnt);
+    if (!ptr) {
+        dprintf(("FlashWaveOut::open - malloc failed"));
+        mymciSendCommand(deviceId, MCI_RELEASEDEVICE,
+                         MCI_WAIT, (PVOID)&GenericParms, 0);
+        return MMSYSERR_NOMEM;
+    }
+    memset(ptr, 0, cnt);
+    pmixBuffers = (MCI_MIX_BUFFER*)ptr;
+    pmixExtra   = (MIX_EXTRA*)&pmixBuffers[dartBufCnt];
+
+    // Initialize the members that don't change.
+    for (int i = 0; i < dartBufCnt; i++) {
+        pmixBuffers[i].ulStructLength = sizeof(MCI_MIX_BUFFER);
+        pmixBuffers[i].ulUserParm = (ULONG)&pmixExtra[i];
+        pmixExtra[i].pThis = this;
+    }
+
+    setVolume(volume);
+    callback(WOM_OPEN, 0, 0);
+
+    return MMSYSERR_NOERROR;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
+FlashWaveOut::~FlashWaveOut()
+{
+    APIRET  rc;
+    MCI_GENERIC_PARMS GenericParms = {0};
+
+    dprintf((__FUNCTION__));
+
+    State = STATE_STOPPED;
+
+    // If the device was successfully opened...
+    if (deviceId) {
+
+        // Stop playback.
+        rc = mymciSendCommand(deviceId, MCI_STOP,
+                              MCI_WAIT, (PVOID)&GenericParms, 0);
+        if (LOUSHORT(rc) != MCIERR_SUCCESS)
+            mciError("~FlashWaveOut - MCI_STOP", rc);
+
+        // Free the DART buffers
+        if (dartBufInit) {
+            MCI_BUFFER_PARMS BufferParms;
+            memset(&BufferParms, 0, sizeof(BufferParms));
+            BufferParms.ulStructLength = sizeof(BufferParms);
+            BufferParms.ulNumBuffers = dartBufCnt;
+            BufferParms.ulBufferSize = dartBufSize;
+            BufferParms.pBufList     = pmixBuffers;
+            rc = mymciSendCommand(deviceId, MCI_BUFFER,
+                                  MCI_WAIT | MCI_DEALLOCATE_MEMORY,
+                                  (PVOID)&BufferParms, 0);
+            if (LOUSHORT(rc) != MCIERR_SUCCESS)
+                mciError("~FlashWaveOut - MCI_BUFFER", rc);
+        }
+
+        // Close the device.
+        rc = mymciSendCommand(deviceId, MCI_CLOSE,
+                              MCI_WAIT, (PVOID)&GenericParms, 0);
+        if (LOUSHORT(rc) != MCIERR_SUCCESS)
+            mciError("~FlashWaveOut - MCI_CLOSE", rc);
+
+        // Advise the Win client that the device has been closed.
+        callback(WOM_CLOSE, 0, 0);
+    }
+
+    // Free the MCI_MIX_BUFFER & MIX_EXTRA structures
+    if (pmixBuffers)
+        free(pmixBuffers);
+
+    // Signal that the device is now available for use by another instance.
+    getDeviceSem(FALSE);
+
+    dprintf(("exit\n"));
+
+    return;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
+// Flash may try to open a new instance of the audio device before it has
+// finished closing the previous instance, causing a failure.  Because it
+// is opened on the primary thread but usually closed by a secondary thread,
+// a mutex sem can't be used to control access to the device.  Instead, an
+// event sem is used, where:  reset == "in use" & posted == "available".
+// Note:  DCE_POSTONE was added in Warp 4.0 FP4 & 3.0 FP29 - the sem is
+//        reset automatically & only one waiting thread is unblocked
+
+BOOL FlashWaveOut::getDeviceSem(BOOL get)
+{
+    APIRET  rc;
+
+    // Create the semaphore.  Unless there's been some error,
+    // this should only be called when 'get' is TRUE.
+    if (!deviceSem) {
+        dprintf(("FlashWaveOut::getDeviceSem - creating event sem in %s state",
+                 (get ? "RESET" : "POSTED")));
+        rc = DosCreateEventSem(0, &deviceSem, DCE_POSTONE, !get);
+        if (rc) {
+            dprintf(("FlashWaveOut::getDeviceSem - DosCreateEventSem failed - rc= %d", rc));
+            return MMSYSERR_NOTENABLED;
+        }
+        return TRUE;
+    }
+
+    // Post the semaphore so other instances can claim the device.
+    if (!get) {
+        rc = DosPostEventSem(deviceSem);
+        if (rc) {
+            dprintf(("FlashWaveOut::getDeviceSem - DosPostEventSem failed - rc= %d", rc));
+            return FALSE;
+        }
+        return TRUE;
+    }
+
+    // Wait for the semaphore (it will reset itself).  Limit the wait
+    // to 5 seconds to avoid causing more problems than we're solving.
+    dprintf(("FlashWaveOut::getDeviceSem - about to wait for event sem"));
+    rc = DosWaitEventSem(deviceSem, 5000);
+    if (rc) {
+        dprintf(("FlashWaveOut::getDeviceSem - DosWaitEventSem failed - rc= %d", rc));
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
+MMRESULT FlashWaveOut::initBuffers()
+{
+    APIRET  rc;
+    MCI_GENERIC_PARMS GenericParms = {0};
+    MCI_BUFFER_PARMS  BufferParms;
+
+    dprintf((__FUNCTION__" - bufsize= %d", dartBufSize));
+
+    // Set up the BufferParms data structure and
+    // allocate device buffers from the Amp-Mixer.
+    memset(&BufferParms, 0, sizeof(BufferParms));
+    BufferParms.ulStructLength = sizeof(BufferParms);
+    BufferParms.ulNumBuffers   = dartBufCnt;
+    BufferParms.ulBufferSize   = dartBufSize;
+    BufferParms.pBufList       = pmixBuffers;
+
+    rc = mymciSendCommand(deviceId, MCI_BUFFER,
+                          MCI_WAIT | MCI_ALLOCATE_MEMORY,
+                          (PVOID)&BufferParms, 0);
+    if (LOUSHORT(rc) != MCIERR_SUCCESS) {
+        mciError("FlashWaveOut::initBuffers - MCI_BUFFER", rc);
+        mymciSendCommand(deviceId, MCI_RELEASEDEVICE,
+                         MCI_WAIT, (PVOID)&GenericParms, 0);
+        return MMSYSERR_NOTSUPPORTED;
+    }
+
+    // DART may not have allocated all the buffers requested.
+    dartBufCnt = BufferParms.ulNumBuffers;
+    dartFreeCnt = dartBufCnt;
+
+    // Signal that the DART buffers have been created & initialized.
+    dartBufInit = TRUE;
+
+    return MMSYSERR_NOERROR;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
+MMRESULT FlashWaveOut::write(LPWAVEHDR pwh, UINT cbwh)
+{
+    APIRET  rc;
+
+    #ifdef DEBUG
+        showWriteMsg(pwh, dartFreeCnt, queuedbuffers, dartBufInit);
+    #endif
+
+    // Allocation of DART buffers is deferred until the first write
+    // so their size can be based on the size of the Win WAVE buffers.
+    if (!dartBufInit) {
+        dartBufSize = pwh->dwBufferLength;
+        if (!dartBufSize || dartBufSize > 0x10000)
+            return MMSYSERR_INVALPARAM;
+
+        rc = initBuffers();
+        if (rc != MMSYSERR_NOERROR)
+            return rc;
+    }
+
+    // Init members used by the Win MM subsystem.
+    pwh->lpNext   = 0;
+    pwh->reserved = 0;
+
+    // Add this header to the tail of the chain of unplayed buffers
+    if (!wavehdr)
+        wavehdr = pwh;
+    else {
+        LPWAVEHDR pTail = wavehdr;
+        while (pTail->lpNext) {
+            pTail = pTail->lpNext;
+        }
+        pTail->lpNext = pwh;
+    }
+    queuedbuffers++;
+
+    // Copy as many WAVE buffers to DART buffers as possible.  Exit
+    // if none were copied, or we don't have enough to start playback, 
+    writeBuffer();
+    if (!readyCnt || (State != STATE_PLAYING && readyCnt < FLASH_PREFILL))
+        return MMSYSERR_NOERROR;
+
+    // Change the state flag to playing.
+    LONG oldState = DosInterlockedExchange((PLONG)&State, STATE_PLAYING);
+    if (oldState != STATE_PLAYING)
+        dprintf(("state change to PLAYING from %s",
+                (oldState == STATE_STOPPED ? "STOPPED" :
+                 (oldState == STATE_PAUSED ? "PAUSED " : "UNKNOWN"))));
+
+    // Write all of the DART buffers that are ready to the device.
+    USHORT selTIB = RestoreOS2FS();
+    if (readyNdx + readyCnt >= dartBufCnt) {
+        ULONG cnt = dartBufCnt - readyNdx;
+        rc = pmixWriteProc(mixHandle, &pmixBuffers[readyNdx], cnt);
+        if (LOUSHORT(rc) != MCIERR_SUCCESS)
+            mciError("FlashWaveOut::write - pmixWriteProc", rc);
+        readyNdx  = 0;
+        readyCnt -= cnt;
+    }
+    if (readyCnt) {
+        rc = pmixWriteProc(mixHandle, &pmixBuffers[readyNdx], readyCnt);
+        if (LOUSHORT(rc) != MCIERR_SUCCESS)
+            mciError("FlashWaveOut::write - pmixWriteProc", rc);
+        readyNdx += readyCnt;
+        readyCnt  = 0;
+    }
+    SetFS(selTIB);
+
+    return MMSYSERR_NOERROR;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
+void FlashWaveOut::writeBuffer()
+{
+    // Loop while there are both WAVE buffers & DART buffers available.
+    while (wavehdr && dartFreeCnt) {
+        MIX_EXTRA * pMX;
+
+        // Write one WAVE buffer to as many DART buffers as needed
+        // (both buffers should be the same size, so this shouldn't loop).
+        while (dartFreeCnt && waveOffs < wavehdr->dwBufferLength) {
+            int cnt = wavehdr->dwBufferLength - waveOffs;
+            if (cnt > dartBufSize)
+                cnt = dartBufSize;
+            memcpy(pmixBuffers[dartFreeNdx].pBuffer, &wavehdr->lpData[waveOffs], cnt);
+            pmixBuffers[dartFreeNdx].ulBufferLength = cnt;
+            pMX = (MIX_EXTRA*)pmixBuffers[dartFreeNdx].ulUserParm;
+            pMX->pwh = 0;
+            waveOffs += cnt;
+            readyCnt++;
+            DosInterlockedDecrement((PLONG)&dartFreeCnt);
+            if (++dartFreeNdx >= dartBufCnt)
+                dartFreeNdx = 0;
+        }
+
+        // Exit if the WAVE buffer still has data
+        // but there are no more DART buffers.
+        if (waveOffs < wavehdr->dwBufferLength)
+            return;
+
+        // Remove this wavehdr from the head of the chain and
+        // store it in the MIX_EXTRA struct associated with this
+        // DART buffer for use by the DART event callback proc.
+        waveOffs = 0;
+        pMX->pwh = wavehdr;
+        wavehdr = wavehdr->lpNext;
+        pMX->pwh->lpNext = 0;
+        queuedbuffers--;
+    }
+
+    return;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
+MMRESULT FlashWaveOut::pause()
+{
+    APIRET  rc;
+    MCI_GENERIC_PARMS GenericParms = {0};
+
+    // Pause playback if current state == playing
+    if (DosInterlockedCompareExchange((PLONG)&State, STATE_PAUSED, STATE_PLAYING)
+        == STATE_PLAYING) {
+        rc = mymciSendCommand(deviceId, MCI_PAUSE,
+                         MCI_WAIT, (PVOID)&GenericParms, 0);
+        if (LOUSHORT(rc) != MCIERR_SUCCESS)
+            mciError("FlashWaveOut::pause - MCI_PAUSE", rc);
+    }
+
+    return MMSYSERR_NOERROR;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
+MMRESULT FlashWaveOut::resume()
+{
+    APIRET  rc;
+    MCI_GENERIC_PARMS GenericParms = {0};
+
+    dprintf2((__FUNCTION__));
+
+    // Resume playback if current state == paused
+    if (DosInterlockedCompareExchange((PLONG)&State, STATE_PLAYING, STATE_PAUSED)
+        == STATE_PAUSED) {
+        rc = mymciSendCommand(deviceId, MCI_RESUME,
+                              MCI_WAIT, (PVOID)&GenericParms, 0);
+        if (LOUSHORT(rc) != MCIERR_SUCCESS)
+            mciError("FlashWaveOut::resume - MCI_RESUME", rc);
+    }
+
+    return MMSYSERR_NOERROR;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
+MMRESULT FlashWaveOut::stop()
+{
+    APIRET  rc;
+    MCI_GENERIC_PARMS GenericParms = {0};
+
+    dprintf2((__FUNCTION__));
+
+    // Stop playback if current state == playing or paused
+    if (DosInterlockedExchange((PLONG)&State, STATE_STOPPED)
+        != STATE_STOPPED) {
+        rc = mymciSendCommand(deviceId, MCI_STOP,
+                              MCI_WAIT, (PVOID)&GenericParms, 0);
+        if (LOUSHORT(rc) != MCIERR_SUCCESS)
+            mciError("FlashWaveOut::stop - MCI_STOP", rc);
+    }
+
+    return MMSYSERR_NOERROR;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
+MMRESULT FlashWaveOut::reset()
+{
+    APIRET  rc;
+    MCI_GENERIC_PARMS GenericParms = {0};
+
+    dprintf((__FUNCTION__));
+
+    // Stop playback if current state == playing or paused
+    if (DosInterlockedExchange((PLONG)&State, STATE_STOPPED)
+        != STATE_STOPPED) {
+        rc = mymciSendCommand(deviceId, MCI_STOP,
+                              MCI_WAIT, (PVOID)&GenericParms, 0);
+        if (LOUSHORT(rc) != MCIERR_SUCCESS)
+            mciError("FlashWaveOut::reset - MCI_STOP", rc);
+    }
+
+    // Handle the wavehdrs that have already been processed.
+    // Cycle thru every DART buffer, including those that should be
+    // free to ensure that every wavehdr we know about is marked as done.
+    int ndx = dartFreeNdx;
+    for (int ctr = 0; ctr < dartBufCnt; ctr++) {
+        LPWAVEHDR pwh = ((MIX_EXTRA*)pmixBuffers[ndx].ulUserParm)->pwh;
+        if (pwh) {
+            ((MIX_EXTRA*)pmixBuffers[ndx].ulUserParm)->pwh = 0;
+            pwh->lpNext    = 0;
+            pwh->dwFlags  |= WHDR_DONE;
+            pwh->dwFlags  &= ~WHDR_INQUEUE;
+            pwh->reserved  = 0;
+            callback(WOM_DONE, (ULONG)pwh, 0);
+        }
+        if (++ndx >= dartBufCnt)
+            ndx = 0;
+    }
+
+    // Handle the wavehdrs that have not been processed yet.
+    while (wavehdr) {
+        LPWAVEHDR pwh = wavehdr;
+        wavehdr = pwh->lpNext;
+        pwh->lpNext    = 0;
+        pwh->dwFlags  |= WHDR_DONE;
+        pwh->dwFlags  &= ~WHDR_INQUEUE;
+        pwh->reserved  = 0;
+        callback(WOM_DONE, (ULONG)pwh, 0);
+    }
+
+    // Reset variables to their initial state.
+    waveOffs    = 0;
+    dartFreeCnt = dartBufCnt;
+    dartFreeNdx = 0;
+    dartPlayed  = 0;
+    readyCnt    = 0;
+    readyNdx    = 0;
+
+    return MMSYSERR_NOERROR;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
+ULONG FlashWaveOut::getPosition()
+{
+    // This is the total of all bytes that have already been played.
+    // It increases whenever the DART event callback is notified of
+    // a free buffer (i.e. it is not a realtime, running byte counter).
+
+    return (ULONG)dartPlayed;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
+MMRESULT FlashWaveOut::setVolume(ULONG ulVol)
+{
+    APIRET  rc;
+    ULONG   ulVolR   = ((ulVol >> 16)    * 100) / 0xFFFF;
+    ULONG   ulVolL   = ((ulVol & 0xffff) * 100) / 0xFFFF;
+    MCI_SET_PARMS SetParms = {0};
+
+    dprintf2((__FUNCTION__));
+
+    volume = ulVol;
+
+// Some drivers can't set left & right volumes independently
+#ifdef GOOD_AUDIO_CARD_DRIVER
+    SetParms.ulAudio = MCI_SET_AUDIO_LEFT;
+    SetParms.ulLevel = ulVolL;
+
+    rc = mymciSendCommand(deviceId, MCI_SET,
+                          MCI_WAIT | MCI_SET_AUDIO | MCI_SET_VOLUME,
+                          &SetParms, 0);
+    if (LOUSHORT(rc) != MCIERR_SUCCESS)
+        mciError("FlashWaveOut::setVolume - MCI_SET (volume)", rc);
+
+    SetParms.ulAudio = MCI_SET_AUDIO_RIGHT;
+    SetParms.ulLevel = ulVolR;
+#else
+    SetParms.ulAudio = MCI_SET_AUDIO_ALL;
+    SetParms.ulLevel = (ulVolR + ulVolL) / 2;
+#endif
+
+    rc = mymciSendCommand(deviceId, MCI_SET,
+                          MCI_WAIT | MCI_SET_AUDIO | MCI_SET_VOLUME,
+                          &SetParms, 0);
+    if (LOUSHORT(rc) != MCIERR_SUCCESS)
+        mciError("FlashWaveOut::setVolume - MCI_SET (volume)", rc);
+
+    return MMSYSERR_NOERROR;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
+LONG APIENTRY FlashWaveOutHandler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer,
+                                  ULONG ulFlags)
+{
+    if (!pBuffer ||
+        !pBuffer->ulUserParm ||
+        !((MIX_EXTRA*)pBuffer->ulUserParm)->pThis) {
+        fprintf(stderr, "FlashWaveOutHandler - no object ptr - "
+                        "pBuffer= %x  ulStatus= %x  ulFlags= %x\n",
+                pBuffer, ulStatus, ulFlags);
+    }
+    else {
+        ((MIX_EXTRA*)pBuffer->ulUserParm)->pThis->handler(ulStatus, pBuffer, ulFlags);
+    }
+
+    return TRUE;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+
+void FlashWaveOut::handler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags)
+{
+    if (ulFlags == MIX_STREAM_ERROR) {
+
+        // out of buffers, so pause playback
+        if (ulStatus == ERROR_DEVICE_UNDERRUN) {
+            pause();
+            dprintf(("FlashWaveOut::handler - Hardware Underrun, state= %s",
+                     (State == STATE_PLAYING) ? "playing" : "stopped"));
+        }
+        else
+            dprintf(("FlashWaveOut::handler - Unknown Error= %x", ulStatus));
+        return;
+    }
+
+    // If there are fewer than FLASH_PREFILL-1 buffers in use,
+    // pause the device or else we're likely to have an underrun.
+    // Do NOT inc dartFreeCnt until we're done with this buffer.
+    // If this is the only one available, the other thread might
+    // change something we need below.
+    if (State == STATE_PLAYING && dartFreeCnt > dartBufCnt - FLASH_PREFILL)
+        pause();
+
+    // Get the wavehdr associated with this DART buffer (if any),
+    // then clear the buffer's reference to it.
+    LPWAVEHDR pwh = ((MIX_EXTRA*)pBuffer->ulUserParm)->pwh;
+    ((MIX_EXTRA*)pBuffer->ulUserParm)->pwh = 0;
+
+    // If the device is supposed to be stopped, don't update variables that
+    // are used by the other thread because ::reset() may have cleared them.
+    if (State != STATE_STOPPED) {
+        // Add the size of this buffer to the total played.  A locked
+        // add operation may not be necessary but is used "just in case".
+        DosInterlockedExchangeAdd((PLONG)&dartPlayed, pBuffer->ulBufferLength);
+
+        // Now that we're done with the buffer, we can inc the free count.
+        // As above, the locked increament may be unnecessary.
+        DosInterlockedIncrement((PLONG)&dartFreeCnt);
+    }
+
+    // On the first call to this function, create a Win32 TEB (equivalent
+    // to an OS/2 TIB) for this thread.  Without it, the Win callback will
+    // be called on this thread with the TEB for the primary thread (which
+    // is probably a bad idea).  Note: the DART thread persists for the life
+    // of the app, so all instances of FlashWaveOut will use the same TEB.
+
+    static USHORT   odinFS = 0;
+    if (!odinFS) {
+        if (ODIN_ThreadEnterOdinContext(0, TRUE))
+            odinFS = RestoreOS2FS();
+        else {
+            odinFS = (USHORT)-1;
+            dprintf(("FlashWaveOut::handler - ODIN_ThreadEnterOdinContext failed"));
+        }
+    }
+
+    // Switch to this thread's Win FS selector, then notify
+    // the Win client that it's buffer has been played.
+    if (pwh) {
+        pwh->lpNext    = 0;
+        pwh->reserved  = 0;
+        pwh->dwFlags  &= ~WHDR_INQUEUE;
+        pwh->dwFlags  |= WHDR_DONE;
+        if (odinFS != (USHORT)-1)
+            SetFS(odinFS);
+        callback(WOM_DONE, (ULONG)pwh, 0);
+        RestoreOS2FS();
+    }
+
+    return;
+}
+
+/******************************************************************************/
+//  Debug messages
+/******************************************************************************/
+
+// Displays the text associated with an MCI error code.
+
+void FlashWaveOut::mciError(char * msg, ULONG rc)
+{
+#ifdef DEBUG
+    char szError[64] = "";
+
+    mymciGetErrorString(rc, szError, sizeof(szError));
+    dprintf(("%s failed - '%s'", msg, szError));
+#endif
+
+    return;
+}
+
+/******************************************************************************/
+/******************************************************************************/
+#ifdef DEBUG
+
+// This offers a potentially incorrect count of the number of WAVE
+// buffers in use.  It saves the address of the very first buffer
+// written, then counts how many writes occur before it's reused.
+// It only displays a message if the count changes.
+
+void showWriteMsg(LPWAVEHDR pwh, int free, int queued, BOOL fInit)
+{
+    static int          bufctr = 0;
+    static int          buflast = 0;
+    static LPWAVEHDR    pwhFirst = 0;
+
+    bufctr++;
+    if (!fInit) {
+        pwhFirst = pwh;
+    }
+    else
+    if (pwhFirst == pwh) {
+        if (bufctr != buflast) {
+            dprintf(("FlashWaveOut::write - bufctr= %d  free= %d  queued= %d",
+                     bufctr, free, queued));
+            buflast = bufctr;
+        }
+        bufctr = 0;
+    }
+
+    return;
+}
+
+#endif
+/******************************************************************************/
+/******************************************************************************/
+
Index: trunk/src/winmm/waveoutflash.h
===================================================================
--- trunk/src/winmm/waveoutflash.h	(revision 21358)
+++ trunk/src/winmm/waveoutflash.h	(revision 21358)
@@ -0,0 +1,75 @@
+/* $Id: waveoutflash.h,v 1.00 2010-02-20 12:00:00 rlwalsh Exp $ */
+
+/*
+ * Wave playback class (DART for Flash10)
+ *
+ * Copyright 1998-2001 Sander van Leeuwen (sandervl@xs4all.nl)
+ * Copyright 2010 Richard L Walsh (rich@e-vertise.com)
+ *
+ * Project Odin Software License can be found in LICENSE.TXT
+ */
+
+/******************************************************************************/
+
+#ifndef __WAVEOUTFLASH_H__
+#define __WAVEOUTFLASH_H__
+
+#include "waveoutbase.h"
+#include "flashaudio.h"
+
+#ifdef OS2_ONLY
+#include "winmmtype.h"
+#endif
+
+// this should be defined in some #included .h file, but it isn't
+typedef LONG (APIENTRY MIXERPROC)(ULONG ulHandle, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags);
+
+/******************************************************************************/
+
+class FlashWaveOut : public WaveOut
+{
+public:
+                    FlashWaveOut(LPWAVEFORMATEX pwfx, DWORD fdwOpen,
+                                 ULONG nCallback, ULONG dwInstance);
+  virtual           ~FlashWaveOut();
+
+  virtual MMRESULT  open();
+  virtual MMRESULT  write(LPWAVEHDR pwh, UINT cbwh);
+  virtual MMRESULT  pause();
+  virtual MMRESULT  stop();
+  virtual MMRESULT  resume();
+  virtual MMRESULT  setVolume(ULONG ulVol);
+  virtual MMRESULT  reset();
+  virtual ULONG     getPosition();
+
+protected:
+          BOOL      getDeviceSem(BOOL get);
+          MMRESULT  initBuffers();
+          void      writeBuffer();
+          void      handler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags);
+          void      mciError(char * msg, ULONG rc);
+
+private:
+   static HEV       deviceSem;
+          USHORT    deviceId;
+          int       waveOffs;
+          BOOL      dartBufInit;
+          int       dartBufSize;
+          int       dartBufCnt;
+ volatile int       dartFreeCnt;
+          int       dartFreeNdx;
+ volatile int       dartPlayed;
+          int       readyCnt;
+          int       readyNdx;
+          ULONG     mixHandle;
+        MIXERPROC * pmixWriteProc;
+   MCI_MIX_BUFFER * pmixBuffers;
+
+  friend LONG APIENTRY FlashWaveOutHandler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer,
+                                           ULONG ulFlags);
+};
+
+#endif
+
+/******************************************************************************/
+
Index: trunk/src/winmm/winmm.mak
===================================================================
--- trunk/src/winmm/winmm.mak	(revision 21357)
+++ trunk/src/winmm/winmm.mak	(revision 21358)
@@ -24,5 +24,4 @@
 #
 !include ../../makefile.inc
-
 
 #
@@ -56,4 +55,5 @@
 $(OBJDIR)\joyos2.obj \
 $(OBJDIR)\winmmrsrc.obj \
+$(OBJDIR)\waveoutflash.obj \
 !ifdef DEBUG
 $(OBJDIR)\dbgwrap.obj \
