SDL  2.0
SDL_coreaudio.c
Go to the documentation of this file.
1 /*
2  Simple DirectMedia Layer
3  Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4 
5  This software is provided 'as-is', without any express or implied
6  warranty. In no event will the authors be held liable for any damages
7  arising from the use of this software.
8 
9  Permission is granted to anyone to use this software for any purpose,
10  including commercial applications, and to alter it and redistribute it
11  freely, subject to the following restrictions:
12 
13  1. The origin of this software must not be misrepresented; you must not
14  claim that you wrote the original software. If you use this software
15  in a product, an acknowledgment in the product documentation would be
16  appreciated but is not required.
17  2. Altered source versions must be plainly marked as such, and must not be
18  misrepresented as being the original software.
19  3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../../SDL_internal.h"
22 
23 #if SDL_AUDIO_DRIVER_COREAUDIO
24 
25 #include "SDL_audio.h"
26 #include "../SDL_audio_c.h"
27 #include "../SDL_sysaudio.h"
28 #include "SDL_coreaudio.h"
29 #include "SDL_assert.h"
30 
31 #define DEBUG_COREAUDIO 0
32 
33 static void COREAUDIO_CloseDevice(_THIS);
34 
35 #define CHECK_RESULT(msg) \
36  if (result != noErr) { \
37  COREAUDIO_CloseDevice(this); \
38  SDL_SetError("CoreAudio error (%s): %d", msg, (int) result); \
39  return 0; \
40  }
41 
42 #if MACOSX_COREAUDIO
43 static const AudioObjectPropertyAddress devlist_address = {
44  kAudioHardwarePropertyDevices,
45  kAudioObjectPropertyScopeGlobal,
46  kAudioObjectPropertyElementMaster
47 };
48 
49 typedef void (*addDevFn)(const char *name, const int iscapture, AudioDeviceID devId, void *data);
50 
51 typedef struct AudioDeviceList
52 {
53  AudioDeviceID devid;
55  struct AudioDeviceList *next;
56 } AudioDeviceList;
57 
58 static AudioDeviceList *output_devs = NULL;
59 static AudioDeviceList *capture_devs = NULL;
60 
61 static SDL_bool
62 add_to_internal_dev_list(const int iscapture, AudioDeviceID devId)
63 {
64  AudioDeviceList *item = (AudioDeviceList *) SDL_malloc(sizeof (AudioDeviceList));
65  if (item == NULL) {
66  return SDL_FALSE;
67  }
68  item->devid = devId;
69  item->alive = SDL_TRUE;
70  item->next = iscapture ? capture_devs : output_devs;
71  if (iscapture) {
72  capture_devs = item;
73  } else {
74  output_devs = item;
75  }
76 
77  return SDL_TRUE;
78 }
79 
80 static void
81 addToDevList(const char *name, const int iscapture, AudioDeviceID devId, void *data)
82 {
83  if (add_to_internal_dev_list(iscapture, devId)) {
84  SDL_AddAudioDevice(iscapture, name, (void *) ((size_t) devId));
85  }
86 }
87 
88 static void
89 build_device_list(int iscapture, addDevFn addfn, void *addfndata)
90 {
91  OSStatus result = noErr;
92  UInt32 size = 0;
93  AudioDeviceID *devs = NULL;
94  UInt32 i = 0;
95  UInt32 max = 0;
96 
97  result = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject,
98  &devlist_address, 0, NULL, &size);
99  if (result != kAudioHardwareNoError)
100  return;
101 
102  devs = (AudioDeviceID *) alloca(size);
103  if (devs == NULL)
104  return;
105 
106  result = AudioObjectGetPropertyData(kAudioObjectSystemObject,
107  &devlist_address, 0, NULL, &size, devs);
108  if (result != kAudioHardwareNoError)
109  return;
110 
111  max = size / sizeof (AudioDeviceID);
112  for (i = 0; i < max; i++) {
113  CFStringRef cfstr = NULL;
114  char *ptr = NULL;
115  AudioDeviceID dev = devs[i];
116  AudioBufferList *buflist = NULL;
117  int usable = 0;
118  CFIndex len = 0;
119  const AudioObjectPropertyAddress addr = {
120  kAudioDevicePropertyStreamConfiguration,
121  iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput,
122  kAudioObjectPropertyElementMaster
123  };
124 
125  const AudioObjectPropertyAddress nameaddr = {
126  kAudioObjectPropertyName,
127  iscapture ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput,
128  kAudioObjectPropertyElementMaster
129  };
130 
131  result = AudioObjectGetPropertyDataSize(dev, &addr, 0, NULL, &size);
132  if (result != noErr)
133  continue;
134 
135  buflist = (AudioBufferList *) SDL_malloc(size);
136  if (buflist == NULL)
137  continue;
138 
139  result = AudioObjectGetPropertyData(dev, &addr, 0, NULL,
140  &size, buflist);
141 
142  if (result == noErr) {
143  UInt32 j;
144  for (j = 0; j < buflist->mNumberBuffers; j++) {
145  if (buflist->mBuffers[j].mNumberChannels > 0) {
146  usable = 1;
147  break;
148  }
149  }
150  }
151 
152  SDL_free(buflist);
153 
154  if (!usable)
155  continue;
156 
157 
158  size = sizeof (CFStringRef);
159  result = AudioObjectGetPropertyData(dev, &nameaddr, 0, NULL, &size, &cfstr);
160  if (result != kAudioHardwareNoError)
161  continue;
162 
163  len = CFStringGetMaximumSizeForEncoding(CFStringGetLength(cfstr),
164  kCFStringEncodingUTF8);
165 
166  ptr = (char *) SDL_malloc(len + 1);
167  usable = ((ptr != NULL) &&
168  (CFStringGetCString
169  (cfstr, ptr, len + 1, kCFStringEncodingUTF8)));
170 
171  CFRelease(cfstr);
172 
173  if (usable) {
174  len = strlen(ptr);
175  /* Some devices have whitespace at the end...trim it. */
176  while ((len > 0) && (ptr[len - 1] == ' ')) {
177  len--;
178  }
179  usable = (len > 0);
180  }
181 
182  if (usable) {
183  ptr[len] = '\0';
184 
185 #if DEBUG_COREAUDIO
186  printf("COREAUDIO: Found %s device #%d: '%s' (devid %d)\n",
187  ((iscapture) ? "capture" : "output"),
188  (int) *devCount, ptr, (int) dev);
189 #endif
190  addfn(ptr, iscapture, dev, addfndata);
191  }
192  SDL_free(ptr); /* addfn() would have copied the string. */
193  }
194 }
195 
196 static void
197 free_audio_device_list(AudioDeviceList **list)
198 {
199  AudioDeviceList *item = *list;
200  while (item) {
201  AudioDeviceList *next = item->next;
202  SDL_free(item);
203  item = next;
204  }
205  *list = NULL;
206 }
207 
208 static void
209 COREAUDIO_DetectDevices(void)
210 {
211  build_device_list(SDL_TRUE, addToDevList, NULL);
212  build_device_list(SDL_FALSE, addToDevList, NULL);
213 }
214 
215 static void
216 build_device_change_list(const char *name, const int iscapture, AudioDeviceID devId, void *data)
217 {
218  AudioDeviceList **list = (AudioDeviceList **) data;
219  AudioDeviceList *item;
220  for (item = *list; item != NULL; item = item->next) {
221  if (item->devid == devId) {
222  item->alive = SDL_TRUE;
223  return;
224  }
225  }
226 
227  add_to_internal_dev_list(iscapture, devId); /* new device, add it. */
228  SDL_AddAudioDevice(iscapture, name, (void *) ((size_t) devId));
229 }
230 
231 static void
232 reprocess_device_list(const int iscapture, AudioDeviceList **list)
233 {
234  AudioDeviceList *item;
235  AudioDeviceList *prev = NULL;
236  for (item = *list; item != NULL; item = item->next) {
237  item->alive = SDL_FALSE;
238  }
239 
240  build_device_list(iscapture, build_device_change_list, list);
241 
242  /* free items in the list that aren't still alive. */
243  item = *list;
244  while (item != NULL) {
245  AudioDeviceList *next = item->next;
246  if (item->alive) {
247  prev = item;
248  } else {
249  SDL_RemoveAudioDevice(iscapture, (void *) ((size_t) item->devid));
250  if (prev) {
251  prev->next = item->next;
252  } else {
253  *list = item->next;
254  }
255  SDL_free(item);
256  }
257  item = next;
258  }
259 }
260 
261 /* this is called when the system's list of available audio devices changes. */
262 static OSStatus
263 device_list_changed(AudioObjectID systemObj, UInt32 num_addr, const AudioObjectPropertyAddress *addrs, void *data)
264 {
265  reprocess_device_list(SDL_TRUE, &capture_devs);
266  reprocess_device_list(SDL_FALSE, &output_devs);
267  return 0;
268 }
269 #endif
270 
271 /* The CoreAudio callback */
272 static OSStatus
273 outputCallback(void *inRefCon,
274  AudioUnitRenderActionFlags * ioActionFlags,
275  const AudioTimeStamp * inTimeStamp,
276  UInt32 inBusNumber, UInt32 inNumberFrames,
277  AudioBufferList * ioData)
278 {
279  SDL_AudioDevice *this = (SDL_AudioDevice *) inRefCon;
280  AudioBuffer *abuf;
281  UInt32 remaining, len;
282  void *ptr;
283  UInt32 i;
284 
285  /* Only do anything if audio is enabled and not paused */
286  if (!this->enabled || this->paused) {
287  for (i = 0; i < ioData->mNumberBuffers; i++) {
288  abuf = &ioData->mBuffers[i];
289  SDL_memset(abuf->mData, this->spec.silence, abuf->mDataByteSize);
290  }
291  return 0;
292  }
293 
294  /* No SDL conversion should be needed here, ever, since we accept
295  any input format in OpenAudio, and leave the conversion to CoreAudio.
296  */
297  /*
298  SDL_assert(!this->convert.needed);
299  SDL_assert(this->spec.channels == ioData->mNumberChannels);
300  */
301 
302  for (i = 0; i < ioData->mNumberBuffers; i++) {
303  abuf = &ioData->mBuffers[i];
304  remaining = abuf->mDataByteSize;
305  ptr = abuf->mData;
306  while (remaining > 0) {
307  if (this->hidden->bufferOffset >= this->hidden->bufferSize) {
308  /* Generate the data */
309  SDL_LockMutex(this->mixer_lock);
310  (*this->spec.callback)(this->spec.userdata,
311  this->hidden->buffer, this->hidden->bufferSize);
312  SDL_UnlockMutex(this->mixer_lock);
313  this->hidden->bufferOffset = 0;
314  }
315 
316  len = this->hidden->bufferSize - this->hidden->bufferOffset;
317  if (len > remaining)
318  len = remaining;
319  SDL_memcpy(ptr, (char *)this->hidden->buffer +
320  this->hidden->bufferOffset, len);
321  ptr = (char *)ptr + len;
322  remaining -= len;
323  this->hidden->bufferOffset += len;
324  }
325  }
326 
327  return 0;
328 }
329 
330 static OSStatus
331 inputCallback(void *inRefCon,
332  AudioUnitRenderActionFlags * ioActionFlags,
333  const AudioTimeStamp * inTimeStamp,
334  UInt32 inBusNumber, UInt32 inNumberFrames,
335  AudioBufferList * ioData)
336 {
337  /* err = AudioUnitRender(afr->fAudioUnit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, afr->fAudioBuffer); */
338  /* !!! FIXME: write me! */
339  return noErr;
340 }
341 
342 
343 #if MACOSX_COREAUDIO
344 static const AudioObjectPropertyAddress alive_address =
345 {
346  kAudioDevicePropertyDeviceIsAlive,
347  kAudioObjectPropertyScopeGlobal,
348  kAudioObjectPropertyElementMaster
349 };
350 
351 static OSStatus
352 device_unplugged(AudioObjectID devid, UInt32 num_addr, const AudioObjectPropertyAddress *addrs, void *data)
353 {
354  SDL_AudioDevice *this = (SDL_AudioDevice *) data;
355  SDL_bool dead = SDL_FALSE;
356  UInt32 isAlive = 1;
357  UInt32 size = sizeof (isAlive);
358  OSStatus error;
359 
360  if (!this->enabled) {
361  return 0; /* already known to be dead. */
362  }
363 
364  error = AudioObjectGetPropertyData(this->hidden->deviceID, &alive_address,
365  0, NULL, &size, &isAlive);
366 
367  if (error == kAudioHardwareBadDeviceError) {
368  dead = SDL_TRUE; /* device was unplugged. */
369  } else if ((error == kAudioHardwareNoError) && (!isAlive)) {
370  dead = SDL_TRUE; /* device died in some other way. */
371  }
372 
373  if (dead) {
375  }
376 
377  return 0;
378 }
379 #endif
380 
381 static void
382 COREAUDIO_CloseDevice(_THIS)
383 {
384  if (this->hidden != NULL) {
385  if (this->hidden->audioUnitOpened) {
386  #if MACOSX_COREAUDIO
387  /* Unregister our disconnect callback. */
388  AudioObjectRemovePropertyListener(this->hidden->deviceID, &alive_address, device_unplugged, this);
389  #endif
390 
391  AURenderCallbackStruct callback;
392  const AudioUnitElement output_bus = 0;
393  const AudioUnitElement input_bus = 1;
394  const int iscapture = this->iscapture;
395  const AudioUnitElement bus =
396  ((iscapture) ? input_bus : output_bus);
397  const AudioUnitScope scope =
398  ((iscapture) ? kAudioUnitScope_Output :
399  kAudioUnitScope_Input);
400 
401  /* stop processing the audio unit */
402  AudioOutputUnitStop(this->hidden->audioUnit);
403 
404  /* Remove the input callback */
405  SDL_memset(&callback, 0, sizeof(AURenderCallbackStruct));
406  AudioUnitSetProperty(this->hidden->audioUnit,
407  kAudioUnitProperty_SetRenderCallback,
408  scope, bus, &callback, sizeof(callback));
409 
410  #if MACOSX_COREAUDIO
411  CloseComponent(this->hidden->audioUnit);
412  #else
413  AudioComponentInstanceDispose(this->hidden->audioUnit);
414  #endif
415 
416  this->hidden->audioUnitOpened = 0;
417  }
418  SDL_free(this->hidden->buffer);
419  SDL_free(this->hidden);
420  this->hidden = NULL;
421  }
422 }
423 
424 #if MACOSX_COREAUDIO
425 static int
426 prepare_device(_THIS, void *handle, int iscapture)
427 {
428  AudioDeviceID devid = (AudioDeviceID) ((size_t) handle);
429  OSStatus result = noErr;
430  UInt32 size = 0;
431  UInt32 alive = 0;
432  pid_t pid = 0;
433 
434  AudioObjectPropertyAddress addr = {
435  0,
436  kAudioObjectPropertyScopeGlobal,
437  kAudioObjectPropertyElementMaster
438  };
439 
440  if (handle == NULL) {
441  size = sizeof (AudioDeviceID);
442  addr.mSelector =
443  ((iscapture) ? kAudioHardwarePropertyDefaultInputDevice :
444  kAudioHardwarePropertyDefaultOutputDevice);
445  result = AudioObjectGetPropertyData(kAudioObjectSystemObject, &addr,
446  0, NULL, &size, &devid);
447  CHECK_RESULT("AudioHardwareGetProperty (default device)");
448  }
449 
450  addr.mSelector = kAudioDevicePropertyDeviceIsAlive;
451  addr.mScope = iscapture ? kAudioDevicePropertyScopeInput :
452  kAudioDevicePropertyScopeOutput;
453 
454  size = sizeof (alive);
455  result = AudioObjectGetPropertyData(devid, &addr, 0, NULL, &size, &alive);
456  CHECK_RESULT
457  ("AudioDeviceGetProperty (kAudioDevicePropertyDeviceIsAlive)");
458 
459  if (!alive) {
460  SDL_SetError("CoreAudio: requested device exists, but isn't alive.");
461  return 0;
462  }
463 
464  addr.mSelector = kAudioDevicePropertyHogMode;
465  size = sizeof (pid);
466  result = AudioObjectGetPropertyData(devid, &addr, 0, NULL, &size, &pid);
467 
468  /* some devices don't support this property, so errors are fine here. */
469  if ((result == noErr) && (pid != -1)) {
470  SDL_SetError("CoreAudio: requested device is being hogged.");
471  return 0;
472  }
473 
474  this->hidden->deviceID = devid;
475  return 1;
476 }
477 #endif
478 
479 static int
480 prepare_audiounit(_THIS, void *handle, int iscapture,
481  const AudioStreamBasicDescription * strdesc)
482 {
483  OSStatus result = noErr;
484  AURenderCallbackStruct callback;
485 #if MACOSX_COREAUDIO
486  ComponentDescription desc;
487  Component comp = NULL;
488 #else
489  AudioComponentDescription desc;
490  AudioComponent comp = NULL;
491 #endif
492  const AudioUnitElement output_bus = 0;
493  const AudioUnitElement input_bus = 1;
494  const AudioUnitElement bus = ((iscapture) ? input_bus : output_bus);
495  const AudioUnitScope scope = ((iscapture) ? kAudioUnitScope_Output :
496  kAudioUnitScope_Input);
497 
498 #if MACOSX_COREAUDIO
499  if (!prepare_device(this, handle, iscapture)) {
500  return 0;
501  }
502 #endif
503 
504  SDL_zero(desc);
505  desc.componentType = kAudioUnitType_Output;
506  desc.componentManufacturer = kAudioUnitManufacturer_Apple;
507 
508 #if MACOSX_COREAUDIO
509  desc.componentSubType = kAudioUnitSubType_DefaultOutput;
510  comp = FindNextComponent(NULL, &desc);
511 #else
512  desc.componentSubType = kAudioUnitSubType_RemoteIO;
513  comp = AudioComponentFindNext(NULL, &desc);
514 #endif
515 
516  if (comp == NULL) {
517  SDL_SetError("Couldn't find requested CoreAudio component");
518  return 0;
519  }
520 
521  /* Open & initialize the audio unit */
522 #if MACOSX_COREAUDIO
523  result = OpenAComponent(comp, &this->hidden->audioUnit);
524  CHECK_RESULT("OpenAComponent");
525 #else
526  /*
527  AudioComponentInstanceNew only available on iPhone OS 2.0 and Mac OS X 10.6
528  We can't use OpenAComponent on iPhone because it is not present
529  */
530  result = AudioComponentInstanceNew(comp, &this->hidden->audioUnit);
531  CHECK_RESULT("AudioComponentInstanceNew");
532 #endif
533 
534  this->hidden->audioUnitOpened = 1;
535 
536 #if MACOSX_COREAUDIO
537  result = AudioUnitSetProperty(this->hidden->audioUnit,
538  kAudioOutputUnitProperty_CurrentDevice,
539  kAudioUnitScope_Global, 0,
540  &this->hidden->deviceID,
541  sizeof(AudioDeviceID));
542  CHECK_RESULT
543  ("AudioUnitSetProperty (kAudioOutputUnitProperty_CurrentDevice)");
544 #endif
545 
546  /* Set the data format of the audio unit. */
547  result = AudioUnitSetProperty(this->hidden->audioUnit,
548  kAudioUnitProperty_StreamFormat,
549  scope, bus, strdesc, sizeof(*strdesc));
550  CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_StreamFormat)");
551 
552  /* Set the audio callback */
553  SDL_memset(&callback, 0, sizeof(AURenderCallbackStruct));
554  callback.inputProc = ((iscapture) ? inputCallback : outputCallback);
555  callback.inputProcRefCon = this;
556  result = AudioUnitSetProperty(this->hidden->audioUnit,
557  kAudioUnitProperty_SetRenderCallback,
558  scope, bus, &callback, sizeof(callback));
559  CHECK_RESULT
560  ("AudioUnitSetProperty (kAudioUnitProperty_SetRenderCallback)");
561 
562  /* Calculate the final parameters for this audio specification */
564 
565  /* Allocate a sample buffer */
566  this->hidden->bufferOffset = this->hidden->bufferSize = this->spec.size;
567  this->hidden->buffer = SDL_malloc(this->hidden->bufferSize);
568 
569  result = AudioUnitInitialize(this->hidden->audioUnit);
570  CHECK_RESULT("AudioUnitInitialize");
571 
572  /* Finally, start processing of the audio unit */
573  result = AudioOutputUnitStart(this->hidden->audioUnit);
574  CHECK_RESULT("AudioOutputUnitStart");
575 
576 #if MACOSX_COREAUDIO
577  /* Fire a callback if the device stops being "alive" (disconnected, etc). */
578  AudioObjectAddPropertyListener(this->hidden->deviceID, &alive_address, device_unplugged, this);
579 #endif
580 
581  /* We're running! */
582  return 1;
583 }
584 
585 
586 static int
587 COREAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
588 {
589  AudioStreamBasicDescription strdesc;
590  SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
591  int valid_datatype = 0;
592 
593  /* Initialize all variables that we clean on shutdown */
594  this->hidden = (struct SDL_PrivateAudioData *)
595  SDL_malloc((sizeof *this->hidden));
596  if (this->hidden == NULL) {
597  return SDL_OutOfMemory();
598  }
599  SDL_memset(this->hidden, 0, (sizeof *this->hidden));
600 
601  /* Setup a AudioStreamBasicDescription with the requested format */
602  SDL_memset(&strdesc, '\0', sizeof(AudioStreamBasicDescription));
603  strdesc.mFormatID = kAudioFormatLinearPCM;
604  strdesc.mFormatFlags = kLinearPCMFormatFlagIsPacked;
605  strdesc.mChannelsPerFrame = this->spec.channels;
606  strdesc.mSampleRate = this->spec.freq;
607  strdesc.mFramesPerPacket = 1;
608 
609  while ((!valid_datatype) && (test_format)) {
610  this->spec.format = test_format;
611  /* Just a list of valid SDL formats, so people don't pass junk here. */
612  switch (test_format) {
613  case AUDIO_U8:
614  case AUDIO_S8:
615  case AUDIO_U16LSB:
616  case AUDIO_S16LSB:
617  case AUDIO_U16MSB:
618  case AUDIO_S16MSB:
619  case AUDIO_S32LSB:
620  case AUDIO_S32MSB:
621  case AUDIO_F32LSB:
622  case AUDIO_F32MSB:
623  valid_datatype = 1;
624  strdesc.mBitsPerChannel = SDL_AUDIO_BITSIZE(this->spec.format);
625  if (SDL_AUDIO_ISBIGENDIAN(this->spec.format))
626  strdesc.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
627 
628  if (SDL_AUDIO_ISFLOAT(this->spec.format))
629  strdesc.mFormatFlags |= kLinearPCMFormatFlagIsFloat;
630  else if (SDL_AUDIO_ISSIGNED(this->spec.format))
631  strdesc.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
632  break;
633  }
634  }
635 
636  if (!valid_datatype) { /* shouldn't happen, but just in case... */
637  COREAUDIO_CloseDevice(this);
638  return SDL_SetError("Unsupported audio format");
639  }
640 
641  strdesc.mBytesPerFrame =
642  strdesc.mBitsPerChannel * strdesc.mChannelsPerFrame / 8;
643  strdesc.mBytesPerPacket =
644  strdesc.mBytesPerFrame * strdesc.mFramesPerPacket;
645 
646  if (!prepare_audiounit(this, handle, iscapture, &strdesc)) {
647  COREAUDIO_CloseDevice(this);
648  return -1; /* prepare_audiounit() will call SDL_SetError()... */
649  }
650 
651  return 0; /* good to go. */
652 }
653 
654 static void
655 COREAUDIO_Deinitialize(void)
656 {
657 #if MACOSX_COREAUDIO
658  AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &devlist_address, device_list_changed, NULL);
659  free_audio_device_list(&capture_devs);
660  free_audio_device_list(&output_devs);
661 #endif
662 }
663 
664 static int
665 COREAUDIO_Init(SDL_AudioDriverImpl * impl)
666 {
667  /* Set the function pointers */
668  impl->OpenDevice = COREAUDIO_OpenDevice;
669  impl->CloseDevice = COREAUDIO_CloseDevice;
670  impl->Deinitialize = COREAUDIO_Deinitialize;
671 
672 #if MACOSX_COREAUDIO
673  impl->DetectDevices = COREAUDIO_DetectDevices;
674  AudioObjectAddPropertyListener(kAudioObjectSystemObject, &devlist_address, device_list_changed, NULL);
675 #else
676  impl->OnlyHasDefaultOutputDevice = 1;
677 
678  /* Set category to ambient sound so that other music continues playing.
679  You can change this at runtime in your own code if you need different
680  behavior. If this is common, we can add an SDL hint for this.
681  */
682  AudioSessionInitialize(NULL, NULL, NULL, nil);
683  UInt32 category = kAudioSessionCategory_AmbientSound;
684  AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(UInt32), &category);
685 #endif
686 
687  impl->ProvidesOwnCallbackThread = 1;
688 
689  return 1; /* this audio target is available. */
690 }
691 
693  "coreaudio", "CoreAudio", COREAUDIO_Init, 0
694 };
695 
696 #endif /* SDL_AUDIO_DRIVER_COREAUDIO */
697 
698 /* vi: set ts=4 sw=4 expandtab: */
int alive
Definition: testsem.c:24
#define SDL_LockMutex
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
Definition: SDL_audio.c:1398
#define AUDIO_S32MSB
Definition: SDL_audio.h:104
GLuint64EXT * result
void(* DetectDevices)(void)
Definition: SDL_sysaudio.h:71
#define SDL_AUDIO_ISBIGENDIAN(x)
Definition: SDL_audio.h:77
#define AUDIO_U16LSB
Definition: SDL_audio.h:91
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1967
#define SDL_AUDIO_ISSIGNED(x)
Definition: SDL_audio.h:78
void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
Definition: SDL_audio.c:364
Uint16 SDL_AudioFormat
Audio format flags.
Definition: SDL_audio.h:64
GLuint const GLchar * name
GLsizeiptr size
GLenum GLsizei len
#define AUDIO_F32MSB
Definition: SDL_audio.h:113
SDL_bool
Definition: SDL_stdinc.h:126
SDL_AudioSpec spec
Definition: loopwave.c:35
#define SDL_AUDIO_ISFLOAT(x)
Definition: SDL_audio.h:76
#define AUDIO_U8
Definition: SDL_audio.h:89
#define SDL_memcpy
void SDL_RemoveAudioDevice(const int iscapture, void *handle)
Definition: SDL_audio.c:405
Uint8 channels
Definition: SDL_audio.h:172
#define _THIS
void SDL_free(void *mem)
GLenum const void * addr
#define SDL_AUDIO_BITSIZE(x)
Definition: SDL_audio.h:75
#define AUDIO_F32LSB
Definition: SDL_audio.h:112
void(* Deinitialize)(void)
Definition: SDL_sysaudio.h:83
AudioBootStrap COREAUDIO_bootstrap
#define AUDIO_S32LSB
Definition: SDL_audio.h:103
#define SDL_zero(x)
Definition: SDL_stdinc.h:355
static Uint32 callback(Uint32 interval, void *param)
Definition: testtimer.c:34
int paused
Definition: testoverlay2.c:149
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
Definition: SDL_audio.c:1419
SDL_AudioCallback callback
Definition: SDL_audio.h:177
GLenum GLenum GLsizei const GLuint GLboolean enabled
Uint32 size
Definition: SDL_audio.h:176
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:42
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
Definition: SDL_sysaudio.h:72
#define NULL
Definition: begin_code.h:143
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
#define SDL_SetError
SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char int SDL_PRINTF_FORMAT_STRING const char const char SDL_SCANF_FORMAT_STRING const char return SDL_ThreadFunction const char void return Uint32 return Uint32 void
void(* CloseDevice)(_THIS)
Definition: SDL_sysaudio.h:79
#define AUDIO_S16MSB
Definition: SDL_audio.h:94
SDL_AudioFormat format
Definition: SDL_audio.h:171
#define AUDIO_S16LSB
Definition: SDL_audio.h:92
void * userdata
Definition: SDL_audio.h:178
#define SDL_UnlockMutex
#define SDL_malloc
#define AUDIO_S8
Definition: SDL_audio.h:90
#define SDL_memset
#define AUDIO_U16MSB
Definition: SDL_audio.h:93
void SDL_AddAudioDevice(const int iscapture, const char *name, void *handle)
Definition: SDL_audio.c:347
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int int in j)
Definition: SDL_x11sym.h:42