@stream-io/video-react-native-sdk 1.21.2 → 1.22.1-alpha.0
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/android/gradle.properties +3 -3
- package/android/src/main/java/com/streamvideo/reactnative/StreamVideoReactNativeModule.kt +10 -0
- package/android/src/main/java/com/streamvideo/reactnative/StreamVideoReactNativePackage.kt +2 -1
- package/android/src/main/java/com/streamvideo/reactnative/audio/AudioDeviceManager.kt +592 -0
- package/android/src/main/java/com/streamvideo/reactnative/audio/BluetoothManager.kt +755 -0
- package/android/src/main/java/com/streamvideo/reactnative/audio/utils/AudioDeviceEndpointUtils.kt +192 -0
- package/android/src/main/java/com/streamvideo/reactnative/audio/utils/AudioFocusUtil.kt +62 -0
- package/android/src/main/java/com/streamvideo/reactnative/audio/utils/AudioManagerUtil.kt +159 -0
- package/android/src/main/java/com/streamvideo/reactnative/audio/utils/AudioSetupStoreUtil.kt +41 -0
- package/android/src/main/java/com/streamvideo/reactnative/audio/utils/WebRtcAudioUtils.kt +250 -0
- package/android/src/main/java/com/streamvideo/reactnative/callmanager/StreamInCallManagerModule.kt +191 -0
- package/android/src/main/java/com/streamvideo/reactnative/model/AudioDeviceEndpoint.kt +136 -0
- package/android/src/main/java/org/webrtc/audio/WebRtcAudioTrackHelper.kt +12 -0
- package/dist/commonjs/components/Call/CallContent/CallContent.js +13 -9
- package/dist/commonjs/components/Call/CallContent/CallContent.js.map +1 -1
- package/dist/commonjs/components/Call/CallContent/RTCViewPipIOS.js +9 -2
- package/dist/commonjs/components/Call/CallContent/RTCViewPipIOS.js.map +1 -1
- package/dist/commonjs/components/Call/CallContent/RTCViewPipNative.js +3 -0
- package/dist/commonjs/components/Call/CallContent/RTCViewPipNative.js.map +1 -1
- package/dist/commonjs/components/Livestream/HostLivestream/HostLivestream.js +10 -6
- package/dist/commonjs/components/Livestream/HostLivestream/HostLivestream.js.map +1 -1
- package/dist/commonjs/components/Livestream/LivestreamControls/ViewerLivestreamControls.js +8 -4
- package/dist/commonjs/components/Livestream/LivestreamControls/ViewerLivestreamControls.js.map +1 -1
- package/dist/commonjs/components/Livestream/LivestreamLayout/LivestreamLayout.js +26 -27
- package/dist/commonjs/components/Livestream/LivestreamLayout/LivestreamLayout.js.map +1 -1
- package/dist/commonjs/components/Livestream/ViewerLivestream/ViewerLivestream.js +10 -6
- package/dist/commonjs/components/Livestream/ViewerLivestream/ViewerLivestream.js.map +1 -1
- package/dist/commonjs/hooks/useIsInPiPMode.js +3 -3
- package/dist/commonjs/hooks/useIsInPiPMode.js.map +1 -1
- package/dist/commonjs/hooks/usePermissionNotification.js +5 -5
- package/dist/commonjs/hooks/usePermissionNotification.js.map +1 -1
- package/dist/commonjs/index.js +12 -0
- package/dist/commonjs/index.js.map +1 -1
- package/dist/commonjs/modules/call-manager/CallManager.js +113 -0
- package/dist/commonjs/modules/call-manager/CallManager.js.map +1 -0
- package/dist/commonjs/modules/call-manager/PrevLibDetection.js +18 -0
- package/dist/commonjs/modules/call-manager/PrevLibDetection.js.map +1 -0
- package/dist/commonjs/modules/call-manager/index.js +24 -0
- package/dist/commonjs/modules/call-manager/index.js.map +1 -0
- package/dist/commonjs/modules/call-manager/native-module.d.js +4 -0
- package/dist/commonjs/modules/call-manager/native-module.d.js.map +1 -0
- package/dist/commonjs/modules/call-manager/types.js +2 -0
- package/dist/commonjs/modules/call-manager/types.js.map +1 -0
- package/dist/commonjs/providers/StreamCall/AppStateListener.js +5 -5
- package/dist/commonjs/providers/StreamCall/AppStateListener.js.map +1 -1
- package/dist/commonjs/theme/theme.js.map +1 -1
- package/dist/commonjs/utils/internal/rxSubjects.js +2 -2
- package/dist/commonjs/utils/internal/rxSubjects.js.map +1 -1
- package/dist/commonjs/version.js +1 -1
- package/dist/commonjs/version.js.map +1 -1
- package/dist/module/components/Call/CallContent/CallContent.js +14 -9
- package/dist/module/components/Call/CallContent/CallContent.js.map +1 -1
- package/dist/module/components/Call/CallContent/RTCViewPipIOS.js +9 -2
- package/dist/module/components/Call/CallContent/RTCViewPipIOS.js.map +1 -1
- package/dist/module/components/Call/CallContent/RTCViewPipNative.js +3 -0
- package/dist/module/components/Call/CallContent/RTCViewPipNative.js.map +1 -1
- package/dist/module/components/Livestream/HostLivestream/HostLivestream.js +10 -5
- package/dist/module/components/Livestream/HostLivestream/HostLivestream.js.map +1 -1
- package/dist/module/components/Livestream/LivestreamControls/ViewerLivestreamControls.js +9 -4
- package/dist/module/components/Livestream/LivestreamControls/ViewerLivestreamControls.js.map +1 -1
- package/dist/module/components/Livestream/LivestreamLayout/LivestreamLayout.js +26 -27
- package/dist/module/components/Livestream/LivestreamLayout/LivestreamLayout.js.map +1 -1
- package/dist/module/components/Livestream/ViewerLivestream/ViewerLivestream.js +10 -5
- package/dist/module/components/Livestream/ViewerLivestream/ViewerLivestream.js.map +1 -1
- package/dist/module/hooks/useIsInPiPMode.js +4 -4
- package/dist/module/hooks/useIsInPiPMode.js.map +1 -1
- package/dist/module/hooks/usePermissionNotification.js +7 -6
- package/dist/module/hooks/usePermissionNotification.js.map +1 -1
- package/dist/module/icons/Back.js +1 -1
- package/dist/module/icons/Back.js.map +1 -1
- package/dist/module/icons/CameraSwitch.js +1 -1
- package/dist/module/icons/CameraSwitch.js.map +1 -1
- package/dist/module/icons/Mic.js +1 -1
- package/dist/module/icons/Mic.js.map +1 -1
- package/dist/module/icons/MicOff.js +1 -1
- package/dist/module/icons/MicOff.js.map +1 -1
- package/dist/module/icons/Phone.js +1 -1
- package/dist/module/icons/Phone.js.map +1 -1
- package/dist/module/icons/PinVertical.js +1 -1
- package/dist/module/icons/PinVertical.js.map +1 -1
- package/dist/module/icons/Reaction.js +1 -1
- package/dist/module/icons/Reaction.js.map +1 -1
- package/dist/module/icons/Spotlight.js +1 -1
- package/dist/module/icons/Spotlight.js.map +1 -1
- package/dist/module/icons/Video.js +1 -1
- package/dist/module/icons/Video.js.map +1 -1
- package/dist/module/icons/VideoSlash.js +1 -1
- package/dist/module/icons/VideoSlash.js.map +1 -1
- package/dist/module/index.js +1 -0
- package/dist/module/index.js.map +1 -1
- package/dist/module/modules/call-manager/CallManager.js +106 -0
- package/dist/module/modules/call-manager/CallManager.js.map +1 -0
- package/dist/module/modules/call-manager/PrevLibDetection.js +12 -0
- package/dist/module/modules/call-manager/PrevLibDetection.js.map +1 -0
- package/dist/module/modules/call-manager/index.js +4 -0
- package/dist/module/modules/call-manager/index.js.map +1 -0
- package/dist/module/modules/call-manager/native-module.d.js +2 -0
- package/dist/module/modules/call-manager/native-module.d.js.map +1 -0
- package/dist/module/modules/call-manager/types.js +2 -0
- package/dist/module/modules/call-manager/types.js.map +1 -0
- package/dist/module/providers/StreamCall/AppStateListener.js +6 -6
- package/dist/module/providers/StreamCall/AppStateListener.js.map +1 -1
- package/dist/module/theme/theme.js.map +1 -1
- package/dist/module/utils/internal/rxSubjects.js +1 -1
- package/dist/module/utils/internal/rxSubjects.js.map +1 -1
- package/dist/module/version.js +1 -1
- package/dist/module/version.js.map +1 -1
- package/dist/typescript/components/Call/CallContent/CallContent.d.ts +3 -2
- package/dist/typescript/components/Call/CallContent/CallContent.d.ts.map +1 -1
- package/dist/typescript/components/Call/CallContent/RTCViewPipIOS.d.ts +5 -0
- package/dist/typescript/components/Call/CallContent/RTCViewPipIOS.d.ts.map +1 -1
- package/dist/typescript/components/Call/CallContent/RTCViewPipNative.d.ts +6 -0
- package/dist/typescript/components/Call/CallContent/RTCViewPipNative.d.ts.map +1 -1
- package/dist/typescript/components/Livestream/HostLivestream/HostLivestream.d.ts.map +1 -1
- package/dist/typescript/components/Livestream/LivestreamControls/ViewerLivestreamControls.d.ts.map +1 -1
- package/dist/typescript/components/Livestream/LivestreamLayout/LivestreamLayout.d.ts.map +1 -1
- package/dist/typescript/components/Livestream/ViewerLivestream/ViewerLivestream.d.ts.map +1 -1
- package/dist/typescript/hooks/usePermissionNotification.d.ts.map +1 -1
- package/dist/typescript/icons/Back.d.ts +1 -1
- package/dist/typescript/icons/Back.d.ts.map +1 -1
- package/dist/typescript/icons/BadNetwork.d.ts +1 -1
- package/dist/typescript/icons/BadNetwork.d.ts.map +1 -1
- package/dist/typescript/icons/CameraSwitch.d.ts +1 -1
- package/dist/typescript/icons/CameraSwitch.d.ts.map +1 -1
- package/dist/typescript/icons/LivestreamControls.d.ts +1 -1
- package/dist/typescript/icons/LivestreamControls.d.ts.map +1 -1
- package/dist/typescript/icons/Lock.d.ts +1 -1
- package/dist/typescript/icons/Lock.d.ts.map +1 -1
- package/dist/typescript/icons/Maximize.d.ts +1 -1
- package/dist/typescript/icons/Maximize.d.ts.map +1 -1
- package/dist/typescript/icons/Mic.d.ts +1 -1
- package/dist/typescript/icons/Mic.d.ts.map +1 -1
- package/dist/typescript/icons/MicOff.d.ts +1 -1
- package/dist/typescript/icons/MicOff.d.ts.map +1 -1
- package/dist/typescript/icons/Phone.d.ts +1 -1
- package/dist/typescript/icons/Phone.d.ts.map +1 -1
- package/dist/typescript/icons/PhoneDown.d.ts +1 -1
- package/dist/typescript/icons/PhoneDown.d.ts.map +1 -1
- package/dist/typescript/icons/PinVertical.d.ts +1 -1
- package/dist/typescript/icons/PinVertical.d.ts.map +1 -1
- package/dist/typescript/icons/Reaction.d.ts +1 -1
- package/dist/typescript/icons/Reaction.d.ts.map +1 -1
- package/dist/typescript/icons/ScreenShare.d.ts +1 -1
- package/dist/typescript/icons/ScreenShare.d.ts.map +1 -1
- package/dist/typescript/icons/ScreenShareIndicator.d.ts +1 -1
- package/dist/typescript/icons/ScreenShareIndicator.d.ts.map +1 -1
- package/dist/typescript/icons/Spotlight.d.ts +1 -1
- package/dist/typescript/icons/Spotlight.d.ts.map +1 -1
- package/dist/typescript/icons/StopScreenShare.d.ts +1 -1
- package/dist/typescript/icons/StopScreenShare.d.ts.map +1 -1
- package/dist/typescript/icons/Video.d.ts +1 -1
- package/dist/typescript/icons/Video.d.ts.map +1 -1
- package/dist/typescript/icons/VideoSlash.d.ts +1 -1
- package/dist/typescript/icons/VideoSlash.d.ts.map +1 -1
- package/dist/typescript/index.d.ts +1 -0
- package/dist/typescript/index.d.ts.map +1 -1
- package/dist/typescript/modules/call-manager/CallManager.d.ts +67 -0
- package/dist/typescript/modules/call-manager/CallManager.d.ts.map +1 -0
- package/dist/typescript/modules/call-manager/PrevLibDetection.d.ts +13 -0
- package/dist/typescript/modules/call-manager/PrevLibDetection.d.ts.map +1 -0
- package/dist/typescript/modules/call-manager/index.d.ts +4 -0
- package/dist/typescript/modules/call-manager/index.d.ts.map +1 -0
- package/dist/typescript/modules/call-manager/types.d.ts +15 -0
- package/dist/typescript/modules/call-manager/types.d.ts.map +1 -0
- package/dist/typescript/providers/StreamCall/AppStateListener.d.ts.map +1 -1
- package/dist/typescript/theme/theme.d.ts +1 -2
- package/dist/typescript/theme/theme.d.ts.map +1 -1
- package/dist/typescript/utils/internal/rxSubjects.d.ts +1 -1
- package/dist/typescript/utils/internal/rxSubjects.d.ts.map +1 -1
- package/dist/typescript/version.d.ts +1 -1
- package/dist/typescript/version.d.ts.map +1 -1
- package/ios/PictureInPicture/StreamPictureInPictureController.swift +5 -0
- package/ios/RTCViewPip.swift +15 -0
- package/ios/RTCViewPipManager.mm +1 -0
- package/ios/StreamInCallManager.m +26 -0
- package/ios/StreamInCallManager.swift +303 -0
- package/ios/StreamVideoReactNative-Bridging-Header.h +1 -0
- package/ios/StreamVideoReactNative.m +6 -5
- package/ios/StreamVideoReactNative.xcodeproj/project.xcworkspace/xcuserdata/santhoshvaiyapuri.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/ios/StreamVideoReactNative.xcodeproj/xcuserdata/santhoshvaiyapuri.xcuserdatad/xcschemes/xcschememanagement.plist +14 -0
- package/package.json +33 -35
- package/src/components/Call/CallContent/CallContent.tsx +14 -10
- package/src/components/Call/CallContent/RTCViewPipIOS.tsx +17 -2
- package/src/components/Call/CallContent/RTCViewPipNative.tsx +8 -0
- package/src/components/Livestream/HostLivestream/HostLivestream.tsx +8 -3
- package/src/components/Livestream/LivestreamControls/ViewerLivestreamControls.tsx +11 -5
- package/src/components/Livestream/LivestreamLayout/LivestreamLayout.tsx +38 -29
- package/src/components/Livestream/ViewerLivestream/ViewerLivestream.tsx +8 -3
- package/src/hooks/useIsInPiPMode.tsx +4 -4
- package/src/hooks/usePermissionNotification.tsx +7 -12
- package/src/icons/Back.tsx +2 -2
- package/src/icons/BadNetwork.tsx +1 -1
- package/src/icons/CameraSwitch.tsx +2 -2
- package/src/icons/LivestreamControls.tsx +1 -1
- package/src/icons/Lock.tsx +1 -1
- package/src/icons/Maximize.tsx +1 -1
- package/src/icons/Mic.tsx +2 -2
- package/src/icons/MicOff.tsx +2 -2
- package/src/icons/Phone.tsx +2 -2
- package/src/icons/PhoneDown.tsx +1 -1
- package/src/icons/PinVertical.tsx +2 -2
- package/src/icons/Reaction.tsx +2 -2
- package/src/icons/ScreenShare.tsx +1 -1
- package/src/icons/ScreenShareIndicator.tsx +1 -1
- package/src/icons/Spotlight.tsx +2 -2
- package/src/icons/StopScreenShare.tsx +1 -1
- package/src/icons/Video.tsx +2 -2
- package/src/icons/VideoSlash.tsx +2 -2
- package/src/index.ts +1 -0
- package/src/modules/call-manager/CallManager.ts +116 -0
- package/src/modules/call-manager/PrevLibDetection.ts +27 -0
- package/src/modules/call-manager/index.ts +5 -0
- package/src/modules/call-manager/native-module.d.ts +80 -0
- package/src/modules/call-manager/types.ts +25 -0
- package/src/providers/StreamCall/AppStateListener.tsx +6 -9
- package/src/theme/theme.ts +2 -2
- package/src/utils/internal/rxSubjects.ts +1 -1
- package/src/version.ts +1 -1
- package/CHANGELOG.md +0 -2783
package/android/src/main/java/com/streamvideo/reactnative/audio/utils/AudioDeviceEndpointUtils.kt
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2023 The Android Open Source Project
|
|
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
|
+
package com.streamvideo.reactnative.audio.utils
|
|
18
|
+
|
|
19
|
+
import android.media.AudioDeviceInfo
|
|
20
|
+
import android.util.Log
|
|
21
|
+
import com.streamvideo.reactnative.model.AudioDeviceEndpoint
|
|
22
|
+
import com.streamvideo.reactnative.model.AudioDeviceEndpoint.Companion.EndpointType
|
|
23
|
+
|
|
24
|
+
internal class AudioDeviceEndpointUtils {
|
|
25
|
+
|
|
26
|
+
companion object {
|
|
27
|
+
const val BLUETOOTH_DEVICE_DEFAULT_NAME = "Bluetooth Device"
|
|
28
|
+
const val EARPIECE = "Earpiece"
|
|
29
|
+
const val SPEAKER = "Speaker"
|
|
30
|
+
const val WIRED_HEADSET = "Wired Headset"
|
|
31
|
+
const val UNKNOWN = "Unknown"
|
|
32
|
+
|
|
33
|
+
private val TAG: String = AudioDeviceEndpointUtils::class.java.simpleName.toString()
|
|
34
|
+
|
|
35
|
+
/** Gets the endpoints from AudioDeviceInfos.
|
|
36
|
+
* IMPORTANT: eliminates Earpiece if Headset is found
|
|
37
|
+
* */
|
|
38
|
+
fun getEndpointsFromAudioDeviceInfo(
|
|
39
|
+
adiArr: List<AudioDeviceInfo>?,
|
|
40
|
+
): List<AudioDeviceEndpoint> {
|
|
41
|
+
if (adiArr == null) {
|
|
42
|
+
return listOf()
|
|
43
|
+
}
|
|
44
|
+
val endpoints: MutableList<AudioDeviceEndpoint> = mutableListOf()
|
|
45
|
+
var foundWiredHeadset = false
|
|
46
|
+
val omittedDevices = StringBuilder("omitting devices =[")
|
|
47
|
+
adiArr.toList().forEach { audioDeviceInfo ->
|
|
48
|
+
val endpoint = getEndpointFromAudioDeviceInfo(audioDeviceInfo)
|
|
49
|
+
if (endpoint.type != AudioDeviceEndpoint.TYPE_UNKNOWN) {
|
|
50
|
+
if (endpoint.type == AudioDeviceEndpoint.TYPE_WIRED_HEADSET) {
|
|
51
|
+
foundWiredHeadset = true
|
|
52
|
+
}
|
|
53
|
+
endpoints.add(endpoint)
|
|
54
|
+
} else {
|
|
55
|
+
omittedDevices.append(
|
|
56
|
+
"(type=[${audioDeviceInfo.type}]," +
|
|
57
|
+
" name=[${audioDeviceInfo.productName}]),"
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
omittedDevices.append("]")
|
|
62
|
+
Log.i(TAG, omittedDevices.toString())
|
|
63
|
+
if (foundWiredHeadset) {
|
|
64
|
+
endpoints.removeIf { it.type == AudioDeviceEndpoint.TYPE_EARPIECE }
|
|
65
|
+
}
|
|
66
|
+
// Sort by endpoint type. The first element has the highest priority!
|
|
67
|
+
endpoints.sort()
|
|
68
|
+
return endpoints
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
private fun getEndpointFromAudioDeviceInfo(
|
|
73
|
+
adi: AudioDeviceInfo,
|
|
74
|
+
): AudioDeviceEndpoint {
|
|
75
|
+
val endpointDeviceName = remapAudioDeviceNameToEndpointDeviceName(adi)
|
|
76
|
+
val endpointType = remapAudioDeviceTypeToCallEndpointType(adi.type)
|
|
77
|
+
val newEndpoint =
|
|
78
|
+
AudioDeviceEndpoint(
|
|
79
|
+
endpointDeviceName,
|
|
80
|
+
endpointType,
|
|
81
|
+
adi,
|
|
82
|
+
)
|
|
83
|
+
return newEndpoint
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
internal fun remapAudioDeviceNameToEndpointDeviceName(
|
|
87
|
+
audioDeviceInfo: AudioDeviceInfo,
|
|
88
|
+
): String {
|
|
89
|
+
return when (audioDeviceInfo.type) {
|
|
90
|
+
AudioDeviceInfo.TYPE_BUILTIN_EARPIECE ->
|
|
91
|
+
EARPIECE
|
|
92
|
+
AudioDeviceInfo.TYPE_BUILTIN_SPEAKER ->
|
|
93
|
+
SPEAKER
|
|
94
|
+
AudioDeviceInfo.TYPE_WIRED_HEADSET,
|
|
95
|
+
AudioDeviceInfo.TYPE_WIRED_HEADPHONES,
|
|
96
|
+
AudioDeviceInfo.TYPE_USB_DEVICE,
|
|
97
|
+
AudioDeviceInfo.TYPE_USB_ACCESSORY,
|
|
98
|
+
AudioDeviceInfo.TYPE_USB_HEADSET ->
|
|
99
|
+
WIRED_HEADSET
|
|
100
|
+
else -> audioDeviceInfo.productName.toString()
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
internal fun remapAudioDeviceTypeToCallEndpointType(
|
|
105
|
+
audioDeviceInfoType: Int
|
|
106
|
+
): (@EndpointType Int) {
|
|
107
|
+
return when (audioDeviceInfoType) {
|
|
108
|
+
AudioDeviceInfo.TYPE_BUILTIN_EARPIECE -> AudioDeviceEndpoint.TYPE_EARPIECE
|
|
109
|
+
AudioDeviceInfo.TYPE_BUILTIN_SPEAKER -> AudioDeviceEndpoint.TYPE_SPEAKER
|
|
110
|
+
// Wired Headset Devices
|
|
111
|
+
AudioDeviceInfo.TYPE_WIRED_HEADSET,
|
|
112
|
+
AudioDeviceInfo.TYPE_WIRED_HEADPHONES,
|
|
113
|
+
AudioDeviceInfo.TYPE_USB_DEVICE,
|
|
114
|
+
AudioDeviceInfo.TYPE_USB_ACCESSORY,
|
|
115
|
+
AudioDeviceInfo.TYPE_USB_HEADSET -> AudioDeviceEndpoint.TYPE_WIRED_HEADSET
|
|
116
|
+
// Bluetooth Devices
|
|
117
|
+
AudioDeviceInfo.TYPE_BLUETOOTH_SCO,
|
|
118
|
+
AudioDeviceInfo.TYPE_BLUETOOTH_A2DP,
|
|
119
|
+
AudioDeviceInfo.TYPE_HEARING_AID,
|
|
120
|
+
AudioDeviceInfo.TYPE_BLE_HEADSET,
|
|
121
|
+
AudioDeviceInfo.TYPE_BLE_SPEAKER,
|
|
122
|
+
AudioDeviceInfo.TYPE_BLE_BROADCAST -> AudioDeviceEndpoint.TYPE_BLUETOOTH
|
|
123
|
+
// Everything else is defaulted to TYPE_UNKNOWN
|
|
124
|
+
else -> AudioDeviceEndpoint.TYPE_UNKNOWN
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
fun getSpeakerEndpoint(endpoints: List<AudioDeviceEndpoint>): AudioDeviceEndpoint? {
|
|
129
|
+
for (e in endpoints) {
|
|
130
|
+
if (e.type == AudioDeviceEndpoint.TYPE_SPEAKER) {
|
|
131
|
+
return e
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return null
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
fun isBluetoothAvailable(endpoints: List<AudioDeviceEndpoint>): Boolean {
|
|
138
|
+
for (e in endpoints) {
|
|
139
|
+
if (e.type == AudioDeviceEndpoint.TYPE_BLUETOOTH) {
|
|
140
|
+
return true
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return false
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
fun isEarpieceEndpoint(endpoint: AudioDeviceEndpoint?): Boolean {
|
|
147
|
+
if (endpoint == null) {
|
|
148
|
+
return false
|
|
149
|
+
}
|
|
150
|
+
return endpoint.type == AudioDeviceEndpoint.TYPE_EARPIECE
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
fun isSpeakerEndpoint(endpoint: AudioDeviceEndpoint?): Boolean {
|
|
154
|
+
if (endpoint == null) {
|
|
155
|
+
return false
|
|
156
|
+
}
|
|
157
|
+
return endpoint.type == AudioDeviceEndpoint.TYPE_SPEAKER
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
fun isWiredHeadsetOrBtEndpoint(endpoint: AudioDeviceEndpoint?): Boolean {
|
|
161
|
+
if (endpoint == null) {
|
|
162
|
+
return false
|
|
163
|
+
}
|
|
164
|
+
return endpoint.type == AudioDeviceEndpoint.TYPE_BLUETOOTH ||
|
|
165
|
+
endpoint.type == AudioDeviceEndpoint.TYPE_WIRED_HEADSET
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
private fun isBluetoothType(type: Int): Boolean {
|
|
169
|
+
return type == AudioDeviceEndpoint.TYPE_BLUETOOTH
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
fun endpointTypeToString(@EndpointType endpointType: Int): String {
|
|
173
|
+
return when (endpointType) {
|
|
174
|
+
AudioDeviceEndpoint.TYPE_EARPIECE -> EARPIECE
|
|
175
|
+
AudioDeviceEndpoint.TYPE_BLUETOOTH -> BLUETOOTH_DEVICE_DEFAULT_NAME
|
|
176
|
+
AudioDeviceEndpoint.TYPE_WIRED_HEADSET -> WIRED_HEADSET
|
|
177
|
+
AudioDeviceEndpoint.TYPE_SPEAKER -> SPEAKER
|
|
178
|
+
else -> UNKNOWN
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
fun endpointStringToType(endpointName: String): Int {
|
|
183
|
+
return when (endpointName) {
|
|
184
|
+
EARPIECE -> AudioDeviceEndpoint.TYPE_EARPIECE
|
|
185
|
+
WIRED_HEADSET -> AudioDeviceEndpoint.TYPE_WIRED_HEADSET
|
|
186
|
+
SPEAKER -> AudioDeviceEndpoint.TYPE_SPEAKER
|
|
187
|
+
BLUETOOTH_DEVICE_DEFAULT_NAME -> AudioDeviceEndpoint.TYPE_BLUETOOTH
|
|
188
|
+
else -> AudioDeviceEndpoint.TYPE_UNKNOWN
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
package com.streamvideo.reactnative.audio.utils
|
|
2
|
+
|
|
3
|
+
import android.media.AudioAttributes
|
|
4
|
+
import android.media.AudioFocusRequest
|
|
5
|
+
import android.media.AudioManager
|
|
6
|
+
import android.os.Build
|
|
7
|
+
import com.facebook.react.bridge.ReactContext
|
|
8
|
+
import com.oney.WebRTCModule.WebRTCModule
|
|
9
|
+
import org.webrtc.audio.JavaAudioDeviceModule
|
|
10
|
+
import org.webrtc.audio.WebRtcAudioTrackHelper
|
|
11
|
+
|
|
12
|
+
enum class CallAudioRole {
|
|
13
|
+
/* high quality audio output is prioritised */
|
|
14
|
+
Listener,
|
|
15
|
+
|
|
16
|
+
/* low latency audio output is prioritised */
|
|
17
|
+
Communicator
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
class AudioFocusUtil(
|
|
21
|
+
private val audioManager: AudioManager,
|
|
22
|
+
private val audioFocusChangeListener: AudioManager.OnAudioFocusChangeListener,
|
|
23
|
+
) {
|
|
24
|
+
|
|
25
|
+
private lateinit var request: AudioFocusRequest
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
fun requestFocus(mode: CallAudioRole, reactContext: ReactContext) {
|
|
30
|
+
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)
|
|
40
|
+
|
|
41
|
+
// 2. request the audio focus with the audio attributes
|
|
42
|
+
request = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT)
|
|
43
|
+
.setAudioAttributes(audioAttributes).setAcceptsDelayedFocusGain(true)
|
|
44
|
+
.setOnAudioFocusChangeListener(audioFocusChangeListener).build()
|
|
45
|
+
audioManager.requestAudioFocus(request)
|
|
46
|
+
} else {
|
|
47
|
+
audioManager.requestAudioFocus(
|
|
48
|
+
audioFocusChangeListener,
|
|
49
|
+
if (mode == CallAudioRole.Communicator) AudioManager.STREAM_VOICE_CALL else AudioManager.STREAM_MUSIC,
|
|
50
|
+
AudioManager.AUDIOFOCUS_GAIN_TRANSIENT,
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
fun abandonFocus() {
|
|
56
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
57
|
+
audioManager.abandonAudioFocusRequest(request)
|
|
58
|
+
} else {
|
|
59
|
+
audioManager.abandonAudioFocus(audioFocusChangeListener)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
package com.streamvideo.reactnative.audio.utils
|
|
2
|
+
|
|
3
|
+
import android.media.AudioDeviceInfo
|
|
4
|
+
import android.media.AudioManager
|
|
5
|
+
import android.os.Build
|
|
6
|
+
import android.util.Log
|
|
7
|
+
import androidx.annotation.DoNotInline
|
|
8
|
+
import androidx.annotation.RequiresApi
|
|
9
|
+
import com.streamvideo.reactnative.audio.BluetoothManager
|
|
10
|
+
import com.streamvideo.reactnative.audio.EndpointMaps
|
|
11
|
+
import com.streamvideo.reactnative.callmanager.StreamInCallManagerModule
|
|
12
|
+
import com.streamvideo.reactnative.model.AudioDeviceEndpoint
|
|
13
|
+
import com.streamvideo.reactnative.model.AudioDeviceEndpoint.Companion.EndpointType
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
internal class AudioManagerUtil {
|
|
17
|
+
companion object {
|
|
18
|
+
private val TAG: String = StreamInCallManagerModule.TAG + ":" + AudioManagerUtil::class.java.simpleName.toString()
|
|
19
|
+
|
|
20
|
+
fun getAvailableAudioDevices(audioManager: AudioManager): List<AudioDeviceInfo> {
|
|
21
|
+
return if (Build.VERSION.SDK_INT >= 31) {
|
|
22
|
+
AudioManager31PlusImpl.getDevices(audioManager)
|
|
23
|
+
} else {
|
|
24
|
+
AudioManager23PlusImpl.getDevices(audioManager)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
fun isSpeakerphoneOn(audioManager: AudioManager): Boolean {
|
|
29
|
+
return if (Build.VERSION.SDK_INT >= 31) {
|
|
30
|
+
AudioManager31PlusImpl.isSpeakerphoneOn(audioManager)
|
|
31
|
+
} else {
|
|
32
|
+
AudioManager23PlusImpl.isSpeakerphoneOn(audioManager)
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Switch the device endpoint type.
|
|
38
|
+
* @return true if the device endpoint type is successfully switched.
|
|
39
|
+
*/
|
|
40
|
+
fun switchDeviceEndpointType(@EndpointType deviceType: Int,
|
|
41
|
+
endpointMaps: EndpointMaps,
|
|
42
|
+
audioManager: AudioManager,
|
|
43
|
+
bluetoothManager: BluetoothManager): AudioDeviceEndpoint? {
|
|
44
|
+
return if (Build.VERSION.SDK_INT >= 31) {
|
|
45
|
+
AudioManager31PlusImpl.switchDeviceEndpointType(deviceType, endpointMaps, audioManager, bluetoothManager)
|
|
46
|
+
} else {
|
|
47
|
+
AudioManager23PlusImpl.switchDeviceEndpointType(deviceType, endpointMaps, audioManager, bluetoothManager)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
@RequiresApi(31)
|
|
53
|
+
object AudioManager31PlusImpl {
|
|
54
|
+
@JvmStatic
|
|
55
|
+
@DoNotInline
|
|
56
|
+
fun getDevices(audioManager: AudioManager): List<AudioDeviceInfo> {
|
|
57
|
+
return audioManager.availableCommunicationDevices
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@JvmStatic
|
|
61
|
+
@DoNotInline
|
|
62
|
+
fun isSpeakerphoneOn(audioManager: AudioManager): Boolean {
|
|
63
|
+
val endpoint = AudioDeviceEndpointUtils.remapAudioDeviceTypeToCallEndpointType(audioManager.communicationDevice?.type ?: AudioDeviceInfo.TYPE_UNKNOWN)
|
|
64
|
+
return endpoint == AudioDeviceEndpoint.TYPE_SPEAKER
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
@JvmStatic
|
|
68
|
+
@DoNotInline
|
|
69
|
+
fun switchDeviceEndpointType(@EndpointType deviceType: Int,
|
|
70
|
+
endpointMaps: EndpointMaps,
|
|
71
|
+
audioManager: AudioManager,
|
|
72
|
+
bluetoothManager: BluetoothManager): AudioDeviceEndpoint? {
|
|
73
|
+
audioManager.mode = AudioManager.MODE_IN_COMMUNICATION
|
|
74
|
+
when (deviceType) {
|
|
75
|
+
AudioDeviceEndpoint.TYPE_BLUETOOTH -> {
|
|
76
|
+
val didSwitch = bluetoothManager.startScoAudio()
|
|
77
|
+
if (didSwitch) {
|
|
78
|
+
return endpointMaps.bluetoothEndpoints[bluetoothManager.getDeviceName()]
|
|
79
|
+
}
|
|
80
|
+
return null
|
|
81
|
+
}
|
|
82
|
+
AudioDeviceEndpoint.TYPE_WIRED_HEADSET, AudioDeviceEndpoint.TYPE_EARPIECE -> {
|
|
83
|
+
endpointMaps.nonBluetoothEndpoints.values.firstOrNull {
|
|
84
|
+
it.type == deviceType
|
|
85
|
+
}?.let {
|
|
86
|
+
audioManager.setCommunicationDevice(it.deviceInfo)
|
|
87
|
+
bluetoothManager.updateDevice()
|
|
88
|
+
return endpointMaps.nonBluetoothEndpoints[deviceType]
|
|
89
|
+
}
|
|
90
|
+
return null
|
|
91
|
+
}
|
|
92
|
+
AudioDeviceEndpoint.TYPE_SPEAKER -> {
|
|
93
|
+
val speakerDevice = endpointMaps.nonBluetoothEndpoints[AudioDeviceEndpoint.TYPE_SPEAKER]
|
|
94
|
+
speakerDevice?.let {
|
|
95
|
+
audioManager.setCommunicationDevice(it.deviceInfo)
|
|
96
|
+
bluetoothManager.updateDevice()
|
|
97
|
+
return speakerDevice
|
|
98
|
+
}
|
|
99
|
+
return null
|
|
100
|
+
}
|
|
101
|
+
else -> {
|
|
102
|
+
Log.e(TAG, "switchDeviceEndpointType(): unknown device type requested")
|
|
103
|
+
return null
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
@Suppress("DEPRECATION")
|
|
110
|
+
object AudioManager23PlusImpl {
|
|
111
|
+
@JvmStatic
|
|
112
|
+
@DoNotInline
|
|
113
|
+
fun getDevices(audioManager: AudioManager): List<AudioDeviceInfo> {
|
|
114
|
+
return audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS).toList()
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
@JvmStatic
|
|
118
|
+
@DoNotInline
|
|
119
|
+
fun isSpeakerphoneOn(audioManager: AudioManager): Boolean {
|
|
120
|
+
return audioManager.isSpeakerphoneOn
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
@JvmStatic
|
|
124
|
+
@DoNotInline
|
|
125
|
+
fun switchDeviceEndpointType(@EndpointType deviceType: Int,
|
|
126
|
+
endpointMaps: EndpointMaps,
|
|
127
|
+
audioManager: AudioManager,
|
|
128
|
+
bluetoothManager: BluetoothManager): AudioDeviceEndpoint? {
|
|
129
|
+
audioManager.mode = AudioManager.MODE_IN_COMMUNICATION
|
|
130
|
+
when (deviceType) {
|
|
131
|
+
AudioDeviceEndpoint.TYPE_BLUETOOTH -> {
|
|
132
|
+
audioManager.setSpeakerphoneOn(false)
|
|
133
|
+
val didSwitch = bluetoothManager.startScoAudio()
|
|
134
|
+
if (didSwitch) {
|
|
135
|
+
// NOTE: SCO connection may fail after timeout, how to catch that on older platforms?
|
|
136
|
+
return endpointMaps.bluetoothEndpoints[bluetoothManager.getDeviceName()]
|
|
137
|
+
}
|
|
138
|
+
return null
|
|
139
|
+
}
|
|
140
|
+
AudioDeviceEndpoint.TYPE_WIRED_HEADSET, AudioDeviceEndpoint.TYPE_EARPIECE -> {
|
|
141
|
+
// NOTE: If wired headset is present,
|
|
142
|
+
// earpiece is always omitted even if chosen
|
|
143
|
+
bluetoothManager.stopScoAudio()
|
|
144
|
+
audioManager.setSpeakerphoneOn(false)
|
|
145
|
+
return endpointMaps.nonBluetoothEndpoints[deviceType]
|
|
146
|
+
}
|
|
147
|
+
AudioDeviceEndpoint.TYPE_SPEAKER -> {
|
|
148
|
+
bluetoothManager.stopScoAudio()
|
|
149
|
+
audioManager.setSpeakerphoneOn(true)
|
|
150
|
+
return endpointMaps.nonBluetoothEndpoints[AudioDeviceEndpoint.TYPE_SPEAKER]
|
|
151
|
+
}
|
|
152
|
+
else -> {
|
|
153
|
+
Log.e(TAG, "switchDeviceEndpointType(): unknown device type requested")
|
|
154
|
+
return null
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
package com.streamvideo.reactnative.audio.utils
|
|
2
|
+
|
|
3
|
+
import android.media.AudioManager
|
|
4
|
+
import android.util.Log
|
|
5
|
+
import com.facebook.react.bridge.ReactContext
|
|
6
|
+
import com.streamvideo.reactnative.audio.AudioDeviceManager
|
|
7
|
+
import com.streamvideo.reactnative.callmanager.StreamInCallManagerModule.Companion.TAG
|
|
8
|
+
|
|
9
|
+
class AudioSetupStoreUtil(
|
|
10
|
+
private val mReactContext: ReactContext,
|
|
11
|
+
private val mAudioManager: AudioManager,
|
|
12
|
+
private val mAudioDeviceManager: AudioDeviceManager
|
|
13
|
+
) {
|
|
14
|
+
private var isOrigAudioSetupStored = false
|
|
15
|
+
private var origIsSpeakerPhoneOn = false
|
|
16
|
+
private var origIsMicrophoneMute = false
|
|
17
|
+
private var origAudioMode = AudioManager.MODE_NORMAL
|
|
18
|
+
|
|
19
|
+
fun storeOriginalAudioSetup() {
|
|
20
|
+
if (!isOrigAudioSetupStored) {
|
|
21
|
+
origAudioMode = mAudioManager.mode
|
|
22
|
+
origIsSpeakerPhoneOn = AudioManagerUtil.isSpeakerphoneOn(mAudioManager)
|
|
23
|
+
origIsMicrophoneMute = mAudioManager.isMicrophoneMute
|
|
24
|
+
isOrigAudioSetupStored = true
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
fun restoreOriginalAudioSetup() {
|
|
29
|
+
if (isOrigAudioSetupStored) {
|
|
30
|
+
if (origIsSpeakerPhoneOn) {
|
|
31
|
+
mAudioDeviceManager.setSpeakerphoneOn(true)
|
|
32
|
+
}
|
|
33
|
+
mAudioManager.setMicrophoneMute(origIsMicrophoneMute)
|
|
34
|
+
mAudioManager.mode = origAudioMode
|
|
35
|
+
mReactContext.currentActivity?.apply {
|
|
36
|
+
volumeControlStream = AudioManager.USE_DEFAULT_STREAM_TYPE
|
|
37
|
+
}
|
|
38
|
+
isOrigAudioSetupStored = false
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|