Use observables for more of the media devices logic
This commit is contained in:
@@ -16,7 +16,7 @@ import {
|
|||||||
useState,
|
useState,
|
||||||
} from "react";
|
} from "react";
|
||||||
import { createMediaDeviceObserver } from "@livekit/components-core";
|
import { createMediaDeviceObserver } from "@livekit/components-core";
|
||||||
import { startWith } from "rxjs";
|
import { map, startWith } from "rxjs";
|
||||||
import { useObservableEagerState } from "observable-hooks";
|
import { useObservableEagerState } from "observable-hooks";
|
||||||
import { logger } from "matrix-js-sdk/src/logger";
|
import { logger } from "matrix-js-sdk/src/logger";
|
||||||
|
|
||||||
@@ -83,36 +83,43 @@ function useMediaDevice(
|
|||||||
).pipe(startWith([])),
|
).pipe(startWith([])),
|
||||||
[kind, requestPermissions],
|
[kind, requestPermissions],
|
||||||
);
|
);
|
||||||
const availableRaw = useObservableEagerState(deviceObserver);
|
const available = useObservableEagerState(
|
||||||
const available = useMemo(() => {
|
useMemo(
|
||||||
// Sometimes browsers (particularly Firefox) can return multiple device
|
() =>
|
||||||
// entries for the exact same device ID; using a map deduplicates them
|
deviceObserver.pipe(
|
||||||
let available = new Map<string, DeviceLabel>(
|
map((availableRaw) => {
|
||||||
availableRaw.map((d, i) => [
|
// Sometimes browsers (particularly Firefox) can return multiple device
|
||||||
d.deviceId,
|
// entries for the exact same device ID; using a map deduplicates them
|
||||||
d.label
|
let available = new Map<string, DeviceLabel>(
|
||||||
? { type: "name", name: d.label }
|
availableRaw.map((d, i) => [
|
||||||
: { type: "number", number: i + 1 },
|
d.deviceId,
|
||||||
]),
|
d.label
|
||||||
);
|
? { type: "name", name: d.label }
|
||||||
// Create a virtual default audio output for browsers that don't have one.
|
: { type: "number", number: i + 1 },
|
||||||
// Its device ID must be the empty string because that's what setSinkId
|
]),
|
||||||
// recognizes.
|
);
|
||||||
if (
|
// Create a virtual default audio output for browsers that don't have one.
|
||||||
kind === "audiooutput" &&
|
// Its device ID must be the empty string because that's what setSinkId
|
||||||
available.size &&
|
// recognizes.
|
||||||
!available.has("") &&
|
if (
|
||||||
!available.has("default")
|
kind === "audiooutput" &&
|
||||||
)
|
available.size &&
|
||||||
available = new Map([
|
!available.has("") &&
|
||||||
["", { type: "default", name: availableRaw[0]?.label || null }],
|
!available.has("default")
|
||||||
...available,
|
)
|
||||||
]);
|
available = new Map([
|
||||||
// Note: creating virtual default input devices would be another problem
|
["", { type: "default", name: availableRaw[0]?.label || null }],
|
||||||
// entirely, because requesting a media stream from deviceId "" won't
|
...available,
|
||||||
// automatically track the default device.
|
]);
|
||||||
return available;
|
// Note: creating virtual default input devices would be another problem
|
||||||
}, [kind, availableRaw]);
|
// entirely, because requesting a media stream from deviceId "" won't
|
||||||
|
// automatically track the default device.
|
||||||
|
return available;
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
[kind, deviceObserver],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
const [preferredId, select] = useSetting(setting);
|
const [preferredId, select] = useSetting(setting);
|
||||||
const selectedId = useMemo(() => {
|
const selectedId = useMemo(() => {
|
||||||
@@ -130,9 +137,17 @@ function useMediaDevice(
|
|||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}, [available, preferredId]);
|
}, [available, preferredId]);
|
||||||
const selectedGroupId = useMemo(
|
const selectedGroupId = useObservableEagerState(
|
||||||
() => availableRaw.find((d) => d.deviceId === selectedId)?.groupId,
|
useMemo(
|
||||||
[availableRaw, selectedId],
|
() =>
|
||||||
|
deviceObserver.pipe(
|
||||||
|
map(
|
||||||
|
(availableRaw) =>
|
||||||
|
availableRaw.find((d) => d.deviceId === selectedId)?.groupId,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
[deviceObserver, selectedId],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
return useMemo(
|
return useMemo(
|
||||||
|
|||||||
Reference in New Issue
Block a user