UNPKG

@fishjam-cloud/react-client

Version:
122 lines (121 loc) 4.94 kB
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, }; };