@cometchat/calls-sdk-react-native 4.0.0-beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -0
- package/android/build.gradle +20 -0
- package/android/src/main/AndroidManifest.xml +8 -0
- package/android/src/main/java/com/CometChatCalls/AudioDeviceHandlerGeneric.java +213 -0
- package/android/src/main/java/com/CometChatCalls/AudioDeviceHandlerLegacy.java +213 -0
- package/android/src/main/java/com/CometChatCalls/AudioModeModule.java +456 -0
- package/android/src/main/java/com/CometChatCalls/BluetoothHeadsetMonitor.java +174 -0
- package/android/src/main/java/com/CometChatCalls/CometChatCallsPackage.java +45 -0
- package/cometchat-calls-sdk-react-native.podspec +21 -0
- package/dist/CometChatErrorConstants.d.ts +124 -0
- package/dist/Constants.d.ts +720 -0
- package/dist/Helper copy.d.ts +1 -0
- package/dist/Helper.d.ts +7 -0
- package/dist/api/APIHandler.d.ts +6 -0
- package/dist/api/endpoints.d.ts +6 -0
- package/dist/api/helper.d.ts +63 -0
- package/dist/api/index.d.ts +2 -0
- package/dist/constants/CallConstants.d.ts +136 -0
- package/dist/constants/index.d.ts +1 -0
- package/dist/defaultCallsettings.d.ts +2 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +128 -0
- package/dist/models/CallAppSettings.d.ts +42 -0
- package/dist/models/CallSettings.d.ts +316 -0
- package/dist/models/CometChatCalls.d.ts +89 -0
- package/dist/models/CometChatCallsComponent.d.ts +13 -0
- package/dist/models/CometChatCallsComponentCore.d.ts +18 -0
- package/dist/models/CometChatCallsException.d.ts +7 -0
- package/dist/models/CometChatPresenterComponent.d.ts +13 -0
- package/dist/models/ErrorModel.d.ts +11 -0
- package/dist/models/Listner.d.ts +64 -0
- package/dist/models/ListnerHandler.d.ts +10 -0
- package/dist/models/MessageComponent.d.ts +7 -0
- package/dist/models/PresenterSettings.d.ts +194 -0
- package/dist/models/RTCUser.d.ts +18 -0
- package/dist/models/index.d.ts +7 -0
- package/dist/types/ICallAppSettings.d.ts +6 -0
- package/dist/types/ICallSettings.d.ts +60 -0
- package/dist/types/RTCUser.d.ts +6 -0
- package/dist/types/callEvents.d.ts +53 -0
- package/dist/types/common.d.ts +17 -0
- package/dist/types/index.d.ts +2 -0
- package/ios/AudioMode.h +11 -0
- package/ios/AudioMode.m +403 -0
- package/ios/JitsiAudioSession+Private.h +25 -0
- package/ios/JitsiAudioSession.h +17 -0
- package/ios/JitsiAudioSession.m +34 -0
- package/ios/LogUtils.h +23 -0
- package/ios/react-native-calls2.xcodeproj/project.pbxproj +269 -0
- package/package.json +122 -0
package/ios/AudioMode.m
ADDED
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright @ 2017-present 8x8, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
#import <AVFoundation/AVFoundation.h>
|
|
18
|
+
|
|
19
|
+
#import <React/RCTEventEmitter.h>
|
|
20
|
+
#import <React/RCTLog.h>
|
|
21
|
+
#import <WebRTC/WebRTC.h>
|
|
22
|
+
|
|
23
|
+
#import "JitsiAudioSession+Private.h"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
// Audio mode
|
|
27
|
+
typedef enum {
|
|
28
|
+
kAudioModeDefault,
|
|
29
|
+
kAudioModeAudioCall,
|
|
30
|
+
kAudioModeVideoCall
|
|
31
|
+
} JitsiMeetAudioMode;
|
|
32
|
+
|
|
33
|
+
// Events
|
|
34
|
+
static NSString * const kDevicesChanged = @"org.jitsi.meet:features/audio-mode#devices-update";
|
|
35
|
+
static NSString * const kDevicesChangedCustom = @"org.jitsi.meet:features/audio-mode#devices-update-custom";
|
|
36
|
+
|
|
37
|
+
// Device types (must match JS and Java)
|
|
38
|
+
static NSString * const kDeviceTypeBluetooth = @"BLUETOOTH";
|
|
39
|
+
static NSString * const kDeviceTypeCar = @"CAR";
|
|
40
|
+
static NSString * const kDeviceTypeEarpiece = @"EARPIECE";
|
|
41
|
+
static NSString * const kDeviceTypeHeadphones = @"HEADPHONES";
|
|
42
|
+
static NSString * const kDeviceTypeSpeaker = @"SPEAKER";
|
|
43
|
+
static NSString * const kDeviceTypeUnknown = @"UNKNOWN";
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@interface AudioMode : RCTEventEmitter<RTCAudioSessionDelegate>
|
|
47
|
+
|
|
48
|
+
@property(nonatomic, strong) dispatch_queue_t workerQueue;
|
|
49
|
+
|
|
50
|
+
@end
|
|
51
|
+
|
|
52
|
+
@implementation AudioMode {
|
|
53
|
+
JitsiMeetAudioMode activeMode;
|
|
54
|
+
RTCAudioSessionConfiguration *defaultConfig;
|
|
55
|
+
RTCAudioSessionConfiguration *audioCallConfig;
|
|
56
|
+
RTCAudioSessionConfiguration *videoCallConfig;
|
|
57
|
+
RTCAudioSessionConfiguration *earpieceConfig;
|
|
58
|
+
BOOL forceSpeaker;
|
|
59
|
+
BOOL forceEarpiece;
|
|
60
|
+
BOOL isSpeakerOn;
|
|
61
|
+
BOOL isEarpieceOn;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
RCT_EXPORT_MODULE();
|
|
65
|
+
|
|
66
|
+
+ (BOOL)requiresMainQueueSetup {
|
|
67
|
+
return NO;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
- (NSArray<NSString *> *)supportedEvents {
|
|
71
|
+
return @[ kDevicesChanged, kDevicesChangedCustom ];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
- (NSDictionary *)constantsToExport {
|
|
75
|
+
return @{
|
|
76
|
+
@"DEVICE_CHANGE_EVENT": kDevicesChanged,
|
|
77
|
+
@"DEVICE_CHANGE_EVENT_CUSTOM": kDevicesChangedCustom,
|
|
78
|
+
@"AUDIO_CALL" : [NSNumber numberWithInt: kAudioModeAudioCall],
|
|
79
|
+
@"DEFAULT" : [NSNumber numberWithInt: kAudioModeDefault],
|
|
80
|
+
@"VIDEO_CALL" : [NSNumber numberWithInt: kAudioModeVideoCall]
|
|
81
|
+
};
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
- (instancetype)init {
|
|
85
|
+
self = [super init];
|
|
86
|
+
if (self) {
|
|
87
|
+
dispatch_queue_attr_t attributes =
|
|
88
|
+
dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INITIATED, -1);
|
|
89
|
+
_workerQueue = dispatch_queue_create("AudioMode.queue", attributes);
|
|
90
|
+
|
|
91
|
+
activeMode = kAudioModeDefault;
|
|
92
|
+
|
|
93
|
+
defaultConfig = [[RTCAudioSessionConfiguration alloc] init];
|
|
94
|
+
defaultConfig.category = AVAudioSessionCategoryAmbient;
|
|
95
|
+
defaultConfig.categoryOptions = 0;
|
|
96
|
+
defaultConfig.mode = AVAudioSessionModeDefault;
|
|
97
|
+
|
|
98
|
+
audioCallConfig = [[RTCAudioSessionConfiguration alloc] init];
|
|
99
|
+
audioCallConfig.category = AVAudioSessionCategoryPlayAndRecord;
|
|
100
|
+
audioCallConfig.categoryOptions = AVAudioSessionCategoryOptionAllowBluetooth | AVAudioSessionCategoryOptionDefaultToSpeaker;
|
|
101
|
+
audioCallConfig.mode = AVAudioSessionModeVoiceChat;
|
|
102
|
+
|
|
103
|
+
videoCallConfig = [[RTCAudioSessionConfiguration alloc] init];
|
|
104
|
+
videoCallConfig.category = AVAudioSessionCategoryPlayAndRecord;
|
|
105
|
+
videoCallConfig.categoryOptions = AVAudioSessionCategoryOptionAllowBluetooth;
|
|
106
|
+
videoCallConfig.mode = AVAudioSessionModeVideoChat;
|
|
107
|
+
|
|
108
|
+
// Manually routing audio to the earpiece doesn't quite work unless one disables BT (weird, I know).
|
|
109
|
+
earpieceConfig = [[RTCAudioSessionConfiguration alloc] init];
|
|
110
|
+
earpieceConfig.category = AVAudioSessionCategoryPlayAndRecord;
|
|
111
|
+
earpieceConfig.categoryOptions = 0;
|
|
112
|
+
earpieceConfig.mode = AVAudioSessionModeVoiceChat;
|
|
113
|
+
|
|
114
|
+
forceSpeaker = NO;
|
|
115
|
+
forceEarpiece = NO;
|
|
116
|
+
isSpeakerOn = NO;
|
|
117
|
+
isEarpieceOn = NO;
|
|
118
|
+
|
|
119
|
+
RTCAudioSession *session = JitsiAudioSession.rtcAudioSession;
|
|
120
|
+
[session addDelegate:self];
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return self;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
- (dispatch_queue_t)methodQueue {
|
|
127
|
+
// Use a dedicated queue for audio mode operations.
|
|
128
|
+
return _workerQueue;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
- (BOOL)setConfigWithoutLock:(RTCAudioSessionConfiguration *)config
|
|
132
|
+
error:(NSError * _Nullable *)outError {
|
|
133
|
+
RTCAudioSession *session = JitsiAudioSession.rtcAudioSession;
|
|
134
|
+
|
|
135
|
+
return [session setConfiguration:config error:outError];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
- (BOOL)setConfig:(RTCAudioSessionConfiguration *)config
|
|
139
|
+
error:(NSError * _Nullable *)outError {
|
|
140
|
+
|
|
141
|
+
RTCAudioSession *session = JitsiAudioSession.rtcAudioSession;
|
|
142
|
+
[session lockForConfiguration];
|
|
143
|
+
BOOL success = [self setConfigWithoutLock:config error:outError];
|
|
144
|
+
[session unlockForConfiguration];
|
|
145
|
+
|
|
146
|
+
return success;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
#pragma mark - Exported methods
|
|
150
|
+
|
|
151
|
+
RCT_EXPORT_METHOD(setMode:(int)mode
|
|
152
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
153
|
+
reject:(RCTPromiseRejectBlock)reject) {
|
|
154
|
+
RTCAudioSessionConfiguration *config = [self configForMode:mode];
|
|
155
|
+
NSError *error;
|
|
156
|
+
|
|
157
|
+
if (config == nil) {
|
|
158
|
+
reject(@"setMode", @"Invalid mode", nil);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Reset.
|
|
163
|
+
if (mode == kAudioModeDefault) {
|
|
164
|
+
forceSpeaker = NO;
|
|
165
|
+
forceEarpiece = NO;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
activeMode = mode;
|
|
169
|
+
|
|
170
|
+
if ([self setConfig:config error:&error]) {
|
|
171
|
+
resolve(nil);
|
|
172
|
+
} else {
|
|
173
|
+
reject(@"setMode", error.localizedDescription, error);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
[self notifyDevicesChanged];
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
RCT_EXPORT_METHOD(setAudioDevice:(NSString *)device
|
|
180
|
+
resolve:(RCTPromiseResolveBlock)resolve
|
|
181
|
+
reject:(RCTPromiseRejectBlock)reject) {
|
|
182
|
+
NSLog(@"[AudioMode] Selected device: %@", device);
|
|
183
|
+
|
|
184
|
+
RTCAudioSession *session = JitsiAudioSession.rtcAudioSession;
|
|
185
|
+
[session lockForConfiguration];
|
|
186
|
+
BOOL success;
|
|
187
|
+
NSError *error = nil;
|
|
188
|
+
|
|
189
|
+
// Reset these, as we are about to compute them.
|
|
190
|
+
forceSpeaker = NO;
|
|
191
|
+
forceEarpiece = NO;
|
|
192
|
+
|
|
193
|
+
// The speaker is special, so test for it first.
|
|
194
|
+
if ([device isEqualToString:kDeviceTypeSpeaker]) {
|
|
195
|
+
forceSpeaker = YES;
|
|
196
|
+
success = [session overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:&error];
|
|
197
|
+
} else {
|
|
198
|
+
// Here we use AVAudioSession because RTCAudioSession doesn't expose availableInputs.
|
|
199
|
+
AVAudioSession *_session = [AVAudioSession sharedInstance];
|
|
200
|
+
AVAudioSessionPortDescription *port = nil;
|
|
201
|
+
|
|
202
|
+
// Find the matching input device.
|
|
203
|
+
for (AVAudioSessionPortDescription *portDesc in _session.availableInputs) {
|
|
204
|
+
if ([portDesc.UID isEqualToString:device] || [portDesc.portType isEqualToString:device]) {
|
|
205
|
+
port = portDesc;
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (port != nil) {
|
|
211
|
+
// First remove the override if we are going to select a different device.
|
|
212
|
+
if (isSpeakerOn) {
|
|
213
|
+
[session overrideOutputAudioPort:AVAudioSessionPortOverrideNone error:nil];
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Special case for the earpiece.
|
|
217
|
+
if ([port.portType isEqualToString:AVAudioSessionPortBuiltInMic]) {
|
|
218
|
+
forceEarpiece = YES;
|
|
219
|
+
[self setConfigWithoutLock:earpieceConfig error:nil];
|
|
220
|
+
} else if (isEarpieceOn) {
|
|
221
|
+
// Reset the config.
|
|
222
|
+
RTCAudioSessionConfiguration *config = [self configForMode:activeMode];
|
|
223
|
+
[self setConfigWithoutLock:config error:nil];
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// Select our preferred input.
|
|
227
|
+
success = [session setPreferredInput:port error:&error];
|
|
228
|
+
} else {
|
|
229
|
+
success = NO;
|
|
230
|
+
error = RCTErrorWithMessage(@"Could not find audio device");
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
[session unlockForConfiguration];
|
|
235
|
+
|
|
236
|
+
if (success) {
|
|
237
|
+
[self sendEventWithName:kDevicesChangedCustom body:device];
|
|
238
|
+
resolve(nil);
|
|
239
|
+
} else {
|
|
240
|
+
reject(@"setAudioDevice", error != nil ? error.localizedDescription : @"", error);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
RCT_EXPORT_METHOD(updateDeviceList) {
|
|
245
|
+
[self notifyDevicesChanged];
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
RCT_EXPORT_METHOD(removeListener) {
|
|
249
|
+
RTCAudioSession *session = [RTCAudioSession sharedInstance];
|
|
250
|
+
[session removeDelegate:self];
|
|
251
|
+
}
|
|
252
|
+
#pragma mark - RTCAudioSessionDelegate
|
|
253
|
+
|
|
254
|
+
- (void)audioSessionDidChangeRoute:(RTCAudioSession *)session
|
|
255
|
+
reason:(AVAudioSessionRouteChangeReason)reason
|
|
256
|
+
previousRoute:(AVAudioSessionRouteDescription *)previousRoute {
|
|
257
|
+
// Update JS about the changes.
|
|
258
|
+
[self notifyDevicesChanged];
|
|
259
|
+
|
|
260
|
+
dispatch_async(_workerQueue, ^{
|
|
261
|
+
switch (reason) {
|
|
262
|
+
case AVAudioSessionRouteChangeReasonNewDeviceAvailable:
|
|
263
|
+
case AVAudioSessionRouteChangeReasonOldDeviceUnavailable:
|
|
264
|
+
// If the device list changed, reset our overrides.
|
|
265
|
+
self->forceSpeaker = NO;
|
|
266
|
+
self->forceEarpiece = NO;
|
|
267
|
+
break;
|
|
268
|
+
case AVAudioSessionRouteChangeReasonCategoryChange: {
|
|
269
|
+
// The category has changed. Check if it's the one we want and adjust as
|
|
270
|
+
// needed.
|
|
271
|
+
RTCAudioSessionConfiguration *currentConfig = [self configForMode:self->activeMode];
|
|
272
|
+
if ([session.category isEqualToString:currentConfig.category]) {
|
|
273
|
+
// We are in the desired category, nothing to do here.
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
break;
|
|
277
|
+
}
|
|
278
|
+
default:
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// We don't want to touch the category when in default mode.
|
|
283
|
+
// This is to play well with other components which could be integrated
|
|
284
|
+
// into the final application.
|
|
285
|
+
if (self->activeMode != kAudioModeDefault) {
|
|
286
|
+
NSLog(@"[AudioMode] Route changed, reapplying RTCAudioSession config");
|
|
287
|
+
RTCAudioSessionConfiguration *config = [self configForMode:self->activeMode];
|
|
288
|
+
[self setConfig:config error:nil];
|
|
289
|
+
if (self->forceSpeaker && !self->isSpeakerOn) {
|
|
290
|
+
[session lockForConfiguration];
|
|
291
|
+
[session overrideOutputAudioPort:AVAudioSessionPortOverrideSpeaker error:nil];
|
|
292
|
+
[session unlockForConfiguration];
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
- (void)audioSession:(RTCAudioSession *)audioSession didSetActive:(BOOL)active {
|
|
299
|
+
NSLog(@"[AudioMode] Audio session didSetActive:%d", active);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
#pragma mark - Helper methods
|
|
303
|
+
|
|
304
|
+
- (RTCAudioSessionConfiguration *)configForMode:(int) mode {
|
|
305
|
+
if (mode != kAudioModeDefault && forceEarpiece) {
|
|
306
|
+
return earpieceConfig;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
switch (mode) {
|
|
310
|
+
case kAudioModeAudioCall:
|
|
311
|
+
return audioCallConfig;
|
|
312
|
+
case kAudioModeDefault:
|
|
313
|
+
return defaultConfig;
|
|
314
|
+
case kAudioModeVideoCall:
|
|
315
|
+
return videoCallConfig;
|
|
316
|
+
default:
|
|
317
|
+
return nil;
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Here we convert input and output port types into a single type.
|
|
322
|
+
- (NSString *)portTypeToString:(AVAudioSessionPort) portType {
|
|
323
|
+
if ([portType isEqualToString:AVAudioSessionPortHeadphones]
|
|
324
|
+
|| [portType isEqualToString:AVAudioSessionPortHeadsetMic]) {
|
|
325
|
+
return kDeviceTypeHeadphones;
|
|
326
|
+
} else if ([portType isEqualToString:AVAudioSessionPortBuiltInMic]
|
|
327
|
+
|| [portType isEqualToString:AVAudioSessionPortBuiltInReceiver]) {
|
|
328
|
+
return kDeviceTypeEarpiece;
|
|
329
|
+
} else if ([portType isEqualToString:AVAudioSessionPortBuiltInSpeaker]) {
|
|
330
|
+
return kDeviceTypeSpeaker;
|
|
331
|
+
} else if ([portType isEqualToString:AVAudioSessionPortBluetoothHFP]
|
|
332
|
+
|| [portType isEqualToString:AVAudioSessionPortBluetoothLE]
|
|
333
|
+
|| [portType isEqualToString:AVAudioSessionPortBluetoothA2DP]) {
|
|
334
|
+
return kDeviceTypeBluetooth;
|
|
335
|
+
} else if ([portType isEqualToString:AVAudioSessionPortCarAudio]) {
|
|
336
|
+
return kDeviceTypeCar;
|
|
337
|
+
} else {
|
|
338
|
+
return kDeviceTypeUnknown;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
- (void)notifyDevicesChanged {
|
|
343
|
+
NSLog(@"notifyDevicesChanged");
|
|
344
|
+
dispatch_async(_workerQueue, ^{
|
|
345
|
+
NSMutableArray *data = [[NSMutableArray alloc] init];
|
|
346
|
+
// Here we use AVAudioSession because RTCAudioSession doesn't expose availableInputs.
|
|
347
|
+
AVAudioSession *session = [AVAudioSession sharedInstance];
|
|
348
|
+
NSString *currentPort = @"";
|
|
349
|
+
AVAudioSessionRouteDescription *currentRoute = session.currentRoute;
|
|
350
|
+
|
|
351
|
+
// Check what the current device is. Because the speaker is somewhat special, we need to
|
|
352
|
+
// check for it first.
|
|
353
|
+
NSLog(@"notifyDevicesChanged %@", currentRoute);
|
|
354
|
+
if (currentRoute != nil) {
|
|
355
|
+
AVAudioSessionPortDescription *output = currentRoute.outputs.firstObject;
|
|
356
|
+
AVAudioSessionPortDescription *input = currentRoute.inputs.firstObject;
|
|
357
|
+
if (output != nil && [output.portType isEqualToString:AVAudioSessionPortBuiltInSpeaker]) {
|
|
358
|
+
currentPort = kDeviceTypeSpeaker;
|
|
359
|
+
self->isSpeakerOn = YES;
|
|
360
|
+
} else if (input != nil) {
|
|
361
|
+
currentPort = input.UID;
|
|
362
|
+
self->isSpeakerOn = NO;
|
|
363
|
+
self->isEarpieceOn = [input.portType isEqualToString:AVAudioSessionPortBuiltInMic];
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
BOOL headphonesAvailable = NO;
|
|
368
|
+
for (AVAudioSessionPortDescription *portDesc in session.availableInputs) {
|
|
369
|
+
if ([portDesc.portType isEqualToString:AVAudioSessionPortHeadsetMic] || [portDesc.portType isEqualToString:AVAudioSessionPortHeadphones]) {
|
|
370
|
+
headphonesAvailable = YES;
|
|
371
|
+
break;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
for (AVAudioSessionPortDescription *portDesc in session.availableInputs) {
|
|
376
|
+
// Skip "Phone" if headphones are present.
|
|
377
|
+
if (headphonesAvailable && [portDesc.portType isEqualToString:AVAudioSessionPortBuiltInMic]) {
|
|
378
|
+
continue;
|
|
379
|
+
}
|
|
380
|
+
id deviceData
|
|
381
|
+
= @{
|
|
382
|
+
@"type": [self portTypeToString:portDesc.portType],
|
|
383
|
+
@"name": portDesc.portName,
|
|
384
|
+
@"uid": portDesc.UID,
|
|
385
|
+
@"selected": [NSNumber numberWithBool:[portDesc.UID isEqualToString:currentPort]]
|
|
386
|
+
};
|
|
387
|
+
[data addObject:deviceData];
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
// We need to manually add the speaker because it will never show up in the
|
|
391
|
+
// previous list, as it's not an input.
|
|
392
|
+
[data addObject:
|
|
393
|
+
@{ @"type": kDeviceTypeSpeaker,
|
|
394
|
+
@"name": @"Speaker",
|
|
395
|
+
@"uid": kDeviceTypeSpeaker,
|
|
396
|
+
@"selected": [NSNumber numberWithBool:[kDeviceTypeSpeaker isEqualToString:currentPort]]
|
|
397
|
+
}];
|
|
398
|
+
NSLog(@"notifyDevicesChanged data %@" ,data);
|
|
399
|
+
[self sendEventWithName:kDevicesChanged body:data];
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
@end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
|
|
2
|
+
/*
|
|
3
|
+
* Copyright @ 2017-present 8x8, Inc.
|
|
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
|
+
|
|
18
|
+
#import "JitsiAudioSession.h"
|
|
19
|
+
#import <WebRTC/WebRTC.h>
|
|
20
|
+
|
|
21
|
+
@interface JitsiAudioSession (Private)
|
|
22
|
+
|
|
23
|
+
+ (RTCAudioSession *)rtcAudioSession;
|
|
24
|
+
|
|
25
|
+
@end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//
|
|
2
|
+
// JitsiAudioSession.h
|
|
3
|
+
// CometChatProCalls
|
|
4
|
+
//
|
|
5
|
+
// Created by CometChat on 27/05/22.
|
|
6
|
+
// Copyright © 2022 Jitsi. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
#import <Foundation/Foundation.h>
|
|
10
|
+
|
|
11
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
12
|
+
|
|
13
|
+
@interface JitsiAudioSession : NSObject
|
|
14
|
+
|
|
15
|
+
@end
|
|
16
|
+
|
|
17
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright @ 2017-present 8x8, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
#import "JitsiAudioSession.h"
|
|
18
|
+
#import "JitsiAudioSession+Private.h"
|
|
19
|
+
|
|
20
|
+
@implementation JitsiAudioSession
|
|
21
|
+
|
|
22
|
+
+ (RTCAudioSession *)rtcAudioSession {
|
|
23
|
+
return [RTCAudioSession sharedInstance];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
+ (void)activateWithAudioSession:(AVAudioSession *)session {
|
|
27
|
+
[self.rtcAudioSession audioSessionDidActivate:session];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
+ (void)deactivateWithAudioSession:(AVAudioSession *)session {
|
|
31
|
+
[self.rtcAudioSession audioSessionDidDeactivate:session];
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@end
|
package/ios/LogUtils.h
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright @ 2019-present 8x8, Inc.
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
#ifndef JM_LOG_UTILS_H
|
|
18
|
+
#define JM_LOG_UTILS_H
|
|
19
|
+
|
|
20
|
+
#import <CocoaLumberjack/CocoaLumberjack.h>
|
|
21
|
+
static const DDLogLevel ddLogLevel = DDLogLevelVerbose;
|
|
22
|
+
|
|
23
|
+
#endif
|