diff options
Diffstat (limited to 'src/multimedia/darwin/qcoreaudiosessionmanager.mm')
-rw-r--r-- | src/multimedia/darwin/qcoreaudiosessionmanager.mm | 437 |
1 files changed, 437 insertions, 0 deletions
diff --git a/src/multimedia/darwin/qcoreaudiosessionmanager.mm b/src/multimedia/darwin/qcoreaudiosessionmanager.mm new file mode 100644 index 000000000..cee955905 --- /dev/null +++ b/src/multimedia/darwin/qcoreaudiosessionmanager.mm @@ -0,0 +1,437 @@ +// Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qcoreaudiosessionmanager_p.h" +#import <AVFoundation/AVAudioSession.h> +#import <Foundation/Foundation.h> + +QT_BEGIN_NAMESPACE + +@interface CoreAudioSessionObserver : NSObject +{ + CoreAudioSessionManager *m_sessionManager; + AVAudioSession *m_audioSession; +} + +@property (readonly, getter=sessionManager) CoreAudioSessionManager *m_sessionManager; +@property (readonly, getter=audioSession) AVAudioSession *m_audioSession; + +-(CoreAudioSessionObserver *)initWithAudioSessionManager:(CoreAudioSessionManager *)sessionManager; + +-(BOOL)activateAudio; +-(BOOL)deactivateAudio; + +//Notification handlers +-(void)audioSessionInterruption:(NSNotification *)notification; +-(void)audioSessionRouteChange:(NSNotification *)notification; +-(void)audioSessionMediaServicesWereReset:(NSNotification *)notification; + +@end //interface CoreAudioSessionObserver + +@implementation CoreAudioSessionObserver + +@synthesize m_sessionManager, m_audioSession; + +-(CoreAudioSessionObserver *)initWithAudioSessionManager:(CoreAudioSessionManager *)sessionManager +{ + if (!(self = [super init])) + return nil; + + self->m_sessionManager = sessionManager; + self->m_audioSession = [AVAudioSession sharedInstance]; + + //Set up observers + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(audioSessionInterruption:) + name:AVAudioSessionInterruptionNotification + object:self->m_audioSession]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(audioSessionMediaServicesWereReset:) + name:AVAudioSessionMediaServicesWereResetNotification + object:self->m_audioSession]; + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(audioSessionRouteChange:) + name:AVAudioSessionRouteChangeNotification + object:self->m_audioSession]; + + return self; +} + +-(void)dealloc +{ +#ifdef QT_DEBUG_COREAUDIO + qDebug() << Q_FUNC_INFO; +#endif + + [[NSNotificationCenter defaultCenter] removeObserver:self + name:AVAudioSessionInterruptionNotification + object:self->m_audioSession]; + [[NSNotificationCenter defaultCenter] removeObserver:self + name:AVAudioSessionMediaServicesWereResetNotification + object:self->m_audioSession]; + [[NSNotificationCenter defaultCenter] removeObserver:self + name:AVAudioSessionRouteChangeNotification + object:self->m_audioSession]; + + [super dealloc]; +} + +-(BOOL)activateAudio +{ + NSError *error = nil; + BOOL success = [self->m_audioSession setActive:YES error:&error]; + if (![self->m_audioSession setActive:YES error:&error]) { +#ifdef QT_DEBUG_COREAUDIO + qDebug("audio session activation failed: %s", [[error localizedDescription] UTF8String]); + } else { + qDebug("audio session activated"); +#endif + } + + return success; +} + +-(BOOL)deactivateAudio +{ + NSError *error = nil; + BOOL success = [m_audioSession setActive:NO error:&error]; +#ifdef QT_DEBUG_COREAUDIO + if (!success) { + qDebug("%s", [[error localizedDescription] UTF8String]); + } +#endif + return success; +} + +-(void)audioSessionInterruption:(NSNotification *)notification +{ + NSNumber *type = [[notification userInfo] valueForKey:AVAudioSessionInterruptionTypeKey]; + if ([type intValue] == AVAudioSessionInterruptionTypeBegan) { +#ifdef QT_DEBUG_COREAUDIO + qDebug("audioSession Interuption begain"); +#endif + } else if ([type intValue] == AVAudioSessionInterruptionTypeEnded) { +#ifdef QT_DEBUG_COREAUDIO + qDebug("audioSession Interuption ended"); +#endif + NSNumber *option = [[notification userInfo] valueForKey:AVAudioSessionInterruptionOptionKey]; + if ([option intValue] == AVAudioSessionInterruptionOptionShouldResume) { +#ifdef QT_DEBUG_COREAUDIO + qDebug("audioSession is active and immediately ready to be used."); +#endif + } else { + [self activateAudio]; + } + } +} + +-(void)audioSessionMediaServicesWereReset:(NSNotification *)notification +{ + Q_UNUSED(notification); +#ifdef QT_DEBUG_COREAUDIO + qDebug("audioSession Media Services were reset"); +#endif + //Reactivate audio when this occurs + [self activateAudio]; +} + +-(void)audioSessionRouteChange:(NSNotification *)notification +{ + NSNumber *reason = [[notification userInfo] valueForKey:AVAudioSessionRouteChangeReasonKey]; + NSUInteger reasonEnum = [reason intValue]; + + if (reasonEnum == AVAudioSessionRouteChangeReasonUnknown) { +#ifdef QT_DEBUG_COREAUDIO + qDebug("audioSession route changed. reason: unknown"); +#endif + } else if (reasonEnum == AVAudioSessionRouteChangeReasonNewDeviceAvailable) { +#ifdef QT_DEBUG_COREAUDIO + qDebug("audioSession route changed. reason: new device available"); +#endif + } else if (reasonEnum == AVAudioSessionRouteChangeReasonOldDeviceUnavailable) { +#ifdef QT_DEBUG_COREAUDIO + qDebug("audioSession route changed. reason: old device unavailable"); +#endif + } else if (reasonEnum == AVAudioSessionRouteChangeReasonCategoryChange) { +#ifdef QT_DEBUG_COREAUDIO + qDebug("audioSession route changed. reason: category changed"); +#endif + } else if (reasonEnum == AVAudioSessionRouteChangeReasonOverride) { +#ifdef QT_DEBUG_COREAUDIO + qDebug("audioSession route changed. reason: override"); +#endif + } else if (reasonEnum == AVAudioSessionRouteChangeReasonWakeFromSleep) { +#ifdef QT_DEBUG_COREAUDIO + qDebug("audioSession route changed. reason: woken from sleep"); +#endif + } else if (reasonEnum == AVAudioSessionRouteChangeReasonNoSuitableRouteForCategory) { +#ifdef QT_DEBUG_COREAUDIO + qDebug("audioSession route changed. reason: no suitable route for category"); +#endif + } + + m_sessionManager->devicesAvailableChanged(); +} + +@end //implementation CoreAudioSessionObserver + +CoreAudioSessionManager::CoreAudioSessionManager() : + QObject(0) +{ + m_sessionObserver = [[CoreAudioSessionObserver alloc] initWithAudioSessionManager:this]; +} + +CoreAudioSessionManager::~CoreAudioSessionManager() +{ +#ifdef QT_DEBUG_COREAUDIO + qDebug() << Q_FUNC_INFO; +#endif + [m_sessionObserver release]; +} + + +CoreAudioSessionManager &CoreAudioSessionManager::instance() +{ + static CoreAudioSessionManager instance; + return instance; +} + +bool CoreAudioSessionManager::setActive(bool active) +{ + if (active) { + return [m_sessionObserver activateAudio]; + } else { + return [m_sessionObserver deactivateAudio]; + } +} + +bool CoreAudioSessionManager::setCategory(CoreAudioSessionManager::AudioSessionCategorys category, CoreAudioSessionManager::AudioSessionCategoryOptions options) +{ + NSString *targetCategory = nil; + + switch (category) { + case CoreAudioSessionManager::Ambient: + targetCategory = AVAudioSessionCategoryAmbient; + break; + case CoreAudioSessionManager::SoloAmbient: + targetCategory = AVAudioSessionCategorySoloAmbient; + break; + case CoreAudioSessionManager::Playback: + targetCategory = AVAudioSessionCategoryPlayback; + break; + case CoreAudioSessionManager::Record: + targetCategory = AVAudioSessionCategoryRecord; + break; + case CoreAudioSessionManager::PlayAndRecord: + targetCategory = AVAudioSessionCategoryPlayAndRecord; + break; + case CoreAudioSessionManager::AudioProcessing: +#ifndef Q_OS_TVOS + targetCategory = AVAudioSessionCategoryAudioProcessing; +#endif + break; + case CoreAudioSessionManager::MultiRoute: + targetCategory = AVAudioSessionCategoryMultiRoute; + break; + } + + if (targetCategory == nil) + return false; + + return [[m_sessionObserver audioSession] setCategory:targetCategory + withOptions:(AVAudioSessionCategoryOptions)options + error:nil]; +} + +bool CoreAudioSessionManager::setMode(CoreAudioSessionManager::AudioSessionModes mode) +{ + NSString *targetMode = nil; + switch (mode) { + case CoreAudioSessionManager::Default: + targetMode = AVAudioSessionModeDefault; + break; + case CoreAudioSessionManager::VoiceChat: + targetMode = AVAudioSessionModeVoiceChat; + break; + case CoreAudioSessionManager::GameChat: + targetMode = AVAudioSessionModeGameChat; + break; + case CoreAudioSessionManager::VideoRecording: + targetMode = AVAudioSessionModeVideoRecording; + break; + case CoreAudioSessionManager::Measurement: + targetMode = AVAudioSessionModeMeasurement; + break; + case CoreAudioSessionManager::MoviePlayback: + targetMode = AVAudioSessionModeMoviePlayback; + break; + } + + if (targetMode == nil) + return false; + + return [[m_sessionObserver audioSession] setMode:targetMode error:nil]; + +} + +CoreAudioSessionManager::AudioSessionCategorys CoreAudioSessionManager::category() +{ + NSString *category = [[m_sessionObserver audioSession] category]; + AudioSessionCategorys localCategory = Ambient; + + if (category == AVAudioSessionCategoryAmbient) { + localCategory = Ambient; + } else if (category == AVAudioSessionCategorySoloAmbient) { + localCategory = SoloAmbient; + } else if (category == AVAudioSessionCategoryPlayback) { + localCategory = Playback; + } else if (category == AVAudioSessionCategoryRecord) { + localCategory = Record; + } else if (category == AVAudioSessionCategoryPlayAndRecord) { + localCategory = PlayAndRecord; +#ifndef Q_OS_TVOS + } else if (category == AVAudioSessionCategoryAudioProcessing) { + localCategory = AudioProcessing; +#endif + } else if (category == AVAudioSessionCategoryMultiRoute) { + localCategory = MultiRoute; + } + + return localCategory; +} + +CoreAudioSessionManager::AudioSessionModes CoreAudioSessionManager::mode() +{ + NSString *mode = [[m_sessionObserver audioSession] mode]; + AudioSessionModes localMode = Default; + + if (mode == AVAudioSessionModeDefault) { + localMode = Default; + } else if (mode == AVAudioSessionModeVoiceChat) { + localMode = VoiceChat; + } else if (mode == AVAudioSessionModeGameChat) { + localMode = GameChat; + } else if (mode == AVAudioSessionModeVideoRecording) { + localMode = VideoRecording; + } else if (mode == AVAudioSessionModeMeasurement) { + localMode = Measurement; + } else if (mode == AVAudioSessionModeMoviePlayback) { + localMode = MoviePlayback; + } + + return localMode; +} + +QList<QByteArray> CoreAudioSessionManager::inputDevices() +{ + //TODO: Add support for USB input devices + //Right now the default behavior on iOS is to have only one input route + //at a time. + QList<QByteArray> inputDevices; + inputDevices << "default"; + return inputDevices; +} + +QList<QByteArray> CoreAudioSessionManager::outputDevices() +{ + //TODO: Add support for USB output devices + //Right now the default behavior on iOS is to have only one output route + //at a time. + QList<QByteArray> outputDevices; + outputDevices << "default"; + return outputDevices; +} + +float CoreAudioSessionManager::currentIOBufferDuration() +{ + return [[m_sessionObserver audioSession] IOBufferDuration]; +} + +float CoreAudioSessionManager::preferredSampleRate() +{ + return [[m_sessionObserver audioSession] preferredSampleRate]; +} + +#ifdef QT_DEBUG_COREAUDIO +QDebug operator<<(QDebug dbg, CoreAudioSessionManager::AudioSessionCategorys category) +{ + QDebug output = dbg.nospace(); + switch (category) { + case CoreAudioSessionManager::Ambient: + output << "AudioSessionCategoryAmbient"; + break; + case CoreAudioSessionManager::SoloAmbient: + output << "AudioSessionCategorySoloAmbient"; + break; + case CoreAudioSessionManager::Playback: + output << "AudioSessionCategoryPlayback"; + break; + case CoreAudioSessionManager::Record: + output << "AudioSessionCategoryRecord"; + break; + case CoreAudioSessionManager::PlayAndRecord: + output << "AudioSessionCategoryPlayAndRecord"; + break; + case CoreAudioSessionManager::AudioProcessing: + output << "AudioSessionCategoryAudioProcessing"; + break; + case CoreAudioSessionManager::MultiRoute: + output << "AudioSessionCategoryMultiRoute"; + break; + } + return output; +} + +QDebug operator<<(QDebug dbg, CoreAudioSessionManager::AudioSessionCategoryOptions option) +{ + QDebug output = dbg.nospace(); + switch (option) { + case CoreAudioSessionManager::None: + output << "AudioSessionCategoryOptionNone"; + break; + case CoreAudioSessionManager::MixWithOthers: + output << "AudioSessionCategoryOptionMixWithOthers"; + break; + case CoreAudioSessionManager::DuckOthers: + output << "AudioSessionCategoryOptionDuckOthers"; + break; + case CoreAudioSessionManager::AllowBluetooth: + output << "AudioSessionCategoryOptionAllowBluetooth"; + break; + case CoreAudioSessionManager::DefaultToSpeaker: + output << "AudioSessionCategoryOptionDefaultToSpeaker"; + break; + } + return output; +} + +QDebug operator<<(QDebug dbg, CoreAudioSessionManager::AudioSessionModes mode) +{ + QDebug output = dbg.nospace(); + switch (mode) { + case CoreAudioSessionManager::Default: + output << "AudioSessionModeDefault"; + break; + case CoreAudioSessionManager::VoiceChat: + output << "AudioSessionModeVoiceChat"; + break; + case CoreAudioSessionManager::GameChat: + output << "AudioSessionModeGameChat"; + break; + case CoreAudioSessionManager::VideoRecording: + output << "AudioSessionModeVideoRecording"; + break; + case CoreAudioSessionManager::Measurement: + output << "AudioSessionModeMeasurement"; + break; + case CoreAudioSessionManager::MoviePlayback: + output << "AudioSessionModeMoviePlayback"; + break; + } + return output; +} +#endif + +QT_END_NAMESPACE + +#include "moc_qcoreaudiosessionmanager_p.cpp" |