From 9b0c9ba3acdb08e6d1bc54fc0f39e05e67161e5a Mon Sep 17 00:00:00 2001 From: jeffvli Date: Tue, 13 Feb 2024 02:05:59 -0800 Subject: [PATCH] Fallback to web player if mpv fails to run --- src/main/features/core/player/index.ts | 12 +++++-- src/main/preload/mpv-player.ts | 5 +++ .../context-menu/context-menu-provider.tsx | 16 ++++----- .../features/lyrics/synchronized-lyrics.tsx | 10 +++--- .../components/play-queue-list-controls.tsx | 14 ++++---- .../now-playing/components/play-queue.tsx | 8 ++--- .../player/components/center-controls.tsx | 8 ++--- .../features/player/components/playerbar.tsx | 5 +-- .../player/hooks/use-center-controls.ts | 33 +++++++++---------- .../player/hooks/use-handle-playqueue-add.ts | 8 ++--- .../components/playback/mpv-settings.tsx | 27 ++++++++------- src/renderer/router/app-outlet.tsx | 11 +++++-- src/renderer/store/player.store.ts | 16 ++++++++- src/renderer/store/settings.store.ts | 12 ++++++- 14 files changed, 115 insertions(+), 70 deletions(-) diff --git a/src/main/features/core/player/index.ts b/src/main/features/core/player/index.ts index f096829f..26307093 100644 --- a/src/main/features/core/player/index.ts +++ b/src/main/features/core/player/index.ts @@ -149,6 +149,10 @@ export const getMpvInstance = () => { return mpvInstance; }; +const setAudioPlayerFallback = (isError: boolean) => { + getMainWindow()?.webContents.send('renderer-player-fallback', isError); +}; + ipcMain.on('player-set-properties', async (_event, data: Record) => { mpvLog({ action: `Setting properties: ${JSON.stringify(data)}` }); if (data.length === 0) { @@ -181,8 +185,10 @@ ipcMain.handle( mpvInstance = await createMpv(data); mpvLog({ action: 'Restarted mpv', toast: 'success' }); + setAudioPlayerFallback(false); } catch (err: NodeMpvError | any) { - mpvLog({ action: 'Failed to restart mpv' }, err); + mpvLog({ action: 'Failed to restart mpv, falling back to web player' }, err); + setAudioPlayerFallback(true); } }, ); @@ -195,8 +201,10 @@ ipcMain.handle( action: `Attempting to initialize mpv with parameters: ${JSON.stringify(data)}`, }); mpvInstance = await createMpv(data); + setAudioPlayerFallback(false); } catch (err: NodeMpvError | any) { - mpvLog({ action: 'Failed to initialize mpv' }, err); + mpvLog({ action: 'Failed to initialize mpv, falling back to web player' }, err); + setAudioPlayerFallback(true); } }, ); diff --git a/src/main/preload/mpv-player.ts b/src/main/preload/mpv-player.ts index e93bacde..78108e29 100644 --- a/src/main/preload/mpv-player.ts +++ b/src/main/preload/mpv-player.ts @@ -153,6 +153,10 @@ const rendererError = (cb: (event: IpcRendererEvent, data: string) => void) => { ipcRenderer.on('renderer-player-error', cb); }; +const rendererPlayerFallback = (cb: (event: IpcRendererEvent, data: boolean) => void) => { + ipcRenderer.on('renderer-player-fallback', cb); +}; + export const mpvPlayer = { autoNext, cleanup, @@ -184,6 +188,7 @@ export const mpvPlayerListener = { rendererPause, rendererPlay, rendererPlayPause, + rendererPlayerFallback, rendererPrevious, rendererQuit, rendererSkipBackward, diff --git a/src/renderer/features/context-menu/context-menu-provider.tsx b/src/renderer/features/context-menu/context-menu-provider.tsx index 4ebe749a..83cce029 100644 --- a/src/renderer/features/context-menu/context-menu-provider.tsx +++ b/src/renderer/features/context-menu/context-menu-provider.tsx @@ -51,7 +51,7 @@ import { usePlayerStore, useQueueControls, } from '/@/renderer/store'; -import { usePlayerType } from '/@/renderer/store/settings.store'; +import { usePlaybackType } from '/@/renderer/store/settings.store'; import { Play, PlaybackType } from '/@/renderer/types'; type ContextMenuContextProps = { @@ -575,7 +575,7 @@ export const ContextMenuProvider = ({ children }: ContextMenuProviderProps) => { [ctx.data, ctx.dataNodes, updateRatingMutation], ); - const playerType = usePlayerType(); + const playbackType = usePlaybackType(); const { moveToBottomOfQueue, moveToTopOfQueue, removeFromQueue } = useQueueControls(); const handleMoveToBottom = useCallback(() => { @@ -584,10 +584,10 @@ export const ContextMenuProvider = ({ children }: ContextMenuProviderProps) => { const playerData = moveToBottomOfQueue(uniqueIds); - if (playerType === PlaybackType.LOCAL) { + if (playbackType === PlaybackType.LOCAL) { mpvPlayer!.setQueueNext(playerData); } - }, [ctx.dataNodes, moveToBottomOfQueue, playerType]); + }, [ctx.dataNodes, moveToBottomOfQueue, playbackType]); const handleMoveToTop = useCallback(() => { const uniqueIds = ctx.dataNodes?.map((row) => row.data.uniqueId); @@ -595,10 +595,10 @@ export const ContextMenuProvider = ({ children }: ContextMenuProviderProps) => { const playerData = moveToTopOfQueue(uniqueIds); - if (playerType === PlaybackType.LOCAL) { + if (playbackType === PlaybackType.LOCAL) { mpvPlayer!.setQueueNext(playerData); } - }, [ctx.dataNodes, moveToTopOfQueue, playerType]); + }, [ctx.dataNodes, moveToTopOfQueue, playbackType]); const handleRemoveSelected = useCallback(() => { const uniqueIds = ctx.dataNodes?.map((row) => row.data.uniqueId); @@ -608,7 +608,7 @@ export const ContextMenuProvider = ({ children }: ContextMenuProviderProps) => { const playerData = removeFromQueue(uniqueIds); const isCurrentSongRemoved = currentSong && uniqueIds.includes(currentSong?.uniqueId); - if (playerType === PlaybackType.LOCAL) { + if (playbackType === PlaybackType.LOCAL) { if (isCurrentSongRemoved) { mpvPlayer!.setQueue(playerData); } else { @@ -621,7 +621,7 @@ export const ContextMenuProvider = ({ children }: ContextMenuProviderProps) => { if (isCurrentSongRemoved) { remote?.updateSong({ song: playerData.current.song }); } - }, [ctx.dataNodes, ctx.tableApi, playerType, removeFromQueue]); + }, [ctx.dataNodes, ctx.tableApi, playbackType, removeFromQueue]); const handleDeselectAll = useCallback(() => { ctx.tableApi?.deselectAll(); diff --git a/src/renderer/features/lyrics/synchronized-lyrics.tsx b/src/renderer/features/lyrics/synchronized-lyrics.tsx index 1207798c..e0e0c17e 100644 --- a/src/renderer/features/lyrics/synchronized-lyrics.tsx +++ b/src/renderer/features/lyrics/synchronized-lyrics.tsx @@ -3,7 +3,7 @@ import { useCurrentStatus, useCurrentTime, useLyricsSettings, - usePlayerType, + usePlaybackType, useSeeked, } from '/@/renderer/store'; import { PlaybackType, PlayerStatus } from '/@/renderer/types'; @@ -59,7 +59,7 @@ export const SynchronizedLyrics = ({ }: SynchronizedLyricsProps) => { const playersRef = PlayersRef; const status = useCurrentStatus(); - const playerType = usePlayerType(); + const playbackType = usePlaybackType(); const now = useCurrentTime(); const settings = useLyricsSettings(); @@ -96,7 +96,7 @@ export const SynchronizedLyrics = ({ }; const getCurrentTime = useCallback(async () => { - if (isElectron() && playerType !== PlaybackType.WEB) { + if (isElectron() && playbackType !== PlaybackType.WEB) { if (mpvPlayer) { return mpvPlayer.getCurrentTime(); } @@ -116,7 +116,7 @@ export const SynchronizedLyrics = ({ if (!player) return 0; return player.currentTime; - }, [playerType, playersRef]); + }, [playbackType, playersRef]); const setCurrentLyric = useCallback( (timeInMs: number, epoch?: number, targetIndex?: number) => { @@ -222,7 +222,7 @@ export const SynchronizedLyrics = ({ } return () => {}; - }, [getCurrentTime, lyrics, playerType, setCurrentLyric, status]); + }, [getCurrentTime, lyrics, playbackType, setCurrentLyric, status]); useEffect(() => { // This handler is used to deal with changes to the current delay. If the offset diff --git a/src/renderer/features/now-playing/components/play-queue-list-controls.tsx b/src/renderer/features/now-playing/components/play-queue-list-controls.tsx index 72879812..ea13d0b5 100644 --- a/src/renderer/features/now-playing/components/play-queue-list-controls.tsx +++ b/src/renderer/features/now-playing/components/play-queue-list-controls.tsx @@ -15,7 +15,7 @@ import { import { Song } from '/@/renderer/api/types'; import { usePlayerControls, useQueueControls } from '/@/renderer/store'; import { PlaybackType, TableType } from '/@/renderer/types'; -import { usePlayerType } from '/@/renderer/store/settings.store'; +import { usePlaybackType } from '/@/renderer/store/settings.store'; import { usePlayerStore, useSetCurrentTime } from '../../../store/player.store'; import { TableConfigDropdown } from '/@/renderer/components/virtual-table'; @@ -34,7 +34,7 @@ export const PlayQueueListControls = ({ type, tableRef }: PlayQueueListOptionsPr const { pause } = usePlayerControls(); - const playerType = usePlayerType(); + const playbackType = usePlaybackType(); const setCurrentTime = useSetCurrentTime(); const handleMoveToBottom = () => { @@ -44,7 +44,7 @@ export const PlayQueueListControls = ({ type, tableRef }: PlayQueueListOptionsPr const playerData = moveToBottomOfQueue(uniqueIds); - if (playerType === PlaybackType.LOCAL) { + if (playbackType === PlaybackType.LOCAL) { mpvPlayer!.setQueueNext(playerData); } }; @@ -56,7 +56,7 @@ export const PlayQueueListControls = ({ type, tableRef }: PlayQueueListOptionsPr const playerData = moveToTopOfQueue(uniqueIds); - if (playerType === PlaybackType.LOCAL) { + if (playbackType === PlaybackType.LOCAL) { mpvPlayer!.setQueueNext(playerData); } }; @@ -70,7 +70,7 @@ export const PlayQueueListControls = ({ type, tableRef }: PlayQueueListOptionsPr const playerData = removeFromQueue(uniqueIds); const isCurrentSongRemoved = currentSong && uniqueIds.includes(currentSong.uniqueId); - if (playerType === PlaybackType.LOCAL) { + if (playbackType === PlaybackType.LOCAL) { if (isCurrentSongRemoved) { mpvPlayer!.setQueue(playerData); } else { @@ -86,7 +86,7 @@ export const PlayQueueListControls = ({ type, tableRef }: PlayQueueListOptionsPr const handleClearQueue = () => { const playerData = clearQueue(); - if (playerType === PlaybackType.LOCAL) { + if (playbackType === PlaybackType.LOCAL) { mpvPlayer!.setQueue(playerData); mpvPlayer!.pause(); } @@ -100,7 +100,7 @@ export const PlayQueueListControls = ({ type, tableRef }: PlayQueueListOptionsPr const handleShuffleQueue = () => { const playerData = shuffleQueue(); - if (playerType === PlaybackType.LOCAL) { + if (playbackType === PlaybackType.LOCAL) { mpvPlayer!.setQueueNext(playerData); } }; diff --git a/src/renderer/features/now-playing/components/play-queue.tsx b/src/renderer/features/now-playing/components/play-queue.tsx index 0b8bc581..1c98b6c3 100644 --- a/src/renderer/features/now-playing/components/play-queue.tsx +++ b/src/renderer/features/now-playing/components/play-queue.tsx @@ -19,7 +19,7 @@ import { useVolume, } from '/@/renderer/store'; import { - usePlayerType, + usePlaybackType, useSettingsStore, useSettingsStoreActions, useTableSettings, @@ -56,7 +56,7 @@ export const PlayQueue = forwardRef(({ type }: QueueProps, ref: Ref) => { const { setAppStore } = useAppStoreActions(); const tableConfig = useTableSettings(type); const [gridApi, setGridApi] = useState(); - const playerType = usePlayerType(); + const playbackType = usePlaybackType(); const { play } = usePlayerControls(); const volume = useVolume(); const isFocused = useAppFocus(); @@ -87,7 +87,7 @@ export const PlayQueue = forwardRef(({ type }: QueueProps, ref: Ref) => { status: PlayerStatus.PLAYING, }); - if (playerType === PlaybackType.LOCAL) { + if (playbackType === PlaybackType.LOCAL) { mpvPlayer!.volume(volume); mpvPlayer!.setQueue(playerData); mpvPlayer!.play(); @@ -111,7 +111,7 @@ export const PlayQueue = forwardRef(({ type }: QueueProps, ref: Ref) => { const playerData = reorderQueue(selectedUniqueIds as string[], e.overNode?.data?.uniqueId); - if (playerType === PlaybackType.LOCAL) { + if (playbackType === PlaybackType.LOCAL) { mpvPlayer!.setQueueNext(playerData); } diff --git a/src/renderer/features/player/components/center-controls.tsx b/src/renderer/features/player/components/center-controls.tsx index cb27df61..c2d72733 100644 --- a/src/renderer/features/player/components/center-controls.tsx +++ b/src/renderer/features/player/components/center-controls.tsx @@ -32,7 +32,7 @@ import { } from '/@/renderer/store'; import { useHotkeySettings, - usePlayerType, + usePlaybackType, useSettingsStore, } from '/@/renderer/store/settings.store'; import { PlayerStatus, PlaybackType, PlayerShuffle, PlayerRepeat } from '/@/renderer/types'; @@ -99,7 +99,7 @@ export const CenterControls = ({ playersRef }: CenterControlsProps) => { const currentSong = useCurrentSong(); const skip = useSettingsStore((state) => state.general.skipButtons); const buttonSize = useSettingsStore((state) => state.general.buttonSize); - const playerType = usePlayerType(); + const playbackType = usePlaybackType(); const player1 = playersRef?.current?.player1; const player2 = playersRef?.current?.player2; const status = useCurrentStatus(); @@ -134,7 +134,7 @@ export const CenterControls = ({ playersRef }: CenterControlsProps) => { let interval: any; if (status === PlayerStatus.PLAYING && !isSeeking) { - if (!isElectron() || playerType === PlaybackType.WEB) { + if (!isElectron() || playbackType === PlaybackType.WEB) { interval = setInterval(() => { setCurrentTime(currentPlayerRef.getCurrentTime()); }, 1000); @@ -144,7 +144,7 @@ export const CenterControls = ({ playersRef }: CenterControlsProps) => { } return () => clearInterval(interval); - }, [currentPlayerRef, isSeeking, setCurrentTime, playerType, status]); + }, [currentPlayerRef, isSeeking, setCurrentTime, playbackType, status]); const [seekValue, setSeekValue] = useState(0); diff --git a/src/renderer/features/player/components/playerbar.tsx b/src/renderer/features/player/components/playerbar.tsx index b251ad0d..03555297 100644 --- a/src/renderer/features/player/components/playerbar.tsx +++ b/src/renderer/features/player/components/playerbar.tsx @@ -1,7 +1,7 @@ import { useCallback } from 'react'; import isElectron from 'is-electron'; import styled from 'styled-components'; -import { useSettingsStore } from '/@/renderer/store/settings.store'; +import { usePlaybackType, useSettingsStore } from '/@/renderer/store/settings.store'; import { PlaybackType } from '/@/renderer/types'; import { AudioPlayer } from '/@/renderer/components'; import { @@ -64,6 +64,7 @@ const remote = isElectron() ? window.electron.remote : null; export const Playerbar = () => { const playersRef = PlayersRef; const settings = useSettingsStore((state) => state.playback); + const playbackType = usePlaybackType(); const volume = useVolume(); const player1 = usePlayer1Data(); const player2 = usePlayer2Data(); @@ -96,7 +97,7 @@ export const Playerbar = () => { - {settings.type === PlaybackType.WEB && ( + {playbackType === PlaybackType.WEB && ( { const { t } = useTranslation(); const { playersRef } = args; - const settings = useSettingsStore((state) => state.playback); const currentPlayer = useCurrentPlayer(); const { setShuffle, setRepeat, play, pause, previous, next, setCurrentIndex, autoNext } = usePlayerControls(); @@ -41,7 +38,7 @@ export const useCenterControls = (args: { playersRef: any }) => { const playerStatus = useCurrentStatus(); const repeatStatus = useRepeatStatus(); const shuffleStatus = useShuffleStatus(); - const playerType = usePlayerType(); + const playbackType = usePlaybackType(); const player1Ref = playersRef?.current?.player1; const player2Ref = playersRef?.current?.player2; const currentPlayerRef = currentPlayer === 1 ? player1Ref : player2Ref; @@ -77,7 +74,7 @@ export const useCenterControls = (args: { playersRef: any }) => { resetPlayers(); }, [player1Ref, player2Ref, resetPlayers]); - const isMpvPlayer = isElectron() && settings.type === PlaybackType.LOCAL; + const isMpvPlayer = isElectron() && playbackType === PlaybackType.LOCAL; const mprisUpdateSong = (args?: { currentTime?: number; @@ -282,13 +279,13 @@ export const useCenterControls = (args: { playersRef: any }) => { switch (repeatStatus) { case PlayerRepeat.NONE: - handleRepeatNone[playerType](); + handleRepeatNone[playbackType](); break; case PlayerRepeat.ALL: - handleRepeatAll[playerType](); + handleRepeatAll[playbackType](); break; case PlayerRepeat.ONE: - handleRepeatOne[playerType](); + handleRepeatOne[playbackType](); break; default: @@ -299,7 +296,7 @@ export const useCenterControls = (args: { playersRef: any }) => { checkIsLastTrack, pause, play, - playerType, + playbackType, repeatStatus, resetPlayers, setCurrentIndex, @@ -380,13 +377,13 @@ export const useCenterControls = (args: { playersRef: any }) => { switch (repeatStatus) { case PlayerRepeat.NONE: - handleRepeatNone[playerType](); + handleRepeatNone[playbackType](); break; case PlayerRepeat.ALL: - handleRepeatAll[playerType](); + handleRepeatAll[playbackType](); break; case PlayerRepeat.ONE: - handleRepeatOne[playerType](); + handleRepeatOne[playbackType](); break; default: @@ -398,7 +395,7 @@ export const useCenterControls = (args: { playersRef: any }) => { checkIsLastTrack, next, pause, - playerType, + playbackType, repeatStatus, resetPlayers, setCurrentIndex, @@ -511,13 +508,13 @@ export const useCenterControls = (args: { playersRef: any }) => { switch (repeatStatus) { case PlayerRepeat.NONE: - handleRepeatNone[playerType](); + handleRepeatNone[playbackType](); break; case PlayerRepeat.ALL: - handleRepeatAll[playerType](); + handleRepeatAll[playbackType](); break; case PlayerRepeat.ONE: - handleRepeatOne[playerType](); + handleRepeatOne[playbackType](); break; default: @@ -531,7 +528,7 @@ export const useCenterControls = (args: { playersRef: any }) => { handleScrobbleFromSongRestart, isMpvPlayer, pause, - playerType, + playbackType, previous, queue.length, repeatStatus, diff --git a/src/renderer/features/player/hooks/use-handle-playqueue-add.ts b/src/renderer/features/player/hooks/use-handle-playqueue-add.ts index 1950b678..099bb4c8 100644 --- a/src/renderer/features/player/hooks/use-handle-playqueue-add.ts +++ b/src/renderer/features/player/hooks/use-handle-playqueue-add.ts @@ -1,7 +1,7 @@ import { useCallback, useRef } from 'react'; import { useQueryClient } from '@tanstack/react-query'; import { useCurrentServer, usePlayerControls, usePlayerStore } from '/@/renderer/store'; -import { usePlayerType } from '/@/renderer/store/settings.store'; +import { usePlaybackType } from '/@/renderer/store/settings.store'; import { PlayQueueAddOptions, Play, @@ -65,7 +65,7 @@ const addToQueue = usePlayerStore.getState().actions.addToQueue; export const useHandlePlayQueueAdd = () => { const { t } = useTranslation(); const queryClient = useQueryClient(); - const playerType = usePlayerType(); + const playbackType = usePlaybackType(); const server = useCurrentServer(); const { play } = usePlayerControls(); const timeoutIds = useRef> | null>({}); @@ -170,7 +170,7 @@ export const useHandlePlayQueueAdd = () => { const hadSong = usePlayerStore.getState().queue.default.length > 0; const playerData = addToQueue({ initialIndex: initialSongIndex, playType, songs }); - if (playerType === PlaybackType.LOCAL) { + if (playbackType === PlaybackType.LOCAL) { mpvPlayer!.volume(usePlayerStore.getState().volume); if (playType === Play.NEXT || playType === Play.LAST) { @@ -200,7 +200,7 @@ export const useHandlePlayQueueAdd = () => { return null; }, - [play, playerType, queryClient, server, t], + [play, playbackType, queryClient, server, t], ); return handlePlayQueueAdd; diff --git a/src/renderer/features/settings/components/playback/mpv-settings.tsx b/src/renderer/features/settings/components/playback/mpv-settings.tsx index 2128ba44..9004a465 100644 --- a/src/renderer/features/settings/components/playback/mpv-settings.tsx +++ b/src/renderer/features/settings/components/playback/mpv-settings.tsx @@ -161,21 +161,24 @@ export const MpvSettings = () => { handleSetMpvPath(null)} + > + + + ) + } width={200} onChange={handleSetMpvPath} /> - {mpvPath && ( - - )} ), description: t('setting.mpvExecutablePath', { diff --git a/src/renderer/router/app-outlet.tsx b/src/renderer/router/app-outlet.tsx index 10131c53..d77a8981 100644 --- a/src/renderer/router/app-outlet.tsx +++ b/src/renderer/router/app-outlet.tsx @@ -2,14 +2,16 @@ import { useMemo, useEffect } from 'react'; import isElectron from 'is-electron'; import { Navigate, Outlet } from 'react-router-dom'; import { AppRoute } from '/@/renderer/router/routes'; -import { useCurrentServer } from '/@/renderer/store'; +import { useCurrentServer, useSetPlayerFallback } from '/@/renderer/store'; import { toast } from '/@/renderer/components'; const ipc = isElectron() ? window.electron.ipc : null; const utils = isElectron() ? window.electron.utils : null; +const mpvPlayerListener = isElectron() ? window.electron.mpvPlayerListener : null; export const AppOutlet = () => { const currentServer = useCurrentServer(); + const setFallback = useSetPlayerFallback(); const isActionsRequired = useMemo(() => { const isServerRequired = !currentServer; @@ -25,10 +27,15 @@ export const AppOutlet = () => { toast.show(data); }); + mpvPlayerListener?.rendererPlayerFallback((_event, data) => { + setFallback(data); + }); + return () => { ipc?.removeAllListeners('toast-from-main'); + ipc?.removeAllListeners('renderer-player-fallback'); }; - }, []); + }, [setFallback]); if (isActionsRequired) { return ( diff --git a/src/renderer/store/player.store.ts b/src/renderer/store/player.store.ts index 7e67523b..737122b3 100644 --- a/src/renderer/store/player.store.ts +++ b/src/renderer/store/player.store.ts @@ -22,6 +22,7 @@ export interface PlayerState { status: PlayerStatus; time: number; }; + fallback: boolean | null; muted: boolean; queue: { default: QueueSong[]; @@ -85,6 +86,7 @@ export interface PlayerSlice extends PlayerState { setCurrentSpeed: (speed: number) => void; setCurrentTime: (time: number, seek?: boolean) => void; setCurrentTrack: (uniqueId: string) => PlayerData; + setFallback: (fallback: boolean | null) => boolean; setFavorite: (ids: string[], favorite: boolean) => string[]; setMuted: (muted: boolean) => void; setRating: (ids: string[], rating: number | null) => string[]; @@ -806,6 +808,13 @@ export const usePlayerStore = create()( return get().actions.getPlayerData(); }, + setFallback: (fallback) => { + set((state) => { + state.fallback = fallback; + }); + + return fallback || false; + }, setFavorite: (ids, favorite) => { const { default: queue } = get().queue; const foundUniqueIds = []; @@ -953,6 +962,7 @@ export const usePlayerStore = create()( status: PlayerStatus.PAUSED, time: 0, }, + fallback: null, muted: false, queue: { default: [], @@ -973,7 +983,7 @@ export const usePlayerStore = create()( }, name: 'store_player', partialize: (state) => { - const notPersisted = ['queue', 'current', 'entry']; + const notPersisted = ['queue', 'current', 'entry', 'fallback']; return Object.fromEntries( Object.entries(state).filter(([key]) => !notPersisted.includes(key)), ); @@ -1066,6 +1076,10 @@ export const useMuted = () => usePlayerStore((state) => state.muted); export const useSpeed = () => usePlayerStore((state) => state.current.speed); +export const usePlayerFallback = () => usePlayerStore((state) => state.fallback); + +export const useSetPlayerFallback = () => usePlayerStore((state) => state.actions.setFallback); + export const useSetCurrentSpeed = () => usePlayerStore((state) => state.actions.setCurrentSpeed); export const useSetQueueFavorite = () => usePlayerStore((state) => state.actions.setFavorite); diff --git a/src/renderer/store/settings.store.ts b/src/renderer/store/settings.store.ts index 0f0b5f92..b58a8b75 100644 --- a/src/renderer/store/settings.store.ts +++ b/src/renderer/store/settings.store.ts @@ -23,6 +23,7 @@ import { } from '/@/renderer/types'; import { randomString } from '/@/renderer/utils'; import i18n from '/@/i18n/i18n'; +import { usePlayerStore } from '/@/renderer/store/player.store'; const utils = isElectron() ? window.electron.utils : null; @@ -616,7 +617,16 @@ export const useTableSettings = (type: TableType) => export const useGeneralSettings = () => useSettingsStore((state) => state.general, shallow); -export const usePlayerType = () => useSettingsStore((state) => state.playback.type, shallow); +export const usePlaybackType = () => + useSettingsStore((state) => { + const isFallback = usePlayerStore.getState().fallback; + + if (isFallback) { + return PlaybackType.WEB; + } + + return state.playback.type; + }); export const usePlayButtonBehavior = () => useSettingsStore((state) => state.general.playButtonBehavior, shallow);