prevent selection while playing to avoid artifacts

This commit is contained in:
Jade (Rose) Rowland 2023-12-30 22:40:27 -05:00
parent 69554c0762
commit b3522fea6a
5 changed files with 32 additions and 12 deletions

View file

@ -28,9 +28,13 @@ export const resetLoadedSounds = () => soundMap.set({});
let audioContext; let audioContext;
export const getAudioContext = (reset) => { export const setDefaultAudioContext = () => {
if (!audioContext || reset) { audioContext = new AudioContext();
audioContext = new AudioContext(); };
export const getAudioContext = () => {
if (!audioContext) {
setDefaultAudioContext();
} }
return audioContext; return audioContext;
}; };

View file

@ -1,5 +1,5 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { getAudioContext, initializeAudioOutput } from '@strudel.cycles/webaudio'; import { getAudioContext, initializeAudioOutput, setDefaultAudioContext } from '@strudel.cycles/webaudio';
import { SelectInput } from './SelectInput'; import { SelectInput } from './SelectInput';
import { logger } from '@strudel.cycles/core'; import { logger } from '@strudel.cycles/core';
@ -19,21 +19,27 @@ export const getAudioDevices = async () => {
}; };
export const setAudioDevice = async (id) => { export const setAudioDevice = async (id) => {
const audioCtx = getAudioContext();
if (audioCtx.sinkId === id) {
console.log(audioCtx.sinkId, id);
return;
}
const isValidID = (id ?? '').length > 0; const isValidID = (id ?? '').length > 0;
// reset the audio context and dont set the sink id if it is invalid AKA System Standard selection
const audioCtx = getAudioContext(!isValidID);
if (isValidID) { if (isValidID) {
try { try {
await audioCtx.setSinkId(id); await audioCtx.setSinkId(id);
} catch { } catch {
logger('failed to set audio interface', 'warning'); logger('failed to set audio interface', 'warning');
} }
} else {
// reset the audio context and dont set the sink id if it is invalid AKA System Standard selection
setDefaultAudioContext();
} }
initializeAudioOutput(); initializeAudioOutput();
}; };
// Allows the user to select an audio interface for Strudel to play through // Allows the user to select an audio interface for Strudel to play through
export function AudioDeviceSelector({ audioDeviceName, onChange }) { export function AudioDeviceSelector({ audioDeviceName, onChange, isDisabled }) {
const [devices, setDevices] = useState(initdevices); const [devices, setDevices] = useState(initdevices);
const devicesInitialized = devices.size > 0; const devicesInitialized = devices.size > 0;
@ -57,5 +63,13 @@ export function AudioDeviceSelector({ audioDeviceName, onChange }) {
Array.from(devices.keys()).forEach((deviceName) => { Array.from(devices.keys()).forEach((deviceName) => {
options.set(deviceName, deviceName); options.set(deviceName, deviceName);
}); });
return <SelectInput options={options} onClick={onClick} value={audioDeviceName} onChange={onDeviceChange} />; return (
<SelectInput
isDisabled={isDisabled}
options={options}
onClick={onClick}
value={audioDeviceName}
onChange={onDeviceChange}
/>
);
} }

View file

@ -114,7 +114,7 @@ export function Panel({ context }) {
{activeFooter === 'console' && <ConsoleTab log={log} />} {activeFooter === 'console' && <ConsoleTab log={log} />}
{activeFooter === 'sounds' && <SoundsTab />} {activeFooter === 'sounds' && <SoundsTab />}
{activeFooter === 'reference' && <Reference />} {activeFooter === 'reference' && <Reference />}
{activeFooter === 'settings' && <SettingsTab />} {activeFooter === 'settings' && <SettingsTab started={context.started} />}
{activeFooter === 'files' && <FilesTab />} {activeFooter === 'files' && <FilesTab />}
</div> </div>
</div> </div>

View file

@ -1,8 +1,9 @@
import React from 'react'; import React from 'react';
// value: ?ID, options: Map<ID, any>, onChange: ID => null, onClick: event => void // value: ?ID, options: Map<ID, any>, onChange: ID => null, onClick: event => void, isDisabled: boolean
export function SelectInput({ value, options, onChange, onClick }) { export function SelectInput({ value, options, onChange, onClick, isDisabled }) {
return ( return (
<select <select
disabled={isDisabled}
onClick={onClick} onClick={onClick}
className="p-2 bg-background rounded-md text-foreground" className="p-2 bg-background rounded-md text-foreground"
value={value ?? ''} value={value ?? ''}

View file

@ -73,7 +73,7 @@ const fontFamilyOptions = {
mode7: 'mode7', mode7: 'mode7',
}; };
export function SettingsTab() { export function SettingsTab({ started }) {
const { const {
theme, theme,
keybindings, keybindings,
@ -95,6 +95,7 @@ export function SettingsTab() {
{AudioContext.prototype.setSinkId != null && ( {AudioContext.prototype.setSinkId != null && (
<FormItem label="Audio Output Device"> <FormItem label="Audio Output Device">
<AudioDeviceSelector <AudioDeviceSelector
isDisabled={started}
audioDeviceName={audioDeviceName} audioDeviceName={audioDeviceName}
onChange={(audioDeviceName) => settingsMap.setKey('audioDeviceName', audioDeviceName)} onChange={(audioDeviceName) => settingsMap.setKey('audioDeviceName', audioDeviceName)}
/> />