diff src/audio/macrom/SDL_romaudio.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 c27292a690b7
children d22372343744
line wrap: on
line diff
--- a/src/audio/macrom/SDL_romaudio.c	Sun Oct 01 16:10:41 2006 +0000
+++ b/src/audio/macrom/SDL_romaudio.c	Tue Oct 17 09:15:21 2006 +0000
@@ -21,11 +21,16 @@
 */
 #include "SDL_config.h"
 
+/* This should work on PowerPC and Intel Mac OS X, and Carbonized Mac OS 9. */
+
 #if defined(__APPLE__) && defined(__MACH__)
+#  define SDL_MACOS_NAME "Mac OS X"
 #  include <Carbon/Carbon.h>
 #elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335)
+#  define SDL_MACOS_NAME "Mac OS 9"
 #  include <Carbon.h>
 #else
+#  define SDL_MACOS_NAME "Mac OS 9"
 #  include <Sound.h>            /* SoundManager interface */
 #  include <Gestalt.h>
 #  include <DriverServices.h>
@@ -45,72 +50,6 @@
 #include "../SDL_sysaudio.h"
 #include "SDL_romaudio.h"
 
-/* Audio driver functions */
-
-static void Mac_CloseAudio(_THIS);
-static int Mac_OpenAudio(_THIS, SDL_AudioSpec * spec);
-static void Mac_LockAudio(_THIS);
-static void Mac_UnlockAudio(_THIS);
-
-/* Audio driver bootstrap functions */
-
-
-static int
-Audio_Available(void)
-{
-    return (1);
-}
-
-static void
-Audio_DeleteDevice(SDL_AudioDevice * device)
-{
-    SDL_free(device->hidden);
-    SDL_free(device);
-}
-
-static 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 = Mac_OpenAudio;
-    this->CloseAudio = Mac_CloseAudio;
-    this->LockAudio = Mac_LockAudio;
-    this->UnlockAudio = Mac_UnlockAudio;
-    this->free = Audio_DeleteDevice;
-
-#ifdef __MACOSX__               /* Mac OS X uses threaded audio, so normal thread code is okay */
-    this->LockAudio = NULL;
-    this->UnlockAudio = NULL;
-#endif
-    return this;
-}
-
-AudioBootStrap SNDMGR_bootstrap = {
-    "sndmgr", "MacOS SoundManager 3.0",
-    Audio_Available, Audio_CreateDevice
-};
-
-#if defined(TARGET_API_MAC_CARBON) || defined(USE_RYANS_SOUNDCODE)
-/* This works correctly on Mac OS X */
-
 #pragma options align=power
 
 static volatile SInt32 audio_is_locked = 0;
@@ -121,6 +60,7 @@
 static CmpSoundHeader header;
 static volatile Uint32 fill_me = 0;
 
+
 static void
 mix_buffer(SDL_AudioDevice * audio, UInt8 * buffer)
 {
@@ -150,13 +90,13 @@
 }
 
 static void
-Mac_LockAudio(_THIS)
+SNDMGR_LockDevice(_THIS)
 {
     IncrementAtomic((SInt32 *) & audio_is_locked);
 }
 
 static void
-Mac_UnlockAudio(_THIS)
+SNDMGR_UnlockDevice(_THIS)
 {
     SInt32 oldval;
 
@@ -198,7 +138,7 @@
     cmd.param2 = (long) &header;
     SndDoCommand(chan, &cmd, 0);
 
-    memset(buffer[fill_me], 0, audio->spec.size);
+    SDL_memset(buffer[fill_me], 0, audio->spec.size);
 
     /*
      * if audio device isn't locked, mix the next buffer to be queued in
@@ -219,14 +159,25 @@
 }
 
 static int
-Mac_OpenAudio(_THIS, SDL_AudioSpec * spec)
+SNDMGR_OpenDevice(_THIS, const char *devname, int iscapture)
 {
-
+    SDL_AudioSpec *spec = &this->spec;
+    SndChannelPtr channel = NULL;
     SndCallBackUPP callback;
     int sample_bits;
     int i;
     long initOptions;
 
+    /* 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));
+
+    /* !!! FIXME: iterate through format matrix... */
     /* Very few conversions are required, but... */
     switch (spec->format) {
     case AUDIO_S8:
@@ -242,10 +193,10 @@
         spec->format = AUDIO_F32MSB;
         break;
     }
-    SDL_CalculateAudioSpec(spec);
+    SDL_CalculateAudioSpec(&this->spec);
 
     /* initialize bufferCmd header */
-    memset(&header, 0, sizeof(header));
+    SDL_memset(&header, 0, sizeof(header));
     callback = (SndCallBackUPP) NewSndCallBackUPP(callBackProc);
     sample_bits = spec->size / spec->samples / spec->channels * 8;
 
@@ -278,20 +229,23 @@
 
     /* allocate 2 buffers */
     for (i = 0; i < 2; i++) {
-        buffer[i] = (UInt8 *) malloc(sizeof(UInt8) * spec->size);
+        buffer[i] = (UInt8 *) SDL_malloc(sizeof(UInt8) * spec->size);
         if (buffer[i] == NULL) {
+            SNDMGR_CloseDevice(this);
             SDL_OutOfMemory();
-            return (-1);
+            return 0;
         }
-        memset(buffer[i], 0, spec->size);
+        SDL_memset(buffer[i], 0, spec->size);
     }
 
     /* Create the sound manager channel */
     channel = (SndChannelPtr) SDL_malloc(sizeof(*channel));
     if (channel == NULL) {
+        SNDMGR_CloseDevice(this);
         SDL_OutOfMemory();
-        return (-1);
+        return 0;
     }
+    this->hidden->channel = channel;
     if (spec->channels >= 2) {
         initOptions = initStereo;
     } else {
@@ -300,10 +254,9 @@
     channel->userInfo = (long) this;
     channel->qLength = 128;
     if (SndNewChannel(&channel, sampledSynth, initOptions, callback) != noErr) {
+        SNDMGR_CloseDevice(this);
         SDL_SetError("Unable to create audio channel");
-        SDL_free(channel);
-        channel = NULL;
-        return (-1);
+        return 0;
     }
 
     /* start playback */
@@ -319,16 +272,15 @@
 }
 
 static void
-Mac_CloseAudio(_THIS)
+SNDMGR_CloseDevice(_THIS)
 {
-
     int i;
 
     running = 0;
 
-    if (channel) {
-        SndDisposeChannel(channel, true);
-        channel = NULL;
+    if (this->hidden->channel) {
+        SndDisposeChannel(this->hidden->channel, true);
+        this->hidden->channel = NULL;
     }
 
     for (i = 0; i < 2; ++i) {
@@ -337,193 +289,31 @@
             buffer[i] = NULL;
         }
     }
-}
-
-#else /* !TARGET_API_MAC_CARBON && !USE_RYANS_SOUNDCODE */
-
-static void
-Mac_LockAudio(_THIS)
-{
-    /* no-op. */
-}
-
-static void
-Mac_UnlockAudio(_THIS)
-{
-    /* no-op. */
-}
-
-
-/* This function is called by Sound Manager when it has exhausted one of
-   the buffers, so we'll zero it to silence and fill it with audio if
-   we're not paused.
-*/
-static pascal void
-sndDoubleBackProc(SndChannelPtr chan, SndDoubleBufferPtr newbuf)
-{
-    SDL_AudioDevice *audio = (SDL_AudioDevice *) newbuf->dbUserInfo[0];
-
-    /* If audio is quitting, don't do anything */
-    if (!audio->enabled) {
-        return;
-    }
-    memset(newbuf->dbSoundData, 0, audio->spec.size);
-    newbuf->dbNumFrames = audio->spec.samples;
-    if (!audio->paused) {
-        if (audio->convert.needed) {
-            audio->spec.callback(audio->spec.userdata,
-                                 (Uint8 *) audio->convert.buf,
-                                 audio->convert.len);
-            SDL_ConvertAudio(&audio->convert);
-#if 0
-            if (audio->convert.len_cvt != audio->spec.size) {
-                /* Uh oh... probably crashes here */ ;
-            }
-#endif
-            SDL_memcpy(newbuf->dbSoundData, audio->convert.buf,
-                       audio->convert.len_cvt);
-        } else {
-            audio->spec.callback(audio->spec.userdata,
-                                 (Uint8 *) newbuf->dbSoundData,
-                                 audio->spec.size);
-        }
-    }
-    newbuf->dbFlags |= dbBufferReady;
+    SDL_free(this->hidden);
+    this->hidden = NULL;
 }
 
 static int
-DoubleBufferAudio_Available(void)
-{
-    int available;
-    NumVersion sndversion;
-    long response;
-
-    available = 0;
-    sndversion = SndSoundManagerVersion();
-    if (sndversion.majorRev >= 3) {
-        if (Gestalt(gestaltSoundAttr, &response) == noErr) {
-            if ((response & (1 << gestaltSndPlayDoubleBuffer))) {
-                available = 1;
-            }
-        }
-    } else {
-        if (Gestalt(gestaltSoundAttr, &response) == noErr) {
-            if ((response & (1 << gestaltHasASC))) {
-                available = 1;
-            }
-        }
-    }
-    return (available);
-}
-
-static void
-Mac_CloseAudio(_THIS)
+SNDMGR_Init(SDL_AudioDriverImpl *impl)
 {
-    int i;
-
-    if (channel != NULL) {
-        /* Clean up the audio channel */
-        SndDisposeChannel(channel, true);
-        channel = NULL;
-    }
-    for (i = 0; i < 2; ++i) {
-        if (audio_buf[i]) {
-            SDL_free(audio_buf[i]);
-            audio_buf[i] = NULL;
-        }
-    }
-}
-
-static int
-Mac_OpenAudio(_THIS, SDL_AudioSpec * spec)
-{
-    SndDoubleBufferHeader2 audio_dbh;
-    int i;
-    long initOptions;
-    int sample_bits;
-    SndDoubleBackUPP doubleBackProc;
-
-    /* Check to make sure double-buffered audio is available */
-    if (!DoubleBufferAudio_Available()) {
-        SDL_SetError("Sound manager doesn't support double-buffering");
-        return (-1);
-    }
+    /* Set the function pointers */
+    impl->OpenDevice = SNDMGR_OpenDevice;
+    impl->CloseDevice = SNDMGR_CloseDevice;
+    impl->ProvidesOwnCallbackThread = 1;
+    impl->OnlyHasDefaultOutputDevice = 1;
 
-    /* Very few conversions are required, but... */
-    switch (spec->format) {
-    case AUDIO_S8:
-        spec->format = AUDIO_U8;
-        break;
-    case AUDIO_U16LSB:
-        spec->format = AUDIO_S16LSB;
-        break;
-    case AUDIO_U16MSB:
-        spec->format = AUDIO_S16MSB;
-        break;
-    }
-    SDL_CalculateAudioSpec(spec);
-
-    /* initialize the double-back header */
-    SDL_memset(&audio_dbh, 0, sizeof(audio_dbh));
-    doubleBackProc = NewSndDoubleBackProc(sndDoubleBackProc);
-    sample_bits = spec->size / spec->samples / spec->channels * 8;
-
-    audio_dbh.dbhNumChannels = spec->channels;
-    audio_dbh.dbhSampleSize = sample_bits;
-    audio_dbh.dbhCompressionID = 0;
-    audio_dbh.dbhPacketSize = 0;
-    audio_dbh.dbhSampleRate = spec->freq << 16;
-    audio_dbh.dbhDoubleBack = doubleBackProc;
-    audio_dbh.dbhFormat = 0;
-
-    /* Note that we install the 16bitLittleEndian Converter if needed. */
-    if (spec->format == 0x8010) {
-        audio_dbh.dbhCompressionID = fixedCompression;
-        audio_dbh.dbhFormat = k16BitLittleEndianFormat;
-    }
-
-    /* allocate the 2 double-back buffers */
-    for (i = 0; i < 2; ++i) {
-        audio_buf[i] = SDL_calloc(1, sizeof(SndDoubleBuffer) + spec->size);
-        if (audio_buf[i] == NULL) {
-            SDL_OutOfMemory();
-            return (-1);
-        }
-        audio_buf[i]->dbNumFrames = spec->samples;
-        audio_buf[i]->dbFlags = dbBufferReady;
-        audio_buf[i]->dbUserInfo[0] = (long) this;
-        audio_dbh.dbhBufferPtr[i] = audio_buf[i];
-    }
-
-    /* Create the sound manager channel */
-    channel = (SndChannelPtr) SDL_malloc(sizeof(*channel));
-    if (channel == NULL) {
-        SDL_OutOfMemory();
-        return (-1);
-    }
-    if (spec->channels >= 2) {
-        initOptions = initStereo;
-    } else {
-        initOptions = initMono;
-    }
-    channel->userInfo = 0;
-    channel->qLength = 128;
-    if (SndNewChannel(&channel, sampledSynth, initOptions, 0L) != noErr) {
-        SDL_SetError("Unable to create audio channel");
-        SDL_free(channel);
-        channel = NULL;
-        return (-1);
-    }
-
-    /* Start playback */
-    if (SndPlayDoubleBuffer(channel, (SndDoubleBufferHeaderPtr) & audio_dbh)
-        != noErr) {
-        SDL_SetError("Unable to play double buffered audio");
-        return (-1);
-    }
+/* Mac OS X uses threaded audio, so normal thread code is okay */
+#ifndef __MACOSX__
+    impl->LockDevice = SNDMGR_LockDevice;
+    impl->UnlockDevice = SNDMGR_UnlockDevice;
+    impl->SkipMixerLock = 1;
+#endif
 
     return 1;
 }
 
-#endif /* TARGET_API_MAC_CARBON || USE_RYANS_SOUNDCODE */
+AudioBootStrap SNDMGR_bootstrap = {
+    "sndmgr", SDL_MACOS_NAME " SoundManager", SNDMGR_Init, 0
+};
+
 /* vi: set ts=4 sw=4 expandtab: */