Changeset 21358 for trunk/src


Ignore:
Timestamp:
Feb 22, 2010, 2:44:21 PM (16 years ago)
Author:
rlwalsh
Message:

add FlashWaveOut class to winmm - see Ticket #2

Location:
trunk/src/winmm
Files:
2 added
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/winmm/WINMM.DEF

    r5433 r21358  
    202202;    winmmf_ThunkData32         = _winmmf_ThunkData32@??      @184
    203203;    winmmsl_ThunkData32        = _winmmsl_ThunkData32@??     @185
     204; ODIN-specific
     205    ODIN_IsFlashAudioEnabled   = _ODIN_IsFlashAudioEnabled@0 @186
     206    ODIN_EnableFlashAudio      = _ODIN_EnableFlashAudio@4    @187
     207
  • trunk/src/winmm/WINMMDBG.DEF

    r8470 r21358  
    202202;    winmmf_ThunkData32         = _Dbgwinmmf_ThunkData32@??      @184
    203203;    winmmsl_ThunkData32        = _Dbgwinmmsl_ThunkData32@??     @185
     204; ODIN-specific
     205    ODIN_IsFlashAudioEnabled   = _DbgODIN_IsFlashAudioEnabled@0 @186
     206    ODIN_EnableFlashAudio      = _DbgODIN_EnableFlashAudio@4    @187
     207
  • trunk/src/winmm/dbglocal.cpp

    r6375 r21358  
    4343"waveoutdaud",
    4444"waveoutbase",
    45 "waveinoutbase"
     45"waveinoutbase",
     46"waveoutflash"
    4647};
    4748//******************************************************************************
  • trunk/src/winmm/dbglocal.h

    r6375 r21358  
    4343#define DBG_waveoutbase     21
    4444#define DBG_waveinoutbase   22
    45 #define DBG_MAXFILES        23
     45#define DBG_waveoutflash    23
     46#define DBG_MAXFILES        24
    4647
    4748extern USHORT DbgEnabledWINMM[DBG_MAXFILES];
  • trunk/src/winmm/dbgwrap.cpp

    r9671 r21358  
    206206DEBUGWRAP12(waveOutUnprepareHeader)
    207207DEBUGWRAP12(waveOutWrite)
     208DEBUGWRAP0(ODIN_IsFlashAudioEnabled)
     209DEBUGWRAP4(ODIN_EnableFlashAudio)
    208210
    209211#undef DBG_LOCALLOG
  • trunk/src/winmm/initwinmm.cpp

    r10576 r21358  
    126126            // try to load the MDM library, not MMPM directly!!!
    127127            if (DosLoadModule(szError, sizeof(szError),
    128                               "MDM.DLL", &MMPMLibraryHandle) != NO_ERROR)
     128                              "MDM", &MMPMLibraryHandle) != NO_ERROR)
    129129            {
    130130                // this system has no MMPM :-(
  • trunk/src/winmm/wavein.cpp

    r10173 r21358  
    1414 */
    1515
    16 
    17 /****************************************************************************
    18  * Includes                                                                 *
    19  ****************************************************************************/
     16/******************************************************************************/
     17// Includes
     18/******************************************************************************/
    2019
    2120#include <os2win.h>
     
    3433#include "dbglocal.h"
    3534
    36 
    3735/******************************************************************************/
    3836/******************************************************************************/
     
    4745        return(WAVERR_BADFORMAT);
    4846
    49     if(fdwOpen & WAVE_FORMAT_QUERY)
    50     {
     47    if(fdwOpen & WAVE_FORMAT_QUERY) {
    5148        if(DartWaveIn::queryFormat(pwfx->wFormatTag, pwfx->nChannels, pwfx->nSamplesPerSec,
    5249                                   pwfx->wBitsPerSample) == TRUE)
    53         {
    5450             return(MMSYSERR_NOERROR);
    55         }
    56         else return(WAVERR_BADFORMAT);
     51
     52        return(WAVERR_BADFORMAT);
    5753    }
    5854
     
    6258    *phwi = (HWAVEOUT)new DartWaveIn(pwfx, fdwOpen, dwCallback, dwInstance);
    6359
    64     if(*phwi == NULL) {
     60    if(*phwi == NULL)
    6561        return(MMSYSERR_NODRIVER);
    66     }
    67 
    68     rc = ((DartWaveIn *)*phwi)->getError();
     62
     63    rc = ((DartWaveIn *)*phwi)->open();
    6964    if(rc != MMSYSERR_NOERROR) {
    7065        delete (DartWaveIn *)*phwi;
  • trunk/src/winmm/waveindart.cpp

    r10185 r21358  
    1010 * Project Odin Software License can be found in LICENSE.TXT
    1111 *
    12  *
    1312 */
    1413
    15 
    16 /****************************************************************************
    17  * Includes                                                                 *
    18  ****************************************************************************/
    19 
    20 
     14/******************************************************************************/
     15// Includes
     16/******************************************************************************/
    2117
    2218#define  INCL_BASE
     
    4137#endif
    4238
    43 #ifndef max
    44 #define max(a, b) ((a > b) ? a : b)
    45 #endif
    46 
    4739LONG APIENTRY WaveInHandler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags);
    4840
     41/******************************************************************************/
     42/******************************************************************************/
     43
    4944static BOOL fwaveInFixedBuffers = FALSE;
    5045
    51 //******************************************************************************
     46/******************************************************************************/
     47/******************************************************************************/
    5248// ODIN_waveInSetFixedBuffers
    5349//
    5450// Tell WINMM to use DART buffers of the same size as the first buffer delivered
    5551// by waveInAddBuffer
    56 //
    57 //******************************************************************************
     52
    5853void WIN32API ODIN_waveInSetFixedBuffers()
    5954{
     
    6560              : WaveInOut(pwfx, fdwOpen, nCallback, dwInstance)
    6661{
    67  MCI_GENERIC_PARMS  GenericParms;
    68  MCI_AMP_OPEN_PARMS AmpOpenParms;
    69  APIRET rc;
    70 
    71     fOverrun        = FALSE;
     62    DeviceId      = 0;
     63    ulBufSize     = DART_BUFSIZE_REC;
    7264    fMixerSetup   = FALSE;
     65    fOverrun      = FALSE;
     66    mixHandle     = 0;
     67    pmixReadProc  = NULL;
     68    MixBuffer     = NULL;
     69    BufferParms   = NULL;
     70
     71    dprintf(("DartWaveIn: samplerate %d, numChan %d bps %d (%d), format %x",
     72            SampleRate, nChannels, BitsPerSample, pwfx->nBlockAlign, pwfx->wFormatTag));
     73}
     74
     75/******************************************************************************/
     76/******************************************************************************/
     77MMRESULT DartWaveIn::open()
     78{
     79    MCI_AMP_OPEN_PARMS AmpOpenParms;
     80    MCI_GENERIC_PARMS  GenericParms = {0};
     81    MCI_MIXSETUP_PARMS MixSetupParms;
     82    APIRET rc;
    7383
    7484    MixBuffer     = (MCI_MIX_BUFFER *)malloc(PREFILLBUF_DART_REC*sizeof(MCI_MIX_BUFFER));
    75     MixSetupParms = (MCI_MIXSETUP_PARMS *)malloc(sizeof(MCI_MIXSETUP_PARMS));
    7685    BufferParms   = (MCI_BUFFER_PARMS *)malloc(sizeof(MCI_BUFFER_PARMS));
    77     if(!MixBuffer || !MixSetupParms || !BufferParms) {
     86    if(!MixBuffer || !BufferParms) {
    7887        dprintf(("ERROR: malloc failed!!"));
    79         ulError = MMSYSERR_NOMEM;
    80         return;
    81     }
    82 
    83     ulBufSize       = DART_BUFSIZE_REC;
    84 
    85     dprintf(("waveInOpen: samplerate %d, numChan %d bps %d (%d), format %x", SampleRate, nChannels, BitsPerSample, pwfx->nBlockAlign, pwfx->wFormatTag));
     88        return MMSYSERR_NOMEM;
     89    }
     90
    8691    // Setup the open structure, pass the playlist and tell MCI_OPEN to use it
    87     memset(&AmpOpenParms,0,sizeof(AmpOpenParms));
    88 
    89     AmpOpenParms.usDeviceID = ( USHORT ) 0;
    90     AmpOpenParms.pszDeviceType = ( PSZ ) MCI_DEVTYPE_AUDIO_AMPMIX;
    91 
    92     rc = mymciSendCommand(0, MCI_OPEN, MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
     92    memset(&AmpOpenParms, 0, sizeof(AmpOpenParms));
     93    AmpOpenParms.usDeviceID = 0;
     94    AmpOpenParms.pszDeviceType = (PSZ)MCI_DEVTYPE_AUDIO_AMPMIX;
     95
     96    rc = mymciSendCommand(0, MCI_OPEN,
     97                          MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
    9398                          (PVOID) &AmpOpenParms, 0);
    94     DeviceId = AmpOpenParms.usDeviceID;
    9599    if(rc) {
    96100        dprintf(("MCI_OPEN failed\n"));
    97101        mciError(rc);
    98         ulError = MMSYSERR_NODRIVER;
    99     }
    100     if(rc == 0) {
    101         //Grab exclusive rights to device instance (NOT entire device)
    102         GenericParms.hwndCallback = 0;  //Not needed, so set to 0
    103         rc = mymciSendCommand(DeviceId, MCI_ACQUIREDEVICE, MCI_EXCLUSIVE_INSTANCE,
    104                             (PVOID)&GenericParms, 0);
    105         if(rc) {
    106             dprintf(("MCI_ACQUIREDEVICE failed\n"));
    107             mciError(rc);
    108             ulError = MMSYSERR_NOTENABLED;
    109         }
    110     }
    111 
    112     if(!ulError)
    113         callback(WIM_OPEN, 0, 0);
     102        return MMSYSERR_NODRIVER;
     103    }
     104
     105    DeviceId = AmpOpenParms.usDeviceID;
     106
     107    //Grab exclusive rights to device instance (NOT entire device)
     108    rc = mymciSendCommand(DeviceId, MCI_ACQUIREDEVICE,
     109                          MCI_EXCLUSIVE_INSTANCE,
     110                          (PVOID)&GenericParms, 0);
     111    if(rc) {
     112        dprintf(("MCI_ACQUIREDEVICE failed\n"));
     113        mciError(rc);
     114        return MMSYSERR_NOTENABLED;
     115    }
     116
     117    dprintf(("device acquired\n"));
     118    dprintf(("bps %d, sps %d chan %d\n", BitsPerSample, SampleRate, nChannels));
     119
     120    // Set the MixSetupParms data structure
     121    memset(&MixSetupParms, 0, sizeof(MCI_MIXSETUP_PARMS));
     122    MixSetupParms.ulBitsPerSample = BitsPerSample;
     123    MixSetupParms.ulSamplesPerSec = SampleRate;
     124    MixSetupParms.ulFormatTag     = MCI_WAVE_FORMAT_PCM;
     125    MixSetupParms.ulChannels      = nChannels;
     126    MixSetupParms.ulFormatMode    = MCI_RECORD;
     127    MixSetupParms.ulDeviceType    = MCI_DEVTYPE_WAVEFORM_AUDIO;
     128    MixSetupParms.pmixEvent       = WaveInHandler;
     129
     130    rc = mymciSendCommand(DeviceId, MCI_MIXSETUP,
     131                          MCI_WAIT | MCI_MIXSETUP_INIT,
     132                          (PVOID)&MixSetupParms, 0);
     133    if ( rc != MCIERR_SUCCESS ) {
     134        mymciSendCommand(DeviceId, MCI_RELEASEDEVICE,
     135                         MCI_WAIT,
     136                         (PVOID)&GenericParms, 0);
     137        mciError(rc);
     138        return MMSYSERR_NOTSUPPORTED;
     139    }
     140
     141    // Save the mixer handle & the ptr to the read proc.
     142    mixHandle    = MixSetupParms.ulMixHandle;
     143    pmixReadProc = MixSetupParms.pmixRead;
     144
     145
     146    callback(WIM_OPEN, 0, 0);
     147
     148    return MMSYSERR_NOERROR;
    114149}
    115150/******************************************************************************/
     
    117152DartWaveIn::~DartWaveIn()
    118153{
    119    MCI_GENERIC_PARMS    GenericParms;
     154   MCI_GENERIC_PARMS    GenericParms = {0};
    120155
    121156   State = STATE_STOPPED;
    122157
    123     if(!ulError)
     158    if (DeviceId)
    124159    {
    125         // Generic parameters
    126         GenericParms.hwndCallback = 0;   //hwndFrame
    127 
    128160        // Stop recording.
    129         mymciSendCommand(DeviceId, MCI_STOP,MCI_WAIT, (PVOID)&GenericParms,0);
    130 
    131         mymciSendCommand(DeviceId,
    132                       MCI_BUFFER,
    133                       MCI_WAIT | MCI_DEALLOCATE_MEMORY,
    134                       (PVOID)&BufferParms,
    135                       0);
    136 
    137         // Generic parameters
    138         GenericParms.hwndCallback = 0;   //hwndFrame
     161        mymciSendCommand(DeviceId, MCI_STOP,
     162                         MCI_WAIT, (PVOID)&GenericParms, 0);
     163
     164        if (fMixerSetup)
     165            mymciSendCommand(DeviceId, MCI_BUFFER,
     166                             MCI_WAIT | MCI_DEALLOCATE_MEMORY,
     167                             (PVOID)&BufferParms, 0);
    139168
    140169        // Close the device
    141         mymciSendCommand(DeviceId, MCI_CLOSE, MCI_WAIT, (PVOID)&GenericParms, 0);
    142     }
    143     if(!ulError)
    144     {
     170        mymciSendCommand(DeviceId, MCI_CLOSE,
     171                         MCI_WAIT,
     172                         (PVOID)&GenericParms, 0);
     173
    145174        callback(WIM_CLOSE, 0, 0);
    146175    }
     
    148177    if(MixBuffer)
    149178        free(MixBuffer);
    150     if(MixSetupParms)
    151         free(MixSetupParms);
    152179    if(BufferParms)
    153180        free(BufferParms);
     
    180207    if(fMixerSetup == FALSE)
    181208    {
    182         dprintf(("device acquired\n"));
    183         /* Set the MixSetupParms data structure to match the loaded file.
    184          * This is a global that is used to setup the mixer.
    185          */
    186         memset(MixSetupParms, 0, sizeof( MCI_MIXSETUP_PARMS ) );
    187 
    188         MixSetupParms->ulBitsPerSample = BitsPerSample;
    189         MixSetupParms->ulSamplesPerSec = SampleRate;
    190         MixSetupParms->ulFormatTag     = MCI_WAVE_FORMAT_PCM;
    191         MixSetupParms->ulChannels      = nChannels;
    192 
    193         dprintf(("bps %d, sps %d chan %d\n", BitsPerSample, SampleRate, nChannels));
    194 
    195         /* Setup the mixer for recording of wave data
    196          */
    197         MixSetupParms->ulFormatMode = MCI_RECORD;
    198         MixSetupParms->ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
    199         MixSetupParms->pmixEvent    = WaveInHandler;
    200 
    201         rc = mymciSendCommand(DeviceId, MCI_MIXSETUP, MCI_WAIT | MCI_MIXSETUP_INIT,
    202                               (PVOID)MixSetupParms, 0);
    203 
    204         if ( rc != MCIERR_SUCCESS ) {
    205             mciError(rc);
    206             mymciSendCommand(DeviceId, MCI_RELEASEDEVICE, MCI_WAIT,
    207                            (PVOID)&GenericParms, 0);
    208             return(MMSYSERR_NOTSUPPORTED);
    209         }
    210 
    211209        /*
    212210         * Set up the BufferParms data structure and allocate
     
    227225            {
    228226                dprintf(("mix setup %d, %d\n", pwh->dwBufferLength, pwh->dwBufferLength));
    229    
    230227                ulBufSize = pwh->dwBufferLength/2;
    231228            }
     
    237234        else ulBufSize = minbufsize;
    238235
    239         MixSetupParms->ulBufferSize = ulBufSize;
    240 
    241236        BufferParms->ulNumBuffers = PREFILLBUF_DART_REC;
    242         BufferParms->ulBufferSize = MixSetupParms->ulBufferSize;
     237        BufferParms->ulBufferSize = ulBufSize;
    243238        BufferParms->pBufList     = MixBuffer;
    244239
     
    247242        }
    248243
    249         rc = mymciSendCommand(DeviceId,
    250                             MCI_BUFFER,
    251                             MCI_WAIT | MCI_ALLOCATE_MEMORY,
    252                             (PVOID)BufferParms,
    253                             0);
     244        rc = mymciSendCommand(DeviceId, MCI_BUFFER,
     245                              MCI_WAIT | MCI_ALLOCATE_MEMORY,
     246                              (PVOID)BufferParms, 0);
    254247
    255248        if(ULONG_LOWD(rc) != MCIERR_SUCCESS) {
    256249            mciError(rc);
    257             mymciSendCommand(DeviceId, MCI_RELEASEDEVICE, MCI_WAIT,
    258                           (PVOID)&GenericParms, 0);
    259             return(MMSYSERR_NOTSUPPORTED);
     250            mymciSendCommand(DeviceId, MCI_RELEASEDEVICE,
     251                             MCI_WAIT,
     252                             (PVOID)&GenericParms, 0);
     253            return MMSYSERR_NOTSUPPORTED;
    260254        }
    261255
     
    263257        //(until we really support the mixer extensions anyway)
    264258        /* Set the connector to 'microphone' */
    265         memset( &ConnectorParms, '\0', sizeof( MCI_CONNECTOR_PARMS ) );
     259        memset(&ConnectorParms, 0, sizeof(MCI_CONNECTOR_PARMS));
    266260        ConnectorParms.ulConnectorType = MCI_MICROPHONE_CONNECTOR;
    267         rc = mymciSendCommand(DeviceId, MCI_CONNECTOR, MCI_WAIT |
    268                               MCI_ENABLE_CONNECTOR | MCI_CONNECTOR_TYPE,
    269                               ( PVOID ) &ConnectorParms, 0 );
     261        rc = mymciSendCommand(DeviceId, MCI_CONNECTOR,
     262                              MCI_WAIT | MCI_ENABLE_CONNECTOR | MCI_CONNECTOR_TYPE,
     263                              (PVOID)&ConnectorParms, 0 );
    270264
    271265        /* Allow the user to hear what is being recorded
    272266         * by turning the monitor on
    273267         */
    274         memset( &AmpSetParms, '\0', sizeof( MCI_AMP_SET_PARMS ) );
     268        memset(&AmpSetParms, 0, sizeof( MCI_AMP_SET_PARMS ) );
    275269        AmpSetParms.ulItem = MCI_AMP_SET_MONITOR;
    276         rc = mymciSendCommand(DeviceId,
    277                             MCI_SET,
    278                             MCI_WAIT | MCI_SET_ON | MCI_SET_ITEM,
    279                             ( PVOID ) &AmpSetParms,
    280                             0 );
     270        rc = mymciSendCommand(DeviceId, MCI_SET,
     271                              MCI_WAIT | MCI_SET_ON | MCI_SET_ITEM,
     272                              (PVOID)&AmpSetParms, 0);
    281273
    282274        wmutex.enter();
     
    284276    }
    285277
    286     for(i=0;i<PREFILLBUF_DART_REC;i++) {
     278    for(i=0; i< PREFILLBUF_DART_REC; i++) {
    287279        memset(MixBuffer[i].pBuffer, 0, MixBuffer[i].ulBufferLength);
    288280    }
    289281    dprintf(("Dart opened, bufsize = %d\n", MixBuffer[0].ulBufferLength));
    290282
    291     dprintf(("MixSetupParms = %X\n", MixSetupParms));
    292283    State    = STATE_RECORDING;
    293284    fOverrun = FALSE;
     
    298289    // Start recording.
    299290    USHORT selTIB = RestoreOS2FS(); // save current FS selector
    300     MixSetupParms->pmixRead(MixSetupParms->ulMixHandle, &MixBuffer[0], PREFILLBUF_DART_REC);
     291    pmixReadProc(mixHandle, &MixBuffer[0], PREFILLBUF_DART_REC);
    301292    SetFS(selTIB);           // switch back to the saved FS selector
    302293
     
    506497/******************************************************************************/
    507498/******************************************************************************/
    508 void DartWaveIn::mciError(ULONG ulError)
     499void DartWaveIn::mciError(ULONG rc)
    509500{
    510501#ifdef DEBUG
    511502    char szError[256] = "";
    512503
    513     mymciGetErrorString(ulError, szError, sizeof(szError));
     504    mymciGetErrorString(rc, szError, sizeof(szError));
    514505    dprintf(("WINMM: DartWaveIn: %s\n", szError));
    515506#endif
     
    586577    // MCI_MIXSETUP_PARMS->pMixWrite does alter FS: selector!
    587578    USHORT selTIB = RestoreOS2FS(); // save current FS selector
    588     MixSetupParms->pmixRead(MixSetupParms->ulMixHandle, pBuffer, 1);
     579    pmixReadProc(mixHandle, pBuffer, 1);
    589580    SetFS(selTIB);           // switch back to the saved FS selector
    590581}
  • trunk/src/winmm/waveindart.h

    r5358 r21358  
    66 * Project Odin Software License can be found in LICENSE.TXT
    77 */
     8
    89#ifndef __DWAVEIN_H__
    910#define __DWAVEIN_H__
     
    2728#endif
    2829
     30// this should be defined in some #included .h file, but it isn't
     31typedef LONG (APIENTRY MIXERPROC)(ULONG ulHandle, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags);
     32
    2933class DartWaveIn : public WaveInOut
    3034{
    3135public:
    32               DartWaveIn(LPWAVEFORMATEX pwfx, DWORD fdwOpen, ULONG nCallback, ULONG dwInstance);
    33      virtual ~DartWaveIn();
     36                     DartWaveIn(LPWAVEFORMATEX pwfx, DWORD fdwOpen,
     37                                ULONG nCallback, ULONG dwInstance);
     38  virtual            ~DartWaveIn();
    3439
    35      MMRESULT addBuffer(LPWAVEHDR pwh, UINT cbwh);
    36      MMRESULT start();
    37      MMRESULT stop();
    38      int      getState()        { return State; };
    39      MMRESULT reset();
    40      ULONG    getPosition();
     40          MMRESULT   open();
     41          MMRESULT   addBuffer(LPWAVEHDR pwh, UINT cbwh);
     42          MMRESULT   start();
     43          MMRESULT   stop();
     44          MMRESULT  reset();
     45          ULONG      getPosition();
    4146
    42 
    43   static int  getNumDevices();
    44 
    45   static BOOL queryFormat(ULONG formatTag, ULONG nChannels,
    46                           ULONG nSamplesPerSec, ULONG sampleSize);
     47   static int        getNumDevices();
     48   static BOOL       queryFormat(ULONG formatTag, ULONG nChannels,
     49                                 ULONG nSamplesPerSec, ULONG sampleSize);
    4750
    4851protected:
    49   static void mciError(ULONG ulError);
    50          void handler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags);
     52   static void       mciError(ULONG rc);
     53          void       handler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer,
     54                             ULONG ulFlags);
    5155
    5256private:
    53         USHORT DeviceId;
    54         ULONG  ulBufferCount;             /* Current file buffer     */
    55         ULONG  ulBufSize;
    56 
    57     MCI_MIX_BUFFER     *MixBuffer;          /* Device buffers          */
    58     MCI_MIXSETUP_PARMS *MixSetupParms;          /* Mixer parameters        */
    59     MCI_BUFFER_PARMS   *BufferParms;                /* Device buffer parms     */
    60 
    61 
    62     BOOL      fMixerSetup;
    63     BOOL      fOverrun;
     57          USHORT     DeviceId;
     58          ULONG      ulBufSize;
     59          BOOL       fMixerSetup;
     60          BOOL       fOverrun;
     61          ULONG      mixHandle;
     62         MIXERPROC * pmixReadProc;
     63    MCI_MIX_BUFFER * MixBuffer;
     64  MCI_BUFFER_PARMS * BufferParms;
    6465
    6566#ifndef _OS2WIN_H
    66     friend    LONG APIENTRY WaveInHandler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags);
     67   friend LONG APIENTRY WaveInHandler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer,
     68                                      ULONG ulFlags);
    6769#endif
    6870};
  • trunk/src/winmm/waveinoutbase.cpp

    r10269 r21358  
    1212 */
    1313
    14 
    15 /****************************************************************************
    16  * Includes                                                                 *
    17  ****************************************************************************/
    18 
    19 
     14/******************************************************************************/
     15// Includes
     16/******************************************************************************/
    2017
    2118#define  INCL_BASE
     
    3532#include "dbglocal.h"
    3633
    37 VMutex wavemutex;
     34/******************************************************************************/
     35/******************************************************************************/
     36
     37VMutex      wavemutex;
     38WaveInOut * WaveInOut::head = NULL;
    3839
    3940/******************************************************************************/
     
    4142WaveInOut::WaveInOut(LPWAVEFORMATEX pwfx, ULONG fdwOpen, ULONG nCallback, ULONG dwInstance)
    4243{
    43     next            = NULL;
    44     wavehdr         = NULL;
    45     curhdr          = NULL;
    46     ulError         = 0;
    47     State           = STATE_STOPPED;
    48     queuedbuffers   = 0;
    49 
    50     BitsPerSample   = pwfx->wBitsPerSample;
    51     SampleRate      = pwfx->nSamplesPerSec;
    52     this->nChannels = pwfx->nChannels;
     44    SampleRate    = pwfx->nSamplesPerSec;
     45    BitsPerSample = pwfx->wBitsPerSample;
     46    nChannels     = pwfx->nChannels;
     47    OpenFlags     = fdwOpen;
     48    Callback      = nCallback;
     49    Instance      = dwInstance;
     50    State         = STATE_STOPPED;
     51    queuedbuffers = 0;
     52    wavehdr       = NULL;
     53    next          = NULL;
    5354
    5455    dprintf(("WaveInOutOpen: samplerate %d, numChan %d bps %d (%d), format %x", SampleRate, nChannels, BitsPerSample, pwfx->nBlockAlign, pwfx->wFormatTag));
    55 
    56     State    = STATE_STOPPED;
    5756
    5857    wavemutex.enter();
     
    7069    }
    7170    wavemutex.leave();
    72 
    73     this->fdwOpen = fdwOpen;
    74     dwCallback    = nCallback;
    75     this->dwInstance = dwInstance;
    7671}
    7772/******************************************************************************/
     
    10196{
    10297    dprintf(("WINMM:WaveInOut::callback type %x, callback 0x%x (HDRVR h=%08xh, UINT uMessage=%08xh, DWORD dwUser=%08xh, DWORD dw1=%08xh, DWORD dw2=%08xh)",
    103              fdwOpen, dwCallback, this, uMessage, dwInstance, dw1, dw2));
     98             OpenFlags, Callback, this, uMessage, Instance, dw1, dw2));
    10499
    105     switch(fdwOpen & CALLBACK_TYPEMASK) {
     100    switch(OpenFlags & CALLBACK_TYPEMASK) {
    106101    case CALLBACK_WINDOW:
    107         PostMessageA((HWND)dwCallback, uMessage, (WPARAM)this, dw1);
     102        PostMessageA((HWND)Callback, uMessage, (WPARAM)this, dw1);
    108103        break;
    109104
    110105    case CALLBACK_TASK: // == CALLBACK_THREAD
    111         PostThreadMessageA(dwCallback, uMessage, (WPARAM)this, dw1);
     106        PostThreadMessageA(Callback, uMessage, (WPARAM)this, dw1);
    112107        break;
    113108
     
    116111        USHORT selTIB = GetFS(); // save current FS selector
    117112        USHORT selCallback;
    118         LPDRVCALLBACK mthdCallback = (LPDRVCALLBACK)dwCallback;
     113        LPDRVCALLBACK mthdCallback = (LPDRVCALLBACK)Callback;
    119114
    120115        if(selTIB == SELECTOR_OS2_FS) {
     
    130125            //@@@PH 1999/12/28 Shockwave Flash seem to make assumptions on a
    131126            // specific stack layout. Do we have the correct calling convention here?
    132             mthdCallback((HDRVR)this, uMessage, dwInstance, dw1, dw2);
     127            mthdCallback((HDRVR)this, uMessage, Instance, dw1, dw2);
    133128            SetFS(selTIB);           // switch back to the saved FS selector
    134129        }
     
    140135
    141136    case CALLBACK_EVENT:
    142         SetEvent((HANDLE)dwCallback);
     137        SetEvent((HANDLE)Callback);
    143138        break;
    144139
     
    147142
    148143    default:
    149         dprintf(("WARNING: Unknown callback type %x %x", fdwOpen, dwCallback));
     144        dprintf(("WARNING: Unknown callback type %x %x", OpenFlags, Callback));
    150145        break;
    151146    } //switch
     
    187182/******************************************************************************/
    188183/******************************************************************************/
    189 WaveInOut *WaveInOut::head = NULL;
    190184
  • trunk/src/winmm/waveinoutbase.h

    r9671 r21358  
    88 * Project Odin Software License can be found in LICENSE.TXT
    99 */
     10
    1011#ifndef __WAVEINOUTBASE_H__
    1112#define __WAVEINOUTBASE_H__
     
    2526{
    2627public:
    27               WaveInOut(LPWAVEFORMATEX pwfx, DWORD fdwOpen, ULONG nCallback, ULONG dwInstance);
    28      virtual ~WaveInOut();
     28                    WaveInOut(LPWAVEFORMATEX pwfx, DWORD fdwOpen,
     29                              ULONG nCallback, ULONG dwInstance);
     30  virtual           ~WaveInOut();
    2931
    30               int      getState()               { return State; };
    31               MMRESULT getError()               { return ulError; };
    32               ULONG    getSampleRate()          { return SampleRate; };
    33               ULONG    getBitsPerSample()       { return BitsPerSample; };
    34               ULONG    getnumChannels()         { return nChannels; };
    35               ULONG    getAvgBytesPerSecond()   { return (BitsPerSample/8) * nChannels * SampleRate; };
     32          int       getState()               { return State; };
     33          ULONG     getSampleRate()          { return SampleRate; };
     34          ULONG     getBitsPerSample()       { return BitsPerSample; };
     35          ULONG     getnumChannels()         { return nChannels; };
     36          ULONG     getAvgBytesPerSecond()   { return (BitsPerSample/8) * nChannels * SampleRate; };
    3637
    37   static BOOL find(WaveInOut *wave);
    38   static void shutdown();
     38   static BOOL      find(WaveInOut *wave);
     39   static void      shutdown();
    3940
    4041protected:
     42          void      callback(UINT uMessage, DWORD dw1, DWORD dw2);
    4143
    42     ULONG       ulError, State;
    43 
    44     int         SampleRate;
    45     int         BitsPerSample;
    46     int         nChannels;
    47 
    48     int         queuedbuffers;
    49 
    50     // callback interface
    51     void        callback(UINT uMessage, DWORD dw1, DWORD dw2);
    52 
    53     DWORD       fdwOpen;
    54     DWORD       dwCallback;
    55     DWORD       dwInstance;
    56 
    57     WAVEHDR    *wavehdr,
    58                *curhdr;
    59 
    60          VMutex wmutex;
     44          int       SampleRate;
     45          int       BitsPerSample;
     46          int       nChannels;
     47          DWORD     OpenFlags;
     48          DWORD     Callback;
     49          DWORD     Instance;
     50          ULONG     State;
     51          int       queuedbuffers;
     52          WAVEHDR * wavehdr;
     53          VMutex    wmutex;
    6154
    6255private:
    63                                           // Linked list management
    64                 WaveInOut *next;          // Next wave class
    65     static      WaveInOut *head;          // List of wave classes
     56 static WaveInOut * head;          // List of wave classes
     57        WaveInOut * next;          // Next wave class
    6658};
    6759
  • trunk/src/winmm/waveout.cpp

    r10173 r21358  
    11/* $Id: waveout.cpp,v 1.27 2003-07-16 15:47:24 sandervl Exp $ */
    2 //#undef DEBUG
     2
    33/*
    44 * Wave out MM apis
     
    1313 */
    1414
    15 
    16 /****************************************************************************
    17  * Includes                                                                 *
    18  ****************************************************************************/
     15/******************************************************************************/
     16// Includes
     17/******************************************************************************/
    1918
    2019#include <os2win.h>
     
    2928#include "waveoutdart.h"
    3029#include "waveoutdaud.h"
     30#include "waveoutflash.h"
    3131#include "misc.h"
    3232#include "winmm.h"
     
    3636#include "dbglocal.h"
    3737
    38 
    3938/******************************************************************************/
    4039/******************************************************************************/
     
    4241                            DWORD dwCallback, DWORD dwInstance, DWORD fdwOpen)
    4342{
    44   MMRESULT rc;
    45 
    46     if(fMMPMAvailable == FALSE) return MMSYSERR_NODRIVER;
    47 
    48     if(pwfx == NULL)
     43    MMRESULT rc;
     44
     45    if (fMMPMAvailable == FALSE)
     46        return MMSYSERR_NODRIVER;
     47
     48    if (pwfx == NULL)
    4949        return(WAVERR_BADFORMAT);
    5050
    51     if(fdwOpen & WAVE_FORMAT_QUERY)
    52     {
    53         if(DartWaveOut::queryFormat(pwfx->wFormatTag, pwfx->nChannels, pwfx->nSamplesPerSec,
    54                                     pwfx->wBitsPerSample) == TRUE) {
    55                 return(MMSYSERR_NOERROR);
    56         }
    57         else    return(WAVERR_BADFORMAT);
    58     }
    59 
    60     if(phwo == NULL)
     51    if (fdwOpen & WAVE_FORMAT_QUERY) {
     52        if (WaveOut::queryFormat(pwfx->wFormatTag, pwfx->nChannels,
     53                                pwfx->nSamplesPerSec,
     54                                 pwfx->wBitsPerSample) == TRUE) {
     55            return (MMSYSERR_NOERROR);
     56        }
     57        return (WAVERR_BADFORMAT);
     58    }
     59
     60    if (phwo == NULL)
    6161        return(MMSYSERR_INVALPARAM);
    6262
    63     if(DAudioWaveOut::isDirectAudioAvailable()) {
    64          *phwo = (HWAVEOUT)new DAudioWaveOut(pwfx, fdwOpen, dwCallback, dwInstance);
    65     }
    66     else *phwo = (HWAVEOUT)new DartWaveOut(pwfx, fdwOpen, dwCallback, dwInstance);
    67 
    68     if(*phwo == NULL) {
     63    if (ODIN_IsFlashAudioEnabled())
     64        *phwo = (HWAVEOUT)new FlashWaveOut(pwfx, fdwOpen, dwCallback, dwInstance);
     65    else
     66    if (DAudioWaveOut::isDirectAudioAvailable())
     67        *phwo = (HWAVEOUT)new DAudioWaveOut(pwfx, fdwOpen, dwCallback, dwInstance);
     68    else
     69        *phwo = (HWAVEOUT)new DartWaveOut(pwfx, fdwOpen, dwCallback, dwInstance);
     70
     71    if(*phwo == NULL)
    6972        return(MMSYSERR_NODRIVER);
    70     }
    71 
    72     rc = ((WaveOut *)*phwo)->getError();
    73     if(rc != MMSYSERR_NOERROR) {
     73
     74    rc = ((WaveOut *)*phwo)->open();
     75    if (rc != MMSYSERR_NOERROR)
    7476        delete (WaveOut *)*phwo;
    75         return(rc);
    76     }
    77     return(MMSYSERR_NOERROR);
     77
     78    return rc;
    7879}
    7980/******************************************************************************/
  • trunk/src/winmm/waveoutbase.cpp

    r7196 r21358  
    1414 */
    1515
    16 
    17 /****************************************************************************
    18  * Includes                                                                 *
    19  ****************************************************************************/
    20 
    21 
     16/******************************************************************************/
     17// Includes
     18/******************************************************************************/
    2219
    2320#define  INCL_BASE
     
    3835#include "dbglocal.h"
    3936
    40 #ifndef min
    41 #define min(a, b) ((a > b) ? b : a)
    42 #endif
     37/******************************************************************************/
     38/******************************************************************************/
    4339
    44 #ifndef max
    45 #define max(a, b) ((a > b) ? a : b)
    46 #endif
     40ULONG WaveOut::defvolume = 0xFFFFFFFF;
    4741
    48 //TODO: mulaw, alaw & adpcm
    4942/******************************************************************************/
    5043/******************************************************************************/
     
    5245           : WaveInOut(pwfx, fdwOpen, nCallback, dwInstance)
    5346{
    54     bytesPlayed = bytesCopied = bytesReturned = 0;
    55 
    5647    volume = defvolume;
    5748
     
    6758int WaveOut::getNumDevices()
    6859{
    69  MCI_GENERIC_PARMS  GenericParms;
    70  MCI_AMP_OPEN_PARMS AmpOpenParms;
    71  APIRET rc;
     60    MCI_AMP_OPEN_PARMS AmpOpenParms;
     61    MCI_GENERIC_PARMS  GenericParms = {0};
     62    APIRET rc;
    7263
    73    // Setup the open structure, pass the playlist and tell MCI_OPEN to use it
    74    memset(&AmpOpenParms,0,sizeof(AmpOpenParms));
     64    // Try to open the device to see if it's there
     65    memset(&AmpOpenParms, 0, sizeof(AmpOpenParms));
     66    AmpOpenParms.usDeviceID = 0;
     67    AmpOpenParms.pszDeviceType = (PSZ)MCI_DEVTYPE_AUDIO_AMPMIX;
    7568
    76    AmpOpenParms.usDeviceID = ( USHORT ) 0;
    77    AmpOpenParms.pszDeviceType = ( PSZ ) MCI_DEVTYPE_AUDIO_AMPMIX;
     69    rc = mymciSendCommand(0, MCI_OPEN,
     70                          MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
     71                          (PVOID) &AmpOpenParms, 0);
    7872
    79    rc = mymciSendCommand(0, MCI_OPEN,
    80                        MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
    81                        (PVOID) &AmpOpenParms,
    82                        0);
     73    if (LOUSHORT(rc) != MCIERR_SUCCESS)
     74        return 0;
    8375
    84    if(rc) {
    85         return 0; //no devices present
    86    }
     76    // Close the device
     77    mymciSendCommand(AmpOpenParms.usDeviceID, MCI_CLOSE,
     78                     MCI_WAIT,
     79                     (PVOID)&GenericParms, 0);
    8780
    88    // Generic parameters
    89    GenericParms.hwndCallback = 0;   //hwndFrame
    90 
    91    // Close the device
    92    mymciSendCommand(AmpOpenParms.usDeviceID, MCI_CLOSE, MCI_WAIT, (PVOID)&GenericParms, 0);
    93 
    94    return 1;
     81    return 1;
    9582}
    9683/******************************************************************************/
    97 //Called if waveOutSetVolume is called by the application with waveout handle NULL
    98 //Sets the default volume of each waveout stream (until it's volume is changed
    99 //with an appropriate waveOutSetVolume call)
     84/******************************************************************************/
     85BOOL WaveOut::queryFormat(ULONG formatTag, ULONG nChannels,
     86                          ULONG nSamplesPerSec, ULONG wBitsPerSample)
     87{
     88    APIRET  rc;
     89    BOOL    winrc = TRUE;
     90    MCI_OPEN_PARMS            OpenParms;
     91    MCI_WAVE_GETDEVCAPS_PARMS DevCapsParms;
     92    MCI_GENERIC_PARMS         GenericParms = {0};
     93#ifdef DEBUG
     94    char szError[64] = "";
     95#endif
     96
     97    dprintf(("WINMM: WaveOut::queryFormat %x srate=%d, nchan=%d, bps=%d", formatTag, nSamplesPerSec, nChannels, wBitsPerSample));
     98
     99    // Open the device.
     100    memset(&OpenParms, 0, sizeof(OpenParms));
     101    OpenParms.pszDeviceType = (PSZ)MCI_DEVTYPE_WAVEFORM_AUDIO;
     102
     103    rc = mymciSendCommand(0, MCI_OPEN,
     104                          MCI_WAIT | MCI_OPEN_TYPE_ID,
     105                          (PVOID)&OpenParms, 0);
     106    if (LOUSHORT(rc) != MCIERR_SUCCESS) {
     107        #ifdef DEBUG
     108        mymciGetErrorString(rc, szError, sizeof(szError));
     109        dprintf(("WINMM: WaveOut::queryFormat: %s\n", szError));
     110        #endif
     111        return FALSE;
     112    }
     113
     114    // See if the device can handle the specified format.
     115    memset(&DevCapsParms, 0, sizeof(MCI_WAVE_GETDEVCAPS_PARMS));
     116    DevCapsParms.ulBitsPerSample = wBitsPerSample;
     117    DevCapsParms.ulFormatTag     = DATATYPE_WAVEFORM;
     118    DevCapsParms.ulSamplesPerSec = nSamplesPerSec;
     119    DevCapsParms.ulChannels      = nChannels;
     120    DevCapsParms.ulFormatMode    = MCI_PLAY;
     121    DevCapsParms.ulItem          = MCI_GETDEVCAPS_WAVE_FORMAT;
     122
     123    rc = mymciSendCommand(OpenParms.usDeviceID, MCI_GETDEVCAPS,
     124                          MCI_WAIT | MCI_GETDEVCAPS_EXTENDED | MCI_GETDEVCAPS_ITEM,
     125                          (PVOID)&DevCapsParms, 0);
     126    if (LOUSHORT(rc) != MCIERR_SUCCESS) {
     127        #ifdef DEBUG
     128        mymciGetErrorString(rc, szError, sizeof(szError));
     129        dprintf(("WINMM: WaveOut::queryFormat: %s\n", szError));
     130        #endif
     131        winrc = FALSE;
     132    }
     133
     134    // Close the device
     135    rc = mymciSendCommand(OpenParms.usDeviceID, MCI_CLOSE,
     136                          MCI_WAIT, (PVOID)&GenericParms, 0);
     137    if (LOUSHORT(rc) != MCIERR_SUCCESS) {
     138        #ifdef DEBUG
     139        mymciGetErrorString(rc, szError, sizeof(szError));
     140        dprintf(("WINMM: WaveOut::queryFormat: %s\n", szError));
     141        #endif
     142        winrc = FALSE;
     143    }
     144
     145    return winrc;
     146}
     147/******************************************************************************/
     148// Called if waveOutSetVolume is called by the application with waveout handle NULL
     149// Sets the default volume of each waveout stream (until it's volume is changed
     150// with an appropriate waveOutSetVolume call)
    100151/******************************************************************************/
    101152void WaveOut::setDefaultVolume(ULONG volume)
     
    112163/******************************************************************************/
    113164/******************************************************************************/
    114 ULONG WaveOut::defvolume = 0xFFFFFFFF;
    115165
  • trunk/src/winmm/waveoutbase.h

    r8568 r21358  
    88 * Project Odin Software License can be found in LICENSE.TXT
    99 */
     10
    1011#ifndef __DWAVEOUTBASE_H__
    1112#define __DWAVEOUTBASE_H__
    1213
    1314#include "waveinoutbase.h"
    14 
    1515#ifdef OS2_ONLY
    1616#include "winmmtype.h"
     
    2121{
    2222public:
    23               WaveOut(LPWAVEFORMATEX pwfx, DWORD fdwOpen, ULONG nCallback, ULONG dwInstance);
    24      virtual ~WaveOut();
     23          WaveOut(LPWAVEFORMATEX pwfx, DWORD fdwOpen, ULONG nCallback, ULONG dwInstance);
     24  virtual ~WaveOut();
    2525
    26      virtual  MMRESULT write(LPWAVEHDR pwh, UINT cbwh) = 0;
    27      virtual  MMRESULT pause() = 0;
    28      virtual  MMRESULT stop() = 0;
    29      virtual  MMRESULT resume() = 0;
    30      virtual  MMRESULT reset() = 0;
    31      virtual  ULONG    getPosition() = 0;
    32      virtual  MMRESULT setVolume(ULONG ulVol) = 0;
    33               ULONG    getVolume()              { return volume; };
     26  virtual MMRESULT  open() = 0;
     27  virtual MMRESULT  write(LPWAVEHDR pwh, UINT cbwh) = 0;
     28  virtual MMRESULT  pause() = 0;
     29  virtual MMRESULT  stop() = 0;
     30  virtual MMRESULT  resume() = 0;
     31  virtual MMRESULT  reset() = 0;
     32  virtual ULONG     getPosition() = 0;
     33  virtual MMRESULT  setVolume(ULONG ulVol) = 0;
    3434
    35   static int  getNumDevices();
    36 
    37   static void setDefaultVolume(ULONG volume);
    38  static DWORD getDefaultVolume();
     35   static int       getNumDevices();
     36   static BOOL      queryFormat(ULONG formatTag, ULONG nChannels,
     37                                ULONG nSamplesPerSec, ULONG sampleSize);
     38   static void      setDefaultVolume(ULONG volume);
     39   static DWORD     getDefaultVolume();
     40          ULONG     getVolume() { return volume; };
    3941
    4042protected:
    41 
    42     ULONG       bytesPlayed, bytesCopied, bytesReturned;
    43     ULONG       volume;                        // Volume state
    44 
    45     static      ULONG    defvolume;  //default volume for streams (if waveOutSetVolume called with NULL stream)
    46 
    47 private:
    48 
     43          ULONG     volume;
     44   static ULONG     defvolume;  // default volume for streams
     45                                // (if waveOutSetVolume called with NULL stream)
    4946};
    5047
  • trunk/src/winmm/waveoutdart.cpp

    r10525 r21358  
    1515 */
    1616
    17 
    18 /****************************************************************************
    19  * Includes                                                                 *
    20  ****************************************************************************/
    21 
    22 
     17/******************************************************************************/
     18// Includes
     19/******************************************************************************/
    2320
    2421#define  INCL_BASE
     
    4138#include "dbglocal.h"
    4239
     40/******************************************************************************/
     41
    4342#ifndef min
    4443#define min(a, b) ((a > b) ? b : a)
     
    5150LONG APIENTRY WaveOutHandler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags);
    5251
    53 static BOOL fFixedWaveBufferSize = FALSE;
     52#define DART_BUFCNT     64
     53#define DART_BUFSIZE    4096
     54
     55/******************************************************************************/
    5456
    5557//#define DEBUG_DUMP_PCM
     
    6769#endif
    6870
    69 //******************************************************************************
     71/******************************************************************************/
     72
     73static BOOL fFixedWaveBufferSize = FALSE;
     74
     75/******************************************************************************/
    7076// ODIN_waveOutSetFixedBuffers
    7177//
     
    7682//       purpose solution.
    7783//
    78 //******************************************************************************
     84/******************************************************************************/
     85
    7986void WIN32API ODIN_waveOutSetFixedBuffers()
    8087{
    8188    fFixedWaveBufferSize = TRUE;
    8289}
    83 /******************************************************************************/
    84 /******************************************************************************/
     90
     91/******************************************************************************/
     92/******************************************************************************/
     93
    8594DartWaveOut::DartWaveOut(LPWAVEFORMATEX pwfx, ULONG fdwOpen, ULONG nCallback, ULONG dwInstance)
    8695                  : WaveOut(pwfx, fdwOpen, nCallback, dwInstance)
    8796{
    88     MCI_GENERIC_PARMS  GenericParms;
     97    DeviceId        = 0;
     98    fMixerSetup     = FALSE;
     99    fUnderrun       = FALSE;
     100    curFillBuf      = 0;
     101    curPlayBuf      = 0;
     102    curFillPos      = 0;
     103    curPlayPos      = 0;
     104    ulBufSize       = DART_BUFSIZE;
     105    ulBufCount      = DART_BUFCNT;
     106    bytesPlayed     = 0;
     107    bytesCopied     = 0;
     108    bytesReturned   = 0;
     109    ulUnderrunBase  = 0;
     110    mixHandle       = 0;
     111    curhdr          = NULL;
     112    pmixWriteProc   = 0;
     113    MixBuffer       = 0;
     114    BufferParms     = 0;
     115}
     116
     117/******************************************************************************/
     118/******************************************************************************/
     119
     120DartWaveOut::~DartWaveOut()
     121{
     122    MCI_GENERIC_PARMS GenericParms = {0};
     123
     124    State = STATE_STOPPED;
     125
     126#ifdef DEBUG_DUMP_PCM
     127    if (pcmfile) fclose(pcmfile);
     128#endif
     129
     130    if (DeviceId) {
     131        // Stop the playback.
     132        mymciSendCommand(DeviceId, MCI_STOP,
     133                         MCI_WAIT,
     134                         (PVOID)&GenericParms,0);
     135
     136        if (fMixerSetup)
     137            mymciSendCommand(DeviceId, MCI_BUFFER,
     138                             MCI_WAIT | MCI_DEALLOCATE_MEMORY,
     139                             (PVOID)&BufferParms, 0);
     140
     141        // Close the device
     142        mymciSendCommand(DeviceId, MCI_CLOSE,
     143                         MCI_WAIT,
     144                         (PVOID)&GenericParms, 0);
     145
     146        callback(WOM_CLOSE, 0, 0);
     147    }
     148
     149    if (MixBuffer)
     150        free(MixBuffer);
     151    if (BufferParms)
     152        free(BufferParms);
     153}
     154
     155/******************************************************************************/
     156/******************************************************************************/
     157
     158MMRESULT DartWaveOut::open()
     159{
    89160    MCI_AMP_OPEN_PARMS AmpOpenParms;
     161    MCI_GENERIC_PARMS  GenericParms = {0};
     162    MCI_MIXSETUP_PARMS MixSetupParms;
    90163    APIRET rc;
    91164
    92     curPlayBuf = curFillBuf = curFillPos = curPlayPos = 0;
    93     fMixerSetup   = FALSE;
    94     fUnderrun     = FALSE;
    95     ulUnderrunBase= 0;
    96 
    97     ulBufSize     = DART_BUFSIZE;
    98 
    99     MixBuffer     = (MCI_MIX_BUFFER *)malloc(PREFILLBUF_DART*sizeof(MCI_MIX_BUFFER));
    100     MixSetupParms = (MCI_MIXSETUP_PARMS *)malloc(sizeof(MCI_MIXSETUP_PARMS));
     165    MixBuffer     = (MCI_MIX_BUFFER *)malloc(ulBufCount*sizeof(MCI_MIX_BUFFER));
    101166    BufferParms   = (MCI_BUFFER_PARMS *)malloc(sizeof(MCI_BUFFER_PARMS));
    102     if(!MixBuffer || !MixSetupParms || !BufferParms) {
     167    if (!MixBuffer || !BufferParms) {
    103168        dprintf(("ERROR: malloc failed!!"));
    104         ulError = MMSYSERR_NOMEM;
    105         return;
    106     }
    107 
    108     // Setup the open structure, pass the playlist and tell MCI_OPEN to use it
    109     memset(&AmpOpenParms,0,sizeof(AmpOpenParms));
    110 
    111     AmpOpenParms.usDeviceID = ( USHORT ) 0;
    112     AmpOpenParms.pszDeviceType = ( PSZ ) MCI_DEVTYPE_AUDIO_AMPMIX;
    113 
    114     rc = mymciSendCommand(0, MCI_OPEN, MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
    115                        (PVOID) &AmpOpenParms, 0);
    116 
    117     DeviceId = AmpOpenParms.usDeviceID;
    118     if(rc) {
     169        return MMSYSERR_NOMEM;
     170    }
     171
     172    // Setup the open structure, then open the device
     173    memset(&AmpOpenParms, 0, sizeof(AmpOpenParms));
     174    AmpOpenParms.usDeviceID = 0;
     175    AmpOpenParms.pszDeviceType = (PSZ)MCI_DEVTYPE_AUDIO_AMPMIX;
     176
     177    rc = mymciSendCommand(0, MCI_OPEN,
     178                          MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
     179                          (PVOID)&AmpOpenParms, 0);
     180    if (LOUSHORT(rc) != MCIERR_SUCCESS) {
    119181        dprintf(("MCI_OPEN failed\n"));
    120182        mciError(rc);
    121         ulError = MMSYSERR_NODRIVER;
    122     }
    123     if(rc == 0) {
    124         //Grab exclusive rights to device instance (NOT entire device)
    125         GenericParms.hwndCallback = 0;  //Not needed, so set to 0
    126         rc = mymciSendCommand(DeviceId, MCI_ACQUIREDEVICE, MCI_EXCLUSIVE_INSTANCE,
    127                             (PVOID)&GenericParms, 0);
    128         if(rc) {
    129             dprintf(("MCI_ACQUIREDEVICE failed\n"));
    130             mciError(rc);
    131             ulError = MMSYSERR_NOTENABLED;
     183        return MMSYSERR_NODRIVER;
     184    }
     185    DeviceId = AmpOpenParms.usDeviceID;
     186
     187    // Grab exclusive rights to device instance (NOT entire device)
     188    rc = mymciSendCommand(DeviceId, MCI_ACQUIREDEVICE,
     189                          MCI_EXCLUSIVE_INSTANCE,
     190                          (PVOID)&GenericParms, 0);
     191    if (LOUSHORT(rc) != MCIERR_SUCCESS) {
     192        dprintf(("MCI_ACQUIREDEVICE failed\n"));
     193        mciError(rc);
     194        return MMSYSERR_NOTENABLED;
     195    }
     196    dprintf(("device acquired\n"));
     197    dprintf(("bps %d, sps %d chan %d\n", BitsPerSample, SampleRate, nChannels));
     198
     199    // Setup the mixer for playback of wave data
     200    memset(&MixSetupParms, 0, sizeof(MixSetupParms));
     201    MixSetupParms.ulBitsPerSample = BitsPerSample;
     202    MixSetupParms.ulSamplesPerSec = SampleRate;
     203    MixSetupParms.ulFormatTag     = MCI_WAVE_FORMAT_PCM;
     204    MixSetupParms.ulChannels      = nChannels;
     205    MixSetupParms.ulFormatMode    = MCI_PLAY;
     206    MixSetupParms.ulDeviceType    = MCI_DEVTYPE_WAVEFORM_AUDIO;
     207    MixSetupParms.pmixEvent       = WaveOutHandler;
     208
     209    rc = mymciSendCommand(DeviceId, MCI_MIXSETUP,
     210                          MCI_WAIT | MCI_MIXSETUP_INIT,
     211                          (PVOID)&MixSetupParms, 0);
     212
     213    if (LOUSHORT(rc) != MCIERR_SUCCESS) {
     214        mciError(rc);
     215        mymciSendCommand(DeviceId, MCI_RELEASEDEVICE,
     216                         MCI_WAIT,
     217                         (PVOID)&GenericParms, 0);
     218        return MMSYSERR_NOTSUPPORTED;
     219    }
     220
     221    // Save the mixer handle & the ptr to the write proc.
     222    mixHandle     = MixSetupParms.ulMixHandle;
     223    pmixWriteProc = MixSetupParms.pmixWrite;
     224
     225#ifdef DEBUG_DUMP_PCM
     226    REC_STRUCT recinfo;
     227
     228    pcmfile = fopen("dartpcm.dat", "wb");
     229    recinfo.bits = BitsPerSample;
     230    recinfo.rate = SampleRate;
     231    recinfo.format = MCI_WAVE_FORMAT_PCM;
     232    recinfo.numchan = nChannels;
     233    fwrite(&recinfo, sizeof(recinfo), 1, pcmfile);
     234#endif
     235
     236    setVolume(volume);
     237    callback(WOM_OPEN, 0, 0);
     238
     239    return MMSYSERR_NOERROR;
     240}
     241
     242/******************************************************************************/
     243/******************************************************************************/
     244
     245MMRESULT DartWaveOut::write(LPWAVEHDR pwh, UINT cbwh)
     246{
     247    APIRET rc;
     248
     249    queuedbuffers++;
     250    pwh->lpNext = NULL;
     251    pwh->reserved = 0;
     252
     253    // Set up the BufferParms data structure and allocate
     254    // device buffers from the Amp-Mixer
     255    if (fMixerSetup == FALSE)
     256    {
     257        ulBufSize = pwh->dwBufferLength;
     258        if (!ulBufSize || ulBufSize > 0x10000)
     259            return MMSYSERR_INVALPARAM;
     260
     261        rc = initBuffers();
     262        if (rc != MMSYSERR_NOERROR)
     263            return rc;
     264
     265        curhdr = pwh;
     266        fMixerSetup = TRUE;
     267    }
     268
     269    wmutex.enter();
     270
     271    if (wavehdr) {
     272        WAVEHDR *chdr = wavehdr;
     273        while (chdr->lpNext) {
     274#ifdef DEBUG
     275            if (chdr == pwh) dprintf(("adding already present buffer!!!!!"));
     276#endif
     277            chdr = chdr->lpNext;
    132278        }
    133     }
    134     setVolume(volume);
    135 
    136     if(!ulError)
    137         callback(WOM_OPEN, 0, 0);
    138 }
    139 /******************************************************************************/
    140 /******************************************************************************/
    141 DartWaveOut::~DartWaveOut()
    142 {
    143     MCI_GENERIC_PARMS GenericParms;
    144 
    145     State = STATE_STOPPED;
    146 
    147 #ifdef DEBUG_DUMP_PCM
    148     if(pcmfile) fclose(pcmfile);
    149 #endif
    150 
    151     if(!ulError) {
    152         // Generic parameters
    153         GenericParms.hwndCallback = 0;   //hwndFrame
    154 
    155         // Stop the playback.
    156         mymciSendCommand(DeviceId, MCI_STOP,MCI_WAIT, (PVOID)&GenericParms,0);
    157 
    158         mymciSendCommand(DeviceId, MCI_BUFFER,
    159                        MCI_WAIT | MCI_DEALLOCATE_MEMORY,
    160                        (PVOID)&BufferParms, 0);
    161 
    162         // Generic parameters
    163         GenericParms.hwndCallback = 0;   //hwndFrame
    164 
    165         // Close the device
    166         mymciSendCommand(DeviceId, MCI_CLOSE, MCI_WAIT, (PVOID)&GenericParms, 0);
    167     }
    168 
    169     if(!ulError)
     279        chdr->lpNext = pwh;
     280    }
     281    else wavehdr = pwh;
     282
     283    //don't start playback if paused
     284    if (!fUnderrun && State != STATE_STOPPED) {
     285        //write new data to the DART buffers (if there's any room left)
     286        if (State == STATE_PLAYING)
     287            writeBuffer();  //must be called before (re)starting playback
     288        wmutex.leave();
     289        return MMSYSERR_NOERROR;
     290    }
     291
     292    writeBuffer();  //must be called before (re)starting playback
     293    State     = STATE_PLAYING;
     294    fUnderrun = FALSE;
     295    wmutex.leave();
     296
     297    //write buffers to DART; starts playback
     298    dprintf(("WINMM: transfer all buffers to DART"));
     299
     300    USHORT selTIB = RestoreOS2FS(); // save current FS selector
     301    pmixWriteProc(mixHandle, MixBuffer, ulBufCount);
     302    SetFS(selTIB);           // switch back to the saved FS selector
     303
     304    dprintf(("Dart playing\n"));
     305
     306    return MMSYSERR_NOERROR;
     307}
     308
     309/******************************************************************************/
     310/******************************************************************************/
     311
     312MMRESULT DartWaveOut::initBuffers()
     313{
     314    APIRET rc;
     315    MCI_GENERIC_PARMS  GenericParms = {0};
     316    int orgbufsize = ulBufSize;  // on entry, ulBufSize == pwh->dwBufferLength
     317
     318#if 1
     319    //by default we need to select a small enough buffer
     320    //to be able to signal buffer completion in time
     321    if (fFixedWaveBufferSize == FALSE)
    170322    {
    171         callback(WOM_CLOSE, 0, 0);
    172     }
    173 
    174     if(MixBuffer)
    175         free(MixBuffer);
    176     if(MixSetupParms)
    177         free(MixSetupParms);
    178     if(BufferParms)
    179         free(BufferParms);
    180 }
    181 /******************************************************************************/
    182 /******************************************************************************/
    183 MMRESULT DartWaveOut::write(LPWAVEHDR pwh, UINT cbwh)
    184 {
    185     MCI_GENERIC_PARMS GenericParms = {0};
    186     APIRET rc;
    187     int i, buflength;
    188 
    189     queuedbuffers++;
    190     if(fMixerSetup == FALSE)
    191     {
    192         dprintf(("device acquired\n"));
    193         /* Set the MixSetupParms data structure to match the loaded file.
    194          * This is a global that is used to setup the mixer.
    195          */
    196         memset(MixSetupParms, 0, sizeof( MCI_MIXSETUP_PARMS ) );
    197 
    198         MixSetupParms->ulBitsPerSample = BitsPerSample;
    199         MixSetupParms->ulSamplesPerSec = SampleRate;
    200         MixSetupParms->ulFormatTag     = MCI_WAVE_FORMAT_PCM;
    201         MixSetupParms->ulChannels      = nChannels;
    202 
    203         dprintf(("bps %d, sps %d chan %d\n", BitsPerSample, SampleRate, nChannels));
    204 
    205 #ifdef DEBUG_DUMP_PCM
    206         REC_STRUCT recinfo;
    207 
    208         pcmfile = fopen("dartpcm.dat", "wb");
    209         recinfo.bits = BitsPerSample;
    210         recinfo.rate = SampleRate;
    211         recinfo.format = MCI_WAVE_FORMAT_PCM;
    212         recinfo.numchan = nChannels;
    213         fwrite(&recinfo, sizeof(recinfo), 1, pcmfile);
    214 #endif
    215         /* Setup the mixer for playback of wave data
    216          */
    217         MixSetupParms->ulFormatMode = MCI_PLAY;
    218         MixSetupParms->ulDeviceType = MCI_DEVTYPE_WAVEFORM_AUDIO;
    219         MixSetupParms->pmixEvent    = WaveOutHandler;
    220 
    221         rc = mymciSendCommand(DeviceId,
    222                             MCI_MIXSETUP,
    223                             MCI_WAIT | MCI_MIXSETUP_INIT,
    224                             (PVOID)MixSetupParms,
    225                             0);
    226 
    227         if ( rc != MCIERR_SUCCESS ) {
    228             mciError(rc);
    229             mymciSendCommand(DeviceId, MCI_RELEASEDEVICE, MCI_WAIT,
    230                            (PVOID)&GenericParms, 0);
    231             return(MMSYSERR_NOTSUPPORTED);
     323        int consumerate = getAvgBytesPerSecond();
     324        int minbufsize = consumerate/32;
     325
     326        ulBufSize /= 2;
     327        if (ulBufSize > minbufsize) {
     328            dprintf(("set buffer size to %d bytes (org size = %d)", minbufsize, orgbufsize));
     329            ulBufSize = minbufsize;
    232330        }
    233 
    234         /*
    235          * Set up the BufferParms data structure and allocate
    236          * device buffers from the Amp-Mixer
    237          */
    238         dprintf(("mix setup %d, %d\n", pwh->dwBufferLength, pwh->dwBufferLength));
    239 
    240 #if 1
    241         if(fFixedWaveBufferSize == FALSE)
    242         {//by default we need to select a small enough buffer to be able to
    243          //signal buffer completion in time
    244             int consumerate = getAvgBytesPerSecond();
    245             int minbufsize = consumerate/32;
    246 
    247             ulBufSize = pwh->dwBufferLength/2;
    248             if(ulBufSize > minbufsize) {
    249                 dprintf(("set buffer size to %d bytes (org size = %d)", minbufsize, pwh->dwBufferLength));
    250                 ulBufSize = minbufsize;
    251             }
    252         }
    253         else ulBufSize = pwh->dwBufferLength;
     331    }
    254332#else
    255         if(pwh->dwBufferLength >= 512 && pwh->dwBufferLength <= 1024)
    256                 ulBufSize = pwh->dwBufferLength;
    257         else    ulBufSize = 1024;
    258 #endif
    259         MixSetupParms->ulBufferSize = ulBufSize;
    260 
    261         BufferParms->ulNumBuffers = PREFILLBUF_DART;
    262         BufferParms->ulBufferSize = MixSetupParms->ulBufferSize;
    263         BufferParms->pBufList     = MixBuffer;
    264 
    265         for(i=0;i<PREFILLBUF_DART;i++) {
    266             MixBuffer[i].ulUserParm = (ULONG)this;
    267         }
    268 
    269         rc = mymciSendCommand(DeviceId,
    270                             MCI_BUFFER,
    271                             MCI_WAIT | MCI_ALLOCATE_MEMORY,
    272                             (PVOID)BufferParms,
    273                             0);
    274 
    275         if(ULONG_LOWD(rc) != MCIERR_SUCCESS) {
    276             mciError(rc);
    277             mymciSendCommand(DeviceId, MCI_RELEASEDEVICE, MCI_WAIT,
    278                           (PVOID)&GenericParms, 0);
    279             return(MMSYSERR_NOTSUPPORTED);
    280         }
    281 
    282         wmutex.enter();
    283         fMixerSetup = TRUE;
    284 
    285         curPlayBuf = curFillBuf = curFillPos = curPlayPos = 0;
    286         bytesPlayed = bytesCopied = bytesReturned = 0;
    287 
    288         for(i=0;i<PREFILLBUF_DART;i++) {
    289             memset(MixBuffer[i].pBuffer, 0, MixBuffer[i].ulBufferLength);
    290         }
    291         dprintf(("Dart opened, bufsize = %d\n", MixBuffer[0].ulBufferLength));
    292 
    293         wavehdr     = pwh;
    294         curhdr      = pwh;
    295         pwh->lpNext = NULL;
    296         pwh->reserved = 0;
    297 
    298         if(State != STATE_STOPPED) {//don't start playback if paused
    299             wmutex.leave();
    300             return(MMSYSERR_NOERROR);
    301         }
    302 
    303         writeBuffer();  //must be called before (re)starting playback
    304 
    305         dprintf(("MixSetupParms = %X\n", MixSetupParms));
    306         State     = STATE_PLAYING;
    307         fUnderrun = FALSE;
    308         wmutex.leave();
    309 
    310         //write buffers to DART; starts playback
    311         dprintf(("WINMM: transfer all buffers to DART"));
    312         USHORT selTIB = RestoreOS2FS(); // save current FS selector
    313 
    314         MixSetupParms->pmixWrite(MixSetupParms->ulMixHandle,
    315                                  MixBuffer,
    316                                  PREFILLBUF_DART);
    317         SetFS(selTIB);           // switch back to the saved FS selector
    318         dprintf(("Dart playing\n"));
    319     }
    320     else
    321     {
    322         pwh->lpNext   = NULL;
    323         pwh->reserved = 0;
    324         wmutex.enter();
    325         if(wavehdr) {
    326             WAVEHDR *chdr = wavehdr;
    327             while(chdr->lpNext) {
    328 #ifdef DEBUG
    329                 if(chdr == pwh) dprintf(("adding already present buffer!!!!!"));
    330 #endif
    331                 chdr = chdr->lpNext;
    332             }
    333             chdr->lpNext = pwh;
    334         }
    335         else wavehdr = pwh;
    336 
    337         if(!fUnderrun && State != STATE_STOPPED) {//don't start playback if paused
    338             //write new data to the DART buffers (if there's any room left)
    339             if(State == STATE_PLAYING) {
    340                 writeBuffer();  //must be called before (re)starting playback
    341             }
    342             wmutex.leave();
    343             return(MMSYSERR_NOERROR);
    344         }
    345         writeBuffer();  //must be called before (re)starting playback
    346         State     = STATE_PLAYING;
    347         fUnderrun = FALSE;
    348         wmutex.leave();
    349 
    350         //write buffers to DART; starts playback
    351         dprintf(("WINMM: transfer all buffers to DART"));
    352         USHORT selTIB = RestoreOS2FS(); // save current FS selector
    353 
    354         MixSetupParms->pmixWrite(MixSetupParms->ulMixHandle,
    355                                  MixBuffer,
    356                                  PREFILLBUF_DART);
    357         SetFS(selTIB);           // switch back to the saved FS selector
    358 
    359         dprintf(("Dart playing\n"));
    360     }
    361     return(MMSYSERR_NOERROR);
    362 }
    363 /******************************************************************************/
    364 /******************************************************************************/
     333    if (ulBufSize < 512 || ulBufSize > 1024)
     334        ulBufSize = 1024;
     335#endif
     336
     337    dprintf(("buffer setup - WAVE size = %d, DART size = %d\n",
     338             orgbufsize, ulBufSize));
     339
     340    BufferParms->ulNumBuffers = ulBufCount;
     341    BufferParms->ulBufferSize = ulBufSize;
     342    BufferParms->pBufList     = MixBuffer;
     343
     344    rc = mymciSendCommand(DeviceId, MCI_BUFFER,
     345                        MCI_WAIT | MCI_ALLOCATE_MEMORY,
     346                        (PVOID)BufferParms, 0);
     347
     348    if (LOUSHORT(rc) != MCIERR_SUCCESS) {
     349        mciError(rc);
     350        mymciSendCommand(DeviceId, MCI_RELEASEDEVICE,
     351                         MCI_WAIT,
     352                         (PVOID)&GenericParms, 0);
     353        return MMSYSERR_NOTSUPPORTED;
     354    }
     355
     356    // DART may not have allocated all the buffers requested.
     357    ulBufCount = BufferParms->ulNumBuffers;
     358
     359    for (int i = 0; i < ulBufCount; i++) {
     360        MixBuffer[i].ulUserParm = (ULONG)this;
     361        memset(MixBuffer[i].pBuffer, 0, MixBuffer[i].ulBufferLength);
     362    }
     363    dprintf(("Dart opened, bufsize = %d\n", MixBuffer[0].ulBufferLength));
     364
     365    return MMSYSERR_NOERROR;
     366}
     367
     368/******************************************************************************/
     369/******************************************************************************/
     370
    365371MMRESULT DartWaveOut::pause()
    366372{
    367     MCI_GENERIC_PARMS Params;
     373    MCI_GENERIC_PARMS  GenericParms = {0};
    368374
    369375    dprintf(("WINMM: DartWaveOut::pause"));
    370376
    371377    wmutex.enter();
    372     if(State != STATE_PLAYING) {
     378    if (State != STATE_PLAYING) {
    373379        State = STATE_PAUSED;
    374380        wmutex.leave();
    375         return(MMSYSERR_NOERROR);
     381        return MMSYSERR_NOERROR;
    376382    }
    377383
     
    379385    wmutex.leave();
    380386
    381     memset(&Params, 0, sizeof(Params));
    382 
    383387    // Pause playback.
    384     mymciSendCommand(DeviceId, MCI_PAUSE, MCI_WAIT, (PVOID)&Params, 0);
    385 
    386     return(MMSYSERR_NOERROR);
    387 }
    388 /******************************************************************************/
    389 /******************************************************************************/
     388    mymciSendCommand(DeviceId, MCI_PAUSE,
     389                     MCI_WAIT,
     390                     (PVOID)&GenericParms, 0);
     391
     392    return MMSYSERR_NOERROR;
     393}
     394
     395/******************************************************************************/
     396/******************************************************************************/
     397
    390398MMRESULT DartWaveOut::resume()
    391399{
    392     MCI_GENERIC_PARMS Params;
    393400    int i, curbuf;
    394401
     
    396403   
    397404    wmutex.enter();
    398     if(State != STATE_PAUSED) {
     405    if (State != STATE_PAUSED) {
    399406        wmutex.leave();
    400         return(MMSYSERR_NOERROR);
     407        return MMSYSERR_NOERROR;
    401408    }
    402409    State = STATE_PLAYING;
     
    405412    //Only write buffers to dart if mixer has been initialized; if not, then
    406413    //the first buffer write will do this for us.
    407     if(fMixerSetup == TRUE)
     414    if (fMixerSetup == TRUE)
    408415    {
    409416        wmutex.enter();
    410417        State     = STATE_PLAYING;
    411418        fUnderrun = FALSE;
    412         curbuf = curPlayBuf;
     419        curbuf    = curPlayBuf;
    413420        writeBuffer();  //must be called before (re)starting playback
    414421        wmutex.leave();
    415422
    416         // MCI_MIXSETUP_PARMS->pMixWrite does alter FS: selector!
    417423        USHORT selTIB = GetFS(); // save current FS selector
    418 
    419         for(i=0;i<PREFILLBUF_DART;i++)
     424        for (i = 0; i < ulBufCount; i++)
    420425        {
    421426            dprintf(("restart: write buffer at %x size %d", MixBuffer[curbuf].pBuffer, MixBuffer[curbuf].ulBufferLength));
    422             MixSetupParms->pmixWrite(MixSetupParms->ulMixHandle, &MixBuffer[curbuf], 1);
    423             if(++curbuf == PREFILLBUF_DART)
     427            pmixWriteProc(mixHandle, &MixBuffer[curbuf], 1);
     428            if (++curbuf == ulBufCount)
    424429                curbuf = 0;
    425430        }
    426431        SetFS(selTIB);           // switch back to the saved FS selector
    427432    }
    428     return(MMSYSERR_NOERROR);
    429 }
    430 /******************************************************************************/
    431 /******************************************************************************/
     433    return MMSYSERR_NOERROR;
     434}
     435
     436/******************************************************************************/
     437/******************************************************************************/
     438
    432439MMRESULT DartWaveOut::stop()
    433440{
    434     MCI_GENERIC_PARMS Params;
     441    MCI_GENERIC_PARMS  GenericParms = {0};
    435442
    436443    dprintf(("DartWaveOut::stop %s", (State == STATE_PLAYING) ? "playing" : "stopped"));
    437     if(State != STATE_PLAYING)
    438         return(MMSYSERR_HANDLEBUSY);
    439 
    440     memset(&Params, 0, sizeof(Params));
     444    if (State != STATE_PLAYING)
     445        return MMSYSERR_HANDLEBUSY;
    441446
    442447    // Stop the playback.
    443     mymciSendCommand(DeviceId, MCI_STOP, MCI_WAIT, (PVOID)&Params, 0);
     448    mymciSendCommand(DeviceId, MCI_STOP,
     449                     MCI_WAIT,
     450                     (PVOID)&GenericParms, 0);
    444451
    445452    State     = STATE_STOPPED;
     
    449456    bytesPlayed = bytesCopied = bytesReturned = 0;
    450457
    451     return(MMSYSERR_NOERROR);
    452 }
    453 /******************************************************************************/
    454 /******************************************************************************/
     458    return MMSYSERR_NOERROR;
     459}
     460
     461/******************************************************************************/
     462/******************************************************************************/
     463
    455464MMRESULT DartWaveOut::reset()
    456465{
    457     MCI_GENERIC_PARMS Params;
     466    MCI_GENERIC_PARMS  GenericParms = {0};
    458467    LPWAVEHDR tmpwavehdr;
    459468
    460469    dprintf(("DartWaveOut::reset %s", (State == STATE_PLAYING) ? "playing" : "stopped"));
    461     if(State != STATE_PLAYING)
    462         return(MMSYSERR_HANDLEBUSY);
    463 
    464     memset(&Params, 0, sizeof(Params));
     470    if (State != STATE_PLAYING)
     471        return MMSYSERR_HANDLEBUSY;
    465472
    466473    wmutex.enter();
     
    469476
    470477    // Stop the playback.
    471     mymciSendCommand(DeviceId, MCI_STOP, MCI_WAIT, (PVOID)&Params, 0);
     478    mymciSendCommand(DeviceId, MCI_STOP,
     479                     MCI_WAIT,
     480                     (PVOID)&GenericParms, 0);
    472481
    473482    wmutex.enter();
    474     while(wavehdr)
     483    while (wavehdr)
    475484    {
    476485        wavehdr->dwFlags  |= WHDR_DONE;
     
    494503
    495504    wmutex.leave();
    496     return(MMSYSERR_NOERROR);
    497 }
    498 /******************************************************************************/
    499 /******************************************************************************/
     505    return MMSYSERR_NOERROR;
     506}
     507
     508/******************************************************************************/
     509/******************************************************************************/
     510
    500511ULONG DartWaveOut::getPosition()
    501512{
    502  MCI_STATUS_PARMS mciStatus = {0};
    503  ULONG rc, nrbytes;
    504 
    505     if(State == STATE_STOPPED) {
     513    MCI_STATUS_PARMS StatusParms = {0};
     514    ULONG rc, nrbytes;
     515
     516    if (State == STATE_STOPPED) {
    506517        dprintf(("Not playing; return 0 position"));
    507518        return ulUnderrunBase;
    508519    }
    509520
    510     mciStatus.ulItem = MCI_STATUS_POSITION;
    511     rc = mymciSendCommand(DeviceId, MCI_STATUS, MCI_STATUS_ITEM|MCI_WAIT, (PVOID)&mciStatus, 0);
    512     if((rc & 0xFFFF) == MCIERR_SUCCESS) {
    513         nrbytes = (ULONG)(((double)mciStatus.ulReturn * (double)getAvgBytesPerSecond())/1000.0);
    514         return ulUnderrunBase+nrbytes;
    515     }
    516     mciError(rc);
    517     return 0xFFFFFFFF;
    518 }
    519 /******************************************************************************/
    520 /******************************************************************************/
    521 BOOL DartWaveOut::queryFormat(ULONG formatTag, ULONG nChannels,
    522                               ULONG nSamplesPerSec, ULONG wBitsPerSample)
    523 {
    524  MCI_WAVE_GETDEVCAPS_PARMS mciAudioCaps;
    525  MCI_GENERIC_PARMS    GenericParms;
    526  MCI_OPEN_PARMS       mciOpenParms;         /* open parms for MCI_OPEN             */
    527  int i, freqbits = 0;
    528  ULONG rc, DeviceId;
    529  BOOL winrc;
    530 
    531     dprintf(("DartWaveOut::queryFormat %x srate=%d, nchan=%d, bps=%d", formatTag, nSamplesPerSec, nChannels, wBitsPerSample));
    532 
    533     memset(&mciOpenParms,            /* Object to fill with zeros.       */
    534            0,                        /* Value to place into the object.  */
    535            sizeof( mciOpenParms ) ); /* How many zero's to use.          */
    536 
    537     mciOpenParms.pszDeviceType = (PSZ)MCI_DEVTYPE_WAVEFORM_AUDIO;
    538 
    539     rc = mymciSendCommand( (USHORT) 0,
    540                         MCI_OPEN,
    541                         MCI_WAIT | MCI_OPEN_TYPE_ID,
    542                         (PVOID) &mciOpenParms,
    543                         0);
    544     if((rc & 0xFFFF) != MCIERR_SUCCESS) {
     521    StatusParms.ulItem = MCI_STATUS_POSITION;
     522    rc = mymciSendCommand(DeviceId, MCI_STATUS,
     523                          MCI_STATUS_ITEM|MCI_WAIT,
     524                          (PVOID)&StatusParms, 0);
     525    if (LOUSHORT(rc) != MCIERR_SUCCESS) {
    545526        mciError(rc);
    546         return(FALSE);
    547     }
    548     DeviceId = mciOpenParms.usDeviceID;
    549 
    550     memset( &mciAudioCaps , 0, sizeof(MCI_WAVE_GETDEVCAPS_PARMS));
    551 
    552     mciAudioCaps.ulBitsPerSample = wBitsPerSample;
    553     mciAudioCaps.ulFormatTag     = DATATYPE_WAVEFORM;
    554     mciAudioCaps.ulSamplesPerSec = nSamplesPerSec;
    555     mciAudioCaps.ulChannels      = nChannels;
    556     mciAudioCaps.ulFormatMode    = MCI_PLAY;
    557     mciAudioCaps.ulItem          = MCI_GETDEVCAPS_WAVE_FORMAT;
    558 
    559     rc = mymciSendCommand(DeviceId,   /* Device ID    */
    560                         MCI_GETDEVCAPS,
    561                         MCI_WAIT | MCI_GETDEVCAPS_EXTENDED | MCI_GETDEVCAPS_ITEM,
    562                         (PVOID) &mciAudioCaps,
    563                         0);
    564     if((rc & 0xFFFF) != MCIERR_SUCCESS) {
     527        return 0xFFFFFFFF;
     528    }
     529
     530    nrbytes = (ULONG)(((double)StatusParms.ulReturn * (double)getAvgBytesPerSecond())/1000.0);
     531    return (ulUnderrunBase + nrbytes);
     532}
     533
     534/******************************************************************************/
     535/******************************************************************************/
     536
     537MMRESULT DartWaveOut::setVolume(ULONG ulVol)
     538{
     539    APIRET  rc;
     540    ULONG   ulVolR   = ((ulVol >> 16)    * 100) / 0xFFFF;
     541    ULONG   ulVolL   = ((ulVol & 0xffff) * 100) / 0xFFFF;
     542    MCI_SET_PARMS SetParms = {0};
     543
     544    dprintf(("DartWaveOut::setVolume %d %d", ulVolL, ulVolR));
     545    volume = ulVol;
     546
     547// Some drivers can't set left & right volumes independently
     548#ifdef GOOD_AUDIO_CARD_DRIVER
     549    SetParms.ulAudio = MCI_SET_AUDIO_LEFT;
     550    SetParms.ulLevel = ulVolL;
     551
     552    rc = mymciSendCommand(DeviceId, MCI_SET,
     553                          MCI_WAIT | MCI_SET_AUDIO | MCI_SET_VOLUME,
     554                          &SetParms, 0);
     555    if (LOUSHORT(rc) != MCIERR_SUCCESS)
    565556        mciError(rc);
    566         winrc = FALSE;
    567     }
    568     else  winrc = TRUE;
    569 
    570     // Close the device
    571     mymciSendCommand(DeviceId,MCI_CLOSE,MCI_WAIT,(PVOID)&GenericParms,0);
    572     return(winrc);
    573 }
    574 /******************************************************************************/
    575 /******************************************************************************/
    576 void DartWaveOut::mciError(ULONG ulError)
     557
     558    SetParms.ulAudio = MCI_SET_AUDIO_RIGHT;
     559    SetParms.ulLevel = ulVolR;
     560#else
     561    SetParms.ulAudio = MCI_SET_AUDIO_ALL;
     562    SetParms.ulLevel = (ulVolR + ulVolL) / 2;
     563#endif
     564
     565    rc = mymciSendCommand(DeviceId, MCI_SET,
     566                          MCI_WAIT | MCI_SET_AUDIO | MCI_SET_VOLUME,
     567                          &SetParms, 0);
     568    if (LOUSHORT(rc) != MCIERR_SUCCESS)
     569        mciError(rc);
     570
     571    return MMSYSERR_NOERROR;
     572}
     573
     574/******************************************************************************/
     575/******************************************************************************/
     576
     577void DartWaveOut::mciError(ULONG rc)
    577578{
    578579#ifdef DEBUG
    579580    char szError[256] = "";
    580581
    581     mymciGetErrorString(ulError, szError, sizeof(szError));
     582    mymciGetErrorString(rc, szError, sizeof(szError));
    582583    dprintf(("WINMM: DartWaveOut: %s\n", szError));
    583584#endif
    584585}
     586
    585587//******************************************************************************
    586588//******************************************************************************
     589
    587590void DartWaveOut::handler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags)
    588591{
    589  ULONG    buflength;
    590  WAVEHDR *whdr, *prevhdr = NULL;
     592    ULONG    buflength;
     593    WAVEHDR *whdr, *prevhdr = NULL;
    591594
    592595    dprintf2(("WINMM: handler %d; buffers left %d", curPlayBuf, queuedbuffers));
    593     if(ulFlags == MIX_STREAM_ERROR) {
    594         if(ulStatus == ERROR_DEVICE_UNDERRUN) {
     596    if (ulFlags == MIX_STREAM_ERROR) {
     597        if (ulStatus == ERROR_DEVICE_UNDERRUN) {
    595598            dprintf(("WINMM: WaveOut handler UNDERRUN! state %s", (State == STATE_PLAYING) ? "playing" : "stopped"));
    596             if(State == STATE_PLAYING) {
     599            if (State == STATE_PLAYING) {
    597600                fUnderrun = TRUE;
    598601                //save current position for when we continue later
     
    605608        return;
    606609    }
    607     if(State != STATE_PLAYING) {
     610    if (State != STATE_PLAYING)
    608611        return;
    609     }
    610612
    611613    wmutex.enter();
     
    613615    bytesPlayed += MixBuffer[curPlayBuf].ulBufferLength;
    614616
    615     //update our buffer index
    616     if(curPlayBuf == PREFILLBUF_DART-1)
    617          curPlayBuf = 0;
    618     else curPlayBuf++;
     617    // update our buffer index
     618    if (++curPlayBuf >= ulBufCount)
     619        curPlayBuf = 0;
    619620
    620621    fUnderrun = FALSE;
    621622
    622623    whdr = wavehdr;
    623     while(whdr) {
    624         if(whdr->reserved == WHDR_DONE)
    625         {
    626             if(bytesPlayed < bytesReturned + whdr->dwBufferLength) {
    627                 dprintf2(("Buffer marked done, but not yet played completely (play %d/%d, cop %d, ret %d)", bytesPlayed, getPosition(), bytesCopied, bytesReturned));
    628                 break;  //not yet done
    629             }
    630 
    631             dprintf2(("WINMM: handler buf %X done (play %d/%d, cop %d, ret %d)", whdr, bytesPlayed, getPosition(), bytesCopied, bytesReturned));
    632             queuedbuffers--;
    633 
    634             whdr->dwFlags  &= ~WHDR_INQUEUE;
    635             whdr->dwFlags  |= WHDR_DONE;
    636             whdr->reserved  = 0;
    637 
    638             if(prevhdr == NULL)
    639                  wavehdr = whdr->lpNext;
    640             else prevhdr->lpNext = whdr->lpNext;
    641 
    642             whdr->lpNext = NULL;
    643 
    644             bytesReturned += whdr->dwBufferLength;
    645             wmutex.leave();
    646 
    647             callback(WOM_DONE, (ULONG)whdr, 0);
    648 
    649             wmutex.enter();
     624    while (whdr) {
     625        if (whdr->reserved != WHDR_DONE)
     626            break;
     627
     628        if (bytesPlayed < bytesReturned + whdr->dwBufferLength) {
     629            dprintf2(("Buffer marked done, but not yet played completely (play %d/%d, cop %d, ret %d)", bytesPlayed, getPosition(), bytesCopied, bytesReturned));
     630            break;  //not yet done
    650631        }
    651         else break;
     632
     633        dprintf2(("WINMM: handler buf %X done (play %d/%d, cop %d, ret %d)", whdr, bytesPlayed, getPosition(), bytesCopied, bytesReturned));
     634        queuedbuffers--;
     635
     636        whdr->dwFlags  &= ~WHDR_INQUEUE;
     637        whdr->dwFlags  |= WHDR_DONE;
     638        whdr->reserved  = 0;
     639
     640        if (prevhdr == NULL)
     641             wavehdr = whdr->lpNext;
     642        else prevhdr->lpNext = whdr->lpNext;
     643
     644        whdr->lpNext = NULL;
     645
     646        bytesReturned += whdr->dwBufferLength;
     647
     648        wmutex.leave();
     649        callback(WOM_DONE, (ULONG)whdr, 0);
     650        wmutex.enter();
    652651
    653652        prevhdr = whdr;
     
    655654    }
    656655
    657     if(wavehdr == NULL) {
    658         //last buffer played -> no new ones -> return now
     656    if (wavehdr == NULL) {
     657        // last buffer played -> no new ones -> return now
    659658        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));
    660         if(getPosition() > bytesPlayed) {
     659        if (getPosition() > bytesPlayed) {
    661660            dprintf(("WINMM: WaveOut handler UNDERRUN! state %s", (State == STATE_PLAYING) ? "playing" : "stopped"));
    662661            //save current position for when we continue later
     
    671670    writeBuffer();
    672671
    673 sendbuffer:
    674672    wmutex.leave();
    675673
     
    677675    dprintf2(("WINMM: handler transfer buffer %d", pBuffer - MixBuffer));
    678676    USHORT selTIB = RestoreOS2FS(); // save current FS selector
    679     MixSetupParms->pmixWrite(MixSetupParms->ulMixHandle, pBuffer, 1);
     677    pmixWriteProc(mixHandle, pBuffer, 1);
    680678    SetFS(selTIB);           // switch back to the saved FS selector
    681679
    682680    dprintf2(("WINMM: handler DONE"));
    683681}
    684 /******************************************************************************/
    685 /******************************************************************************/
     682
     683/******************************************************************************/
     684/******************************************************************************/
     685
    686686void DartWaveOut::writeBuffer()
    687687{
    688688    ULONG buflength;
    689689
    690     if(!fUnderrun && State == STATE_PLAYING && wavehdr == NULL && curFillBuf == curPlayBuf) {
     690    if (!fUnderrun && State == STATE_PLAYING && wavehdr == NULL && curFillBuf == curPlayBuf) {
    691691        dprintf2(("writeBuffer: no more room for more audio data"));
    692692        return; //no room left
    693693    }
    694694
    695     if(curhdr == NULL)
     695    if (curhdr == NULL)
    696696        curhdr = wavehdr;
    697697
    698     while(curhdr && (curhdr->reserved == WHDR_DONE))  {
     698    while (curhdr && (curhdr->reserved == WHDR_DONE))  {
    699699        curhdr = curhdr->lpNext;
    700700    }
    701701
    702     if(curhdr == NULL) {
     702    if (curhdr == NULL)
    703703        return;     //no unprocessed buffers left
    704     }
    705 
    706     if(State == STATE_PLAYING && curFillBuf == curPlayBuf)
     704
     705    if (State == STATE_PLAYING && curFillBuf == curPlayBuf)
    707706    {
    708707        dprintf(("curFillBuf == curPlayBuf; no more room (%d,%d)", curFillBuf, curPlayBuf));
     
    712711    dprintf2(("WINMM: handler cur (%d,%d), fill (%d,%d)\n", curPlayBuf, curPlayPos, curFillBuf, curFillPos));
    713712
    714     while(curhdr) {
     713    while (curhdr) {
    715714        buflength = min((ULONG)MixBuffer[curFillBuf].ulBufferLength - curPlayPos,
    716715                        (ULONG)curhdr->dwBufferLength - curFillPos);
     
    727726        bytesCopied += buflength;
    728727
    729         if(curFillPos == curhdr->dwBufferLength) {
     728        if (curFillPos == curhdr->dwBufferLength) {
    730729            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));
    731730
     
    733732            curhdr->reserved = WHDR_DONE;
    734733            //search for next unprocessed buffer
    735             while(curhdr && (curhdr->reserved == WHDR_DONE))
     734            while (curhdr && (curhdr->reserved == WHDR_DONE))
    736735                curhdr = curhdr->lpNext;
    737736        }
    738         if(curPlayPos == MixBuffer[curFillBuf].ulBufferLength) {
     737        if (curPlayPos == MixBuffer[curFillBuf].ulBufferLength) {
    739738            curPlayPos = 0;
    740739
    741             if(++curFillBuf == PREFILLBUF_DART) {
     740            if (++curFillBuf >= ulBufCount)
    742741                curFillBuf = 0;
    743             }
    744             if(curFillBuf == curPlayBuf)
     742
     743            if (curFillBuf == curPlayBuf)
    745744                break;  //no more room left
    746745        }
    747746    }
    748747}
    749 /******************************************************************************/
    750 /******************************************************************************/
     748
     749/******************************************************************************/
     750/******************************************************************************/
     751
    751752LONG APIENTRY WaveOutHandler(ULONG ulStatus,
    752753                             PMCI_MIX_BUFFER pBuffer,
     
    759760
    760761    ptib2 = (PTIB2)_getTIBvalue(offsetof(TIB, tib_ptib2));
    761     if(ptib2 && HIBYTE(ptib2->tib2_ulpri) != PRTYC_TIMECRITICAL &&
     762    if (ptib2 && HIBYTE(ptib2->tib2_ulpri) != PRTYC_TIMECRITICAL &&
    762763       LOBYTE(ptib2->tib2_ulpri) != PRTYD_MAXIMUM)
    763764    {
     
    765766        DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, PRTYD_MAXIMUM, 0);
    766767    }
    767     if(pBuffer && pBuffer->ulUserParm)
     768    if (pBuffer && pBuffer->ulUserParm)
    768769    {
    769770        dwave = (DartWaveOut *)pBuffer->ulUserParm;
    770771        dwave->handler(ulStatus, pBuffer, ulFlags);
    771772    }
    772     return(TRUE);
    773 }
    774 
    775 /******************************************************************************/
    776 /******************************************************************************/
    777 MMRESULT DartWaveOut::setVolume(ULONG ulVol)
    778 {
    779   ULONG ulVolR     = (((ulVol & 0xffff0000) >> 16 )*100)/0xFFFF; // Right Volume
    780   ULONG ulVolL      = ((ulVol& 0x0000ffff)*100)/0xFFFF;          // Left Volume
    781   MCI_SET_PARMS msp = {0};
    782 
    783   dprintf(("DartWaveOut::setVolume %d %d", ulVolL, ulVolR));
    784   volume = ulVol;
    785 
    786 // PD: My card (ESS 1868 PnP) driver can't change only
    787 //     one channel Left or Right :-(
    788 //
    789 #ifdef GOOD_AUDIO_CARD_DRIVER
    790 
    791   msp.ulAudio = MCI_SET_AUDIO_LEFT;
    792   msp.ulLevel = ulVolL;
    793 
    794   mymciSendCommand(DeviceId, MCI_SET,
    795                  MCI_WAIT | MCI_SET_AUDIO | MCI_SET_VOLUME,
    796                  &msp, 0);
    797 
    798   msp.ulAudio = MCI_SET_AUDIO_RIGHT;
    799   msp.ulLevel = ulVolR;
    800 
    801 #else
    802   msp.ulAudio = MCI_SET_AUDIO_ALL;
    803   msp.ulLevel = max(ulVolR,ulVolL);
    804 #endif
    805 
    806   mymciSendCommand(DeviceId, MCI_SET,
    807                  MCI_WAIT | MCI_SET_AUDIO | MCI_SET_VOLUME,
    808                  &msp, 0);
    809   return 0;
    810 }
    811 /******************************************************************************/
    812 /******************************************************************************/
    813 
     773    return TRUE;
     774}
     775
     776/******************************************************************************/
     777/******************************************************************************/
     778
  • trunk/src/winmm/waveoutdart.h

    r21349 r21358  
    88 * Project Odin Software License can be found in LICENSE.TXT
    99 */
     10
    1011#ifndef __DWAVEOUT_H__
    1112#define __DWAVEOUT_H__
    1213
    1314#include "waveoutbase.h"
    14 
    15 #define PREFILLBUF_DART 64
    16 #define DART_BUFSIZE    4096
    1715
    1816#ifdef OS2_ONLY
     
    2927#endif
    3028
     29// this should be defined in some #included .h file, but it isn't
     30typedef LONG (APIENTRY MIXERPROC)(ULONG ulHandle, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags);
     31
    3132class DartWaveOut : public WaveOut
    3233{
    3334public:
    34               DartWaveOut(LPWAVEFORMATEX pwfx, DWORD fdwOpen, ULONG nCallback, ULONG dwInstance);
    35      virtual ~DartWaveOut();
     35                    DartWaveOut(LPWAVEFORMATEX pwfx, DWORD fdwOpen,
     36                                ULONG nCallback, ULONG dwInstance);
     37  virtual           ~DartWaveOut();
    3638
    37      virtual  MMRESULT write(LPWAVEHDR pwh, UINT cbwh);
    38      virtual  MMRESULT pause();
    39      virtual  MMRESULT stop();
    40      virtual  MMRESULT resume();
    41      virtual  MMRESULT setVolume(ULONG ulVol);
    42      virtual  MMRESULT reset();
    43      virtual  ULONG    getPosition();
    44 
    45   static BOOL queryFormat(ULONG formatTag, ULONG nChannels,
    46                           ULONG nSamplesPerSec, ULONG sampleSize);
     39  virtual MMRESULT  open();
     40  virtual MMRESULT  write(LPWAVEHDR pwh, UINT cbwh);
     41  virtual MMRESULT  pause();
     42  virtual MMRESULT  stop();
     43  virtual MMRESULT  resume();
     44  virtual MMRESULT  setVolume(ULONG ulVol);
     45  virtual MMRESULT  reset();
     46  virtual ULONG     getPosition();
    4747
    4848protected:
    49   static void mciError(ULONG ulError);
    50          void Init(LPWAVEFORMATEX pwfx);
    51          void handler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags);
     49          MMRESULT  initBuffers();
     50          void      writeBuffer();
     51   static void      mciError(ULONG rc);
     52          void      handler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags);
    5253
    5354private:
    54          void writeBuffer();
     55          USHORT    DeviceId;
     56          BOOL      fMixerSetup;
     57          BOOL      fUnderrun;
     58          int       curFillBuf;
     59          int       curPlayBuf;
     60          ULONG     curFillPos;
     61          ULONG     curPlayPos;
     62          ULONG     ulBufSize;
     63          ULONG     ulBufCount;
     64          ULONG     bytesPlayed;
     65          ULONG     bytesCopied;
     66          ULONG     bytesReturned;
     67          ULONG     ulUnderrunBase;
     68          ULONG     mixHandle;
     69          WAVEHDR * curhdr;
     70        MIXERPROC * pmixWriteProc;
     71   MCI_MIX_BUFFER * MixBuffer;
     72 MCI_BUFFER_PARMS * BufferParms;
    5573
    56         USHORT          DeviceId;
    57         ULONG           ulBufferCount;             /* Current file buffer     */
    58         ULONG           ulBufSize;
    59 
    60   MCI_MIX_BUFFER       *MixBuffer;          /* Device buffers          */
    61   MCI_MIXSETUP_PARMS   *MixSetupParms;          /* Mixer parameters        */
    62   MCI_BUFFER_PARMS     *BufferParms;                /* Device buffer parms     */
    63 
    64         int             curPlayBuf, curFillBuf;
    65         ULONG           curFillPos, curPlayPos; //fillpos == pos in os2 mix buffer, bufpos == pos in win buffer
    66 
    67         BOOL            fMixerSetup;
    68         BOOL            fUnderrun;
    69         ULONG           ulUnderrunBase;
    70 
    71 #ifndef _OS2WIN_H
    72         friend LONG APIENTRY WaveOutHandler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags);
    73 #endif
     74  friend LONG APIENTRY WaveOutHandler(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer,
     75                                      ULONG ulFlags);
    7476};
    7577
  • trunk/src/winmm/waveoutdaud.cpp

    r9979 r21358  
    1212 */
    1313
    14 
    15 /****************************************************************************
    16  * Includes                                                                 *
    17  ****************************************************************************/
    18 
    19 
     14/******************************************************************************/
     15// Includes
     16/******************************************************************************/
    2017
    2118#define  INCL_BASE
     
    5754                  : WaveOut(pwfx, fdwOpen, nCallback, dwInstance)
    5855{
     56    hSem = 0;
     57    hDAudioDrv = 0;
     58    hThread = 0;
     59    dwThreadID = 0;
     60    bytesReturned = 0;
     61    fUnderrun = 0;
     62}
     63/******************************************************************************/
     64/******************************************************************************/
     65DAudioWaveOut::~DAudioWaveOut()
     66{
     67    DAUDIO_CMD cmd;
     68
     69    if(hThread)
     70        callback(WOM_CLOSE, 0, 0);
     71
     72    if(hDAudioDrv) {
     73        cmd.Thread.hSemaphore = hSem;
     74        sendIOCTL(DAUDIO_DEREGISTER_THREAD, &cmd);
     75        sendIOCTL(DAUDIO_CLOSE, &cmd);
     76        DosClose(hDAudioDrv);
     77        hDAudioDrv = 0;
     78    }
     79    if(hSem) {
     80        DosPostEventSem(hSem);
     81        DosCloseEventSem(hSem);
     82    }
     83}
     84/******************************************************************************/
     85/******************************************************************************/
     86MMRESULT DAudioWaveOut::open()
     87{
    5988    APIRET          rc;
    6089    ULONG           action;
     
    6493    ULONG           ParmLength = 0, DataLength;
    6594
    66     fUnderrun = FALSE;
    67     hSem      = 0;
    68 
    69     dprintf(("DAudioWaveOut::DAudioWaveOut"));
     95    dprintf(("DAudioWaveOut::open"));
    7096
    7197    rc = DosOpen(szPDDName, &hDAudioDrv, &action, 0,
     
    75101    if(rc) {
    76102        dprintf(("DosOpen failed with error %d\n", rc));
    77         ulError = MMSYSERR_NODRIVER;
    78         goto fail;
     103        return MMSYSERR_NODRIVER;
    79104    }
    80105
    81106    DataLength = sizeof(init);
    82107
    83     init.lSRate         = pwfx->nSamplesPerSec;
    84     init.lBitsPerSRate  = pwfx->wBitsPerSample;
    85     init.sChannels      = pwfx->nChannels;
     108    init.lSRate         = SampleRate;
     109    init.lBitsPerSRate  = BitsPerSample;
     110    init.sChannels      = nChannels;
    86111    init.sMode          = PCM;  //todo!!
    87112
     
    90115    if(rc) {
    91116        dprintf(("DosDevIOCtl failed with error %d\n", rc));
    92         ulError = MMSYSERR_NODRIVER;
    93         goto fail;
     117        return MMSYSERR_NODRIVER;
    94118    }
    95119    if(init.sReturnCode != 0) {
    96120        dprintf(("init.sReturnCode = %d\n", init.sReturnCode));
    97         ulError = MMSYSERR_NODRIVER;
    98         goto fail;
     121        return MMSYSERR_NODRIVER;
    99122    }
    100123
     
    102125    if(rc) {
    103126        dprintf(("DosCreateEventSem failed with error %d\n", rc));
    104         ulError = MMSYSERR_NODRIVER;
    105         goto fail;
     127        return MMSYSERR_NODRIVER;
    106128    }
    107129    cmd.Thread.hSemaphore = hSem;
     
    110132    if(rc) {
    111133        dprintf(("DosDevIOCtl failed with error %d\n", rc));
    112         ulError = MMSYSERR_NODRIVER;
    113         goto fail;
     134        return MMSYSERR_NODRIVER;
    114135    }
    115136
    116137    hThread = CreateThread(NULL, 0x4000, (LPTHREAD_START_ROUTINE)DAudioThreadHandler,
    117138                           (LPVOID)this, 0, &dwThreadID);
     139    if (!hThread) {
     140        dprintf(("CreateThread failed\n"));
     141        return MMSYSERR_NODRIVER;
     142    }
    118143
    119144    setVolume(volume);
    120 
    121     if(!ulError)
    122         callback(WOM_OPEN, 0, 0);
    123 
    124 fail:
    125     return;
    126 }
    127 /******************************************************************************/
    128 /******************************************************************************/
    129 DAudioWaveOut::~DAudioWaveOut()
    130 {
    131     DAUDIO_CMD cmd;
    132 
    133     if(!ulError)
    134         callback(WOM_CLOSE, 0, 0);
    135 
    136     if(hDAudioDrv) {
    137         cmd.Thread.hSemaphore = hSem;
    138         sendIOCTL(DAUDIO_DEREGISTER_THREAD, &cmd);
    139         sendIOCTL(DAUDIO_CLOSE, &cmd);
    140         DosClose(hDAudioDrv);
    141         hDAudioDrv = 0;
    142     }
    143     if(hSem) {
    144         DosPostEventSem(hSem);
    145         DosCloseEventSem(hSem);
    146     }
     145    callback(WOM_OPEN, 0, 0);
     146
     147    return(MMSYSERR_NOERROR);
    147148}
    148149/******************************************************************************/
     
    235236    fUnderrun = FALSE;
    236237
    237     bytesPlayed = bytesCopied = bytesReturned = 0;
     238    bytesReturned = 0;
    238239
    239240    return rc;
     
    271272    fUnderrun = FALSE;
    272273
    273     bytesPlayed = bytesCopied = bytesReturned = 0;
     274    bytesReturned = 0;
    274275    queuedbuffers = 0;
    275276
     
    409410 LPWAVEHDR whdr = wavehdr;
    410411
    411     dprintf2(("WINMM: handler buf %X done (play %d/%d, cop %d, ret %d)", whdr, bytesPlayed, getPosition(), bytesCopied, bytesReturned));
     412    dprintf2(("WINMM: handler buf %X done (play %d, ret %d)", whdr, getPosition(), bytesReturned));
    412413
    413414    if(State != STATE_PLAYING || whdr == NULL)
  • trunk/src/winmm/waveoutdaud.h

    r8568 r21358  
    88 * Project Odin Software License can be found in LICENSE.TXT
    99 */
     10
    1011#ifndef __DWAVEOUTEX_H__
    1112#define __DWAVEOUTEX_H__
     
    2425{
    2526public:
    26                DAudioWaveOut(LPWAVEFORMATEX pwfx, ULONG fdwOpen, ULONG nCallback, ULONG dwInstance);
    27      virtual  ~DAudioWaveOut();
     27                    DAudioWaveOut(LPWAVEFORMATEX pwfx, ULONG fdwOpen,
     28                                  ULONG nCallback, ULONG dwInstance);
     29  virtual           ~DAudioWaveOut();
    2830
    29      virtual  MMRESULT write(LPWAVEHDR pwh, UINT cbwh);
    30      virtual  MMRESULT pause();
    31      virtual  MMRESULT stop();
    32      virtual  MMRESULT resume();
    33      virtual  MMRESULT setVolume(ULONG ulVol);
    34      virtual  MMRESULT reset();
    35      virtual  ULONG    getPosition();
     31  virtual MMRESULT  open();
     32  virtual MMRESULT  write(LPWAVEHDR pwh, UINT cbwh);
     33  virtual MMRESULT  pause();
     34  virtual MMRESULT  stop();
     35  virtual MMRESULT  resume();
     36  virtual MMRESULT  setVolume(ULONG ulVol);
     37  virtual MMRESULT  reset();
     38  virtual ULONG     getPosition();
    3639
    37      static   BOOL     queryFormat(ULONG formatTag, ULONG nChannels,
    38                                    ULONG nSamplesPerSec, ULONG sampleSize);
    39 
    40 
    41      static   BOOL     isDirectAudioAvailable();
     40   static BOOL      queryFormat(ULONG formatTag, ULONG nChannels,
     41                                ULONG nSamplesPerSec, ULONG sampleSize);
     42   static BOOL      isDirectAudioAvailable();
    4243
    4344protected:
    4445
    4546private:
    46        BOOL     handler();
    47        MMRESULT sendIOCTL(ULONG cmd, DAUDIO_CMD *pDataPacket);
     47          BOOL      handler();
     48          MMRESULT sendIOCTL(ULONG cmd, DAUDIO_CMD *pDataPacket);
    4849
    49         HEV     hSem;
     50          HEV       hSem;
     51          HFILE     hDAudioDrv;
     52          HANDLE    hThread;
     53          DWORD     dwThreadID;
     54          ULONG     bytesReturned;
     55          BOOL      fUnderrun;
    5056
    51         ULONG   bytesPlayed, bytesReturned;
    52         int     queuedbuffers;
    53 
    54         BOOL    fUnderrun;
    55         HANDLE  hThread;
    56         DWORD   dwThreadID;
    57 
    58         HFILE   hDAudioDrv;
    59 
    60         friend  DWORD WIN32API DAudioThreadHandler(LPVOID pUserData);
     57  friend  DWORD WIN32API DAudioThreadHandler(LPVOID pUserData);
    6158};
    6259
  • trunk/src/winmm/winmm.mak

    r21342 r21358  
    2424#
    2525!include ../../makefile.inc
    26 
    2726
    2827#
     
    5655$(OBJDIR)\joyos2.obj \
    5756$(OBJDIR)\winmmrsrc.obj \
     57$(OBJDIR)\waveoutflash.obj \
    5858!ifdef DEBUG
    5959$(OBJDIR)\dbgwrap.obj \
Note: See TracChangeset for help on using the changeset viewer.