diff src/audio/dart/SDL_dart.c @ 2049:5f6550e5184f

Merged SDL-ryan-multiple-audio-device branch r2803:2871 into the trunk.
author Ryan C. Gordon <icculus@icculus.org>
date Tue, 17 Oct 2006 09:15:21 +0000
parents adf732f1f016
children 866052b01ee5
line wrap: on
line diff
--- a/src/audio/dart/SDL_dart.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/dart/SDL_dart.c	Tue Oct 17 09:15:21 2006 +0000
@@ -42,10 +42,10 @@
 //---------------------------------------------------------------------
 // DARTEventFunc
 //
-// This function is called by DART, when an event occures, like end of 
+// This function is called by DART, when an event occurs, like end of
 // playback of a buffer, etc...
 //---------------------------------------------------------------------
-LONG APIENTRY
+static LONG APIENTRY
 DARTEventFunc(ULONG ulStatus, PMCI_MIX_BUFFER pBuffer, ULONG ulFlags)
 {
     if (ulFlags && MIX_WRITE_COMPLETE) {        // Playback of buffer completed!
@@ -71,13 +71,12 @@
 }
 
 
-int
-DART_OpenAudio(_THIS, SDL_AudioSpec * spec)
+static int
+DART_OpenDevice(_THIS, const char *devname, int iscapture)
 {
-    SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format);
+    SDL_AudioFormat test_format = SDL_FirstAudioFormat(_this->spec.format);
     int valid_datatype = 0;
     MCI_AMP_OPEN_PARMS AmpOpenParms;
-    MCI_GENERIC_PARMS GenericParms;
     int iDeviceOrd = 0;         // Default device to be used
     int bOpenShared = 1;        // Try opening it shared
     int iBits = 16;             // Default is 16 bits signed
@@ -89,6 +88,15 @@
     int iSilence;
     int rc;
 
+    /* Initialize all variables that we clean on shutdown */
+    _this->hidden = (struct SDL_PrivateAudioData *)
+                        SDL_malloc((sizeof *_this->hidden));
+    if (_this->hidden == NULL) {
+        SDL_OutOfMemory();
+        return 0;
+    }
+    SDL_memset(_this->hidden, 0, (sizeof *_this->hidden));
+
     // First thing is to try to open a given DART device!
     SDL_memset(&AmpOpenParms, 0, sizeof(MCI_AMP_OPEN_PARMS));
     // pszDeviceType should contain the device type in low word, and device ordinal in high word!
@@ -100,30 +108,34 @@
         iOpenMode |= MCI_OPEN_SHAREABLE;
 
     rc = mciSendCommand(0, MCI_OPEN, iOpenMode, (PVOID) & AmpOpenParms, 0);
-    if (rc != MCIERR_SUCCESS)   // No audio available??
-        return (-1);
+    if (rc != MCIERR_SUCCESS) {  // No audio available??
+        DART_CloseDevice(_this);
+        SDL_SetError("DART: Couldn't open audio device.");
+        return 0;
+    }
+
     // Save the device ID we got from DART!
     // We will use this in the next calls!
-    iDeviceOrd = AmpOpenParms.usDeviceID;
+    _this->hidden->iCurrDeviceOrd = iDeviceOrd = AmpOpenParms.usDeviceID;
 
     // Determine the audio parameters from the AudioSpec
-    if (spec->channels > 2)
-        spec->channels = 2;     // !!! FIXME: more than stereo support in OS/2?
+    if (_this->spec.channels > 4)
+        _this->spec.channels = 4;
 
     while ((!valid_datatype) && (test_format)) {
-        spec->format = test_format;
+        _this->spec.format = test_format;
         valid_datatype = 1;
         switch (test_format) {
         case AUDIO_U8:
             // Unsigned 8 bit audio data
             iSilence = 0x80;
-            iBits = 8;
+            _this->hidden->iCurrBits = iBits = 8;
             break;
 
         case AUDIO_S16LSB:
             // Signed 16 bit audio data
             iSilence = 0x00;
-            iBits = 16;
+            _this->hidden->iCurrBits = iBits = 16;
             break;
 
             // !!! FIXME: int32?
@@ -137,16 +149,16 @@
 
     if (!valid_datatype) {      // shouldn't happen, but just in case...
         // Close DART, and exit with error code!
-        mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
+        DART_CloseDevice(_this);
         SDL_SetError("Unsupported audio format");
-        return (-1);
+        return 0;
     }
 
-    iFreq = spec->freq;
-    iChannels = spec->channels;
+    _this->hidden->iCurrFreq = iFreq = _this->spec.freq;
+    _this->hidden->iCurrChannels = iChannels = _this->spec.channels;
     /* Update the fragment size as size in bytes */
-    SDL_CalculateAudioSpec(spec);
-    iBufSize = spec->size;
+    SDL_CalculateAudioSpec(&_this->spec);
+    _this->hidden->iCurrBufSize = iBufSize = _this->spec.size;
 
     // Now query this device if it supports the given freq/bits/channels!
     SDL_memset(&(_this->hidden->MixSetupParms), 0,
@@ -163,9 +175,9 @@
                         &(_this->hidden->MixSetupParms), 0);
     if (rc != MCIERR_SUCCESS) { // The device cannot handle this format!
         // Close DART, and exit with error code!
-        mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
+        DART_CloseDevice(_this);
         SDL_SetError("Audio device doesn't support requested audio format");
-        return (-1);
+        return 0;
     }
     // The device can handle this format, so initialize!
     rc = mciSendCommand(iDeviceOrd, MCI_MIXSETUP,
@@ -173,9 +185,9 @@
                         &(_this->hidden->MixSetupParms), 0);
     if (rc != MCIERR_SUCCESS) { // The device could not be opened!
         // Close DART, and exit with error code!
-        mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
+        DART_CloseDevice(_this);
         SDL_SetError("Audio device could not be set up");
-        return (-1);
+        return 0;
     }
     // Ok, the device is initialized.
     // Now we should allocate buffers. For this, we need a place where
@@ -184,9 +196,9 @@
         (MCI_MIX_BUFFER *) SDL_malloc(sizeof(MCI_MIX_BUFFER) * iNumBufs);
     if (!(_this->hidden->pMixBuffers)) {        // Not enough memory!
         // Close DART, and exit with error code!
-        mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
-        SDL_SetError("Not enough memory for audio buffer descriptors");
-        return (-1);
+        DART_CloseDevice(_this);
+        SDL_OutOfMemory();
+        return 0;
     }
     // Now that we have the place for buffer list, we can ask DART for the
     // buffers!
@@ -201,12 +213,12 @@
         || (iNumBufs != _this->hidden->BufferParms.ulNumBuffers)
         || (_this->hidden->BufferParms.ulBufferSize == 0)) {    // Could not allocate memory!
         // Close DART, and exit with error code!
-        SDL_free(_this->hidden->pMixBuffers);
-        _this->hidden->pMixBuffers = NULL;
-        mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
+        DART_CloseDevice(_this);
         SDL_SetError("DART could not allocate buffers");
-        return (-1);
+        return 0;
     }
+    _this->hidden->iCurrNumBufs = iNumBufs;
+
     // Ok, we have all the buffers allocated, let's mark them!
     {
         int i;
@@ -216,24 +228,9 @@
             // Check if this buffer was really allocated by DART
             if ((!(_this->hidden->pMixBuffers[i].pBuffer))
                 || (!pBufferDesc)) {    // Wrong buffer!
-                // Close DART, and exit with error code!
-                // Free buffer descriptions
-                {
-                    int j;
-                    for (j = 0; j < i; j++)
-                        SDL_free((void *) (_this->hidden->pMixBuffers[j].
-                                           ulUserParm));
-                }
-                // and cleanup
-                mciSendCommand(iDeviceOrd, MCI_BUFFER,
-                               MCI_WAIT | MCI_DEALLOCATE_MEMORY,
-                               &(_this->hidden->BufferParms), 0);
-                SDL_free(_this->hidden->pMixBuffers);
-                _this->hidden->pMixBuffers = NULL;
-                mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT,
-                               &GenericParms, 0);
+                DART_CloseDevice(_this);
                 SDL_SetError("Error at internal buffer check");
-                return (-1);
+                return 0;
             }
             pBufferDesc->iBufferUsage = BUFFER_EMPTY;
             pBufferDesc->pSDLAudioDevice = _this;
@@ -254,43 +251,41 @@
     if (DosCreateEventSem
         (NULL, &(_this->hidden->hevAudioBufferPlayed), 0, FALSE) != NO_ERROR)
     {
-        // Could not create event semaphore!
-        {
-            int i;
-            for (i = 0; i < iNumBufs; i++)
-                SDL_free((void *) (_this->hidden->pMixBuffers[i].ulUserParm));
-        }
-        mciSendCommand(iDeviceOrd, MCI_BUFFER,
-                       MCI_WAIT | MCI_DEALLOCATE_MEMORY,
-                       &(_this->hidden->BufferParms), 0);
-        SDL_free(_this->hidden->pMixBuffers);
-        _this->hidden->pMixBuffers = NULL;
-        mciSendCommand(iDeviceOrd, MCI_CLOSE, MCI_WAIT, &GenericParms, 0);
+        DART_CloseDevice(_this);
         SDL_SetError("Could not create event semaphore");
-        return (-1);
+        return 0;
     }
-    // Store the new settings in global variables
-    _this->hidden->iCurrDeviceOrd = iDeviceOrd;
-    _this->hidden->iCurrFreq = iFreq;
-    _this->hidden->iCurrBits = iBits;
-    _this->hidden->iCurrChannels = iChannels;
-    _this->hidden->iCurrNumBufs = iNumBufs;
-    _this->hidden->iCurrBufSize = iBufSize;
 
-    return (0);
+    return 1;
 }
 
-
-
-void
+static void
 DART_ThreadInit(_THIS)
 {
-    return;
+    /* Increase the priority of this thread to make sure that
+       the audio will be continuous all the time! */
+#ifdef USE_DOSSETPRIORITY
+    if (SDL_getenv("SDL_USE_TIMECRITICAL_AUDIO")) {
+#ifdef DEBUG_BUILD
+        printf
+            ("[DART_ThreadInit] : Setting priority to TimeCritical+0! (TID%d)\n",
+             SDL_ThreadID());
+#endif
+        DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0);
+    } else {
+#ifdef DEBUG_BUILD
+        printf
+            ("[DART_ThreadInit] : Setting priority to ForegroundServer+0! (TID%d)\n",
+             SDL_ThreadID());
+#endif
+        DosSetPriority(PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0);
+    }
+#endif
 }
 
 /* This function waits until it is possible to write a full sound buffer */
-void
-DART_WaitAudio(_THIS)
+static void
+DART_WaitDevice(_THIS)
 {
     int i;
     pMixBufferDesc pBufDesc;
@@ -308,8 +303,8 @@
     return;
 }
 
-void
-DART_PlayAudio(_THIS)
+static void
+DART_PlayDevice(_THIS)
 {
     int iFreeBuf = _this->hidden->iNextFreeBuffer;
     pMixBufferDesc pBufDesc;
@@ -328,8 +323,8 @@
     _this->hidden->iNextFreeBuffer = iFreeBuf;
 }
 
-Uint8 *
-DART_GetAudioBuf(_THIS)
+static Uint8 *
+DART_GetDeviceBuf(_THIS)
 {
     int iFreeBuf;
     Uint8 *pResult;
@@ -348,125 +343,110 @@
                     return pResult;
                 }
             } else
-                printf("[DART_GetAudioBuf] : ERROR! pBufDesc = %p\n",
+                printf("[DART_GetDeviceBuf] : ERROR! pBufDesc = %p\n",
                        pBufDesc);
         } else
-            printf("[DART_GetAudioBuf] : ERROR! _this->hidden = %p\n",
+            printf("[DART_GetDeviceBuf] : ERROR! _this->hidden = %p\n",
                    _this->hidden);
     } else
-        printf("[DART_GetAudioBuf] : ERROR! _this = %p\n", _this);
+        printf("[DART_GetDeviceBuf] : ERROR! _this = %p\n", _this);
     return NULL;
 }
 
-void
+static void
 DART_WaitDone(_THIS)
 {
     pMixBufferDesc pBufDesc;
-    ULONG ulPostCount;
-    APIRET rc;
+    ULONG ulPostCount = 0;
+    APIRET rc = NO_ERROR;
 
-    pBufDesc =
-        (pMixBufferDesc) _this->hidden->pMixBuffers[_this->hidden->
-                                                    iLastPlayedBuf].
-        ulUserParm;
-    rc = NO_ERROR;
+    pBufDesc = (pMixBufferDesc)
+          _this->hidden->pMixBuffers[_this->hidden->iLastPlayedBuf].ulUserParm;
+
     while ((pBufDesc->iBufferUsage != BUFFER_EMPTY) && (rc == NO_ERROR)) {
         DosResetEventSem(_this->hidden->hevAudioBufferPlayed, &ulPostCount);
         rc = DosWaitEventSem(_this->hidden->hevAudioBufferPlayed, 1000);        // 1 sec timeout! Important!
     }
 }
 
-void
-DART_CloseAudio(_THIS)
+static void
+DART_CloseDevice(_THIS)
 {
     MCI_GENERIC_PARMS GenericParms;
     int rc;
+    int i;
 
-    // Stop DART playback
-    rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_STOP, MCI_WAIT,
-                        &GenericParms, 0);
-    if (rc != MCIERR_SUCCESS) {
+    if (_this->hidden != NULL) {
+        // Stop DART playback
+        if (_this->hidden->iCurrDeviceOrd) {
+            rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_STOP,
+                                MCI_WAIT, &GenericParms, 0);
 #ifdef SFX_DEBUG_BUILD
-        printf("Could not stop DART playback!\n");
-        fflush(stdout);
+            if (rc != MCIERR_SUCCESS) {
+                printf("Could not stop DART playback!\n");
+                fflush(stdout);
+            }
 #endif
-    }
-    // Close event semaphore
-    DosCloseEventSem(_this->hidden->hevAudioBufferPlayed);
+        }
 
-    // Free memory of buffer descriptions
-    {
-        int i;
-        for (i = 0; i < _this->hidden->iCurrNumBufs; i++)
-            SDL_free((void *) (_this->hidden->pMixBuffers[i].ulUserParm));
-    }
+        // Close event semaphore
+        if (_this->hidden->hevAudioBufferPlayed) {
+            DosCloseEventSem(_this->hidden->hevAudioBufferPlayed);
+            _this->hidden->hevAudioBufferPlayed = 0;
+        }
 
-    // Deallocate buffers
-    rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_BUFFER,
-                        MCI_WAIT | MCI_DEALLOCATE_MEMORY,
-                        &(_this->hidden->BufferParms), 0);
+        // Free memory of buffer descriptions
+        for (i = 0; i < _this->hidden->iCurrNumBufs; i++) {
+            SDL_free((void *) (_this->hidden->pMixBuffers[i].ulUserParm));
+            _this->hidden->pMixBuffers[i].ulUserParm = 0;
+        }
+        _this->hidden->iCurrNumBufs = 0;
 
-    // Free bufferlist
-    SDL_free(_this->hidden->pMixBuffers);
-    _this->hidden->pMixBuffers = NULL;
+        // Deallocate buffers
+        if (_this->hidden->iCurrDeviceOrd) {
+            rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_BUFFER,
+                                MCI_WAIT | MCI_DEALLOCATE_MEMORY,
+                                &(_this->hidden->BufferParms), 0);
+        }
 
-    // Close dart
-    rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_CLOSE, MCI_WAIT,
-                        &(GenericParms), 0);
-}
+        // Free bufferlist
+        if (_this->hidden->pMixBuffers != NULL) {
+            SDL_free(_this->hidden->pMixBuffers);
+            _this->hidden->pMixBuffers = NULL;
+        }
 
-/* Audio driver bootstrap functions */
+        // Close dart
+        if (_this->hidden->iCurrDeviceOrd) {
+            rc = mciSendCommand(_this->hidden->iCurrDeviceOrd, MCI_CLOSE,
+                                MCI_WAIT, &(GenericParms), 0);
+        }
+        _this->hidden->iCurrDeviceOrd = 0;
 
-int
-Audio_Available(void)
-{
-    return (1);
+        SDL_free(_this->hidden);
+        _this->hidden = NULL;
+    }
 }
 
-void
-Audio_DeleteDevice(SDL_AudioDevice * device)
+
+static int
+DART_Init(SDL_AudioDriverImpl *impl)
 {
-    SDL_free(device->hidden);
-    SDL_free(device);
+    /* Set the function pointers */
+    impl->OpenDevice = DART_OpenDevice;
+    impl->ThreadInit = DART_ThreadInit;
+    impl->WaitDevice = DART_WaitDevice;
+    impl->GetDeviceBuf = DART_GetDeviceBuf;
+    impl->PlayDevice = DART_PlayDevice;
+    impl->WaitDone = DART_WaitDone;
+    impl->CloseDevice = DART_CloseDevice;
+    impl->OnlyHasDefaultOutputDevice = 1;  /* !!! FIXME: is this right? */
+
+    return 1;
 }
 
-SDL_AudioDevice *
-Audio_CreateDevice(int devindex)
-{
-    SDL_AudioDevice *this;
-
-    /* Initialize all variables that we clean on shutdown */
-    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
-    if (this) {
-        SDL_memset(this, 0, (sizeof *this));
-        this->hidden = (struct SDL_PrivateAudioData *)
-            SDL_malloc((sizeof *this->hidden));
-    }
-    if ((this == NULL) || (this->hidden == NULL)) {
-        SDL_OutOfMemory();
-        if (this)
-            SDL_free(this);
-        return (0);
-    }
-    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
-
-    /* Set the function pointers */
-    this->OpenAudio = DART_OpenAudio;
-    this->ThreadInit = DART_ThreadInit;
-    this->WaitAudio = DART_WaitAudio;
-    this->PlayAudio = DART_PlayAudio;
-    this->GetAudioBuf = DART_GetAudioBuf;
-    this->WaitDone = DART_WaitDone;
-    this->CloseAudio = DART_CloseAudio;
-
-    this->free = Audio_DeleteDevice;
-
-    return this;
-}
 
 AudioBootStrap DART_bootstrap = {
-    "dart", "OS/2 Direct Audio RouTines (DART)",
-    Audio_Available, Audio_CreateDevice
+    "dart", "OS/2 Direct Audio RouTines (DART)", DART_Init, 0
 };
 
 /* vi: set ts=4 sw=4 expandtab: */