@fishjam-cloud/react-client
Version:
React client library for Fishjam
122 lines (121 loc) • 4.94 kB
JavaScript
import { useCallback, useMemo, useRef, useState } from "react";
import { parseUserMediaError } from "../../../utils/errors";
import { getTrackFromStream, stopStream } from "../../../utils/track";
import { useTrackMiddleware } from "../useTrackMiddleware";
import { useHandleTrackEnd } from "./useHandleTrackEnd";
async function getDeviceStream(type, constraints, deviceId) {
constraints = typeof constraints === "object" ? constraints : {};
if (deviceId) {
constraints.deviceId = { exact: deviceId };
}
const stream = await navigator.mediaDevices.getUserMedia({
[type]: constraints,
});
return stream;
}
export const useDeviceManager = ({ mediaStream, setMediaStream, getInitialStream, deviceType, constraints, allDevicesList, setSelectedDevice, deviceError, setDeviceError, selectedDevice, logger, }) => {
const mediaStreamRef = useRef(mediaStream);
mediaStreamRef.current = mediaStream;
const rawTrack = useMemo(() => mediaStream && getTrackFromStream(mediaStream, deviceType), [mediaStream, deviceType]);
const clearStream = useCallback(() => {
setMediaStream(null);
}, [setMediaStream]);
useHandleTrackEnd(rawTrack, clearStream);
const { processedTrack, applyMiddleware, currentMiddleware } = useTrackMiddleware(rawTrack);
const currentTrack = processedTrack ?? rawTrack;
const deviceList = useMemo(() => allDevicesList.filter(({ kind }) => kind === `${deviceType}input`), [allDevicesList, deviceType]);
const activeDevice = useMemo(() => {
const currentDevice = mediaStream &&
deviceList.find((device) => device.deviceId === getTrackFromStream(mediaStream, deviceType)?.getSettings().deviceId);
if (!currentDevice)
return null;
return { label: currentDevice.label, deviceId: currentDevice.deviceId };
}, [mediaStream, deviceList, deviceType]);
const [deviceEnabled, setDeviceEnabled] = useState(true);
const setSelectedDeviceId = useCallback((deviceId) => {
const device = deviceList.find((d) => d.deviceId === deviceId);
if (!device)
return;
setSelectedDevice(device);
}, [deviceList, setSelectedDevice]);
const startDevice = useCallback(async (deviceId = selectedDevice?.deviceId) => {
const initialStream = await getInitialStream();
const track = initialStream && getTrackFromStream(initialStream, deviceType);
const isUsingDesiredDevice = !deviceId || deviceId === track?.getSettings().deviceId;
if (track?.enabled && isUsingDesiredDevice) {
return [track, null];
}
try {
const stream = await getDeviceStream(deviceType, constraints, deviceId ?? null);
if (mediaStreamRef.current) {
stopStream(mediaStreamRef.current, deviceType);
}
setMediaStream(stream);
const retrievedTrack = stream && getTrackFromStream(stream, deviceType);
const retrievedTrackDeviceId = retrievedTrack.getSettings().deviceId;
if (retrievedTrackDeviceId) {
setSelectedDeviceId(retrievedTrackDeviceId);
}
if (retrievedTrack && !deviceEnabled) {
retrievedTrack.enabled = false;
}
return [retrievedTrack, null];
}
catch (err) {
const parsedError = parseUserMediaError(err, logger);
setDeviceError(parsedError);
return [null, parsedError];
}
}, [
selectedDevice?.deviceId,
getInitialStream,
deviceType,
constraints,
setMediaStream,
deviceEnabled,
setSelectedDeviceId,
logger,
setDeviceError,
]);
const selectDevice = useCallback((deviceId) => {
if (currentTrack) {
return startDevice(deviceId);
}
else {
setSelectedDeviceId(deviceId);
}
}, [currentTrack, setSelectedDeviceId, startDevice]);
const stopDevice = useCallback(() => {
if (mediaStreamRef.current) {
stopStream(mediaStreamRef.current, deviceType);
}
setMediaStream(null);
}, [setMediaStream, deviceType]);
const enableDevice = useCallback(() => {
if (!currentTrack)
return;
currentTrack.enabled = true;
setDeviceEnabled(true);
}, [currentTrack]);
const disableDevice = useCallback(() => {
if (!currentTrack)
return;
currentTrack.enabled = false;
setDeviceEnabled(false);
}, [currentTrack]);
return {
startDevice,
stopDevice,
selectDevice,
activeDevice,
deviceTrack: processedTrack ?? rawTrack,
deviceList,
enableDevice,
disableDevice,
deviceEnabled,
currentMiddleware,
applyMiddleware,
deviceError,
selectedDevice,
};
};