Skip to content

Commit e7909ad

Browse files
committed
add methods to js client
1 parent ccfa4aa commit e7909ad

File tree

11 files changed

+197
-136
lines changed

11 files changed

+197
-136
lines changed

packages/client/src/Call.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,7 @@ export class Call {
345345
setup = async () => {
346346
await withoutConcurrency(this.joinLeaveConcurrencyTag, async () => {
347347
if (this.initialized) return;
348+
streamRNVideoSDK?.callManager.setup();
348349

349350
this.leaveCallHooks.add(
350351
this.on('all', (event) => {
@@ -659,6 +660,8 @@ export class Call {
659660
this.cancelAutoDrop();
660661
this.clientStore.unregisterCall(this);
661662

663+
streamRNVideoSDK?.callManager.stop();
664+
662665
this.camera.dispose();
663666
this.microphone.dispose();
664667
this.screenShare.dispose();
@@ -884,6 +887,8 @@ export class Call {
884887
throw new Error(`Illegal State: call.join() shall be called only once`);
885888
}
886889

890+
streamRNVideoSDK?.callManager.start();
891+
887892
// we will count the number of join failures per SFU.
888893
// once the number of failures reaches 2, we will piggyback on the `migrating_from`
889894
// field to force the coordinator to provide us another SFU

packages/client/src/types.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,29 @@ export type CallConstructor = {
322322
clientStore: StreamVideoWriteableStateStore;
323323
};
324324

325+
export type StreamRNVideoSDKGlobals = {
326+
callManager: {
327+
/**
328+
* Sets up the in call manager.
329+
*/
330+
setup(): void;
331+
332+
/**
333+
* Starts the in call manager.
334+
*/
335+
start(): void;
336+
337+
/**
338+
* Stops the in call manager.
339+
*/
340+
stop(): void;
341+
};
342+
};
343+
344+
declare global {
345+
var streamRNVideoSDK: StreamRNVideoSDKGlobals | undefined;
346+
}
347+
325348
/**
326349
* The options to pass to {@link Call.join} method.
327350
*/

packages/react-native-sdk/android/src/main/java/com/streamvideo/reactnative/audio/AudioDeviceManager.kt

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import com.streamvideo.reactnative.audio.utils.AudioDeviceEndpointUtils
3131
import com.streamvideo.reactnative.audio.utils.AudioFocusUtil
3232
import com.streamvideo.reactnative.audio.utils.AudioManagerUtil
3333
import com.streamvideo.reactnative.audio.utils.AudioManagerUtil.Companion.getAvailableAudioDevices
34-
import com.streamvideo.reactnative.audio.utils.AudioSetupStoreUtil
3534
import com.streamvideo.reactnative.audio.utils.CallAudioRole
3635
import com.streamvideo.reactnative.callmanager.ProximityManager
3736
import com.streamvideo.reactnative.callmanager.StreamInCallManagerModule
@@ -90,6 +89,8 @@ class AudioDeviceManager(
9089
@EndpointType
9190
private var userSelectedAudioDevice: Int? = null
9291

92+
var enableStereo: Boolean = false
93+
9394
private val mAudioManager =
9495
mReactContext.getSystemService(Context.AUDIO_SERVICE) as AudioManager
9596

@@ -99,7 +100,6 @@ class AudioDeviceManager(
99100
private var audioFocusLost = false
100101

101102
private var audioFocusUtil = AudioFocusUtil(mAudioManager, this)
102-
private var audioSetupStoreUtil = AudioSetupStoreUtil(mReactContext, mAudioManager, this)
103103

104104
var callAudioRole: CallAudioRole = CallAudioRole.Communicator
105105

@@ -113,33 +113,38 @@ class AudioDeviceManager(
113113
mAudioManager.registerAudioDeviceCallback(this, null)
114114
}
115115

116+
fun setup() {
117+
if (callAudioRole == CallAudioRole.Communicator) {
118+
mAudioManager.mode = AudioManager.MODE_IN_COMMUNICATION
119+
} else {
120+
// Audio routing is handled automatically by the system in normal media mode
121+
// and bluetooth microphones may not work on some devices.
122+
mAudioManager.mode = AudioManager.MODE_NORMAL
123+
}
124+
audioFocusUtil.setup(callAudioRole, mReactContext)
125+
}
126+
116127
fun start(activity: Activity) {
117128
runInAudioThread {
129+
setup()
118130
userSelectedAudioDevice = null
119131
selectedAudioDeviceEndpoint = null
120-
audioSetupStoreUtil.storeOriginalAudioSetup()
121132
if (callAudioRole == CallAudioRole.Communicator) {
122133
// Audio routing is manually controlled by the SDK in communication media mode
123134
// and local microphone can be published
124-
mAudioManager.mode = AudioManager.MODE_IN_COMMUNICATION
125135
activity.volumeControlStream = AudioManager.STREAM_VOICE_CALL
126136
bluetoothManager.start()
127137
mAudioManager.registerAudioDeviceCallback(this, null)
128138
updateAudioDeviceState()
129139
proximityManager.start()
130140
} else {
131-
// Audio routing is handled automatically by the system in normal media mode
132-
// and bluetooth microphones may not work on some devices.
133-
mAudioManager.mode = AudioManager.MODE_NORMAL
134141
activity.volumeControlStream = AudioManager.USE_DEFAULT_STREAM_TYPE
135142
}
136-
137-
audioSetupStoreUtil.storeOriginalAudioSetup()
138143
audioFocusUtil.requestFocus(callAudioRole, mReactContext)
139144
}
140145
}
141146

142-
fun stop() {
147+
fun stop(activity: Activity) {
143148
runInAudioThread {
144149
if (callAudioRole == CallAudioRole.Communicator) {
145150
if (Build.VERSION.SDK_INT >= 31) {
@@ -150,7 +155,7 @@ class AudioDeviceManager(
150155
bluetoothManager.stop()
151156
proximityManager.stop()
152157
}
153-
audioSetupStoreUtil.restoreOriginalAudioSetup()
158+
activity.volumeControlStream = AudioManager.USE_DEFAULT_STREAM_TYPE
154159
audioFocusUtil.abandonFocus()
155160
}
156161
}

packages/react-native-sdk/android/src/main/java/com/streamvideo/reactnative/audio/utils/AudioFocusUtil.kt

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import android.media.AudioAttributes
44
import android.media.AudioFocusRequest
55
import android.media.AudioManager
66
import android.os.Build
7+
import androidx.annotation.RequiresApi
78
import com.facebook.react.bridge.ReactContext
89
import com.oney.WebRTCModule.WebRTCModule
910
import org.webrtc.audio.JavaAudioDeviceModule
@@ -25,18 +26,31 @@ class AudioFocusUtil(
2526
private lateinit var request: AudioFocusRequest
2627

2728

29+
@RequiresApi(26)
30+
private fun getAudioAttributes(mode: CallAudioRole): AudioAttributes {
31+
return AudioAttributes.Builder()
32+
.setUsage(if (mode == CallAudioRole.Communicator) AudioAttributes.USAGE_VOICE_COMMUNICATION else AudioAttributes.USAGE_MEDIA)
33+
.setContentType(if (mode == CallAudioRole.Communicator) AudioAttributes.CONTENT_TYPE_SPEECH else AudioAttributes.CONTENT_TYPE_MUSIC)
34+
.build()
35+
}
36+
37+
private fun setup(audioAttributes: AudioAttributes, reactContext: ReactContext) {
38+
val webRTCModule = reactContext.getNativeModule(WebRTCModule::class.java)!!
39+
val adm = webRTCModule.audioDeviceModule as JavaAudioDeviceModule
40+
WebRtcAudioTrackHelper.setAudioOutputAttributes(adm, audioAttributes)
41+
}
42+
43+
fun setup(mode: CallAudioRole, reactContext: ReactContext) {
44+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
45+
val audioAttributes = getAudioAttributes(mode)
46+
setup(audioAttributes, reactContext)
47+
}
48+
}
2849

2950
fun requestFocus(mode: CallAudioRole, reactContext: ReactContext) {
3051
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
31-
val audioAttributes = AudioAttributes.Builder()
32-
.setUsage(if (mode == CallAudioRole.Communicator) AudioAttributes.USAGE_VOICE_COMMUNICATION else AudioAttributes.USAGE_MEDIA)
33-
.setContentType(if (mode == CallAudioRole.Communicator) AudioAttributes.CONTENT_TYPE_SPEECH else AudioAttributes.CONTENT_TYPE_MUSIC)
34-
.build()
35-
36-
// 1. set audio attributes to webrtc
37-
val webRTCModule = reactContext.getNativeModule(WebRTCModule::class.java)!!
38-
val adm = webRTCModule.audioDeviceModule as JavaAudioDeviceModule
39-
WebRtcAudioTrackHelper.setAudioOutputAttributes(adm, audioAttributes)
52+
val audioAttributes = getAudioAttributes(mode)
53+
setup(audioAttributes, reactContext)
4054

4155
// 2. request the audio focus with the audio attributes
4256
request = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT)

packages/react-native-sdk/android/src/main/java/com/streamvideo/reactnative/audio/utils/AudioSetupStoreUtil.kt

Lines changed: 0 additions & 41 deletions
This file was deleted.

packages/react-native-sdk/android/src/main/java/com/streamvideo/reactnative/callmanager/StreamInCallManagerModule.kt

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,22 @@ class StreamInCallManagerModule(reactContext: ReactApplicationContext) :
8080
}
8181
}
8282

83+
@ReactMethod
84+
fun setEnableStereoAudioOutput(enabled: Boolean) {
85+
AudioDeviceManager.runInAudioThread {
86+
if (audioManagerActivated) {
87+
Log.e(TAG, "setAudioRole(): AudioManager is already activated and so enabling stereo audio output cannot be changed")
88+
return@runInAudioThread
89+
}
90+
mAudioDeviceManager.enableStereo = enabled
91+
}
92+
}
93+
94+
@ReactMethod
95+
fun setup() {
96+
mAudioDeviceManager.setup()
97+
}
98+
8399
@ReactMethod
84100
fun start() {
85101
AudioDeviceManager.runInAudioThread {
@@ -99,7 +115,9 @@ class StreamInCallManagerModule(reactContext: ReactApplicationContext) :
99115
AudioDeviceManager.runInAudioThread {
100116
if (audioManagerActivated) {
101117
Log.d(TAG, "stop() mAudioDeviceManager")
102-
mAudioDeviceManager.stop()
118+
reactApplicationContext.currentActivity?.let {
119+
mAudioDeviceManager.stop(it)
120+
}
103121
setMicrophoneMute(false)
104122
setKeepScreenOn(false)
105123
audioManagerActivated = false

packages/react-native-sdk/ios/StreamInCallManager.m

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ @interface RCT_EXTERN_MODULE(StreamInCallManager, RCTEventEmitter)
99

1010
RCT_EXTERN_METHOD(setEnableStereoAudioOutput:(BOOL)enable)
1111

12+
RCT_EXTERN_METHOD(setup)
13+
1214
RCT_EXTERN_METHOD(start)
1315

1416
RCT_EXTERN_METHOD(stop)

0 commit comments

Comments
 (0)