Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

AudioMode.m 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /*
  2. * Copyright @ 2018-present 8x8, Inc.
  3. * Copyright @ 2017-2018 Atlassian Pty Ltd
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. #import <AVFoundation/AVFoundation.h>
  18. #import <React/RCTBridgeModule.h>
  19. #import <React/RCTLog.h>
  20. #import <WebRTC/WebRTC.h>
  21. typedef enum {
  22. kAudioModeDefault,
  23. kAudioModeAudioCall,
  24. kAudioModeVideoCall
  25. } JitsiMeetAudioMode;
  26. @interface AudioMode : NSObject<RCTBridgeModule, RTCAudioSessionDelegate>
  27. @property(nonatomic, strong) dispatch_queue_t workerQueue;
  28. @end
  29. @implementation AudioMode {
  30. JitsiMeetAudioMode activeMode;
  31. RTCAudioSessionConfiguration *defaultConfig;
  32. RTCAudioSessionConfiguration *audioCallConfig;
  33. RTCAudioSessionConfiguration *videoCallConfig;
  34. }
  35. RCT_EXPORT_MODULE();
  36. + (BOOL)requiresMainQueueSetup {
  37. return NO;
  38. }
  39. - (NSDictionary *)constantsToExport {
  40. return @{
  41. @"AUDIO_CALL" : [NSNumber numberWithInt: kAudioModeAudioCall],
  42. @"DEFAULT" : [NSNumber numberWithInt: kAudioModeDefault],
  43. @"VIDEO_CALL" : [NSNumber numberWithInt: kAudioModeVideoCall]
  44. };
  45. };
  46. - (instancetype)init {
  47. self = [super init];
  48. if (self) {
  49. dispatch_queue_attr_t attributes =
  50. dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL,
  51. QOS_CLASS_USER_INITIATED, -1);
  52. _workerQueue = dispatch_queue_create("AudioMode.queue", attributes);
  53. activeMode = kAudioModeDefault;
  54. defaultConfig = [[RTCAudioSessionConfiguration alloc] init];
  55. defaultConfig.category = AVAudioSessionCategoryAmbient;
  56. defaultConfig.categoryOptions = 0;
  57. defaultConfig.mode = AVAudioSessionModeDefault;
  58. audioCallConfig = [[RTCAudioSessionConfiguration alloc] init];
  59. audioCallConfig.category = AVAudioSessionCategoryPlayAndRecord;
  60. audioCallConfig.categoryOptions = AVAudioSessionCategoryOptionAllowBluetooth;
  61. audioCallConfig.mode = AVAudioSessionModeVoiceChat;
  62. videoCallConfig = [[RTCAudioSessionConfiguration alloc] init];
  63. videoCallConfig.category = AVAudioSessionCategoryPlayAndRecord;
  64. videoCallConfig.categoryOptions = AVAudioSessionCategoryOptionAllowBluetooth;
  65. videoCallConfig.mode = AVAudioSessionModeVideoChat;
  66. RTCAudioSession *session = [RTCAudioSession sharedInstance];
  67. [session addDelegate:self];
  68. }
  69. return self;
  70. }
  71. - (dispatch_queue_t)methodQueue {
  72. // Use a dedicated queue for audio mode operations.
  73. return _workerQueue;
  74. }
  75. - (BOOL)setConfig:(RTCAudioSessionConfiguration *)config
  76. error:(NSError * _Nullable *)outError {
  77. RTCAudioSession *session = [RTCAudioSession sharedInstance];
  78. [session lockForConfiguration];
  79. BOOL success = [session setConfiguration:config error:outError];
  80. [session unlockForConfiguration];
  81. return success;
  82. }
  83. #pragma mark - Exported methods
  84. RCT_EXPORT_METHOD(setMode:(int)mode
  85. resolve:(RCTPromiseResolveBlock)resolve
  86. reject:(RCTPromiseRejectBlock)reject) {
  87. RTCAudioSessionConfiguration *config;
  88. NSError *error;
  89. switch (mode) {
  90. case kAudioModeAudioCall:
  91. config = audioCallConfig;
  92. break;
  93. case kAudioModeDefault:
  94. config = defaultConfig;
  95. break;
  96. case kAudioModeVideoCall:
  97. config = videoCallConfig;
  98. break;
  99. default:
  100. reject(@"setMode", @"Invalid mode", nil);
  101. return;
  102. }
  103. activeMode = mode;
  104. if ([self setConfig:config error:&error]) {
  105. resolve(nil);
  106. } else {
  107. reject(@"setMode", error.localizedDescription, error);
  108. }
  109. }
  110. #pragma mark - RTCAudioSessionDelegate
  111. - (void)audioSessionDidChangeRoute:(RTCAudioSession *)session
  112. reason:(AVAudioSessionRouteChangeReason)reason
  113. previousRoute:(AVAudioSessionRouteDescription *)previousRoute {
  114. if (reason == AVAudioSessionRouteChangeReasonCategoryChange) {
  115. // The category has changed. Check if it's the one we want and adjust as
  116. // needed. This notification is posted on a secondary thread, so make
  117. // sure we switch to our worker thread.
  118. dispatch_async(_workerQueue, ^{
  119. // We don't want to touch the category when in default mode.
  120. // This is to play well with other components which could be integrated
  121. // into the final application.
  122. if (self->activeMode != kAudioModeDefault) {
  123. NSLog(@"Audio route changed, reapplying RTCAudioSession config");
  124. RTCAudioSessionConfiguration *config
  125. = self->activeMode == kAudioModeAudioCall ? self->audioCallConfig : self->videoCallConfig;
  126. [self setConfig:config error:nil];
  127. }
  128. });
  129. }
  130. }
  131. - (void)audioSession:(RTCAudioSession *)audioSession didSetActive:(BOOL)active {
  132. NSLog(@"[AudioMode] Audio session didSetActive:%d", active);
  133. }
  134. @end