|
@@ -268,6 +268,27 @@ device_list_changed(AudioObjectID systemObj, UInt32 num_addr, const AudioObjectP
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
+
|
|
|
+static int open_playback_devices = 0;
|
|
|
+static int open_capture_devices = 0;
|
|
|
+
|
|
|
+static void update_audio_session()
|
|
|
+{
|
|
|
+#if !MACOSX_COREAUDIO
|
|
|
+ /* !!! FIXME: move this to AVAudioSession. This is deprecated, and the new version is available as of (ancient!) iOS 3.0 */
|
|
|
+ UInt32 category;
|
|
|
+ if (open_playback_devices && open_capture_devices) {
|
|
|
+ category = kAudioSessionCategory_PlayAndRecord;
|
|
|
+ } else if (open_capture_devices) {
|
|
|
+ category = kAudioSessionCategory_RecordAudio;
|
|
|
+ } else { /* nothing open, or just playing audio. */
|
|
|
+ category = kAudioSessionCategory_AmbientSound;
|
|
|
+ }
|
|
|
+ AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof (UInt32), &category);
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
/* The CoreAudio callback */
|
|
|
static OSStatus
|
|
|
outputCallback(void *inRefCon,
|
|
@@ -416,6 +437,7 @@ static void
|
|
|
COREAUDIO_CloseDevice(_THIS)
|
|
|
{
|
|
|
if (this->hidden != NULL) {
|
|
|
+ const int iscapture = this->iscapture;
|
|
|
if (this->hidden->audioUnitOpened) {
|
|
|
#if MACOSX_COREAUDIO
|
|
|
/* Unregister our disconnect callback. */
|
|
@@ -425,7 +447,6 @@ COREAUDIO_CloseDevice(_THIS)
|
|
|
AURenderCallbackStruct callback;
|
|
|
const AudioUnitElement output_bus = 0;
|
|
|
const AudioUnitElement input_bus = 1;
|
|
|
- const int iscapture = this->iscapture;
|
|
|
const AudioUnitElement bus =
|
|
|
((iscapture) ? input_bus : output_bus);
|
|
|
|
|
@@ -440,13 +461,19 @@ COREAUDIO_CloseDevice(_THIS)
|
|
|
AudioComponentInstanceDispose(this->hidden->audioUnit);
|
|
|
this->hidden->audioUnitOpened = 0;
|
|
|
|
|
|
- #if MACOSX_COREAUDIO
|
|
|
SDL_free(this->hidden->captureBufferList.mBuffers[0].mData);
|
|
|
- #endif
|
|
|
+
|
|
|
}
|
|
|
SDL_free(this->hidden->buffer);
|
|
|
SDL_free(this->hidden);
|
|
|
this->hidden = NULL;
|
|
|
+
|
|
|
+ if (iscapture) {
|
|
|
+ open_capture_devices--;
|
|
|
+ } else {
|
|
|
+ open_playback_devices--;
|
|
|
+ }
|
|
|
+ update_audio_session();
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -544,7 +571,6 @@ prepare_audiounit(_THIS, void *handle, int iscapture,
|
|
|
|
|
|
this->hidden->audioUnitOpened = 1;
|
|
|
|
|
|
-#if MACOSX_COREAUDIO
|
|
|
if (iscapture) { /* have to do EnableIO only for capture devices. */
|
|
|
UInt32 enable = 1;
|
|
|
result = AudioUnitSetProperty(this->hidden->audioUnit,
|
|
@@ -563,6 +589,7 @@ prepare_audiounit(_THIS, void *handle, int iscapture,
|
|
|
("AudioUnitSetProperty (kAudioOutputUnitProperty_EnableIO output bus)");
|
|
|
}
|
|
|
|
|
|
+#if MACOSX_COREAUDIO
|
|
|
/* this is always on the output_bus, even for capture devices. */
|
|
|
result = AudioUnitSetProperty(this->hidden->audioUnit,
|
|
|
kAudioOutputUnitProperty_CurrentDevice,
|
|
@@ -581,14 +608,13 @@ prepare_audiounit(_THIS, void *handle, int iscapture,
|
|
|
strdesc, sizeof (*strdesc));
|
|
|
CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_StreamFormat)");
|
|
|
|
|
|
-#if MACOSX_COREAUDIO
|
|
|
if (iscapture) { /* only need to do this for capture devices. */
|
|
|
void *ptr;
|
|
|
UInt32 framesize = 0;
|
|
|
UInt32 propsize = sizeof (UInt32);
|
|
|
|
|
|
result = AudioUnitGetProperty(this->hidden->audioUnit,
|
|
|
- kAudioDevicePropertyBufferFrameSize,
|
|
|
+ kAudioUnitProperty_MaximumFramesPerSlice,
|
|
|
kAudioUnitScope_Global, output_bus,
|
|
|
&framesize, &propsize);
|
|
|
CHECK_RESULT
|
|
@@ -601,13 +627,11 @@ prepare_audiounit(_THIS, void *handle, int iscapture,
|
|
|
SDL_OutOfMemory();
|
|
|
return 0;
|
|
|
}
|
|
|
-
|
|
|
this->hidden->captureBufferList.mNumberBuffers = 1;
|
|
|
this->hidden->captureBufferList.mBuffers[0].mNumberChannels = this->spec.channels;
|
|
|
this->hidden->captureBufferList.mBuffers[0].mDataByteSize = framesize;
|
|
|
this->hidden->captureBufferList.mBuffers[0].mData = ptr;
|
|
|
}
|
|
|
-#endif
|
|
|
|
|
|
/* Set the audio callback */
|
|
|
SDL_zero(callback);
|
|
@@ -616,7 +640,9 @@ prepare_audiounit(_THIS, void *handle, int iscapture,
|
|
|
|
|
|
result = AudioUnitSetProperty(this->hidden->audioUnit,
|
|
|
iscapture ? kAudioOutputUnitProperty_SetInputCallback : kAudioUnitProperty_SetRenderCallback,
|
|
|
- kAudioUnitScope_Global, output_bus, &callback, sizeof(callback));
|
|
|
+ kAudioUnitScope_Global,
|
|
|
+ iscapture ? input_bus : output_bus,
|
|
|
+ &callback, sizeof (callback));
|
|
|
CHECK_RESULT
|
|
|
("AudioUnitSetProperty (kAudioUnitProperty_SetRenderCallback)");
|
|
|
|
|
@@ -668,6 +694,13 @@ COREAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
|
|
}
|
|
|
SDL_zerop(this->hidden);
|
|
|
|
|
|
+ if (iscapture) {
|
|
|
+ open_capture_devices++;
|
|
|
+ } else {
|
|
|
+ open_playback_devices++;
|
|
|
+ }
|
|
|
+ update_audio_session();
|
|
|
+
|
|
|
/* Setup a AudioStreamBasicDescription with the requested format */
|
|
|
SDL_zero(strdesc);
|
|
|
strdesc.mFormatID = kAudioFormatLinearPCM;
|
|
@@ -742,20 +775,22 @@ COREAUDIO_Init(SDL_AudioDriverImpl * impl)
|
|
|
#if MACOSX_COREAUDIO
|
|
|
impl->DetectDevices = COREAUDIO_DetectDevices;
|
|
|
AudioObjectAddPropertyListener(kAudioObjectSystemObject, &devlist_address, device_list_changed, NULL);
|
|
|
- impl->HasCaptureSupport = 1;
|
|
|
#else
|
|
|
impl->OnlyHasDefaultOutputDevice = 1;
|
|
|
+ impl->OnlyHasDefaultInputDevice = 1;
|
|
|
|
|
|
/* Set category to ambient sound so that other music continues playing.
|
|
|
You can change this at runtime in your own code if you need different
|
|
|
behavior. If this is common, we can add an SDL hint for this.
|
|
|
*/
|
|
|
+ /* !!! FIXME: move this to AVAudioSession. This is deprecated, and the new version is available as of (ancient!) iOS 3.0 */
|
|
|
AudioSessionInitialize(NULL, NULL, NULL, nil);
|
|
|
UInt32 category = kAudioSessionCategory_AmbientSound;
|
|
|
AudioSessionSetProperty(kAudioSessionProperty_AudioCategory, sizeof(UInt32), &category);
|
|
|
#endif
|
|
|
|
|
|
impl->ProvidesOwnCallbackThread = 1;
|
|
|
+ impl->HasCaptureSupport = 1;
|
|
|
|
|
|
return 1; /* this audio target is available. */
|
|
|
}
|