mirror of https://github.com/encounter/SDL.git
Fixed Bluetooth audio output on Apple TV
This commit is contained in:
parent
cced5eb937
commit
ff53521bc6
|
@ -291,34 +291,34 @@ static BOOL session_active = NO;
|
||||||
|
|
||||||
static void pause_audio_devices()
|
static void pause_audio_devices()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!open_devices) {
|
if (!open_devices) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < num_open_devices; ++i) {
|
for (i = 0; i < num_open_devices; ++i) {
|
||||||
SDL_AudioDevice *device = open_devices[i];
|
SDL_AudioDevice *device = open_devices[i];
|
||||||
if (device->hidden->audioQueue && !device->hidden->interrupted) {
|
if (device->hidden->audioQueue && !device->hidden->interrupted) {
|
||||||
AudioQueuePause(device->hidden->audioQueue);
|
AudioQueuePause(device->hidden->audioQueue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void resume_audio_devices()
|
static void resume_audio_devices()
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!open_devices) {
|
if (!open_devices) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < num_open_devices; ++i) {
|
for (i = 0; i < num_open_devices; ++i) {
|
||||||
SDL_AudioDevice *device = open_devices[i];
|
SDL_AudioDevice *device = open_devices[i];
|
||||||
if (device->hidden->audioQueue && !device->hidden->interrupted) {
|
if (device->hidden->audioQueue && !device->hidden->interrupted) {
|
||||||
AudioQueueStart(device->hidden->audioQueue, NULL);
|
AudioQueueStart(device->hidden->audioQueue, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void interruption_begin(_THIS)
|
static void interruption_begin(_THIS)
|
||||||
|
@ -406,26 +406,29 @@ static BOOL update_audio_session(_THIS, SDL_bool open, SDL_bool allow_playandrec
|
||||||
if (category == AVAudioSessionCategoryPlayAndRecord) {
|
if (category == AVAudioSessionCategoryPlayAndRecord) {
|
||||||
options |= AVAudioSessionCategoryOptionDefaultToSpeaker;
|
options |= AVAudioSessionCategoryOptionDefaultToSpeaker;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (category == AVAudioSessionCategoryRecord ||
|
if (category == AVAudioSessionCategoryRecord ||
|
||||||
category == AVAudioSessionCategoryPlayAndRecord) {
|
category == AVAudioSessionCategoryPlayAndRecord) {
|
||||||
options |= AVAudioSessionCategoryOptionAllowBluetooth;
|
/* AVAudioSessionCategoryOptionAllowBluetooth isn't available in the SDK for
|
||||||
|
Apple TV but is still needed in order to output to Bluetooth devices.
|
||||||
|
*/
|
||||||
|
options |= 0x4; /* AVAudioSessionCategoryOptionAllowBluetooth; */
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (category == AVAudioSessionCategoryPlayAndRecord) {
|
if (category == AVAudioSessionCategoryPlayAndRecord) {
|
||||||
options |= AVAudioSessionCategoryOptionAllowBluetoothA2DP |
|
options |= AVAudioSessionCategoryOptionAllowBluetoothA2DP |
|
||||||
AVAudioSessionCategoryOptionAllowAirPlay;
|
AVAudioSessionCategoryOptionAllowAirPlay;
|
||||||
}
|
}
|
||||||
if (category == AVAudioSessionCategoryPlayback ||
|
if (category == AVAudioSessionCategoryPlayback ||
|
||||||
category == AVAudioSessionCategoryPlayAndRecord) {
|
category == AVAudioSessionCategoryPlayAndRecord) {
|
||||||
options |= AVAudioSessionCategoryOptionDuckOthers;
|
options |= AVAudioSessionCategoryOptionDuckOthers;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ([session respondsToSelector:@selector(setCategory:mode:options:error:)]) {
|
if ([session respondsToSelector:@selector(setCategory:mode:options:error:)]) {
|
||||||
if (![session.category isEqualToString:category] || session.categoryOptions != options) {
|
if (![session.category isEqualToString:category] || session.categoryOptions != options) {
|
||||||
/* Stop the current session so we don't interrupt other application audio */
|
/* Stop the current session so we don't interrupt other application audio */
|
||||||
pause_audio_devices();
|
pause_audio_devices();
|
||||||
[session setActive:NO error:nil];
|
[session setActive:NO error:nil];
|
||||||
session_active = NO;
|
session_active = NO;
|
||||||
|
|
||||||
if (![session setCategory:category mode:mode options:options error:&err]) {
|
if (![session setCategory:category mode:mode options:options error:&err]) {
|
||||||
NSString *desc = err.description;
|
NSString *desc = err.description;
|
||||||
|
@ -435,10 +438,10 @@ static BOOL update_audio_session(_THIS, SDL_bool open, SDL_bool allow_playandrec
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (![session.category isEqualToString:category]) {
|
if (![session.category isEqualToString:category]) {
|
||||||
/* Stop the current session so we don't interrupt other application audio */
|
/* Stop the current session so we don't interrupt other application audio */
|
||||||
pause_audio_devices();
|
pause_audio_devices();
|
||||||
[session setActive:NO error:nil];
|
[session setActive:NO error:nil];
|
||||||
session_active = NO;
|
session_active = NO;
|
||||||
|
|
||||||
if (![session setCategory:category error:&err]) {
|
if (![session setCategory:category error:&err]) {
|
||||||
NSString *desc = err.description;
|
NSString *desc = err.description;
|
||||||
|
@ -459,12 +462,12 @@ static BOOL update_audio_session(_THIS, SDL_bool open, SDL_bool allow_playandrec
|
||||||
SDL_SetError("Could not activate Audio Session: %s", desc.UTF8String);
|
SDL_SetError("Could not activate Audio Session: %s", desc.UTF8String);
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
session_active = YES;
|
session_active = YES;
|
||||||
resume_audio_devices();
|
resume_audio_devices();
|
||||||
} else if (!open_playback_devices && !open_capture_devices && session_active) {
|
} else if (!open_playback_devices && !open_capture_devices && session_active) {
|
||||||
pause_audio_devices();
|
pause_audio_devices();
|
||||||
[session setActive:NO error:nil];
|
[session setActive:NO error:nil];
|
||||||
session_active = NO;
|
session_active = NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (open) {
|
if (open) {
|
||||||
|
@ -492,12 +495,12 @@ static BOOL update_audio_session(_THIS, SDL_bool open, SDL_bool allow_playandrec
|
||||||
|
|
||||||
this->hidden->interruption_listener = CFBridgingRetain(listener);
|
this->hidden->interruption_listener = CFBridgingRetain(listener);
|
||||||
} else {
|
} else {
|
||||||
SDLInterruptionListener *listener = nil;
|
SDLInterruptionListener *listener = nil;
|
||||||
listener = (SDLInterruptionListener *) CFBridgingRelease(this->hidden->interruption_listener);
|
listener = (SDLInterruptionListener *) CFBridgingRelease(this->hidden->interruption_listener);
|
||||||
[center removeObserver:listener];
|
[center removeObserver:listener];
|
||||||
@synchronized (listener) {
|
@synchronized (listener) {
|
||||||
listener.device = NULL;
|
listener.device = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -671,7 +674,7 @@ static void
|
||||||
COREAUDIO_CloseDevice(_THIS)
|
COREAUDIO_CloseDevice(_THIS)
|
||||||
{
|
{
|
||||||
const SDL_bool iscapture = this->iscapture;
|
const SDL_bool iscapture = this->iscapture;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* !!! FIXME: what does iOS do when a bluetooth audio device vanishes? Headphones unplugged? */
|
/* !!! FIXME: what does iOS do when a bluetooth audio device vanishes? Headphones unplugged? */
|
||||||
/* !!! FIXME: (we only do a "default" device on iOS right now...can we do more?) */
|
/* !!! FIXME: (we only do a "default" device on iOS right now...can we do more?) */
|
||||||
|
@ -691,19 +694,19 @@ COREAUDIO_CloseDevice(_THIS)
|
||||||
update_audio_session(this, SDL_FALSE, SDL_TRUE);
|
update_audio_session(this, SDL_FALSE, SDL_TRUE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (i = 0; i < num_open_devices; ++i) {
|
for (i = 0; i < num_open_devices; ++i) {
|
||||||
if (open_devices[i] == this) {
|
if (open_devices[i] == this) {
|
||||||
--num_open_devices;
|
--num_open_devices;
|
||||||
if (i < num_open_devices) {
|
if (i < num_open_devices) {
|
||||||
SDL_memmove(&open_devices[i], &open_devices[i+1], sizeof(open_devices[i])*(num_open_devices - i));
|
SDL_memmove(&open_devices[i], &open_devices[i+1], sizeof(open_devices[i])*(num_open_devices - i));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (num_open_devices == 0) {
|
if (num_open_devices == 0) {
|
||||||
SDL_free(open_devices);
|
SDL_free(open_devices);
|
||||||
open_devices = NULL;
|
open_devices = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if callback fires again, feed silence; don't call into the app. */
|
/* if callback fires again, feed silence; don't call into the app. */
|
||||||
SDL_AtomicSet(&this->paused, 1);
|
SDL_AtomicSet(&this->paused, 1);
|
||||||
|
@ -1009,7 +1012,7 @@ COREAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||||
AudioStreamBasicDescription *strdesc;
|
AudioStreamBasicDescription *strdesc;
|
||||||
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
|
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
|
||||||
int valid_datatype = 0;
|
int valid_datatype = 0;
|
||||||
SDL_AudioDevice **new_open_devices;
|
SDL_AudioDevice **new_open_devices;
|
||||||
|
|
||||||
/* Initialize all variables that we clean on shutdown */
|
/* Initialize all variables that we clean on shutdown */
|
||||||
this->hidden = (struct SDL_PrivateAudioData *)
|
this->hidden = (struct SDL_PrivateAudioData *)
|
||||||
|
@ -1027,11 +1030,11 @@ COREAUDIO_OpenDevice(_THIS, void *handle, const char *devname, int iscapture)
|
||||||
open_playback_devices++;
|
open_playback_devices++;
|
||||||
}
|
}
|
||||||
|
|
||||||
new_open_devices = (SDL_AudioDevice **)SDL_realloc(open_devices, sizeof(open_devices[0]) * (num_open_devices + 1));
|
new_open_devices = (SDL_AudioDevice **)SDL_realloc(open_devices, sizeof(open_devices[0]) * (num_open_devices + 1));
|
||||||
if (new_open_devices) {
|
if (new_open_devices) {
|
||||||
open_devices = new_open_devices;
|
open_devices = new_open_devices;
|
||||||
open_devices[num_open_devices++] = this;
|
open_devices[num_open_devices++] = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !MACOSX_COREAUDIO
|
#if !MACOSX_COREAUDIO
|
||||||
if (!update_audio_session(this, SDL_TRUE, SDL_TRUE)) {
|
if (!update_audio_session(this, SDL_TRUE, SDL_TRUE)) {
|
||||||
|
|
Loading…
Reference in New Issue