Files
element-call/src/lotus/lotusAudioOutput.ts
T
Lotus CIandClaude Opus 5 4a48ec98d0 feat(lotus): io.lotus.set_audio_output — host-driven output device switch (#119)
The embed hides Element Call's footer, so its own output picker is out of
reach; the host's call bar now sends io.lotus.set_audio_output { deviceId }
and the fork applies it via mediaDevices.audioOutput.select(), answering
with io.lotus.audio_output_state { deviceId } on every change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PPmy3tPq869XDW4njjVaKA
2026-09-20 15:31:33 -04:00

47 lines
1.7 KiB
TypeScript

/*
Copyright 2026 Lotus Guild
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import { type IWidgetApiRequest } from "matrix-widget-api";
import { logger } from "matrix-js-sdk/lib/logger";
import { type MediaDevices } from "../state/MediaDevices";
import { widget } from "../widget";
import { LotusWidgetActions } from "./lotusActions";
import { lotusSendToHost } from "./lotusWidget";
/**
* [Gitea #119] Let the host switch the audio output device (headset ↔
* speakers) from its own call bar: `io.lotus.set_audio_output { deviceId }`
* selects the output; the fork answers each change (and the initial state)
* with `io.lotus.audio_output_state { deviceId, available: [{id,label}] }`.
* No effect unless the host sends the action. Returns a teardown function.
*/
export function startLotusAudioOutput(mediaDevices: MediaDevices): () => void {
const w = widget;
if (!w) return () => undefined;
const handler = (ev: CustomEvent<IWidgetApiRequest>): void => {
w.api.transport.reply(ev.detail, {});
const data = ev.detail.data as { deviceId?: string } | undefined;
if (typeof data?.deviceId !== "string") return;
logger.debug(`[lotus] set_audio_output: ${data.deviceId}`);
mediaDevices.audioOutput.select(data.deviceId);
};
w.lazyActions.on(LotusWidgetActions.SetAudioOutput, handler);
const sub = mediaDevices.audioOutput.selected$.subscribe((selected) => {
lotusSendToHost(LotusWidgetActions.AudioOutputState, {
deviceId: selected?.id ?? null,
});
});
return () => {
sub.unsubscribe();
w.lazyActions.off(LotusWidgetActions.SetAudioOutput, handler);
};
}