import React from "react"; import { connect } from "react-redux"; import Controls from "./components/controls"; import Visualizer from "./components/visualizer"; import { State } from "./store"; type AudioState = { audioContext: AudioContext; audioSource: HTMLAudioElement; audioSourceNode: MediaElementAudioSourceNode; audioVolume: GainNode; }; type MusicPlayerProps = { playing: boolean; muted: boolean; source?: string; }; class MusicPlayer extends React.Component { private audioState: AudioState; constructor(props: MusicPlayerProps) { super(props); const context = new AudioContext(); const source = new Audio(); const sourceNode = context.createMediaElementSource(source); const volume = context.createGain(); sourceNode.connect(volume); volume.connect(context.destination); this.audioState = { audioContext: context, audioSourceNode: sourceNode, audioSource: source, audioVolume: volume, }; } render() { return (
); } componentDidUpdate() { const context = this.audioState.audioContext; const source = this.audioState.audioSource; const volume = this.audioState.audioVolume; // First, set the audio source (if it changed) if (this.props.source && source.src != this.props.source) { source.src = this.props.source; } if (this.props.playing) { source .play() .then(() => { console.info("Started playing audio"); }) .catch((error) => { console.error(`Could not play audio: ${error}`); }); } else { source.pause(); } if (!this.props.muted) { volume.gain.setValueAtTime(1, context.currentTime); } else { volume.gain.setValueAtTime(0, context.currentTime); } } } function mapStateToProps(state: State): MusicPlayerProps { return { playing: state.musicState.playing, muted: state.musicState.muted, source: state.musicState.source, }; } export default connect(mapStateToProps)(MusicPlayer);