Add system audio device selector (#96)

This commit is contained in:
jeffvli
2021-11-23 12:05:20 -08:00
committed by Jeff
parent f542895839
commit 42a86b2edf
5 changed files with 57 additions and 4 deletions

View File

@@ -590,6 +590,13 @@ const Player = ({ currentEntryList, children }: any, ref: any) => {
[config.serverType, currentEntryList, playQueue, player.currentSeek]
);
useEffect(() => {
if (config.playback.audioDeviceId) {
player1Ref.current.audioEl.current.setSinkId(config.playback.audioDeviceId);
player2Ref.current.audioEl.current.setSinkId(config.playback.audioDeviceId);
}
}, [config.playback.audioDeviceId]);
return (
<>
<Helmet>

View File

@@ -1,4 +1,4 @@
import React, { useEffect, useState } from 'react';
import React, { useEffect, useRef, useState } from 'react';
import { shell } from 'electron';
import settings from 'electron-settings';
import { ControlLabel, Divider, Form } from 'rsuite';
@@ -9,16 +9,24 @@ import {
StyledInput,
StyledInputGroup,
StyledInputNumber,
StyledInputPicker,
StyledInputPickerContainer,
StyledLink,
StyledPanel,
} from '../../shared/styled';
import { useAppDispatch, useAppSelector } from '../../../redux/hooks';
import { setPlaybackSetting } from '../../../redux/playQueueSlice';
import ListViewTable from '../../viewtypes/ListViewTable';
import { appendPlaybackFilter } from '../../../redux/configSlice';
import { appendPlaybackFilter, setAudioDeviceId } from '../../../redux/configSlice';
import { notifyToast } from '../../shared/toast';
const isMacOS = process.platform === 'darwin';
const getAudioDevice = async () => {
const devices = await navigator.mediaDevices.enumerateDevices();
return (devices || []).filter((dev: MediaDeviceInfo) => dev.kind === 'audiooutput');
};
const playbackFilterColumns = [
{
id: '#',
@@ -64,18 +72,44 @@ const PlayerConfig = () => {
Boolean(settings.getSync('globalMediaHotkeys'))
);
const [scrobble, setScrobble] = useState(Boolean(settings.getSync('scrobble')));
const [audioDevices, setAudioDevices] = useState<MediaDeviceInfo[]>();
const audioDevicePickerContainerRef = useRef(null);
useEffect(() => {
settings.setSync('playbackFilters', config.playback.filters);
}, [config.playback.filters]);
useEffect(() => {
const getAudioDevices = () => {
getAudioDevice()
.then((dev) => setAudioDevices(dev))
.catch(() => notifyToast('error', 'Error fetching audio devices'));
};
getAudioDevices();
}, []);
return (
<ConfigPanel header="Player" bordered>
<p>
Configure the number of seconds to skip forwards/backwards by when clicking the seek
forward/backward buttons.
Set your desired audio device. Leaving this blank will use the system default audio device.
</p>
<br />
<StyledInputPickerContainer ref={audioDevicePickerContainerRef}>
<StyledInputPicker
container={() => audioDevicePickerContainerRef.current}
data={audioDevices}
defaultValue={config.playback.audioDeviceId}
value={config.playback.audioDeviceId}
labelKey="label"
valueKey="deviceId"
onChange={(e: string) => {
dispatch(setAudioDeviceId(e));
settings.setSync('audioDeviceId', e);
}}
/>
</StyledInputPickerContainer>
<br />
<ControlLabel>Seek forward (s)</ControlLabel>
<StyledInputNumber
defaultValue={String(settings.getSync('seekForwardInterval')) || '0'}

View File

@@ -78,6 +78,10 @@ const setDefaultSettings = (force: boolean) => {
settings.setSync('volume', 0.3);
}
if (force || !settings.hasSync('audioDeviceId')) {
settings.setSync('audioDeviceId', null);
}
if (force || !settings.hasSync('seekForwardInterval')) {
settings.setSync('seekForwardInterval', 5);
}

View File

@@ -14,6 +14,7 @@ export interface ConfigPage {
};
playback: {
filters: PlaybackFilter[];
audioDeviceId?: string;
};
sort: {
albumListPage?: SortColumn;
@@ -64,6 +65,7 @@ const initialState: ConfigPage = {
},
playback: {
filters: parsedSettings.playbackFilters,
audioDeviceId: parsedSettings.audioDeviceId || undefined,
},
sort: {
albumListPage: undefined,
@@ -176,6 +178,10 @@ const configSlice = createSlice({
state.playback.filters[selectedFilterIndex] = action.payload.newFilter;
},
setAudioDeviceId: (state, action: PayloadAction<string>) => {
state.playback.audioDeviceId = action.payload;
},
removePlaybackFilter: (state, action: PayloadAction<{ filterName: string }>) => {
state.playback.filters = state.playback.filters.filter(
(f: PlaybackFilter) => f.filter !== action.payload.filterName
@@ -237,6 +243,7 @@ export const {
removePlaybackFilter,
setPlaybackFilter,
setPlaybackFilters,
setAudioDeviceId,
setColumnList,
setRowHeight,
setFontSize,

View File

@@ -5,6 +5,7 @@ export const mockSettings = {
cachePath: 'C:\\Users\\jli\\AppData\\Roaming\\Electron',
legacyAuth: false,
volume: 0.93,
audioDeviceId: null,
seekForwardInterval: 5,
seekBackwardInterval: 5,
volumeFade: true,