decouple audio device setting property depending on player type (#1617)

This commit is contained in:
jeffvli
2026-01-30 17:55:25 -08:00
parent bdd5c78d39
commit ad83e95a46
4 changed files with 35 additions and 13 deletions
@@ -56,7 +56,7 @@ export const MpvPlayerEngine = (props: MpvPlayerEngineProps) => {
const hasPopulatedQueueRef = useRef<boolean>(false); const hasPopulatedQueueRef = useRef<boolean>(false);
const isMountedRef = useRef<boolean>(true); const isMountedRef = useRef<boolean>(true);
const { audioDeviceId, transcode } = usePlaybackSettings(); const { mpvAudioDeviceId, transcode } = usePlaybackSettings();
const mpvExtraParameters = useSettingsStore((store) => store.playback.mpvExtraParameters); const mpvExtraParameters = useSettingsStore((store) => store.playback.mpvExtraParameters);
const mpvProperties = useSettingsStore((store) => store.playback.mpvProperties); const mpvProperties = useSettingsStore((store) => store.playback.mpvProperties);
const [reloadTrigger, setReloadTrigger] = useState(0); const [reloadTrigger, setReloadTrigger] = useState(0);
@@ -108,8 +108,8 @@ export const MpvPlayerEngine = (props: MpvPlayerEngineProps) => {
const extraParameters: string[] = [...mpvExtraParameters]; const extraParameters: string[] = [...mpvExtraParameters];
if (audioDeviceId) { if (mpvAudioDeviceId) {
extraParameters.push(`--audio-device=${audioDeviceId}`); extraParameters.push(`--audio-device=${mpvAudioDeviceId}`);
} }
await mpvPlayer?.initialize({ await mpvPlayer?.initialize({
@@ -154,7 +154,7 @@ export const MpvPlayerEngine = (props: MpvPlayerEngineProps) => {
// update callbacks in usePlayerEvents. // update callbacks in usePlayerEvents.
// reloadTrigger is included to allow manual reload via MPV_RELOAD event. // reloadTrigger is included to allow manual reload via MPV_RELOAD event.
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [mpvExtraParameters, mpvProperties, audioDeviceId, reloadTrigger]); }, [mpvExtraParameters, mpvProperties, mpvAudioDeviceId, reloadTrigger]);
// Update volume // Update volume
useEffect(() => { useEffect(() => {
@@ -5,6 +5,7 @@ import { useTranslation } from 'react-i18next';
import { useAudioDevices } from '/@/renderer/features/settings/components/playback/audio-settings'; import { useAudioDevices } from '/@/renderer/features/settings/components/playback/audio-settings';
import { ListConfigTable } from '/@/renderer/features/shared/components/list-config-menu'; import { ListConfigTable } from '/@/renderer/features/shared/components/list-config-menu';
import { import {
usePlaybackType,
usePlayerActions, usePlayerActions,
usePlayerProperties, usePlayerProperties,
usePlayerSongProperties, usePlayerSongProperties,
@@ -233,23 +234,30 @@ const AudioPlayerTypeConfig = () => {
const AudioDeviceConfig = () => { const AudioDeviceConfig = () => {
const status = usePlayerStatus(); const status = usePlayerStatus();
const playbackType = usePlaybackType();
const playbackSettings = usePlaybackSettings(); const playbackSettings = usePlaybackSettings();
const { setSettings } = useSettingsStoreActions(); const { setSettings } = useSettingsStoreActions();
const audioDevices = useAudioDevices(); const audioDevices = useAudioDevices(playbackType);
const audioDeviceId =
playbackType === PlayerType.LOCAL
? playbackSettings.mpvAudioDeviceId
: playbackSettings.audioDeviceId;
return ( return (
<Select <Select
clearable clearable
comboboxProps={{ withinPortal: false }} comboboxProps={{ withinPortal: false }}
data={audioDevices} data={audioDevices}
defaultValue={playbackSettings.audioDeviceId} defaultValue={audioDeviceId}
disabled={status === PlayerStatus.PLAYING} disabled={status === PlayerStatus.PLAYING}
onChange={(e) => { onChange={(e) => {
setSettings({ setSettings({
playback: { playback: {
...playbackSettings, ...playbackSettings,
audioDeviceId: e, ...(playbackType === PlayerType.LOCAL
? { mpvAudioDeviceId: e }
: { audioDeviceId: e }),
}, },
}); });
}} }}
@@ -36,9 +36,10 @@ const getMpvAudioDevices = async () => {
} }
}; };
export const useAudioDevices = () => { export type AudioDeviceOption = { label: string; value: string };
const playbackType = usePlaybackType();
const [audioDevices, setAudioDevices] = useState<{ label: string; value: string }[]>([]); export const useAudioDevices = (playbackType: PlayerType) => {
const [audioDevices, setAudioDevices] = useState<AudioDeviceOption[]>([]);
useEffect(() => { useEffect(() => {
const fetchAudioDevices = async () => { const fetchAudioDevices = async () => {
@@ -92,8 +93,11 @@ export const AudioSettings = memo(() => {
const settings = usePlaybackSettings(); const settings = usePlaybackSettings();
const { setSettings } = useSettingsStoreActions(); const { setSettings } = useSettingsStoreActions();
const status = usePlayerStatus(); const status = usePlayerStatus();
const playbackType = usePlaybackType();
const audioDevices = useAudioDevices(); const audioDevices = useAudioDevices(playbackType);
const audioDeviceId =
playbackType === PlayerType.LOCAL ? settings.mpvAudioDeviceId : settings.audioDeviceId;
const audioOptions: SettingOption[] = [ const audioOptions: SettingOption[] = [
{ {
@@ -131,15 +135,23 @@ export const AudioSettings = memo(() => {
<Select <Select
clearable clearable
data={audioDevices} data={audioDevices}
defaultValue={settings.audioDeviceId} defaultValue={audioDeviceId}
disabled={!isElectron()} disabled={!isElectron()}
onChange={(e) => setSettings({ playback: { audioDeviceId: e } })} onChange={(e) =>
setSettings({
playback:
playbackType === PlayerType.LOCAL
? { mpvAudioDeviceId: e }
: { audioDeviceId: e },
})
}
/> />
), ),
description: t('setting.audioDevice', { description: t('setting.audioDevice', {
context: 'description', context: 'description',
postProcess: 'sentenceCase', postProcess: 'sentenceCase',
}), }),
isHidden: !isElectron(),
title: t('setting.audioDevice', { postProcess: 'sentenceCase' }), title: t('setting.audioDevice', { postProcess: 'sentenceCase' }),
}, },
{ {
+2
View File
@@ -554,6 +554,7 @@ const PlaybackSettingsSchema = z.object({
audioFadeOnStatusChange: z.boolean(), audioFadeOnStatusChange: z.boolean(),
filters: z.array(PlayerFilterSchema), filters: z.array(PlayerFilterSchema),
mediaSession: z.boolean(), mediaSession: z.boolean(),
mpvAudioDeviceId: z.string().nullable().optional(),
mpvExtraParameters: z.array(z.string()), mpvExtraParameters: z.array(z.string()),
mpvProperties: MpvSettingsSchema, mpvProperties: MpvSettingsSchema,
preservePitch: z.boolean(), preservePitch: z.boolean(),
@@ -1538,6 +1539,7 @@ const initialState: SettingsState = {
audioFadeOnStatusChange: true, audioFadeOnStatusChange: true,
filters: [], filters: [],
mediaSession: false, mediaSession: false,
mpvAudioDeviceId: undefined,
mpvExtraParameters: [], mpvExtraParameters: [],
mpvProperties: { mpvProperties: {
audioExclusiveMode: 'no', audioExclusiveMode: 'no',