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

223 lines (222 loc) • 7.31 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 _jsxRuntime = require("react/jsx-runtime"); 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, source, playbackRate, preservesPitch, volume, onLoadStart, onLoad, onError, onPositionChange, onEnded: onEndedCallback, onPlay, onPause, onVolumeChange } = (0, _utils.useStableAudioProps)(props); const audioRef = (0, _react.useRef)(null); const [volumeState, setVolumeState] = (0, _react.useState)(volume); 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 [duration, setDuration] = (0, _react.useState)(0); const lastElementVolumeRef = (0, _react.useRef)(muted ? 0 : volume); const effectiveMutedState = (0, _react.useMemo)(() => { return mutedState ?? muted; }, [mutedState, muted]); const effectiveVolumeState = (0, _react.useMemo)(() => { return volumeState ?? volume; }, [volumeState, volume]); const reportedVolumeState = (0, _react.useMemo)(() => { return effectiveMutedState ? 0 : effectiveVolumeState; }, [effectiveMutedState, effectiveVolumeState]); const path = (0, _react.useMemo)(() => { if (!source) { return ''; } if (typeof source === 'string') { return source; } if (typeof source === 'number') { throw new Error('Asset source is not supported on web'); } return source.uri ?? ''; }, [source]); (0, _react.useEffect)(() => { const el = audioRef.current; if (!el) { return; } el.loop = loop; el.playbackRate = playbackRate; // `preservesPitch` is non-standard but supported in modern browsers. el.preservesPitch = preservesPitch; }, [loop, playbackRate, preservesPitch]); (0, _react.useEffect)(() => { const el = audioRef.current; if (!el) { return; } el.volume = effectiveVolumeState; }, [effectiveVolumeState]); (0, _react.useEffect)(() => { const el = audioRef.current; if (!el) { return; } el.muted = effectiveMutedState; }, [effectiveMutedState]); (0, _react.useEffect)(() => { const el = audioRef.current; if (!el) { return; } const handleTimeUpdate = () => { setCurrentTime(el.currentTime); onPositionChange(el.currentTime); }; const handleVolumeChange = () => { const nextMuted = el.muted; const nextVolume = nextMuted ? 0 : el.volume; setMutedState(nextMuted); setVolumeState(el.volume); if (lastElementVolumeRef.current !== nextVolume) { lastElementVolumeRef.current = nextVolume; onVolumeChange(nextVolume); } }; el.addEventListener('timeupdate', handleTimeUpdate); el.addEventListener('volumechange', handleVolumeChange); setDuration(el.duration); setCurrentTime(el.currentTime); lastElementVolumeRef.current = el.muted ? 0 : el.volume; return () => { el.removeEventListener('timeupdate', handleTimeUpdate); el.removeEventListener('volumechange', handleVolumeChange); }; }, [onPositionChange, onVolumeChange, ready]); const play = (0, _react.useCallback)(() => { audioRef.current?.play(); setPlaybackState('playing'); onPlay(); }, [onPlay]); const pause = (0, _react.useCallback)(() => { audioRef.current?.pause(); setPlaybackState('paused'); onPause(); }, [onPause]); const seekToTime = (0, _react.useCallback)(seconds => { const el = audioRef.current; if (!el) { return; } const nextTime = duration > 0 ? Math.max(0, Math.min(seconds, duration)) : Math.max(0, seconds); el.currentTime = nextTime; setCurrentTime(nextTime); }, [duration]); const setVolume = (0, _react.useCallback)(next => { setVolumeState(next); }, []); const setMuted = (0, _react.useCallback)(next => { setMutedState(next); }, []); const setPlaybackRate = (0, _react.useCallback)(nextPlaybackRate => { const el = audioRef.current; if (!el) { return; } el.playbackRate = nextPlaybackRate; }, []); (0, _react.useImperativeHandle)(ref, () => ({ play, pause, seekToTime, setVolume, setMuted, setPlaybackRate }), [pause, play, seekToTime, setMuted, setVolume, setPlaybackRate]); const ctxValue = (0, _react.useMemo)(() => ({ play, pause, seekToTime, setVolume, ready, volume: reportedVolumeState, setMuted, muted: effectiveMutedState, playbackState, currentTime, duration, autoPlay, controls, loop, preload, playbackRate, preservesPitch, audioContext: null }), [play, pause, seekToTime, setVolume, ready, reportedVolumeState, setMuted, effectiveMutedState, playbackState, currentTime, duration, autoPlay, controls, loop, preload, playbackRate, preservesPitch]); return /*#__PURE__*/(0, _jsxRuntime.jsx)(_AudioTagContext.AudioComponentContext.Provider, { value: ctxValue, children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { style: { alignSelf: 'stretch', width: '100%' }, children: [/*#__PURE__*/(0, _jsxRuntime.jsx)("audio", { autoPlay: autoPlay, controls: controls, loop: loop, muted: effectiveMutedState, preload: preload, src: path, ref: audioRef, onLoadStart: () => { setReady(false); onLoadStart(); }, onLoadedData: () => { setReady(true); onLoad(); }, onPlay: () => { setPlaybackState('playing'); onPlay(); }, onPause: () => { setPlaybackState(state => state === 'playing' ? 'paused' : state); onPause(); }, onEnded: () => { setPlaybackState('idle'); setCurrentTime(duration); onEndedCallback(); }, onError: () => { setReady(false); onError(new Error('Failed to load audio element source')); } }), children] }) }); })); var _default = exports.default = Audio; //# sourceMappingURL=Audio.web.js.map