comparison src/audio/macrom/SDL_romaudio.c @ 3782:8225ef1f4dee SDL-ryan-multiple-audio-device

Removed the pre-Carbon Mac OS 9 audio code, so Mac OS 8 is officially unsupported now. :) The "USE_RYANS_SOUNDCODE" portion, which is what remains, has been the active codepath for years now without complaint, and was used in several shipping OS X titles before the CoreAudio support obsoleted it, so it's a good fallback to keep around for testing if nothing else. This code should still work on both OS 9, and PowerPC/Intel Mac OS X.
author Ryan C. Gordon <icculus@icculus.org>
date Sun, 01 Oct 2006 05:19:16 +0000
parents c27292a690b7
children 37c9c4590689
comparison
equal deleted inserted replaced
3781:3a64f57eb3cf 3782:8225ef1f4dee
19 Sam Lantinga 19 Sam Lantinga
20 slouken@libsdl.org 20 slouken@libsdl.org
21 */ 21 */
22 #include "SDL_config.h" 22 #include "SDL_config.h"
23 23
24 /* This should work on PowerPC and Intel Mac OS X, and Carbonized Mac OS 9. */
25
24 #if defined(__APPLE__) && defined(__MACH__) 26 #if defined(__APPLE__) && defined(__MACH__)
27 # define SDL_MACOS_NAME "Mac OS X"
25 # include <Carbon/Carbon.h> 28 # include <Carbon/Carbon.h>
26 #elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335) 29 #elif TARGET_API_MAC_CARBON && (UNIVERSAL_INTERFACES_VERSION > 0x0335)
30 # define SDL_MACOS_NAME "Mac OS 9"
27 # include <Carbon.h> 31 # include <Carbon.h>
28 #else 32 #else
33 # define SDL_MACOS_NAME "Mac OS 9"
29 # include <Sound.h> /* SoundManager interface */ 34 # include <Sound.h> /* SoundManager interface */
30 # include <Gestalt.h> 35 # include <Gestalt.h>
31 # include <DriverServices.h> 36 # include <DriverServices.h>
32 #endif 37 #endif
33 38
102 #endif 107 #endif
103 return this; 108 return this;
104 } 109 }
105 110
106 AudioBootStrap SNDMGR_bootstrap = { 111 AudioBootStrap SNDMGR_bootstrap = {
107 "sndmgr", "MacOS SoundManager 3.0", 112 "sndmgr", SDL_MACOS_NAME " SoundManager",
108 Audio_Available, Audio_CreateDevice 113 Audio_Available, Audio_CreateDevice
109 }; 114 };
110
111 #if defined(TARGET_API_MAC_CARBON) || defined(USE_RYANS_SOUNDCODE)
112 /* This works correctly on Mac OS X */
113 115
114 #pragma options align=power 116 #pragma options align=power
115 117
116 static volatile SInt32 audio_is_locked = 0; 118 static volatile SInt32 audio_is_locked = 0;
117 static volatile SInt32 need_to_mix = 0; 119 static volatile SInt32 need_to_mix = 0;
337 buffer[i] = NULL; 339 buffer[i] = NULL;
338 } 340 }
339 } 341 }
340 } 342 }
341 343
342 #else /* !TARGET_API_MAC_CARBON && !USE_RYANS_SOUNDCODE */
343
344 static void
345 Mac_LockAudio(_THIS)
346 {
347 /* no-op. */
348 }
349
350 static void
351 Mac_UnlockAudio(_THIS)
352 {
353 /* no-op. */
354 }
355
356
357 /* This function is called by Sound Manager when it has exhausted one of
358 the buffers, so we'll zero it to silence and fill it with audio if
359 we're not paused.
360 */
361 static pascal void
362 sndDoubleBackProc(SndChannelPtr chan, SndDoubleBufferPtr newbuf)
363 {
364 SDL_AudioDevice *audio = (SDL_AudioDevice *) newbuf->dbUserInfo[0];
365
366 /* If audio is quitting, don't do anything */
367 if (!audio->enabled) {
368 return;
369 }
370 memset(newbuf->dbSoundData, 0, audio->spec.size);
371 newbuf->dbNumFrames = audio->spec.samples;
372 if (!audio->paused) {
373 if (audio->convert.needed) {
374 audio->spec.callback(audio->spec.userdata,
375 (Uint8 *) audio->convert.buf,
376 audio->convert.len);
377 SDL_ConvertAudio(&audio->convert);
378 #if 0
379 if (audio->convert.len_cvt != audio->spec.size) {
380 /* Uh oh... probably crashes here */ ;
381 }
382 #endif
383 SDL_memcpy(newbuf->dbSoundData, audio->convert.buf,
384 audio->convert.len_cvt);
385 } else {
386 audio->spec.callback(audio->spec.userdata,
387 (Uint8 *) newbuf->dbSoundData,
388 audio->spec.size);
389 }
390 }
391 newbuf->dbFlags |= dbBufferReady;
392 }
393
394 static int
395 DoubleBufferAudio_Available(void)
396 {
397 int available;
398 NumVersion sndversion;
399 long response;
400
401 available = 0;
402 sndversion = SndSoundManagerVersion();
403 if (sndversion.majorRev >= 3) {
404 if (Gestalt(gestaltSoundAttr, &response) == noErr) {
405 if ((response & (1 << gestaltSndPlayDoubleBuffer))) {
406 available = 1;
407 }
408 }
409 } else {
410 if (Gestalt(gestaltSoundAttr, &response) == noErr) {
411 if ((response & (1 << gestaltHasASC))) {
412 available = 1;
413 }
414 }
415 }
416 return (available);
417 }
418
419 static void
420 Mac_CloseAudio(_THIS)
421 {
422 int i;
423
424 if (channel != NULL) {
425 /* Clean up the audio channel */
426 SndDisposeChannel(channel, true);
427 channel = NULL;
428 }
429 for (i = 0; i < 2; ++i) {
430 if (audio_buf[i]) {
431 SDL_free(audio_buf[i]);
432 audio_buf[i] = NULL;
433 }
434 }
435 }
436
437 static int
438 Mac_OpenAudio(_THIS, SDL_AudioSpec * spec)
439 {
440 SndDoubleBufferHeader2 audio_dbh;
441 int i;
442 long initOptions;
443 int sample_bits;
444 SndDoubleBackUPP doubleBackProc;
445
446 /* Check to make sure double-buffered audio is available */
447 if (!DoubleBufferAudio_Available()) {
448 SDL_SetError("Sound manager doesn't support double-buffering");
449 return (-1);
450 }
451
452 /* Very few conversions are required, but... */
453 switch (spec->format) {
454 case AUDIO_S8:
455 spec->format = AUDIO_U8;
456 break;
457 case AUDIO_U16LSB:
458 spec->format = AUDIO_S16LSB;
459 break;
460 case AUDIO_U16MSB:
461 spec->format = AUDIO_S16MSB;
462 break;
463 }
464 SDL_CalculateAudioSpec(spec);
465
466 /* initialize the double-back header */
467 SDL_memset(&audio_dbh, 0, sizeof(audio_dbh));
468 doubleBackProc = NewSndDoubleBackProc(sndDoubleBackProc);
469 sample_bits = spec->size / spec->samples / spec->channels * 8;
470
471 audio_dbh.dbhNumChannels = spec->channels;
472 audio_dbh.dbhSampleSize = sample_bits;
473 audio_dbh.dbhCompressionID = 0;
474 audio_dbh.dbhPacketSize = 0;
475 audio_dbh.dbhSampleRate = spec->freq << 16;
476 audio_dbh.dbhDoubleBack = doubleBackProc;
477 audio_dbh.dbhFormat = 0;
478
479 /* Note that we install the 16bitLittleEndian Converter if needed. */
480 if (spec->format == 0x8010) {
481 audio_dbh.dbhCompressionID = fixedCompression;
482 audio_dbh.dbhFormat = k16BitLittleEndianFormat;
483 }
484
485 /* allocate the 2 double-back buffers */
486 for (i = 0; i < 2; ++i) {
487 audio_buf[i] = SDL_calloc(1, sizeof(SndDoubleBuffer) + spec->size);
488 if (audio_buf[i] == NULL) {
489 SDL_OutOfMemory();
490 return (-1);
491 }
492 audio_buf[i]->dbNumFrames = spec->samples;
493 audio_buf[i]->dbFlags = dbBufferReady;
494 audio_buf[i]->dbUserInfo[0] = (long) this;
495 audio_dbh.dbhBufferPtr[i] = audio_buf[i];
496 }
497
498 /* Create the sound manager channel */
499 channel = (SndChannelPtr) SDL_malloc(sizeof(*channel));
500 if (channel == NULL) {
501 SDL_OutOfMemory();
502 return (-1);
503 }
504 if (spec->channels >= 2) {
505 initOptions = initStereo;
506 } else {
507 initOptions = initMono;
508 }
509 channel->userInfo = 0;
510 channel->qLength = 128;
511 if (SndNewChannel(&channel, sampledSynth, initOptions, 0L) != noErr) {
512 SDL_SetError("Unable to create audio channel");
513 SDL_free(channel);
514 channel = NULL;
515 return (-1);
516 }
517
518 /* Start playback */
519 if (SndPlayDoubleBuffer(channel, (SndDoubleBufferHeaderPtr) & audio_dbh)
520 != noErr) {
521 SDL_SetError("Unable to play double buffered audio");
522 return (-1);
523 }
524
525 return 1;
526 }
527
528 #endif /* TARGET_API_MAC_CARBON || USE_RYANS_SOUNDCODE */
529 /* vi: set ts=4 sw=4 expandtab: */ 344 /* vi: set ts=4 sw=4 expandtab: */