Simplify the source code (with the idea that source code which does not exist does not have to be maintained). Additionally, apply modifications to have the source code comply with the coding style. Overall, prepare saghul:audio-mode for merge into jitsi:master.
135 lines
3.7 KiB
Objective-C
135 lines
3.7 KiB
Objective-C
#import "RCTBridgeModule.h"
|
|
#import "RCTLog.h"
|
|
|
|
#import <AVFoundation/AVFoundation.h>
|
|
|
|
@interface AudioMode : NSObject<RCTBridgeModule>
|
|
@end
|
|
|
|
@implementation AudioMode {
|
|
NSString *_category;
|
|
NSString *_mode;
|
|
}
|
|
|
|
RCT_EXPORT_MODULE();
|
|
|
|
typedef enum {
|
|
kAudioModeDefault,
|
|
kAudioModeAudioCall,
|
|
kAudioModeVideoCall
|
|
} JitsiMeetAudioMode;
|
|
|
|
- (NSDictionary *)constantsToExport {
|
|
return @{
|
|
@"AUDIO_CALL" : [NSNumber numberWithInt: kAudioModeAudioCall],
|
|
@"DEFAULT" : [NSNumber numberWithInt: kAudioModeDefault],
|
|
@"VIDEO_CALL" : [NSNumber numberWithInt: kAudioModeVideoCall]
|
|
};
|
|
};
|
|
|
|
- (instancetype)init {
|
|
self = [super init];
|
|
if (self) {
|
|
_category = nil;
|
|
_mode = nil;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (dispatch_queue_t)methodQueue {
|
|
// Make sure all our methods run in the main thread. The route change
|
|
// notification runs there so this will make sure it will only be fired
|
|
// after our changes have been applied (when we cause them, that is).
|
|
return dispatch_get_main_queue();
|
|
}
|
|
|
|
- (void)routeChanged:(NSNotification*)notification {
|
|
NSInteger reason
|
|
= [[notification.userInfo
|
|
valueForKey:AVAudioSessionRouteChangeReasonKey]
|
|
integerValue];
|
|
|
|
switch (reason) {
|
|
case AVAudioSessionRouteChangeReasonCategoryChange:
|
|
// The category has changed. Check if it's the one we want and adjust as
|
|
// needed.
|
|
[self setCategory:_category mode:_mode error:nil];
|
|
break;
|
|
|
|
default:
|
|
// Do nothing.
|
|
break;
|
|
}
|
|
}
|
|
|
|
- (BOOL)setCategory:(NSString *)category
|
|
mode:(NSString *)mode
|
|
error:(NSError * _Nullable *)outError {
|
|
AVAudioSession *session = [AVAudioSession sharedInstance];
|
|
|
|
if (session.category != category
|
|
&& ![session setCategory:category error:outError]) {
|
|
RCTLogError(@"Failed to (re)apply specified AVAudioSession category!");
|
|
return NO;
|
|
}
|
|
|
|
if (session.mode != mode && ![session setMode:mode error:outError]) {
|
|
RCTLogError(@"Failed to (re)apply specified AVAudioSession mode!");
|
|
return NO;
|
|
}
|
|
|
|
return YES;
|
|
}
|
|
|
|
RCT_EXPORT_METHOD(setMode:(int)mode
|
|
resolve:(RCTPromiseResolveBlock)resolve
|
|
reject:(RCTPromiseRejectBlock)reject) {
|
|
NSString *avCategory;
|
|
NSString *avMode;
|
|
NSError *error;
|
|
|
|
switch (mode) {
|
|
case kAudioModeAudioCall:
|
|
avCategory = AVAudioSessionCategoryPlayAndRecord;
|
|
avMode = AVAudioSessionModeVoiceChat;
|
|
break;
|
|
case kAudioModeDefault:
|
|
avCategory = AVAudioSessionCategorySoloAmbient;
|
|
avMode = AVAudioSessionModeDefault;
|
|
break;
|
|
case kAudioModeVideoCall:
|
|
avCategory = AVAudioSessionCategoryPlayAndRecord;
|
|
avMode = AVAudioSessionModeVideoChat;
|
|
break;
|
|
default:
|
|
reject(@"setMode", @"Invalid mode", nil);
|
|
return;
|
|
}
|
|
|
|
if (![self setCategory:avCategory mode:avMode error:&error] || error) {
|
|
reject(@"setMode", error.localizedDescription, error);
|
|
return;
|
|
}
|
|
|
|
// Even though the specified category and mode were successfully set, the
|
|
// AVAudioSession is a singleton and other parts of the application such as
|
|
// WebRTC may undo the settings. Make sure that the settings are reapplied
|
|
// upon undoes.
|
|
if (!_category || !_mode) {
|
|
[[NSNotificationCenter defaultCenter]
|
|
addObserver:self
|
|
selector:@selector(routeChanged:)
|
|
name:AVAudioSessionRouteChangeNotification
|
|
object:nil];
|
|
}
|
|
|
|
// Save the desired/specified category and mode so that they may be
|
|
// reapplied (upon undoes as described above).
|
|
_category = avCategory;
|
|
_mode = avMode;
|
|
|
|
resolve(nil);
|
|
}
|
|
|
|
@end
|