|
@ -25,6 +25,100 @@ import { setCurrentSeek } from '../../redux/playerSlice'; |
|
|
import cacheSong from '../shared/cacheSong'; |
|
|
import cacheSong from '../shared/cacheSong'; |
|
|
import { getSongCachePath, isCached } from '../../shared/utils'; |
|
|
import { getSongCachePath, isCached } from '../../shared/utils'; |
|
|
|
|
|
|
|
|
|
|
|
const listenHandler = ( |
|
|
|
|
|
currentPlayerRef: any, |
|
|
|
|
|
nextPlayerRef: any, |
|
|
|
|
|
playQueue: any, |
|
|
|
|
|
currentEntryList: any, |
|
|
|
|
|
dispatch: any, |
|
|
|
|
|
player: number |
|
|
|
|
|
) => { |
|
|
|
|
|
const fadeDuration = Number(settings.getSync('fadeDuration')) || 0; |
|
|
|
|
|
const fadeType = String(settings.getSync('fadeType')); |
|
|
|
|
|
const currentSeek = |
|
|
|
|
|
currentPlayerRef.current?.audioEl.current?.currentTime || 0; |
|
|
|
|
|
const seekable = |
|
|
|
|
|
currentPlayerRef.current.audioEl.current.seekable.length >= 1 |
|
|
|
|
|
? currentPlayerRef.current.audioEl.current.seekable.end( |
|
|
|
|
|
currentPlayerRef.current.audioEl.current.seekable.length - 1 |
|
|
|
|
|
) |
|
|
|
|
|
: 0; |
|
|
|
|
|
const duration = currentPlayerRef.current?.audioEl.current?.duration; |
|
|
|
|
|
const fadeAtTime = duration - fadeDuration; |
|
|
|
|
|
|
|
|
|
|
|
// Fade only if repeat is 'all' or if not on the last track
|
|
|
|
|
|
if ( |
|
|
|
|
|
playQueue[`player${player}`].index + 1 < |
|
|
|
|
|
playQueue[currentEntryList].length || |
|
|
|
|
|
playQueue.repeat === 'all' |
|
|
|
|
|
) { |
|
|
|
|
|
if (currentSeek >= fadeAtTime) { |
|
|
|
|
|
// If it's not the last track in the queue OR we want to repeat
|
|
|
|
|
|
// Once fading starts, start playing player 2 and set current to 2
|
|
|
|
|
|
|
|
|
|
|
|
if (fadeDuration > 1.5) { |
|
|
|
|
|
const timeLeft = duration - currentSeek; |
|
|
|
|
|
if (nextPlayerRef.current.audioEl.current) { |
|
|
|
|
|
const currentPlayerVolumeCalculation = |
|
|
|
|
|
fadeType === 'equalPower' |
|
|
|
|
|
? Math.sqrt(0.5 * ((timeLeft / fadeDuration) * 2)) * |
|
|
|
|
|
playQueue.volume |
|
|
|
|
|
: fadeType === 'linear' |
|
|
|
|
|
? (timeLeft / fadeDuration) * playQueue.volume |
|
|
|
|
|
: 0; |
|
|
|
|
|
|
|
|
|
|
|
const currentPlayerVolume = |
|
|
|
|
|
currentPlayerVolumeCalculation <= 0 |
|
|
|
|
|
? 0 |
|
|
|
|
|
: currentPlayerVolumeCalculation; |
|
|
|
|
|
|
|
|
|
|
|
const nextPlayerVolumeCalculation = |
|
|
|
|
|
fadeType === 'equalPower' |
|
|
|
|
|
? Math.sqrt(0.5 * (2 - (timeLeft / fadeDuration) * 2)) * |
|
|
|
|
|
playQueue.volume |
|
|
|
|
|
: fadeType === 'linear' |
|
|
|
|
|
? ((fadeDuration - timeLeft) / fadeDuration) * playQueue.volume |
|
|
|
|
|
: 0; |
|
|
|
|
|
|
|
|
|
|
|
const nextPlayerVolume = |
|
|
|
|
|
nextPlayerVolumeCalculation >= playQueue.volume |
|
|
|
|
|
? playQueue.volume |
|
|
|
|
|
: nextPlayerVolumeCalculation; |
|
|
|
|
|
|
|
|
|
|
|
if (player === 1) { |
|
|
|
|
|
dispatch( |
|
|
|
|
|
setPlayerVolume({ player: 1, volume: currentPlayerVolume }) |
|
|
|
|
|
); |
|
|
|
|
|
dispatch(setPlayerVolume({ player: 2, volume: nextPlayerVolume })); |
|
|
|
|
|
} else { |
|
|
|
|
|
dispatch( |
|
|
|
|
|
setPlayerVolume({ player: 2, volume: currentPlayerVolume }) |
|
|
|
|
|
); |
|
|
|
|
|
dispatch(setPlayerVolume({ player: 1, volume: nextPlayerVolume })); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
nextPlayerRef.current.audioEl.current.play(); |
|
|
|
|
|
dispatch(setIsFading(true)); |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
// If fade time is less than 1 second, don't fade and just start at
|
|
|
|
|
|
// full volume. Due to the low fade duration, it causes the volume to
|
|
|
|
|
|
// blast from low to full incredibly quickly due to the intervalled polling
|
|
|
|
|
|
if (player === 1) { |
|
|
|
|
|
dispatch(setPlayerVolume({ player: 2, volume: playQueue.volume })); |
|
|
|
|
|
} else { |
|
|
|
|
|
dispatch(setPlayerVolume({ player: 2, volume: playQueue.volume })); |
|
|
|
|
|
} |
|
|
|
|
|
nextPlayerRef.current.audioEl.current.play(); |
|
|
|
|
|
dispatch(setIsFading(true)); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
if (playQueue.currentPlayer === player) { |
|
|
|
|
|
dispatch(setCurrentSeek({ seek: currentSeek, seekable })); |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
const Player = ({ children }: any, ref: any) => { |
|
|
const Player = ({ children }: any, ref: any) => { |
|
|
const player1Ref = useRef<any>(); |
|
|
const player1Ref = useRef<any>(); |
|
|
const player2Ref = useRef<any>(); |
|
|
const player2Ref = useRef<any>(); |
|
@ -69,126 +163,37 @@ const Player = ({ children }: any, ref: any) => { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} else { |
|
|
} else { |
|
|
player1Ref.current.audioEl.current.pause(); |
|
|
// Add short timeout otherwise sometimes fading-in player doesn't pause
|
|
|
player2Ref.current.audioEl.current.pause(); |
|
|
setTimeout(() => { |
|
|
|
|
|
player1Ref.current.audioEl.current.pause(); |
|
|
|
|
|
player2Ref.current.audioEl.current.pause(); |
|
|
|
|
|
}, 100); |
|
|
} |
|
|
} |
|
|
}, [playQueue.currentPlayer, player.status]); |
|
|
}, [playQueue.currentPlayer, player.status]); |
|
|
|
|
|
|
|
|
const handleListen1 = () => { |
|
|
const handleListenPlayer1 = () => { |
|
|
const fadeDuration = Number(settings.getSync('fadeDuration')) || 0; |
|
|
listenHandler( |
|
|
const currentSeek = player1Ref.current?.audioEl.current?.currentTime || 0; |
|
|
player1Ref, |
|
|
const seekable = |
|
|
player2Ref, |
|
|
player1Ref.current.audioEl.current.seekable.length >= 1 |
|
|
playQueue, |
|
|
? player1Ref.current.audioEl.current.seekable.end( |
|
|
currentEntryList, |
|
|
player1Ref.current.audioEl.current.seekable.length - 1 |
|
|
dispatch, |
|
|
) |
|
|
1 |
|
|
: 0; |
|
|
); |
|
|
const duration = player1Ref.current?.audioEl.current?.duration; |
|
|
|
|
|
const fadeAtTime = duration - fadeDuration; |
|
|
|
|
|
|
|
|
|
|
|
// Don't fade if player2Index <= player1Index unless repeat==='all'
|
|
|
|
|
|
|
|
|
|
|
|
if ( |
|
|
|
|
|
playQueue.player1.index + 1 < playQueue[currentEntryList].length || |
|
|
|
|
|
playQueue.repeat === 'all' |
|
|
|
|
|
) { |
|
|
|
|
|
if (currentSeek >= fadeAtTime) { |
|
|
|
|
|
// If it's not the last track in the queue OR we want to repeat
|
|
|
|
|
|
// Once fading starts, start playing player 2 and set current to 2
|
|
|
|
|
|
|
|
|
|
|
|
if (fadeDuration > 1.5) { |
|
|
|
|
|
const timeLeft = duration - currentSeek; |
|
|
|
|
|
if (player2Ref.current.audioEl.current) { |
|
|
|
|
|
const player1Volume = |
|
|
|
|
|
playQueue.player1.volume - |
|
|
|
|
|
(playQueue.volume / timeLeft) * 0.095 <= |
|
|
|
|
|
0 |
|
|
|
|
|
? 0 |
|
|
|
|
|
: playQueue.player1.volume - |
|
|
|
|
|
(playQueue.volume / timeLeft) * 0.095; |
|
|
|
|
|
|
|
|
|
|
|
const player2Volume = |
|
|
|
|
|
playQueue.player2.volume + |
|
|
|
|
|
(playQueue.volume / timeLeft) * 0.095 >= |
|
|
|
|
|
playQueue.volume |
|
|
|
|
|
? playQueue.volume |
|
|
|
|
|
: playQueue.player2.volume + |
|
|
|
|
|
(playQueue.volume / timeLeft) * 0.095; |
|
|
|
|
|
|
|
|
|
|
|
dispatch(setPlayerVolume({ player: 1, volume: player1Volume })); |
|
|
|
|
|
dispatch(setPlayerVolume({ player: 2, volume: player2Volume })); |
|
|
|
|
|
player2Ref.current.audioEl.current.play(); |
|
|
|
|
|
dispatch(setIsFading(true)); |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
// If fade time is less than 1 second, don't fade and just start at
|
|
|
|
|
|
// full volume. Due to the low fade duration, it causes the volume to
|
|
|
|
|
|
// blast from low to full incredibly quickly due to the intervalled polling
|
|
|
|
|
|
dispatch(setPlayerVolume({ player: 2, volume: playQueue.volume })); |
|
|
|
|
|
player2Ref.current.audioEl.current.play(); |
|
|
|
|
|
dispatch(setIsFading(true)); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
if (playQueue.currentPlayer === 1) { |
|
|
|
|
|
dispatch(setCurrentSeek({ seek: currentSeek, seekable })); |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
const handleListen2 = () => { |
|
|
const handleListenPlayer2 = () => { |
|
|
const fadeDuration = Number(settings.getSync('fadeDuration')) || 0; |
|
|
listenHandler( |
|
|
const currentSeek = player2Ref.current?.audioEl.current?.currentTime || 0; |
|
|
player2Ref, |
|
|
const seekable = |
|
|
player1Ref, |
|
|
player2Ref.current.audioEl.current.seekable.length >= 1 |
|
|
playQueue, |
|
|
? player2Ref.current.audioEl.current.seekable.end( |
|
|
currentEntryList, |
|
|
player2Ref.current.audioEl.current.seekable.length - 1 |
|
|
dispatch, |
|
|
) |
|
|
2 |
|
|
: 0; |
|
|
); |
|
|
const duration = player2Ref.current?.audioEl.current?.duration; |
|
|
|
|
|
const fadeAtTime = duration - fadeDuration; |
|
|
|
|
|
|
|
|
|
|
|
if ( |
|
|
|
|
|
playQueue.player2.index + 1 < playQueue[currentEntryList].length || |
|
|
|
|
|
playQueue.repeat === 'all' |
|
|
|
|
|
) { |
|
|
|
|
|
if (currentSeek >= fadeAtTime) { |
|
|
|
|
|
if (fadeDuration > 1.5) { |
|
|
|
|
|
const timeLeft = duration - currentSeek; |
|
|
|
|
|
if (player1Ref.current.audioEl.current) { |
|
|
|
|
|
const player1Volume = |
|
|
|
|
|
playQueue.player1.volume + |
|
|
|
|
|
(playQueue.volume / timeLeft) * 0.095 >= |
|
|
|
|
|
playQueue.volume |
|
|
|
|
|
? playQueue.volume |
|
|
|
|
|
: playQueue.player1.volume + |
|
|
|
|
|
(playQueue.volume / timeLeft) * 0.095; |
|
|
|
|
|
|
|
|
|
|
|
const player2Volume = |
|
|
|
|
|
playQueue.player2.volume - |
|
|
|
|
|
(playQueue.volume / timeLeft) * 0.095 <= |
|
|
|
|
|
0 |
|
|
|
|
|
? 0 |
|
|
|
|
|
: playQueue.player2.volume - |
|
|
|
|
|
(playQueue.volume / timeLeft) * 0.095; |
|
|
|
|
|
|
|
|
|
|
|
dispatch(setPlayerVolume({ player: 1, volume: player1Volume })); |
|
|
|
|
|
dispatch(setPlayerVolume({ player: 2, volume: player2Volume })); |
|
|
|
|
|
player1Ref.current.audioEl.current.play(); |
|
|
|
|
|
dispatch(setIsFading(true)); |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
dispatch(setPlayerVolume({ player: 1, volume: playQueue.volume })); |
|
|
|
|
|
player1Ref.current.audioEl.current.play(); |
|
|
|
|
|
dispatch(setIsFading(true)); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
if (playQueue.currentPlayer === 2) { |
|
|
|
|
|
dispatch(setCurrentSeek({ seek: currentSeek, seekable })); |
|
|
|
|
|
} |
|
|
|
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
const handleOnEnded1 = () => { |
|
|
const handleOnEndedPlayer1 = () => { |
|
|
if (cacheSongs) { |
|
|
if (cacheSongs) { |
|
|
cacheSong( |
|
|
cacheSong( |
|
|
`${playQueue[currentEntryList][playQueue.player1.index].id}.mp3`, |
|
|
`${playQueue[currentEntryList][playQueue.player1.index].id}.mp3`, |
|
@ -229,7 +234,7 @@ const Player = ({ children }: any, ref: any) => { |
|
|
} |
|
|
} |
|
|
}; |
|
|
}; |
|
|
|
|
|
|
|
|
const handleOnEnded2 = () => { |
|
|
const handleOnEndedPlayer2 = () => { |
|
|
if (cacheSongs) { |
|
|
if (cacheSongs) { |
|
|
cacheSong( |
|
|
cacheSong( |
|
|
`${playQueue[currentEntryList][playQueue.player2.index].id}.mp3`, |
|
|
`${playQueue[currentEntryList][playQueue.player2.index].id}.mp3`, |
|
@ -312,10 +317,10 @@ const Player = ({ children }: any, ref: any) => { |
|
|
}.mp3` |
|
|
}.mp3` |
|
|
: playQueue[currentEntryList][playQueue.player1.index]?.streamUrl |
|
|
: playQueue[currentEntryList][playQueue.player1.index]?.streamUrl |
|
|
} |
|
|
} |
|
|
listenInterval={150} |
|
|
listenInterval={50} |
|
|
preload="auto" |
|
|
preload="auto" |
|
|
onListen={handleListen1} |
|
|
onListen={handleListenPlayer1} |
|
|
onEnded={handleOnEnded1} |
|
|
onEnded={handleOnEndedPlayer1} |
|
|
volume={playQueue.player1.volume} |
|
|
volume={playQueue.player1.volume} |
|
|
autoPlay={ |
|
|
autoPlay={ |
|
|
playQueue.player1.index === playQueue.currentIndex && |
|
|
playQueue.player1.index === playQueue.currentIndex && |
|
@ -336,10 +341,10 @@ const Player = ({ children }: any, ref: any) => { |
|
|
}.mp3` |
|
|
}.mp3` |
|
|
: playQueue[currentEntryList][playQueue.player2.index]?.streamUrl |
|
|
: playQueue[currentEntryList][playQueue.player2.index]?.streamUrl |
|
|
} |
|
|
} |
|
|
listenInterval={150} |
|
|
listenInterval={50} |
|
|
preload="auto" |
|
|
preload="auto" |
|
|
onListen={handleListen2} |
|
|
onListen={handleListenPlayer2} |
|
|
onEnded={handleOnEnded2} |
|
|
onEnded={handleOnEndedPlayer2} |
|
|
volume={playQueue.player2.volume} |
|
|
volume={playQueue.player2.volume} |
|
|
autoPlay={ |
|
|
autoPlay={ |
|
|
playQueue.player2.index === playQueue.currentIndex && |
|
|
playQueue.player2.index === playQueue.currentIndex && |
|
|