import React, { useState, useRef, useEffect } from "react";
import { Text, IconButton, Box, Flex } from "theme-ui";
import StreamMuteIcon from "../../icons/StreamMuteIcon";
import Banner from "../banner/Banner";
import Slider from "../Slider";
function Stream({ stream, nickname }) {
const [streamVolume, setStreamVolume] = useState(1);
const [showStreamInteractBanner, setShowStreamInteractBanner] = useState(
false
);
const [streamMuted, setStreamMuted] = useState(false);
const audioRef = useRef();
useEffect(() => {
if (audioRef.current) {
audioRef.current.srcObject = stream;
// Try and auto play the audio
audioRef.current
.play()
.then(() => {
// Played fine
})
.catch(() => {
// Unable to autoplay
setStreamMuted(true);
setShowStreamInteractBanner(true);
});
}
}, [stream]);
function toggleMute() {
if (audioRef.current) {
if (streamMuted) {
audioRef.current.play().then(() => {
setStreamMuted(false);
setShowStreamInteractBanner(false);
});
} else {
setStreamMuted(true);
}
}
}
function handleVolumeChange(event) {
const volume = parseFloat(event.target.value);
setStreamVolume(volume);
}
// Platforms like iOS don't allow you to control audio volume
// Detect this by trying to change the audio volume
const [isVolumeControlAvailable, setIsVolumeControlAvailable] = useState(
true
);
useEffect(() => {
let audio = audioRef.current;
function checkVolumeControlAvailable() {
const prevVolume = audio.volume;
// Set volume to 0.5, then check if the value actually stuck 100ms later
audio.volume = 0.5;
setTimeout(() => {
setIsVolumeControlAvailable(audio.volume === 0.5);
audio.volume = prevVolume;
}, [100]);
}
audio.addEventListener("playing", checkVolumeControlAvailable);
return () => {
audio.removeEventListener("playing", checkVolumeControlAvailable);
};
}, []);
// Use an audio context gain node to control volume to go past 100%
const audioGainRef = useRef();
useEffect(() => {
let audioContext;
if (stream && !streamMuted && isVolumeControlAvailable) {
audioContext = new AudioContext();
let source = audioContext.createMediaStreamSource(stream);
let gainNode = audioContext.createGain();
gainNode.gain.value = 0;
source.connect(gainNode);
gainNode.connect(audioContext.destination);
audioGainRef.current = gainNode;
}
return () => {
audioContext && audioContext.close();
};
}, [stream, streamMuted, isVolumeControlAvailable]);
useEffect(() => {
if (audioGainRef.current && audioRef.current) {
if (streamVolume <= 1) {
audioGainRef.current.gain.value = 0;
audioRef.current.volume = streamVolume;
} else {
audioRef.current.volume = 1;
audioGainRef.current.gain.value = (streamVolume - 1) * 2;
}
}
}, [streamVolume]);
return (
<>
{
if (stream) {
toggleMute();
}
}}
>
{stream && }
setShowStreamInteractBanner(false)}
>
{nickname} has started streaming. Click
{
}
to listen.
>
);
}
export default Stream;