Mercurial > sdl-ios-xcode
annotate src/audio/macrom/SDL_romaudio.c @ 315:3333b6e68289
Date: Sat, 23 Mar 2002 13:53:37 +0200
From: "Mike Gorchak" <mike@malva.ua>
Subject: Big QNX patch again.
Added 8bit palette emulation code for window mode with bpp>=15.
Added store/restore original palette for 8bit modes.
Added more information about photon API call fails.
Rewroten change palette code, slow but works.
Fixed bug with set caption before window was inited.
Fixed bugs with some initial state of variables.
Fixed bug with storing old video mode settings.
Fixed bug with switching to fullscreen mode and back.
Fixed few double SEGFAULTS during parachute mode.
Removed compilation warning with no PgWaitHWIdle prototype.
Removed pack of dead unusable code.
Cleanups SDL_PrivateVideoData structure, some headers.
Some code formatting.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sat, 23 Mar 2002 20:19:44 +0000 |
parents | f6ffac90895c |
children | b7e8038e40ae |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
297
f6ffac90895c
Updated copyright information for 2002
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
3 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 of the License, or (at your option) any later version. | |
9 | |
10 This library is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
47
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 #if TARGET_API_MAC_CARBON | |
29 # include <Carbon.h> | |
30 #else | |
31 # include <Sound.h> /* SoundManager interface */ | |
32 # include <Gestalt.h> | |
33 #endif | |
34 | |
35 #include <stdlib.h> | |
36 #include <stdio.h> | |
37 | |
38 #include "SDL_endian.h" | |
39 #include "SDL_audio.h" | |
40 #include "SDL_audio_c.h" | |
41 #include "SDL_audiomem.h" | |
42 #include "SDL_sysaudio.h" | |
43 #include "SDL_romaudio.h" | |
44 | |
45 /* Audio driver functions */ | |
46 | |
47 static void Mac_CloseAudio(_THIS); | |
48 static int Mac_OpenAudio(_THIS, SDL_AudioSpec *spec); | |
49 | |
50 /* Audio driver bootstrap functions */ | |
51 | |
52 | |
53 static int Audio_Available(void) | |
54 { | |
55 return(1); | |
56 } | |
57 | |
58 static void Audio_DeleteDevice(SDL_AudioDevice *device) | |
59 { | |
60 free(device->hidden); | |
61 free(device); | |
62 } | |
63 | |
64 static SDL_AudioDevice *Audio_CreateDevice(int devindex) | |
65 { | |
66 SDL_AudioDevice *this; | |
67 | |
68 /* Initialize all variables that we clean on shutdown */ | |
69 this = (SDL_AudioDevice *)malloc(sizeof(SDL_AudioDevice)); | |
70 if ( this ) { | |
71 memset(this, 0, (sizeof *this)); | |
72 this->hidden = (struct SDL_PrivateAudioData *) | |
73 malloc((sizeof *this->hidden)); | |
74 } | |
75 if ( (this == NULL) || (this->hidden == NULL) ) { | |
76 SDL_OutOfMemory(); | |
77 if ( this ) { | |
78 free(this); | |
79 } | |
80 return(0); | |
81 } | |
82 memset(this->hidden, 0, (sizeof *this->hidden)); | |
83 | |
84 /* Set the function pointers */ | |
85 this->OpenAudio = Mac_OpenAudio; | |
86 this->CloseAudio = Mac_CloseAudio; | |
87 this->free = Audio_DeleteDevice; | |
88 | |
89 return this; | |
90 } | |
91 | |
92 AudioBootStrap SNDMGR_bootstrap = { | |
93 "sndmgr", "MacOS SoundManager 3.0", | |
94 Audio_Available, Audio_CreateDevice | |
95 }; | |
96 | |
97 #if TARGET_API_MAC_CARBON | |
98 | |
99 static UInt8 *buffer[2]; | |
100 static volatile UInt32 running = 0; | |
101 static CmpSoundHeader header; | |
102 | |
103 static void callBackProc (SndChannel *chan, SndCommand *cmd_passed ) { | |
104 | |
105 UInt32 fill_me, play_me; | |
106 SndCommand cmd; | |
107 SDL_AudioDevice *audio = (SDL_AudioDevice *)chan->userInfo; | |
47
45b1c4303f87
Added initial support for Quartz video (thanks Darrell!)
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
108 |
45b1c4303f87
Added initial support for Quartz video (thanks Darrell!)
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
109 fill_me = cmd_passed->param2; /* buffer that has just finished playing, so fill it */ |
0 | 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; | |
47
45b1c4303f87
Added initial support for Quartz video (thanks Darrell!)
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
121 |
45b1c4303f87
Added initial support for Quartz video (thanks Darrell!)
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
122 SndDoCommand (chan, &cmd, 0); |
0 | 123 |
124 memset (buffer[fill_me], 0, audio->spec.size); | |
125 | |
126 if ( ! audio->paused ) { | |
127 if ( audio->convert.needed ) { | |
47
45b1c4303f87
Added initial support for Quartz video (thanks Darrell!)
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
128 #if MACOSX |
45b1c4303f87
Added initial support for Quartz video (thanks Darrell!)
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
129 SDL_mutexP(audio->mixer_lock); |
45b1c4303f87
Added initial support for Quartz video (thanks Darrell!)
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
130 #endif |
45b1c4303f87
Added initial support for Quartz video (thanks Darrell!)
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
131 audio->spec.callback(audio->spec.userdata, |
45b1c4303f87
Added initial support for Quartz video (thanks Darrell!)
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
132 (Uint8 *)audio->convert.buf,audio->convert.len); |
45b1c4303f87
Added initial support for Quartz video (thanks Darrell!)
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
133 #if MACOSX |
45b1c4303f87
Added initial support for Quartz video (thanks Darrell!)
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
134 SDL_mutexV(audio->mixer_lock); |
45b1c4303f87
Added initial support for Quartz video (thanks Darrell!)
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
135 #endif |
0 | 136 SDL_ConvertAudio(&audio->convert); |
137 #if 0 | |
138 if ( audio->convert.len_cvt != audio->spec.size ) { | |
139 /* Uh oh... probably crashes here; */ | |
140 } | |
141 #endif | |
142 memcpy(buffer[fill_me], audio->convert.buf, | |
143 audio->convert.len_cvt); | |
144 } else { | |
47
45b1c4303f87
Added initial support for Quartz video (thanks Darrell!)
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
145 #if MACOSX |
45b1c4303f87
Added initial support for Quartz video (thanks Darrell!)
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
146 SDL_mutexP(audio->mixer_lock); |
45b1c4303f87
Added initial support for Quartz video (thanks Darrell!)
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
147 #endif |
0 | 148 audio->spec.callback(audio->spec.userdata, |
149 (Uint8 *)buffer[fill_me], audio->spec.size); | |
47
45b1c4303f87
Added initial support for Quartz video (thanks Darrell!)
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
150 #if MACOSX |
45b1c4303f87
Added initial support for Quartz video (thanks Darrell!)
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
151 SDL_mutexV(audio->mixer_lock); |
45b1c4303f87
Added initial support for Quartz video (thanks Darrell!)
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
152 #endif |
0 | 153 } |
154 } | |
47
45b1c4303f87
Added initial support for Quartz video (thanks Darrell!)
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
155 |
0 | 156 if ( running ) { |
157 | |
158 cmd.cmd = callBackCmd; | |
159 cmd.param1 = 0; | |
160 cmd.param2 = play_me; | |
161 | |
162 SndDoCommand (chan, &cmd, 0); | |
163 } | |
47
45b1c4303f87
Added initial support for Quartz video (thanks Darrell!)
Sam Lantinga <slouken@lokigames.com>
parents:
0
diff
changeset
|
164 |
0 | 165 } |
166 | |
167 static int Mac_OpenAudio(_THIS, SDL_AudioSpec *spec) { | |
168 | |
169 SndCallBackUPP callback; | |
170 int sample_bits; | |
171 int i; | |
172 long initOptions; | |
173 | |
174 /* Very few conversions are required, but... */ | |
175 switch (spec->format) { | |
176 case AUDIO_S8: | |
177 spec->format = AUDIO_U8; | |
178 break; | |
179 case AUDIO_U16LSB: | |
180 spec->format = AUDIO_S16LSB; | |
181 break; | |
182 case AUDIO_U16MSB: | |
183 spec->format = AUDIO_S16MSB; | |
184 break; | |
185 } | |
186 SDL_CalculateAudioSpec(spec); | |
187 | |
188 /* initialize bufferCmd header */ | |
189 memset (&header, 0, sizeof(header)); | |
190 callback = NewSndCallBackUPP (callBackProc); | |
191 sample_bits = spec->size / spec->samples / spec->channels * 8; | |
192 | |
193 #ifdef DEBUG_AUDIO | |
194 fprintf(stderr, | |
195 "Audio format 0x%x, channels = %d, sample_bits = %d, frequency = %d\n", | |
196 spec->format, spec->channels, sample_bits, spec->freq); | |
197 #endif /* DEBUG_AUDIO */ | |
198 | |
199 header.numChannels = spec->channels; | |
200 header.sampleSize = sample_bits; | |
201 header.sampleRate = spec->freq << 16; | |
202 header.numFrames = spec->samples; | |
203 header.encode = cmpSH; | |
204 | |
205 /* Note that we install the 16bitLittleEndian Converter if needed. */ | |
206 if ( spec->format == 0x8010 ) { | |
207 header.compressionID = fixedCompression; | |
208 header.format = k16BitLittleEndianFormat; | |
209 } | |
210 | |
211 /* allocate 2 buffers */ | |
212 for (i=0; i<2; i++) { | |
213 buffer[i] = (UInt8*)malloc (sizeof(UInt8) * spec->size); | |
214 if (buffer[i] == NULL) { | |
215 SDL_OutOfMemory(); | |
216 return (-1); | |
217 } | |
218 memset (buffer[i], 0, spec->size); | |
219 } | |
220 | |
221 /* Create the sound manager channel */ | |
222 channel = (SndChannelPtr)malloc(sizeof(*channel)); | |
223 if ( channel == NULL ) { | |
224 SDL_OutOfMemory(); | |
225 return(-1); | |
226 } | |
227 if ( spec->channels >= 2 ) { | |
228 initOptions = initStereo; | |
229 } else { | |
230 initOptions = initMono; | |
231 } | |
232 channel->userInfo = (long)this; | |
233 channel->qLength = 128; | |
234 if ( SndNewChannel(&channel, sampledSynth, initOptions, callback) != | |
235 noErr ) { | |
236 SDL_SetError("Unable to create audio channel"); | |
237 free(channel); | |
238 channel = NULL; | |
239 return(-1); | |
240 } | |
241 | |
242 /* start playback */ | |
243 { | |
244 SndCommand cmd; | |
245 cmd.cmd = callBackCmd; | |
246 cmd.param2 = 0; | |
247 running = 1; | |
248 SndDoCommand (channel, &cmd, 0); | |
249 } | |
250 | |
251 return 1; | |
252 } | |
253 | |
254 static void Mac_CloseAudio(_THIS) { | |
255 | |
256 int i; | |
257 | |
258 running = 0; | |
259 | |
260 if (channel) { | |
261 SndDisposeChannel (channel, true); | |
262 channel = NULL; | |
263 } | |
264 | |
265 for ( i=0; i<2; ++i ) { | |
266 if ( buffer[i] ) { | |
267 free(buffer[i]); | |
268 buffer[i] = NULL; | |
269 } | |
270 } | |
271 } | |
272 | |
273 #else /* !TARGET_API_MAC_CARBON */ | |
274 | |
275 /* 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 | |
277 we're not paused. | |
278 */ | |
279 static pascal | |
280 void sndDoubleBackProc (SndChannelPtr chan, SndDoubleBufferPtr newbuf) | |
281 { | |
282 SDL_AudioDevice *audio = (SDL_AudioDevice *)newbuf->dbUserInfo[0]; | |
283 | |
284 /* If audio is quitting, don't do anything */ | |
285 if ( ! audio->enabled ) { | |
286 return; | |
287 } | |
288 memset (newbuf->dbSoundData, 0, audio->spec.size); | |
289 newbuf->dbNumFrames = audio->spec.samples; | |
290 if ( ! audio->paused ) { | |
291 if ( audio->convert.needed ) { | |
292 audio->spec.callback(audio->spec.userdata, | |
293 (Uint8 *)audio->convert.buf,audio->convert.len); | |
294 SDL_ConvertAudio(&audio->convert); | |
295 #if 0 | |
296 if ( audio->convert.len_cvt != audio->spec.size ) { | |
297 /* Uh oh... probably crashes here */; | |
298 } | |
299 #endif | |
300 memcpy(newbuf->dbSoundData, audio->convert.buf, | |
301 audio->convert.len_cvt); | |
302 } else { | |
303 audio->spec.callback(audio->spec.userdata, | |
304 (Uint8 *)newbuf->dbSoundData, audio->spec.size); | |
305 } | |
306 } | |
307 newbuf->dbFlags |= dbBufferReady; | |
308 } | |
309 | |
310 static int DoubleBufferAudio_Available(void) | |
311 { | |
312 int available; | |
313 NumVersion sndversion; | |
314 long response; | |
315 | |
316 available = 0; | |
317 sndversion = SndSoundManagerVersion(); | |
318 if ( sndversion.majorRev >= 3 ) { | |
319 if ( Gestalt(gestaltSoundAttr, &response) == noErr ) { | |
320 if ( (response & (1 << gestaltSndPlayDoubleBuffer)) ) { | |
321 available = 1; | |
322 } | |
323 } | |
324 } else { | |
325 if ( Gestalt(gestaltSoundAttr, &response) == noErr ) { | |
326 if ( (response & (1 << gestaltHasASC)) ) { | |
327 available = 1; | |
328 } | |
329 } | |
330 } | |
331 return(available); | |
332 } | |
333 | |
334 static void Mac_CloseAudio(_THIS) | |
335 { | |
336 int i; | |
337 | |
338 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 */ | |
348 SndDisposeChannel(channel, true); | |
349 channel = NULL; | |
350 } | |
351 for ( i=0; i<2; ++i ) { | |
352 if ( audio_buf[i] ) { | |
353 free(audio_buf[i]); | |
354 audio_buf[i] = NULL; | |
355 } | |
356 } | |
357 } | |
358 | |
359 static int Mac_OpenAudio(_THIS, SDL_AudioSpec *spec) | |
360 { | |
361 SndDoubleBufferHeader2 audio_dbh; | |
362 int i; | |
363 long initOptions; | |
364 int sample_bits; | |
365 SndDoubleBackUPP doubleBackProc; | |
366 | |
367 /* Check to make sure double-buffered audio is available */ | |
368 if ( ! DoubleBufferAudio_Available() ) { | |
369 SDL_SetError("Sound manager doesn't support double-buffering"); | |
370 return(-1); | |
371 } | |
372 | |
373 /* Very few conversions are required, but... */ | |
374 switch (spec->format) { | |
375 case AUDIO_S8: | |
376 spec->format = AUDIO_U8; | |
377 break; | |
378 case AUDIO_U16LSB: | |
379 spec->format = AUDIO_S16LSB; | |
380 break; | |
381 case AUDIO_U16MSB: | |
382 spec->format = AUDIO_S16MSB; | |
383 break; | |
384 } | |
385 SDL_CalculateAudioSpec(spec); | |
386 | |
387 /* initialize the double-back header */ | |
388 memset(&audio_dbh, 0, sizeof(audio_dbh)); | |
389 doubleBackProc = NewSndDoubleBackProc (sndDoubleBackProc); | |
390 sample_bits = spec->size / spec->samples / spec->channels * 8; | |
391 | |
392 audio_dbh.dbhNumChannels = spec->channels; | |
393 audio_dbh.dbhSampleSize = sample_bits; | |
394 audio_dbh.dbhCompressionID = 0; | |
395 audio_dbh.dbhPacketSize = 0; | |
396 audio_dbh.dbhSampleRate = spec->freq << 16; | |
397 audio_dbh.dbhDoubleBack = doubleBackProc; | |
398 audio_dbh.dbhFormat = 0; | |
399 | |
400 /* Note that we install the 16bitLittleEndian Converter if needed. */ | |
401 if ( spec->format == 0x8010 ) { | |
402 audio_dbh.dbhCompressionID = fixedCompression; | |
403 audio_dbh.dbhFormat = k16BitLittleEndianFormat; | |
404 } | |
405 | |
406 /* allocate the 2 double-back buffers */ | |
407 for ( i=0; i<2; ++i ) { | |
408 audio_buf[i] = calloc(1, sizeof(SndDoubleBuffer)+spec->size); | |
409 if ( audio_buf[i] == NULL ) { | |
410 SDL_OutOfMemory(); | |
411 return(-1); | |
412 } | |
413 audio_buf[i]->dbNumFrames = spec->samples; | |
414 audio_buf[i]->dbFlags = dbBufferReady; | |
415 audio_buf[i]->dbUserInfo[0] = (long)this; | |
416 audio_dbh.dbhBufferPtr[i] = audio_buf[i]; | |
417 } | |
418 | |
419 /* Create the sound manager channel */ | |
420 channel = (SndChannelPtr)malloc(sizeof(*channel)); | |
421 if ( channel == NULL ) { | |
422 SDL_OutOfMemory(); | |
423 return(-1); | |
424 } | |
425 if ( spec->channels >= 2 ) { | |
426 initOptions = initStereo; | |
427 } else { | |
428 initOptions = initMono; | |
429 } | |
430 channel->userInfo = 0; | |
431 channel->qLength = 128; | |
432 if ( SndNewChannel(&channel, sampledSynth, initOptions, 0L) != noErr ) { | |
433 SDL_SetError("Unable to create audio channel"); | |
434 free(channel); | |
435 channel = NULL; | |
436 return(-1); | |
437 } | |
438 | |
439 /* Start playback */ | |
440 if ( SndPlayDoubleBuffer(channel, (SndDoubleBufferHeaderPtr)&audio_dbh) | |
441 != noErr ) { | |
442 SDL_SetError("Unable to play double buffered audio"); | |
443 return(-1); | |
444 } | |
445 | |
446 return 1; | |
447 } | |
448 | |
449 #endif /* TARGET_API_MAC_CARBON */ | |
450 | |
451 |