mirror of
https://github.com/jeffvli/sonixd.git
synced 2026-04-30 11:12:36 -04:00
Add system audio device selector (#96)
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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'}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user