From 45915ed67eedc8596e3a0046ff91c7ccd2d11b82 Mon Sep 17 00:00:00 2001 From: Robin Townsend Date: Fri, 23 Jun 2023 14:17:51 -0400 Subject: [PATCH] Fix device selection never completing in widget mode By reinstating some of the code from the full mesh branch that was there to handle this --- README.md | 1 + src/media-utils.ts | 32 +++++++++++++++++++++++++++ src/room/GroupCallView.tsx | 44 +++++++++++++++++++++++++++++++++++++- src/widget.ts | 5 +++++ 4 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 src/media-utils.ts diff --git a/README.md b/README.md index b683605..8210bf7 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,7 @@ Add SFU parameter in your local config `./public/config.yml`: ``` Run backend components: + ``` yarn backend ``` diff --git a/src/media-utils.ts b/src/media-utils.ts new file mode 100644 index 0000000..ec829c7 --- /dev/null +++ b/src/media-utils.ts @@ -0,0 +1,32 @@ +/* +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. +*/ + +/** + * 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 { + const deviceInfo = devices.find( + (d) => d.kind === kind && d.label === deviceName + ); + return deviceInfo?.deviceId; +} diff --git a/src/room/GroupCallView.tsx b/src/room/GroupCallView.tsx index 4326b3f..e6acf52 100644 --- a/src/room/GroupCallView.tsx +++ b/src/room/GroupCallView.tsx @@ -19,9 +19,11 @@ import { useHistory } from "react-router-dom"; import { GroupCall, GroupCallState } from "matrix-js-sdk/src/webrtc/groupCall"; import { MatrixClient } from "matrix-js-sdk/src/client"; import { useTranslation } from "react-i18next"; +import { Room } from "livekit-client"; +import { logger } from "matrix-js-sdk/src/logger"; import type { IWidgetApiRequest } from "matrix-widget-api"; -import { widget, ElementWidgetActions } from "../widget"; +import { widget, ElementWidgetActions, JoinCallData } from "../widget"; import { useGroupCall } from "./useGroupCall"; import { ErrorView, FullScreenView } from "../FullScreenView"; import { LobbyView } from "./LobbyView"; @@ -32,6 +34,7 @@ import { useSentryGroupCallHandler } from "./useSentryGroupCallHandler"; import { PosthogAnalytics } from "../analytics/PosthogAnalytics"; import { useProfile } from "../profile/useProfile"; import { UserChoices } from "../livekit/useLiveKit"; +import { findDeviceByName } from "../media-utils"; declare global { interface Window { @@ -90,6 +93,45 @@ export function GroupCallView({ if (widget && preload) { // In preload mode, wait for a join action before entering const onJoin = async (ev: CustomEvent) => { + const devices = await Room.getLocalDevices(); + + const { audioInput, videoInput } = ev.detail + .data as unknown as JoinCallData; + const newChoices = {} as UserChoices; + + if (audioInput !== null) { + const deviceId = await findDeviceByName( + audioInput, + "audioinput", + devices + ); + if (!deviceId) { + logger.warn("Unknown audio input: " + audioInput); + } else { + logger.debug( + `Found audio input ID ${deviceId} for name ${audioInput}` + ); + newChoices.audio = { selectedId: deviceId, enabled: true }; + } + } + + if (videoInput !== null) { + const deviceId = await findDeviceByName( + videoInput, + "videoinput", + devices + ); + if (!deviceId) { + logger.warn("Unknown video input: " + videoInput); + } else { + logger.debug( + `Found video input ID ${deviceId} for name ${videoInput}` + ); + newChoices.video = { selectedId: deviceId, enabled: true }; + } + } + + setUserChoices(newChoices); await enter(); PosthogAnalytics.instance.eventCallEnded.cacheStartCall(new Date()); diff --git a/src/widget.ts b/src/widget.ts index ebbd903..0bee23f 100644 --- a/src/widget.ts +++ b/src/widget.ts @@ -47,6 +47,11 @@ export enum ElementWidgetActions { ScreenshareStop = "io.element.screenshare_stop", } +export interface JoinCallData { + audioInput: string | null; + videoInput: string | null; +} + export interface ScreenshareStartData { desktopCapturerSourceId: string; }