mirror of
https://gitcode.com/GitHub_Trending/ji/jitsi-meet.git
synced 2025-12-30 03:12:29 +00:00
feat(rn) implement startSilent
Technically, on Android, the audio mode is configured but no audio is played. Since the configured audio mode matches what we expect from a calling app (what we support to coexist with) this is enough to not create audio disruptions.
This commit is contained in:
committed by
Saúl Ibarra Corretgé
parent
95a6001a6f
commit
b3ee8fe127
@@ -136,6 +136,11 @@ class AudioModeModule extends ReactContextBaseJavaModule {
|
||||
*/
|
||||
private String userSelectedDevice;
|
||||
|
||||
/**
|
||||
* Whether or not audio is disabled.
|
||||
*/
|
||||
private boolean audioDisabled;
|
||||
|
||||
/**
|
||||
* Initializes a new module instance. There shall be a single instance of
|
||||
* this module throughout the lifetime of the application.
|
||||
@@ -236,6 +241,12 @@ class AudioModeModule extends ReactContextBaseJavaModule {
|
||||
audioDeviceHandler.stop();
|
||||
}
|
||||
|
||||
audioDeviceHandler = null;
|
||||
|
||||
if (audioDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (useConnectionService()) {
|
||||
audioDeviceHandler = new AudioDeviceHandlerConnectionService(audioManager);
|
||||
} else {
|
||||
@@ -278,6 +289,27 @@ class AudioModeModule extends ReactContextBaseJavaModule {
|
||||
});
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void setDisabled(final boolean disabled, final Promise promise) {
|
||||
if (audioDisabled == disabled) {
|
||||
promise.resolve(null);
|
||||
return;
|
||||
}
|
||||
|
||||
JitsiMeetLogger.i(TAG + " audio disabled: " + disabled);
|
||||
|
||||
audioDisabled = disabled;
|
||||
setAudioDeviceHandler();
|
||||
|
||||
if (disabled) {
|
||||
mode = -1;
|
||||
availableDevices.clear();
|
||||
resetSelectedDevice();
|
||||
}
|
||||
|
||||
promise.resolve(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Public method to set the current audio mode.
|
||||
*
|
||||
@@ -287,7 +319,12 @@ class AudioModeModule extends ReactContextBaseJavaModule {
|
||||
*/
|
||||
@ReactMethod
|
||||
public void setMode(final int mode, final Promise promise) {
|
||||
if (mode != DEFAULT && mode != AUDIO_CALL && mode != VIDEO_CALL) {
|
||||
if (audioDisabled) {
|
||||
promise.resolve(null);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode < DEFAULT || mode > VIDEO_CALL) {
|
||||
promise.reject("setMode", "Invalid audio mode " + mode);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#import <WebRTC/WebRTC.h>
|
||||
|
||||
#import "JitsiAudioSession+Private.h"
|
||||
#import "callkit/JMCallKitProxy.h"
|
||||
|
||||
|
||||
// Audio mode
|
||||
@@ -54,6 +55,7 @@ static NSString * const kDeviceTypeUnknown = @"UNKNOWN";
|
||||
RTCAudioSessionConfiguration *audioCallConfig;
|
||||
RTCAudioSessionConfiguration *videoCallConfig;
|
||||
RTCAudioSessionConfiguration *earpieceConfig;
|
||||
BOOL audioDisabled;
|
||||
BOOL forceSpeaker;
|
||||
BOOL forceEarpiece;
|
||||
BOOL isSpeakerOn;
|
||||
@@ -146,9 +148,36 @@ RCT_EXPORT_MODULE();
|
||||
|
||||
#pragma mark - Exported methods
|
||||
|
||||
RCT_EXPORT_METHOD(setDisabled:(BOOL)disabled
|
||||
resolve:(RCTPromiseResolveBlock)resolve
|
||||
reject:(RCTPromiseRejectBlock)reject) {
|
||||
if (audioDisabled == disabled) {
|
||||
resolve(nil);
|
||||
return;
|
||||
}
|
||||
|
||||
RCTLogInfo(@"[AudioMode] audio disabled: %d", disabled);
|
||||
|
||||
audioDisabled = disabled;
|
||||
JMCallKitProxy.enabled = !disabled;
|
||||
|
||||
RTCAudioSession *session = JitsiAudioSession.rtcAudioSession;
|
||||
if (disabled) {
|
||||
[session removeDelegate:self];
|
||||
} else {
|
||||
[session addDelegate:self];
|
||||
}
|
||||
session.useManualAudio = disabled;
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(setMode:(int)mode
|
||||
resolve:(RCTPromiseResolveBlock)resolve
|
||||
reject:(RCTPromiseRejectBlock)reject) {
|
||||
if (audioDisabled) {
|
||||
resolve(nil);
|
||||
return;
|
||||
}
|
||||
|
||||
RTCAudioSessionConfiguration *config = [self configForMode:mode];
|
||||
NSError *error;
|
||||
|
||||
@@ -177,6 +206,11 @@ RCT_EXPORT_METHOD(setMode:(int)mode
|
||||
RCT_EXPORT_METHOD(setAudioDevice:(NSString *)device
|
||||
resolve:(RCTPromiseResolveBlock)resolve
|
||||
reject:(RCTPromiseRejectBlock)reject) {
|
||||
if (audioDisabled) {
|
||||
resolve(nil);
|
||||
return;
|
||||
}
|
||||
|
||||
RCTLogInfo(@"[AudioMode] Selected device: %@", device);
|
||||
|
||||
RTCAudioSession *session = JitsiAudioSession.rtcAudioSession;
|
||||
@@ -239,6 +273,10 @@ RCT_EXPORT_METHOD(setAudioDevice:(NSString *)device
|
||||
}
|
||||
|
||||
RCT_EXPORT_METHOD(updateDeviceList) {
|
||||
if (audioDisabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
[self notifyDevicesChanged];
|
||||
}
|
||||
|
||||
|
||||
@@ -24,11 +24,15 @@
|
||||
}
|
||||
|
||||
+ (void)activateWithAudioSession:(AVAudioSession *)session {
|
||||
[self.rtcAudioSession audioSessionDidActivate:session];
|
||||
if (!self.rtcAudioSession.useManualAudio) {
|
||||
[self.rtcAudioSession audioSessionDidActivate:session];
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)deactivateWithAudioSession:(AVAudioSession *)session {
|
||||
[self.rtcAudioSession audioSessionDidDeactivate:session];
|
||||
if (!self.rtcAudioSession.useManualAudio) {
|
||||
[self.rtcAudioSession audioSessionDidDeactivate:session];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -86,12 +86,16 @@ export function createDesiredLocalTracks(...desiredTypes: any) {
|
||||
dispatch(destroyLocalDesktopTrackIfExists());
|
||||
|
||||
if (desiredTypes.length === 0) {
|
||||
const { startSilent } = state['features/base/config'];
|
||||
const { video } = state['features/base/media'];
|
||||
|
||||
// XXX: Always create the audio track early, even if it will be muted.
|
||||
// This fixes a timing issue when adding the track to the conference which
|
||||
// manifests primarily on iOS 15.
|
||||
desiredTypes.push(MEDIA_TYPE.AUDIO);
|
||||
if (!startSilent) {
|
||||
// Always create the audio track early, even if it will be muted.
|
||||
// This fixes a timing issue when adding the track to the conference which
|
||||
// manifests primarily on iOS 15.
|
||||
// Unless we are silent, of course.
|
||||
desiredTypes.push(MEDIA_TYPE.AUDIO);
|
||||
}
|
||||
|
||||
// XXX When the app is coming into the foreground from the
|
||||
// background in order to handle a URL, it may realize the new
|
||||
|
||||
@@ -10,9 +10,11 @@ import {
|
||||
CONFERENCE_LEFT
|
||||
} from '../../base/conference/actionTypes';
|
||||
import { getCurrentConference } from '../../base/conference/functions';
|
||||
import { SET_CONFIG } from '../../base/config/actionTypes';
|
||||
import { AUDIO_FOCUS_DISABLED } from '../../base/flags/constants';
|
||||
import { getFeatureFlag } from '../../base/flags/functions';
|
||||
import MiddlewareRegistry from '../../base/redux/MiddlewareRegistry';
|
||||
import { parseURIString } from '../../base/util/uri';
|
||||
|
||||
import { _SET_AUDIOMODE_DEVICES, _SET_AUDIOMODE_SUBSCRIPTIONS } from './actionTypes';
|
||||
import logger from './logger';
|
||||
@@ -44,7 +46,7 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
}
|
||||
case APP_WILL_MOUNT:
|
||||
_appWillMount(store);
|
||||
case CONFERENCE_FAILED: // eslint-disable-line no-fallthrough
|
||||
case CONFERENCE_FAILED:
|
||||
case CONFERENCE_LEFT:
|
||||
|
||||
/*
|
||||
@@ -60,6 +62,23 @@ MiddlewareRegistry.register(store => next => action => {
|
||||
case SET_AUDIO_ONLY:
|
||||
return _updateAudioMode(store, next, action);
|
||||
|
||||
case SET_CONFIG: {
|
||||
const { locationURL } = store.getState()['features/base/connection'];
|
||||
const location = parseURIString(locationURL?.href ?? '');
|
||||
|
||||
/**
|
||||
* Don't touch the current value if there is no room in the URL. This
|
||||
* avoids audio cutting off for a moment right after the user leaves
|
||||
* a meeting. The next meeting join will set it to the right value.
|
||||
*/
|
||||
if (location.room) {
|
||||
const { startSilent } = action.config;
|
||||
|
||||
AudioMode.setDisabled?.(Boolean(startSilent));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* eslint-enable no-fallthrough */
|
||||
|
||||
Reference in New Issue
Block a user