@fishjam-cloud/react-native-client 0.23.0 → 0.25.0-rc.1
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/README.md +56 -15
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/overrides/RTCPeerConnection.d.ts +8 -0
- package/dist/overrides/RTCPeerConnection.d.ts.map +1 -0
- package/dist/overrides/RTCPeerConnection.js +16 -0
- package/dist/overrides/RTCView.d.ts +11 -0
- package/dist/overrides/RTCView.d.ts.map +1 -0
- package/dist/overrides/RTCView.js +21 -0
- package/dist/polyfills/local-storage.d.ts +10 -0
- package/dist/polyfills/local-storage.d.ts.map +1 -0
- package/dist/polyfills/local-storage.js +24 -0
- package/{build/hooks → dist}/useForegroundService.d.ts +10 -10
- package/dist/useForegroundService.d.ts.map +1 -0
- package/dist/useForegroundService.js +10 -0
- package/dist/webrtc-polyfill.d.ts +2 -0
- package/dist/webrtc-polyfill.d.ts.map +1 -0
- package/dist/webrtc-polyfill.js +14 -0
- package/package.json +44 -92
- package/plugin/broadcastExtensionFiles/Atomic.swift +37 -0
- package/plugin/broadcastExtensionFiles/DarwinNotificationCenter.swift +29 -0
- package/plugin/broadcastExtensionFiles/Info.plist +2 -2
- package/plugin/broadcastExtensionFiles/SampleHandler.swift +104 -0
- package/plugin/broadcastExtensionFiles/SampleUploader.swift +146 -0
- package/plugin/broadcastExtensionFiles/SocketConnection.swift +198 -0
- package/plugin/build/types.d.ts +5 -3
- package/plugin/build/withFishjam.d.ts +31 -2
- package/plugin/build/withFishjam.js +32 -6
- package/plugin/build/withFishjamAndroid.d.ts +2 -2
- package/plugin/build/withFishjamAndroid.js +60 -13
- package/plugin/build/withFishjamIos.d.ts +3 -8
- package/plugin/build/withFishjamIos.js +54 -69
- package/plugin/src/types.ts +19 -0
- package/plugin/src/withFishjam.ts +42 -0
- package/plugin/src/withFishjamAndroid.ts +112 -0
- package/plugin/src/withFishjamIos.ts +336 -0
- package/plugin/tsconfig.json +9 -0
- package/plugin/tsconfig.tsbuildinfo +1 -0
- package/LICENSE.txt +0 -201
- package/android/build.gradle +0 -95
- package/android/src/main/AndroidManifest.xml +0 -2
- package/android/src/main/java/io/fishjam/reactnative/AudioDeviceKind.kt +0 -34
- package/android/src/main/java/io/fishjam/reactnative/AudioSwitchManager.kt +0 -61
- package/android/src/main/java/io/fishjam/reactnative/EmitableEvents.kt +0 -126
- package/android/src/main/java/io/fishjam/reactnative/Errors.kt +0 -31
- package/android/src/main/java/io/fishjam/reactnative/PipContainerView.kt +0 -282
- package/android/src/main/java/io/fishjam/reactnative/PipContainerViewModule.kt +0 -41
- package/android/src/main/java/io/fishjam/reactnative/PipTrackSelector.kt +0 -98
- package/android/src/main/java/io/fishjam/reactnative/PipViewFactory.kt +0 -186
- package/android/src/main/java/io/fishjam/reactnative/RNFishjamClient.kt +0 -1001
- package/android/src/main/java/io/fishjam/reactnative/RNFishjamClientModule.kt +0 -358
- package/android/src/main/java/io/fishjam/reactnative/Utils.kt +0 -11
- package/android/src/main/java/io/fishjam/reactnative/VideoPreviewView.kt +0 -40
- package/android/src/main/java/io/fishjam/reactnative/VideoPreviewViewModule.kt +0 -22
- package/android/src/main/java/io/fishjam/reactnative/VideoRendererView.kt +0 -76
- package/android/src/main/java/io/fishjam/reactnative/VideoRendererViewModule.kt +0 -33
- package/android/src/main/java/io/fishjam/reactnative/VideoView.kt +0 -257
- package/android/src/main/java/io/fishjam/reactnative/extensions/CaptureDevice.kt +0 -17
- package/android/src/main/java/io/fishjam/reactnative/foregroundService/FishjamForegroundService.kt +0 -101
- package/android/src/main/java/io/fishjam/reactnative/foregroundService/ForegroundServiceManager.kt +0 -118
- package/android/src/main/java/io/fishjam/reactnative/foregroundService/ForegroundServiceState.kt +0 -46
- package/android/src/main/java/io/fishjam/reactnative/helpers/PictureInPictureHelperFragment.kt +0 -20
- package/android/src/main/java/io/fishjam/reactnative/managers/ListenerManager.kt +0 -24
- package/android/src/main/java/io/fishjam/reactnative/managers/LocalCameraTracksChangedListenersManager.kt +0 -8
- package/android/src/main/java/io/fishjam/reactnative/managers/LocalTracksSwitchListenersManager.kt +0 -17
- package/android/src/main/java/io/fishjam/reactnative/managers/TracksUpdateListenersManager.kt +0 -7
- package/android/src/main/java/io/fishjam/reactnative/utils/PermissionUtils.kt +0 -45
- package/build/RNFishjamClientModule.d.ts +0 -106
- package/build/RNFishjamClientModule.d.ts.map +0 -1
- package/build/RNFishjamClientModule.js +0 -21
- package/build/RNFishjamClientModule.js.map +0 -1
- package/build/common/metadata.d.ts +0 -9
- package/build/common/metadata.d.ts.map +0 -1
- package/build/common/metadata.js +0 -11
- package/build/common/metadata.js.map +0 -1
- package/build/components/FishjamRoom/GridTrackItem.d.ts +0 -12
- package/build/components/FishjamRoom/GridTrackItem.d.ts.map +0 -1
- package/build/components/FishjamRoom/GridTrackItem.js +0 -56
- package/build/components/FishjamRoom/GridTrackItem.js.map +0 -1
- package/build/components/FishjamRoom/VideosGrid.d.ts +0 -3
- package/build/components/FishjamRoom/VideosGrid.d.ts.map +0 -1
- package/build/components/FishjamRoom/VideosGrid.js +0 -20
- package/build/components/FishjamRoom/VideosGrid.js.map +0 -1
- package/build/components/FishjamRoom/index.d.ts +0 -33
- package/build/components/FishjamRoom/index.d.ts.map +0 -1
- package/build/components/FishjamRoom/index.js +0 -53
- package/build/components/FishjamRoom/index.js.map +0 -1
- package/build/components/FishjamRoom/parsePeersToTracks.d.ts +0 -4
- package/build/components/FishjamRoom/parsePeersToTracks.d.ts.map +0 -1
- package/build/components/FishjamRoom/parsePeersToTracks.js +0 -37
- package/build/components/FishjamRoom/parsePeersToTracks.js.map +0 -1
- package/build/components/PipContainerView.d.ts +0 -48
- package/build/components/PipContainerView.d.ts.map +0 -1
- package/build/components/PipContainerView.js +0 -34
- package/build/components/PipContainerView.js.map +0 -1
- package/build/components/VideoPreviewView.d.ts +0 -28
- package/build/components/VideoPreviewView.d.ts.map +0 -1
- package/build/components/VideoPreviewView.js +0 -17
- package/build/components/VideoPreviewView.js.map +0 -1
- package/build/components/VideoRendererView.d.ts +0 -39
- package/build/components/VideoRendererView.d.ts.map +0 -1
- package/build/components/VideoRendererView.js +0 -25
- package/build/components/VideoRendererView.js.map +0 -1
- package/build/consts/index.d.ts +0 -5
- package/build/consts/index.d.ts.map +0 -1
- package/build/consts/index.js +0 -8
- package/build/consts/index.js.map +0 -1
- package/build/debug/common/webRTC.d.ts +0 -9
- package/build/debug/common/webRTC.d.ts.map +0 -1
- package/build/debug/common/webRTC.js +0 -11
- package/build/debug/common/webRTC.js.map +0 -1
- package/build/debug/index.d.ts +0 -4
- package/build/debug/index.d.ts.map +0 -1
- package/build/debug/index.js +0 -3
- package/build/debug/index.js.map +0 -1
- package/build/debug/stats/types.d.ts +0 -55
- package/build/debug/stats/types.d.ts.map +0 -1
- package/build/debug/stats/types.js +0 -2
- package/build/debug/stats/types.js.map +0 -1
- package/build/debug/stats/useRTCStatistics.d.ts +0 -9
- package/build/debug/stats/useRTCStatistics.d.ts.map +0 -1
- package/build/debug/stats/useRTCStatistics.js +0 -79
- package/build/debug/stats/useRTCStatistics.js.map +0 -1
- package/build/hooks/internal/useFishjamEvent.d.ts +0 -4
- package/build/hooks/internal/useFishjamEvent.d.ts.map +0 -1
- package/build/hooks/internal/useFishjamEvent.js +0 -38
- package/build/hooks/internal/useFishjamEvent.js.map +0 -1
- package/build/hooks/internal/useFishjamEventState.d.ts +0 -3
- package/build/hooks/internal/useFishjamEventState.d.ts.map +0 -1
- package/build/hooks/internal/useFishjamEventState.js +0 -18
- package/build/hooks/internal/useFishjamEventState.js.map +0 -1
- package/build/hooks/useAppScreenShare.d.ts +0 -20
- package/build/hooks/useAppScreenShare.d.ts.map +0 -1
- package/build/hooks/useAppScreenShare.js +0 -54
- package/build/hooks/useAppScreenShare.js.map +0 -1
- package/build/hooks/useAudioSettings.d.ts +0 -49
- package/build/hooks/useAudioSettings.d.ts.map +0 -1
- package/build/hooks/useAudioSettings.js +0 -70
- package/build/hooks/useAudioSettings.js.map +0 -1
- package/build/hooks/useBandwidthEstimation.d.ts +0 -14
- package/build/hooks/useBandwidthEstimation.d.ts.map +0 -1
- package/build/hooks/useBandwidthEstimation.js +0 -19
- package/build/hooks/useBandwidthEstimation.js.map +0 -1
- package/build/hooks/useCallKit.d.ts +0 -121
- package/build/hooks/useCallKit.d.ts.map +0 -1
- package/build/hooks/useCallKit.js +0 -142
- package/build/hooks/useCallKit.js.map +0 -1
- package/build/hooks/useCamera.d.ts +0 -113
- package/build/hooks/useCamera.d.ts.map +0 -1
- package/build/hooks/useCamera.js +0 -95
- package/build/hooks/useCamera.js.map +0 -1
- package/build/hooks/useConnection.d.ts +0 -73
- package/build/hooks/useConnection.d.ts.map +0 -1
- package/build/hooks/useConnection.js +0 -46
- package/build/hooks/useConnection.js.map +0 -1
- package/build/hooks/useForegroundService.d.ts.map +0 -1
- package/build/hooks/useForegroundService.js +0 -66
- package/build/hooks/useForegroundService.js.map +0 -1
- package/build/hooks/useMicrophone.d.ts +0 -16
- package/build/hooks/useMicrophone.d.ts.map +0 -1
- package/build/hooks/useMicrophone.js +0 -31
- package/build/hooks/useMicrophone.js.map +0 -1
- package/build/hooks/usePeerStatus.d.ts +0 -10
- package/build/hooks/usePeerStatus.d.ts.map +0 -1
- package/build/hooks/usePeerStatus.js +0 -13
- package/build/hooks/usePeerStatus.js.map +0 -1
- package/build/hooks/usePeers.d.ts +0 -98
- package/build/hooks/usePeers.d.ts.map +0 -1
- package/build/hooks/usePeers.js +0 -81
- package/build/hooks/usePeers.js.map +0 -1
- package/build/hooks/usePermissions.d.ts +0 -24
- package/build/hooks/usePermissions.d.ts.map +0 -1
- package/build/hooks/usePermissions.js +0 -61
- package/build/hooks/usePermissions.js.map +0 -1
- package/build/hooks/useReconnection.d.ts +0 -11
- package/build/hooks/useReconnection.d.ts.map +0 -1
- package/build/hooks/useReconnection.js +0 -14
- package/build/hooks/useReconnection.js.map +0 -1
- package/build/hooks/useSandbox.d.ts +0 -20
- package/build/hooks/useSandbox.d.ts.map +0 -1
- package/build/hooks/useSandbox.js +0 -54
- package/build/hooks/useSandbox.js.map +0 -1
- package/build/hooks/useScreenShare.d.ts +0 -37
- package/build/hooks/useScreenShare.d.ts.map +0 -1
- package/build/hooks/useScreenShare.js +0 -52
- package/build/hooks/useScreenShare.js.map +0 -1
- package/build/hooks/useUpdatePeerMetadata.d.ts +0 -15
- package/build/hooks/useUpdatePeerMetadata.d.ts.map +0 -1
- package/build/hooks/useUpdatePeerMetadata.js +0 -21
- package/build/hooks/useUpdatePeerMetadata.js.map +0 -1
- package/build/index.d.ts +0 -36
- package/build/index.d.ts.map +0 -1
- package/build/index.js +0 -30
- package/build/index.js.map +0 -1
- package/build/livestream/components/LivestreamStreamer.d.ts +0 -24
- package/build/livestream/components/LivestreamStreamer.d.ts.map +0 -1
- package/build/livestream/components/LivestreamStreamer.js +0 -12
- package/build/livestream/components/LivestreamStreamer.js.map +0 -1
- package/build/livestream/components/LivestreamViewer.d.ts +0 -46
- package/build/livestream/components/LivestreamViewer.d.ts.map +0 -1
- package/build/livestream/components/LivestreamViewer.js +0 -10
- package/build/livestream/components/LivestreamViewer.js.map +0 -1
- package/build/livestream/hooks/useLivestreamStreamer.d.ts +0 -65
- package/build/livestream/hooks/useLivestreamStreamer.d.ts.map +0 -1
- package/build/livestream/hooks/useLivestreamStreamer.js +0 -72
- package/build/livestream/hooks/useLivestreamStreamer.js.map +0 -1
- package/build/livestream/hooks/useLivestreamViewer.d.ts +0 -36
- package/build/livestream/hooks/useLivestreamViewer.d.ts.map +0 -1
- package/build/livestream/hooks/useLivestreamViewer.js +0 -73
- package/build/livestream/hooks/useLivestreamViewer.js.map +0 -1
- package/build/livestream/index.d.ts +0 -11
- package/build/livestream/index.d.ts.map +0 -1
- package/build/livestream/index.js +0 -6
- package/build/livestream/index.js.map +0 -1
- package/build/protos/fishjam/peer_notifications.d.ts +0 -63
- package/build/protos/fishjam/peer_notifications.d.ts.map +0 -1
- package/build/protos/fishjam/peer_notifications.js +0 -235
- package/build/protos/fishjam/peer_notifications.js.map +0 -1
- package/build/types.d.ts +0 -34
- package/build/types.d.ts.map +0 -1
- package/build/types.js +0 -2
- package/build/types.js.map +0 -1
- package/build/utils/config.d.ts +0 -6
- package/build/utils/config.d.ts.map +0 -1
- package/build/utils/config.js +0 -10
- package/build/utils/config.js.map +0 -1
- package/build/utils/errorListener.d.ts +0 -2
- package/build/utils/errorListener.d.ts.map +0 -1
- package/build/utils/errorListener.js +0 -15
- package/build/utils/errorListener.js.map +0 -1
- package/build/utils/eventPayloadValidator.d.ts +0 -3
- package/build/utils/eventPayloadValidator.d.ts.map +0 -1
- package/build/utils/eventPayloadValidator.js +0 -86
- package/build/utils/eventPayloadValidator.js.map +0 -1
- package/build/utils/getFishjamUrl.d.ts +0 -2
- package/build/utils/getFishjamUrl.d.ts.map +0 -1
- package/build/utils/getFishjamUrl.js +0 -10
- package/build/utils/getFishjamUrl.js.map +0 -1
- package/debug/package.json +0 -4
- package/expo-module.config.json +0 -19
- package/ios/CameraPermissionsRequester.swift +0 -117
- package/ios/Events.swift +0 -152
- package/ios/PictureInPictureManager.swift +0 -215
- package/ios/PipContainerView.swift +0 -56
- package/ios/PipContainerViewModule.swift +0 -48
- package/ios/RNFishjamClient.podspec +0 -30
- package/ios/RNFishjamClient.swift +0 -995
- package/ios/RNFishjamClientModule.swift +0 -289
- package/ios/RNFishjamProxy.swift +0 -12
- package/ios/Utils/PermissionUtils.swift +0 -16
- package/ios/Utils.swift +0 -23
- package/ios/VideoPreviewView.swift +0 -54
- package/ios/VideoPreviewViewModule.swift +0 -21
- package/ios/VideoRendererView.swift +0 -98
- package/ios/VideoRendererViewModule.swift +0 -23
- package/ios/extensions/AVCaptureDevice.swift +0 -20
- package/ios/managers/LocalCameraTracksChangedListenersManager.swift +0 -23
- package/ios/managers/TracksUpdateListenersManager.swift +0 -21
- package/livestream/package.json +0 -4
- package/plugin/broadcastExtensionFiles/FishjamBroadcastSampleHandler.swift +0 -50
- /package/plugin/broadcastExtensionFiles/{FishjamScreenBroadcastExtension.entitlements → ScreenBroadcastExtension.entitlements} +0 -0
|
@@ -1,995 +0,0 @@
|
|
|
1
|
-
import AVKit
|
|
2
|
-
import ExpoModulesCore
|
|
3
|
-
import FishjamCloudClient
|
|
4
|
-
import React
|
|
5
|
-
import ReplayKit
|
|
6
|
-
import WebRTC
|
|
7
|
-
|
|
8
|
-
class RNFishjamClient: FishjamClientListener {
|
|
9
|
-
static var fishjamClient: FishjamClient? = nil
|
|
10
|
-
private var callKitManager: CallKitManager?
|
|
11
|
-
|
|
12
|
-
var isMicrophoneOn = false
|
|
13
|
-
var isCameraOn = false
|
|
14
|
-
var isScreenShareOn = false
|
|
15
|
-
var isAppScreenShareOn = false
|
|
16
|
-
var isConnected = false
|
|
17
|
-
|
|
18
|
-
private(set) var isCameraInitialized = false {
|
|
19
|
-
didSet {
|
|
20
|
-
emit(
|
|
21
|
-
event: .currentCameraChanged(
|
|
22
|
-
localCamera: currentCamera, isCameraOn: isCameraOn, isCameraInitialized: isCameraInitialized))
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
var connectPromise: Promise? = nil {
|
|
27
|
-
didSet {
|
|
28
|
-
guard connectPromise != nil else { return }
|
|
29
|
-
|
|
30
|
-
let timeout = DispatchTime.now() + .seconds(15)
|
|
31
|
-
DispatchQueue.main.asyncAfter(deadline: timeout) { [weak self] in
|
|
32
|
-
// If promise is still assigned it means it was not resolved in that time,
|
|
33
|
-
// so close the client and reject it with timeout error.
|
|
34
|
-
guard let promise = self?.connectPromise else { return }
|
|
35
|
-
RNFishjamClient.fishjamClient?.leave { [weak self] in
|
|
36
|
-
promise.reject("E_MEMBRANE_CONNECT", "Failed to connect: Fishjam server is not responding")
|
|
37
|
-
self?.connectPromise = nil
|
|
38
|
-
self?.peerStatus = .error
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
var videoSimulcastConfig: SimulcastConfig = SimulcastConfig()
|
|
45
|
-
|
|
46
|
-
var screenShareSimulcastConfig: SimulcastConfig = SimulcastConfig()
|
|
47
|
-
|
|
48
|
-
var cameraId: String? = nil
|
|
49
|
-
|
|
50
|
-
var audioSessionMode: AVAudioSession.Mode = .videoChat
|
|
51
|
-
var errorMessage: String?
|
|
52
|
-
|
|
53
|
-
var currentCamera: LocalCamera? { getLocalCameraTrack()?.currentCaptureDevice?.toLocalCamera() }
|
|
54
|
-
|
|
55
|
-
private(set) var peerStatus: PeerStatus = .idle {
|
|
56
|
-
didSet {
|
|
57
|
-
emit(event: .peerStatusChanged(peerStatus: peerStatus))
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
private(set) var reconnectionStatus: ReconnectionStatus = .idle {
|
|
62
|
-
didSet {
|
|
63
|
-
emit(event: .reconnectionStatusChanged(reconnectionStatus: reconnectionStatus))
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
static private(set) var sendEvent: ((_ event: EmitableEvent) -> Void)?
|
|
68
|
-
|
|
69
|
-
static var tracksUpdateListenersManager = TracksUpdateListenersManager()
|
|
70
|
-
static var localCameraTracksChangedListenersManager = LocalCameraTracksChangedListenersManager()
|
|
71
|
-
|
|
72
|
-
init(_ eventEmitter: @escaping (_ eventName: String, _ data: [String: Any?]) -> Void) {
|
|
73
|
-
RNFishjamClient.sendEvent = { event in
|
|
74
|
-
eventEmitter(event.event.name, event.data)
|
|
75
|
-
}
|
|
76
|
-
NotificationCenter.default.addObserver(
|
|
77
|
-
self,
|
|
78
|
-
selector: #selector(onRouteChangeNotification),
|
|
79
|
-
name: AVAudioSession.routeChangeNotification,
|
|
80
|
-
object: nil
|
|
81
|
-
)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
deinit {
|
|
85
|
-
RNFishjamClient.sendEvent = nil
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
private func getSimulcastConfigFromOptions(simulcastConfig: RNSimulcastConfig) throws -> SimulcastConfig {
|
|
89
|
-
// iOS has a limit of 3 hardware encoders
|
|
90
|
-
// 3 simulcast layers + 1 screen share layer = 4, which is too much
|
|
91
|
-
// so we limit simulcast layers to 2
|
|
92
|
-
let activeEncodings: [TrackEncoding] = [.l, .h]
|
|
93
|
-
|
|
94
|
-
return SimulcastConfig(
|
|
95
|
-
enabled: simulcastConfig.enabled,
|
|
96
|
-
activeEncodings: activeEncodings
|
|
97
|
-
)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
func create() {
|
|
101
|
-
RNFishjamClient.fishjamClient = FishjamClient(listener: self)
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
func getVideoParametersFromOptions(connectionOptions: CameraConfig) throws -> VideoParameters {
|
|
105
|
-
let videoQuality = connectionOptions.quality
|
|
106
|
-
let flipDimensions = connectionOptions.flipDimensions
|
|
107
|
-
let simulcastConfig = try getSimulcastConfigFromOptions(simulcastConfig: connectionOptions.simulcastConfig)
|
|
108
|
-
|
|
109
|
-
let preset: VideoParameters = {
|
|
110
|
-
switch videoQuality {
|
|
111
|
-
case "QVGA169":
|
|
112
|
-
return VideoParameters.presetQVGA169
|
|
113
|
-
case "VGA169":
|
|
114
|
-
return VideoParameters.presetVGA169
|
|
115
|
-
case "VQHD169":
|
|
116
|
-
return VideoParameters.presetQHD169
|
|
117
|
-
case "HD169":
|
|
118
|
-
return VideoParameters.presetHD169
|
|
119
|
-
case "FHD169":
|
|
120
|
-
return VideoParameters.presetFHD169
|
|
121
|
-
case "QVGA43":
|
|
122
|
-
return VideoParameters.presetQVGA43
|
|
123
|
-
case "VGA43":
|
|
124
|
-
return VideoParameters.presetVGA43
|
|
125
|
-
case "VQHD43":
|
|
126
|
-
return VideoParameters.presetQHD43
|
|
127
|
-
case "HD43":
|
|
128
|
-
return VideoParameters.presetHD43
|
|
129
|
-
case "FHD43":
|
|
130
|
-
return VideoParameters.presetFHD43
|
|
131
|
-
default:
|
|
132
|
-
return VideoParameters.presetVGA169
|
|
133
|
-
}
|
|
134
|
-
}()
|
|
135
|
-
let videoParameters = VideoParameters(
|
|
136
|
-
dimensions: flipDimensions ? preset.dimensions.flipped : preset.dimensions,
|
|
137
|
-
maxBandwidth: preset.maxBandwidth,
|
|
138
|
-
simulcastConfig: simulcastConfig
|
|
139
|
-
)
|
|
140
|
-
return videoParameters
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
private var localEndpoint: Endpoint? {
|
|
144
|
-
RNFishjamClient.fishjamClient?.getLocalEndpoint()
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
private func getLocalCameraTrack() -> LocalCameraTrack? {
|
|
148
|
-
return localEndpoint?.tracks.compactMap { $0.value as? LocalCameraTrack }.first
|
|
149
|
-
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
private func getLocalAudioTrack() -> LocalAudioTrack? {
|
|
153
|
-
return localEndpoint?.tracks.compactMap { $0.value as? LocalAudioTrack }.first
|
|
154
|
-
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
private func getLocalScreenBroadcastTrack() -> LocalBroadcastScreenShareTrack? {
|
|
158
|
-
return localEndpoint?.tracks.compactMap { $0.value as? LocalBroadcastScreenShareTrack }.first
|
|
159
|
-
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
private func getLocalScreenAppTrack() -> LocalAppScreenShareTrack? {
|
|
163
|
-
return localEndpoint?.tracks.compactMap { $0.value as? LocalAppScreenShareTrack }.first
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
private func ensureCreated() throws {
|
|
167
|
-
if RNFishjamClient.fishjamClient == nil {
|
|
168
|
-
throw Exception(
|
|
169
|
-
name: "E_NOT_CREATED",
|
|
170
|
-
description: "Client not created. Call create"
|
|
171
|
-
)
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
private func ensureConnected() throws {
|
|
176
|
-
if !isConnected {
|
|
177
|
-
throw Exception(
|
|
178
|
-
name: "E_NOT_CONNECTED",
|
|
179
|
-
description:
|
|
180
|
-
"Client not connected to server yet. Make sure to call connect() first!")
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
private func ensureCameraTrack() throws {
|
|
185
|
-
if getLocalCameraTrack() == nil {
|
|
186
|
-
throw Exception(
|
|
187
|
-
name: "E_NO_LOCAL_VIDEO_TRACK",
|
|
188
|
-
description: "No local video track. Make sure to call connect() first!")
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
private func ensureAudioTrack() throws {
|
|
193
|
-
if getLocalAudioTrack() == nil {
|
|
194
|
-
throw Exception(
|
|
195
|
-
name: "E_NO_LOCAL_AUDIO_TRACK",
|
|
196
|
-
description: "No local audio track. Make sure to call connect() first!")
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
private func ensureScreenBroadcastTrack() throws {
|
|
201
|
-
if getLocalScreenBroadcastTrack() == nil {
|
|
202
|
-
throw Exception(
|
|
203
|
-
name: "E_NO_LOCAL_SCREENSHARE_TRACK",
|
|
204
|
-
description: "No local screen broadcast track. Make sure to toggle screen broadcast on first!")
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
private func ensureScreenAppTrack() throws {
|
|
209
|
-
if getLocalScreenAppTrack() == nil {
|
|
210
|
-
throw Exception(
|
|
211
|
-
name: "E_NO_LOCAL_SCREENSHARE_TRACK",
|
|
212
|
-
description: "No local screen app track. Make sure to toggle screen app on first!")
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
func onAuthError(reason: FishjamCloudClient.AuthError) {
|
|
217
|
-
if let connectPromise = connectPromise {
|
|
218
|
-
connectPromise.reject("E_MEMBRANE_CONNECT", "Failed to connect: socket error")
|
|
219
|
-
}
|
|
220
|
-
connectPromise = nil
|
|
221
|
-
peerStatus = .error
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
func joinRoom(
|
|
225
|
-
url: String, peerToken: String, peerMetadata: [String: Any], config: ConnectConfig,
|
|
226
|
-
promise: Promise
|
|
227
|
-
) {
|
|
228
|
-
guard connectPromise == nil && peerStatus != .connected else {
|
|
229
|
-
promise.reject("E_MEMBRANE_CONNECT", "Room already joined or it's connecting. You must call leaveRoom() before calling joinRoom() again.")
|
|
230
|
-
return
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
peerStatus = .connecting
|
|
234
|
-
connectPromise = promise
|
|
235
|
-
|
|
236
|
-
let reconnectConfig = FishjamCloudClient.ReconnectConfig(
|
|
237
|
-
maxAttempts: config.reconnectConfig.maxAttempts, initialDelayMs: config.reconnectConfig.initialDelayMs,
|
|
238
|
-
delayMs: config.reconnectConfig.delayMs)
|
|
239
|
-
|
|
240
|
-
RNFishjamClient.fishjamClient?.connect(
|
|
241
|
-
config: FishjamCloudClient.ConnectConfig(
|
|
242
|
-
websocketUrl: url, token: peerToken, peerMetadata: peerMetadata.toMetadata(),
|
|
243
|
-
reconnectConfig: reconnectConfig
|
|
244
|
-
))
|
|
245
|
-
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
func leaveRoom() {
|
|
249
|
-
connectPromise?.reject("E_MEMBRANE_CONNECT", "leaveRoom called before connected")
|
|
250
|
-
connectPromise = nil
|
|
251
|
-
if isScreenShareOn {
|
|
252
|
-
let screenShareExtensionBundleId =
|
|
253
|
-
Bundle.main.infoDictionary?["ScreenShareExtensionBundleId"] as? String
|
|
254
|
-
DispatchQueue.main.async {
|
|
255
|
-
RPSystemBroadcastPickerView.show(for: screenShareExtensionBundleId)
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
isMicrophoneOn = false
|
|
259
|
-
isCameraOn = false
|
|
260
|
-
isScreenShareOn = false
|
|
261
|
-
isAppScreenShareOn = false
|
|
262
|
-
isConnected = false
|
|
263
|
-
isCameraInitialized = false
|
|
264
|
-
RNFishjamClient.fishjamClient?.leave { [weak self] in
|
|
265
|
-
self?.emitEndpoints()
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
private let startCameraLock = NSLock()
|
|
270
|
-
|
|
271
|
-
func startCamera(config: CameraConfig) async throws -> Bool {
|
|
272
|
-
#if targetEnvironment(simulator)
|
|
273
|
-
emit(
|
|
274
|
-
event: .warning(
|
|
275
|
-
message: "Camera is not supported on simulator."))
|
|
276
|
-
return false
|
|
277
|
-
#endif
|
|
278
|
-
|
|
279
|
-
try ensureCreated()
|
|
280
|
-
|
|
281
|
-
guard await PermissionUtils.requestCameraPermission() else {
|
|
282
|
-
emit(event: .warning(message: "Camera permission not granted."))
|
|
283
|
-
return false
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
return try startCameraLock.withLock {
|
|
287
|
-
guard !isCameraInitialized else {
|
|
288
|
-
return true
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
let cameraTrack = try createCameraTrack(config: config)
|
|
292
|
-
cameraTrack.captureDeviceChangedListener = self
|
|
293
|
-
setCameraTrackState(cameraTrack, enabled: config.cameraEnabled)
|
|
294
|
-
emitEndpoints()
|
|
295
|
-
isCameraInitialized = true
|
|
296
|
-
return true
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
private func createCameraTrack(config: CameraConfig) throws -> LocalCameraTrack {
|
|
301
|
-
try ensureCreated()
|
|
302
|
-
let videoParameters = try getVideoParametersFromOptions(connectionOptions: config)
|
|
303
|
-
videoSimulcastConfig = try getSimulcastConfigFromOptions(simulcastConfig: config.simulcastConfig)
|
|
304
|
-
return RNFishjamClient.fishjamClient!.createVideoTrack(
|
|
305
|
-
videoParameters: videoParameters,
|
|
306
|
-
metadata: config.videoTrackMetadata.toMetadata(),
|
|
307
|
-
captureDeviceName: config.cameraId
|
|
308
|
-
)
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
private func setCameraTrackState(_ cameraTrack: LocalCameraTrack, enabled: Bool) {
|
|
312
|
-
cameraTrack.enabled = enabled
|
|
313
|
-
isCameraOn = enabled
|
|
314
|
-
emit(
|
|
315
|
-
event: .currentCameraChanged(
|
|
316
|
-
localCamera: cameraTrack.currentCaptureDevice?.toLocalCamera(), isCameraOn: enabled,
|
|
317
|
-
isCameraInitialized: isCameraInitialized))
|
|
318
|
-
RNFishjamClient.localCameraTracksChangedListenersManager.notifyListeners()
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
func toggleCamera() throws -> Bool {
|
|
322
|
-
try ensureCameraTrack()
|
|
323
|
-
setCameraTrackState(getLocalCameraTrack()!, enabled: !isCameraOn)
|
|
324
|
-
return isCameraOn
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
func flipCamera() throws {
|
|
328
|
-
try ensureCameraTrack()
|
|
329
|
-
getLocalCameraTrack()?.flipCamera()
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
func switchCamera(cameraId: String) throws {
|
|
333
|
-
try ensureCameraTrack()
|
|
334
|
-
getLocalCameraTrack()?.switchCamera(deviceId: cameraId)
|
|
335
|
-
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
func toggleMicrophone() async throws -> Bool {
|
|
339
|
-
if isMicrophoneOn {
|
|
340
|
-
try stopMicrophone()
|
|
341
|
-
} else {
|
|
342
|
-
try await startMicrophone()
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
return isMicrophoneOn
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
func startMicrophone() async throws {
|
|
349
|
-
// If microphone track already exist, just enable it
|
|
350
|
-
if let microphoneTrack = getLocalAudioTrack() {
|
|
351
|
-
try setMicrophoneTrackState(microphoneTrack, enabled: true)
|
|
352
|
-
} else {
|
|
353
|
-
guard await PermissionUtils.requestMicrophonePermission() else {
|
|
354
|
-
emit(event: .warning(message: "Microphone permission not granted."))
|
|
355
|
-
return
|
|
356
|
-
}
|
|
357
|
-
let microphoneTrack = RNFishjamClient.fishjamClient!.createAudioTrack(
|
|
358
|
-
metadata: getMicrophoneTrackMetadata(isEnabled: true).toMetadata())
|
|
359
|
-
setAudioSessionMode()
|
|
360
|
-
try setMicrophoneTrackState(microphoneTrack, enabled: true)
|
|
361
|
-
emitEndpoints()
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
func stopMicrophone() throws {
|
|
366
|
-
guard let microphoneTrack = getLocalAudioTrack() else {
|
|
367
|
-
return
|
|
368
|
-
}
|
|
369
|
-
try setMicrophoneTrackState(microphoneTrack, enabled: false)
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
private func getMicrophoneTrackMetadata(isEnabled: Bool) -> [String: Any] {
|
|
373
|
-
return [
|
|
374
|
-
"active": isEnabled,
|
|
375
|
-
"paused": !isEnabled, //TODO: FCE-711
|
|
376
|
-
"type": "microphone",
|
|
377
|
-
]
|
|
378
|
-
}
|
|
379
|
-
|
|
380
|
-
private func setMicrophoneTrackState(_ microphoneTrack: LocalAudioTrack, enabled: Bool) throws {
|
|
381
|
-
microphoneTrack.enabled = enabled
|
|
382
|
-
isMicrophoneOn = enabled
|
|
383
|
-
try updateLocalAudioTrackMetadata(metadata: getMicrophoneTrackMetadata(isEnabled: enabled))
|
|
384
|
-
emit(event: .isMicrophoneOn(enabled: enabled))
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
func setAudioSessionMode() {
|
|
388
|
-
guard let localAudioTrack = getLocalAudioTrack() else {
|
|
389
|
-
return
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
switch self.audioSessionMode {
|
|
393
|
-
case AVAudioSession.Mode.videoChat:
|
|
394
|
-
localAudioTrack.setVideoChatMode()
|
|
395
|
-
break
|
|
396
|
-
case AVAudioSession.Mode.voiceChat:
|
|
397
|
-
localAudioTrack.setVoiceChatMode()
|
|
398
|
-
break
|
|
399
|
-
default:
|
|
400
|
-
localAudioTrack.setVideoChatMode()
|
|
401
|
-
break
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
func toggleScreenShare(screenShareOptions: ScreenShareOptions) throws {
|
|
406
|
-
try ensureCreated()
|
|
407
|
-
try ensureConnected()
|
|
408
|
-
|
|
409
|
-
guard isAppScreenShareOn == false else {
|
|
410
|
-
emit(event: .warning(message: "Screensharing screen not available during screensharing app."))
|
|
411
|
-
return
|
|
412
|
-
}
|
|
413
|
-
guard let screenShareExtensionBundleId = Bundle.main.infoDictionary?["ScreenShareExtensionBundleId"] as? String
|
|
414
|
-
else {
|
|
415
|
-
throw Exception(
|
|
416
|
-
name: "E_NO_BUNDLE_ID_SET",
|
|
417
|
-
description:
|
|
418
|
-
"No screen share extension bundle id set. Please set ScreenShareExtensionBundleId in Info.plist"
|
|
419
|
-
)
|
|
420
|
-
}
|
|
421
|
-
guard let appGroupName = Bundle.main.infoDictionary?["AppGroupName"] as? String
|
|
422
|
-
else {
|
|
423
|
-
throw Exception(
|
|
424
|
-
name: "E_NO_APP_GROUP_SET",
|
|
425
|
-
description: "No app group name set. Please set AppGroupName in Info.plist")
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
guard !isScreenShareOn else {
|
|
429
|
-
DispatchQueue.main.async {
|
|
430
|
-
RPSystemBroadcastPickerView.show(for: screenShareExtensionBundleId)
|
|
431
|
-
}
|
|
432
|
-
return
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
if RNFishjamClient.fishjamClient?.lastSdpAnswer?.detectedCodec != .h264 {
|
|
436
|
-
emit(event: .warning(
|
|
437
|
-
message: "Incompatible codec detected: \(RNFishjamClient.fishjamClient?.lastSdpAnswer?.detectedCodec?.rawValue ?? "Unknown"). Screen sharing requires H264, otherwise UploadBroadcastExtenstion will crash due to memory pressure (no hardware acceleration). " +
|
|
438
|
-
"Please configure your Fishjam room to use H264 codec for better screen sharing performance."
|
|
439
|
-
))
|
|
440
|
-
}
|
|
441
|
-
|
|
442
|
-
let simulcastConfig = try getSimulcastConfigFromOptions(simulcastConfig: screenShareOptions.simulcastConfig)
|
|
443
|
-
|
|
444
|
-
screenShareSimulcastConfig = simulcastConfig
|
|
445
|
-
let screenShareMetadata = screenShareOptions.screenShareMetadata.toMetadata()
|
|
446
|
-
let videoParameters = getScreenShareVideoParameters(options: screenShareOptions)
|
|
447
|
-
RNFishjamClient.fishjamClient!.prepareForScreenBroadcast(
|
|
448
|
-
appGroup: appGroupName,
|
|
449
|
-
videoParameters: videoParameters,
|
|
450
|
-
metadata: screenShareMetadata,
|
|
451
|
-
canStart: {
|
|
452
|
-
if self.isAppScreenShareOn {
|
|
453
|
-
self.emit(event: .warning(message: "Screensharing screen not available during screensharing app."))
|
|
454
|
-
}
|
|
455
|
-
return !self.isAppScreenShareOn
|
|
456
|
-
},
|
|
457
|
-
onStart: { [weak self] in
|
|
458
|
-
guard let self else { return }
|
|
459
|
-
do {
|
|
460
|
-
try setScreenShareTrackState(enabled: true)
|
|
461
|
-
} catch {
|
|
462
|
-
os_log(
|
|
463
|
-
"Error starting screen share: %{public}s", log: log, type: .error,
|
|
464
|
-
String(describing: error)
|
|
465
|
-
)
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
},
|
|
469
|
-
onStop: { [weak self] in
|
|
470
|
-
guard let self else { return }
|
|
471
|
-
do {
|
|
472
|
-
try setScreenShareTrackState(enabled: false)
|
|
473
|
-
} catch {
|
|
474
|
-
os_log(
|
|
475
|
-
"Error stopping screen share: %{public}s", log: log, type: .error,
|
|
476
|
-
String(describing: error)
|
|
477
|
-
)
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
)
|
|
481
|
-
DispatchQueue.main.async {
|
|
482
|
-
RPSystemBroadcastPickerView.show(for: screenShareExtensionBundleId)
|
|
483
|
-
}
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
private func setScreenShareTrackState(enabled: Bool) throws {
|
|
487
|
-
isScreenShareOn = enabled
|
|
488
|
-
emit(event: .isScreenShareOn(enabled: enabled))
|
|
489
|
-
}
|
|
490
|
-
|
|
491
|
-
func startScreenAppShare(screenShareOptions: ScreenShareOptions) throws {
|
|
492
|
-
try ensureCreated()
|
|
493
|
-
try ensureConnected()
|
|
494
|
-
|
|
495
|
-
let simulcastConfig = try getSimulcastConfigFromOptions(simulcastConfig: screenShareOptions.simulcastConfig)
|
|
496
|
-
|
|
497
|
-
screenShareSimulcastConfig = simulcastConfig
|
|
498
|
-
let metadata = screenShareOptions.screenShareMetadata.toMetadata()
|
|
499
|
-
let videoParameters = getScreenShareVideoParameters(options: screenShareOptions)
|
|
500
|
-
let screenAppTrack = RNFishjamClient.fishjamClient!.createScreenAppTrack(
|
|
501
|
-
videoParameters: videoParameters, metadata: metadata)
|
|
502
|
-
setScreenAppTrackState(screenAppTrack, enabled: true)
|
|
503
|
-
emitEndpoints()
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
func stopAppScreenShare() throws {
|
|
507
|
-
try ensureScreenAppTrack()
|
|
508
|
-
let track = getLocalScreenAppTrack()!
|
|
509
|
-
setScreenAppTrackState(track, enabled: false)
|
|
510
|
-
RNFishjamClient.fishjamClient?.removeTrack(trackId: track.id)
|
|
511
|
-
emitEndpoints()
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
func toggleAppScreenShare(screenShareOptions: ScreenShareOptions) throws {
|
|
515
|
-
guard isScreenShareOn == false else {
|
|
516
|
-
emit(event: .warning(message: "App screensharing not available during screensharing."))
|
|
517
|
-
return
|
|
518
|
-
}
|
|
519
|
-
if getLocalScreenAppTrack() != nil {
|
|
520
|
-
try stopAppScreenShare()
|
|
521
|
-
} else {
|
|
522
|
-
try startScreenAppShare(screenShareOptions: screenShareOptions)
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
|
|
526
|
-
private func setScreenAppTrackState(_ track: LocalAppScreenShareTrack, enabled: Bool) {
|
|
527
|
-
track.enabled = enabled
|
|
528
|
-
isAppScreenShareOn = enabled
|
|
529
|
-
emit(event: .isAppScreenShareOn(enabled: enabled))
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
//returns local endpoint and remote endpoints
|
|
533
|
-
static func getLocalAndRemoteEndpoints() -> [Endpoint] {
|
|
534
|
-
let localEndpoint = RNFishjamClient.fishjamClient!.getLocalEndpoint()
|
|
535
|
-
let remoteEndpoints = RNFishjamClient.fishjamClient!.getRemoteEndpoints()
|
|
536
|
-
return [localEndpoint] + remoteEndpoints
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
func getPeers() -> [[String: Any?]] {
|
|
540
|
-
let endpoints = RNFishjamClient.getLocalAndRemoteEndpoints()
|
|
541
|
-
return endpoints.compactMap { endpoint in
|
|
542
|
-
[
|
|
543
|
-
"id": endpoint.id,
|
|
544
|
-
"isLocal": endpoint.id == RNFishjamClient.fishjamClient!.getLocalEndpoint().id,
|
|
545
|
-
"metadata": endpoint.metadata.toDict(),
|
|
546
|
-
"tracks": endpoint.tracks.values.compactMap { track -> [String: Any?]? in
|
|
547
|
-
switch track {
|
|
548
|
-
case let track as RemoteVideoTrack:
|
|
549
|
-
return [
|
|
550
|
-
"id": track.id,
|
|
551
|
-
"type": "Video",
|
|
552
|
-
"metadata": track.metadata.toDict(),
|
|
553
|
-
"encoding": track.encoding?.description,
|
|
554
|
-
"encodingReason": track.encodingReason?.rawValue,
|
|
555
|
-
"aspectRatio": track.dimensions?.aspectRatio,
|
|
556
|
-
]
|
|
557
|
-
|
|
558
|
-
case let track as RemoteAudioTrack:
|
|
559
|
-
return [
|
|
560
|
-
"id": track.id,
|
|
561
|
-
"type": "Audio",
|
|
562
|
-
"metadata": track.metadata.toDict(),
|
|
563
|
-
"vadStatus": track.vadStatus == .speech ? "speech" : "silence",
|
|
564
|
-
]
|
|
565
|
-
|
|
566
|
-
case let track as LocalVideoTrack:
|
|
567
|
-
return [
|
|
568
|
-
"id": track.id,
|
|
569
|
-
"type": "Video",
|
|
570
|
-
"metadata": track.metadata.toDict(),
|
|
571
|
-
"aspectRatio": track.dimensions?.aspectRatio,
|
|
572
|
-
]
|
|
573
|
-
case let track as LocalAudioTrack:
|
|
574
|
-
return [
|
|
575
|
-
"id": track.id,
|
|
576
|
-
"type": "Audio",
|
|
577
|
-
"metadata": track.metadata.toDict(),
|
|
578
|
-
]
|
|
579
|
-
|
|
580
|
-
default:
|
|
581
|
-
return nil
|
|
582
|
-
}
|
|
583
|
-
},
|
|
584
|
-
]
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
func getCaptureDevices() -> [[String: Any]] {
|
|
589
|
-
let devices = LocalCameraTrack.getCaptureDevices()
|
|
590
|
-
return devices.map { $0.toLocalCamera() }
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
func updatePeerMetadata(metadata: [String: Any]) throws {
|
|
594
|
-
try ensureConnected()
|
|
595
|
-
RNFishjamClient.fishjamClient?.updatePeerMetadata(metadata: metadata.toMetadata())
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
func updateTrackMetadata(trackId: String, metadata: [String: Any]) {
|
|
599
|
-
RNFishjamClient.fishjamClient?.updateTrackMetadata(trackId: trackId, metadata: metadata.toMetadata())
|
|
600
|
-
emitEndpoints()
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
func updateLocalVideoTrackMetadata(metadata: [String: Any]) throws {
|
|
604
|
-
try ensureCameraTrack()
|
|
605
|
-
if let track = getLocalCameraTrack() {
|
|
606
|
-
updateTrackMetadata(trackId: track.id, metadata: metadata)
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
|
|
610
|
-
private func updateLocalAudioTrackMetadata(metadata: [String: Any]) throws {
|
|
611
|
-
try ensureAudioTrack()
|
|
612
|
-
if let track = getLocalAudioTrack() {
|
|
613
|
-
updateTrackMetadata(trackId: track.id, metadata: metadata)
|
|
614
|
-
}
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
func updateLocalScreenShareTrackMetadata(metadata: [String: Any]) throws {
|
|
618
|
-
try ensureScreenBroadcastTrack()
|
|
619
|
-
if let track = getLocalScreenBroadcastTrack() {
|
|
620
|
-
updateTrackMetadata(trackId: track.id, metadata: metadata)
|
|
621
|
-
}
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
private func toggleTrackEncoding(encoding: String, trackId: String, simulcastConfig: SimulcastConfig) throws
|
|
625
|
-
-> SimulcastConfig
|
|
626
|
-
{
|
|
627
|
-
try ensureCreated()
|
|
628
|
-
let trackEncoding = try TrackEncoding(encoding)
|
|
629
|
-
let trackEncodingActive = simulcastConfig.activeEncodings.contains(trackEncoding)
|
|
630
|
-
var updatedEncodings = simulcastConfig.activeEncodings
|
|
631
|
-
|
|
632
|
-
if trackEncodingActive {
|
|
633
|
-
RNFishjamClient.fishjamClient?.disableTrackEncoding(trackId: trackId, encoding: trackEncoding)
|
|
634
|
-
updatedEncodings.removeAll(where: { encoding in trackEncoding == encoding })
|
|
635
|
-
} else {
|
|
636
|
-
RNFishjamClient.fishjamClient?.enableTrackEncoding(trackId: trackId, encoding: trackEncoding)
|
|
637
|
-
updatedEncodings += [trackEncoding]
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
return SimulcastConfig(enabled: true, activeEncodings: updatedEncodings)
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
func toggleScreenShareTrackEncoding(encoding: String) throws -> [String: Any?] {
|
|
644
|
-
try ensureScreenBroadcastTrack()
|
|
645
|
-
if let track = getLocalScreenBroadcastTrack() {
|
|
646
|
-
screenShareSimulcastConfig = try toggleTrackEncoding(
|
|
647
|
-
encoding: encoding, trackId: track.id, simulcastConfig: screenShareSimulcastConfig)
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
return EmitableEvent.simulcastConfigUpdate(simulcastConfig: screenShareSimulcastConfig).data
|
|
651
|
-
}
|
|
652
|
-
|
|
653
|
-
func setScreenShareTrackBandwidth(bandwidth: Int) throws {
|
|
654
|
-
try ensureScreenBroadcastTrack()
|
|
655
|
-
if let track = getLocalScreenBroadcastTrack() {
|
|
656
|
-
RNFishjamClient.fishjamClient?.setTrackBandwidth(trackId: track.id, bandwidthLimit: bandwidth)
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
func setScreenShareTrackEncodingBandwidth(encoding: String, bandwidth: Int) throws {
|
|
661
|
-
try ensureScreenBroadcastTrack()
|
|
662
|
-
if let track = getLocalScreenBroadcastTrack() {
|
|
663
|
-
RNFishjamClient.fishjamClient?.setEncodingBandwidth(
|
|
664
|
-
trackId: track.id, encoding: encoding, bandwidthLimit: bandwidth)
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
func setTargetTrackEncoding(trackId: String, encoding: String) throws {
|
|
669
|
-
try ensureConnected()
|
|
670
|
-
let trackEncoding = try TrackEncoding(encoding)
|
|
671
|
-
RNFishjamClient.fishjamClient?.setTargetTrackEncoding(trackId: trackId, encoding: trackEncoding)
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
func toggleVideoTrackEncoding(encoding: String) throws -> [String: Any?] {
|
|
675
|
-
try ensureCameraTrack()
|
|
676
|
-
try ensureConnected()
|
|
677
|
-
|
|
678
|
-
let track = getLocalCameraTrack()!
|
|
679
|
-
videoSimulcastConfig = try toggleTrackEncoding(
|
|
680
|
-
encoding: encoding, trackId: track.id, simulcastConfig: videoSimulcastConfig)
|
|
681
|
-
|
|
682
|
-
let event = EmitableEvent.simulcastConfigUpdate(simulcastConfig: videoSimulcastConfig)
|
|
683
|
-
emit(event: event)
|
|
684
|
-
|
|
685
|
-
return event.data
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
func setVideoTrackEncodingBandwidth(encoding: String, bandwidth: Int) throws {
|
|
689
|
-
try ensureCameraTrack()
|
|
690
|
-
let track = getLocalCameraTrack()!
|
|
691
|
-
RNFishjamClient.fishjamClient?.setEncodingBandwidth(
|
|
692
|
-
trackId: track.id, encoding: encoding, bandwidthLimit: bandwidth)
|
|
693
|
-
}
|
|
694
|
-
|
|
695
|
-
func setVideoTrackBandwidth(bandwidth: Int) throws {
|
|
696
|
-
try ensureCameraTrack()
|
|
697
|
-
let track = getLocalCameraTrack()!
|
|
698
|
-
RNFishjamClient.fishjamClient?.setTrackBandwidth(trackId: track.id, bandwidthLimit: bandwidth)
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
func changeWebRTCLoggingSeverity(severity: String) throws {
|
|
702
|
-
switch severity {
|
|
703
|
-
case "verbose":
|
|
704
|
-
RNFishjamClient.fishjamClient?.changeWebRTCLoggingSeverity(severity: .verbose)
|
|
705
|
-
case "info":
|
|
706
|
-
RNFishjamClient.fishjamClient?.changeWebRTCLoggingSeverity(severity: .info)
|
|
707
|
-
case "warning":
|
|
708
|
-
RNFishjamClient.fishjamClient?.changeWebRTCLoggingSeverity(severity: .warning)
|
|
709
|
-
case "error":
|
|
710
|
-
RNFishjamClient.fishjamClient?.changeWebRTCLoggingSeverity(severity: .error)
|
|
711
|
-
case "none":
|
|
712
|
-
RNFishjamClient.fishjamClient?.changeWebRTCLoggingSeverity(severity: .none)
|
|
713
|
-
default:
|
|
714
|
-
throw Exception(
|
|
715
|
-
name: "E_INVALID_SEVERITY_LEVEL",
|
|
716
|
-
description: "Severity with name=\(severity) not found")
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
|
-
|
|
720
|
-
private func rtcOutboundStatsToRNMap(obj: RTCOutboundStats) -> [String: Any] {
|
|
721
|
-
var innerMap: [String: Double] = [:]
|
|
722
|
-
|
|
723
|
-
innerMap["bandwidth"] = obj.qualityLimitationDurations?.bandwidth ?? 0.0
|
|
724
|
-
innerMap["cpu"] = obj.qualityLimitationDurations?.cpu ?? 0.0
|
|
725
|
-
innerMap["none"] = obj.qualityLimitationDurations?.none ?? 0.0
|
|
726
|
-
innerMap["other"] = obj.qualityLimitationDurations?.other ?? 0.0
|
|
727
|
-
|
|
728
|
-
var res: [String: Any] = [:]
|
|
729
|
-
res["kind"] = obj.kind
|
|
730
|
-
res["rid"] = obj.rid
|
|
731
|
-
res["bytesSent"] = obj.bytesSent
|
|
732
|
-
res["targetBitrate"] = obj.targetBitrate
|
|
733
|
-
res["packetsSent"] = obj.packetsSent
|
|
734
|
-
res["framesEncoded"] = obj.framesEncoded
|
|
735
|
-
res["framesPerSecond"] = obj.framesPerSecond
|
|
736
|
-
res["frameWidth"] = obj.frameWidth
|
|
737
|
-
res["frameHeight"] = obj.frameHeight
|
|
738
|
-
res["qualityLimitationDurations"] = innerMap
|
|
739
|
-
|
|
740
|
-
return res
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
private func rtcInboundStatsToRNMap(obj: RTCInboundStats) -> [String: Any] {
|
|
744
|
-
var res: [String: Any] = [:]
|
|
745
|
-
res["kind"] = obj.kind
|
|
746
|
-
res["jitter"] = obj.jitter
|
|
747
|
-
res["packetsLost"] = obj.packetsLost
|
|
748
|
-
res["packetsReceived"] = obj.packetsReceived
|
|
749
|
-
res["bytesReceived"] = obj.bytesReceived
|
|
750
|
-
res["framesReceived"] = obj.framesReceived
|
|
751
|
-
res["frameWidth"] = obj.frameWidth
|
|
752
|
-
res["frameHeight"] = obj.frameHeight
|
|
753
|
-
res["framesPerSecond"] = obj.framesPerSecond
|
|
754
|
-
res["framesDropped"] = obj.framesDropped
|
|
755
|
-
|
|
756
|
-
return res
|
|
757
|
-
}
|
|
758
|
-
|
|
759
|
-
func getStatistics() async throws -> [String: Any] {
|
|
760
|
-
try ensureCreated()
|
|
761
|
-
|
|
762
|
-
let stats = await RNFishjamClient.fishjamClient!.getStats()
|
|
763
|
-
|
|
764
|
-
let pairs = stats.map { (key, value) in
|
|
765
|
-
let rnValue =
|
|
766
|
-
value is RTCOutboundStats
|
|
767
|
-
? rtcOutboundStatsToRNMap(obj: value as! RTCOutboundStats)
|
|
768
|
-
: rtcInboundStatsToRNMap(obj: value as! RTCInboundStats)
|
|
769
|
-
return (key, rnValue)
|
|
770
|
-
}
|
|
771
|
-
|
|
772
|
-
return Dictionary(uniqueKeysWithValues: pairs)
|
|
773
|
-
}
|
|
774
|
-
|
|
775
|
-
private func getScreenShareVideoParameters(options: ScreenShareOptions) -> VideoParameters {
|
|
776
|
-
let preset: VideoParameters
|
|
777
|
-
switch options.quality {
|
|
778
|
-
case "VGA":
|
|
779
|
-
preset = VideoParameters.presetScreenShareVGA
|
|
780
|
-
case "HD5":
|
|
781
|
-
preset = VideoParameters.presetScreenShareHD5
|
|
782
|
-
case "HD15":
|
|
783
|
-
preset = VideoParameters.presetScreenShareHD15
|
|
784
|
-
case "FHD15":
|
|
785
|
-
preset = VideoParameters.presetScreenShareFHD15
|
|
786
|
-
case "FHD30":
|
|
787
|
-
preset = VideoParameters.presetScreenShareFHD30
|
|
788
|
-
default:
|
|
789
|
-
preset = VideoParameters.presetScreenShareHD15
|
|
790
|
-
}
|
|
791
|
-
return VideoParameters(
|
|
792
|
-
dimensions: preset.dimensions.flipped,
|
|
793
|
-
maxFps: preset.maxFps,
|
|
794
|
-
simulcastConfig: screenShareSimulcastConfig
|
|
795
|
-
)
|
|
796
|
-
}
|
|
797
|
-
|
|
798
|
-
func emit(event: EmitableEvent) {
|
|
799
|
-
DispatchQueue.main.async {
|
|
800
|
-
RNFishjamClient.sendEvent?(event)
|
|
801
|
-
}
|
|
802
|
-
}
|
|
803
|
-
|
|
804
|
-
func emitEndpoints() {
|
|
805
|
-
emit(event: .peersUpdate())
|
|
806
|
-
RNFishjamClient.tracksUpdateListenersManager.notifyListeners()
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
func onJoined(peerID: String, peersInRoom: [String: Endpoint]) {
|
|
810
|
-
isConnected = true
|
|
811
|
-
connectPromise?.resolve(nil)
|
|
812
|
-
connectPromise = nil
|
|
813
|
-
emitEndpoints()
|
|
814
|
-
peerStatus = .connected
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
func onJoinError(metadata: Any) {
|
|
818
|
-
let reason = (metadata as? [String: Any])?["reason"] as? String ?? "Unknown error"
|
|
819
|
-
connectPromise?.reject("E_MEMBRANE_CONNECT", "Failed to join room, reason: \(reason)")
|
|
820
|
-
connectPromise = nil
|
|
821
|
-
}
|
|
822
|
-
|
|
823
|
-
private func addOrUpdateTrack(_ track: Track) {
|
|
824
|
-
if track is RemoteAudioTrack {
|
|
825
|
-
(track as! RemoteAudioTrack).setVadChangedListener { track in
|
|
826
|
-
self.emitEndpoints()
|
|
827
|
-
}
|
|
828
|
-
}
|
|
829
|
-
|
|
830
|
-
if track is RemoteVideoTrack {
|
|
831
|
-
(track as! RemoteVideoTrack).setOnEncodingChangedListener { track in
|
|
832
|
-
self.emitEndpoints()
|
|
833
|
-
}
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
RNFishjamClient.tracksUpdateListenersManager.notifyListeners()
|
|
837
|
-
|
|
838
|
-
emitEndpoints()
|
|
839
|
-
}
|
|
840
|
-
|
|
841
|
-
func onTrackReady(track: Track) {
|
|
842
|
-
addOrUpdateTrack(track)
|
|
843
|
-
}
|
|
844
|
-
|
|
845
|
-
func onTrackAdded(track: Track) {
|
|
846
|
-
emitEndpoints()
|
|
847
|
-
}
|
|
848
|
-
|
|
849
|
-
func onTrackRemoved(track: Track) {
|
|
850
|
-
emitEndpoints()
|
|
851
|
-
}
|
|
852
|
-
|
|
853
|
-
func onTrackUpdated(track: Track) {
|
|
854
|
-
emitEndpoints()
|
|
855
|
-
}
|
|
856
|
-
|
|
857
|
-
func onPeerJoined(endpoint: Endpoint) {
|
|
858
|
-
emitEndpoints()
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
func onPeerLeft(endpoint: Endpoint) {
|
|
862
|
-
emitEndpoints()
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
func onPeerUpdated(endpoint: Endpoint) {
|
|
866
|
-
emitEndpoints()
|
|
867
|
-
}
|
|
868
|
-
|
|
869
|
-
func onSocketClose(code: UInt16, reason: String) {
|
|
870
|
-
if let connectPromise = connectPromise {
|
|
871
|
-
connectPromise.reject(
|
|
872
|
-
"E_MEMBRANE_CONNECT", "Failed to connect: socket close, code: \(code), reason: \(reason)")
|
|
873
|
-
}
|
|
874
|
-
connectPromise = nil
|
|
875
|
-
peerStatus = .idle
|
|
876
|
-
}
|
|
877
|
-
|
|
878
|
-
func onSocketError(_ errorMessage: String? = nil) {
|
|
879
|
-
connectPromise?.reject("E_MEMBRANE_CONNECT", "Failed to connect: socket error\(errorMessage.map { " - \($0)" } ?? "")")
|
|
880
|
-
connectPromise = nil
|
|
881
|
-
peerStatus = .error
|
|
882
|
-
}
|
|
883
|
-
|
|
884
|
-
func onSocketOpen() {}
|
|
885
|
-
|
|
886
|
-
func onDisconnected() {
|
|
887
|
-
peerStatus = .idle
|
|
888
|
-
}
|
|
889
|
-
|
|
890
|
-
func selectAudioSessionMode(sessionMode: String) throws {
|
|
891
|
-
switch sessionMode {
|
|
892
|
-
case "videoChat":
|
|
893
|
-
self.audioSessionMode = AVAudioSession.Mode.videoChat
|
|
894
|
-
break
|
|
895
|
-
case "voiceChat":
|
|
896
|
-
self.audioSessionMode = AVAudioSession.Mode.voiceChat
|
|
897
|
-
break
|
|
898
|
-
default:
|
|
899
|
-
throw Exception(
|
|
900
|
-
name: "E_MEMBRANE_AUDIO_SESSION",
|
|
901
|
-
description:
|
|
902
|
-
"Invalid audio session mode: \(sessionMode). Supported modes: videoChat, voiceChat"
|
|
903
|
-
)
|
|
904
|
-
}
|
|
905
|
-
setAudioSessionMode()
|
|
906
|
-
}
|
|
907
|
-
|
|
908
|
-
func showAudioRoutePicker() {
|
|
909
|
-
DispatchQueue.main.sync {
|
|
910
|
-
let pickerView = AVRoutePickerView()
|
|
911
|
-
if let button = pickerView.subviews.first(where: { $0 is UIButton }) as? UIButton {
|
|
912
|
-
button.sendActions(for: .touchUpInside)
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
func startAudioSwitcher() {
|
|
918
|
-
onRouteChangeNotification()
|
|
919
|
-
}
|
|
920
|
-
|
|
921
|
-
@objc func onRouteChangeNotification() {
|
|
922
|
-
emit(event: .audioDeviceUpdate(currentRoute: AVAudioSession.sharedInstance().currentRoute))
|
|
923
|
-
}
|
|
924
|
-
|
|
925
|
-
func onBandwidthEstimationChanged(estimation: Int) {
|
|
926
|
-
emit(event: .bandwidthEstimation(estimation: estimation))
|
|
927
|
-
}
|
|
928
|
-
|
|
929
|
-
func onReconnectionStarted() {
|
|
930
|
-
reconnectionStatus = .reconnecting
|
|
931
|
-
}
|
|
932
|
-
|
|
933
|
-
func onReconnected() {
|
|
934
|
-
reconnectionStatus = .idle
|
|
935
|
-
}
|
|
936
|
-
|
|
937
|
-
func onReconnectionRetriesLimitReached() {
|
|
938
|
-
reconnectionStatus = .error
|
|
939
|
-
}
|
|
940
|
-
|
|
941
|
-
func onIncompatibleTracksDetected() {
|
|
942
|
-
// TODO: FCE-1215 Add proper url after docs are updated
|
|
943
|
-
emit(
|
|
944
|
-
event: .warning(
|
|
945
|
-
message:
|
|
946
|
-
"Incompatible track detected. This usually means your device is missing codecs negotiated for the room. Visit https://docs.fishjam.io/category/react-native-integration for information."
|
|
947
|
-
))
|
|
948
|
-
}
|
|
949
|
-
|
|
950
|
-
static func add(customSource: CustomSource) async throws {
|
|
951
|
-
try await fishjamClient?.create(customSource: customSource)
|
|
952
|
-
}
|
|
953
|
-
|
|
954
|
-
static func remove(customSource: CustomSource) {
|
|
955
|
-
fishjamClient?.remove(customSource: customSource)
|
|
956
|
-
}
|
|
957
|
-
|
|
958
|
-
public func startCallKitSessionWith(displayName: String, isVideo: Bool) throws {
|
|
959
|
-
if callKitManager == nil {
|
|
960
|
-
callKitManager = CallKitManager()
|
|
961
|
-
callKitManager?.onCallStarted = { [weak self] in
|
|
962
|
-
self?.emit(event: .callKitActionPerformed(.started))
|
|
963
|
-
}
|
|
964
|
-
callKitManager?.onCallEnded = { [weak self] in
|
|
965
|
-
self?.emit(event: .callKitActionPerformed(.ended))
|
|
966
|
-
}
|
|
967
|
-
callKitManager?.onCallFailed = { [weak self] reason in
|
|
968
|
-
self?.emit(event: .callKitActionPerformed(.failed(reason)))
|
|
969
|
-
}
|
|
970
|
-
callKitManager?.onCallMuted = { [weak self] isMuted in
|
|
971
|
-
self?.emit(event: .callKitActionPerformed(.muted(isMuted)))
|
|
972
|
-
}
|
|
973
|
-
callKitManager?.onCallHeld = { [weak self] isOnHold in
|
|
974
|
-
self?.emit(event: .callKitActionPerformed(.held(isOnHold)))
|
|
975
|
-
}
|
|
976
|
-
}
|
|
977
|
-
try callKitManager?.startCallWith(displayName: displayName, isVideo: isVideo)
|
|
978
|
-
}
|
|
979
|
-
|
|
980
|
-
public func endCallKitSession() {
|
|
981
|
-
callKitManager?.endCall()
|
|
982
|
-
}
|
|
983
|
-
|
|
984
|
-
public var hasActiveCallKitSession: Bool {
|
|
985
|
-
return callKitManager?.hasActiveCall ?? false
|
|
986
|
-
}
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
extension RNFishjamClient: CameraCapturerDeviceChangedListener {
|
|
990
|
-
func onCaptureDeviceChanged(_ device: AVCaptureDevice?) {
|
|
991
|
-
emit(
|
|
992
|
-
event: .currentCameraChanged(
|
|
993
|
-
localCamera: device?.toLocalCamera(), isCameraOn: isCameraOn, isCameraInitialized: isCameraInitialized))
|
|
994
|
-
}
|
|
995
|
-
}
|