adds autostart=true/false and nosound=true/false to the query params shows the player element when autoplay is off, so that the user can manually click on it.master
parent
9a564e9844
commit
e8453967a8
@ -1,58 +0,0 @@ |
|||||||
import {roomTime, useRoomRunningAndReadyChanged, useRoomTime, useTimelineSongFileChanged} from "../lib/Connection"; |
|
||||||
import {useRef, useState} from "react"; |
|
||||||
|
|
||||||
|
|
||||||
const Player = () => { |
|
||||||
const roomRunning = useRoomRunningAndReadyChanged(); |
|
||||||
const _ = useRoomTime() |
|
||||||
const timeline = useTimelineSongFileChanged(); |
|
||||||
|
|
||||||
const player = useRef(timeline ? new Audio(timeline.songFile) : null); |
|
||||||
|
|
||||||
const [timesSeeked, setTimesSeeked] = useState(0); |
|
||||||
|
|
||||||
// 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 = 20; |
|
||||||
|
|
||||||
if (player.current && roomRunning?.running && roomRunning.readyToParticipate) { |
|
||||||
let targetTime = roomTime() / 1000; |
|
||||||
let diff = player.current.currentTime - targetTime; |
|
||||||
|
|
||||||
console.log('PLAYER DIFF', 'Our time diff with the server: ', diff, |
|
||||||
'Time required to seek (seconds): ', diffSecondsRequiredToSeekRunningPlayer); |
|
||||||
|
|
||||||
if (Math.abs(diff) > diffSecondsRequiredToSeekRunningPlayer) { |
|
||||||
if (roomRunning.speedFactor != 1 || timesSeeked < maxTimesSeekAllow) { |
|
||||||
player.current.currentTime = targetTime; |
|
||||||
|
|
||||||
player.current.playbackRate = Math.max(Math.min(4.0, roomRunning.speedFactor), 0.25); |
|
||||||
|
|
||||||
setTimesSeeked(timesSeeked + 1); |
|
||||||
console.log('SEEKED', 'The running player time was seeked, times seeked in total: ' + timesSeeked); |
|
||||||
} else { |
|
||||||
console.warn('The running player is off, but we\'ve changed the time ' + |
|
||||||
'too often, skipping synchronizing the player.'); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
if (player.current.paused) { |
|
||||||
player.current.play().catch(e => { |
|
||||||
console.error('Error playing', e); |
|
||||||
}) |
|
||||||
} |
|
||||||
} else { |
|
||||||
if (player.current) { |
|
||||||
player.current.pause(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
export default Player; |
|
@ -0,0 +1,110 @@ |
|||||||
|
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; |
||||||
|
|
||||||
|
console.log('PLAYER DIFF', diff, |
||||||
|
'min req to seek: ', diffSecondsRequiredToSeekRunningPlayer); |
||||||
|
|
||||||
|
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); |
||||||
|
} |
||||||
|
console.log('PLAYER SEEKED', 'Player was seeked (total: ' + timesSeeked + ')'); |
||||||
|
} 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; |
@ -0,0 +1,4 @@ |
|||||||
|
.player |
||||||
|
position: fixed |
||||||
|
left: 0 |
||||||
|
bottom: 0 |
Loading…
Reference in new issue