1
|
{"version":3,"file":"mediaHandler.js","names":["_typedEventEmitter","require","_groupCall","_logger","MediaHandlerEvent","exports","MediaHandler","TypedEventEmitter","constructor","client","_defineProperty2","default","restoreMediaSettings","audioInput","videoInput","setAudioInput","deviceId","logger","info","updateLocalUsermediaStreams","setAudioSettings","opts","JSON","stringify","audioSettings","Object","assign","setVideoInput","setMediaInputs","log","userMediaStreams","length","callMediaStreamParams","Map","call","callEventHandler","calls","values","set","callId","audio","hasLocalUserMediaAudioTrack","video","hasLocalUserMediaVideoTrack","stream","id","track","getTracks","stop","localUserMediaStream","undefined","callHasEnded","has","get","getUserMediaStream","updateLocalUsermediaStream","groupCall","groupCallEventHandler","groupCalls","localCallFeed","groupCallId","type","GroupCallType","Video","state","GroupCallState","Ended","emit","LocalStreamsChanged","hasAudioDevice","devices","navigator","mediaDevices","enumerateDevices","filter","device","kind","err","hasVideoDevice","reusable","getMediaStreamPromise","then","getUserMediaStreamInternal","shouldRequestAudio","shouldRequestVideo","canReuseStream","_this$localUserMediaS","_this$localUserMediaS2","_this$localUserMediaS3","_this$localUserMediaS4","getAudioTracks","getVideoTracks","getSettings","constraints","getUserMediaContraints","getUserMedia","settings","_this$localUserMediaS5","clone","removeTrack","push","stopUserMediaStream","mediaStream","index","indexOf","debug","splice","getScreensharingStream","screensharingStreams","screenshareConstraints","getScreenshareContraints","desktopCapturerSourceId","getDisplayMedia","matchingStream","stopScreensharingStream","stopAllStreams","isWebkit","webkitGetUserMedia","ideal","autoGainControl","echoCancellation","noiseSuppression","width","exact","height","mandatory","chromeMediaSource","chromeMediaSourceId"],"sources":["../../src/webrtc/mediaHandler.ts"],"sourcesContent":["/*\nCopyright 2015, 2016 OpenMarket Ltd\nCopyright 2017 New Vector Ltd\nCopyright 2019, 2020 The Matrix.org Foundation C.I.C.\nCopyright 2021 - 2022 Šimon Brandner <simon.bra.ag@gmail.com>\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n*/\n\nimport { TypedEventEmitter } from \"../models/typed-event-emitter\";\nimport { GroupCallType, GroupCallState } from \"../webrtc/groupCall\";\nimport { logger } from \"../logger\";\nimport { MatrixClient } from \"../client\";\n\nexport enum MediaHandlerEvent {\n LocalStreamsChanged = \"local_streams_changed\",\n}\n\nexport type MediaHandlerEventHandlerMap = {\n [MediaHandlerEvent.LocalStreamsChanged]: () => void;\n};\n\nexport interface IScreensharingOpts {\n desktopCapturerSourceId?: string;\n audio?: boolean;\n // For electron screen capture, there are very few options for detecting electron\n // apart from inspecting the user agent or just trying getDisplayMedia() and\n // catching the failure, so we do the latter - this flag tells the function to just\n // throw an error so we can catch it in this case, rather than logging and emitting.\n throwOnFail?: boolean;\n}\n\nexport interface AudioSettings {\n autoGainControl: boolean;\n echoCancellation: boolean;\n noiseSuppression: boolean;\n}\n\nexport class MediaHandler extends TypedEventEmitter<\n MediaHandlerEvent.LocalStreamsChanged,\n MediaHandlerEventHandlerMap\n> {\n private audioInput?: string;\n private audioSettings?: AudioSettings;\n private videoInput?: string;\n private localUserMediaStream?: MediaStream;\n public userMediaStreams: MediaStream[] = [];\n public screensharingStreams: MediaStream[] = [];\n\n // Promise chain to serialise calls to getMediaStream\n private getMediaStreamPromise?: Promise<MediaStream>;\n\n public constructor(private client: MatrixClient) {\n super();\n }\n\n public restoreMediaSettings(audioInput: string, videoInput: string): void {\n this.audioInput = audioInput;\n this.videoInput = videoInput;\n }\n\n /**\n * Set an audio input device to use for MatrixCalls\n * @param deviceId - the identifier for the device\n * undefined treated as unset\n */\n public async setAudioInput(deviceId: string): Promise<void> {\n logger.info(`MediaHandler setAudioInput() running (deviceId=${deviceId})`);\n\n if (this.audioInput === deviceId) return;\n\n this.audioInput = deviceId;\n await this.updateLocalUsermediaStreams();\n }\n\n /**\n * Set audio settings for MatrixCalls\n * @param opts - audio options to set\n */\n public async setAudioSettings(opts: AudioSettings): Promise<void> {\n logger.info(`MediaHandler setAudioSettings() running (opts=${JSON.stringify(opts)})`);\n\n this.audioSettings = Object.assign({}, opts) as AudioSettings;\n await this.updateLocalUsermediaStreams();\n }\n\n /**\n * Set a video input device to use for MatrixCalls\n * @param deviceId - the identifier for the device\n * undefined treated as unset\n */\n public async setVideoInput(deviceId: string): Promise<void> {\n logger.info(`MediaHandler setVideoInput() running (deviceId=${deviceId})`);\n\n if (this.videoInput === deviceId) return;\n\n this.videoInput = deviceId;\n await this.updateLocalUsermediaStreams();\n }\n\n /**\n * Set media input devices to use for MatrixCalls\n * @param audioInput - the identifier for the audio device\n * @param videoInput - the identifier for the video device\n * undefined treated as unset\n */\n public async setMediaInputs(audioInput: string, videoInput: string): Promise<void> {\n logger.log(`MediaHandler setMediaInputs() running (audioInput: ${audioInput} videoInput: ${videoInput})`);\n this.audioInput = audioInput;\n this.videoInput = videoInput;\n await this.updateLocalUsermediaStreams();\n }\n\n /*\n * Requests new usermedia streams and replace the old ones\n */\n public async updateLocalUsermediaStreams(): Promise<void> {\n if (this.userMediaStreams.length === 0) return;\n\n const callMediaStreamParams: Map<string, { audio: boolean; video: boolean }> = new Map();\n for (const call of this.client.callEventHandler!.calls.values()) {\n callMediaStreamParams.set(call.callId, {\n audio: call.hasLocalUserMediaAudioTrack,\n video: call.hasLocalUserMediaVideoTrack,\n });\n }\n\n for (const stream of this.userMediaStreams) {\n logger.log(`MediaHandler updateLocalUsermediaStreams() stopping all tracks (streamId=${stream.id})`);\n for (const track of stream.getTracks()) {\n track.stop();\n }\n }\n\n this.userMediaStreams = [];\n this.localUserMediaStream = undefined;\n\n for (const call of this.client.callEventHandler!.calls.values()) {\n if (call.callHasEnded() || !callMediaStreamParams.has(call.callId)) {\n continue;\n }\n\n const { audio, video } = callMediaStreamParams.get(call.callId)!;\n\n logger.log(\n `MediaHandler updateLocalUsermediaStreams() calling getUserMediaStream() (callId=${call.callId})`,\n );\n const stream = await this.getUserMediaStream(audio, video);\n\n if (call.callHasEnded()) {\n continue;\n }\n\n await call.updateLocalUsermediaStream(stream);\n }\n\n for (const groupCall of this.client.groupCallEventHandler!.groupCalls.values()) {\n if (!groupCall.localCallFeed) {\n continue;\n }\n\n logger.log(\n `MediaHandler updateLocalUsermediaStreams() calling getUserMediaStream() (groupCallId=${groupCall.groupCallId})`,\n );\n const stream = await this.getUserMediaStream(true, groupCall.type === GroupCallType.Video);\n\n if (groupCall.state === GroupCallState.Ended) {\n continue;\n }\n\n await groupCall.updateLocalUsermediaStream(stream);\n }\n\n this.emit(MediaHandlerEvent.LocalStreamsChanged);\n }\n\n public async hasAudioDevice(): Promise<boolean> {\n try {\n const devices = await navigator.mediaDevices.enumerateDevices();\n return devices.filter((device) => device.kind === \"audioinput\").length > 0;\n } catch (err) {\n logger.log(`MediaHandler hasAudioDevice() calling navigator.mediaDevices.enumerateDevices with error`, err);\n return false;\n }\n }\n\n public async hasVideoDevice(): Promise<boolean> {\n try {\n const devices = await navigator.mediaDevices.enumerateDevices();\n return devices.filter((device) => device.kind === \"videoinput\").length > 0;\n } catch (err) {\n logger.log(`MediaHandler hasVideoDevice() calling navigator.mediaDevices.enumerateDevices with error`, err);\n return false;\n }\n }\n\n /**\n * @param audio - should have an audio track\n * @param video - should have a video track\n * @param reusable - is allowed to be reused by the MediaHandler\n * @returns based on passed parameters\n */\n public async getUserMediaStream(audio: boolean, video: boolean, reusable = true): Promise<MediaStream> {\n // Serialise calls, othertwise we can't sensibly re-use the stream\n if (this.getMediaStreamPromise) {\n this.getMediaStreamPromise = this.getMediaStreamPromise.then(() => {\n return this.getUserMediaStreamInternal(audio, video, reusable);\n });\n } else {\n this.getMediaStreamPromise = this.getUserMediaStreamInternal(audio, video, reusable);\n }\n\n return this.getMediaStreamPromise;\n }\n\n private async getUserMediaStreamInternal(audio: boolean, video: boolean, reusable: boolean): Promise<MediaStream> {\n const shouldRequestAudio = audio && (await this.hasAudioDevice());\n const shouldRequestVideo = video && (await this.hasVideoDevice());\n\n let stream: MediaStream;\n\n let canReuseStream = true;\n if (this.localUserMediaStream) {\n // This figures out if we can reuse the current localUsermediaStream\n // based on whether or not the \"mute state\" (presence of tracks of a\n // given kind) matches what is being requested\n if (shouldRequestAudio !== this.localUserMediaStream.getAudioTracks().length > 0) {\n canReuseStream = false;\n }\n if (shouldRequestVideo !== this.localUserMediaStream.getVideoTracks().length > 0) {\n canReuseStream = false;\n }\n\n // This code checks that the device ID is the same as the localUserMediaStream stream, but we update\n // the localUserMediaStream whenever the device ID changes (apart from when restoring) so it's not\n // clear why this would ever be different, unless there's a race.\n if (\n shouldRequestAudio &&\n this.localUserMediaStream.getAudioTracks()[0]?.getSettings()?.deviceId !== this.audioInput\n ) {\n canReuseStream = false;\n }\n if (\n shouldRequestVideo &&\n this.localUserMediaStream.getVideoTracks()[0]?.getSettings()?.deviceId !== this.videoInput\n ) {\n canReuseStream = false;\n }\n } else {\n canReuseStream = false;\n }\n\n if (!canReuseStream) {\n const constraints = this.getUserMediaContraints(shouldRequestAudio, shouldRequestVideo);\n stream = await navigator.mediaDevices.getUserMedia(constraints);\n logger.log(\n `MediaHandler getUserMediaStreamInternal() calling getUserMediaStream (streamId=${\n stream.id\n }, shouldRequestAudio=${shouldRequestAudio}, shouldRequestVideo=${shouldRequestVideo}, constraints=${JSON.stringify(\n constraints,\n )})`,\n );\n\n for (const track of stream.getTracks()) {\n const settings = track.getSettings();\n\n if (track.kind === \"audio\") {\n this.audioInput = settings.deviceId!;\n } else if (track.kind === \"video\") {\n this.videoInput = settings.deviceId!;\n }\n }\n\n if (reusable) {\n this.localUserMediaStream = stream;\n }\n } else {\n stream = this.localUserMediaStream!.clone();\n logger.log(\n `MediaHandler getUserMediaStreamInternal() cloning (oldStreamId=${this.localUserMediaStream?.id} newStreamId=${stream.id} shouldRequestAudio=${shouldRequestAudio} shouldRequestVideo=${shouldRequestVideo})`,\n );\n\n if (!shouldRequestAudio) {\n for (const track of stream.getAudioTracks()) {\n stream.removeTrack(track);\n }\n }\n\n if (!shouldRequestVideo) {\n for (const track of stream.getVideoTracks()) {\n stream.removeTrack(track);\n }\n }\n }\n\n if (reusable) {\n this.userMediaStreams.push(stream);\n }\n\n this.emit(MediaHandlerEvent.LocalStreamsChanged);\n\n return stream;\n }\n\n /**\n * Stops all tracks on the provided usermedia stream\n */\n public stopUserMediaStream(mediaStream: MediaStream): void {\n logger.log(`MediaHandler stopUserMediaStream() stopping (streamId=${mediaStream.id})`);\n for (const track of mediaStream.getTracks()) {\n track.stop();\n }\n\n const index = this.userMediaStreams.indexOf(mediaStream);\n\n if (index !== -1) {\n logger.debug(\n `MediaHandler stopUserMediaStream() splicing usermedia stream out stream array (streamId=${mediaStream.id})`,\n mediaStream.id,\n );\n this.userMediaStreams.splice(index, 1);\n }\n\n this.emit(MediaHandlerEvent.LocalStreamsChanged);\n\n if (this.localUserMediaStream === mediaStream) {\n this.localUserMediaStream = undefined;\n }\n }\n\n /**\n * @param desktopCapturerSourceId - sourceId for Electron DesktopCapturer\n * @param reusable - is allowed to be reused by the MediaHandler\n * @returns based on passed parameters\n */\n public async getScreensharingStream(opts: IScreensharingOpts = {}, reusable = true): Promise<MediaStream> {\n let stream: MediaStream;\n\n if (this.screensharingStreams.length === 0) {\n const screenshareConstraints = this.getScreenshareContraints(opts);\n\n if (opts.desktopCapturerSourceId) {\n // We are using Electron\n logger.debug(\n `MediaHandler getScreensharingStream() calling getUserMedia() (opts=${JSON.stringify(opts)})`,\n );\n stream = await navigator.mediaDevices.getUserMedia(screenshareConstraints);\n } else {\n // We are not using Electron\n logger.debug(\n `MediaHandler getScreensharingStream() calling getDisplayMedia() (opts=${JSON.stringify(opts)})`,\n );\n stream = await navigator.mediaDevices.getDisplayMedia(screenshareConstraints);\n }\n } else {\n const matchingStream = this.screensharingStreams[this.screensharingStreams.length - 1];\n logger.log(`MediaHandler getScreensharingStream() cloning (streamId=${matchingStream.id})`);\n stream = matchingStream.clone();\n }\n\n if (reusable) {\n this.screensharingStreams.push(stream);\n }\n\n this.emit(MediaHandlerEvent.LocalStreamsChanged);\n\n return stream;\n }\n\n /**\n * Stops all tracks on the provided screensharing stream\n */\n public stopScreensharingStream(mediaStream: MediaStream): void {\n logger.debug(`MediaHandler stopScreensharingStream() stopping stream (streamId=${mediaStream.id})`);\n for (const track of mediaStream.getTracks()) {\n track.stop();\n }\n\n const index = this.screensharingStreams.indexOf(mediaStream);\n\n if (index !== -1) {\n logger.debug(`MediaHandler stopScreensharingStream() splicing stream out (streamId=${mediaStream.id})`);\n this.screensharingStreams.splice(index, 1);\n }\n\n this.emit(MediaHandlerEvent.LocalStreamsChanged);\n }\n\n /**\n * Stops all local media tracks\n */\n public stopAllStreams(): void {\n for (const stream of this.userMediaStreams) {\n logger.log(`MediaHandler stopAllStreams() stopping (streamId=${stream.id})`);\n for (const track of stream.getTracks()) {\n track.stop();\n }\n }\n\n for (const stream of this.screensharingStreams) {\n for (const track of stream.getTracks()) {\n track.stop();\n }\n }\n\n this.userMediaStreams = [];\n this.screensharingStreams = [];\n this.localUserMediaStream = undefined;\n\n this.emit(MediaHandlerEvent.LocalStreamsChanged);\n }\n\n private getUserMediaContraints(audio: boolean, video: boolean): MediaStreamConstraints {\n const isWebkit = !!navigator.webkitGetUserMedia;\n\n return {\n audio: audio\n ? {\n deviceId: this.audioInput ? { ideal: this.audioInput } : undefined,\n autoGainControl: this.audioSettings ? { ideal: this.audioSettings.autoGainControl } : undefined,\n echoCancellation: this.audioSettings ? { ideal: this.audioSettings.echoCancellation } : undefined,\n noiseSuppression: this.audioSettings ? { ideal: this.audioSettings.noiseSuppression } : undefined,\n }\n : false,\n video: video\n ? {\n deviceId: this.videoInput ? { ideal: this.videoInput } : undefined,\n /* We want 640x360. Chrome will give it only if we ask exactly,\n FF refuses entirely if we ask exactly, so have to ask for ideal\n instead\n XXX: Is this still true?\n */\n width: isWebkit ? { exact: 640 } : { ideal: 640 },\n height: isWebkit ? { exact: 360 } : { ideal: 360 },\n }\n : false,\n };\n }\n\n private getScreenshareContraints(opts: IScreensharingOpts): DesktopCapturerConstraints {\n const { desktopCapturerSourceId, audio } = opts;\n if (desktopCapturerSourceId) {\n return {\n audio: audio ?? false,\n video: {\n mandatory: {\n chromeMediaSource: \"desktop\",\n chromeMediaSourceId: desktopCapturerSourceId,\n },\n },\n };\n } else {\n return {\n audio: audio ?? false,\n video: true,\n };\n }\n }\n}\n"],"mappings":"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"}
|