Changeset 5334 for trunk/src


Ignore:
Timestamp:
Mar 19, 2001, 8:28:39 PM (24 years ago)
Author:
sandervl
Message:

many wave playback & recording fixes

Location:
trunk/src/winmm
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/winmm/dbglocal.cpp

    r5272 r5334  
    1 /* $Id: dbglocal.cpp,v 1.3 2001-02-27 21:13:59 sandervl Exp $ */
     1/* $Id: dbglocal.cpp,v 1.4 2001-03-19 19:28:37 sandervl Exp $ */
    22
    33/*
     
    1616#include "dbglocal.h"
    1717
    18 USHORT DbgEnabled[DBG_MAXFILES];
     18USHORT DbgEnabled[DBG_MAXFILES] = {0};
     19USHORT DbgEnabledLvl2[DBG_MAXFILES] = {0};
     20
    1921char  *DbgFileNames[DBG_MAXFILES] =
    2022{
     
    4547{
    4648 char *envvar = getenv(DBG_ENVNAME);
     49 char *envvar2= getenv(DBG_ENVNAME_LVL2);
    4750 char *dbgvar;
    4851 int   i;
     
    6972                    DbgEnabled[i] = 0;
    7073            }
    71             else
     74            else   
    7275            if(*(dbgvar-1) == '+') {
    73                 DbgEnabled[i] = 1;
    74             }
     76                DbgEnabled[i] = 1;
     77            }
     78        }
     79    }
     80    if(envvar2) {
     81        dbgvar = strstr(envvar2, "dll");
     82        if(dbgvar) {
     83                if(*(dbgvar-1) == '+') {
     84                    for(i=0;i<DBG_MAXFILES;i++) {
     85                        DbgEnabledLvl2[i] = 1;
     86                    }
     87                }
     88        }
     89        for(i=0;i<DBG_MAXFILES;i++) {
     90                dbgvar = strstr(envvar2, DbgFileNames[i]);
     91                if(dbgvar) {
     92                    if(*(dbgvar-1) == '-') {
     93                            DbgEnabledLvl2[i] = 0;
     94                    }
     95                    else   
     96                    if(*(dbgvar-1) == '+') {
     97                        DbgEnabledLvl2[i] = 1;
     98                    }
     99                }
    75100        }
    76101    }
  • trunk/src/winmm/dbglocal.h

    r5272 r5334  
    1 /* $Id: dbglocal.h,v 1.3 2001-02-27 21:13:59 sandervl Exp $ */
     1/* $Id: dbglocal.h,v 1.4 2001-03-19 19:28:38 sandervl Exp $ */
    22
    33/*
     
    1818
    1919#define DBG_ENVNAME        "dbg_winmm"
     20#define DBG_ENVNAME_LVL2   "dbg_winmm_lvl2"
    2021
    2122#define DBG_os2timer        0
     
    4243
    4344extern USHORT DbgEnabled[DBG_MAXFILES];
     45extern USHORT DbgEnabledLvl2[DBG_MAXFILES];
    4446
    4547#ifdef dprintf
     
    4850
    4951#define dprintf(a)      if(DbgEnabled[DBG_LOCALLOG] == 1) WriteLog a
     52
     53#ifdef dprintf2
     54#undef dprintf2
     55#endif
     56
     57#define dprintf2(a)     if(DbgEnabledLvl2[DBG_LOCALLOG] == 1) WriteLog a
    5058
    5159#else
  • trunk/src/winmm/dwavein.cpp

    r5272 r5334  
    1 /* $Id: dwavein.cpp,v 1.1 2001-02-27 21:13:59 sandervl Exp $ */
     1/* $Id: dwavein.cpp,v 1.2 2001-03-19 19:28:38 sandervl Exp $ */
    22
    33/*
     
    5454/******************************************************************************/
    5555/******************************************************************************/
    56 DartWaveIn::DartWaveIn(LPWAVEFORMATEX pwfx, ULONG nCallback, ULONG dwInstance, USHORT usSel)
     56DartWaveIn::DartWaveIn(LPWAVEFORMATEX pwfx, ULONG nCallback, ULONG dwInstance)
    5757{
    5858   Init(pwfx);
    5959
    6060   mthdCallback     = (LPDRVCALLBACK)nCallback; // callback function
    61    selCallback      = usSel;                    // callback win32 tib selector
    6261   this->dwInstance = dwInstance;
    6362   fOverrun        = FALSE;
     
    8281{
    8382  USHORT selTIB = GetFS(); // save current FS selector
     83  USHORT selCallback;
    8484
    8585    dprintf(("WINMM:DartWaveIn::callback(HDRVR h=%08xh, UINT uMessage=%08xh, DWORD dwUser=%08xh, DWORD dw1=%08xh, DWORD dw2=%08xh)\n",
    8686              h, uMessage, dwUser, dw1, dw2));
    8787
    88     if (selCallback != 0)
    89         SetFS(selCallback);      // switch to callback win32 tib selector (stored in waveInOpen)
    90     else
    91         dprintf(("WINMM:DartWaveIn::callback - selCallback is invalid"));
    92 
    93     //@@@PH 1999/12/28 Shockwave Flashes seem to make assumptions on a
    94     // specific stack layout. Do we have the correct calling convention here?
    95     mthdCallback(h,uMessage,dwUser,dw1,dw2);
    96     SetFS(selTIB);           // switch back to the saved FS selector
     88    selCallback = GetProcessTIBSel();
     89
     90    //TODO: may not be very safe. perhaps we should allocate a new TIB for the DART thread or let another thread do the actual callback
     91    if(selCallback)
     92    {
     93        SetFS(selCallback);      // switch to callback win32 tib selector (stored in waveOutOpen)
     94
     95        //@@@PH 1999/12/28 Shockwave Flashes seem to make assumptions on a
     96        // specific stack layout. Do we have the correct calling convention here?
     97        mthdCallback(h,uMessage,dwUser,dw1,dw2);
     98        SetFS(selTIB);           // switch back to the saved FS selector
     99    }
     100    else {
     101        dprintf(("WARNING: no valid selector of main thread available (process exiting); skipping waveout notify"));
     102    }
     103    dprintf(("WINMM:DartWaveOut::callback returned"));
    97104}
    98105/******************************************************************************/
     
    109116   mthdCallback  = NULL;
    110117   hwndCallback  = 0;
    111    selCallback   = 0;
    112118   dwInstance    = 0;
    113119   ulError       = 0;
    114    selCallback   = 0;
    115120   State         = STATE_STOPPED;
    116121
     
    450455{
    451456 MCI_GENERIC_PARMS Params;
    452 
    453   dprintf(("DartWaveIn::reset %s", (State == STATE_RECORDING) ? "recording" : "stopped"));
    454   if(State != STATE_RECORDING)
     457 LPWAVEHDR tmpwavehdr;
     458
     459    dprintf(("DartWaveIn::reset %s", (State == STATE_RECORDING) ? "recording" : "stopped"));
     460    if(State != STATE_RECORDING)
    455461        return(MMSYSERR_HANDLEBUSY);
    456462
    457   memset(&Params, 0, sizeof(Params));
    458 
    459   // Stop recording
    460   mciSendCommand(DeviceId, MCI_STOP, MCI_WAIT, (PVOID)&Params, 0);
    461 
    462   dprintf(("Nr of threads blocked on mutex = %d\n", wmutex->getNrBlocked()));
    463 
    464   wmutex->enter(VMUTEX_WAIT_FOREVER);
    465   while(wavehdr)
    466   {
     463    memset(&Params, 0, sizeof(Params));
     464
     465    // Stop recording
     466    mciSendCommand(DeviceId, MCI_STOP, MCI_WAIT, (PVOID)&Params, 0);
     467
     468    dprintf(("Nr of threads blocked on mutex = %d\n", wmutex->getNrBlocked()));
     469
     470    wmutex->enter(VMUTEX_WAIT_FOREVER);
     471    while(wavehdr)
     472    {
    467473        wavehdr->dwFlags |= WHDR_DONE;
    468474        wavehdr->dwFlags &= ~WHDR_INQUEUE;
    469         wavehdr = wavehdr->lpNext;
    470         wavehdr->lpNext = NULL;
     475        tmpwavehdr         = wavehdr;
     476        wavehdr            = wavehdr->lpNext;
     477        tmpwavehdr->lpNext = NULL;
    471478
    472479        wmutex->leave();
    473480        if(mthdCallback) {
    474             callback((ULONG)this, WIM_DATA, dwInstance, (ULONG)wavehdr, 0);
     481            callback((ULONG)this, WIM_DATA, dwInstance, (ULONG)tmpwavehdr, 0);
    475482        }
    476483        else
    477484        if(hwndCallback) {
    478485            dprintf(("Callback (msg) for buffer %x", wavehdr));
    479             PostMessageA(hwndCallback, WIM_DATA, (WPARAM)this, (ULONG)wavehdr);
     486            PostMessageA(hwndCallback, WIM_DATA, (WPARAM)this, (ULONG)tmpwavehdr);
    480487        }
    481488        wmutex->enter(VMUTEX_WAIT_FOREVER);
    482   }
    483   wavehdr   = NULL;
    484   State     = STATE_STOPPED;
    485   fOverrun = FALSE;
    486 
    487   wmutex->leave();
    488   return(MMSYSERR_NOERROR);
     489    }
     490    wavehdr   = NULL;
     491    State     = STATE_STOPPED;
     492    fOverrun = FALSE;
     493
     494    wmutex->leave();
     495    return(MMSYSERR_NOERROR);
    489496}
    490497/******************************************************************************/
     
    495502
    496503    wmutex->enter(VMUTEX_WAIT_FOREVER);
    497     pwh->lpNext   = NULL;
     504    pwh->lpNext          = NULL;
    498505    pwh->dwBytesRecorded = 0;
    499506    if(wavehdr) {
     
    585592{
    586593#ifdef DEBUG
    587  char szError[256] = "";
    588 
    589   mciGetErrorString(ulError, szError, sizeof(szError));
    590   dprintf(("WINMM: DartWaveIn: %s\n", szError));
     594    char szError[256] = "";
     595
     596    mciGetErrorString(ulError, szError, sizeof(szError));
     597    dprintf(("WINMM: DartWaveIn: %s\n", szError));
    591598#endif
    592599}
     
    595602BOOL DartWaveIn::find(DartWaveIn *dwave)
    596603{
    597  DartWaveIn *curwave = wavein;
    598 
    599   while(curwave) {
    600     if(dwave == curwave) {
    601         return(TRUE);
    602     }
    603     curwave = curwave->next;
    604   }
    605 
    606 #ifdef DEBUG
    607 //  WriteLog("WINMM:DartWaveIn not found!\n");
    608 #endif
    609   return(FALSE);
     604    DartWaveIn *curwave = wavein;
     605
     606    while(curwave) {
     607        if(dwave == curwave) {
     608            return(TRUE);
     609        }
     610        curwave = curwave->next;
     611    }
     612
     613    dprintf2(("WINMM:DartWaveIn not found!"));
     614    return(FALSE);
    610615}
    611616/******************************************************************************/
     
    619624 WAVEHDR *whdr, *prevhdr = NULL;
    620625
    621 #ifdef DEBUG1
    622     dprintf(("WINMM: DartWaveIn handler %x\n", pBuffer));
    623 #endif
     626    dprintf2(("WINMM: DartWaveIn handler %x\n", pBuffer));
    624627    if(ulFlags == MIX_STREAM_ERROR) {
    625628        if(ulStatus == ERROR_DEVICE_OVERRUN) {
     
    627630            if(State == STATE_RECORDING) {
    628631                fOverrun = TRUE;
    629                 stop();    //out of buffers, so pause playback
     632                stop();    //out of buffers, so stop playback
    630633            }
    631634            return;
     
    644647        return;
    645648    }
    646 
    647 #ifdef DEBUG1
    648     dprintf(("WINMM: DartWaveIn handler cur (%d,%d), fill (%d,%d)\n", curPlayBuf, curPlayPos, curFillBuf, curFillPos));
    649 #endif
    650649
    651650    buflength = pBuffer->ulBufferLength;
     
    663662            buflength                -= bytestocopy;
    664663
    665             if(wavehdr->dwBytesRecorded == wavehdr->dwBufferLength) {
    666 #ifdef DEBUG1
    667                 dprintf(("WINMM: DartWaveIn handler buf %X done\n", whdr));
    668 #endif
     664            if(wavehdr->dwBytesRecorded == wavehdr->dwBufferLength)
     665            {
     666                dprintf2(("WINMM: DartWaveIn handler buf %X done\n", whdr));
    669667                whdr->dwFlags |= WHDR_DONE;
    670668                whdr->dwFlags &= ~WHDR_INQUEUE;
     
    675673
    676674                if(mthdCallback) {
    677                     callback((ULONG)this, WIM_DATA, dwInstance, (ULONG)whdr, 0);
     675                    callback((ULONG)this, WIM_DATA, dwInstance, (ULONG)whdr, whdr->dwBytesRecorded);
    678676                }
    679677                else
    680678                if(hwndCallback) {
    681                         dprintf(("Callback (msg) for buffer %x", whdr));
    682                     PostMessageA(hwndCallback, WIM_DATA, (WPARAM)this, (ULONG)whdr);
    683                 }
     679                    dprintf(("Callback (msg) for buffer %x", whdr));
     680                    PostMessageA(hwndCallback, WIM_DATA, (WPARAM)this, (ULONG)whdr);
     681                }
    684682                wmutex->enter(VMUTEX_WAIT_FOREVER);
    685683            }
     
    701699                            ULONG ulFlags)
    702700{
    703     // PTIB ptib;
    704     // PPIB ppib;
    705     // DosGetInfoBlocks(&ptib, &ppib);
    706     // dprintf(("WaveInHandler: thread %d prio %X", ptib->tib_ptib2->tib2_ultid, ptib->tib_ptib2->tib2_ulpri));
    707 
    708701    DartWaveIn *dwave;
    709702
  • trunk/src/winmm/dwavein.h

    r5272 r5334  
    1 /* $Id: dwavein.h,v 1.1 2001-02-27 21:13:59 sandervl Exp $ */
     1/* $Id: dwavein.h,v 1.2 2001-03-19 19:28:38 sandervl Exp $ */
    22
    33/*
     
    3131{
    3232public:
    33               DartWaveIn(LPWAVEFORMATEX pwfx, ULONG nCallback, ULONG dwInstance, USHORT usSel);
     33              DartWaveIn(LPWAVEFORMATEX pwfx, ULONG nCallback, ULONG dwInstance);
    3434              DartWaveIn(LPWAVEFORMATEX pwfx, HWND hwndCallback);
    3535              DartWaveIn(LPWAVEFORMATEX pwfx);
     
    7777    // callback interface
    7878    LPDRVCALLBACK mthdCallback; // pointer to win32 routine for the callback
    79     USHORT        selCallback;  // the win32 tib selector for the callback (saved at waveOutOpen)
    8079    void          callback(HDRVR h, UINT uMessage, DWORD dwUser, DWORD dw1, DWORD dw2);
    8180    HWND          hwndCallback;
  • trunk/src/winmm/dwaveout.cpp

    r5272 r5334  
    1 /* $Id: dwaveout.cpp,v 1.31 2001-02-27 21:13:59 sandervl Exp $ */
     1/* $Id: dwaveout.cpp,v 1.32 2001-03-19 19:28:38 sandervl Exp $ */
    22
    33/*
     
    5656/******************************************************************************/
    5757/******************************************************************************/
    58 DartWaveOut::DartWaveOut(LPWAVEFORMATEX pwfx, ULONG nCallback, ULONG dwInstance, USHORT usSel)
     58DartWaveOut::DartWaveOut(LPWAVEFORMATEX pwfx, ULONG nCallback, ULONG dwInstance)
    5959{
    6060   Init(pwfx);
    6161
    62    mthdCallback     = (LPDRVCALLBACK)nCallback; // callback function
    63    selCallback      = usSel;                    // callback win32 tib selector
     62   mthdCallback     = (LPDRVCALLBACK)nCallback;   // callback function
    6463   this->dwInstance = dwInstance;
    6564   fUnderrun        = FALSE;
    6665
    6766   if(!ulError)
    68     callback((ULONG)this, WOM_OPEN, dwInstance, 0, 0);
     67        callback((ULONG)this, WOM_OPEN, dwInstance, 0, 0);
    6968}
    7069/******************************************************************************/
     
    7776
    7877   if(!ulError)
    79     PostMessageA(hwndCallback, WOM_OPEN, 0, 0);
     78        PostMessageA(hwndCallback, WOM_OPEN, 0, 0);
    8079}
    8180/******************************************************************************/
     
    8382void DartWaveOut::callback(HDRVR h, UINT uMessage, DWORD dwUser, DWORD dw1, DWORD dw2)
    8483{
    85   USHORT selTIB = GetFS(); // save current FS selector
    86 
    87   dprintf(("WINMM:DartWaveOut::callback(HDRVR h=%08xh, UINT uMessage=%08xh, DWORD dwUser=%08xh, DWORD dw1=%08xh, DWORD dw2=%08xh)\n",
     84    USHORT selTIB = GetFS(); // save current FS selector
     85    USHORT selCallback;
     86
     87    dprintf(("WINMM:DartWaveOut::callback(HDRVR h=%08xh, UINT uMessage=%08xh, DWORD dwUser=%08xh, DWORD dw1=%08xh, DWORD dw2=%08xh)\n",
    8888           h,
    8989           uMessage,
     
    9292           dw2));
    9393
    94   if (selCallback != 0)
    95     SetFS(selCallback);      // switch to callback win32 tib selector (stored in waveOutOpen)
    96   else
    97     dprintf(("WINMM:DartWaveOut::callback - selCallback is invalid"));
    98 
    99   //@@@PH 1999/12/28 Shockwave Flashes seem to make assumptions on a
    100   // specific stack layout. Do we have the correct calling convention here?
    101   mthdCallback(h,uMessage,dwUser,dw1,dw2);
    102   SetFS(selTIB);           // switch back to the saved FS selector
     94    selCallback = GetProcessTIBSel();
     95
     96    //TODO: may not be very safe. perhaps we should allocate a new TIB for the DART thread or let another thread do the actual callback
     97    if(selCallback)
     98    {
     99        SetFS(selCallback);      // switch to callback win32 tib selector (stored in waveOutOpen)
     100
     101        //@@@PH 1999/12/28 Shockwave Flashes seem to make assumptions on a
     102        // specific stack layout. Do we have the correct calling convention here?
     103        mthdCallback(h,uMessage,dwUser,dw1,dw2);
     104        SetFS(selTIB);           // switch back to the saved FS selector
     105    }
     106    else {
     107        dprintf(("WARNING: no valid selector of main thread available (process exiting); skipping waveout notify"));
     108    }
     109    dprintf(("WINMM:DartWaveOut::callback returned"));
    103110}
    104111/******************************************************************************/
    105112/******************************************************************************/
    106113void DartWaveOut::Init(LPWAVEFORMATEX pwfx)
     114{
     115    MCI_GENERIC_PARMS  GenericParms;
     116    MCI_AMP_OPEN_PARMS AmpOpenParms;
     117    APIRET rc;
     118
     119    curPlayBuf = curFillBuf = curFillPos = curPlayPos = 0;
     120    readPos = writePos = 0;
     121
     122    fMixerSetup   = FALSE;
     123    next          = NULL;
     124    wavehdr       = NULL;
     125    curhdr        = NULL;
     126    mthdCallback  = NULL;
     127    hwndCallback  = 0;
     128    dwInstance    = 0;
     129    ulError       = 0;
     130    volume        = defvolume;
     131    State         = STATE_STOPPED;
     132
     133    MixBuffer     = (MCI_MIX_BUFFER *)malloc(PREFILLBUF_DART*sizeof(MCI_MIX_BUFFER));
     134    MixSetupParms = (MCI_MIXSETUP_PARMS *)malloc(sizeof(MCI_MIXSETUP_PARMS));
     135    BufferParms   = (MCI_BUFFER_PARMS *)malloc(sizeof(MCI_BUFFER_PARMS));
     136
     137    BitsPerSample   = pwfx->wBitsPerSample;
     138    SampleRate      = pwfx->nSamplesPerSec;
     139    this->nChannels = pwfx->nChannels;
     140    ulBufSize       = DART_BUFSIZE;
     141
     142    dprintf(("waveOutOpen: samplerate %d, numChan %d bps %d (%d), format %x", SampleRate, nChannels, BitsPerSample, pwfx->nBlockAlign, pwfx->wFormatTag));
     143    // Setup the open structure, pass the playlist and tell MCI_OPEN to use it
     144    memset(&AmpOpenParms,0,sizeof(AmpOpenParms));
     145
     146    AmpOpenParms.usDeviceID = ( USHORT ) 0;
     147    AmpOpenParms.pszDeviceType = ( PSZ ) MCI_DEVTYPE_AUDIO_AMPMIX;
     148
     149    rc = mciSendCommand(0, MCI_OPEN, MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
     150                       (PVOID) &AmpOpenParms, 0);
     151
     152    DeviceId = AmpOpenParms.usDeviceID;
     153    if(rc) {
     154        dprintf(("MCI_OPEN failed\n"));
     155        mciError(rc);
     156        ulError = MMSYSERR_NODRIVER;
     157    }
     158    if(rc == 0) {
     159        //Grab exclusive rights to device instance (NOT entire device)
     160        GenericParms.hwndCallback = 0;  //Not needed, so set to 0
     161        rc = mciSendCommand(DeviceId, MCI_ACQUIREDEVICE, MCI_EXCLUSIVE_INSTANCE,
     162                            (PVOID)&GenericParms, 0);
     163        if(rc) {
     164            dprintf(("MCI_ACQUIREDEVICE failed\n"));
     165            mciError(rc);
     166            ulError = MMSYSERR_NOTENABLED;
     167        }
     168    }
     169    State    = STATE_STOPPED;
     170
     171    setVolume(volume);
     172
     173    wmutex   = new VMutex();
     174    if(wmutex == NULL) {
     175        DebugInt3();
     176        ulError = MMSYSERR_NOTSUPPORTED;
     177    }
     178    if(wmutex)
     179        wmutex->enter(VMUTEX_WAIT_FOREVER);
     180
     181    if(waveout == NULL) {
     182        waveout = this;
     183    }
     184    else {
     185        DartWaveOut *dwave = waveout;
     186
     187        while(dwave->next) {
     188            dwave = dwave->next;
     189        }
     190        dwave->next = this;
     191    }
     192
     193    if(wmutex)
     194        wmutex->leave();
     195}
     196/******************************************************************************/
     197/******************************************************************************/
     198DartWaveOut::~DartWaveOut()
     199{
     200   MCI_GENERIC_PARMS    GenericParms;
     201
     202    if(!ulError) {
     203        // Generic parameters
     204        GenericParms.hwndCallback = 0;   //hwndFrame
     205
     206        // Stop the playback.
     207        mciSendCommand(DeviceId, MCI_STOP,MCI_WAIT, (PVOID)&GenericParms,0);
     208
     209        mciSendCommand(DeviceId, MCI_BUFFER,
     210                       MCI_WAIT | MCI_DEALLOCATE_MEMORY,
     211                       (PVOID)&BufferParms, 0);
     212
     213        // Generic parameters
     214        GenericParms.hwndCallback = 0;   //hwndFrame
     215
     216        // Close the device
     217        mciSendCommand(DeviceId, MCI_CLOSE, MCI_WAIT, (PVOID)&GenericParms, 0);
     218    }
     219
     220    if(wmutex)
     221        wmutex->enter(VMUTEX_WAIT_FOREVER);
     222
     223    State = STATE_STOPPED;
     224
     225    if(waveout == this) {
     226        waveout = this->next;
     227    }
     228    else {
     229        DartWaveOut *dwave = waveout;
     230
     231        while(dwave->next != this) {
     232            dwave = dwave->next;
     233        }
     234        dwave->next = this->next;
     235    }
     236    if(wmutex)
     237        wmutex->leave();
     238
     239    if(!ulError) {
     240        if(mthdCallback) {
     241            callback((ULONG)this, WOM_CLOSE, dwInstance, 0, 0);
     242        }
     243        else
     244        if(hwndCallback)
     245            PostMessageA(hwndCallback, WOM_CLOSE, 0, 0);
     246    }
     247
     248    if(wmutex)
     249        delete wmutex;
     250
     251    if(MixBuffer)
     252        free(MixBuffer);
     253    if(MixSetupParms)
     254        free(MixSetupParms);
     255    if(BufferParms)
     256        free(BufferParms);
     257}
     258/******************************************************************************/
     259/******************************************************************************/
     260MMRESULT DartWaveOut::getError()
     261{
     262    return(ulError);
     263}
     264/******************************************************************************/
     265/******************************************************************************/
     266int DartWaveOut::getNumDevices()
    107267{
    108268 MCI_GENERIC_PARMS  GenericParms;
     
    110270 APIRET rc;
    111271
    112    curPlayBuf = curFillBuf = curFillPos = curPlayPos = 0;
    113 
    114    fMixerSetup   = FALSE;
    115    next          = NULL;
    116    wavehdr       = NULL;
    117    curhdr        = NULL;
    118    mthdCallback  = NULL;
    119    hwndCallback  = 0;
    120    selCallback   = 0;
    121    dwInstance    = 0;
    122    ulError       = 0;
    123    selCallback   = 0;
    124    volume        = defvolume;
    125    State         = STATE_STOPPED;
    126 
    127    MixBuffer     = (MCI_MIX_BUFFER *)malloc(PREFILLBUF_DART*sizeof(MCI_MIX_BUFFER));
    128    MixSetupParms = (MCI_MIXSETUP_PARMS *)malloc(sizeof(MCI_MIXSETUP_PARMS));
    129    BufferParms   = (MCI_BUFFER_PARMS *)malloc(sizeof(MCI_BUFFER_PARMS));
    130 
    131    BitsPerSample   = pwfx->wBitsPerSample;
    132    SampleRate      = pwfx->nSamplesPerSec;
    133    this->nChannels = pwfx->nChannels;
    134    ulBufSize       = DART_BUFSIZE;
    135 
    136    dprintf(("waveOutOpen: samplerate %d, numChan %d bps %d (%d), format %x", SampleRate, nChannels, BitsPerSample, pwfx->nBlockAlign, pwfx->wFormatTag));
    137272   // Setup the open structure, pass the playlist and tell MCI_OPEN to use it
    138273   memset(&AmpOpenParms,0,sizeof(AmpOpenParms));
     
    145280                       (PVOID) &AmpOpenParms,
    146281                       0);
    147    DeviceId = AmpOpenParms.usDeviceID;
    148    if(rc) {
    149     dprintf(("MCI_OPEN failed\n"));
    150     mciError(rc);
    151     ulError = MMSYSERR_NODRIVER;
    152    }
    153    if(rc == 0) {
    154     //Grab exclusive rights to device instance (NOT entire device)
    155     GenericParms.hwndCallback = 0;  //Not needed, so set to 0
    156     rc = mciSendCommand(DeviceId, MCI_ACQUIREDEVICE, MCI_EXCLUSIVE_INSTANCE,
    157                         (PVOID)&GenericParms, 0);
    158     if(rc) {
    159         dprintf(("MCI_ACQUIREDEVICE failed\n"));
    160         mciError(rc);
    161         ulError = MMSYSERR_NOTENABLED;
    162     }
    163    }
    164    State    = STATE_STOPPED;
    165 
    166    setVolume(volume);
    167 
    168    wmutex   = new VMutex();
    169    if(wmutex == NULL) {
    170     DebugInt3();
    171     ulError = MMSYSERR_NOTSUPPORTED;
    172    }
    173    if(wmutex)
    174     wmutex->enter(VMUTEX_WAIT_FOREVER);
    175 
    176    if(waveout == NULL) {
    177     waveout = this;
    178    }
    179    else {
    180     DartWaveOut *dwave = waveout;
    181 
    182     while(dwave->next) {
    183         dwave = dwave->next;
    184     }
    185     dwave->next = this;
    186    }
    187 
    188    if(wmutex)
    189     wmutex->leave();
    190 }
    191 /******************************************************************************/
    192 /******************************************************************************/
    193 DartWaveOut::~DartWaveOut()
    194 {
    195    MCI_GENERIC_PARMS    GenericParms;
    196 
    197    if(!ulError) {
    198     // Generic parameters
    199     GenericParms.hwndCallback = 0;   //hwndFrame
    200 
    201     // Stop the playback.
    202     mciSendCommand(DeviceId, MCI_STOP,MCI_WAIT, (PVOID)&GenericParms,0);
    203 
    204     mciSendCommand(DeviceId,
    205                   MCI_BUFFER,
    206                   MCI_WAIT | MCI_DEALLOCATE_MEMORY,
    207                   (PVOID)&BufferParms,
    208                   0);
    209 
    210     // Generic parameters
    211     GenericParms.hwndCallback = 0;   //hwndFrame
    212 
    213     // Close the device
    214     mciSendCommand(DeviceId, MCI_CLOSE, MCI_WAIT, (PVOID)&GenericParms, 0);
    215    }
    216 
    217    if(wmutex)
    218         wmutex->enter(VMUTEX_WAIT_FOREVER);
    219 
    220    State = STATE_STOPPED;
    221 
    222    if(waveout == this) {
    223         waveout = this->next;
    224    }
    225    else {
    226         DartWaveOut *dwave = waveout;
    227 
    228         while(dwave->next != this) {
    229             dwave = dwave->next;
    230         }
    231         dwave->next = this->next;
    232    }
    233    if(wmutex)
    234         wmutex->leave();
    235 
    236    if(!ulError) {
    237         if(mthdCallback) {
    238             callback((ULONG)this, WOM_CLOSE, dwInstance, 0, 0);
    239         }
    240         else
    241         if(hwndCallback)
    242             PostMessageA(hwndCallback, WOM_CLOSE, 0, 0);
    243    }
    244 
    245    if(wmutex)
    246         delete wmutex;
    247 
    248    if(MixBuffer)
    249         free(MixBuffer);
    250    if(MixSetupParms)
    251         free(MixSetupParms);
    252    if(BufferParms)
    253         free(BufferParms);
    254 }
    255 /******************************************************************************/
    256 /******************************************************************************/
    257 MMRESULT DartWaveOut::getError()
    258 {
    259   return(ulError);
    260 }
    261 /******************************************************************************/
    262 /******************************************************************************/
    263 int DartWaveOut::getNumDevices()
    264 {
    265  MCI_GENERIC_PARMS  GenericParms;
    266  MCI_AMP_OPEN_PARMS AmpOpenParms;
    267  APIRET rc;
    268 
    269    // Setup the open structure, pass the playlist and tell MCI_OPEN to use it
    270    memset(&AmpOpenParms,0,sizeof(AmpOpenParms));
    271 
    272    AmpOpenParms.usDeviceID = ( USHORT ) 0;
    273    AmpOpenParms.pszDeviceType = ( PSZ ) MCI_DEVTYPE_AUDIO_AMPMIX;
    274 
    275    rc = mciSendCommand(0, MCI_OPEN,
    276                        MCI_WAIT | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE,
    277                        (PVOID) &AmpOpenParms,
    278                        0);
    279282
    280283   if(rc) {
     
    294297MMRESULT DartWaveOut::write(LPWAVEHDR pwh, UINT cbwh)
    295298{
    296  MCI_GENERIC_PARMS GenericParms = {0};
    297  APIRET rc;
    298  int i, buflength;
    299 
    300   if(fMixerSetup == FALSE)
    301   {
     299    MCI_GENERIC_PARMS GenericParms = {0};
     300    APIRET rc;
     301    int i, buflength;
     302
     303    if(fMixerSetup == FALSE)
     304    {
    302305        dprintf(("device acquired\n"));
    303306        /* Set the MixSetupParms data structure to match the loaded file.
     
    339342
    340343#if 1
    341         int consumerate = getAvgBytesPerSecond();
    342         int minbufsize = consumerate/32;
     344        int consumerate = getAvgBytesPerSecond();
     345        int minbufsize = consumerate/32;
    343346
    344347        ulBufSize = pwh->dwBufferLength/2;
    345         if(ulBufSize < minbufsize) {
    346                 dprintf(("set buffer size to %d bytes (org size = %d)", minbufsize, pwh->dwBufferLength));
    347                 ulBufSize = minbufsize;
    348         }
     348        if(ulBufSize > minbufsize) {
     349            dprintf(("set buffer size to %d bytes (org size = %d)", minbufsize, pwh->dwBufferLength));
     350            ulBufSize = minbufsize;
     351        }
    349352#else
    350353        if(pwh->dwBufferLength >= 512 && pwh->dwBufferLength <= 1024)
     
    380383
    381384        curPlayBuf = curFillBuf = curFillPos = curPlayPos = 0;
     385        readPos = writePos = 0;
    382386
    383387        for(i=0;i<PREFILLBUF_DART;i++) {
     
    389393        curhdr      = pwh;
    390394        pwh->lpNext = NULL;
     395        pwh->reserved = 0;
    391396
    392397        if(State != STATE_STOPPED) {//don't start playback if paused
    393                 wmutex->leave();
    394                 return(MMSYSERR_NOERROR);
    395         }
    396 
    397         while(TRUE) {
    398             buflength = min((ULONG)MixBuffer[curFillBuf].ulBufferLength - curPlayPos,
    399                             (ULONG)wavehdr->dwBufferLength - curFillPos);
    400             dprintf(("Copying %d data; curPlayPos = %d curFillPos = %d\n", buflength, curPlayPos, curFillPos));
    401 
    402             memcpy((char *)MixBuffer[curFillBuf].pBuffer + curPlayPos,
    403                    wavehdr->lpData + curFillPos,
    404                    buflength);
    405 
    406             curPlayPos  += buflength;
    407             curFillPos += buflength;
    408             if(curFillPos == wavehdr->dwBufferLength) {
    409                 dprintf(("Processed first win32 buffer\n"));
    410                 curFillPos        = 0;
    411                 wavehdr->dwFlags |= WHDR_DONE;
    412                 curhdr            = NULL;
    413             }
    414             if(curPlayPos == MixBuffer[curPlayBuf].ulBufferLength) {
    415                 if(++curPlayBuf == PREFILLBUF_DART) {
    416                     curPlayBuf = 0;
    417                     break;
    418                 }
    419                 curPlayPos = 0;
    420             }
    421             if(curFillPos == 0)
    422                 break;
    423         }
     398            wmutex->leave();
     399            return(MMSYSERR_NOERROR);
     400        }
     401
     402        writeBuffer();  //must be called before (re)starting playback
     403
    424404        dprintf(("MixSetupParms = %X\n", MixSetupParms));
    425405        State     = STATE_PLAYING;
     
    428408
    429409        //write buffers to DART; starts playback
    430         {
    431           // MCI_MIXSETUP_PARMS->pMixWrite does alter FS: selector!
    432           USHORT selTIB = GetFS(); // save current FS selector
    433 
    434           MixSetupParms->pmixWrite(MixSetupParms->ulMixHandle,
    435                                    MixBuffer,
    436                                    PREFILLBUF_DART);
    437           SetFS(selTIB);           // switch back to the saved FS selector
    438         }
     410        // MCI_MIXSETUP_PARMS->pMixWrite does alter FS: selector!
     411        USHORT selTIB = GetFS(); // save current FS selector
     412
     413        MixSetupParms->pmixWrite(MixSetupParms->ulMixHandle,
     414                                 MixBuffer,
     415                                 PREFILLBUF_DART);
     416        SetFS(selTIB);           // switch back to the saved FS selector
     417
    439418        dprintf(("Dart playing\n"));
    440   }
    441   else
    442   {
     419    }
     420    else
     421    {
     422        pwh->lpNext   = NULL;
     423        pwh->reserved = 0;
    443424        wmutex->enter(VMUTEX_WAIT_FOREVER);
    444         pwh->lpNext   = NULL;
    445425        if(wavehdr) {
    446426            WAVEHDR *chdr = wavehdr;
     
    450430            chdr->lpNext = pwh;
    451431        }
    452         else    wavehdr = pwh;
     432        else wavehdr = pwh;
     433
     434        writeBuffer();  //must be called before (re)starting playback
     435
    453436        wmutex->leave();
    454         if(State == STATE_STOPPED || fUnderrun) {//continue playback
     437        if(State == STATE_STOPPED) {//continue playback
    455438            restart();
    456439        }
    457   }
    458 
    459   return(MMSYSERR_NOERROR);
     440    }
     441    return(MMSYSERR_NOERROR);
    460442}
    461443/******************************************************************************/
     
    465447 MCI_GENERIC_PARMS Params;
    466448
    467   wmutex->enter(VMUTEX_WAIT_FOREVER);
    468   if(State != STATE_PLAYING) {
    469         State = STATE_PAUSED;
    470         wmutex->leave();
     449    wmutex->enter(VMUTEX_WAIT_FOREVER);
     450    if(State != STATE_PLAYING) {
     451        State = STATE_PAUSED;
     452        wmutex->leave();
    471453        return(MMSYSERR_NOERROR);
    472   }
    473 
    474   State = STATE_PAUSED;
    475   wmutex->leave();
    476 
    477   memset(&Params, 0, sizeof(Params));
    478 
    479   // Stop the playback.
    480   mciSendCommand(DeviceId, MCI_PAUSE, MCI_WAIT, (PVOID)&Params, 0);
    481 
    482   return(MMSYSERR_NOERROR);
     454    }
     455
     456    State = STATE_PAUSED;
     457    wmutex->leave();
     458
     459    memset(&Params, 0, sizeof(Params));
     460
     461    // Stop the playback.
     462    mciSendCommand(DeviceId, MCI_PAUSE, MCI_WAIT, (PVOID)&Params, 0);
     463
     464    return(MMSYSERR_NOERROR);
     465}
     466/******************************************************************************/
     467/******************************************************************************/
     468MMRESULT DartWaveOut::stop()
     469{
     470 MCI_GENERIC_PARMS Params;
     471
     472    dprintf(("DartWaveOut::stop %s", (State == STATE_PLAYING) ? "playing" : "stopped"));
     473    if(State != STATE_PLAYING)
     474        return(MMSYSERR_HANDLEBUSY);
     475
     476    memset(&Params, 0, sizeof(Params));
     477
     478    // Stop the playback.
     479    mciSendCommand(DeviceId, MCI_STOP, MCI_WAIT, (PVOID)&Params, 0);
     480
     481    State     = STATE_STOPPED;
     482    fUnderrun = FALSE;
     483
     484    curPlayBuf = curFillBuf = curFillPos = curPlayPos = 0;
     485    readPos = writePos = 0;
     486
     487    return(MMSYSERR_NOERROR);
    483488}
    484489/******************************************************************************/
     
    487492{
    488493 MCI_GENERIC_PARMS Params;
    489 
    490   dprintf(("DartWaveOut::reset %s", (State == STATE_PLAYING) ? "playing" : "stopped"));
    491   if(State != STATE_PLAYING)
     494 LPWAVEHDR tmpwavehdr;
     495
     496    dprintf(("DartWaveOut::reset %s", (State == STATE_PLAYING) ? "playing" : "stopped"));
     497    if(State != STATE_PLAYING)
    492498        return(MMSYSERR_HANDLEBUSY);
    493499
    494   memset(&Params, 0, sizeof(Params));
    495 
    496   // Stop the playback.
    497   mciSendCommand(DeviceId, MCI_STOP, MCI_WAIT, (PVOID)&Params, 0);
    498 
    499   dprintf(("Nr of threads blocked on mutex = %d\n", wmutex->getNrBlocked()));
    500 
    501   wmutex->enter(VMUTEX_WAIT_FOREVER);
    502   while(wavehdr) {
    503         wavehdr->dwFlags |= WHDR_DONE;
    504         wavehdr->dwFlags &= ~WHDR_INQUEUE;
    505         wavehdr = wavehdr->lpNext;
    506         wavehdr->lpNext = NULL;
    507         wmutex->leave();
    508         if(mthdCallback) {
    509                 callback((ULONG)this, WOM_DONE, dwInstance, (ULONG)wavehdr, 0);
    510         }
    511         else
     500    memset(&Params, 0, sizeof(Params));
     501
     502    // Stop the playback.
     503    mciSendCommand(DeviceId, MCI_STOP, MCI_WAIT, (PVOID)&Params, 0);
     504
     505    dprintf(("Nr of threads blocked on mutex = %d\n", wmutex->getNrBlocked()));
     506
     507    wmutex->enter(VMUTEX_WAIT_FOREVER);
     508    while(wavehdr)
     509    {
     510        wavehdr->dwFlags  |= WHDR_DONE;
     511        wavehdr->dwFlags  &= ~WHDR_INQUEUE;
     512        tmpwavehdr         = wavehdr;
     513        wavehdr            = wavehdr->lpNext;
     514        tmpwavehdr->lpNext = NULL;
     515        wmutex->leave();
     516
     517        if(mthdCallback) {
     518            callback((ULONG)this, WOM_DONE, dwInstance, (ULONG)tmpwavehdr, 0);
     519        }
     520        else
    512521        if(hwndCallback) {
    513                 dprintf(("Callback (msg) for buffer %x", wavehdr));
    514                 PostMessageA(hwndCallback, WOM_DONE, (WPARAM)this, (ULONG)wavehdr);
    515         }
    516         wmutex->enter(VMUTEX_WAIT_FOREVER);
    517   }
    518   wavehdr   = NULL;
    519   State     = STATE_STOPPED;
    520   fUnderrun = FALSE;
    521 
    522   wmutex->leave();
    523   return(MMSYSERR_NOERROR);
     522            dprintf(("Callback (msg) for buffer %x", tmpwavehdr));
     523            PostMessageA(hwndCallback, WOM_DONE, (WPARAM)this, (ULONG)tmpwavehdr);
     524        }
     525        wmutex->enter(VMUTEX_WAIT_FOREVER);
     526    }
     527    wavehdr   = NULL;
     528    State     = STATE_STOPPED;
     529    fUnderrun = FALSE;
     530
     531    curPlayBuf = curFillBuf = curFillPos = curPlayPos = 0;
     532    readPos = writePos = 0;
     533
     534    wmutex->leave();
     535    return(MMSYSERR_NOERROR);
    524536}
    525537/******************************************************************************/
     
    529541  int i, curbuf;
    530542
    531   dprintf(("DartWaveOut::restart"));
    532   if(State == STATE_PLAYING)
     543    dprintf(("DartWaveOut::restart"));
     544    if(State == STATE_PLAYING)
     545        return(MMSYSERR_NOERROR);
     546
     547    //Only write buffers to dart if mixer has been initialized; if not, then
     548    //the first buffer write will do this for us.
     549    if(fMixerSetup == TRUE)
     550    {
     551        wmutex->enter(VMUTEX_WAIT_FOREVER);
     552        State     = STATE_PLAYING;
     553        fUnderrun = FALSE;
     554        wmutex->leave();
     555        curbuf = curPlayBuf;
     556
     557        // MCI_MIXSETUP_PARMS->pMixWrite does alter FS: selector!
     558        USHORT selTIB = GetFS(); // save current FS selector
     559
     560        for(i=0;i<PREFILLBUF_DART;i++)
     561        {
     562            dprintf(("restart: write buffer at %x size %d", MixBuffer[curbuf].pBuffer, MixBuffer[curbuf].ulBufferLength));
     563            MixSetupParms->pmixWrite(MixSetupParms->ulMixHandle, &MixBuffer[curbuf], 1);
     564            if(++curbuf == PREFILLBUF_DART)
     565                curbuf = 0;
     566        }
     567        SetFS(selTIB);           // switch back to the saved FS selector
     568    }
    533569    return(MMSYSERR_NOERROR);
    534 
    535   //Only write buffers to dart if mixer has been initialized; if not, then
    536   //the first buffer write will do this for us.
    537   if(fMixerSetup == TRUE)
    538   {
    539     wmutex->enter(VMUTEX_WAIT_FOREVER);
    540     State     = STATE_PLAYING;
    541     fUnderrun = FALSE;
    542     wmutex->leave();
    543     curbuf = curPlayBuf;
    544    
    545     // MCI_MIXSETUP_PARMS->pMixWrite does alter FS: selector!
    546     USHORT selTIB = GetFS(); // save current FS selector
    547    
    548     for(i=0;i<PREFILLBUF_DART;i++)
    549     {
    550       MixSetupParms->pmixWrite(MixSetupParms->ulMixHandle, &MixBuffer[curbuf], 1);
    551       if(++curbuf == PREFILLBUF_DART)
    552         curbuf = 0;
    553     }
    554    
    555     SetFS(selTIB);           // switch back to the saved FS selector
    556   }
    557   return(MMSYSERR_NOERROR);
    558570}
    559571/******************************************************************************/
     
    585597 BOOL winrc;
    586598
    587   dprintf(("DartWaveOut::queryFormat %x srate=%d, nchan=%d, bps=%d", formatTag, nSamplesPerSec, nChannels, wBitsPerSample));
    588 
    589   memset(&mciOpenParms,            /* Object to fill with zeros.       */
    590          0,                        /* Value to place into the object.  */
    591          sizeof( mciOpenParms ) ); /* How many zero's to use.          */
    592 
    593   mciOpenParms.pszDeviceType = (PSZ)MCI_DEVTYPE_WAVEFORM_AUDIO;
    594 
    595   rc = mciSendCommand( (USHORT) 0,
    596                        MCI_OPEN,
    597                        MCI_WAIT | MCI_OPEN_TYPE_ID,
    598                        (PVOID) &mciOpenParms,
    599                        0);
    600   if((rc & 0xFFFF) != MCIERR_SUCCESS) {
     599    dprintf(("DartWaveOut::queryFormat %x srate=%d, nchan=%d, bps=%d", formatTag, nSamplesPerSec, nChannels, wBitsPerSample));
     600
     601    memset(&mciOpenParms,            /* Object to fill with zeros.       */
     602           0,                        /* Value to place into the object.  */
     603           sizeof( mciOpenParms ) ); /* How many zero's to use.          */
     604
     605    mciOpenParms.pszDeviceType = (PSZ)MCI_DEVTYPE_WAVEFORM_AUDIO;
     606
     607    rc = mciSendCommand( (USHORT) 0,
     608                        MCI_OPEN,
     609                        MCI_WAIT | MCI_OPEN_TYPE_ID,
     610                        (PVOID) &mciOpenParms,
     611                        0);
     612    if((rc & 0xFFFF) != MCIERR_SUCCESS) {
    601613        mciError(rc);
    602614        return(FALSE);
    603   }
    604   DeviceId = mciOpenParms.usDeviceID;
    605 
    606   memset( &mciAudioCaps , 0, sizeof(MCI_WAVE_GETDEVCAPS_PARMS));
    607 
    608   mciAudioCaps.ulBitsPerSample = wBitsPerSample;
    609   mciAudioCaps.ulFormatTag     = DATATYPE_WAVEFORM;
    610   mciAudioCaps.ulSamplesPerSec = nSamplesPerSec;
    611   mciAudioCaps.ulChannels      = nChannels;
    612   mciAudioCaps.ulFormatMode    = MCI_PLAY;
    613   mciAudioCaps.ulItem          = MCI_GETDEVCAPS_WAVE_FORMAT;
    614 
    615   rc = mciSendCommand(DeviceId,   /* Device ID    */
    616                       MCI_GETDEVCAPS,
    617                       MCI_WAIT | MCI_GETDEVCAPS_EXTENDED | MCI_GETDEVCAPS_ITEM,
    618                       (PVOID) &mciAudioCaps,
    619                       0);
    620   if((rc & 0xFFFF) != MCIERR_SUCCESS) {
     615    }
     616    DeviceId = mciOpenParms.usDeviceID;
     617
     618    memset( &mciAudioCaps , 0, sizeof(MCI_WAVE_GETDEVCAPS_PARMS));
     619
     620    mciAudioCaps.ulBitsPerSample = wBitsPerSample;
     621    mciAudioCaps.ulFormatTag     = DATATYPE_WAVEFORM;
     622    mciAudioCaps.ulSamplesPerSec = nSamplesPerSec;
     623    mciAudioCaps.ulChannels      = nChannels;
     624    mciAudioCaps.ulFormatMode    = MCI_PLAY;
     625    mciAudioCaps.ulItem          = MCI_GETDEVCAPS_WAVE_FORMAT;
     626
     627    rc = mciSendCommand(DeviceId,   /* Device ID    */
     628                        MCI_GETDEVCAPS,
     629                        MCI_WAIT | MCI_GETDEVCAPS_EXTENDED | MCI_GETDEVCAPS_ITEM,
     630                        (PVOID) &mciAudioCaps,
     631                        0);
     632    if((rc & 0xFFFF) != MCIERR_SUCCESS) {
    621633        mciError(rc);
    622634        winrc = FALSE;
    623   }
    624   else  winrc = TRUE;
    625 
    626   // Close the device
    627   mciSendCommand(DeviceId,MCI_CLOSE,MCI_WAIT,(PVOID)&GenericParms,0);
    628   return(winrc);
     635    }
     636    else  winrc = TRUE;
     637
     638    // Close the device
     639    mciSendCommand(DeviceId,MCI_CLOSE,MCI_WAIT,(PVOID)&GenericParms,0);
     640    return(winrc);
    629641}
    630642/******************************************************************************/
     
    633645{
    634646#ifdef DEBUG
    635  char szError[256] = "";
    636 
    637   mciGetErrorString(ulError, szError, sizeof(szError));
    638   dprintf(("WINMM: DartWaveOut: %s\n", szError));
     647    char szError[256] = "";
     648
     649    mciGetErrorString(ulError, szError, sizeof(szError));
     650    dprintf(("WINMM: DartWaveOut: %s\n", szError));
    639651#endif
    640652}
     
    645657 DartWaveOut *curwave = waveout;
    646658
    647   while(curwave) {
    648     if(dwave == curwave) {
    649         return(TRUE);
    650     }
    651     curwave = curwave->next;
    652   }
    653 
    654 #ifdef DEBUG
    655 //  WriteLog("WINMM:DartWaveOut not found!\n");
    656 #endif
    657   return(FALSE);
     659    while(curwave) {
     660        if(dwave == curwave) {
     661            return(TRUE);
     662        }
     663        curwave = curwave->next;
     664    }
     665
     666    dprintf2(("WINMM:DartWaveOut not found!\n"));
     667    return(FALSE);
    658668}
    659669/******************************************************************************/
     
    664674 WAVEHDR *whdr, *prevhdr = NULL;
    665675
    666 #ifdef DEBUG1
    667   dprintf(("WINMM: handler %d\n", curPlayBuf));
    668 #endif
    669   if(ulFlags == MIX_STREAM_ERROR) {
    670     if(ulStatus == ERROR_DEVICE_UNDERRUN) {
    671         dprintf(("WINMM: WaveOut handler UNDERRUN!\n"));
    672         if(State == STATE_PLAYING) {
    673                 fUnderrun = TRUE;
    674                 pause();    //out of buffers, so pause playback
    675         }
     676    dprintf2(("WINMM: handler %d\n", curPlayBuf));
     677    if(ulFlags == MIX_STREAM_ERROR) {
     678        if(ulStatus == ERROR_DEVICE_UNDERRUN) {
     679            dprintf(("WINMM: WaveOut handler UNDERRUN! state %s", (State == STATE_PLAYING) ? "playing" : "stopped"));
     680            if(State == STATE_PLAYING) {
     681                fUnderrun = TRUE;
     682                stop();    //out of buffers, so stop playback
     683            }
     684            return;
     685        }
     686        dprintf(("WINMM: WaveOut handler, Unknown error %X\n", ulStatus));
    676687        return;
    677688    }
    678     dprintf(("WINMM: WaveOut handler, Unknown error %X\n", ulStatus));
    679     return;
    680   }
    681   wmutex->enter(VMUTEX_WAIT_FOREVER);
    682 
    683   whdr = wavehdr;
    684   if(whdr == NULL) {
     689    if(State != STATE_PLAYING) {
     690        return;
     691    }
     692
     693    wmutex->enter(VMUTEX_WAIT_FOREVER);
     694
     695    readPos += MixBuffer[curPlayBuf].ulBufferLength;
     696
     697    if(curPlayBuf == PREFILLBUF_DART-1)
     698         curPlayBuf = 0;
     699    else curPlayBuf++;
     700
     701    whdr = wavehdr;
     702    if(whdr == NULL) {
     703        //last buffer played -> no new ones -> silence buffer & continue
     704        dprintf(("WINMM: WaveOut handler LAST BUFFER PLAYED! state %s", (State == STATE_PLAYING) ? "playing" : "stopped"));
     705        if(State == STATE_PLAYING) {
     706            fUnderrun = TRUE;
     707////            memset(MixBuffer[curPlayBuf].pBuffer, 0, MixBuffer[curPlayBuf].ulBufferLength);
     708            goto sendbuffer;
     709        }
    685710        wmutex->leave();
    686         //last buffer played -> no new ones -> underrun; pause playback
    687         dprintf(("WINMM: WaveOut handler UNDERRUN!\n"));
    688         if(State == STATE_PLAYING) {
    689                 fUnderrun = TRUE;
    690                 pause();    //out of buffers, so pause playback
    691         }
    692711        return;
    693   }
    694   while(whdr) {
    695     if(whdr->dwFlags & WHDR_DONE) {
    696 #ifdef DEBUG1
    697         dprintf(("WINMM: handler buf %X done\n", whdr));
    698 #endif
    699         whdr->dwFlags &= ~WHDR_INQUEUE;
    700 
    701         if(prevhdr == NULL)
    702                 wavehdr = whdr->lpNext;
    703         else    prevhdr->lpNext = whdr->lpNext;
    704 
    705         whdr->lpNext = NULL;
    706         wmutex->leave();
    707 
    708         if(mthdCallback) {
    709             callback((ULONG)this, WOM_DONE, dwInstance, (ULONG)whdr, 0);
    710         }
    711         else
    712         if(hwndCallback) {
    713                 dprintf(("Callback (msg) for buffer %x", whdr));
    714                 PostMessageA(hwndCallback, WOM_DONE, (WPARAM)this, (ULONG)whdr);
    715         }
    716 
    717         wmutex->enter(VMUTEX_WAIT_FOREVER);
    718     }
    719     prevhdr = whdr;
    720     whdr    = whdr->lpNext;
    721   }
    722 
    723   if(curhdr == NULL)
    724     curhdr = wavehdr;
    725 
    726 #ifdef DEBUG1
    727   dprintf(("WINMM: handler cur (%d,%d), fill (%d,%d)\n", curPlayBuf, curPlayPos, curFillBuf, curFillPos));
    728 #endif
    729 
    730   while(curhdr) {
    731     buflength = min((ULONG)MixBuffer[curFillBuf].ulBufferLength - curPlayPos,
    732             (ULONG)curhdr->dwBufferLength - curFillPos);
    733     memcpy((char *)MixBuffer[curFillBuf].pBuffer + curPlayPos,
    734            curhdr->lpData + curFillPos,
    735            buflength);
    736     curPlayPos += buflength;
    737     curFillPos += buflength;
    738 #ifdef DEBUG1
    739     dprintf(("WINMM: copied %d bytes, cufFillPos = %d, dwBufferLength = %d\n", buflength, curFillPos, curhdr->dwBufferLength));
    740 #endif
    741     if(curFillPos == curhdr->dwBufferLength) {
    742 #ifdef DEBUG1
    743         dprintf(("Buffer %d done\n", curFillBuf));
    744 #endif
    745         curFillPos = 0;
    746         curhdr->dwFlags |= WHDR_DONE;
    747         //search for next unprocessed buffer
    748         while(curhdr && curhdr->dwFlags & WHDR_DONE)
    749             curhdr = curhdr->lpNext;
    750     }
    751     if(curPlayPos == MixBuffer[curFillBuf].ulBufferLength) {
    752         curPlayPos = 0;
    753         if(++curFillBuf == PREFILLBUF_DART) {
    754             curFillBuf = 0;
    755         }
    756         if(curFillBuf == curPlayBuf)
    757             break;  //no more room left
    758     }
    759   }
    760 
    761   if(curPlayBuf == PREFILLBUF_DART-1)
    762         curPlayBuf = 0;
    763   else  curPlayBuf++;
    764 
    765   wmutex->leave();
    766  
    767   //Transfer buffer to DART
    768   // MCI_MIXSETUP_PARMS->pMixWrite does alter FS: selector!
    769   USHORT selTIB = GetFS(); // save current FS selector
    770   MixSetupParms->pmixWrite(MixSetupParms->ulMixHandle, &MixBuffer[curPlayBuf], 1);
    771   SetFS(selTIB);           // switch back to the saved FS selector
     712    }
     713    fUnderrun = FALSE;
     714    while(whdr) {
     715        if(whdr->reserved == WHDR_DONE)
     716        {
     717            if(readPos < writePos + whdr->dwBufferLength) {
     718                dprintf2(("Buffer marked done, but not yet played completely (%d,%d)", readPos, writePos));
     719                break;  //not yet done
     720            }
     721
     722            dprintf2(("WINMM: handler buf %X done (read %d, write %d)", whdr, readPos, writePos));
     723            whdr->dwFlags &= ~WHDR_INQUEUE;
     724            whdr->dwFlags |= WHDR_DONE;
     725
     726            if(prevhdr == NULL)
     727                 wavehdr = whdr->lpNext;
     728            else prevhdr->lpNext = whdr->lpNext;
     729
     730            whdr->lpNext = NULL;
     731
     732            writePos += whdr->dwBufferLength;
     733            wmutex->leave();
     734
     735            if(mthdCallback) {
     736                callback((ULONG)this, WOM_DONE, dwInstance, (ULONG)whdr, 0);
     737            }
     738            else
     739            if(hwndCallback) {
     740                dprintf(("Callback (msg) for buffer %x", whdr));
     741                PostMessageA(hwndCallback, WOM_DONE, (WPARAM)this, (ULONG)whdr);
     742            }
     743
     744            wmutex->enter(VMUTEX_WAIT_FOREVER);
     745        }
     746        else break;
     747
     748        prevhdr = whdr;
     749        whdr    = whdr->lpNext;
     750    }
     751
     752    writeBuffer();
     753
     754sendbuffer:
     755    wmutex->leave();
     756
     757    //Transfer buffer to DART
     758    // MCI_MIXSETUP_PARMS->pMixWrite does alter FS: selector!
     759    USHORT selTIB = GetFS(); // save current FS selector
     760    MixSetupParms->pmixWrite(MixSetupParms->ulMixHandle, &MixBuffer[curPlayBuf], 1);
     761    SetFS(selTIB);           // switch back to the saved FS selector
     762}
     763/******************************************************************************/
     764/******************************************************************************/
     765void DartWaveOut::writeBuffer()
     766{
     767    ULONG buflength;
     768
     769    if(!fUnderrun && State == STATE_PLAYING && curFillBuf == curPlayBuf) {
     770        dprintf2(("writeBuffer: no more room for more audio data"));
     771        return; //no room left
     772    }
     773
     774    if(curhdr == NULL)
     775        curhdr = wavehdr;
     776
     777    while(curhdr && (curhdr->reserved == WHDR_DONE))  {
     778        curhdr = curhdr->lpNext;
     779    }
     780
     781    if(curhdr == NULL) {
     782        return;     //no unprocessed buffers left
     783    }
     784
     785    dprintf2(("WINMM: handler cur (%d,%d), fill (%d,%d)\n", curPlayBuf, curPlayPos, curFillBuf, curFillPos));
     786
     787    while(curhdr) {
     788        buflength = min((ULONG)MixBuffer[curFillBuf].ulBufferLength - curPlayPos,
     789                        (ULONG)curhdr->dwBufferLength - curFillPos);
     790        dprintf2(("WINMM: copied %d bytes, cufFillPos = %d, dwBufferLength = %d\n", buflength, curFillPos, curhdr->dwBufferLength));
     791
     792        memcpy((char *)MixBuffer[curFillBuf].pBuffer + curPlayPos,
     793               curhdr->lpData + curFillPos,  buflength);
     794        curPlayPos += buflength;
     795        curFillPos += buflength;
     796
     797
     798        if(curFillPos == curhdr->dwBufferLength) {
     799            dprintf2(("Buffer %d done (%x)", curFillBuf, curhdr));
     800            curFillPos = 0;
     801            curhdr->reserved = WHDR_DONE;
     802            //search for next unprocessed buffer
     803            while(curhdr && (curhdr->reserved == WHDR_DONE))
     804                curhdr = curhdr->lpNext;
     805        }
     806        if(curPlayPos == MixBuffer[curFillBuf].ulBufferLength) {
     807            curPlayPos = 0;
     808            if(++curFillBuf == PREFILLBUF_DART) {
     809                curFillBuf = 0;
     810            }
     811            if(curFillBuf == curPlayBuf)
     812                break;  //no more room left
     813        }
     814    }
    772815}
    773816/******************************************************************************/
     
    777820                             ULONG ulFlags)
    778821{
    779   // PTIB ptib;
    780   // PPIB ppib;
    781   // DosGetInfoBlocks(&ptib, &ppib);
    782   // dprintf(("WaveOutHandler: thread %d prio %X", ptib->tib_ptib2->tib2_ultid, ptib->tib_ptib2->tib2_ulpri));
    783 
    784   DartWaveOut *dwave;
    785 
    786   if(pBuffer && pBuffer->ulUserParm)
    787   {
    788     dwave = (DartWaveOut *)pBuffer->ulUserParm;
    789     dwave->handler(ulStatus, pBuffer, ulFlags);
    790   }
    791   return(TRUE);
     822 PTIB2 ptib2;
     823 DartWaveOut *dwave;
     824
     825    ptib2 = (PTIB2)_getTIBvalue(offsetof(TIB, tib_ptib2));
     826    if(ptib2 && HIBYTE(ptib2->tib2_ulpri) != PRTYC_TIMECRITICAL) {
     827        dprintf(("Setting priority of DART thread to PRTYC_TIMECRITICAL"));
     828        DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0);
     829    }
     830    if(pBuffer && pBuffer->ulUserParm)
     831    {
     832        dwave = (DartWaveOut *)pBuffer->ulUserParm;
     833        dwave->handler(ulStatus, pBuffer, ulFlags);
     834    }
     835    return(TRUE);
    792836}
    793837
  • trunk/src/winmm/dwaveout.h

    r3852 r5334  
    1 /* $Id: dwaveout.h,v 1.10 2000-07-18 18:34:43 sandervl Exp $ */
     1/* $Id: dwaveout.h,v 1.11 2001-03-19 19:28:38 sandervl Exp $ */
    22
    33/*
     
    3232{
    3333public:
    34               DartWaveOut(LPWAVEFORMATEX pwfx, ULONG nCallback, ULONG dwInstance, USHORT usSel);
     34              DartWaveOut(LPWAVEFORMATEX pwfx, ULONG nCallback, ULONG dwInstance);
    3535              DartWaveOut(LPWAVEFORMATEX pwfx, HWND hwndCallback);
    3636              DartWaveOut(LPWAVEFORMATEX pwfx);
     
    4040     MMRESULT write(LPWAVEHDR pwh, UINT cbwh);
    4141     MMRESULT pause();
     42     MMRESULT stop();
    4243     MMRESULT restart();
    4344     MMRESULT setVolume(ULONG ulVol);
     
    6667
    6768private:
     69         void writeBuffer();
     70
    6871        USHORT DeviceId;
    6972        ULONG  ulBufferCount;             /* Current file buffer     */
     
    7780    MCI_BUFFER_PARMS   *BufferParms;                /* Device buffer parms     */
    7881
    79     int SampleRate;
    80     int BitsPerSample;
    81     int nChannels;
    82     int curPlayBuf, curFillBuf;
    83     int curFillPos, curPlayPos; //fillpos == pos in os2 mix buffer, bufpos == pos in win buffer
     82    int   SampleRate;
     83    int   BitsPerSample;
     84    int   nChannels;
     85    int   curPlayBuf, curFillBuf;
     86    ULONG curFillPos, curPlayPos; //fillpos == pos in os2 mix buffer, bufpos == pos in win buffer
     87    ULONG readPos, writePos;
    8488
    8589    // callback interface
    8690    LPDRVCALLBACK mthdCallback; // pointer to win32 routine for the callback
    87     USHORT        selCallback;  // the win32 tib selector for the callback (saved at waveOutOpen)
    8891    void          callback(HDRVR h, UINT uMessage, DWORD dwUser, DWORD dw1, DWORD dw2);
    8992    HWND          hwndCallback;
  • trunk/src/winmm/wavein.cpp

    r5273 r5334  
    1 /* $Id: wavein.cpp,v 1.7 2001-02-27 21:17:01 sandervl Exp $ */
     1/* $Id: wavein.cpp,v 1.8 2001-03-19 19:28:38 sandervl Exp $ */
    22
    33/*
     
    6868  if(fdwOpen == CALLBACK_FUNCTION)
    6969  {
    70         //@@@PH 1999/12/28 save valid FS: to win32 TIB
    71         *phwi = (HWAVEOUT)new DartWaveIn(pwfx, dwCallback, dwInstance, GetFS());
     70        *phwi = (HWAVEOUT)new DartWaveIn(pwfx, dwCallback, dwInstance);
    7271  }
    7372  else  *phwi = (HWAVEOUT)new DartWaveIn(pwfx);
  • trunk/src/winmm/waveout.cpp

    r5272 r5334  
    1 /* $Id: waveout.cpp,v 1.17 2001-02-27 21:14:00 sandervl Exp $ */
     1/* $Id: waveout.cpp,v 1.18 2001-03-19 19:28:39 sandervl Exp $ */
    22//#undef DEBUG
    33/*
     
    7373  if(fdwOpen == CALLBACK_FUNCTION)
    7474  {
    75         //@@@PH 1999/12/28 save valid FS: to win32 TIB
    76         *phwo = (HWAVEOUT)new DartWaveOut(pwfx, dwCallback, dwInstance, GetFS());
     75        *phwo = (HWAVEOUT)new DartWaveOut(pwfx, dwCallback, dwInstance);
    7776  }
    7877  else  *phwo = (HWAVEOUT)new DartWaveOut(pwfx);
     
    240239        case TIME_BYTES:
    241240            pmmt->u.cb = position;
     241            dprintf2(("WINMM:waveOutGetPosition: TIME_BYTES %d (%x)", position, GetCurrentTime()));
    242242            break;
    243243        case TIME_SAMPLES:
    244244            pmmt->u.sample = position * 8 / dwave->getBitsPerSample();
     245            dprintf2(("WINMM:waveOutGetPosition: TIME_SAMPLES %d", pmmt->u.sample));
    245246            break;
    246247        case TIME_SMPTE:
     
    255256            pmmt->u.smpte.frame = timeval;
    256257            pmmt->u.smpte.fps = 30;
     258            dprintf2(("WINMM:waveOutGetPosition: TIME_SAMPLES %d", position));
    257259            break;
    258260        }
     
    262264        case TIME_MS:
    263265            pmmt->u.ms = position / (dwave->getAvgBytesPerSecond() / 1000);
    264             dprintf(("WINMM:waveOutGetPosition: TIME_MS pos=%d ms=%d time=%d", position, pmmt->u.ms, GetCurrentTime()));
     266            dprintf2(("WINMM:waveOutGetPosition: TIME_MS pos=%d ms=%d time=%d", position, pmmt->u.ms, GetCurrentTime()));
    265267            break;
    266268        }
Note: See TracChangeset for help on using the changeset viewer.