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