UNPKG

react-native-audio-api

Version:

react-native-audio-api provides system for controlling audio in React Native environment compatible with Web Audio API specification

209 lines (207 loc) • 7.42 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = _interopRequireWildcard(require("react")); var _reactNative = require("react-native"); var _AudioTagContext = require("./AudioTagContext"); var _utils = require("./utils"); var _AudioControls = _interopRequireDefault(require("./controls/AudioControls")); var _useAudioSourceLoader = require("./useAudioSourceLoader"); var _jsxRuntime = require("react/jsx-runtime"); function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } const Audio = /*#__PURE__*/_react.default.memo(/*#__PURE__*/_react.default.forwardRef((props, ref) => { const { children } = props; const { autoPlay, controls, loop, muted, preload, forceDownload, source, playbackRate, preservesPitch, volume, context, onLoadStart, onLoad, onError, onPositionChange, onEnded: onEndedCallback, onPlay, onPause, onVolumeChange } = (0, _utils.useStableAudioProps)(props); const [volumeState, setVolumeState] = (0, _react.useState)(null); const [mutedState, setMutedState] = (0, _react.useState)(null); const [ready, setReady] = (0, _react.useState)(false); const [playbackState, setPlaybackState] = (0, _react.useState)('idle'); const [currentTime, setCurrentTime] = (0, _react.useState)(0); const path = (0, _react.useMemo)(() => (0, _utils.resolveSourcePath)(source), [source]); const lastEffectiveVolumeRef = (0, _react.useRef)(muted ? 0 : volume); (0, _react.useEffect)(() => { return () => { fileSourceRef.current?.disconnect(); fileSourceRef.current?.pause(); fileSourceRef.current?.dispose(); fileSourceRef.current = null; }; }, []); // eslint-disable-line react-hooks/exhaustive-deps const effectiveMutedState = (0, _react.useMemo)(() => { return mutedState ?? muted; }, [mutedState, muted]); const effectiveVolumeState = (0, _react.useMemo)(() => { return effectiveMutedState ? 0 : volumeState ?? volume; }, [effectiveMutedState, volumeState, volume]); const effectiveVolumeRef = (0, _react.useRef)(effectiveVolumeState); effectiveVolumeRef.current = effectiveVolumeState; const playRef = (0, _react.useRef)(() => {}); const handleAutoPlay = (0, _react.useCallback)(() => { playRef.current(); }, []); const handleEnded = (0, _react.useCallback)(endedDuration => { setPlaybackState('idle'); setCurrentTime(endedDuration); onEndedCallback(); }, [onEndedCallback]); const { fileSourceRef, ready: loaderReady, duration, loadForPlayback } = (0, _useAudioSourceLoader.useAudioSourceLoader)({ context, path, source, preloadMode: preload, forceDownload, loop, playbackRate, preservesPitch, autoPlay, effectiveVolumeRef, onLoadStart, onLoad, onError, onEnded: handleEnded, onAutoPlay: handleAutoPlay }); (0, _react.useEffect)(() => { setReady(loaderReady); }, [loaderReady]); (0, _react.useEffect)(() => { fileSourceRef.current?.setVolume(effectiveVolumeState); }, [effectiveVolumeState, fileSourceRef]); const play = (0, _react.useCallback)(async () => { if (!fileSourceRef.current) { const loaded = await loadForPlayback(); if (!loaded) { return; } } if (!fileSourceRef.current) { return; } fileSourceRef.current.play(); setPlaybackState('playing'); onPlay(); }, [fileSourceRef, loadForPlayback, onPlay]); playRef.current = () => { play(); }; const pause = (0, _react.useCallback)(() => { fileSourceRef.current?.pause(); setPlaybackState('paused'); onPause(); }, [onPause, fileSourceRef]); const setPlaybackRate = (0, _react.useCallback)(nextPlaybackRate => { fileSourceRef.current?.setPlaybackRate(nextPlaybackRate); }, [fileSourceRef]); const seekToTime = (0, _react.useCallback)(seconds => { fileSourceRef.current?.seekToTime(seconds); const nextTime = duration > 0 ? Math.max(0, Math.min(seconds, duration)) : Math.max(0, seconds); setCurrentTime(nextTime); onPositionChange(nextTime); }, [duration, setCurrentTime, onPositionChange, fileSourceRef]); (0, _react.useEffect)(() => { if (!path) { setPlaybackState('idle'); setCurrentTime(0); } }, [path]); (0, _react.useEffect)(() => { if (lastEffectiveVolumeRef.current !== effectiveVolumeState) { lastEffectiveVolumeRef.current = effectiveVolumeState; onVolumeChange(effectiveVolumeState); } }, [onVolumeChange, effectiveVolumeState]); (0, _react.useEffect)(() => { fileSourceRef.current?.setLoop(loop); }, [loop, fileSourceRef]); (0, _react.useEffect)(() => { fileSourceRef.current?.setPlaybackRate(playbackRate); }, [playbackRate, fileSourceRef]); (0, _react.useEffect)(() => { fileSourceRef.current?.setPreservesPitch(preservesPitch); }, [preservesPitch, fileSourceRef]); (0, _react.useEffect)(() => { if (playbackState !== 'playing') { return; } const fileSource = fileSourceRef.current; fileSource?.startPositionTracking(seconds => { setCurrentTime(seconds); onPositionChange(seconds); }); return () => { fileSource?.stopPositionTracking(); }; }, [onPositionChange, playbackState, fileSourceRef]); (0, _react.useImperativeHandle)(ref, () => ({ play, pause, seekToTime, setVolume: setVolumeState, setMuted: setMutedState, setPlaybackRate, getFileSourceNode: () => fileSourceRef.current?.getFileSourceNode() ?? null }), [pause, play, seekToTime, setMutedState, setVolumeState, setPlaybackRate, fileSourceRef]); const ctxValue = (0, _react.useMemo)(() => ({ play, pause, seekToTime, setVolume: setVolumeState, volume: effectiveVolumeState, ready, setMuted: setMutedState, muted: effectiveMutedState, playbackState, currentTime, duration, autoPlay, controls, loop, preload, playbackRate, preservesPitch, sourcePath: path, source }), [play, pause, seekToTime, setVolumeState, effectiveVolumeState, ready, setMutedState, effectiveMutedState, playbackState, currentTime, duration, autoPlay, controls, loop, preload, playbackRate, preservesPitch, path, source]); return /*#__PURE__*/(0, _jsxRuntime.jsx)(_AudioTagContext.AudioComponentContext.Provider, { value: ctxValue, children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: { alignSelf: 'stretch', width: '100%' }, children: [controls && /*#__PURE__*/(0, _jsxRuntime.jsx)(_AudioControls.default, {}), children] }) }); })); var _default = exports.default = Audio; //# sourceMappingURL=Audio.js.map