add onAudioPlaybackStarted callback for controls (#3309)
* add onAudioTrackReady callback for controls * more details in controls.md for `onAudioPlaybackStarted`
This commit is contained in:
@@ -19,3 +19,7 @@ On mobile platforms (iOS, Android), web views do not reliably support selecting
|
|||||||
- `controls.setAudioEnabled(enabled: boolean)` Enables/disables all audio output from the application. Output is enabled by default.
|
- `controls.setAudioEnabled(enabled: boolean)` Enables/disables all audio output from the application. Output is enabled by default.
|
||||||
- `showNativeAudioDevicePicker: (() => void) | undefined`. Callback called whenever the user presses the output button in the settings menu.
|
- `showNativeAudioDevicePicker: (() => void) | undefined`. Callback called whenever the user presses the output button in the settings menu.
|
||||||
This button is only shown on iOS. (`userAgent.includes("iPhone")`)
|
This button is only shown on iOS. (`userAgent.includes("iPhone")`)
|
||||||
|
- `controls.onAudioPlaybackStarted: ((id: string) => void) | undefined`: This will be called the first time we start
|
||||||
|
playing audio in the webview. It can be helpful to do device setup on the native app when the webviews audio is ready.
|
||||||
|
In particular android is using it to setup the output channel so that the call volume can
|
||||||
|
be controlled by the hardware volume rocker.
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ export interface Controls {
|
|||||||
/** @deprecated use onAudioDeviceSelect instead*/
|
/** @deprecated use onAudioDeviceSelect instead*/
|
||||||
onOutputDeviceSelect?: (id: string) => void;
|
onOutputDeviceSelect?: (id: string) => void;
|
||||||
onAudioDeviceSelect?: (id: string) => void;
|
onAudioDeviceSelect?: (id: string) => void;
|
||||||
|
onAudioPlaybackStarted?: () => void;
|
||||||
/** @deprecated use setAudioEnabled instead*/
|
/** @deprecated use setAudioEnabled instead*/
|
||||||
setOutputEnabled(enabled: boolean): void;
|
setOutputEnabled(enabled: boolean): void;
|
||||||
setAudioEnabled(enabled: boolean): void;
|
setAudioEnabled(enabled: boolean): void;
|
||||||
@@ -54,7 +55,13 @@ export const outputDevice$ = new BehaviorSubject<string | undefined>(undefined);
|
|||||||
* This should also be used to display a darkened overlay screen letting the user know that audio is muted.
|
* This should also be used to display a darkened overlay screen letting the user know that audio is muted.
|
||||||
*/
|
*/
|
||||||
export const setAudioEnabled$ = new Subject<boolean>();
|
export const setAudioEnabled$ = new Subject<boolean>();
|
||||||
|
let playbackStartedEmitted = false;
|
||||||
|
export const setPlaybackStarted = (): void => {
|
||||||
|
if (!playbackStartedEmitted) {
|
||||||
|
playbackStartedEmitted = true;
|
||||||
|
window.controls.onAudioPlaybackStarted?.();
|
||||||
|
}
|
||||||
|
};
|
||||||
window.controls = {
|
window.controls = {
|
||||||
canEnterPip(): boolean {
|
canEnterPip(): boolean {
|
||||||
return setPipEnabled$.observed;
|
return setPipEnabled$.observed;
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import { logger } from "matrix-js-sdk/lib/logger";
|
|||||||
|
|
||||||
import { useEarpieceAudioConfig } from "./MediaDevicesContext";
|
import { useEarpieceAudioConfig } from "./MediaDevicesContext";
|
||||||
import { useReactiveState } from "../useReactiveState";
|
import { useReactiveState } from "../useReactiveState";
|
||||||
|
import * as controls from "../controls";
|
||||||
export interface MatrixAudioRendererProps {
|
export interface MatrixAudioRendererProps {
|
||||||
/**
|
/**
|
||||||
* The list of participants to render audio for.
|
* The list of participants to render audio for.
|
||||||
@@ -204,6 +204,7 @@ function AudioTrackWithAudioNodes({
|
|||||||
useContext ? [audioNodes.gain!, audioNodes.pan!] : [],
|
useContext ? [audioNodes.gain!, audioNodes.pan!] : [],
|
||||||
);
|
);
|
||||||
setTrackReady(true);
|
setTrackReady(true);
|
||||||
|
controls.setPlaybackStarted();
|
||||||
}, [audioContext, audioNodes, setTrackReady, trackReady, trackRef]);
|
}, [audioContext, audioNodes, setTrackReady, trackReady, trackRef]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import {
|
|||||||
} from "./livekit/MediaDevicesContext";
|
} from "./livekit/MediaDevicesContext";
|
||||||
import { type PrefetchedSounds } from "./soundUtils";
|
import { type PrefetchedSounds } from "./soundUtils";
|
||||||
import { useUrlParams } from "./UrlParams";
|
import { useUrlParams } from "./UrlParams";
|
||||||
|
import * as controls from "./controls";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Play a sound though a given AudioContext. Will take
|
* Play a sound though a given AudioContext. Will take
|
||||||
@@ -42,6 +43,7 @@ async function playSound(
|
|||||||
src.buffer = buffer;
|
src.buffer = buffer;
|
||||||
src.connect(gain).connect(pan).connect(ctx.destination);
|
src.connect(gain).connect(pan).connect(ctx.destination);
|
||||||
const p = new Promise<void>((r) => src.addEventListener("ended", () => r()));
|
const p = new Promise<void>((r) => src.addEventListener("ended", () => r()));
|
||||||
|
controls.setPlaybackStarted();
|
||||||
src.start();
|
src.start();
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user