df9c1fed2a
This is an Element project (in the vector-im repo) so the Copyright should be for New Vector: it was incorrectly attributed to the foundation for some files (and some files were missing headers).
89 lines
3.1 KiB
TypeScript
89 lines
3.1 KiB
TypeScript
/*
|
|
Copyright 2022 New Vector Ltd
|
|
|
|
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 { logger } from "matrix-js-sdk/src/logger";
|
|
|
|
/**
|
|
* Finds a media device with label matching 'deviceName'
|
|
* @param deviceName The label of the device to look for
|
|
* @param devices The list of devices to search
|
|
* @returns A matching media device or undefined if no matching device was found
|
|
*/
|
|
export async function findDeviceByName(
|
|
deviceName: string,
|
|
kind: MediaDeviceKind,
|
|
devices: MediaDeviceInfo[]
|
|
): Promise<string | undefined> {
|
|
const deviceInfo = devices.find(
|
|
(d) => d.kind === kind && d.label === deviceName
|
|
);
|
|
return deviceInfo?.deviceId;
|
|
}
|
|
|
|
/**
|
|
* Gets the available audio input/output and video input devices
|
|
* from the browser: a wrapper around mediaDevices.enumerateDevices()
|
|
* that requests a stream and holds it while calling enumerateDevices().
|
|
* This is because some browsers (Firefox) only return device labels when
|
|
* the app has an active user media stream. In Chrome, this will get a
|
|
* stream from the default camera which can mean, for example, that the
|
|
* light for the FaceTime camera turns on briefly even if you selected
|
|
* another camera. Once the Permissions API
|
|
* (https://developer.mozilla.org/en-US/docs/Web/API/Permissions_API)
|
|
* is ready for primetime, this should allow us to avoid this.
|
|
*
|
|
* @return The available media devices
|
|
*/
|
|
export async function getDevices(): Promise<MediaDeviceInfo[]> {
|
|
// First get the devices without their labels, to learn what kinds of streams
|
|
// we can request
|
|
let devices: MediaDeviceInfo[];
|
|
try {
|
|
devices = await navigator.mediaDevices.enumerateDevices();
|
|
} catch (error) {
|
|
logger.warn("Unable to refresh WebRTC devices", error);
|
|
devices = [];
|
|
}
|
|
|
|
let stream: MediaStream | null = null;
|
|
try {
|
|
if (devices.some((d) => d.kind === "audioinput")) {
|
|
// Holding just an audio stream will be enough to get us all device labels
|
|
stream = await navigator.mediaDevices.getUserMedia({ audio: true });
|
|
} else if (devices.some((d) => d.kind === "videoinput")) {
|
|
// We have to resort to a video stream
|
|
stream = await navigator.mediaDevices.getUserMedia({ video: true });
|
|
}
|
|
} catch (e) {
|
|
logger.info("Couldn't get media stream for enumerateDevices: failing");
|
|
throw e;
|
|
}
|
|
|
|
if (stream !== null) {
|
|
try {
|
|
return await navigator.mediaDevices.enumerateDevices();
|
|
} catch (error) {
|
|
logger.warn("Unable to refresh WebRTC devices", error);
|
|
} finally {
|
|
for (const track of stream.getTracks()) {
|
|
track.stop();
|
|
}
|
|
}
|
|
}
|
|
|
|
// If all else failed, continue without device labels
|
|
return devices;
|
|
}
|