summaryrefslogtreecommitdiffstats
path: root/src/multimedia/darwin/qcoreaudiosessionmanager.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/multimedia/darwin/qcoreaudiosessionmanager.mm')
-rw-r--r--src/multimedia/darwin/qcoreaudiosessionmanager.mm437
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"