Browse Source

Fix player break in fade when nav to NowPlaying

- Add better handling to pause/play when the current index changes
- Add better audio handling when switching songs
master
jeffvli 3 years ago
parent
commit
15cf9de9c2
  1. 10
      src/components/card/Card.tsx
  2. 28
      src/components/player/Player.tsx
  3. 148
      src/components/shared/ContextMenu.tsx
  4. 3
      src/components/viewtypes/ListViewTable.tsx

10
src/components/card/Card.tsx

@ -77,17 +77,15 @@ const Card = ({
if (playClick.type === 'playlist') {
const res = await getPlaylist(playClick.id);
dispatch(appendPlayQueue({ entries: res.song }));
if (playQueue.entry.length < 1) {
dispatch(setStatus('PLAYING'));
}
}
if (playClick.type === 'album' || playClick.type === 'artist') {
const res = await getAlbum(playClick.id);
dispatch(appendPlayQueue({ entries: res.song }));
if (playQueue.entry.length < 1) {
dispatch(setStatus('PLAYING'));
}
}
if (playQueue.entry.length < 1) {
dispatch(setStatus('PLAYING'));
}
};

28
src/components/player/Player.tsx

@ -235,7 +235,6 @@ const Player = ({ currentEntryList, children }: any, ref: any) => {
const cacheSongs = settings.getSync('cacheSongs');
const [debug, setDebug] = useState(playQueue.showDebugWindow);
const [title] = useState('');
const [srcIsSet, setSrcIsSet] = useState(false);
const [cachePath] = useState(path.join(getSongCachePath(), '/'));
const [fadeDuration, setFadeDuration] = useState(playQueue.fadeDuration);
const [fadeType, setFadeType] = useState(playQueue.fadeType);
@ -305,10 +304,9 @@ const Player = ({ currentEntryList, children }: any, ref: any) => {
}, [playQueue.currentPlayer, player.status]);
useEffect(() => {
/* Adding a small delay when setting the track src helps to not break the player when we're modifying
the currentSongIndex such as when sorting the table, shuffling, or drag and dropping rows.
It can also prevent loading unneeded tracks when rapidly incrementing/decrementing the player. */
// Adding a small delay when setting the track src helps to not break the player when we're modifying
// the currentSongIndex such as when sorting the table, shuffling, or drag and dropping rows.
// It can also prevent loading unneeded tracks when rapidly incrementing/decrementing the player.
if (playQueue[currentEntryList].length > 0 && !playQueue.isFading) {
const timer1 = setTimeout(() => {
dispatch(setPlayerSrc({ player: 1, src: getSrc1() }));
@ -325,15 +323,17 @@ const Player = ({ currentEntryList, children }: any, ref: any) => {
}
if (playQueue[currentEntryList].length > 0) {
/* If fading, just instantly switch the track, otherwise the player breaks
from the timeout due to the listen handlers that run during the fade */
// If fading, just instantly switch the track, otherwise the player breaks
// from the timeout due to the listen handlers that run during the fade
// If switching to the NowPlayingView while on player1 and fading, dispatching
// the src for player1 will cause the player to break
dispatch(setPlayerSrc({ player: 1, src: getSrc1() }));
dispatch(setPlayerSrc({ player: 2, src: getSrc2() }));
setSrcIsSet(true);
}
return undefined;
}, [currentEntryList, dispatch, getSrc1, getSrc2, playQueue, srcIsSet]);
}, [currentEntryList, dispatch, getSrc1, getSrc2, playQueue]);
useEffect(() => {
// Update playback settings when changed in redux store
@ -381,6 +381,7 @@ const Player = ({ currentEntryList, children }: any, ref: any) => {
};
const handleOnEndedPlayer1 = () => {
player1Ref.current.audioEl.current.currentTime = 0;
if (cacheSongs) {
cacheSong(
`${playQueue[currentEntryList][playQueue.player1.index].id}.mp3`,
@ -422,10 +423,10 @@ const Player = ({ currentEntryList, children }: any, ref: any) => {
dispatch(setAutoIncremented(false));
}
}
setSrcIsSet(false);
};
const handleOnEndedPlayer2 = () => {
player2Ref.current.audioEl.current.currentTime = 0;
if (cacheSongs) {
cacheSong(
`${playQueue[currentEntryList][playQueue.player2.index].id}.mp3`,
@ -466,7 +467,6 @@ const Player = ({ currentEntryList, children }: any, ref: any) => {
dispatch(setAutoIncremented(false));
}
}
setSrcIsSet(false);
};
const handleGaplessPlayer1 = () => {
@ -509,7 +509,8 @@ const Player = ({ currentEntryList, children }: any, ref: any) => {
volume={playQueue.player1.volume}
autoPlay={
playQueue.player1.index === playQueue.currentIndex &&
playQueue.currentPlayer === 1
playQueue.currentPlayer === 1 &&
player.status === 'PLAYING'
}
onError={(e: any) => {
if (playQueue[currentEntryList].length > 0) {
@ -534,7 +535,8 @@ const Player = ({ currentEntryList, children }: any, ref: any) => {
volume={playQueue.player2.volume}
autoPlay={
playQueue.player2.index === playQueue.currentIndex &&
playQueue.currentPlayer === 2
playQueue.currentPlayer === 2 &&
player.status === 'PLAYING'
}
onError={(e: any) => {
if (playQueue[currentEntryList].length > 0) {

148
src/components/shared/ContextMenu.tsx

@ -96,16 +96,6 @@ export const GlobalContextMenu = () => {
dispatch(fixPlayer2Index());
}
dispatch(setContextMenu({ show: false }));
// If the currently playing song is removed, then the player will autostart because
// the player src changed. If that happens, automatically set the playing status
if (
_.map(multiSelect.selected, 'uniqueId').includes(
playQueue.current.uniqueId
)
) {
setTimeout(() => dispatch(setStatus('PLAYING')), 50);
}
};
const handleAddToPlaylist = async () => {
@ -208,80 +198,78 @@ export const GlobalContextMenu = () => {
return (
<>
{misc.contextMenu.show && misc.contextMenu.type === 'nowPlaying' && (
<>
<ContextMenu
xPos={misc.contextMenu.xPos}
yPos={misc.contextMenu.yPos}
width={190}
numOfButtons={7}
numOfDividers={3}
<ContextMenu
xPos={misc.contextMenu.xPos}
yPos={misc.contextMenu.yPos}
width={190}
numOfButtons={7}
numOfDividers={3}
>
<ContextMenuButton
text={`Selected: ${multiSelect.selected.length}`}
/>
<ContextMenuDivider />
<ContextMenuButton text="Add to queue" onClick={handleAddToQueue} />
<ContextMenuButton
text="Remove from current"
onClick={handleRemoveFromQueue}
/>
<ContextMenuDivider />
<Whisper
ref={playlistTriggerRef}
enterable
placement="autoHorizontalStart"
trigger="none"
speaker={
<Popover>
<StyledInputPicker
data={playlists}
placement="autoVerticalStart"
virtualized
labelKey="name"
valueKey="id"
width={200}
onChange={(e: any) => setSelectedPlaylistId(e)}
/>
<StyledButton
disabled={
!selectedPlaylistId ||
misc.isProcessingPlaylist.includes(selectedPlaylistId)
}
loading={misc.isProcessingPlaylist.includes(
selectedPlaylistId
)}
onClick={handleAddToPlaylist}
>
Add
</StyledButton>
</Popover>
}
>
<ContextMenuButton
text={`Selected: ${multiSelect.selected.length}`}
/>
<ContextMenuDivider />
<ContextMenuButton text="Add to queue" onClick={handleAddToQueue} />
<ContextMenuButton
text="Remove from current"
onClick={handleRemoveFromQueue}
/>
<ContextMenuDivider />
<Whisper
ref={playlistTriggerRef}
enterable
placement="autoHorizontalStart"
trigger="none"
speaker={
<Popover>
<StyledInputPicker
data={playlists}
placement="autoVerticalStart"
virtualized
labelKey="name"
valueKey="id"
width={200}
onChange={(e: any) => setSelectedPlaylistId(e)}
/>
<StyledButton
disabled={
!selectedPlaylistId ||
misc.isProcessingPlaylist.includes(selectedPlaylistId)
}
loading={misc.isProcessingPlaylist.includes(
selectedPlaylistId
)}
onClick={handleAddToPlaylist}
>
Add
</StyledButton>
</Popover>
text="Add to playlist"
onClick={() =>
playlistTriggerRef.current.state.isOverlayShown
? playlistTriggerRef.current.close()
: playlistTriggerRef.current.open()
}
>
<ContextMenuButton
text="Add to playlist"
onClick={() =>
playlistTriggerRef.current.state.isOverlayShown
? playlistTriggerRef.current.close()
: playlistTriggerRef.current.open()
}
/>
</Whisper>
<ContextMenuDivider />
<ContextMenuButton
text="Add to favorites"
onClick={() => handleFavorite(false)}
/>
<ContextMenuButton
text="Add to favorites (ordered)"
onClick={() => handleFavorite(true)}
/>
<ContextMenuButton
text="Remove from favorites"
onClick={handleUnfavorite}
/>
</ContextMenu>
</>
</Whisper>
<ContextMenuDivider />
<ContextMenuButton
text="Add to favorites"
onClick={() => handleFavorite(false)}
/>
<ContextMenuButton
text="Add to favorites (ordered)"
onClick={() => handleFavorite(true)}
/>
<ContextMenuButton
text="Remove from favorites"
onClick={handleUnfavorite}
/>
</ContextMenu>
)}
</>
);

3
src/components/viewtypes/ListViewTable.tsx

@ -186,7 +186,7 @@ const ListViewTable = ({
})
);
}
if (playQueue.currentPlayer === 1) {
if (playQueue.currentPlayer === 1 && !playQueue.isFading) {
dispatch(fixPlayer2Index());
}
}
@ -195,6 +195,7 @@ const ListViewTable = ({
dispatch,
nowPlaying,
playQueue.currentPlayer,
playQueue.isFading,
playQueue.sortColumn,
playQueue.sortType,
sortedData,

Loading…
Cancel
Save