Merge branch 'livekit' into robin/behaviors
This commit is contained in:
@@ -323,16 +323,18 @@ export function useLivekit(
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// Sync the requested devices with LiveKit's devices
|
// Sync the requested devices with LiveKit's devices
|
||||||
if (
|
if (room !== undefined && connectionState === ConnectionState.Connected) {
|
||||||
room !== undefined &&
|
|
||||||
connectionState === ConnectionState.Connected &&
|
|
||||||
!controlledAudioDevices
|
|
||||||
) {
|
|
||||||
const syncDevice = (
|
const syncDevice = (
|
||||||
kind: MediaDeviceKind,
|
kind: MediaDeviceKind,
|
||||||
selected$: Observable<SelectedDevice | undefined>,
|
selected$: Observable<SelectedDevice | undefined>,
|
||||||
): Subscription =>
|
): Subscription =>
|
||||||
selected$.subscribe((device) => {
|
selected$.subscribe((device) => {
|
||||||
|
logger.info(
|
||||||
|
"[LivekitRoom] syncDevice room.getActiveDevice(kind) !== d.id :",
|
||||||
|
room.getActiveDevice(kind),
|
||||||
|
" !== ",
|
||||||
|
device?.id,
|
||||||
|
);
|
||||||
if (
|
if (
|
||||||
device !== undefined &&
|
device !== undefined &&
|
||||||
room.getActiveDevice(kind) !== device.id
|
room.getActiveDevice(kind) !== device.id
|
||||||
@@ -347,7 +349,9 @@ export function useLivekit(
|
|||||||
|
|
||||||
const subscriptions = [
|
const subscriptions = [
|
||||||
syncDevice("audioinput", devices.audioInput.selected$),
|
syncDevice("audioinput", devices.audioInput.selected$),
|
||||||
syncDevice("audiooutput", devices.audioOutput.selected$),
|
!controlledAudioDevices
|
||||||
|
? syncDevice("audiooutput", devices.audioOutput.selected$)
|
||||||
|
: undefined,
|
||||||
syncDevice("videoinput", devices.videoInput.selected$),
|
syncDevice("videoinput", devices.videoInput.selected$),
|
||||||
// Restart the audio input track whenever we detect that the active media
|
// Restart the audio input track whenever we detect that the active media
|
||||||
// device has changed to refer to a different hardware device. We do this
|
// device has changed to refer to a different hardware device. We do this
|
||||||
@@ -387,7 +391,7 @@ export function useLivekit(
|
|||||||
];
|
];
|
||||||
|
|
||||||
return (): void => {
|
return (): void => {
|
||||||
for (const s of subscriptions) s.unsubscribe();
|
for (const s of subscriptions) s?.unsubscribe();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}, [room, devices, connectionState, controlledAudioDevices]);
|
}, [room, devices, connectionState, controlledAudioDevices]);
|
||||||
|
|||||||
@@ -86,6 +86,14 @@ export function useMuteStates(isJoined: boolean): MuteStates {
|
|||||||
const audio = useMuteState(devices.audioInput, () => {
|
const audio = useMuteState(devices.audioInput, () => {
|
||||||
return Config.get().media_devices.enable_audio && !skipLobby && !isJoined;
|
return Config.get().media_devices.enable_audio && !skipLobby && !isJoined;
|
||||||
});
|
});
|
||||||
|
useEffect(() => {
|
||||||
|
// If audio is enabled, we need to request the device names again,
|
||||||
|
// because iOS will not be able to switch to the correct device after un-muting.
|
||||||
|
// This is one of the main changes that makes iOS work with bluetooth audio devices.
|
||||||
|
if (audio.enabled) {
|
||||||
|
devices.requestDeviceNames();
|
||||||
|
}
|
||||||
|
}, [audio.enabled, devices]);
|
||||||
const isEarpiece = useIsEarpiece();
|
const isEarpiece = useIsEarpiece();
|
||||||
const video = useMuteState(
|
const video = useMuteState(
|
||||||
devices.videoInput,
|
devices.videoInput,
|
||||||
|
|||||||
@@ -1326,7 +1326,7 @@ export class CallViewModel extends ViewModel {
|
|||||||
(available, selected) => {
|
(available, selected) => {
|
||||||
const selectionType = selected && available.get(selected.id)?.type;
|
const selectionType = selected && available.get(selected.id)?.type;
|
||||||
|
|
||||||
// If we are in any output mode other than spaeker switch to speaker.
|
// If we are in any output mode other than speaker switch to speaker.
|
||||||
const newSelectionType: "earpiece" | "speaker" =
|
const newSelectionType: "earpiece" | "speaker" =
|
||||||
selectionType === "speaker" ? "earpiece" : "speaker";
|
selectionType === "speaker" ? "earpiece" : "speaker";
|
||||||
const newSelection = [...available].find(
|
const newSelection = [...available].find(
|
||||||
|
|||||||
@@ -258,6 +258,15 @@ class AudioOutput
|
|||||||
class ControlledAudioOutput
|
class ControlledAudioOutput
|
||||||
implements MediaDevice<AudioOutputDeviceLabel, SelectedAudioOutputDevice>
|
implements MediaDevice<AudioOutputDeviceLabel, SelectedAudioOutputDevice>
|
||||||
{
|
{
|
||||||
|
// We need to subscribe to the raw devices so that the OS does update the input
|
||||||
|
// back to what it was before. otherwise we will switch back to the default
|
||||||
|
// whenever we allocate a new stream.
|
||||||
|
public readonly availableRaw$ = availableRawDevices$(
|
||||||
|
"audiooutput",
|
||||||
|
this.usingNames$,
|
||||||
|
this.scope,
|
||||||
|
);
|
||||||
|
|
||||||
public readonly available$ = this.scope.behavior(
|
public readonly available$ = this.scope.behavior(
|
||||||
combineLatest(
|
combineLatest(
|
||||||
[controlledAvailableOutputDevices$.pipe(startWith([])), iosDeviceMenu$],
|
[controlledAvailableOutputDevices$.pipe(startWith([])), iosDeviceMenu$],
|
||||||
@@ -309,14 +318,17 @@ class ControlledAudioOutput
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
public constructor(private readonly scope: ObservableScope) {
|
public constructor(
|
||||||
|
private readonly usingNames$: Behavior<boolean>,
|
||||||
|
private readonly scope: ObservableScope,
|
||||||
|
) {
|
||||||
this.selected$.subscribe((device) => {
|
this.selected$.subscribe((device) => {
|
||||||
// Let the hosting application know which output device has been selected.
|
// Let the hosting application know which output device has been selected.
|
||||||
// This information is probably only of interest if the earpiece mode has
|
// This information is probably only of interest if the earpiece mode has
|
||||||
// been selected - for example, Element X iOS listens to this to determine
|
// been selected - for example, Element X iOS listens to this to determine
|
||||||
// whether it should enable the proximity sensor.
|
// whether it should enable the proximity sensor.
|
||||||
if (device !== undefined) {
|
if (device !== undefined) {
|
||||||
logger.info("[controlled-output] setAudioDeviceSelect called:", device);
|
logger.info("[controlled-output] onAudioDeviceSelect called:", device);
|
||||||
window.controls.onAudioDeviceSelect?.(device.id);
|
window.controls.onAudioDeviceSelect?.(device.id);
|
||||||
// Also invoke the deprecated callback for backward compatibility
|
// Also invoke the deprecated callback for backward compatibility
|
||||||
window.controls.onOutputDeviceSelect?.(device.id);
|
window.controls.onOutputDeviceSelect?.(device.id);
|
||||||
@@ -325,6 +337,9 @@ class ControlledAudioOutput
|
|||||||
this.available$.subscribe((available) => {
|
this.available$.subscribe((available) => {
|
||||||
logger.info("[controlled-output] available devices:", available);
|
logger.info("[controlled-output] available devices:", available);
|
||||||
});
|
});
|
||||||
|
this.availableRaw$.subscribe((availableRaw) => {
|
||||||
|
logger.info("[controlled-output] available raw devices:", availableRaw);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,7 +400,7 @@ export class MediaDevices {
|
|||||||
AudioOutputDeviceLabel,
|
AudioOutputDeviceLabel,
|
||||||
SelectedAudioOutputDevice
|
SelectedAudioOutputDevice
|
||||||
> = getUrlParams().controlledAudioDevices
|
> = getUrlParams().controlledAudioDevices
|
||||||
? new ControlledAudioOutput(this.scope)
|
? new ControlledAudioOutput(this.usingNames$, this.scope)
|
||||||
: new AudioOutput(this.usingNames$, this.scope);
|
: new AudioOutput(this.usingNames$, this.scope);
|
||||||
|
|
||||||
public readonly videoInput: MediaDevice<DeviceLabel, SelectedDevice> =
|
public readonly videoInput: MediaDevice<DeviceLabel, SelectedDevice> =
|
||||||
|
|||||||
Reference in New Issue
Block a user