123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- #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
|