Mercurial > sdl-ios-xcode
comparison src/audio/macrom/SDL_romaudio.c @ 323:b7e8038e40ae
The audio lock and unlock functions are now a part of the driver.
The MacOS audio locking has been implemented, courtesy of Ryan Gordon
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sat, 30 Mar 2002 20:03:27 +0000 |
parents | f6ffac90895c |
children | f25f666d609a |
comparison
equal
deleted
inserted
replaced
322:fd93a09655e3 | 323:b7e8038e40ae |
---|---|
28 #if TARGET_API_MAC_CARBON | 28 #if TARGET_API_MAC_CARBON |
29 # include <Carbon.h> | 29 # include <Carbon.h> |
30 #else | 30 #else |
31 # include <Sound.h> /* SoundManager interface */ | 31 # include <Sound.h> /* SoundManager interface */ |
32 # include <Gestalt.h> | 32 # include <Gestalt.h> |
33 # include <DriverServices.h> | |
33 #endif | 34 #endif |
34 | 35 |
35 #include <stdlib.h> | 36 #include <stdlib.h> |
36 #include <stdio.h> | 37 #include <stdio.h> |
37 | 38 |
44 | 45 |
45 /* Audio driver functions */ | 46 /* Audio driver functions */ |
46 | 47 |
47 static void Mac_CloseAudio(_THIS); | 48 static void Mac_CloseAudio(_THIS); |
48 static int Mac_OpenAudio(_THIS, SDL_AudioSpec *spec); | 49 static int Mac_OpenAudio(_THIS, SDL_AudioSpec *spec); |
50 static void Mac_LockAudio(_THIS); | |
51 static void Mac_UnlockAudio(_THIS); | |
49 | 52 |
50 /* Audio driver bootstrap functions */ | 53 /* Audio driver bootstrap functions */ |
51 | 54 |
52 | 55 |
53 static int Audio_Available(void) | 56 static int Audio_Available(void) |
82 memset(this->hidden, 0, (sizeof *this->hidden)); | 85 memset(this->hidden, 0, (sizeof *this->hidden)); |
83 | 86 |
84 /* Set the function pointers */ | 87 /* Set the function pointers */ |
85 this->OpenAudio = Mac_OpenAudio; | 88 this->OpenAudio = Mac_OpenAudio; |
86 this->CloseAudio = Mac_CloseAudio; | 89 this->CloseAudio = Mac_CloseAudio; |
90 this->LockAudio = Mac_LockAudio; | |
91 this->UnlockAudio = Mac_UnlockAudio; | |
87 this->free = Audio_DeleteDevice; | 92 this->free = Audio_DeleteDevice; |
88 | 93 |
89 return this; | 94 return this; |
90 } | 95 } |
91 | 96 |
92 AudioBootStrap SNDMGR_bootstrap = { | 97 AudioBootStrap SNDMGR_bootstrap = { |
93 "sndmgr", "MacOS SoundManager 3.0", | 98 "sndmgr", "MacOS SoundManager 3.0", |
94 Audio_Available, Audio_CreateDevice | 99 Audio_Available, Audio_CreateDevice |
95 }; | 100 }; |
96 | 101 |
97 #if TARGET_API_MAC_CARBON | 102 #if defined(TARGET_API_MAC_CARBON) || defined(USE_RYANS_SOUNDCODE) |
103 /* FIXME: Does this work correctly on MacOS X as well? */ | |
104 | |
105 #pragma options align=power | |
106 | |
107 static volatile SInt32 audio_is_locked = 0; | |
108 static volatile SInt32 need_to_mix = 0; | |
98 | 109 |
99 static UInt8 *buffer[2]; | 110 static UInt8 *buffer[2]; |
100 static volatile UInt32 running = 0; | 111 static volatile UInt32 running = 0; |
101 static CmpSoundHeader header; | 112 static CmpSoundHeader header; |
102 | 113 static volatile Uint32 fill_me = 0; |
103 static void callBackProc (SndChannel *chan, SndCommand *cmd_passed ) { | 114 |
104 | 115 static void mix_buffer(SDL_AudioDevice *audio, UInt8 *buffer) |
105 UInt32 fill_me, play_me; | 116 { |
106 SndCommand cmd; | |
107 SDL_AudioDevice *audio = (SDL_AudioDevice *)chan->userInfo; | |
108 | |
109 fill_me = cmd_passed->param2; /* buffer that has just finished playing, so fill it */ | |
110 play_me = ! fill_me; /* filled buffer to play _now_ */ | |
111 | |
112 if ( ! audio->enabled ) { | |
113 return; | |
114 } | |
115 | |
116 header.samplePtr = (Ptr)buffer[play_me]; | |
117 | |
118 cmd.cmd = bufferCmd; | |
119 cmd.param1 = 0; | |
120 cmd.param2 = (long)&header; | |
121 | |
122 SndDoCommand (chan, &cmd, 0); | |
123 | |
124 memset (buffer[fill_me], 0, audio->spec.size); | |
125 | |
126 if ( ! audio->paused ) { | 117 if ( ! audio->paused ) { |
127 if ( audio->convert.needed ) { | 118 if ( audio->convert.needed ) { |
128 #if MACOSX | |
129 SDL_mutexP(audio->mixer_lock); | |
130 #endif | |
131 audio->spec.callback(audio->spec.userdata, | 119 audio->spec.callback(audio->spec.userdata, |
132 (Uint8 *)audio->convert.buf,audio->convert.len); | 120 (Uint8 *)audio->convert.buf,audio->convert.len); |
133 #if MACOSX | |
134 SDL_mutexV(audio->mixer_lock); | |
135 #endif | |
136 SDL_ConvertAudio(&audio->convert); | 121 SDL_ConvertAudio(&audio->convert); |
137 #if 0 | 122 #if 0 |
138 if ( audio->convert.len_cvt != audio->spec.size ) { | 123 if ( audio->convert.len_cvt != audio->spec.size ) { |
139 /* Uh oh... probably crashes here; */ | 124 /* Uh oh... probably crashes here; */ |
140 } | 125 } |
141 #endif | 126 #endif |
142 memcpy(buffer[fill_me], audio->convert.buf, | 127 memcpy(buffer, audio->convert.buf, audio->convert.len_cvt); |
143 audio->convert.len_cvt); | |
144 } else { | 128 } else { |
145 #if MACOSX | 129 audio->spec.callback(audio->spec.userdata, buffer, audio->spec.size); |
146 SDL_mutexP(audio->mixer_lock); | 130 } |
147 #endif | 131 } |
148 audio->spec.callback(audio->spec.userdata, | 132 |
149 (Uint8 *)buffer[fill_me], audio->spec.size); | 133 DecrementAtomic((SInt32 *) &need_to_mix); |
150 #if MACOSX | 134 } |
151 SDL_mutexV(audio->mixer_lock); | 135 |
152 #endif | 136 static void Mac_LockAudio(_THIS) |
153 } | 137 { |
154 } | 138 IncrementAtomic((SInt32 *) &audio_is_locked); |
155 | 139 } |
156 if ( running ) { | 140 |
141 static void Mac_UnlockAudio(_THIS) | |
142 { | |
143 SInt32 oldval; | |
157 | 144 |
145 oldval = DecrementAtomic((SInt32 *) &audio_is_locked); | |
146 if ( oldval != 1 ) /* != 1 means audio is still locked. */ | |
147 return; | |
148 | |
149 /* Did we miss the chance to mix in an interrupt? Do it now. */ | |
150 if ( BitAndAtomic (0xFFFFFFFF, &need_to_mix) ) { | |
151 /* | |
152 * Note that this could be a problem if you missed an interrupt | |
153 * while the audio was locked, and get preempted by a second | |
154 * interrupt here, but that means you locked for way too long anyhow. | |
155 */ | |
156 mix_buffer (this, buffer[fill_me]); | |
157 } | |
158 } | |
159 | |
160 static void callBackProc (SndChannel *chan, SndCommand *cmd_passed ) { | |
161 UInt32 play_me; | |
162 SndCommand cmd; | |
163 SDL_AudioDevice *audio = (SDL_AudioDevice *)chan->userInfo; | |
164 | |
165 IncrementAtomic((SInt32 *) &need_to_mix); | |
166 | |
167 fill_me = cmd_passed->param2; /* buffer that has just finished playing, so fill it */ | |
168 play_me = ! fill_me; /* filled buffer to play _now_ */ | |
169 | |
170 if ( ! audio->enabled ) { | |
171 return; | |
172 } | |
173 | |
174 /* queue previously mixed buffer for playback. */ | |
175 header.samplePtr = (Ptr)buffer[play_me]; | |
176 cmd.cmd = bufferCmd; | |
177 cmd.param1 = 0; | |
178 cmd.param2 = (long)&header; | |
179 SndDoCommand (chan, &cmd, 0); | |
180 | |
181 memset (buffer[fill_me], 0, audio->spec.size); | |
182 | |
183 /* | |
184 * if audio device isn't locked, mix the next buffer to be queued in | |
185 * the memory block that just finished playing. | |
186 */ | |
187 if ( ! BitAndAtomic(0xFFFFFFFF, &audio_is_locked) ) { | |
188 mix_buffer (audio, buffer[fill_me]); | |
189 } | |
190 | |
191 /* set this callback to run again when current buffer drains. */ | |
192 if ( running ) { | |
158 cmd.cmd = callBackCmd; | 193 cmd.cmd = callBackCmd; |
159 cmd.param1 = 0; | 194 cmd.param1 = 0; |
160 cmd.param2 = play_me; | 195 cmd.param2 = play_me; |
161 | 196 |
162 SndDoCommand (chan, &cmd, 0); | 197 SndDoCommand (chan, &cmd, 0); |
163 } | 198 } |
164 | |
165 } | 199 } |
166 | 200 |
167 static int Mac_OpenAudio(_THIS, SDL_AudioSpec *spec) { | 201 static int Mac_OpenAudio(_THIS, SDL_AudioSpec *spec) { |
168 | 202 |
169 SndCallBackUPP callback; | 203 SndCallBackUPP callback; |
170 int sample_bits; | 204 int sample_bits; |
171 int i; | 205 int i; |
172 long initOptions; | 206 long initOptions; |
173 | 207 |
174 /* Very few conversions are required, but... */ | 208 /* Very few conversions are required, but... */ |
175 switch (spec->format) { | 209 switch (spec->format) { |
176 case AUDIO_S8: | 210 case AUDIO_S8: |
177 spec->format = AUDIO_U8; | 211 spec->format = AUDIO_U8; |
178 break; | 212 break; |
229 } else { | 263 } else { |
230 initOptions = initMono; | 264 initOptions = initMono; |
231 } | 265 } |
232 channel->userInfo = (long)this; | 266 channel->userInfo = (long)this; |
233 channel->qLength = 128; | 267 channel->qLength = 128; |
234 if ( SndNewChannel(&channel, sampledSynth, initOptions, callback) != | 268 if ( SndNewChannel(&channel, sampledSynth, initOptions, callback) != noErr ) { |
235 noErr ) { | |
236 SDL_SetError("Unable to create audio channel"); | 269 SDL_SetError("Unable to create audio channel"); |
237 free(channel); | 270 free(channel); |
238 channel = NULL; | 271 channel = NULL; |
239 return(-1); | 272 return(-1); |
240 } | 273 } |
268 buffer[i] = NULL; | 301 buffer[i] = NULL; |
269 } | 302 } |
270 } | 303 } |
271 } | 304 } |
272 | 305 |
273 #else /* !TARGET_API_MAC_CARBON */ | 306 #else /* !TARGET_API_MAC_CARBON && !USE_RYANS_SOUNDCODE */ |
307 | |
308 static void Mac_LockAudio(_THIS) | |
309 { | |
310 /* no-op. */ | |
311 } | |
312 | |
313 static void Mac_UnlockAudio(_THIS) | |
314 { | |
315 /* no-op. */ | |
316 } | |
317 | |
274 | 318 |
275 /* This function is called by Sound Manager when it has exhausted one of | 319 /* This function is called by Sound Manager when it has exhausted one of |
276 the buffers, so we'll zero it to silence and fill it with audio if | 320 the buffers, so we'll zero it to silence and fill it with audio if |
277 we're not paused. | 321 we're not paused. |
278 */ | 322 */ |
334 static void Mac_CloseAudio(_THIS) | 378 static void Mac_CloseAudio(_THIS) |
335 { | 379 { |
336 int i; | 380 int i; |
337 | 381 |
338 if ( channel != NULL ) { | 382 if ( channel != NULL ) { |
339 #if 0 | |
340 SCStatus status; | |
341 | |
342 /* Wait for audio to complete */ | |
343 do { | |
344 SndChannelStatus(channel, sizeof(status), &status); | |
345 } while ( status.scChannelBusy ); | |
346 #endif | |
347 /* Clean up the audio channel */ | 383 /* Clean up the audio channel */ |
348 SndDisposeChannel(channel, true); | 384 SndDisposeChannel(channel, true); |
349 channel = NULL; | 385 channel = NULL; |
350 } | 386 } |
351 for ( i=0; i<2; ++i ) { | 387 for ( i=0; i<2; ++i ) { |
444 } | 480 } |
445 | 481 |
446 return 1; | 482 return 1; |
447 } | 483 } |
448 | 484 |
449 #endif /* TARGET_API_MAC_CARBON */ | 485 #endif /* TARGET_API_MAC_CARBON || USE_RYANS_SOUNDCODE */ |
450 | 486 |
451 |