2026-09-13 14:14:38 -04:00
|
|
|
"use strict";
|
|
|
|
|
|
|
|
|
|
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
|
|
|
value: true
|
|
|
|
|
});
|
|
|
|
|
exports.MediaHandlerEvent = exports.MediaHandler = void 0;
|
|
|
|
|
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
|
|
|
var _typedEventEmitter = require("../models/typed-event-emitter");
|
|
|
|
|
var _groupCall = require("../webrtc/groupCall");
|
|
|
|
|
var _logger = require("../logger");
|
2026-09-12 23:57:45 -04:00
|
|
|
/*
|
|
|
|
|
Copyright 2015, 2016 OpenMarket Ltd
|
|
|
|
|
Copyright 2017 New Vector Ltd
|
|
|
|
|
Copyright 2019, 2020 The Matrix.org Foundation C.I.C.
|
|
|
|
|
Copyright 2021 - 2022 Š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.
|
|
|
|
|
*/
|
2026-09-13 14:14:38 -04:00
|
|
|
let MediaHandlerEvent = /*#__PURE__*/function (MediaHandlerEvent) {
|
2026-09-12 23:57:45 -04:00
|
|
|
MediaHandlerEvent["LocalStreamsChanged"] = "local_streams_changed";
|
|
|
|
|
return MediaHandlerEvent;
|
|
|
|
|
}({});
|
2026-09-13 14:14:38 -04:00
|
|
|
exports.MediaHandlerEvent = MediaHandlerEvent;
|
|
|
|
|
class MediaHandler extends _typedEventEmitter.TypedEventEmitter {
|
2026-09-12 23:57:45 -04:00
|
|
|
constructor(client) {
|
|
|
|
|
super();
|
|
|
|
|
this.client = client;
|
2026-09-13 14:14:38 -04:00
|
|
|
(0, _defineProperty2.default)(this, "audioInput", void 0);
|
|
|
|
|
(0, _defineProperty2.default)(this, "audioSettings", void 0);
|
|
|
|
|
(0, _defineProperty2.default)(this, "videoInput", void 0);
|
|
|
|
|
(0, _defineProperty2.default)(this, "localUserMediaStream", void 0);
|
|
|
|
|
(0, _defineProperty2.default)(this, "userMediaStreams", []);
|
|
|
|
|
(0, _defineProperty2.default)(this, "screensharingStreams", []);
|
|
|
|
|
// Promise chain to serialise calls to getMediaStream
|
|
|
|
|
(0, _defineProperty2.default)(this, "getMediaStreamPromise", void 0);
|
2026-09-12 23:57:45 -04:00
|
|
|
}
|
|
|
|
|
restoreMediaSettings(audioInput, videoInput) {
|
|
|
|
|
this.audioInput = audioInput;
|
|
|
|
|
this.videoInput = videoInput;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set an audio input device to use for MatrixCalls
|
|
|
|
|
* @param deviceId - the identifier for the device
|
|
|
|
|
* undefined treated as unset
|
|
|
|
|
*/
|
|
|
|
|
async setAudioInput(deviceId) {
|
2026-09-13 14:14:38 -04:00
|
|
|
_logger.logger.info(`MediaHandler setAudioInput() running (deviceId=${deviceId})`);
|
2026-09-12 23:57:45 -04:00
|
|
|
if (this.audioInput === deviceId) return;
|
|
|
|
|
this.audioInput = deviceId;
|
|
|
|
|
await this.updateLocalUsermediaStreams();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set audio settings for MatrixCalls
|
|
|
|
|
* @param opts - audio options to set
|
|
|
|
|
*/
|
|
|
|
|
async setAudioSettings(opts) {
|
2026-09-13 14:14:38 -04:00
|
|
|
_logger.logger.info(`MediaHandler setAudioSettings() running (opts=${JSON.stringify(opts)})`);
|
2026-09-12 23:57:45 -04:00
|
|
|
this.audioSettings = Object.assign({}, opts);
|
|
|
|
|
await this.updateLocalUsermediaStreams();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set a video input device to use for MatrixCalls
|
|
|
|
|
* @param deviceId - the identifier for the device
|
|
|
|
|
* undefined treated as unset
|
|
|
|
|
*/
|
|
|
|
|
async setVideoInput(deviceId) {
|
2026-09-13 14:14:38 -04:00
|
|
|
_logger.logger.info(`MediaHandler setVideoInput() running (deviceId=${deviceId})`);
|
2026-09-12 23:57:45 -04:00
|
|
|
if (this.videoInput === deviceId) return;
|
|
|
|
|
this.videoInput = deviceId;
|
|
|
|
|
await this.updateLocalUsermediaStreams();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set media input devices to use for MatrixCalls
|
|
|
|
|
* @param audioInput - the identifier for the audio device
|
|
|
|
|
* @param videoInput - the identifier for the video device
|
|
|
|
|
* undefined treated as unset
|
|
|
|
|
*/
|
|
|
|
|
async setMediaInputs(audioInput, videoInput) {
|
2026-09-13 14:14:38 -04:00
|
|
|
_logger.logger.log(`MediaHandler setMediaInputs() running (audioInput: ${audioInput} videoInput: ${videoInput})`);
|
2026-09-12 23:57:45 -04:00
|
|
|
this.audioInput = audioInput;
|
|
|
|
|
this.videoInput = videoInput;
|
|
|
|
|
await this.updateLocalUsermediaStreams();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Requests new usermedia streams and replace the old ones
|
|
|
|
|
*/
|
|
|
|
|
async updateLocalUsermediaStreams() {
|
|
|
|
|
if (this.userMediaStreams.length === 0) return;
|
|
|
|
|
const callMediaStreamParams = new Map();
|
|
|
|
|
for (const call of this.client.callEventHandler.calls.values()) {
|
|
|
|
|
callMediaStreamParams.set(call.callId, {
|
|
|
|
|
audio: call.hasLocalUserMediaAudioTrack,
|
|
|
|
|
video: call.hasLocalUserMediaVideoTrack
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
for (const stream of this.userMediaStreams) {
|
2026-09-13 14:14:38 -04:00
|
|
|
_logger.logger.log(`MediaHandler updateLocalUsermediaStreams() stopping all tracks (streamId=${stream.id})`);
|
2026-09-12 23:57:45 -04:00
|
|
|
for (const track of stream.getTracks()) {
|
|
|
|
|
track.stop();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
this.userMediaStreams = [];
|
|
|
|
|
this.localUserMediaStream = undefined;
|
|
|
|
|
for (const call of this.client.callEventHandler.calls.values()) {
|
|
|
|
|
if (call.callHasEnded() || !callMediaStreamParams.has(call.callId)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
const {
|
|
|
|
|
audio,
|
|
|
|
|
video
|
|
|
|
|
} = callMediaStreamParams.get(call.callId);
|
2026-09-13 14:14:38 -04:00
|
|
|
_logger.logger.log(`MediaHandler updateLocalUsermediaStreams() calling getUserMediaStream() (callId=${call.callId})`);
|
2026-09-12 23:57:45 -04:00
|
|
|
const stream = await this.getUserMediaStream(audio, video);
|
|
|
|
|
if (call.callHasEnded()) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
await call.updateLocalUsermediaStream(stream);
|
|
|
|
|
}
|
|
|
|
|
for (const groupCall of this.client.groupCallEventHandler.groupCalls.values()) {
|
|
|
|
|
if (!groupCall.localCallFeed) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2026-09-13 14:14:38 -04:00
|
|
|
_logger.logger.log(`MediaHandler updateLocalUsermediaStreams() calling getUserMediaStream() (groupCallId=${groupCall.groupCallId})`);
|
|
|
|
|
const stream = await this.getUserMediaStream(true, groupCall.type === _groupCall.GroupCallType.Video);
|
|
|
|
|
if (groupCall.state === _groupCall.GroupCallState.Ended) {
|
2026-09-12 23:57:45 -04:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
await groupCall.updateLocalUsermediaStream(stream);
|
|
|
|
|
}
|
|
|
|
|
this.emit(MediaHandlerEvent.LocalStreamsChanged);
|
|
|
|
|
}
|
|
|
|
|
async hasAudioDevice() {
|
|
|
|
|
try {
|
|
|
|
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
|
|
|
return devices.filter(device => device.kind === "audioinput").length > 0;
|
|
|
|
|
} catch (err) {
|
2026-09-13 14:14:38 -04:00
|
|
|
_logger.logger.log(`MediaHandler hasAudioDevice() calling navigator.mediaDevices.enumerateDevices with error`, err);
|
2026-09-12 23:57:45 -04:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
async hasVideoDevice() {
|
|
|
|
|
try {
|
|
|
|
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
|
|
|
return devices.filter(device => device.kind === "videoinput").length > 0;
|
|
|
|
|
} catch (err) {
|
2026-09-13 14:14:38 -04:00
|
|
|
_logger.logger.log(`MediaHandler hasVideoDevice() calling navigator.mediaDevices.enumerateDevices with error`, err);
|
2026-09-12 23:57:45 -04:00
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param audio - should have an audio track
|
|
|
|
|
* @param video - should have a video track
|
|
|
|
|
* @param reusable - is allowed to be reused by the MediaHandler
|
|
|
|
|
* @returns based on passed parameters
|
|
|
|
|
*/
|
|
|
|
|
async getUserMediaStream(audio, video, reusable = true) {
|
|
|
|
|
// Serialise calls, othertwise we can't sensibly re-use the stream
|
|
|
|
|
if (this.getMediaStreamPromise) {
|
|
|
|
|
this.getMediaStreamPromise = this.getMediaStreamPromise.then(() => {
|
|
|
|
|
return this.getUserMediaStreamInternal(audio, video, reusable);
|
|
|
|
|
});
|
|
|
|
|
} else {
|
|
|
|
|
this.getMediaStreamPromise = this.getUserMediaStreamInternal(audio, video, reusable);
|
|
|
|
|
}
|
|
|
|
|
return this.getMediaStreamPromise;
|
|
|
|
|
}
|
|
|
|
|
async getUserMediaStreamInternal(audio, video, reusable) {
|
|
|
|
|
const shouldRequestAudio = audio && (await this.hasAudioDevice());
|
|
|
|
|
const shouldRequestVideo = video && (await this.hasVideoDevice());
|
|
|
|
|
let stream;
|
|
|
|
|
let canReuseStream = true;
|
|
|
|
|
if (this.localUserMediaStream) {
|
2026-09-13 14:14:38 -04:00
|
|
|
var _this$localUserMediaS, _this$localUserMediaS2;
|
2026-09-12 23:57:45 -04:00
|
|
|
// This figures out if we can reuse the current localUsermediaStream
|
|
|
|
|
// based on whether or not the "mute state" (presence of tracks of a
|
|
|
|
|
// given kind) matches what is being requested
|
|
|
|
|
if (shouldRequestAudio !== this.localUserMediaStream.getAudioTracks().length > 0) {
|
|
|
|
|
canReuseStream = false;
|
|
|
|
|
}
|
|
|
|
|
if (shouldRequestVideo !== this.localUserMediaStream.getVideoTracks().length > 0) {
|
|
|
|
|
canReuseStream = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// This code checks that the device ID is the same as the localUserMediaStream stream, but we update
|
|
|
|
|
// the localUserMediaStream whenever the device ID changes (apart from when restoring) so it's not
|
|
|
|
|
// clear why this would ever be different, unless there's a race.
|
2026-09-13 14:14:38 -04:00
|
|
|
if (shouldRequestAudio && ((_this$localUserMediaS = this.localUserMediaStream.getAudioTracks()[0]) === null || _this$localUserMediaS === void 0 || (_this$localUserMediaS = _this$localUserMediaS.getSettings()) === null || _this$localUserMediaS === void 0 ? void 0 : _this$localUserMediaS.deviceId) !== this.audioInput) {
|
2026-09-12 23:57:45 -04:00
|
|
|
canReuseStream = false;
|
|
|
|
|
}
|
2026-09-13 14:14:38 -04:00
|
|
|
if (shouldRequestVideo && ((_this$localUserMediaS2 = this.localUserMediaStream.getVideoTracks()[0]) === null || _this$localUserMediaS2 === void 0 || (_this$localUserMediaS2 = _this$localUserMediaS2.getSettings()) === null || _this$localUserMediaS2 === void 0 ? void 0 : _this$localUserMediaS2.deviceId) !== this.videoInput) {
|
2026-09-12 23:57:45 -04:00
|
|
|
canReuseStream = false;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
canReuseStream = false;
|
|
|
|
|
}
|
|
|
|
|
if (!canReuseStream) {
|
2026-09-13 14:14:38 -04:00
|
|
|
const constraints = this.getUserMediaContraints(shouldRequestAudio, shouldRequestVideo);
|
|
|
|
|
stream = await navigator.mediaDevices.getUserMedia(constraints);
|
|
|
|
|
_logger.logger.log(`MediaHandler getUserMediaStreamInternal() calling getUserMediaStream (streamId=${stream.id}, shouldRequestAudio=${shouldRequestAudio}, shouldRequestVideo=${shouldRequestVideo}, constraints=${JSON.stringify(constraints)})`);
|
2026-09-12 23:57:45 -04:00
|
|
|
for (const track of stream.getTracks()) {
|
|
|
|
|
const settings = track.getSettings();
|
|
|
|
|
if (track.kind === "audio") {
|
|
|
|
|
this.audioInput = settings.deviceId;
|
|
|
|
|
} else if (track.kind === "video") {
|
|
|
|
|
this.videoInput = settings.deviceId;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (reusable) {
|
|
|
|
|
this.localUserMediaStream = stream;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2026-09-13 14:14:38 -04:00
|
|
|
var _this$localUserMediaS3;
|
2026-09-12 23:57:45 -04:00
|
|
|
stream = this.localUserMediaStream.clone();
|
2026-09-13 14:14:38 -04:00
|
|
|
_logger.logger.log(`MediaHandler getUserMediaStreamInternal() cloning (oldStreamId=${(_this$localUserMediaS3 = this.localUserMediaStream) === null || _this$localUserMediaS3 === void 0 ? void 0 : _this$localUserMediaS3.id} newStreamId=${stream.id} shouldRequestAudio=${shouldRequestAudio} shouldRequestVideo=${shouldRequestVideo})`);
|
2026-09-12 23:57:45 -04:00
|
|
|
if (!shouldRequestAudio) {
|
|
|
|
|
for (const track of stream.getAudioTracks()) {
|
|
|
|
|
stream.removeTrack(track);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!shouldRequestVideo) {
|
|
|
|
|
for (const track of stream.getVideoTracks()) {
|
|
|
|
|
stream.removeTrack(track);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (reusable) {
|
|
|
|
|
this.userMediaStreams.push(stream);
|
|
|
|
|
}
|
|
|
|
|
this.emit(MediaHandlerEvent.LocalStreamsChanged);
|
|
|
|
|
return stream;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Stops all tracks on the provided usermedia stream
|
|
|
|
|
*/
|
|
|
|
|
stopUserMediaStream(mediaStream) {
|
2026-09-13 14:14:38 -04:00
|
|
|
_logger.logger.log(`MediaHandler stopUserMediaStream() stopping (streamId=${mediaStream.id})`);
|
2026-09-12 23:57:45 -04:00
|
|
|
for (const track of mediaStream.getTracks()) {
|
|
|
|
|
track.stop();
|
|
|
|
|
}
|
|
|
|
|
const index = this.userMediaStreams.indexOf(mediaStream);
|
|
|
|
|
if (index !== -1) {
|
2026-09-13 14:14:38 -04:00
|
|
|
_logger.logger.debug(`MediaHandler stopUserMediaStream() splicing usermedia stream out stream array (streamId=${mediaStream.id})`, mediaStream.id);
|
2026-09-12 23:57:45 -04:00
|
|
|
this.userMediaStreams.splice(index, 1);
|
|
|
|
|
}
|
|
|
|
|
this.emit(MediaHandlerEvent.LocalStreamsChanged);
|
|
|
|
|
if (this.localUserMediaStream === mediaStream) {
|
|
|
|
|
// if we have this stream cahced, remove it, because we've stopped it
|
|
|
|
|
this.localUserMediaStream = undefined;
|
|
|
|
|
} else {
|
|
|
|
|
// If it's not the same stream. remove any tracks from the cached stream that
|
|
|
|
|
// we have just stopped, and if we do stop any, call the same method on the
|
|
|
|
|
// cached stream too in order to stop all its tracks (in case they are different)
|
|
|
|
|
// and un-cache it.
|
|
|
|
|
for (const track of mediaStream.getTracks()) {
|
2026-09-13 14:14:38 -04:00
|
|
|
var _this$localUserMediaS4;
|
|
|
|
|
if ((_this$localUserMediaS4 = this.localUserMediaStream) !== null && _this$localUserMediaS4 !== void 0 && _this$localUserMediaS4.getTrackById(track.id)) {
|
2026-09-12 23:57:45 -04:00
|
|
|
this.stopUserMediaStream(this.localUserMediaStream);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2026-09-13 14:14:38 -04:00
|
|
|
* @param desktopCapturerSourceId - sourceId for Electron DesktopCapturer
|
2026-09-12 23:57:45 -04:00
|
|
|
* @param reusable - is allowed to be reused by the MediaHandler
|
|
|
|
|
* @returns based on passed parameters
|
|
|
|
|
*/
|
|
|
|
|
async getScreensharingStream(opts = {}, reusable = true) {
|
|
|
|
|
let stream;
|
|
|
|
|
if (this.screensharingStreams.length === 0) {
|
|
|
|
|
const screenshareConstraints = this.getScreenshareContraints(opts);
|
|
|
|
|
if (opts.desktopCapturerSourceId) {
|
|
|
|
|
// We are using Electron
|
2026-09-13 14:14:38 -04:00
|
|
|
_logger.logger.debug(`MediaHandler getScreensharingStream() calling getUserMedia() (opts=${JSON.stringify(opts)})`);
|
2026-09-12 23:57:45 -04:00
|
|
|
stream = await navigator.mediaDevices.getUserMedia(screenshareConstraints);
|
|
|
|
|
} else {
|
|
|
|
|
// We are not using Electron
|
2026-09-13 14:14:38 -04:00
|
|
|
_logger.logger.debug(`MediaHandler getScreensharingStream() calling getDisplayMedia() (opts=${JSON.stringify(opts)})`);
|
2026-09-12 23:57:45 -04:00
|
|
|
stream = await navigator.mediaDevices.getDisplayMedia(screenshareConstraints);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
const matchingStream = this.screensharingStreams[this.screensharingStreams.length - 1];
|
2026-09-13 14:14:38 -04:00
|
|
|
_logger.logger.log(`MediaHandler getScreensharingStream() cloning (streamId=${matchingStream.id})`);
|
2026-09-12 23:57:45 -04:00
|
|
|
stream = matchingStream.clone();
|
|
|
|
|
}
|
|
|
|
|
if (reusable) {
|
|
|
|
|
this.screensharingStreams.push(stream);
|
|
|
|
|
}
|
|
|
|
|
this.emit(MediaHandlerEvent.LocalStreamsChanged);
|
|
|
|
|
return stream;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Stops all tracks on the provided screensharing stream
|
|
|
|
|
*/
|
|
|
|
|
stopScreensharingStream(mediaStream) {
|
2026-09-13 14:14:38 -04:00
|
|
|
_logger.logger.debug(`MediaHandler stopScreensharingStream() stopping stream (streamId=${mediaStream.id})`);
|
2026-09-12 23:57:45 -04:00
|
|
|
for (const track of mediaStream.getTracks()) {
|
|
|
|
|
track.stop();
|
|
|
|
|
}
|
|
|
|
|
const index = this.screensharingStreams.indexOf(mediaStream);
|
|
|
|
|
if (index !== -1) {
|
2026-09-13 14:14:38 -04:00
|
|
|
_logger.logger.debug(`MediaHandler stopScreensharingStream() splicing stream out (streamId=${mediaStream.id})`);
|
2026-09-12 23:57:45 -04:00
|
|
|
this.screensharingStreams.splice(index, 1);
|
|
|
|
|
}
|
|
|
|
|
this.emit(MediaHandlerEvent.LocalStreamsChanged);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Stops all local media tracks
|
|
|
|
|
*/
|
|
|
|
|
stopAllStreams() {
|
|
|
|
|
for (const stream of this.userMediaStreams) {
|
2026-09-13 14:14:38 -04:00
|
|
|
_logger.logger.log(`MediaHandler stopAllStreams() stopping (streamId=${stream.id})`);
|
2026-09-12 23:57:45 -04:00
|
|
|
for (const track of stream.getTracks()) {
|
|
|
|
|
track.stop();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (const stream of this.screensharingStreams) {
|
|
|
|
|
for (const track of stream.getTracks()) {
|
|
|
|
|
track.stop();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
this.userMediaStreams = [];
|
|
|
|
|
this.screensharingStreams = [];
|
|
|
|
|
this.localUserMediaStream = undefined;
|
|
|
|
|
this.emit(MediaHandlerEvent.LocalStreamsChanged);
|
|
|
|
|
}
|
2026-09-13 14:14:38 -04:00
|
|
|
getUserMediaContraints(audio, video) {
|
2026-09-12 23:57:45 -04:00
|
|
|
const isWebkit = !!navigator.webkitGetUserMedia;
|
|
|
|
|
return {
|
2026-09-13 14:14:38 -04:00
|
|
|
audio: audio ? {
|
|
|
|
|
deviceId: this.audioInput ? {
|
|
|
|
|
ideal: this.audioInput
|
|
|
|
|
} : undefined,
|
|
|
|
|
autoGainControl: this.audioSettings ? {
|
|
|
|
|
ideal: this.audioSettings.autoGainControl
|
|
|
|
|
} : undefined,
|
|
|
|
|
echoCancellation: this.audioSettings ? {
|
|
|
|
|
ideal: this.audioSettings.echoCancellation
|
|
|
|
|
} : undefined,
|
|
|
|
|
noiseSuppression: this.audioSettings ? {
|
|
|
|
|
ideal: this.audioSettings.noiseSuppression
|
|
|
|
|
} : undefined
|
|
|
|
|
} : false,
|
|
|
|
|
video: video ? {
|
|
|
|
|
deviceId: this.videoInput ? {
|
|
|
|
|
ideal: this.videoInput
|
|
|
|
|
} : undefined,
|
|
|
|
|
/* We want 640x360. Chrome will give it only if we ask exactly,
|
|
|
|
|
FF refuses entirely if we ask exactly, so have to ask for ideal
|
|
|
|
|
instead
|
|
|
|
|
XXX: Is this still true?
|
|
|
|
|
*/
|
|
|
|
|
width: isWebkit ? {
|
|
|
|
|
exact: 640
|
|
|
|
|
} : {
|
|
|
|
|
ideal: 640
|
|
|
|
|
},
|
|
|
|
|
height: isWebkit ? {
|
|
|
|
|
exact: 360
|
|
|
|
|
} : {
|
|
|
|
|
ideal: 360
|
|
|
|
|
}
|
|
|
|
|
} : false
|
2026-09-12 23:57:45 -04:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
getScreenshareContraints(opts) {
|
|
|
|
|
const {
|
|
|
|
|
desktopCapturerSourceId,
|
|
|
|
|
audio
|
|
|
|
|
} = opts;
|
|
|
|
|
if (desktopCapturerSourceId) {
|
|
|
|
|
return {
|
2026-09-13 14:14:38 -04:00
|
|
|
audio: audio !== null && audio !== void 0 ? audio : false,
|
2026-09-12 23:57:45 -04:00
|
|
|
video: {
|
|
|
|
|
mandatory: {
|
|
|
|
|
chromeMediaSource: "desktop",
|
|
|
|
|
chromeMediaSourceId: desktopCapturerSourceId
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
} else {
|
|
|
|
|
return {
|
2026-09-13 14:14:38 -04:00
|
|
|
audio: audio !== null && audio !== void 0 ? audio : false,
|
2026-09-12 23:57:45 -04:00
|
|
|
video: true
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-09-13 14:14:38 -04:00
|
|
|
exports.MediaHandler = MediaHandler;
|
2026-09-12 23:57:45 -04:00
|
|
|
//# sourceMappingURL=mediaHandler.js.map
|