summaryrefslogtreecommitdiff
path: root/includes/external/matrix/node_modules/matrix-js-sdk/src/webrtc/callFeed.ts
diff options
context:
space:
mode:
authorRaindropsSys <raindrops@equestria.dev>2023-11-17 23:25:29 +0100
committerRaindropsSys <raindrops@equestria.dev>2023-11-17 23:25:29 +0100
commit953ddd82e48dd206cef5ac94456549aed13b3ad5 (patch)
tree8f003106ee2e7f422e5a22d2ee04d0db302e66c0 /includes/external/matrix/node_modules/matrix-js-sdk/src/webrtc/callFeed.ts
parent62a9199846b0c07c03218703b33e8385764f42d9 (diff)
downloadpluralconnect-953ddd82e48dd206cef5ac94456549aed13b3ad5.tar.gz
pluralconnect-953ddd82e48dd206cef5ac94456549aed13b3ad5.tar.bz2
pluralconnect-953ddd82e48dd206cef5ac94456549aed13b3ad5.zip
Updated 30 files and deleted 2976 files (automated)
Diffstat (limited to 'includes/external/matrix/node_modules/matrix-js-sdk/src/webrtc/callFeed.ts')
-rw-r--r--includes/external/matrix/node_modules/matrix-js-sdk/src/webrtc/callFeed.ts361
1 files changed, 0 insertions, 361 deletions
diff --git a/includes/external/matrix/node_modules/matrix-js-sdk/src/webrtc/callFeed.ts b/includes/external/matrix/node_modules/matrix-js-sdk/src/webrtc/callFeed.ts
deleted file mode 100644
index 505cf56..0000000
--- a/includes/external/matrix/node_modules/matrix-js-sdk/src/webrtc/callFeed.ts
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
-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.
-*/
-
-import { SDPStreamMetadataPurpose } from "./callEventTypes";
-import { acquireContext, releaseContext } from "./audioContext";
-import { MatrixClient } from "../client";
-import { RoomMember } from "../models/room-member";
-import { logger } from "../logger";
-import { TypedEventEmitter } from "../models/typed-event-emitter";
-import { CallEvent, CallState, MatrixCall } from "./call";
-
-const POLLING_INTERVAL = 200; // ms
-export const SPEAKING_THRESHOLD = -60; // dB
-const SPEAKING_SAMPLE_COUNT = 8; // samples
-
-export interface ICallFeedOpts {
- client: MatrixClient;
- roomId?: string;
- userId: string;
- deviceId: string | undefined;
- stream: MediaStream;
- purpose: SDPStreamMetadataPurpose;
- /**
- * Whether or not the remote SDPStreamMetadata says audio is muted
- */
- audioMuted: boolean;
- /**
- * Whether or not the remote SDPStreamMetadata says video is muted
- */
- videoMuted: boolean;
- /**
- * The MatrixCall which is the source of this CallFeed
- */
- call?: MatrixCall;
-}
-
-export enum CallFeedEvent {
- NewStream = "new_stream",
- MuteStateChanged = "mute_state_changed",
- LocalVolumeChanged = "local_volume_changed",
- VolumeChanged = "volume_changed",
- ConnectedChanged = "connected_changed",
- Speaking = "speaking",
- Disposed = "disposed",
-}
-
-type EventHandlerMap = {
- [CallFeedEvent.NewStream]: (stream: MediaStream) => void;
- [CallFeedEvent.MuteStateChanged]: (audioMuted: boolean, videoMuted: boolean) => void;
- [CallFeedEvent.LocalVolumeChanged]: (localVolume: number) => void;
- [CallFeedEvent.VolumeChanged]: (volume: number) => void;
- [CallFeedEvent.ConnectedChanged]: (connected: boolean) => void;
- [CallFeedEvent.Speaking]: (speaking: boolean) => void;
- [CallFeedEvent.Disposed]: () => void;
-};
-
-export class CallFeed extends TypedEventEmitter<CallFeedEvent, EventHandlerMap> {
- public stream: MediaStream;
- public sdpMetadataStreamId: string;
- public userId: string;
- public readonly deviceId: string | undefined;
- public purpose: SDPStreamMetadataPurpose;
- public speakingVolumeSamples: number[];
-
- private client: MatrixClient;
- private call?: MatrixCall;
- private roomId?: string;
- private audioMuted: boolean;
- private videoMuted: boolean;
- private localVolume = 1;
- private measuringVolumeActivity = false;
- private audioContext?: AudioContext;
- private analyser?: AnalyserNode;
- private frequencyBinCount?: Float32Array;
- private speakingThreshold = SPEAKING_THRESHOLD;
- private speaking = false;
- private volumeLooperTimeout?: ReturnType<typeof setTimeout>;
- private _disposed = false;
- private _connected = false;
-
- public constructor(opts: ICallFeedOpts) {
- super();
-
- 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(CallEvent.State, this.onCallState);
- this.onCallState(opts.call.state);
- }
- }
-
- public get connected(): boolean {
- // Local feeds are always considered connected
- return this.isLocal() || this._connected;
- }
-
- private set connected(connected: boolean) {
- this._connected = connected;
- this.emit(CallFeedEvent.ConnectedChanged, this.connected);
- }
-
- private get hasAudioTrack(): boolean {
- return this.stream.getAudioTracks().length > 0;
- }
-
- private updateStream(oldStream: MediaStream | null, newStream: MediaStream): void {
- 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);
- }
-
- private initVolumeMeasuring(): void {
- if (!this.hasAudioTrack) return;
- if (!this.audioContext) this.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);
- }
-
- private onAddTrack = (): void => {
- this.emit(CallFeedEvent.NewStream, this.stream);
- };
-
- private onCallState = (state: CallState): void => {
- if (state === CallState.Connected) {
- this.connected = true;
- } else if (state === CallState.Connecting) {
- this.connected = false;
- }
- };
-
- /**
- * Returns callRoom member
- * @returns member of the callRoom
- */
- public getMember(): RoomMember | null {
- const callRoom = this.client.getRoom(this.roomId);
- return callRoom?.getMember(this.userId) ?? null;
- }
-
- /**
- * Returns true if CallFeed is local, otherwise returns false
- * @returns is local?
- */
- public isLocal(): boolean {
- 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?
- */
- public isAudioMuted(): boolean {
- 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?
- */
- public isVideoMuted(): boolean {
- // We assume only one video track
- return this.stream.getVideoTracks().length === 0 || this.videoMuted;
- }
-
- public isSpeaking(): boolean {
- 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
- */
- public setNewStream(newStream: MediaStream): void {
- 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?
- */
- public setAudioVideoMuted(audioMuted: boolean | null, videoMuted: boolean | null): void {
- 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
- */
- public measureVolumeActivity(enabled: boolean): void {
- 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);
- }
- }
-
- public setSpeakingThreshold(threshold: number): void {
- this.speakingThreshold = threshold;
- }
-
- private volumeLooper = (): void => {
- 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);
- };
-
- public clone(): CallFeed {
- const mediaHandler = this.client.getMediaHandler();
- const stream = this.stream.clone();
- logger.log(`CallFeed clone() cloning stream (originalStreamId=${this.stream.id}, newStreamId${stream.id})`);
-
- if (this.purpose === 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,
- });
- }
-
- public dispose(): void {
- clearTimeout(this.volumeLooperTimeout);
- this.stream?.removeEventListener("addtrack", this.onAddTrack);
- this.call?.removeListener(CallEvent.State, this.onCallState);
- if (this.audioContext) {
- this.audioContext = undefined;
- this.analyser = undefined;
- releaseContext();
- }
- this._disposed = true;
- this.emit(CallFeedEvent.Disposed);
- }
-
- public get disposed(): boolean {
- return this._disposed;
- }
-
- private set disposed(value: boolean) {
- this._disposed = value;
- }
-
- public getLocalVolume(): number {
- return this.localVolume;
- }
-
- public setLocalVolume(localVolume: number): void {
- this.localVolume = localVolume;
- this.emit(CallFeedEvent.LocalVolumeChanged, localVolume);
- }
-}