diff --git a/src/main/features/core/player/index.ts b/src/main/features/core/player/index.ts index e9f80c290..38bc0e9bb 100644 --- a/src/main/features/core/player/index.ts +++ b/src/main/features/core/player/index.ts @@ -1,4 +1,5 @@ import { ipcMain } from 'electron'; +import uniq from 'lodash/uniq'; import MpvAPI from 'node-mpv'; import { PlayerData } from '../../../../renderer/store'; import { getMainWindow } from '../../../main'; @@ -7,7 +8,29 @@ import './media-keys'; declare module 'node-mpv'; -const BINARY_PATH = store.get('mpv_path') as string; +const BINARY_PATH = store.get('mpv_path') as string | undefined; +const MPV_PARAMETERS = store.get('mpv_parameters') as Array | undefined; +const DEFAULT_MPV_PARAMETERS = () => { + const parameters = []; + if ( + !MPV_PARAMETERS?.includes('--gapless-audio=weak') || + !MPV_PARAMETERS?.includes('--gapless-audio=no') || + !MPV_PARAMETERS?.includes('--gapless-audio=yes') || + !MPV_PARAMETERS?.includes('--gapless-audio') + ) { + parameters.push('--gapless-audio=yes'); + } + + if ( + !MPV_PARAMETERS?.includes('--prefetch-playlist=no') || + !MPV_PARAMETERS?.includes('--prefetch-playlist=yes') || + !MPV_PARAMETERS?.includes('--prefetch-playlist') + ) { + parameters.push('--prefetch-playlist=yes'); + } + + return parameters; +}; const mpv = new MpvAPI( { @@ -16,7 +39,9 @@ const mpv = new MpvAPI( binary: BINARY_PATH || '', time_update: 1, }, - ['--gapless-audio=yes', '--prefetch-playlist'] + MPV_PARAMETERS + ? uniq([...DEFAULT_MPV_PARAMETERS(), ...MPV_PARAMETERS]) + : DEFAULT_MPV_PARAMETERS() ); mpv.start().catch((error: any) => { diff --git a/src/renderer/features/settings/components/playback-tab.tsx b/src/renderer/features/settings/components/playback-tab.tsx index 963ee1fe6..58ed4b5ef 100644 --- a/src/renderer/features/settings/components/playback-tab.tsx +++ b/src/renderer/features/settings/components/playback-tab.tsx @@ -8,6 +8,8 @@ import { Select, Slider, Switch, + Text, + Textarea, toast, Tooltip, } from '@/renderer/components'; @@ -46,6 +48,7 @@ export const PlaybackTab = () => { const status = usePlayerStore((state) => state.current.status); const [audioDevices, setAudioDevices] = useState([]); const [mpvPath, setMpvPath] = useState(''); + const [mpvParameters, setMpvParameters] = useState(''); const handleSetMpvPath = (e: File) => { setLocalSetting('mpv_path', e.path); @@ -58,7 +61,15 @@ export const PlaybackTab = () => { return setMpvPath(mpvPath); }; + const getMpvParameters = async () => { + if (!isElectron()) return setMpvPath(''); + const mpvParametersFromSettings = await getLocalSetting('mpv_parameters'); + const mpvParameters = mpvParametersFromSettings?.join('\n'); + return setMpvParameters(mpvParameters); + }; + getMpvPath(); + getMpvParameters(); }, []); useEffect(() => { @@ -82,7 +93,7 @@ export const PlaybackTab = () => { data={[ { disabled: !isElectron(), - label: 'MPV', + label: 'Mpv', value: PlaybackType.LOCAL, }, { label: 'Web', value: PlaybackType.WEB }, @@ -98,7 +109,7 @@ export const PlaybackTab = () => { }} /> ), - description: 'The audio player to use for playback (desktop only)', + description: 'The audio player to use for playback', isHidden: !isElectron(), note: status === PlayerStatus.PLAYING ? 'Player must be paused' : undefined, @@ -113,10 +124,55 @@ export const PlaybackTab = () => { onChange={handleSetMpvPath} /> ), - description: 'The location of your MPV executable', + description: 'The location of your mpv executable', isHidden: settings.type !== PlaybackType.LOCAL, note: 'Restart required', - title: 'MPV executable path', + title: 'Mpv executable path', + }, + { + control: ( + +