Kopie van https://gitlab.com/studieverenigingvia/ict/centurion met een paar aanpassingen
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
107 lines
3.4 KiB
107 lines
3.4 KiB
4 years ago
|
import {roomTime, useRoomRunningAndReadyChanged, useRoomTime, useTimelineSongFileChanged} from "../lib/Connection";
|
||
|
import React, {createRef, SyntheticEvent, useRef, useState} from "react";
|
||
|
|
||
|
import '../css/player.sass'
|
||
|
import {Room} from "../types/types";
|
||
|
import {parse as parseQueryString} from "query-string";
|
||
|
|
||
|
const Player = () => {
|
||
|
const room = useRoomRunningAndReadyChanged();
|
||
|
const _ = useRoomTime()
|
||
|
const timeline = useTimelineSongFileChanged();
|
||
|
|
||
|
let player = useRef<HTMLAudioElement>(null)
|
||
|
|
||
|
const [timesSeeked, setTimesSeeked] = useState(0);
|
||
|
const [hadError, setHadError] = useState(false);
|
||
|
|
||
|
// If our time synchronisation algorithm thing thinks the time is off by more
|
||
|
// than this value, we seek the running player to correct it.
|
||
|
const diffSecondsRequiredToSeekRunningPlayer = 0.20;
|
||
|
|
||
|
// Hard cap we are allowed to seek this player. Some browsers are slow or inaccurate
|
||
|
// and will always be off. To avoid endless skipping of the song this cap stops seeking the
|
||
|
// player.
|
||
|
const maxTimesSeekAllow = 25;
|
||
|
|
||
|
const query = parseQueryString(window.location.search);
|
||
|
if (query.nosound) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
if (player.current && player.current.dataset.src != timeline!!.songFile) {
|
||
|
player.current.dataset.src = timeline!!.songFile;
|
||
|
player.current.src = timeline!!.songFile;
|
||
|
}
|
||
|
|
||
|
function handlePlayerOnPlay(e: SyntheticEvent) {
|
||
|
e.preventDefault();
|
||
|
|
||
|
// For when the user manually started the player for when autoplay is off.
|
||
|
setHadError(false);
|
||
|
if (shouldPlay()) {
|
||
|
startPlaying(true)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function shouldPlay() {
|
||
|
return player.current && timeline && room && room.running && room.readyToParticipate
|
||
|
}
|
||
|
|
||
|
function startPlaying(manual: boolean) {
|
||
|
if (!player.current) return;
|
||
|
|
||
|
if (player.current.paused && !hadError) {
|
||
|
player.current.play().then(() => {
|
||
|
setHadError(false);
|
||
|
}).catch(e => {
|
||
|
console.error('Error playing', e);
|
||
|
setHadError(true);
|
||
|
})
|
||
|
}
|
||
|
|
||
|
if (!hadError) {
|
||
|
setPlayerTime(room!!, manual);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function setPlayerTime(room: Room, manualAdjustment: boolean) {
|
||
|
if (!player.current) return;
|
||
|
|
||
|
let targetTime = roomTime() / 1000;
|
||
|
let diff = player.current.currentTime - targetTime;
|
||
|
|
||
|
if (player.current && Math.abs(diff) > diffSecondsRequiredToSeekRunningPlayer) {
|
||
|
if (room.speedFactor != 1 || manualAdjustment || timesSeeked < maxTimesSeekAllow) {
|
||
|
player.current.currentTime = targetTime;
|
||
|
player.current.playbackRate = Math.max(Math.min(4.0, room.speedFactor), 0.25);
|
||
|
|
||
|
if (!manualAdjustment) {
|
||
|
setTimesSeeked(timesSeeked + 1);
|
||
|
}
|
||
|
} else {
|
||
|
console.warn('The running player is off, but we\'ve changed the time ' +
|
||
|
'too often, skipping synchronizing the player.');
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (shouldPlay()) {
|
||
|
startPlaying(false)
|
||
|
} else {
|
||
|
if (player.current) {
|
||
|
player.current.pause();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function render() {
|
||
|
return (
|
||
|
<audio ref={player} className='player' hidden={!hadError} controls={true} onPlay={handlePlayerOnPlay}/>
|
||
|
)
|
||
|
}
|
||
|
|
||
|
return render();
|
||
|
}
|
||
|
|
||
|
export default Player;
|