Mercurial > sdl-ios-xcode
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: */