@abrar71/lib-jitsi-meet 0.0.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/LICENSE +202 -0
- package/README.md +26 -0
- package/dist/esm/JitsiConference.js +3692 -0
- package/dist/esm/JitsiConference.js.map +1 -0
- package/dist/esm/JitsiConferenceErrors.js +126 -0
- package/dist/esm/JitsiConferenceErrors.js.map +1 -0
- package/dist/esm/JitsiConferenceEventManager.js +424 -0
- package/dist/esm/JitsiConferenceEventManager.js.map +1 -0
- package/dist/esm/JitsiConferenceEvents.js +431 -0
- package/dist/esm/JitsiConferenceEvents.js.map +1 -0
- package/dist/esm/JitsiConnection.js +187 -0
- package/dist/esm/JitsiConnection.js.map +1 -0
- package/dist/esm/JitsiConnectionErrors.js +52 -0
- package/dist/esm/JitsiConnectionErrors.js.map +1 -0
- package/dist/esm/JitsiConnectionEvents.js +57 -0
- package/dist/esm/JitsiConnectionEvents.js.map +1 -0
- package/dist/esm/JitsiMediaDevices.js +221 -0
- package/dist/esm/JitsiMediaDevices.js.map +1 -0
- package/dist/esm/JitsiMediaDevicesEvents.js +29 -0
- package/dist/esm/JitsiMediaDevicesEvents.js.map +1 -0
- package/dist/esm/JitsiMeetJS.js +499 -0
- package/dist/esm/JitsiMeetJS.js.map +1 -0
- package/dist/esm/JitsiParticipant.js +323 -0
- package/dist/esm/JitsiParticipant.js.map +1 -0
- package/dist/esm/JitsiTrackError.js +122 -0
- package/dist/esm/JitsiTrackError.js.map +1 -0
- package/dist/esm/JitsiTrackErrors.js +91 -0
- package/dist/esm/JitsiTrackErrors.js.map +1 -0
- package/dist/esm/JitsiTrackEvents.js +60 -0
- package/dist/esm/JitsiTrackEvents.js.map +1 -0
- package/dist/esm/JitsiTranscriptionStatus.js +15 -0
- package/dist/esm/JitsiTranscriptionStatus.js.map +1 -0
- package/dist/esm/modules/RTC/BridgeChannel.js +398 -0
- package/dist/esm/modules/RTC/BridgeChannel.js.map +1 -0
- package/dist/esm/modules/RTC/JitsiLocalTrack.js +896 -0
- package/dist/esm/modules/RTC/JitsiLocalTrack.js.map +1 -0
- package/dist/esm/modules/RTC/JitsiRemoteTrack.js +427 -0
- package/dist/esm/modules/RTC/JitsiRemoteTrack.js.map +1 -0
- package/dist/esm/modules/RTC/JitsiTrack.js +453 -0
- package/dist/esm/modules/RTC/JitsiTrack.js.map +1 -0
- package/dist/esm/modules/RTC/MockClasses.js +388 -0
- package/dist/esm/modules/RTC/MockClasses.js.map +1 -0
- package/dist/esm/modules/RTC/RTC.js +658 -0
- package/dist/esm/modules/RTC/RTC.js.map +1 -0
- package/dist/esm/modules/RTC/RTCUtils.js +762 -0
- package/dist/esm/modules/RTC/RTCUtils.js.map +1 -0
- package/dist/esm/modules/RTC/ScreenObtainer.js +380 -0
- package/dist/esm/modules/RTC/ScreenObtainer.js.map +1 -0
- package/dist/esm/modules/RTC/TPCUtils.js +803 -0
- package/dist/esm/modules/RTC/TPCUtils.js.map +1 -0
- package/dist/esm/modules/RTC/TraceablePeerConnection.js +2223 -0
- package/dist/esm/modules/RTC/TraceablePeerConnection.js.map +1 -0
- package/dist/esm/modules/RTCStats/DefaulLogStorage.js +35 -0
- package/dist/esm/modules/RTCStats/DefaulLogStorage.js.map +1 -0
- package/dist/esm/modules/RTCStats/RTCStats.js +219 -0
- package/dist/esm/modules/RTCStats/RTCStats.js.map +1 -0
- package/dist/esm/modules/RTCStats/RTCStatsEvents.js +92 -0
- package/dist/esm/modules/RTCStats/RTCStatsEvents.js.map +1 -0
- package/dist/esm/modules/RTCStats/interfaces.js +2 -0
- package/dist/esm/modules/RTCStats/interfaces.js.map +1 -0
- package/dist/esm/modules/browser/BrowserCapabilities.js +345 -0
- package/dist/esm/modules/browser/BrowserCapabilities.js.map +1 -0
- package/dist/esm/modules/browser/index.js +3 -0
- package/dist/esm/modules/browser/index.js.map +1 -0
- package/dist/esm/modules/connectivity/ConnectionQuality.js +389 -0
- package/dist/esm/modules/connectivity/ConnectionQuality.js.map +1 -0
- package/dist/esm/modules/connectivity/IceFailedHandling.js +84 -0
- package/dist/esm/modules/connectivity/IceFailedHandling.js.map +1 -0
- package/dist/esm/modules/connectivity/NetworkInfo.js +49 -0
- package/dist/esm/modules/connectivity/NetworkInfo.js.map +1 -0
- package/dist/esm/modules/connectivity/TrackStreamingStatus.js +453 -0
- package/dist/esm/modules/connectivity/TrackStreamingStatus.js.map +1 -0
- package/dist/esm/modules/detection/ActiveDeviceDetector.js +79 -0
- package/dist/esm/modules/detection/ActiveDeviceDetector.js.map +1 -0
- package/dist/esm/modules/detection/DetectionEvents.js +58 -0
- package/dist/esm/modules/detection/DetectionEvents.js.map +1 -0
- package/dist/esm/modules/detection/NoAudioSignalDetection.js +127 -0
- package/dist/esm/modules/detection/NoAudioSignalDetection.js.map +1 -0
- package/dist/esm/modules/detection/P2PDominantSpeakerDetection.js +47 -0
- package/dist/esm/modules/detection/P2PDominantSpeakerDetection.js.map +1 -0
- package/dist/esm/modules/detection/TrackVADEmitter.js +190 -0
- package/dist/esm/modules/detection/TrackVADEmitter.js.map +1 -0
- package/dist/esm/modules/detection/VADAudioAnalyser.js +199 -0
- package/dist/esm/modules/detection/VADAudioAnalyser.js.map +1 -0
- package/dist/esm/modules/detection/VADNoiseDetection.js +168 -0
- package/dist/esm/modules/detection/VADNoiseDetection.js.map +1 -0
- package/dist/esm/modules/detection/VADReportingService.js +203 -0
- package/dist/esm/modules/detection/VADReportingService.js.map +1 -0
- package/dist/esm/modules/detection/VADTalkMutedDetection.js +131 -0
- package/dist/esm/modules/detection/VADTalkMutedDetection.js.map +1 -0
- package/dist/esm/modules/e2ee/Context.js +274 -0
- package/dist/esm/modules/e2ee/Context.js.map +1 -0
- package/dist/esm/modules/e2ee/E2EEContext.js +158 -0
- package/dist/esm/modules/e2ee/E2EEContext.js.map +1 -0
- package/dist/esm/modules/e2ee/E2EEErrors.js +10 -0
- package/dist/esm/modules/e2ee/E2EEErrors.js.map +1 -0
- package/dist/esm/modules/e2ee/E2EEncryption.js +87 -0
- package/dist/esm/modules/e2ee/E2EEncryption.js.map +1 -0
- package/dist/esm/modules/e2ee/ExternallyManagedKeyHandler.js +24 -0
- package/dist/esm/modules/e2ee/ExternallyManagedKeyHandler.js.map +1 -0
- package/dist/esm/modules/e2ee/KeyHandler.js +137 -0
- package/dist/esm/modules/e2ee/KeyHandler.js.map +1 -0
- package/dist/esm/modules/e2ee/ManagedKeyHandler.js +182 -0
- package/dist/esm/modules/e2ee/ManagedKeyHandler.js.map +1 -0
- package/dist/esm/modules/e2ee/OlmAdapter.js +860 -0
- package/dist/esm/modules/e2ee/OlmAdapter.js.map +1 -0
- package/dist/esm/modules/e2ee/SAS.js +128 -0
- package/dist/esm/modules/e2ee/SAS.js.map +1 -0
- package/dist/esm/modules/e2ee/Worker.js +102 -0
- package/dist/esm/modules/e2ee/Worker.js.map +1 -0
- package/dist/esm/modules/e2ee/crypto-utils.js +53 -0
- package/dist/esm/modules/e2ee/crypto-utils.js.map +1 -0
- package/dist/esm/modules/e2ee/utils.js +15 -0
- package/dist/esm/modules/e2ee/utils.js.map +1 -0
- package/dist/esm/modules/e2eping/e2eping.js +314 -0
- package/dist/esm/modules/e2eping/e2eping.js.map +1 -0
- package/dist/esm/modules/flags/FeatureFlags.js +36 -0
- package/dist/esm/modules/flags/FeatureFlags.js.map +1 -0
- package/dist/esm/modules/litemode/LiteModeContext.js +50 -0
- package/dist/esm/modules/litemode/LiteModeContext.js.map +1 -0
- package/dist/esm/modules/proxyconnection/CustomSignalingLayer.js +98 -0
- package/dist/esm/modules/proxyconnection/CustomSignalingLayer.js.map +1 -0
- package/dist/esm/modules/proxyconnection/ProxyConnectionPC.js +348 -0
- package/dist/esm/modules/proxyconnection/ProxyConnectionPC.js.map +1 -0
- package/dist/esm/modules/proxyconnection/ProxyConnectionService.js +279 -0
- package/dist/esm/modules/proxyconnection/ProxyConnectionService.js.map +1 -0
- package/dist/esm/modules/proxyconnection/constants.js +14 -0
- package/dist/esm/modules/proxyconnection/constants.js.map +1 -0
- package/dist/esm/modules/qualitycontrol/CodecSelection.js +222 -0
- package/dist/esm/modules/qualitycontrol/CodecSelection.js.map +1 -0
- package/dist/esm/modules/qualitycontrol/MockClasses.js +120 -0
- package/dist/esm/modules/qualitycontrol/MockClasses.js.map +1 -0
- package/dist/esm/modules/qualitycontrol/QualityController.js +366 -0
- package/dist/esm/modules/qualitycontrol/QualityController.js.map +1 -0
- package/dist/esm/modules/qualitycontrol/ReceiveAudioController.js +73 -0
- package/dist/esm/modules/qualitycontrol/ReceiveAudioController.js.map +1 -0
- package/dist/esm/modules/qualitycontrol/ReceiveVideoController.js +216 -0
- package/dist/esm/modules/qualitycontrol/ReceiveVideoController.js.map +1 -0
- package/dist/esm/modules/qualitycontrol/SendVideoController.js +133 -0
- package/dist/esm/modules/qualitycontrol/SendVideoController.js.map +1 -0
- package/dist/esm/modules/recording/JibriSession.js +279 -0
- package/dist/esm/modules/recording/JibriSession.js.map +1 -0
- package/dist/esm/modules/recording/RecordingManager.js +257 -0
- package/dist/esm/modules/recording/RecordingManager.js.map +1 -0
- package/dist/esm/modules/recording/recordingConstants.js +21 -0
- package/dist/esm/modules/recording/recordingConstants.js.map +1 -0
- package/dist/esm/modules/recording/recordingXMLUtils.js +69 -0
- package/dist/esm/modules/recording/recordingXMLUtils.js.map +1 -0
- package/dist/esm/modules/red/red.js +108 -0
- package/dist/esm/modules/red/red.js.map +1 -0
- package/dist/esm/modules/sdp/LocalSdpMunger.js +143 -0
- package/dist/esm/modules/sdp/LocalSdpMunger.js.map +1 -0
- package/dist/esm/modules/sdp/RtxModifier.js +179 -0
- package/dist/esm/modules/sdp/RtxModifier.js.map +1 -0
- package/dist/esm/modules/sdp/SDP.js +848 -0
- package/dist/esm/modules/sdp/SDP.js.map +1 -0
- package/dist/esm/modules/sdp/SDPDiffer.js +96 -0
- package/dist/esm/modules/sdp/SDPDiffer.js.map +1 -0
- package/dist/esm/modules/sdp/SDPUtil.js +798 -0
- package/dist/esm/modules/sdp/SDPUtil.js.map +1 -0
- package/dist/esm/modules/sdp/SampleSdpStrings.js +589 -0
- package/dist/esm/modules/sdp/SampleSdpStrings.js.map +1 -0
- package/dist/esm/modules/sdp/SdpSimulcast.js +196 -0
- package/dist/esm/modules/sdp/SdpSimulcast.js.map +1 -0
- package/dist/esm/modules/sdp/SdpTransformUtil.js +337 -0
- package/dist/esm/modules/sdp/SdpTransformUtil.js.map +1 -0
- package/dist/esm/modules/sdp/constants.js +2 -0
- package/dist/esm/modules/sdp/constants.js.map +1 -0
- package/dist/esm/modules/settings/Settings.js +95 -0
- package/dist/esm/modules/settings/Settings.js.map +1 -0
- package/dist/esm/modules/statistics/AnalyticsAdapter.js +277 -0
- package/dist/esm/modules/statistics/AnalyticsAdapter.js.map +1 -0
- package/dist/esm/modules/statistics/AvgRTPStatsReporter.js +817 -0
- package/dist/esm/modules/statistics/AvgRTPStatsReporter.js.map +1 -0
- package/dist/esm/modules/statistics/LocalStatsCollector.js +149 -0
- package/dist/esm/modules/statistics/LocalStatsCollector.js.map +1 -0
- package/dist/esm/modules/statistics/PreCallTest.js +15 -0
- package/dist/esm/modules/statistics/PreCallTest.js.map +1 -0
- package/dist/esm/modules/statistics/RTPStatsCollector.js +601 -0
- package/dist/esm/modules/statistics/RTPStatsCollector.js.map +1 -0
- package/dist/esm/modules/statistics/SpeakerStats.js +163 -0
- package/dist/esm/modules/statistics/SpeakerStats.js.map +1 -0
- package/dist/esm/modules/statistics/SpeakerStatsCollector.js +161 -0
- package/dist/esm/modules/statistics/SpeakerStatsCollector.js.map +1 -0
- package/dist/esm/modules/statistics/constants.js +7 -0
- package/dist/esm/modules/statistics/constants.js.map +1 -0
- package/dist/esm/modules/statistics/statistics.js +362 -0
- package/dist/esm/modules/statistics/statistics.js.map +1 -0
- package/dist/esm/modules/util/AsyncQueue.js +102 -0
- package/dist/esm/modules/util/AsyncQueue.js.map +1 -0
- package/dist/esm/modules/util/Deferred.js +41 -0
- package/dist/esm/modules/util/Deferred.js.map +1 -0
- package/dist/esm/modules/util/EventEmitter.js +17 -0
- package/dist/esm/modules/util/EventEmitter.js.map +1 -0
- package/dist/esm/modules/util/EventEmitterForwarder.js +52 -0
- package/dist/esm/modules/util/EventEmitterForwarder.js.map +1 -0
- package/dist/esm/modules/util/Listenable.js +106 -0
- package/dist/esm/modules/util/Listenable.js.map +1 -0
- package/dist/esm/modules/util/MathUtil.js +103 -0
- package/dist/esm/modules/util/MathUtil.js.map +1 -0
- package/dist/esm/modules/util/RandomUtil.js +66 -0
- package/dist/esm/modules/util/RandomUtil.js.map +1 -0
- package/dist/esm/modules/util/Retry.js +15 -0
- package/dist/esm/modules/util/Retry.js.map +1 -0
- package/dist/esm/modules/util/ScriptUtil.js +58 -0
- package/dist/esm/modules/util/ScriptUtil.js.map +1 -0
- package/dist/esm/modules/util/StringUtils.js +21 -0
- package/dist/esm/modules/util/StringUtils.js.map +1 -0
- package/dist/esm/modules/util/TestUtils.js +14 -0
- package/dist/esm/modules/util/TestUtils.js.map +1 -0
- package/dist/esm/modules/util/UsernameGenerator.js +436 -0
- package/dist/esm/modules/util/UsernameGenerator.js.map +1 -0
- package/dist/esm/modules/util/XMLUtils.js +135 -0
- package/dist/esm/modules/util/XMLUtils.js.map +1 -0
- package/dist/esm/modules/version/ComponentsVersions.js +52 -0
- package/dist/esm/modules/version/ComponentsVersions.js.map +1 -0
- package/dist/esm/modules/videosipgw/JitsiVideoSIPGWSession.js +137 -0
- package/dist/esm/modules/videosipgw/JitsiVideoSIPGWSession.js.map +1 -0
- package/dist/esm/modules/videosipgw/VideoSIPGW.js +102 -0
- package/dist/esm/modules/videosipgw/VideoSIPGW.js.map +1 -0
- package/dist/esm/modules/videosipgw/VideoSIPGWConstants.js +65 -0
- package/dist/esm/modules/videosipgw/VideoSIPGWConstants.js.map +1 -0
- package/dist/esm/modules/watchRTC/WatchRTC.js +69 -0
- package/dist/esm/modules/watchRTC/WatchRTC.js.map +1 -0
- package/dist/esm/modules/watchRTC/functions.js +31 -0
- package/dist/esm/modules/watchRTC/functions.js.map +1 -0
- package/dist/esm/modules/watchRTC/interfaces.js +2 -0
- package/dist/esm/modules/watchRTC/interfaces.js.map +1 -0
- package/dist/esm/modules/webaudio/AudioMixer.js +74 -0
- package/dist/esm/modules/webaudio/AudioMixer.js.map +1 -0
- package/dist/esm/modules/webaudio/WebAudioUtils.js +13 -0
- package/dist/esm/modules/webaudio/WebAudioUtils.js.map +1 -0
- package/dist/esm/modules/xmpp/AVModeration.js +156 -0
- package/dist/esm/modules/xmpp/AVModeration.js.map +1 -0
- package/dist/esm/modules/xmpp/BreakoutRooms.js +230 -0
- package/dist/esm/modules/xmpp/BreakoutRooms.js.map +1 -0
- package/dist/esm/modules/xmpp/Caps.js +223 -0
- package/dist/esm/modules/xmpp/Caps.js.map +1 -0
- package/dist/esm/modules/xmpp/ChatRoom.js +1877 -0
- package/dist/esm/modules/xmpp/ChatRoom.js.map +1 -0
- package/dist/esm/modules/xmpp/ConnectionPlugin.js +37 -0
- package/dist/esm/modules/xmpp/ConnectionPlugin.js.map +1 -0
- package/dist/esm/modules/xmpp/FileSharing.js +95 -0
- package/dist/esm/modules/xmpp/FileSharing.js.map +1 -0
- package/dist/esm/modules/xmpp/JingleHelperFunctions.js +168 -0
- package/dist/esm/modules/xmpp/JingleHelperFunctions.js.map +1 -0
- package/dist/esm/modules/xmpp/JingleSession.js +166 -0
- package/dist/esm/modules/xmpp/JingleSession.js.map +1 -0
- package/dist/esm/modules/xmpp/JingleSessionPC.js +1969 -0
- package/dist/esm/modules/xmpp/JingleSessionPC.js.map +1 -0
- package/dist/esm/modules/xmpp/JingleSessionState.js +23 -0
- package/dist/esm/modules/xmpp/JingleSessionState.js.map +1 -0
- package/dist/esm/modules/xmpp/Lobby.js +384 -0
- package/dist/esm/modules/xmpp/Lobby.js.map +1 -0
- package/dist/esm/modules/xmpp/MediaSessionEvents.js +12 -0
- package/dist/esm/modules/xmpp/MediaSessionEvents.js.map +1 -0
- package/dist/esm/modules/xmpp/MockClasses.js +77 -0
- package/dist/esm/modules/xmpp/MockClasses.js.map +1 -0
- package/dist/esm/modules/xmpp/Polls.js +87 -0
- package/dist/esm/modules/xmpp/Polls.js.map +1 -0
- package/dist/esm/modules/xmpp/ResumeTask.js +149 -0
- package/dist/esm/modules/xmpp/ResumeTask.js.map +1 -0
- package/dist/esm/modules/xmpp/RoomMetadata.js +96 -0
- package/dist/esm/modules/xmpp/RoomMetadata.js.map +1 -0
- package/dist/esm/modules/xmpp/SignalingLayerImpl.js +313 -0
- package/dist/esm/modules/xmpp/SignalingLayerImpl.js.map +1 -0
- package/dist/esm/modules/xmpp/StropheErrorHandler.js +53 -0
- package/dist/esm/modules/xmpp/StropheErrorHandler.js.map +1 -0
- package/dist/esm/modules/xmpp/StropheLastSuccess.js +52 -0
- package/dist/esm/modules/xmpp/StropheLastSuccess.js.map +1 -0
- package/dist/esm/modules/xmpp/XmppConnection.js +579 -0
- package/dist/esm/modules/xmpp/XmppConnection.js.map +1 -0
- package/dist/esm/modules/xmpp/moderator.js +524 -0
- package/dist/esm/modules/xmpp/moderator.js.map +1 -0
- package/dist/esm/modules/xmpp/sha1.js +165 -0
- package/dist/esm/modules/xmpp/sha1.js.map +1 -0
- package/dist/esm/modules/xmpp/strophe.disco.js +222 -0
- package/dist/esm/modules/xmpp/strophe.disco.js.map +1 -0
- package/dist/esm/modules/xmpp/strophe.emuc.js +206 -0
- package/dist/esm/modules/xmpp/strophe.emuc.js.map +1 -0
- package/dist/esm/modules/xmpp/strophe.jingle.js +404 -0
- package/dist/esm/modules/xmpp/strophe.jingle.js.map +1 -0
- package/dist/esm/modules/xmpp/strophe.logger.js +44 -0
- package/dist/esm/modules/xmpp/strophe.logger.js.map +1 -0
- package/dist/esm/modules/xmpp/strophe.ping.js +170 -0
- package/dist/esm/modules/xmpp/strophe.ping.js.map +1 -0
- package/dist/esm/modules/xmpp/strophe.rayo.js +117 -0
- package/dist/esm/modules/xmpp/strophe.rayo.js.map +1 -0
- package/dist/esm/modules/xmpp/strophe.stream-management.js +365 -0
- package/dist/esm/modules/xmpp/strophe.stream-management.js.map +1 -0
- package/dist/esm/modules/xmpp/strophe.util.js +116 -0
- package/dist/esm/modules/xmpp/strophe.util.js.map +1 -0
- package/dist/esm/modules/xmpp/xmpp.js +973 -0
- package/dist/esm/modules/xmpp/xmpp.js.map +1 -0
- package/dist/esm/service/RTC/BridgeVideoType.js +24 -0
- package/dist/esm/service/RTC/BridgeVideoType.js.map +1 -0
- package/dist/esm/service/RTC/CameraFacingMode.js +21 -0
- package/dist/esm/service/RTC/CameraFacingMode.js.map +1 -0
- package/dist/esm/service/RTC/CodecMimeType.js +36 -0
- package/dist/esm/service/RTC/CodecMimeType.js.map +1 -0
- package/dist/esm/service/RTC/MediaDirection.js +23 -0
- package/dist/esm/service/RTC/MediaDirection.js.map +1 -0
- package/dist/esm/service/RTC/MediaType.js +20 -0
- package/dist/esm/service/RTC/MediaType.js.map +1 -0
- package/dist/esm/service/RTC/RTCEvents.js +111 -0
- package/dist/esm/service/RTC/RTCEvents.js.map +1 -0
- package/dist/esm/service/RTC/ReceiverAudioSubscription.js +27 -0
- package/dist/esm/service/RTC/ReceiverAudioSubscription.js.map +1 -0
- package/dist/esm/service/RTC/Resolutions.js +56 -0
- package/dist/esm/service/RTC/Resolutions.js.map +1 -0
- package/dist/esm/service/RTC/SignalingEvents.js +42 -0
- package/dist/esm/service/RTC/SignalingEvents.js.map +1 -0
- package/dist/esm/service/RTC/SignalingLayer.js +153 -0
- package/dist/esm/service/RTC/SignalingLayer.js.map +1 -0
- package/dist/esm/service/RTC/StandardVideoQualitySettings.js +180 -0
- package/dist/esm/service/RTC/StandardVideoQualitySettings.js.map +1 -0
- package/dist/esm/service/RTC/VideoEncoderScalabilityMode.js +36 -0
- package/dist/esm/service/RTC/VideoEncoderScalabilityMode.js.map +1 -0
- package/dist/esm/service/RTC/VideoType.js +19 -0
- package/dist/esm/service/RTC/VideoType.js.map +1 -0
- package/dist/esm/service/authentication/AuthenticationEvents.js +13 -0
- package/dist/esm/service/authentication/AuthenticationEvents.js.map +1 -0
- package/dist/esm/service/connectivity/ConnectionQualityEvents.js +13 -0
- package/dist/esm/service/connectivity/ConnectionQualityEvents.js.map +1 -0
- package/dist/esm/service/connectivity/Constants.js +3 -0
- package/dist/esm/service/connectivity/Constants.js.map +1 -0
- package/dist/esm/service/e2eping/E2ePingEvents.js +8 -0
- package/dist/esm/service/e2eping/E2ePingEvents.js.map +1 -0
- package/dist/esm/service/statistics/AnalyticsEvents.js +521 -0
- package/dist/esm/service/statistics/AnalyticsEvents.js.map +1 -0
- package/dist/esm/service/statistics/Events.js +36 -0
- package/dist/esm/service/statistics/Events.js.map +1 -0
- package/dist/esm/service/statistics/constants.js +2 -0
- package/dist/esm/service/statistics/constants.js.map +1 -0
- package/dist/esm/service/xmpp/XMPPEvents.js +359 -0
- package/dist/esm/service/xmpp/XMPPEvents.js.map +1 -0
- package/dist/esm/service/xmpp/XMPPExtensioProtocols.js +64 -0
- package/dist/esm/service/xmpp/XMPPExtensioProtocols.js.map +1 -0
- package/dist/esm/test-setup-polyfill.js +34 -0
- package/dist/esm/test-setup-polyfill.js.map +1 -0
- package/dist/esm/tools/gen-version.js +15 -0
- package/dist/esm/tools/gen-version.js.map +1 -0
- package/dist/esm/version.js +3 -0
- package/dist/esm/version.js.map +1 -0
- package/dist/umd/lib-jitsi-meet.e2ee-worker.js +484 -0
- package/dist/umd/lib-jitsi-meet.min.js +3 -0
- package/dist/umd/lib-jitsi-meet.min.js.LICENSE.txt +18 -0
- package/dist/umd/lib-jitsi-meet.min.map +1 -0
- package/package.json +93 -0
- package/types/index.d.ts +16180 -0
|
@@ -0,0 +1,896 @@
|
|
|
1
|
+
import { getLogger } from '@jitsi/logger';
|
|
2
|
+
import JitsiTrackError from '../../JitsiTrackError';
|
|
3
|
+
import { JitsiTrackErrors, TRACK_IS_DISPOSED, TRACK_NO_STREAM_FOUND } from '../../JitsiTrackErrors';
|
|
4
|
+
import { JitsiTrackEvents } from '../../JitsiTrackEvents';
|
|
5
|
+
import { CameraFacingMode } from '../../service/RTC/CameraFacingMode';
|
|
6
|
+
import { MediaType } from '../../service/RTC/MediaType';
|
|
7
|
+
import { RTCEvents } from '../../service/RTC/RTCEvents';
|
|
8
|
+
import { VideoType } from '../../service/RTC/VideoType';
|
|
9
|
+
import { AnalyticsEvents, createNoDataFromSourceEvent } from '../../service/statistics/AnalyticsEvents';
|
|
10
|
+
import RTCStats from '../RTCStats/RTCStats';
|
|
11
|
+
import { RTCStatsEvents } from '../RTCStats/RTCStatsEvents';
|
|
12
|
+
import browser from '../browser';
|
|
13
|
+
import Statistics from '../statistics/statistics';
|
|
14
|
+
import { isValidNumber } from '../util/MathUtil';
|
|
15
|
+
import JitsiTrack from './JitsiTrack';
|
|
16
|
+
import RTCUtils from './RTCUtils';
|
|
17
|
+
const logger = getLogger('rtc:JitsiLocalTrack');
|
|
18
|
+
/**
|
|
19
|
+
* Represents a single media track(either audio or video).
|
|
20
|
+
* One <tt>JitsiLocalTrack</tt> corresponds to one WebRTC MediaStreamTrack.
|
|
21
|
+
*/
|
|
22
|
+
export default class JitsiLocalTrack extends JitsiTrack {
|
|
23
|
+
/**
|
|
24
|
+
* Constructs a new JitsiLocalTrack instance.
|
|
25
|
+
*
|
|
26
|
+
* @param {Object} trackInfo
|
|
27
|
+
* @param {Object} trackInfo.constraints - The contraints used for creating the track.
|
|
28
|
+
* @param {number} trackInfo.rtcId - The ID assigned by the RTC module.
|
|
29
|
+
* @param {Object} trackInfo.stream - The WebRTC MediaStream, parent of the track.
|
|
30
|
+
* @param {Object} trackInfo.track - The underlying WebRTC MediaStreamTrack for new JitsiLocalTrack.
|
|
31
|
+
* @param {string} trackInfo.mediaType - The MediaType of the JitsiLocalTrack.
|
|
32
|
+
* @param {string} trackInfo.videoType - The VideoType of the JitsiLocalTrack.
|
|
33
|
+
* @param {Array<Object>} trackInfo.effects - The effects to be applied to the JitsiLocalTrack.
|
|
34
|
+
* @param {string} trackInfo.deviceId - The ID of the local device for this track.
|
|
35
|
+
* @param {string} trackInfo.facingMode - Thehe camera facing mode used in getUserMedia call (for mobile only).
|
|
36
|
+
* @param {string} trackInfo.sourceId - The id of the desktop sharing source, which is the Chrome media source ID,
|
|
37
|
+
* returned by Desktop Picker on Electron. NOTE: defined for desktop sharing tracks only.
|
|
38
|
+
* @param {string} trackInfo.sourceType - The type of source the track originates from.
|
|
39
|
+
*
|
|
40
|
+
* @noInheritDoc
|
|
41
|
+
*/
|
|
42
|
+
constructor({ constraints, deviceId, facingMode, mediaType, rtcId, sourceId, sourceType, stream, track, videoType, effects = [] }) {
|
|
43
|
+
super(
|
|
44
|
+
/* conference */ null, stream, track,
|
|
45
|
+
/* streamInactiveHandler */ () => this.emit(JitsiTrackEvents.LOCAL_TRACK_STOPPED, this), mediaType, videoType);
|
|
46
|
+
this._setEffectInProgress = false;
|
|
47
|
+
const effect = effects.find(e => e.isEnabled(this));
|
|
48
|
+
if (effect) {
|
|
49
|
+
this._startStreamEffect(effect);
|
|
50
|
+
}
|
|
51
|
+
const displaySurface = videoType === VideoType.DESKTOP
|
|
52
|
+
? track.getSettings().displaySurface
|
|
53
|
+
: null;
|
|
54
|
+
/**
|
|
55
|
+
* Track metadata.
|
|
56
|
+
*/
|
|
57
|
+
this.metadata = {
|
|
58
|
+
timestamp: Date.now(),
|
|
59
|
+
...displaySurface ? { displaySurface } : {}
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* The ID assigned by the RTC module on instance creation.
|
|
63
|
+
*
|
|
64
|
+
* @type {number}
|
|
65
|
+
*/
|
|
66
|
+
this.rtcId = rtcId;
|
|
67
|
+
this.sourceId = sourceId;
|
|
68
|
+
this.sourceType = sourceType ?? displaySurface;
|
|
69
|
+
// Cache the constraints of the track in case of any this track
|
|
70
|
+
// model needs to call getUserMedia again, such as when unmuting.
|
|
71
|
+
this._constraints = track.getConstraints();
|
|
72
|
+
if (mediaType === MediaType.VIDEO) {
|
|
73
|
+
if (videoType === VideoType.CAMERA) {
|
|
74
|
+
// Safari returns an empty constraints object, construct the constraints using getSettings.
|
|
75
|
+
// Firefox in "fingerprint resistance mode" does a similar thing, except a `mediaSource` key is set.
|
|
76
|
+
if (!this._constraints.height || !this._constraints.width) {
|
|
77
|
+
this._constraints = {
|
|
78
|
+
height: { ideal: this.getHeight() },
|
|
79
|
+
width: { ideal: this.getWidth() }
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
// If the constraints are still empty, fallback to the constraints used for initial gUM.
|
|
83
|
+
if (!isValidNumber(this._constraints.height.ideal) && !isValidNumber(this._constraints.width.ideal)) {
|
|
84
|
+
this._constraints.height = { ideal: constraints.height.ideal };
|
|
85
|
+
this._constraints.width = { ideal: constraints.width.ideal };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Get the resolution from the track itself since we do not know what camera capability the browser has
|
|
89
|
+
// picked for the given constraints, fallback to the constraints if MediaStreamTrack.getSettings() doesn't
|
|
90
|
+
// return the height.
|
|
91
|
+
this.resolution = this.getHeight();
|
|
92
|
+
if (!isValidNumber(this.resolution) && this._constraints.height?.ideal) {
|
|
93
|
+
this.resolution = this._constraints.height.ideal;
|
|
94
|
+
}
|
|
95
|
+
this.maxEnabledResolution = this.resolution;
|
|
96
|
+
}
|
|
97
|
+
this.deviceId = deviceId;
|
|
98
|
+
/**
|
|
99
|
+
* The <tt>Promise</tt> which represents the progress of a previously
|
|
100
|
+
* queued/scheduled {@link _setMuted} (from the point of view of
|
|
101
|
+
* {@link _queueSetMuted}).
|
|
102
|
+
*
|
|
103
|
+
* @private
|
|
104
|
+
* @type {Promise}
|
|
105
|
+
*/
|
|
106
|
+
this._prevSetMuted = Promise.resolve();
|
|
107
|
+
/**
|
|
108
|
+
* The facing mode of the camera from which this JitsiLocalTrack
|
|
109
|
+
* instance was obtained.
|
|
110
|
+
*
|
|
111
|
+
* @private
|
|
112
|
+
* @type {CameraFacingMode|undefined}
|
|
113
|
+
*/
|
|
114
|
+
this._facingMode = facingMode;
|
|
115
|
+
// Currently there is no way to know the MediaStreamTrack ended due to
|
|
116
|
+
// to device disconnect in Firefox through e.g. "readyState" property.
|
|
117
|
+
// Instead we will compare current track's label with device labels from
|
|
118
|
+
// enumerateDevices() list.
|
|
119
|
+
this._trackEnded = false;
|
|
120
|
+
/**
|
|
121
|
+
* Indicates whether data has been sent or not.
|
|
122
|
+
*/
|
|
123
|
+
this._hasSentData = false;
|
|
124
|
+
/**
|
|
125
|
+
* Used only for detection of audio problems. We want to check only once
|
|
126
|
+
* whether the track is sending data ot not. This flag is set to false
|
|
127
|
+
* after the check.
|
|
128
|
+
*/
|
|
129
|
+
this._testDataSent = true;
|
|
130
|
+
// Currently there is no way to determine with what device track was
|
|
131
|
+
// created (until getConstraints() support), however we can associate
|
|
132
|
+
// tracks with real devices obtained from enumerateDevices() call as
|
|
133
|
+
// soon as it's called.
|
|
134
|
+
// NOTE: this.deviceId corresponds to the device id specified in GUM constraints and this._realDeviceId seems to
|
|
135
|
+
// correspond to the id of a matching device from the available device list.
|
|
136
|
+
this._realDeviceId = this.deviceId === '' ? undefined : this.deviceId;
|
|
137
|
+
// The source name that will be signaled for this track.
|
|
138
|
+
this._sourceName = null;
|
|
139
|
+
// The primary SSRC associated with the local media track. This will be set after the local desc
|
|
140
|
+
// is processed once the track is added to the peerconnection.
|
|
141
|
+
this._ssrc = null;
|
|
142
|
+
this._trackMutedTS = 0;
|
|
143
|
+
this._onDeviceListWillChange = (devices) => {
|
|
144
|
+
const oldRealDeviceId = this._realDeviceId;
|
|
145
|
+
this._setRealDeviceIdFromDeviceList(devices);
|
|
146
|
+
if (
|
|
147
|
+
// Mark track as ended for those browsers that do not support
|
|
148
|
+
// "readyState" property. We do not touch tracks created with
|
|
149
|
+
// default device ID "".
|
|
150
|
+
(typeof this.getTrack().readyState === 'undefined'
|
|
151
|
+
&& typeof this._realDeviceId !== 'undefined'
|
|
152
|
+
&& !devices.find(d => d.deviceId === this._realDeviceId))
|
|
153
|
+
// If there was an associated realDeviceID and after the device change the realDeviceId is undefined
|
|
154
|
+
// then the associated device has been disconnected and the _trackEnded flag needs to be set. In
|
|
155
|
+
// addition on some Chrome versions the readyState property is set after the device change event is
|
|
156
|
+
// triggered which causes issues in jitsi-meet with the selection of a new device because we don't
|
|
157
|
+
// detect that the old one was removed.
|
|
158
|
+
|| (typeof oldRealDeviceId !== 'undefined' && typeof this._realDeviceId === 'undefined')) {
|
|
159
|
+
this._trackEnded = true;
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
// Subscribe each created local audio track to
|
|
163
|
+
// RTCEvents.AUDIO_OUTPUT_DEVICE_CHANGED event. This is different from
|
|
164
|
+
// handling this event for remote tracks (which are handled in RTC.js),
|
|
165
|
+
// because there might be local tracks not attached to a conference.
|
|
166
|
+
if (this.isAudioTrack() && RTCUtils.isDeviceChangeAvailable('output')) {
|
|
167
|
+
this._onAudioOutputDeviceChanged = this.setAudioOutput.bind(this);
|
|
168
|
+
RTCUtils.addListener(RTCEvents.AUDIO_OUTPUT_DEVICE_CHANGED, this._onAudioOutputDeviceChanged);
|
|
169
|
+
}
|
|
170
|
+
RTCUtils.addListener(RTCEvents.DEVICE_LIST_WILL_CHANGE, this._onDeviceListWillChange);
|
|
171
|
+
this._initNoDataFromSourceHandlers();
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Adds stream to conference and marks it as "unmute" operation.
|
|
175
|
+
*
|
|
176
|
+
* @private
|
|
177
|
+
* @returns {Promise}
|
|
178
|
+
*/
|
|
179
|
+
_addStreamToConferenceAsUnmute() {
|
|
180
|
+
if (!this.conference) {
|
|
181
|
+
return Promise.resolve();
|
|
182
|
+
}
|
|
183
|
+
// FIXME it would be good to not included conference as part of this process. Only TraceablePeerConnections to
|
|
184
|
+
// which the track is attached should care about this action. The TPCs to which the track is not attached can
|
|
185
|
+
// sync up when track is re-attached. A problem with that is that the "modify sources" queue is part of the
|
|
186
|
+
// JingleSessionPC and it would be excluded from the process. One solution would be to extract class between
|
|
187
|
+
// TPC and JingleSessionPC which would contain the queue and would notify the signaling layer when local SSRCs
|
|
188
|
+
// are changed. This would help to separate XMPP from the RTC module.
|
|
189
|
+
return new Promise((resolve, reject) => {
|
|
190
|
+
this.conference._addLocalTrackToPc(this)
|
|
191
|
+
.then(resolve, (error) => reject(new Error(error)));
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Fires NO_DATA_FROM_SOURCE event and logs it to analytics
|
|
196
|
+
*
|
|
197
|
+
* @private
|
|
198
|
+
* @returns {void}
|
|
199
|
+
*/
|
|
200
|
+
_fireNoDataFromSourceEvent() {
|
|
201
|
+
const value = !this.isReceivingData();
|
|
202
|
+
this.emit(JitsiTrackEvents.NO_DATA_FROM_SOURCE, value);
|
|
203
|
+
logger.debug(`NO_DATA_FROM_SOURCE event with value ${value} detected for track: ${this}`);
|
|
204
|
+
// FIXME: Should we report all of those events
|
|
205
|
+
Statistics.sendAnalytics(createNoDataFromSourceEvent(this.getType(), value));
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Sets handlers to the MediaStreamTrack object that will detect camera issues.
|
|
209
|
+
*
|
|
210
|
+
* @private
|
|
211
|
+
* @returns {void}
|
|
212
|
+
*/
|
|
213
|
+
_initNoDataFromSourceHandlers() {
|
|
214
|
+
if (!this._isNoDataFromSourceEventsEnabled()) {
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
this._setHandler('track_mute', () => {
|
|
218
|
+
this._trackMutedTS = window.performance.now();
|
|
219
|
+
this._fireNoDataFromSourceEvent();
|
|
220
|
+
});
|
|
221
|
+
this._setHandler('track_unmute', () => {
|
|
222
|
+
this._fireNoDataFromSourceEvent();
|
|
223
|
+
Statistics.sendAnalyticsAndLog(AnalyticsEvents.TRACK_UNMUTED, {
|
|
224
|
+
'media_type': this.getType(),
|
|
225
|
+
'track_type': 'local',
|
|
226
|
+
value: window.performance.now() - this._trackMutedTS
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
if (this.isVideoTrack() && this.videoType === VideoType.CAMERA) {
|
|
230
|
+
this._setHandler('track_ended', () => {
|
|
231
|
+
if (!this.isReceivingData()) {
|
|
232
|
+
this._fireNoDataFromSourceEvent();
|
|
233
|
+
}
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Returns true if no data from source events are enabled for this JitsiLocalTrack and false otherwise.
|
|
239
|
+
*
|
|
240
|
+
* @private
|
|
241
|
+
* @returns {boolean} - True if no data from source events are enabled for this JitsiLocalTrack and false otherwise.
|
|
242
|
+
*/
|
|
243
|
+
_isNoDataFromSourceEventsEnabled() {
|
|
244
|
+
// Disable the events for screen sharing.
|
|
245
|
+
return !this.isVideoTrack() || this.videoType !== VideoType.DESKTOP;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Initializes a new Promise to execute {@link #_setMuted}. May be called multiple times in a row and the
|
|
249
|
+
* invocations of {@link #_setMuted} and, consequently, {@link #mute} and/or {@link #unmute} will be resolved in a
|
|
250
|
+
* serialized fashion.
|
|
251
|
+
*
|
|
252
|
+
* @param {boolean} muted - The value to invoke <tt>_setMuted</tt> with.
|
|
253
|
+
* @private
|
|
254
|
+
* @returns {Promise}
|
|
255
|
+
*/
|
|
256
|
+
_queueSetMuted(muted) {
|
|
257
|
+
const setMuted = this._setMuted.bind(this, muted);
|
|
258
|
+
this._prevSetMuted = this._prevSetMuted.then(setMuted, setMuted);
|
|
259
|
+
return this._prevSetMuted;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Removes stream from conference and marks it as "mute" operation.
|
|
263
|
+
*
|
|
264
|
+
* @param {Function} successCallback - Callback that will be called when the operation is successful.
|
|
265
|
+
* @param {Function} errorCallback - Callback that will be called when the operation fails.
|
|
266
|
+
* @private
|
|
267
|
+
* @returns {Promise}
|
|
268
|
+
*/
|
|
269
|
+
_removeStreamFromConferenceAsMute(successCallback, errorCallback) {
|
|
270
|
+
if (!this.conference) {
|
|
271
|
+
successCallback();
|
|
272
|
+
return;
|
|
273
|
+
}
|
|
274
|
+
this.conference._removeLocalTrackFromPc(this).then(successCallback, (error) => errorCallback(new Error(error)));
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Mutes / unmutes this track.
|
|
278
|
+
*
|
|
279
|
+
* @param {boolean} muted - If <tt>true</tt>, this track will be muted; otherwise, this track will be unmuted.
|
|
280
|
+
* @private
|
|
281
|
+
* @returns {Promise}
|
|
282
|
+
*/
|
|
283
|
+
_setMuted(muted) {
|
|
284
|
+
if (this.isMuted() === muted && this.videoType !== VideoType.DESKTOP) {
|
|
285
|
+
return Promise.resolve();
|
|
286
|
+
}
|
|
287
|
+
if (this.disposed) {
|
|
288
|
+
return Promise.reject(new JitsiTrackError(TRACK_IS_DISPOSED));
|
|
289
|
+
}
|
|
290
|
+
let promise = Promise.resolve();
|
|
291
|
+
// A function that will print info about muted status transition
|
|
292
|
+
const logMuteInfo = () => logger.info(`Mute ${this}: ${muted}`);
|
|
293
|
+
// In React Native we mute the camera by setting track.enabled but that doesn't
|
|
294
|
+
// work for screen-share tracks, so do the remove-as-mute for those.
|
|
295
|
+
const doesVideoMuteByStreamRemove = browser.isReactNative() ? this.videoType === VideoType.DESKTOP : browser.doesVideoMuteByStreamRemove();
|
|
296
|
+
// In the multi-stream mode, desktop tracks are muted from jitsi-meet instead of being removed from the
|
|
297
|
+
// conference. This is needed because we don't want the client to signal a source-remove to the remote peer for
|
|
298
|
+
// the desktop track when screenshare is stopped. Later when screenshare is started again, the same sender will
|
|
299
|
+
// be re-used without the need for signaling a new ssrc through source-add.
|
|
300
|
+
if (this.isAudioTrack() || !doesVideoMuteByStreamRemove) {
|
|
301
|
+
logMuteInfo();
|
|
302
|
+
// If we have a stream effect that implements its own mute functionality, prioritize it before
|
|
303
|
+
// normal mute e.g. the stream effect that implements system audio sharing has a custom
|
|
304
|
+
// mute state in which if the user mutes, system audio still has to go through.
|
|
305
|
+
if (this._streamEffect?.setMuted) {
|
|
306
|
+
this._streamEffect.setMuted(muted);
|
|
307
|
+
}
|
|
308
|
+
else if (this.track) {
|
|
309
|
+
this.track.enabled = !muted;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
else if (muted) {
|
|
313
|
+
promise = new Promise((resolve, reject) => {
|
|
314
|
+
logMuteInfo();
|
|
315
|
+
this._removeStreamFromConferenceAsMute(() => {
|
|
316
|
+
if (this._streamEffect) {
|
|
317
|
+
this._stopStreamEffect();
|
|
318
|
+
}
|
|
319
|
+
// FIXME: Maybe here we should set the SRC for the
|
|
320
|
+
// containers to something
|
|
321
|
+
// We don't want any events to be fired on this stream
|
|
322
|
+
this._unregisterHandlers();
|
|
323
|
+
this.stopStream();
|
|
324
|
+
this._setStream(null);
|
|
325
|
+
resolve();
|
|
326
|
+
}, reject);
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
else {
|
|
330
|
+
logMuteInfo();
|
|
331
|
+
let streamOptions;
|
|
332
|
+
if (this.videoType === VideoType.CAMERA) {
|
|
333
|
+
streamOptions = {
|
|
334
|
+
cameraDeviceId: this.getDeviceId(),
|
|
335
|
+
devices: [MediaType.VIDEO],
|
|
336
|
+
effects: this._streamEffect ? [this._streamEffect] : [],
|
|
337
|
+
facingMode: this.getCameraFacingMode()
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
streamOptions = {
|
|
342
|
+
devices: [MediaType.DESKTOP],
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
promise
|
|
346
|
+
= RTCUtils.obtainAudioAndVideoPermissions({
|
|
347
|
+
...streamOptions,
|
|
348
|
+
constraints: { video: this._constraints }
|
|
349
|
+
});
|
|
350
|
+
promise = promise.then((streamsInfo) => {
|
|
351
|
+
const streamInfo = streamsInfo.find(info => info.track.kind === this.getType());
|
|
352
|
+
if (streamInfo) {
|
|
353
|
+
this._setStream(streamInfo.stream);
|
|
354
|
+
this.track = streamInfo.track;
|
|
355
|
+
// This is not good when video type changes after
|
|
356
|
+
// unmute, but let's not crash here
|
|
357
|
+
if (this.videoType !== streamInfo.videoType) {
|
|
358
|
+
logger.warn(`${this}: video type has changed after unmute!`, this.videoType, streamInfo.videoType);
|
|
359
|
+
this.videoType = streamInfo.videoType;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
throw new JitsiTrackError(TRACK_NO_STREAM_FOUND);
|
|
364
|
+
}
|
|
365
|
+
if (this._streamEffect) {
|
|
366
|
+
this._startStreamEffect(this._streamEffect);
|
|
367
|
+
}
|
|
368
|
+
this.containers.map(cont => RTCUtils.attachMediaStream(cont, this.stream).catch(() => {
|
|
369
|
+
logger.error(`Attach media failed for ${this} on video unmute!`);
|
|
370
|
+
}));
|
|
371
|
+
return this._addStreamToConferenceAsUnmute();
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
return promise
|
|
375
|
+
.then(() => {
|
|
376
|
+
this._sendMuteStatus(muted);
|
|
377
|
+
const event = this.isAudioTrack() ? RTCStatsEvents.AUDIO_MUTE_CHANGED_EVENT : RTCStatsEvents.VIDEO_MUTE_CHANGED_EVENT;
|
|
378
|
+
RTCStats.sendStatsEntry(event, null, muted);
|
|
379
|
+
// Send the videoType message to the bridge.
|
|
380
|
+
this.isVideoTrack() && this.conference?._sendBridgeVideoTypeMessage(this);
|
|
381
|
+
this.emit(JitsiTrackEvents.TRACK_MUTE_CHANGED, this);
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Sets real device ID by comparing track information with device information. This is temporary solution until
|
|
386
|
+
* getConstraints() method will be implemented in browsers.
|
|
387
|
+
*
|
|
388
|
+
* @param {MediaDeviceInfo[]} devices - The list of devices obtained from enumerateDevices() call.
|
|
389
|
+
* @private
|
|
390
|
+
* @returns {void}
|
|
391
|
+
*/
|
|
392
|
+
_setRealDeviceIdFromDeviceList(devices) {
|
|
393
|
+
const track = this.getTrack();
|
|
394
|
+
const kind = `${track.kind}input`;
|
|
395
|
+
// We need to match by deviceId as well, in case of multiple devices with the same label.
|
|
396
|
+
let device = devices.find(d => d.kind === kind && d.label === track.label && d.deviceId === this.deviceId);
|
|
397
|
+
if (!device && this._realDeviceId === 'default') { // the default device has been changed.
|
|
398
|
+
// If the default device was 'A' and the default device is changed to 'B' the label for the track will
|
|
399
|
+
// remain 'Default - A' but the label for the device in the device list will be updated to 'A'. That's
|
|
400
|
+
// why in order to match it we need to remove the 'Default - ' part.
|
|
401
|
+
const label = (track.label || '').replace('Default - ', '');
|
|
402
|
+
device = devices.find(d => d.kind === kind && d.label === label);
|
|
403
|
+
}
|
|
404
|
+
if (device) {
|
|
405
|
+
this._realDeviceId = device.deviceId;
|
|
406
|
+
}
|
|
407
|
+
else {
|
|
408
|
+
this._realDeviceId = undefined;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Starts the effect process and returns the modified stream.
|
|
413
|
+
*
|
|
414
|
+
* @param {Object} effect - Represents effect instance
|
|
415
|
+
* @private
|
|
416
|
+
* @returns {void}
|
|
417
|
+
*/
|
|
418
|
+
_startStreamEffect(effect) {
|
|
419
|
+
this._streamEffect = effect;
|
|
420
|
+
this._originalStream = this.stream;
|
|
421
|
+
this._setStream(this._streamEffect.startEffect(this._originalStream));
|
|
422
|
+
this.track = this.stream.getTracks()[0];
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Stops the effect process and returns the original stream.
|
|
426
|
+
*
|
|
427
|
+
* @private
|
|
428
|
+
* @returns {void}
|
|
429
|
+
*/
|
|
430
|
+
_stopStreamEffect() {
|
|
431
|
+
if (this._streamEffect) {
|
|
432
|
+
this._streamEffect.stopEffect();
|
|
433
|
+
this._setStream(this._originalStream);
|
|
434
|
+
this._originalStream = null;
|
|
435
|
+
this.track = this.stream ? this.stream.getTracks()[0] : null;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Switches the camera facing mode if the WebRTC implementation supports the custom MediaStreamTrack._switchCamera
|
|
440
|
+
* method. Currently, the method in question is implemented in react-native-webrtc only. When such a WebRTC
|
|
441
|
+
* implementation is executing, the method is the preferred way to switch between the front/user-facing and the
|
|
442
|
+
* back/environment-facing cameras because it will likely be (as is the case of react-native-webrtc) noticeably
|
|
443
|
+
* faster that creating a new MediaStreamTrack via a new getUserMedia call with the switched facingMode constraint
|
|
444
|
+
* value. Moreover, the approach with a new getUserMedia call may not even work: WebRTC on Android and iOS is
|
|
445
|
+
* either very slow to open the camera a second time or plainly freezes attempting to do that.
|
|
446
|
+
*
|
|
447
|
+
* @returns {void}
|
|
448
|
+
*/
|
|
449
|
+
_switchCamera() {
|
|
450
|
+
if (this.isVideoTrack()
|
|
451
|
+
&& this.videoType === VideoType.CAMERA
|
|
452
|
+
&& typeof this.track._switchCamera === 'function') {
|
|
453
|
+
this.track._switchCamera();
|
|
454
|
+
this._facingMode
|
|
455
|
+
= this._facingMode === CameraFacingMode.ENVIRONMENT
|
|
456
|
+
? CameraFacingMode.USER
|
|
457
|
+
: CameraFacingMode.ENVIRONMENT;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Stops the currently used effect (if there is one) and starts the passed effect (if there is one).
|
|
462
|
+
*
|
|
463
|
+
* @param {Object|undefined} effect - The new effect to be set.
|
|
464
|
+
* @private
|
|
465
|
+
* @returns {void}
|
|
466
|
+
*/
|
|
467
|
+
_switchStreamEffect(effect) {
|
|
468
|
+
if (this._streamEffect) {
|
|
469
|
+
this._stopStreamEffect();
|
|
470
|
+
this._streamEffect = undefined;
|
|
471
|
+
}
|
|
472
|
+
if (effect) {
|
|
473
|
+
this._startStreamEffect(effect);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* @inheritdoc
|
|
478
|
+
*
|
|
479
|
+
* Stops sending the media track. And removes it from the HTML. NOTE: Works for local tracks only.
|
|
480
|
+
*
|
|
481
|
+
* @returns {Promise}
|
|
482
|
+
*/
|
|
483
|
+
async dispose() {
|
|
484
|
+
if (this.disposed) {
|
|
485
|
+
return;
|
|
486
|
+
}
|
|
487
|
+
// Remove the effect instead of stopping it so that the original stream is restored
|
|
488
|
+
// on both the local track and on the peerconnection.
|
|
489
|
+
if (this._streamEffect) {
|
|
490
|
+
await this.setEffect(undefined);
|
|
491
|
+
}
|
|
492
|
+
if (this.conference) {
|
|
493
|
+
await this.conference.removeTrack(this);
|
|
494
|
+
}
|
|
495
|
+
if (this.stream) {
|
|
496
|
+
this.stopStream();
|
|
497
|
+
}
|
|
498
|
+
RTCUtils.removeListener(RTCEvents.DEVICE_LIST_WILL_CHANGE, this._onDeviceListWillChange);
|
|
499
|
+
if (this._onAudioOutputDeviceChanged) {
|
|
500
|
+
RTCUtils.removeListener(RTCEvents.AUDIO_OUTPUT_DEVICE_CHANGED, this._onAudioOutputDeviceChanged);
|
|
501
|
+
}
|
|
502
|
+
return super.dispose();
|
|
503
|
+
}
|
|
504
|
+
/**
|
|
505
|
+
* Sends mute status for a track to conference if any.
|
|
506
|
+
*
|
|
507
|
+
* @param {boolean} mute - If track is muted.
|
|
508
|
+
* @internal
|
|
509
|
+
* @returns {void}
|
|
510
|
+
*/
|
|
511
|
+
_sendMuteStatus(mute) {
|
|
512
|
+
if (this.conference) {
|
|
513
|
+
this.conference._setTrackMuteStatus(this, mute) && this.conference.room.sendPresence();
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Returns facing mode for video track from camera. For other cases (e.g. audio track or 'desktop' video track)
|
|
518
|
+
* returns undefined.
|
|
519
|
+
*
|
|
520
|
+
* @returns {Optional<CameraFacingMode>}
|
|
521
|
+
*/
|
|
522
|
+
getCameraFacingMode() {
|
|
523
|
+
if (this.isVideoTrack() && this.videoType === VideoType.CAMERA) {
|
|
524
|
+
// MediaStreamTrack#getSettings() is not implemented in many
|
|
525
|
+
// browsers, so we need feature checking here. Progress on the
|
|
526
|
+
// respective browser's implementation can be tracked at
|
|
527
|
+
// https://bugs.chromium.org/p/webrtc/issues/detail?id=2481 for
|
|
528
|
+
// Chromium and https://bugzilla.mozilla.org/show_bug.cgi?id=1213517
|
|
529
|
+
// for Firefox. Even if a browser implements getSettings() already,
|
|
530
|
+
// it might still not return anything for 'facingMode'.
|
|
531
|
+
const trackSettings = this.track.getSettings?.();
|
|
532
|
+
if (trackSettings && 'facingMode' in trackSettings) {
|
|
533
|
+
return trackSettings.facingMode;
|
|
534
|
+
}
|
|
535
|
+
if (typeof this._facingMode !== 'undefined') {
|
|
536
|
+
return this._facingMode;
|
|
537
|
+
}
|
|
538
|
+
// In most cases we are showing a webcam. So if we've gotten here,
|
|
539
|
+
// it should be relatively safe to assume that we are probably
|
|
540
|
+
// showing the user-facing camera.
|
|
541
|
+
return CameraFacingMode.USER;
|
|
542
|
+
}
|
|
543
|
+
return undefined;
|
|
544
|
+
}
|
|
545
|
+
/**
|
|
546
|
+
* Returns the capture resolution of the video track.
|
|
547
|
+
*
|
|
548
|
+
* @returns {Number}
|
|
549
|
+
*/
|
|
550
|
+
getCaptureResolution() {
|
|
551
|
+
if (this.videoType === VideoType.CAMERA || !browser.isWebKitBased()) {
|
|
552
|
+
return this.resolution;
|
|
553
|
+
}
|
|
554
|
+
return this.getHeight();
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* Returns device id associated with track.
|
|
558
|
+
*
|
|
559
|
+
* @returns {string}
|
|
560
|
+
*/
|
|
561
|
+
getDeviceId() {
|
|
562
|
+
return this._realDeviceId || this.deviceId;
|
|
563
|
+
}
|
|
564
|
+
/**
|
|
565
|
+
* Get the duration of the track.
|
|
566
|
+
*
|
|
567
|
+
* @returns {Number} the duration of the track in seconds
|
|
568
|
+
*/
|
|
569
|
+
getDuration() {
|
|
570
|
+
return (Date.now() / 1000) - (this.metadata.timestamp / 1000);
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Returns the participant id which owns the track.
|
|
574
|
+
*
|
|
575
|
+
* @returns {string} the id of the participants. It corresponds to the
|
|
576
|
+
* Colibri endpoint id/MUC nickname in case of Jitsi-meet.
|
|
577
|
+
*/
|
|
578
|
+
getParticipantId() {
|
|
579
|
+
return this.conference?.myUserId();
|
|
580
|
+
}
|
|
581
|
+
/**
|
|
582
|
+
* Returns the source name associated with the jitsi track.
|
|
583
|
+
*
|
|
584
|
+
* @returns {Nullable<string>} source name
|
|
585
|
+
*/
|
|
586
|
+
getSourceName() {
|
|
587
|
+
return this._sourceName;
|
|
588
|
+
}
|
|
589
|
+
/**
|
|
590
|
+
* Returns the primary SSRC associated with the track.
|
|
591
|
+
* @returns {Nullable<number>}
|
|
592
|
+
*/
|
|
593
|
+
getSsrc() {
|
|
594
|
+
return this._ssrc;
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
597
|
+
* Returns if associated MediaStreamTrack is in the 'ended' state
|
|
598
|
+
*
|
|
599
|
+
* @returns {boolean}
|
|
600
|
+
*/
|
|
601
|
+
isEnded() {
|
|
602
|
+
if (this.isVideoTrack() && this.isMuted()) {
|
|
603
|
+
// If a video track is muted the readyState will be ended, that's why we need to rely only on the
|
|
604
|
+
// _trackEnded flag.
|
|
605
|
+
return this._trackEnded;
|
|
606
|
+
}
|
|
607
|
+
return this.getTrack().readyState === 'ended' || this._trackEnded;
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* Returns <tt>true</tt>.
|
|
611
|
+
*
|
|
612
|
+
* @returns {boolean} <tt>true</tt>
|
|
613
|
+
*/
|
|
614
|
+
isLocal() {
|
|
615
|
+
return true;
|
|
616
|
+
}
|
|
617
|
+
/**
|
|
618
|
+
* Returns <tt>true</tt> - if the stream is muted and <tt>false</tt> otherwise.
|
|
619
|
+
*
|
|
620
|
+
* @returns {boolean} <tt>true</tt> - if the stream is muted and <tt>false</tt> otherwise.
|
|
621
|
+
*/
|
|
622
|
+
isMuted() {
|
|
623
|
+
// this.stream will be null when we mute local video on Chrome
|
|
624
|
+
if (!this.stream) {
|
|
625
|
+
return true;
|
|
626
|
+
}
|
|
627
|
+
if (this.isVideoTrack() && !this.isActive()) {
|
|
628
|
+
return true;
|
|
629
|
+
}
|
|
630
|
+
// If currently used stream effect has its own muted state, use that.
|
|
631
|
+
if (this._streamEffect?.isMuted) {
|
|
632
|
+
return this._streamEffect.isMuted();
|
|
633
|
+
}
|
|
634
|
+
return !this.track?.enabled;
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* Checks whether the attached MediaStream is receiving data from source or not. If the stream property is null
|
|
638
|
+
* (because of mute or another reason) this method will return false.
|
|
639
|
+
* NOTE: This method doesn't indicate problem with the streams directly. For example in case of video mute the
|
|
640
|
+
* method will return false or if the user has disposed the track.
|
|
641
|
+
*
|
|
642
|
+
* @returns {boolean} true if the stream is receiving data and false this otherwise.
|
|
643
|
+
*/
|
|
644
|
+
isReceivingData() {
|
|
645
|
+
if (this.isVideoTrack()
|
|
646
|
+
&& (this.isMuted() || this._stopStreamInProgress || this.videoType === VideoType.DESKTOP)) {
|
|
647
|
+
return true;
|
|
648
|
+
}
|
|
649
|
+
if (!this.stream) {
|
|
650
|
+
return false;
|
|
651
|
+
}
|
|
652
|
+
// In older version of the spec there is no muted property and readyState can have value muted. In the latest
|
|
653
|
+
// versions readyState can have values "live" and "ended" and there is muted boolean property. If the stream is
|
|
654
|
+
// muted that means that we aren't receiving any data from the source. We want to notify the users for error if
|
|
655
|
+
// the stream is muted or ended on it's creation.
|
|
656
|
+
// For video blur enabled use the original video stream
|
|
657
|
+
const stream = this._effectEnabled ? this._originalStream : this.stream;
|
|
658
|
+
return stream.getTracks().some(track => (!('readyState' in track) || track.readyState === 'live')
|
|
659
|
+
&& (!('muted' in track) || track.muted !== true));
|
|
660
|
+
}
|
|
661
|
+
/**
|
|
662
|
+
* Asynchronously mutes this track.
|
|
663
|
+
*
|
|
664
|
+
* @returns {Promise}
|
|
665
|
+
*/
|
|
666
|
+
mute() {
|
|
667
|
+
return this._queueSetMuted(true);
|
|
668
|
+
}
|
|
669
|
+
/**
|
|
670
|
+
* Handles bytes sent statistics. NOTE: used only for audio tracks to detect audio issues.
|
|
671
|
+
*
|
|
672
|
+
* @param {TraceablePeerConnection} tpc - The peerconnection that is reporting the bytes sent stat.
|
|
673
|
+
* @param {number} bytesSent - The new value.
|
|
674
|
+
* @returns {void}
|
|
675
|
+
*/
|
|
676
|
+
onByteSentStatsReceived(tpc, bytesSent) {
|
|
677
|
+
if (bytesSent > 0) {
|
|
678
|
+
this._hasSentData = true;
|
|
679
|
+
}
|
|
680
|
+
const iceConnectionState = tpc.getConnectionState();
|
|
681
|
+
if (this._testDataSent && iceConnectionState === 'connected') {
|
|
682
|
+
setTimeout(() => {
|
|
683
|
+
if (!this._hasSentData) {
|
|
684
|
+
logger.warn(`${this} 'bytes sent' <= 0: \
|
|
685
|
+
${bytesSent}`);
|
|
686
|
+
Statistics.analytics.sendEvent(AnalyticsEvents.NO_BYTES_SENT, { 'media_type': this.getType() });
|
|
687
|
+
}
|
|
688
|
+
}, 3000);
|
|
689
|
+
this._testDataSent = false;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* Sets the JitsiConference object associated with the track. This is temp solution.
|
|
694
|
+
*
|
|
695
|
+
* @param conference - JitsiConference object.
|
|
696
|
+
* @returns {void}
|
|
697
|
+
*/
|
|
698
|
+
setConference(conference) {
|
|
699
|
+
this.conference = conference;
|
|
700
|
+
}
|
|
701
|
+
/**
|
|
702
|
+
* Sets the effect and switches between the modified stream and original one.
|
|
703
|
+
*
|
|
704
|
+
* @param {Object} effect - Represents the effect instance to be used.
|
|
705
|
+
* @returns {Promise}
|
|
706
|
+
*/
|
|
707
|
+
setEffect(effect) {
|
|
708
|
+
if (typeof this._streamEffect === 'undefined' && typeof effect === 'undefined') {
|
|
709
|
+
return Promise.resolve();
|
|
710
|
+
}
|
|
711
|
+
if (typeof effect !== 'undefined' && !effect.isEnabled(this)) {
|
|
712
|
+
return Promise.reject(new Error('Incompatible effect instance!'));
|
|
713
|
+
}
|
|
714
|
+
if (this._setEffectInProgress === true) {
|
|
715
|
+
return Promise.reject(new Error('setEffect already in progress!'));
|
|
716
|
+
}
|
|
717
|
+
// In case we have an audio track that is being enhanced with an effect, we still want it to be applied,
|
|
718
|
+
// even if the track is muted. Where as for video the actual track doesn't exists if it's muted.
|
|
719
|
+
if (this.isMuted() && !this.isAudioTrack()) {
|
|
720
|
+
this._streamEffect = effect;
|
|
721
|
+
return Promise.resolve();
|
|
722
|
+
}
|
|
723
|
+
const conference = this.conference;
|
|
724
|
+
if (!conference) {
|
|
725
|
+
this._switchStreamEffect(effect);
|
|
726
|
+
if (this.isVideoTrack()) {
|
|
727
|
+
this.containers.forEach(cont => {
|
|
728
|
+
RTCUtils.attachMediaStream(cont, this.stream).catch(() => {
|
|
729
|
+
logger.error(`Attach media failed for ${this} when trying to set effect.`);
|
|
730
|
+
});
|
|
731
|
+
});
|
|
732
|
+
}
|
|
733
|
+
return Promise.resolve();
|
|
734
|
+
}
|
|
735
|
+
this._setEffectInProgress = true;
|
|
736
|
+
return conference._removeLocalTrackFromPc(this)
|
|
737
|
+
.then(() => {
|
|
738
|
+
this._switchStreamEffect(effect);
|
|
739
|
+
if (this.isVideoTrack()) {
|
|
740
|
+
this.containers.forEach(cont => {
|
|
741
|
+
RTCUtils.attachMediaStream(cont, this.stream).catch(() => {
|
|
742
|
+
logger.error(`Attach media failed for ${this} when trying to set effect.`);
|
|
743
|
+
});
|
|
744
|
+
});
|
|
745
|
+
}
|
|
746
|
+
return conference._addLocalTrackToPc(this);
|
|
747
|
+
})
|
|
748
|
+
.then(() => {
|
|
749
|
+
this._setEffectInProgress = false;
|
|
750
|
+
})
|
|
751
|
+
.catch((error) => {
|
|
752
|
+
// Any error will be not recovarable and will trigger CONFERENCE_FAILED event. But let's try to cleanup
|
|
753
|
+
// everyhting related to the effect functionality.
|
|
754
|
+
this._setEffectInProgress = false;
|
|
755
|
+
this._switchStreamEffect();
|
|
756
|
+
logger.error('Failed to switch to the new stream!', error);
|
|
757
|
+
throw error;
|
|
758
|
+
});
|
|
759
|
+
}
|
|
760
|
+
/**
|
|
761
|
+
* Sets the source name to be used for signaling the jitsi track.
|
|
762
|
+
*
|
|
763
|
+
* @param {string} name The source name.
|
|
764
|
+
* @internal
|
|
765
|
+
*/
|
|
766
|
+
setSourceName(name) {
|
|
767
|
+
this._sourceName = name;
|
|
768
|
+
}
|
|
769
|
+
/**
|
|
770
|
+
* Sets the primary SSRC for the track.
|
|
771
|
+
*
|
|
772
|
+
* @param {number} ssrc The SSRC.
|
|
773
|
+
*/
|
|
774
|
+
setSsrc(ssrc) {
|
|
775
|
+
if (isValidNumber(ssrc)) {
|
|
776
|
+
this._ssrc = ssrc;
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
/**
|
|
780
|
+
* Stops the associated MediaStream.
|
|
781
|
+
*
|
|
782
|
+
* @returns {void}
|
|
783
|
+
*/
|
|
784
|
+
stopStream() {
|
|
785
|
+
/**
|
|
786
|
+
* Indicates that we are executing {@link #stopStream} i.e.
|
|
787
|
+
* {@link RTCUtils#stopMediaStream} for the <tt>MediaStream</tt>
|
|
788
|
+
* associated with this <tt>JitsiTrack</tt> instance.
|
|
789
|
+
*
|
|
790
|
+
* @private
|
|
791
|
+
* @type {boolean}
|
|
792
|
+
*/
|
|
793
|
+
this._stopStreamInProgress = true;
|
|
794
|
+
try {
|
|
795
|
+
RTCUtils.stopMediaStream(this.stream);
|
|
796
|
+
}
|
|
797
|
+
finally {
|
|
798
|
+
this._stopStreamInProgress = false;
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
/**
|
|
802
|
+
* Creates a text representation of this local track instance.
|
|
803
|
+
*
|
|
804
|
+
* @return {string}
|
|
805
|
+
*/
|
|
806
|
+
toString() {
|
|
807
|
+
return `LocalTrack[${this.rtcId},${this.getType()}]`;
|
|
808
|
+
}
|
|
809
|
+
/**
|
|
810
|
+
* Asynchronously unmutes this track.
|
|
811
|
+
*
|
|
812
|
+
* @returns {Promise}
|
|
813
|
+
*/
|
|
814
|
+
unmute() {
|
|
815
|
+
return this._queueSetMuted(false);
|
|
816
|
+
}
|
|
817
|
+
/**
|
|
818
|
+
* Applies media constraints to the current MediaStreamTrack.
|
|
819
|
+
*
|
|
820
|
+
* @param {IAudioConstraints} constraints - Media constraints to apply.
|
|
821
|
+
* @returns {Promise<void>}
|
|
822
|
+
*/
|
|
823
|
+
async applyConstraints(constraints) {
|
|
824
|
+
const mediaType = this.getType();
|
|
825
|
+
if (!this.isAudioTrack()) {
|
|
826
|
+
throw new Error(`Media ${mediaType} is not supported, track must be audio`);
|
|
827
|
+
}
|
|
828
|
+
const hasAudioMixEffect = typeof this._streamEffect?.setMuted === 'function';
|
|
829
|
+
if (this._streamEffect && !hasAudioMixEffect) {
|
|
830
|
+
throw new Error(`Cannot apply constraints while the effect ${JSON.stringify(this._streamEffect)} is active`);
|
|
831
|
+
}
|
|
832
|
+
const hasConference = Boolean(this.conference);
|
|
833
|
+
let audioAnalyser;
|
|
834
|
+
if (hasConference) {
|
|
835
|
+
audioAnalyser = this.conference.getAudioAnalyser();
|
|
836
|
+
if (audioAnalyser) {
|
|
837
|
+
logger.debug(`Removing track ${this} from audio analyser`);
|
|
838
|
+
audioAnalyser._trackRemoved(this);
|
|
839
|
+
}
|
|
840
|
+
logger.debug(`Removing track ${this} from conference`);
|
|
841
|
+
await this.conference._removeLocalTrackFromPc(this);
|
|
842
|
+
}
|
|
843
|
+
const isMuted = this.isMuted();
|
|
844
|
+
if (hasAudioMixEffect) {
|
|
845
|
+
this._stopStreamEffect();
|
|
846
|
+
}
|
|
847
|
+
this.stopStream();
|
|
848
|
+
const initialSettings = this.track.getSettings();
|
|
849
|
+
const constraintsToApply = {
|
|
850
|
+
...initialSettings,
|
|
851
|
+
...constraints
|
|
852
|
+
};
|
|
853
|
+
const deviceIdKey = mediaType === MediaType.AUDIO ? 'micDeviceId' : 'cameraDeviceId';
|
|
854
|
+
let mediaStreamData;
|
|
855
|
+
try {
|
|
856
|
+
logger.debug(`applyConstraints for track ${this} with constraints: ${JSON.stringify(constraints)}`);
|
|
857
|
+
[mediaStreamData] = await RTCUtils.obtainAudioAndVideoPermissions({
|
|
858
|
+
constraints: { [mediaType]: constraintsToApply },
|
|
859
|
+
[deviceIdKey]: constraintsToApply.deviceId,
|
|
860
|
+
devices: [mediaType]
|
|
861
|
+
});
|
|
862
|
+
if (!mediaStreamData?.stream) {
|
|
863
|
+
throw new JitsiTrackError(JitsiTrackErrors.CONSTRAINT_FAILED);
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
catch (error) {
|
|
867
|
+
logger.error(`applyConstraints failed for track ${this} with constraints: ${JSON.stringify(constraints)}: `, error);
|
|
868
|
+
[mediaStreamData] = await RTCUtils.obtainAudioAndVideoPermissions({
|
|
869
|
+
constraints: { [mediaType]: initialSettings },
|
|
870
|
+
[deviceIdKey]: constraintsToApply.deviceId,
|
|
871
|
+
devices: [mediaType]
|
|
872
|
+
});
|
|
873
|
+
}
|
|
874
|
+
if (!mediaStreamData?.stream) {
|
|
875
|
+
throw new JitsiTrackError(JitsiTrackErrors.GENERAL);
|
|
876
|
+
}
|
|
877
|
+
logger.debug('Setting updated stream and track');
|
|
878
|
+
this._setStream(mediaStreamData.stream);
|
|
879
|
+
this.track = mediaStreamData.track;
|
|
880
|
+
if (hasAudioMixEffect) {
|
|
881
|
+
this._startStreamEffect(this._streamEffect);
|
|
882
|
+
}
|
|
883
|
+
if (isMuted) {
|
|
884
|
+
this._setMuted(true);
|
|
885
|
+
}
|
|
886
|
+
if (hasConference) {
|
|
887
|
+
logger.debug(`Adding track ${this} to conference`);
|
|
888
|
+
await this.conference._addLocalTrackToPc(this);
|
|
889
|
+
if (audioAnalyser) {
|
|
890
|
+
logger.debug(`Adding track ${this} to audio analyser`);
|
|
891
|
+
audioAnalyser._trackAdded(this);
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
//# sourceMappingURL=JitsiLocalTrack.js.map
|