diff options
author | RaindropsSys <contact@minteck.org> | 2023-04-24 14:03:36 +0200 |
---|---|---|
committer | RaindropsSys <contact@minteck.org> | 2023-04-24 14:03:36 +0200 |
commit | 633c92eae865e957121e08de634aeee11a8b3992 (patch) | |
tree | 09d881bee1dae0b6eee49db1dfaf0f500240606c /includes/external/matrix/node_modules/matrix-js-sdk/lib/webrtc/callFeed.js | |
parent | c4657e4509733699c0f26a3c900bab47e915d5a0 (diff) | |
download | pluralconnect-633c92eae865e957121e08de634aeee11a8b3992.tar.gz pluralconnect-633c92eae865e957121e08de634aeee11a8b3992.tar.bz2 pluralconnect-633c92eae865e957121e08de634aeee11a8b3992.zip |
Updated 18 files, added 1692 files and deleted includes/system/compare.inc (automated)
Diffstat (limited to 'includes/external/matrix/node_modules/matrix-js-sdk/lib/webrtc/callFeed.js')
-rw-r--r-- | includes/external/matrix/node_modules/matrix-js-sdk/lib/webrtc/callFeed.js | 296 |
1 files changed, 296 insertions, 0 deletions
diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/lib/webrtc/callFeed.js b/includes/external/matrix/node_modules/matrix-js-sdk/lib/webrtc/callFeed.js new file mode 100644 index 0000000..3638765 --- /dev/null +++ b/includes/external/matrix/node_modules/matrix-js-sdk/lib/webrtc/callFeed.js @@ -0,0 +1,296 @@ +"use strict"; + +var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.SPEAKING_THRESHOLD = exports.CallFeedEvent = exports.CallFeed = void 0; +var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); +var _callEventTypes = require("./callEventTypes"); +var _audioContext = require("./audioContext"); +var _logger = require("../logger"); +var _typedEventEmitter = require("../models/typed-event-emitter"); +var _call = require("./call"); +/* +Copyright 2021 Šimon Brandner <simon.bra.ag@gmail.com> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +const POLLING_INTERVAL = 200; // ms +const SPEAKING_THRESHOLD = -60; // dB +exports.SPEAKING_THRESHOLD = SPEAKING_THRESHOLD; +const SPEAKING_SAMPLE_COUNT = 8; // samples +let CallFeedEvent; +exports.CallFeedEvent = CallFeedEvent; +(function (CallFeedEvent) { + CallFeedEvent["NewStream"] = "new_stream"; + CallFeedEvent["MuteStateChanged"] = "mute_state_changed"; + CallFeedEvent["LocalVolumeChanged"] = "local_volume_changed"; + CallFeedEvent["VolumeChanged"] = "volume_changed"; + CallFeedEvent["ConnectedChanged"] = "connected_changed"; + CallFeedEvent["Speaking"] = "speaking"; + CallFeedEvent["Disposed"] = "disposed"; +})(CallFeedEvent || (exports.CallFeedEvent = CallFeedEvent = {})); +class CallFeed extends _typedEventEmitter.TypedEventEmitter { + constructor(opts) { + super(); + (0, _defineProperty2.default)(this, "stream", void 0); + (0, _defineProperty2.default)(this, "sdpMetadataStreamId", void 0); + (0, _defineProperty2.default)(this, "userId", void 0); + (0, _defineProperty2.default)(this, "deviceId", void 0); + (0, _defineProperty2.default)(this, "purpose", void 0); + (0, _defineProperty2.default)(this, "speakingVolumeSamples", void 0); + (0, _defineProperty2.default)(this, "client", void 0); + (0, _defineProperty2.default)(this, "call", void 0); + (0, _defineProperty2.default)(this, "roomId", void 0); + (0, _defineProperty2.default)(this, "audioMuted", void 0); + (0, _defineProperty2.default)(this, "videoMuted", void 0); + (0, _defineProperty2.default)(this, "localVolume", 1); + (0, _defineProperty2.default)(this, "measuringVolumeActivity", false); + (0, _defineProperty2.default)(this, "audioContext", void 0); + (0, _defineProperty2.default)(this, "analyser", void 0); + (0, _defineProperty2.default)(this, "frequencyBinCount", void 0); + (0, _defineProperty2.default)(this, "speakingThreshold", SPEAKING_THRESHOLD); + (0, _defineProperty2.default)(this, "speaking", false); + (0, _defineProperty2.default)(this, "volumeLooperTimeout", void 0); + (0, _defineProperty2.default)(this, "_disposed", false); + (0, _defineProperty2.default)(this, "_connected", false); + (0, _defineProperty2.default)(this, "onAddTrack", () => { + this.emit(CallFeedEvent.NewStream, this.stream); + }); + (0, _defineProperty2.default)(this, "onCallState", state => { + if (state === _call.CallState.Connected) { + this.connected = true; + } else if (state === _call.CallState.Connecting) { + this.connected = false; + } + }); + (0, _defineProperty2.default)(this, "volumeLooper", () => { + if (!this.analyser) return; + if (!this.measuringVolumeActivity) return; + this.analyser.getFloatFrequencyData(this.frequencyBinCount); + let maxVolume = -Infinity; + for (const volume of this.frequencyBinCount) { + if (volume > maxVolume) { + maxVolume = volume; + } + } + this.speakingVolumeSamples.shift(); + this.speakingVolumeSamples.push(maxVolume); + this.emit(CallFeedEvent.VolumeChanged, maxVolume); + let newSpeaking = false; + for (const volume of this.speakingVolumeSamples) { + if (volume > this.speakingThreshold) { + newSpeaking = true; + break; + } + } + if (this.speaking !== newSpeaking) { + this.speaking = newSpeaking; + this.emit(CallFeedEvent.Speaking, this.speaking); + } + this.volumeLooperTimeout = setTimeout(this.volumeLooper, POLLING_INTERVAL); + }); + this.client = opts.client; + this.call = opts.call; + this.roomId = opts.roomId; + this.userId = opts.userId; + this.deviceId = opts.deviceId; + this.purpose = opts.purpose; + this.audioMuted = opts.audioMuted; + this.videoMuted = opts.videoMuted; + this.speakingVolumeSamples = new Array(SPEAKING_SAMPLE_COUNT).fill(-Infinity); + this.sdpMetadataStreamId = opts.stream.id; + this.updateStream(null, opts.stream); + this.stream = opts.stream; // updateStream does this, but this makes TS happier + + if (this.hasAudioTrack) { + this.initVolumeMeasuring(); + } + if (opts.call) { + opts.call.addListener(_call.CallEvent.State, this.onCallState); + this.onCallState(opts.call.state); + } + } + get connected() { + // Local feeds are always considered connected + return this.isLocal() || this._connected; + } + set connected(connected) { + this._connected = connected; + this.emit(CallFeedEvent.ConnectedChanged, this.connected); + } + get hasAudioTrack() { + return this.stream.getAudioTracks().length > 0; + } + updateStream(oldStream, newStream) { + if (newStream === oldStream) return; + if (oldStream) { + oldStream.removeEventListener("addtrack", this.onAddTrack); + this.measureVolumeActivity(false); + } + this.stream = newStream; + newStream.addEventListener("addtrack", this.onAddTrack); + if (this.hasAudioTrack) { + this.initVolumeMeasuring(); + } else { + this.measureVolumeActivity(false); + } + this.emit(CallFeedEvent.NewStream, this.stream); + } + initVolumeMeasuring() { + if (!this.hasAudioTrack) return; + if (!this.audioContext) this.audioContext = (0, _audioContext.acquireContext)(); + this.analyser = this.audioContext.createAnalyser(); + this.analyser.fftSize = 512; + this.analyser.smoothingTimeConstant = 0.1; + const mediaStreamAudioSourceNode = this.audioContext.createMediaStreamSource(this.stream); + mediaStreamAudioSourceNode.connect(this.analyser); + this.frequencyBinCount = new Float32Array(this.analyser.frequencyBinCount); + } + /** + * Returns callRoom member + * @returns member of the callRoom + */ + getMember() { + var _callRoom$getMember; + const callRoom = this.client.getRoom(this.roomId); + return (_callRoom$getMember = callRoom === null || callRoom === void 0 ? void 0 : callRoom.getMember(this.userId)) !== null && _callRoom$getMember !== void 0 ? _callRoom$getMember : null; + } + + /** + * Returns true if CallFeed is local, otherwise returns false + * @returns is local? + */ + isLocal() { + return this.userId === this.client.getUserId() && (this.deviceId === undefined || this.deviceId === this.client.getDeviceId()); + } + + /** + * Returns true if audio is muted or if there are no audio + * tracks, otherwise returns false + * @returns is audio muted? + */ + isAudioMuted() { + return this.stream.getAudioTracks().length === 0 || this.audioMuted; + } + + /** + * Returns true video is muted or if there are no video + * tracks, otherwise returns false + * @returns is video muted? + */ + isVideoMuted() { + // We assume only one video track + return this.stream.getVideoTracks().length === 0 || this.videoMuted; + } + isSpeaking() { + return this.speaking; + } + + /** + * Replaces the current MediaStream with a new one. + * The stream will be different and new stream as remote parties are + * concerned, but this can be used for convenience locally to set up + * volume listeners automatically on the new stream etc. + * @param newStream - new stream with which to replace the current one + */ + setNewStream(newStream) { + this.updateStream(this.stream, newStream); + } + + /** + * Set one or both of feed's internal audio and video video mute state + * Either value may be null to leave it as-is + * @param audioMuted - is the feed's audio muted? + * @param videoMuted - is the feed's video muted? + */ + setAudioVideoMuted(audioMuted, videoMuted) { + if (audioMuted !== null) { + if (this.audioMuted !== audioMuted) { + this.speakingVolumeSamples.fill(-Infinity); + } + this.audioMuted = audioMuted; + } + if (videoMuted !== null) this.videoMuted = videoMuted; + this.emit(CallFeedEvent.MuteStateChanged, this.audioMuted, this.videoMuted); + } + + /** + * Starts emitting volume_changed events where the emitter value is in decibels + * @param enabled - emit volume changes + */ + measureVolumeActivity(enabled) { + if (enabled) { + if (!this.analyser || !this.frequencyBinCount || !this.hasAudioTrack) return; + this.measuringVolumeActivity = true; + this.volumeLooper(); + } else { + this.measuringVolumeActivity = false; + this.speakingVolumeSamples.fill(-Infinity); + this.emit(CallFeedEvent.VolumeChanged, -Infinity); + } + } + setSpeakingThreshold(threshold) { + this.speakingThreshold = threshold; + } + clone() { + const mediaHandler = this.client.getMediaHandler(); + const stream = this.stream.clone(); + _logger.logger.log(`CallFeed clone() cloning stream (originalStreamId=${this.stream.id}, newStreamId${stream.id})`); + if (this.purpose === _callEventTypes.SDPStreamMetadataPurpose.Usermedia) { + mediaHandler.userMediaStreams.push(stream); + } else { + mediaHandler.screensharingStreams.push(stream); + } + return new CallFeed({ + client: this.client, + roomId: this.roomId, + userId: this.userId, + deviceId: this.deviceId, + stream, + purpose: this.purpose, + audioMuted: this.audioMuted, + videoMuted: this.videoMuted + }); + } + dispose() { + var _this$stream, _this$call; + clearTimeout(this.volumeLooperTimeout); + (_this$stream = this.stream) === null || _this$stream === void 0 ? void 0 : _this$stream.removeEventListener("addtrack", this.onAddTrack); + (_this$call = this.call) === null || _this$call === void 0 ? void 0 : _this$call.removeListener(_call.CallEvent.State, this.onCallState); + if (this.audioContext) { + this.audioContext = undefined; + this.analyser = undefined; + (0, _audioContext.releaseContext)(); + } + this._disposed = true; + this.emit(CallFeedEvent.Disposed); + } + get disposed() { + return this._disposed; + } + set disposed(value) { + this._disposed = value; + } + getLocalVolume() { + return this.localVolume; + } + setLocalVolume(localVolume) { + this.localVolume = localVolume; + this.emit(CallFeedEvent.LocalVolumeChanged, localVolume); + } +} +exports.CallFeed = CallFeed; +//# sourceMappingURL=callFeed.js.map
\ No newline at end of file |