UNPKG

react-hifi

Version:

A set of react components wich provides simple abstraption to manipulate HTML5 AudioContext API (Equalizer, visualisation, stereo, basic controls)

210 lines 9.05 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); var react_1 = __importDefault(require("react")); var plugins_1 = require("../plugins"); var SoundStatus; (function (SoundStatus) { SoundStatus["PAUSED"] = "PAUSED"; SoundStatus["PLAYING"] = "PLAYING"; SoundStatus["STOPPED"] = "STOPPED"; })(SoundStatus || (SoundStatus = {})); var Destination = plugins_1.pluginFactory({ createNode: function (audioContext) { return audioContext.destination; }, }); var SoundErrors; (function (SoundErrors) { SoundErrors["MEDIA_ERR_ABORTED"] = "Video playback aborted by the user."; SoundErrors["MEDIA_ERR_NETWORK"] = "A network error caused the audio download to fail."; SoundErrors["MEDIA_ERR_DECODE"] = "The audio playback was aborted due to a corruption problem."; SoundErrors["MEDIA_ERR_SRC_NOT_SUPPORTED"] = "The audio playback can not be loaded, either because the server or network failed or because the format is not supported."; SoundErrors["UNKNOWN"] = "An unknown error occurred during audio playback loading."; })(SoundErrors = exports.SoundErrors || (exports.SoundErrors = {})); /** * Sound Component */ var Sound = /** @class */ (function (_super) { __extends(Sound, _super); function Sound(props) { var _this = _super.call(this, props) || this; _this.state = { audioContext: new AudioContext(), audioNodes: [], }; _this.handleTimeUpdate = _this.handleTimeUpdate.bind(_this); _this.attachRef = _this.attachRef.bind(_this); _this.handleRegisterPlugin = _this.handleRegisterPlugin.bind(_this); _this.handleError = _this.handleError.bind(_this); return _this; } Sound.prototype.attachRef = function (element) { if (element) { this.audio = element; } }; Sound.prototype.renderPlugins = function () { var _this = this; var children = this.props.children; if (Array.isArray(children)) { var flatChildren = children.flat(); return flatChildren.map(function (plugin, idx) { return (react_1.default.createElement(plugin.type, __assign({}, plugin.props, { key: idx, audioContext: _this.state.audioContext, previousNode: _this.state.audioNodes[idx], onRegister: _this.handleRegisterPlugin }))); }).concat([ react_1.default.createElement(Destination, { key: flatChildren.length, audioContext: this.state.audioContext, previousNode: this.state.audioNodes[flatChildren.length - 1] }), ]); } else if (children) { return [ react_1.default.createElement(children.type, __assign({}, children.props, { key: 1, audioContext: this.state.audioContext, previousNode: this.state.audioNodes[0], onRegister: this.handleRegisterPlugin })), react_1.default.createElement(Destination, { key: 2, audioContext: this.state.audioContext, previousNode: this.state.audioNodes[1] }), ]; } else { return null; } }; Sound.prototype.handleRegisterPlugin = function (plugin) { this.setState({ audioNodes: this.state.audioNodes.concat([plugin]), }); }; Sound.prototype.handleTimeUpdate = function (_a) { var target = _a.target; if (this.props.onPlaying) { this.props.onPlaying({ position: target.currentTime, duration: target.duration, }); } }; Sound.prototype.setPlayerState = function (status) { switch (status) { case Sound.status.PAUSED: this.pause(); break; case Sound.status.STOPPED: this.stop(); break; case Sound.status.PLAYING: default: this.play(); break; } }; Sound.prototype.shouldUpdatePosition = function (_a) { var position = _a.position; var nextPosition = this.props.position; if ((position || position === 0) && (nextPosition || nextPosition === 0)) { var dif = nextPosition - position; return position > nextPosition || dif > 1; } else { return false; } }; Sound.prototype.setPosition = function (position) { this.audio.currentTime = position; }; Sound.prototype.play = function () { var _this = this; this.state.audioContext.resume().then(function () { return _this.audio.play(); }); }; Sound.prototype.pause = function () { var _this = this; this.state.audioContext.suspend().then(function () { return _this.audio.pause(); }); }; Sound.prototype.stop = function () { this.pause(); this.audio.currentTime = 0; }; Sound.prototype.handleError = function (evt) { var error; switch (evt.target.error.code) { case evt.target.error.MEDIA_ERR_ABORTED: error = new Error(SoundErrors.MEDIA_ERR_ABORTED); break; case evt.target.error.MEDIA_ERR_NETWORK: error = new Error(SoundErrors.MEDIA_ERR_NETWORK); break; case evt.target.error.MEDIA_ERR_DECODE: error = new Error(SoundErrors.MEDIA_ERR_DECODE); break; case evt.target.error.MEDIA_ERR_SRC_NOT_SUPPORTED: error = new Error(SoundErrors.MEDIA_ERR_SRC_NOT_SUPPORTED); break; default: error = new Error(SoundErrors.UNKNOWN); break; } this.props.onError && this.props.onError(error); }; Sound.prototype.componentDidUpdate = function (prevProps) { var _a = this.props, playStatus = _a.playStatus, url = _a.url; if ((playStatus && prevProps.playStatus !== playStatus) || url !== prevProps.url) { this.setPlayerState(playStatus); } if (this.shouldUpdatePosition(prevProps)) { this.setPosition(this.props.position); } }; Sound.prototype.componentDidMount = function () { this.source = this.state.audioContext.createMediaElementSource(this.audio); if (!this.props.children) { this.source.connect(this.state.audioContext.destination); } else { this.setState({ audioNodes: [this.source], }); } this.setPlayerState(this.props.playStatus); this.props.position && this.setPosition(this.props.position); }; Sound.prototype.componentWillUnmount = function () { this.state.audioContext.close(); }; Sound.prototype.componentDidCatch = function (err) { this.state.audioContext.close(); this.props.onError && this.props.onError(err); }; Sound.prototype.render = function () { var _a = this.props, url = _a.url, onPlaying = _a.onPlaying, onFinishedPlaying = _a.onFinishedPlaying, onLoad = _a.onLoad, onLoading = _a.onLoading; return (react_1.default.createElement(react_1.default.Fragment, null, react_1.default.createElement("audio", { crossOrigin: "anonymous", style: { visibility: 'hidden' }, src: Array.isArray(url) ? undefined : url, ref: this.attachRef, onTimeUpdate: onPlaying ? this.handleTimeUpdate : undefined, onEnded: onFinishedPlaying, onLoadStart: onLoading, onCanPlay: onLoad, onError: this.handleError }, Array.isArray(url) && url.map(function (_a, index) { var url = _a.url, type = _a.type; return react_1.default.createElement("source", { key: index, type: type, src: url }); })), this.renderPlugins())); }; Sound.status = SoundStatus; return Sound; }(react_1.default.Component)); exports.Sound = Sound; //# sourceMappingURL=index.js.map