|
@@ -20,6 +20,12 @@
|
20
|
20
|
#import <React/RCTBridgeModule.h>
|
21
|
21
|
#import <React/RCTLog.h>
|
22
|
22
|
|
|
23
|
+typedef enum {
|
|
24
|
+ kAudioModeDefault,
|
|
25
|
+ kAudioModeAudioCall,
|
|
26
|
+ kAudioModeVideoCall
|
|
27
|
+} JitsiMeetAudioMode;
|
|
28
|
+
|
23
|
29
|
@interface AudioMode : NSObject<RCTBridgeModule>
|
24
|
30
|
|
25
|
31
|
@property(nonatomic, strong) dispatch_queue_t workerQueue;
|
|
@@ -27,18 +33,13 @@
|
27
|
33
|
@end
|
28
|
34
|
|
29
|
35
|
@implementation AudioMode {
|
30
|
|
- NSString *_category;
|
31
|
|
- NSString *_mode;
|
|
36
|
+ NSString *_avCategory;
|
|
37
|
+ NSString *_avMode;
|
|
38
|
+ JitsiMeetAudioMode _mode;
|
32
|
39
|
}
|
33
|
40
|
|
34
|
41
|
RCT_EXPORT_MODULE();
|
35
|
42
|
|
36
|
|
-typedef enum {
|
37
|
|
- kAudioModeDefault,
|
38
|
|
- kAudioModeAudioCall,
|
39
|
|
- kAudioModeVideoCall
|
40
|
|
-} JitsiMeetAudioMode;
|
41
|
|
-
|
42
|
43
|
+ (BOOL)requiresMainQueueSetup {
|
43
|
44
|
return NO;
|
44
|
45
|
}
|
|
@@ -54,13 +55,23 @@ typedef enum {
|
54
|
55
|
- (instancetype)init {
|
55
|
56
|
self = [super init];
|
56
|
57
|
if (self) {
|
57
|
|
- _category = nil;
|
58
|
|
- _mode = nil;
|
|
58
|
+ _avCategory = nil;
|
|
59
|
+ _avMode = nil;
|
|
60
|
+ _mode = kAudioModeDefault;
|
59
|
61
|
|
60
|
62
|
dispatch_queue_attr_t attributes =
|
61
|
63
|
dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL,
|
62
|
64
|
QOS_CLASS_USER_INITIATED, -1);
|
63
|
65
|
_workerQueue = dispatch_queue_create("AudioMode.queue", attributes);
|
|
66
|
+
|
|
67
|
+ // AVAudioSession is a singleton and other parts of the application such as
|
|
68
|
+ // WebRTC may undo the settings. Make sure that the settings are reapplied
|
|
69
|
+ // upon undoes.
|
|
70
|
+ [[NSNotificationCenter defaultCenter]
|
|
71
|
+ addObserver:self
|
|
72
|
+ selector:@selector(routeChanged:)
|
|
73
|
+ name:AVAudioSessionRouteChangeNotification
|
|
74
|
+ object:nil];
|
64
|
75
|
}
|
65
|
76
|
return self;
|
66
|
77
|
}
|
|
@@ -82,7 +93,7 @@ typedef enum {
|
82
|
93
|
// needed. This notification is posted on a secondary thread, so make
|
83
|
94
|
// sure we switch to our worker thread.
|
84
|
95
|
dispatch_async(_workerQueue, ^{
|
85
|
|
- [self setCategory:self->_category mode:self->_mode error:nil];
|
|
96
|
+ [self setCategory:self->_avCategory mode:self->_avMode error:nil];
|
86
|
97
|
});
|
87
|
98
|
break;
|
88
|
99
|
}
|
|
@@ -97,6 +108,18 @@ typedef enum {
|
97
|
108
|
error:(NSError * _Nullable *)outError {
|
98
|
109
|
AVAudioSession *session = [AVAudioSession sharedInstance];
|
99
|
110
|
|
|
111
|
+ // We don't want to touch the category when setting the default mode.
|
|
112
|
+ // This is to play well with other components which could be integrated
|
|
113
|
+ // into the final application.
|
|
114
|
+ if (_mode == kAudioModeDefault) {
|
|
115
|
+ return YES;
|
|
116
|
+ }
|
|
117
|
+
|
|
118
|
+ // Nothing to do.
|
|
119
|
+ if (category == nil && mode == nil) {
|
|
120
|
+ return YES;
|
|
121
|
+ }
|
|
122
|
+
|
100
|
123
|
if (session.category != category
|
101
|
124
|
&& ![session setCategory:category error:outError]) {
|
102
|
125
|
RCTLogError(@"Failed to (re)apply specified AVAudioSession category!");
|
|
@@ -114,8 +137,8 @@ typedef enum {
|
114
|
137
|
RCT_EXPORT_METHOD(setMode:(int)mode
|
115
|
138
|
resolve:(RCTPromiseResolveBlock)resolve
|
116
|
139
|
reject:(RCTPromiseRejectBlock)reject) {
|
117
|
|
- NSString *avCategory;
|
118
|
|
- NSString *avMode;
|
|
140
|
+ NSString *avCategory = nil;
|
|
141
|
+ NSString *avMode = nil;
|
119
|
142
|
NSError *error;
|
120
|
143
|
|
121
|
144
|
switch (mode) {
|
|
@@ -124,8 +147,6 @@ RCT_EXPORT_METHOD(setMode:(int)mode
|
124
|
147
|
avMode = AVAudioSessionModeVoiceChat;
|
125
|
148
|
break;
|
126
|
149
|
case kAudioModeDefault:
|
127
|
|
- avCategory = AVAudioSessionCategorySoloAmbient;
|
128
|
|
- avMode = AVAudioSessionModeDefault;
|
129
|
150
|
break;
|
130
|
151
|
case kAudioModeVideoCall:
|
131
|
152
|
avCategory = AVAudioSessionCategoryPlayAndRecord;
|
|
@@ -136,29 +157,17 @@ RCT_EXPORT_METHOD(setMode:(int)mode
|
136
|
157
|
return;
|
137
|
158
|
}
|
138
|
159
|
|
|
160
|
+ // Save the desired/specified category and mode so that they may be
|
|
161
|
+ // reapplied.
|
|
162
|
+ _avCategory = avCategory;
|
|
163
|
+ _avMode = avMode;
|
|
164
|
+ _mode = mode;
|
|
165
|
+
|
139
|
166
|
if (![self setCategory:avCategory mode:avMode error:&error] || error) {
|
140
|
167
|
reject(@"setMode", error.localizedDescription, error);
|
141
|
|
- return;
|
|
168
|
+ } else {
|
|
169
|
+ resolve(nil);
|
142
|
170
|
}
|
143
|
|
-
|
144
|
|
- // Even though the specified category and mode were successfully set, the
|
145
|
|
- // AVAudioSession is a singleton and other parts of the application such as
|
146
|
|
- // WebRTC may undo the settings. Make sure that the settings are reapplied
|
147
|
|
- // upon undoes.
|
148
|
|
- if (!_category || !_mode) {
|
149
|
|
- [[NSNotificationCenter defaultCenter]
|
150
|
|
- addObserver:self
|
151
|
|
- selector:@selector(routeChanged:)
|
152
|
|
- name:AVAudioSessionRouteChangeNotification
|
153
|
|
- object:nil];
|
154
|
|
- }
|
155
|
|
-
|
156
|
|
- // Save the desired/specified category and mode so that they may be
|
157
|
|
- // reapplied (upon undoes as described above).
|
158
|
|
- _category = avCategory;
|
159
|
|
- _mode = avMode;
|
160
|
|
-
|
161
|
|
- resolve(nil);
|
162
|
171
|
}
|
163
|
172
|
|
164
|
173
|
@end
|