Fix media handler device changes

This commit is contained in:
Robert Long 2022-02-23 15:07:51 -08:00
parent 2c3ebd4c03
commit 42e2041d6f

View file

@ -9,6 +9,32 @@ import React, {
const MediaHandlerContext = createContext(); const MediaHandlerContext = createContext();
function getMediaPreferences() {
const mediaPreferences = localStorage.getItem("matrix-media-preferences");
if (mediaPreferences) {
try {
return JSON.parse(mediaPreferences);
} catch (e) {
return undefined;
}
} else {
return undefined;
}
}
function updateMediaPreferences(newPreferences) {
const oldPreferences = getMediaPreferences(newPreferences);
localStorage.setItem(
"matrix-media-preferences",
JSON.stringify({
...oldPreferences,
...newPreferences,
})
);
}
export function MediaHandlerProvider({ client, children }) { export function MediaHandlerProvider({ client, children }) {
const [ const [
{ {
@ -21,8 +47,14 @@ export function MediaHandlerProvider({ client, children }) {
}, },
setState, setState,
] = useState(() => { ] = useState(() => {
const mediaPreferences = getMediaPreferences();
const mediaHandler = client.getMediaHandler(); const mediaHandler = client.getMediaHandler();
mediaHandler.restoreMediaSettings(
mediaPreferences?.audioInput,
mediaPreferences?.videoInput
);
return { return {
audioInput: mediaHandler.audioInput, audioInput: mediaHandler.audioInput,
videoInput: mediaHandler.videoInput, videoInput: mediaHandler.videoInput,
@ -38,42 +70,67 @@ export function MediaHandlerProvider({ client, children }) {
function updateDevices() { function updateDevices() {
navigator.mediaDevices.enumerateDevices().then((devices) => { navigator.mediaDevices.enumerateDevices().then((devices) => {
const mediaPreferences = getMediaPreferences();
const audioInputs = devices.filter( const audioInputs = devices.filter(
(device) => device.kind === "audioinput" (device) => device.kind === "audioinput"
); );
const audioConnected = audioInputs.some(
(device) => device.deviceId === mediaHandler.audioInput
);
let audioInput = mediaHandler.audioInput;
if (!audioConnected && audioInputs.length > 0) {
audioInput = audioInputs[0].deviceId;
}
const videoInputs = devices.filter( const videoInputs = devices.filter(
(device) => device.kind === "videoinput" (device) => device.kind === "videoinput"
); );
const videoConnected = videoInputs.some(
(device) => device.deviceId === mediaHandler.videoInput
);
let videoInput = mediaHandler.videoInput;
if (!videoConnected && videoInputs.length > 0) {
videoInput = videoInputs[0].deviceId;
}
const audioOutputs = devices.filter( const audioOutputs = devices.filter(
(device) => device.kind === "audiooutput" (device) => device.kind === "audiooutput"
); );
let audioOutput = undefined; let audioOutput = undefined;
const audioOutputPreference = localStorage.getItem(
"matrix-audio-output"
);
if ( if (
audioOutputPreference && mediaPreferences &&
audioOutputs.some( audioOutputs.some(
(device) => device.deviceId === audioOutputPreference (device) => device.deviceId === mediaPreferences.audioOutput
) )
) { ) {
audioOutput = audioOutputPreference; audioOutput = mediaPreferences.audioOutput;
} }
if (
mediaHandler.videoInput !== videoInput ||
mediaHandler.audioInput !== audioInput
) {
mediaHandler.setMediaInputs(audioInput, videoInput);
}
updateMediaPreferences({ audioInput, videoInput, audioOutput });
setState({ setState({
audioInput: mediaHandler.audioInput, audioInput,
videoInput: mediaHandler.videoInput, videoInput,
audioOutput, audioOutput,
audioInputs, audioInputs,
audioOutputs,
videoInputs, videoInputs,
audioOutputs,
}); });
}); });
} }
updateDevices(); updateDevices();
mediaHandler.on("local_streams_changed", updateDevices); mediaHandler.on("local_streams_changed", updateDevices);
@ -82,11 +139,13 @@ export function MediaHandlerProvider({ client, children }) {
return () => { return () => {
mediaHandler.removeListener("local_streams_changed", updateDevices); mediaHandler.removeListener("local_streams_changed", updateDevices);
navigator.mediaDevices.removeEventListener("devicechange", updateDevices); navigator.mediaDevices.removeEventListener("devicechange", updateDevices);
mediaHandler.stopAllStreams();
}; };
}, [client]); }, [client]);
const setAudioInput = useCallback( const setAudioInput = useCallback(
(deviceId) => { (deviceId) => {
updateMediaPreferences({ audioInput: deviceId });
setState((prevState) => ({ ...prevState, audioInput: deviceId })); setState((prevState) => ({ ...prevState, audioInput: deviceId }));
client.getMediaHandler().setAudioInput(deviceId); client.getMediaHandler().setAudioInput(deviceId);
}, },
@ -95,6 +154,7 @@ export function MediaHandlerProvider({ client, children }) {
const setVideoInput = useCallback( const setVideoInput = useCallback(
(deviceId) => { (deviceId) => {
updateMediaPreferences({ videoInput: deviceId });
setState((prevState) => ({ ...prevState, videoInput: deviceId })); setState((prevState) => ({ ...prevState, videoInput: deviceId }));
client.getMediaHandler().setVideoInput(deviceId); client.getMediaHandler().setVideoInput(deviceId);
}, },
@ -102,7 +162,7 @@ export function MediaHandlerProvider({ client, children }) {
); );
const setAudioOutput = useCallback((deviceId) => { const setAudioOutput = useCallback((deviceId) => {
localStorage.setItem("matrix-audio-output", deviceId); updateMediaPreferences({ audioOutput: deviceId });
setState((prevState) => ({ ...prevState, audioOutput: deviceId })); setState((prevState) => ({ ...prevState, audioOutput: deviceId }));
}, []); }, []);