Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qcoreaudiosessionmanager.mm
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies).
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <QtMultimedia/private/qcoreaudiosessionmanager_p.h>
5
6#import <AVFoundation/AVAudioSession.h>
7#import <Foundation/Foundation.h>
8
9QT_USE_NAMESPACE
10
11@interface CoreAudioSessionObserver : NSObject
12{
13 CoreAudioSessionManager *m_sessionManager;
14 AVAudioSession *m_audioSession;
15}
16
17@property (readonly, getter=sessionManager) CoreAudioSessionManager *m_sessionManager;
18@property (readonly, getter=audioSession) AVAudioSession *m_audioSession;
19
20-(CoreAudioSessionObserver *)initWithAudioSessionManager:(CoreAudioSessionManager *)sessionManager;
21
22-(BOOL)activateAudio;
23-(BOOL)deactivateAudio;
24
25//Notification handlers
26-(void)audioSessionInterruption:(NSNotification *)notification;
27-(void)audioSessionRouteChange:(NSNotification *)notification;
28-(void)audioSessionMediaServicesWereReset:(NSNotification *)notification;
29
30@end //interface CoreAudioSessionObserver
31
32@implementation CoreAudioSessionObserver
33
34@synthesize m_sessionManager, m_audioSession;
35
36-(CoreAudioSessionObserver *)initWithAudioSessionManager:(CoreAudioSessionManager *)sessionManager
37{
38 if (!(self = [super init]))
39 return nil;
40
41 self->m_sessionManager = sessionManager;
42 self->m_audioSession = [AVAudioSession sharedInstance];
43
44 //Set up observers
45 [[NSNotificationCenter defaultCenter] addObserver:self
46 selector:@selector(audioSessionInterruption:)
47 name:AVAudioSessionInterruptionNotification
48 object:self->m_audioSession];
49 [[NSNotificationCenter defaultCenter] addObserver:self
50 selector:@selector(audioSessionMediaServicesWereReset:)
51 name:AVAudioSessionMediaServicesWereResetNotification
52 object:self->m_audioSession];
53 [[NSNotificationCenter defaultCenter] addObserver:self
54 selector:@selector(audioSessionRouteChange:)
55 name:AVAudioSessionRouteChangeNotification
56 object:self->m_audioSession];
57
58 return self;
59}
60
61-(void)dealloc
62{
63#ifdef QT_DEBUG_COREAUDIO
64 qDebug() << Q_FUNC_INFO;
65#endif
66
67 [[NSNotificationCenter defaultCenter] removeObserver:self
68 name:AVAudioSessionInterruptionNotification
69 object:self->m_audioSession];
70 [[NSNotificationCenter defaultCenter] removeObserver:self
71 name:AVAudioSessionMediaServicesWereResetNotification
72 object:self->m_audioSession];
73 [[NSNotificationCenter defaultCenter] removeObserver:self
74 name:AVAudioSessionRouteChangeNotification
75 object:self->m_audioSession];
76
77 [super dealloc];
78}
79
80-(BOOL)activateAudio
81{
82 NSError *error = nil;
83 BOOL success = [self->m_audioSession setActive:YES error:&error];
84 if (![self->m_audioSession setActive:YES error:&error]) {
85#ifdef QT_DEBUG_COREAUDIO
86 qDebug("audio session activation failed: %s", [[error localizedDescription] UTF8String]);
87 } else {
88 qDebug("audio session activated");
89#endif
90 }
91
92 return success;
93}
94
95-(BOOL)deactivateAudio
96{
97 NSError *error = nil;
98 BOOL success = [m_audioSession setActive:NO error:&error];
99#ifdef QT_DEBUG_COREAUDIO
100 if (!success) {
101 qDebug("%s", [[error localizedDescription] UTF8String]);
102 }
103#endif
104 return success;
105}
106
107-(void)audioSessionInterruption:(NSNotification *)notification
108{
109 NSNumber *type = [[notification userInfo] valueForKey:AVAudioSessionInterruptionTypeKey];
110 if ([type intValue] == AVAudioSessionInterruptionTypeBegan) {
111#ifdef QT_DEBUG_COREAUDIO
112 qDebug("audioSession Interuption begain");
113#endif
114 } else if ([type intValue] == AVAudioSessionInterruptionTypeEnded) {
115#ifdef QT_DEBUG_COREAUDIO
116 qDebug("audioSession Interuption ended");
117#endif
118 NSNumber *option = [[notification userInfo] valueForKey:AVAudioSessionInterruptionOptionKey];
119 if ([option intValue] == AVAudioSessionInterruptionOptionShouldResume) {
120#ifdef QT_DEBUG_COREAUDIO
121 qDebug("audioSession is active and immediately ready to be used.");
122#endif
123 } else {
124 [self activateAudio];
125 }
126 }
127}
128
129-(void)audioSessionMediaServicesWereReset:(NSNotification *)notification
130{
131 Q_UNUSED(notification);
132#ifdef QT_DEBUG_COREAUDIO
133 qDebug("audioSession Media Services were reset");
134#endif
135 //Reactivate audio when this occurs
136 [self activateAudio];
137}
138
139-(void)audioSessionRouteChange:(NSNotification *)notification
140{
141 NSNumber *reason = [[notification userInfo] valueForKey:AVAudioSessionRouteChangeReasonKey];
142 NSUInteger reasonEnum = [reason intValue];
143
144 if (reasonEnum == AVAudioSessionRouteChangeReasonUnknown) {
145#ifdef QT_DEBUG_COREAUDIO
146 qDebug("audioSession route changed. reason: unknown");
147#endif
148 } else if (reasonEnum == AVAudioSessionRouteChangeReasonNewDeviceAvailable) {
149#ifdef QT_DEBUG_COREAUDIO
150 qDebug("audioSession route changed. reason: new device available");
151#endif
152 } else if (reasonEnum == AVAudioSessionRouteChangeReasonOldDeviceUnavailable) {
153#ifdef QT_DEBUG_COREAUDIO
154 qDebug("audioSession route changed. reason: old device unavailable");
155#endif
156 } else if (reasonEnum == AVAudioSessionRouteChangeReasonCategoryChange) {
157#ifdef QT_DEBUG_COREAUDIO
158 qDebug("audioSession route changed. reason: category changed");
159#endif
160 } else if (reasonEnum == AVAudioSessionRouteChangeReasonOverride) {
161#ifdef QT_DEBUG_COREAUDIO
162 qDebug("audioSession route changed. reason: override");
163#endif
164 } else if (reasonEnum == AVAudioSessionRouteChangeReasonWakeFromSleep) {
165#ifdef QT_DEBUG_COREAUDIO
166 qDebug("audioSession route changed. reason: woken from sleep");
167#endif
168 } else if (reasonEnum == AVAudioSessionRouteChangeReasonNoSuitableRouteForCategory) {
169#ifdef QT_DEBUG_COREAUDIO
170 qDebug("audioSession route changed. reason: no suitable route for category");
171#endif
172 }
173
174 m_sessionManager->devicesAvailableChanged();
175}
176
177@end //implementation CoreAudioSessionObserver
178
179CoreAudioSessionManager::CoreAudioSessionManager() :
180 QObject(0)
181{
182 m_sessionObserver = [[CoreAudioSessionObserver alloc] initWithAudioSessionManager:this];
183}
184
185CoreAudioSessionManager::~CoreAudioSessionManager()
186{
187#ifdef QT_DEBUG_COREAUDIO
188 qDebug() << Q_FUNC_INFO;
189#endif
190 [m_sessionObserver release];
191}
192
193
194CoreAudioSessionManager &CoreAudioSessionManager::instance()
195{
196 static CoreAudioSessionManager instance;
197 return instance;
198}
199
200bool CoreAudioSessionManager::setActive(bool active)
201{
202 if (active) {
203 return [m_sessionObserver activateAudio];
204 } else {
205 return [m_sessionObserver deactivateAudio];
206 }
207}
208
209bool CoreAudioSessionManager::setCategory(CoreAudioSessionManager::AudioSessionCategorys category, CoreAudioSessionManager::AudioSessionCategoryOptions options)
210{
211 NSString *targetCategory = nil;
212
213 switch (category) {
214 case CoreAudioSessionManager::Ambient:
215 targetCategory = AVAudioSessionCategoryAmbient;
216 break;
217 case CoreAudioSessionManager::SoloAmbient:
218 targetCategory = AVAudioSessionCategorySoloAmbient;
219 break;
220 case CoreAudioSessionManager::Playback:
221 targetCategory = AVAudioSessionCategoryPlayback;
222 break;
223 case CoreAudioSessionManager::Record:
224 targetCategory = AVAudioSessionCategoryRecord;
225 break;
226 case CoreAudioSessionManager::PlayAndRecord:
227 targetCategory = AVAudioSessionCategoryPlayAndRecord;
228 break;
229 case CoreAudioSessionManager::MultiRoute:
230 targetCategory = AVAudioSessionCategoryMultiRoute;
231 break;
232 }
233
234 if (targetCategory == nil)
235 return false;
236
237 return [[m_sessionObserver audioSession] setCategory:targetCategory
238 withOptions:(AVAudioSessionCategoryOptions)options
239 error:nil];
240}
241
242bool CoreAudioSessionManager::setMode(CoreAudioSessionManager::AudioSessionModes mode)
243{
244 NSString *targetMode = nil;
245 switch (mode) {
246 case CoreAudioSessionManager::Default:
247 targetMode = AVAudioSessionModeDefault;
248 break;
249 case CoreAudioSessionManager::VoiceChat:
250 targetMode = AVAudioSessionModeVoiceChat;
251 break;
252 case CoreAudioSessionManager::GameChat:
253 targetMode = AVAudioSessionModeGameChat;
254 break;
255 case CoreAudioSessionManager::VideoRecording:
256 targetMode = AVAudioSessionModeVideoRecording;
257 break;
258 case CoreAudioSessionManager::Measurement:
259 targetMode = AVAudioSessionModeMeasurement;
260 break;
261 case CoreAudioSessionManager::MoviePlayback:
262 targetMode = AVAudioSessionModeMoviePlayback;
263 break;
264 }
265
266 if (targetMode == nil)
267 return false;
268
269 return [[m_sessionObserver audioSession] setMode:targetMode error:nil];
270
271}
272
273CoreAudioSessionManager::AudioSessionCategorys CoreAudioSessionManager::category()
274{
275 NSString *category = [[m_sessionObserver audioSession] category];
276 AudioSessionCategorys localCategory = Ambient;
277
278 if (category == AVAudioSessionCategoryAmbient) {
279 localCategory = Ambient;
280 } else if (category == AVAudioSessionCategorySoloAmbient) {
281 localCategory = SoloAmbient;
282 } else if (category == AVAudioSessionCategoryPlayback) {
283 localCategory = Playback;
284 } else if (category == AVAudioSessionCategoryRecord) {
285 localCategory = Record;
286 } else if (category == AVAudioSessionCategoryPlayAndRecord) {
287 localCategory = PlayAndRecord;
288 } else if (category == AVAudioSessionCategoryMultiRoute) {
289 localCategory = MultiRoute;
290 }
291
292 return localCategory;
293}
294
295CoreAudioSessionManager::AudioSessionModes CoreAudioSessionManager::mode()
296{
297 NSString *mode = [[m_sessionObserver audioSession] mode];
298 AudioSessionModes localMode = Default;
299
300 if (mode == AVAudioSessionModeDefault) {
301 localMode = Default;
302 } else if (mode == AVAudioSessionModeVoiceChat) {
303 localMode = VoiceChat;
304 } else if (mode == AVAudioSessionModeGameChat) {
305 localMode = GameChat;
306 } else if (mode == AVAudioSessionModeVideoRecording) {
307 localMode = VideoRecording;
308 } else if (mode == AVAudioSessionModeMeasurement) {
309 localMode = Measurement;
310 } else if (mode == AVAudioSessionModeMoviePlayback) {
311 localMode = MoviePlayback;
312 }
313
314 return localMode;
315}
316
317QList<QByteArray> CoreAudioSessionManager::inputDevices()
318{
319 //TODO: Add support for USB input devices
320 //Right now the default behavior on iOS is to have only one input route
321 //at a time.
322 QList<QByteArray> inputDevices;
323 inputDevices << "default";
324 return inputDevices;
325}
326
327QList<QByteArray> CoreAudioSessionManager::outputDevices()
328{
329 //TODO: Add support for USB output devices
330 //Right now the default behavior on iOS is to have only one output route
331 //at a time.
332 QList<QByteArray> outputDevices;
333 outputDevices << "default";
334 return outputDevices;
335}
336
337float CoreAudioSessionManager::currentIOBufferDuration()
338{
339 return [[m_sessionObserver audioSession] IOBufferDuration];
340}
341
342float CoreAudioSessionManager::preferredSampleRate()
343{
344 return [[m_sessionObserver audioSession] preferredSampleRate];
345}
346
347#ifdef QT_DEBUG_COREAUDIO
348QDebug operator<<(QDebug dbg, CoreAudioSessionManager::AudioSessionCategorys category)
349{
350 QDebug output = dbg.nospace();
351 switch (category) {
352 case CoreAudioSessionManager::Ambient:
353 output << "AudioSessionCategoryAmbient";
354 break;
355 case CoreAudioSessionManager::SoloAmbient:
356 output << "AudioSessionCategorySoloAmbient";
357 break;
358 case CoreAudioSessionManager::Playback:
359 output << "AudioSessionCategoryPlayback";
360 break;
361 case CoreAudioSessionManager::Record:
362 output << "AudioSessionCategoryRecord";
363 break;
364 case CoreAudioSessionManager::PlayAndRecord:
365 output << "AudioSessionCategoryPlayAndRecord";
366 break;
367 case CoreAudioSessionManager::MultiRoute:
368 output << "AudioSessionCategoryMultiRoute";
369 break;
370 }
371 return output;
372}
373
374QDebug operator<<(QDebug dbg, CoreAudioSessionManager::AudioSessionCategoryOptions option)
375{
376 QDebug output = dbg.nospace();
377 switch (option) {
378 case CoreAudioSessionManager::None:
379 output << "AudioSessionCategoryOptionNone";
380 break;
381 case CoreAudioSessionManager::MixWithOthers:
382 output << "AudioSessionCategoryOptionMixWithOthers";
383 break;
384 case CoreAudioSessionManager::DuckOthers:
385 output << "AudioSessionCategoryOptionDuckOthers";
386 break;
387 case CoreAudioSessionManager::AllowBluetooth:
388 output << "AudioSessionCategoryOptionAllowBluetooth";
389 break;
390 case CoreAudioSessionManager::DefaultToSpeaker:
391 output << "AudioSessionCategoryOptionDefaultToSpeaker";
392 break;
393 }
394 return output;
395}
396
397QDebug operator<<(QDebug dbg, CoreAudioSessionManager::AudioSessionModes mode)
398{
399 QDebug output = dbg.nospace();
400 switch (mode) {
401 case CoreAudioSessionManager::Default:
402 output << "AudioSessionModeDefault";
403 break;
404 case CoreAudioSessionManager::VoiceChat:
405 output << "AudioSessionModeVoiceChat";
406 break;
407 case CoreAudioSessionManager::GameChat:
408 output << "AudioSessionModeGameChat";
409 break;
410 case CoreAudioSessionManager::VideoRecording:
411 output << "AudioSessionModeVideoRecording";
412 break;
413 case CoreAudioSessionManager::Measurement:
414 output << "AudioSessionModeMeasurement";
415 break;
416 case CoreAudioSessionManager::MoviePlayback:
417 output << "AudioSessionModeMoviePlayback";
418 break;
419 }
420 return output;
421}
422#endif
423
424#include "moc_qcoreaudiosessionmanager_p.cpp"