OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2016 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h" | 11 #import "webrtc/modules/audio_device/ios/objc/RTCAudioSession.h" |
12 | 12 |
13 #include "webrtc/base/checks.h" | 13 #include "webrtc/base/checks.h" |
14 | 14 |
15 #import "webrtc/base/objc/RTCLogging.h" | 15 #import "webrtc/base/objc/RTCLogging.h" |
16 #import "webrtc/modules/audio_device/ios/objc/RTCAudioSession+Private.h" | 16 #import "webrtc/modules/audio_device/ios/objc/RTCAudioSession+Private.h" |
17 | 17 |
18 NSString * const kRTCAudioSessionErrorDomain = @"org.webrtc.RTCAudioSession"; | 18 NSString * const kRTCAudioSessionErrorDomain = @"org.webrtc.RTCAudioSession"; |
19 NSInteger const kRTCAudioSessionErrorLockRequired = -1; | 19 NSInteger const kRTCAudioSessionErrorLockRequired = -1; |
20 | 20 |
21 // This class needs to be thread-safe because it is accessed from many threads. | 21 // This class needs to be thread-safe because it is accessed from many threads. |
22 // TODO(tkchin): Consider more granular locking. We're not expecting a lot of | 22 // TODO(tkchin): Consider more granular locking. We're not expecting a lot of |
23 // lock contention so coarse locks should be fine for now. | 23 // lock contention so coarse locks should be fine for now. |
24 @implementation RTCAudioSession { | 24 @implementation RTCAudioSession { |
25 AVAudioSession *_session; | 25 AVAudioSession *_session; |
26 NSHashTable *_delegates; | 26 NSHashTable *_delegates; |
27 NSInteger _activationCount; | 27 NSInteger _activationCount; |
28 BOOL _isActive; | 28 BOOL _isActive; |
29 BOOL _isLocked; | 29 BOOL _isLocked; |
| 30 BOOL _shouldDelayAudioConfiguration; |
30 } | 31 } |
31 | 32 |
32 @synthesize session = _session; | 33 @synthesize session = _session; |
33 @synthesize lock = _lock; | 34 @synthesize lock = _lock; |
34 | 35 |
35 + (instancetype)sharedInstance { | 36 + (instancetype)sharedInstance { |
36 static dispatch_once_t onceToken; | 37 static dispatch_once_t onceToken; |
37 static RTCAudioSession *sharedInstance = nil; | 38 static RTCAudioSession *sharedInstance = nil; |
38 dispatch_once(&onceToken, ^{ | 39 dispatch_once(&onceToken, ^{ |
39 sharedInstance = [[RTCAudioSession alloc] init]; | 40 sharedInstance = [[RTCAudioSession alloc] init]; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 return _isActive; | 84 return _isActive; |
84 } | 85 } |
85 } | 86 } |
86 | 87 |
87 - (BOOL)isLocked { | 88 - (BOOL)isLocked { |
88 @synchronized(self) { | 89 @synchronized(self) { |
89 return _isLocked; | 90 return _isLocked; |
90 } | 91 } |
91 } | 92 } |
92 | 93 |
| 94 - (void)setShouldDelayAudioConfiguration:(BOOL)shouldDelayAudioConfiguration { |
| 95 @synchronized(self) { |
| 96 if (_shouldDelayAudioConfiguration == shouldDelayAudioConfiguration) { |
| 97 return; |
| 98 } |
| 99 _shouldDelayAudioConfiguration = shouldDelayAudioConfiguration; |
| 100 } |
| 101 } |
| 102 |
| 103 - (BOOL)shouldDelayAudioConfiguration { |
| 104 @synchronized(self) { |
| 105 return _shouldDelayAudioConfiguration; |
| 106 } |
| 107 } |
| 108 |
93 - (void)addDelegate:(id<RTCAudioSessionDelegate>)delegate { | 109 - (void)addDelegate:(id<RTCAudioSessionDelegate>)delegate { |
94 @synchronized(self) { | 110 @synchronized(self) { |
95 [_delegates addObject:delegate]; | 111 [_delegates addObject:delegate]; |
96 } | 112 } |
97 } | 113 } |
98 | 114 |
99 - (void)removeDelegate:(id<RTCAudioSessionDelegate>)delegate { | 115 - (void)removeDelegate:(id<RTCAudioSessionDelegate>)delegate { |
100 @synchronized(self) { | 116 @synchronized(self) { |
101 [_delegates removeObject:delegate]; | 117 [_delegates removeObject:delegate]; |
102 } | 118 } |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 } | 259 } |
244 } | 260 } |
245 if (success) { | 261 if (success) { |
246 if (shouldSetActive) { | 262 if (shouldSetActive) { |
247 self.isActive = active; | 263 self.isActive = active; |
248 } | 264 } |
249 if (active) { | 265 if (active) { |
250 [self incrementActivationCount]; | 266 [self incrementActivationCount]; |
251 } | 267 } |
252 } else { | 268 } else { |
253 RTCLogError(@"Failed to setActive:%d. Error: %@", active, error); | 269 RTCLogError(@"Failed to setActive:%d. Error: %@", |
| 270 active, error.localizedDescription); |
254 } | 271 } |
255 // Decrement activation count on deactivation whether or not it succeeded. | 272 // Decrement activation count on deactivation whether or not it succeeded. |
256 if (!active) { | 273 if (!active) { |
257 [self decrementActivationCount]; | 274 [self decrementActivationCount]; |
258 } | 275 } |
259 RTCLog(@"Number of current activations: %ld", (long)self.activationCount); | 276 RTCLog(@"Number of current activations: %ld", (long)self.activationCount); |
260 return success; | 277 return success; |
261 } | 278 } |
262 | 279 |
263 - (BOOL)setCategory:(NSString *)category | 280 - (BOOL)setCategory:(NSString *)category |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
434 NSLocalizedDescriptionKey: | 451 NSLocalizedDescriptionKey: |
435 @"Must call lockForConfiguration before calling this method." | 452 @"Must call lockForConfiguration before calling this method." |
436 }; | 453 }; |
437 NSError *error = | 454 NSError *error = |
438 [[NSError alloc] initWithDomain:kRTCAudioSessionErrorDomain | 455 [[NSError alloc] initWithDomain:kRTCAudioSessionErrorDomain |
439 code:kRTCAudioSessionErrorLockRequired | 456 code:kRTCAudioSessionErrorLockRequired |
440 userInfo:userInfo]; | 457 userInfo:userInfo]; |
441 return error; | 458 return error; |
442 } | 459 } |
443 | 460 |
444 - (BOOL)checkLock:(NSError **)outError { | |
445 // Check ivar instead of trying to acquire lock so that we won't accidentally | |
446 // acquire lock if it hasn't already been called. | |
447 if (!self.isLocked) { | |
448 if (outError) { | |
449 *outError = [RTCAudioSession lockError]; | |
450 } | |
451 return NO; | |
452 } | |
453 return YES; | |
454 } | |
455 | |
456 - (NSSet *)delegates { | 461 - (NSSet *)delegates { |
457 @synchronized(self) { | 462 @synchronized(self) { |
458 return _delegates.setRepresentation; | 463 return _delegates.setRepresentation; |
459 } | 464 } |
460 } | 465 } |
461 | 466 |
462 - (NSInteger)activationCount { | 467 - (NSInteger)activationCount { |
463 @synchronized(self) { | 468 @synchronized(self) { |
464 return _activationCount; | 469 return _activationCount; |
465 } | 470 } |
466 } | 471 } |
467 | 472 |
468 - (NSInteger)incrementActivationCount { | 473 - (NSInteger)incrementActivationCount { |
469 RTCLog(@"Incrementing activation count."); | 474 RTCLog(@"Incrementing activation count."); |
470 @synchronized(self) { | 475 @synchronized(self) { |
471 return ++_activationCount; | 476 return ++_activationCount; |
472 } | 477 } |
473 } | 478 } |
474 | 479 |
475 - (NSInteger)decrementActivationCount { | 480 - (NSInteger)decrementActivationCount { |
476 RTCLog(@"Decrementing activation count."); | 481 RTCLog(@"Decrementing activation count."); |
477 @synchronized(self) { | 482 @synchronized(self) { |
478 return --_activationCount; | 483 return --_activationCount; |
479 } | 484 } |
480 } | 485 } |
481 | 486 |
| 487 - (BOOL)checkLock:(NSError **)outError { |
| 488 // Check ivar instead of trying to acquire lock so that we won't accidentally |
| 489 // acquire lock if it hasn't already been called. |
| 490 if (!self.isLocked) { |
| 491 if (outError) { |
| 492 *outError = [RTCAudioSession lockError]; |
| 493 } |
| 494 return NO; |
| 495 } |
| 496 return YES; |
| 497 } |
| 498 |
482 - (void)updateAudioSessionAfterEvent { | 499 - (void)updateAudioSessionAfterEvent { |
483 BOOL shouldActivate = self.activationCount > 0; | 500 BOOL shouldActivate = self.activationCount > 0; |
484 AVAudioSessionSetActiveOptions options = shouldActivate ? | 501 AVAudioSessionSetActiveOptions options = shouldActivate ? |
485 0 : AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation; | 502 0 : AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation; |
486 NSError *error = nil; | 503 NSError *error = nil; |
487 if ([self.session setActive:shouldActivate | 504 if ([self.session setActive:shouldActivate |
488 withOptions:options | 505 withOptions:options |
489 error:&error]) { | 506 error:&error]) { |
490 self.isActive = shouldActivate; | 507 self.isActive = shouldActivate; |
491 } else { | 508 } else { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
524 } | 541 } |
525 } | 542 } |
526 | 543 |
527 - (void)notifyMediaServicesWereReset { | 544 - (void)notifyMediaServicesWereReset { |
528 for (id<RTCAudioSessionDelegate> delegate in self.delegates) { | 545 for (id<RTCAudioSessionDelegate> delegate in self.delegates) { |
529 [delegate audioSessionMediaServicesWereReset:self]; | 546 [delegate audioSessionMediaServicesWereReset:self]; |
530 } | 547 } |
531 } | 548 } |
532 | 549 |
533 @end | 550 @end |
OLD | NEW |