From 5281c61f99c3a428bb4b91ec4f3e7ca6e14409c8 Mon Sep 17 00:00:00 2001 From: Jade Rowland Date: Fri, 8 Dec 2023 01:01:06 -0500 Subject: [PATCH] fixing async stuff --- packages/superdough/superdough.mjs | 1 - .../src/repl/panel/AudioDeviceSelector.jsx | 85 +++++++++---------- website/src/repl/panel/SelectInput.jsx | 9 +- website/src/repl/panel/SettingsTab.jsx | 14 +-- 4 files changed, 51 insertions(+), 58 deletions(-) diff --git a/packages/superdough/superdough.mjs b/packages/superdough/superdough.mjs index 6c7d8cd3..b8edac1c 100644 --- a/packages/superdough/superdough.mjs +++ b/packages/superdough/superdough.mjs @@ -86,7 +86,6 @@ let channelMerger, destinationGain; export function initializeAudioOutput() { const audioContext = getAudioContext(); const maxChannelCount = audioContext.destination.maxChannelCount; - console.log(maxChannelCount); audioContext.destination.channelCount = maxChannelCount; channelMerger = new ChannelMergerNode(audioContext, { numberOfInputs: audioContext.destination.channelCount }); destinationGain = new GainNode(audioContext); diff --git a/website/src/repl/panel/AudioDeviceSelector.jsx b/website/src/repl/panel/AudioDeviceSelector.jsx index 27d50349..afdaff00 100644 --- a/website/src/repl/panel/AudioDeviceSelector.jsx +++ b/website/src/repl/panel/AudioDeviceSelector.jsx @@ -1,70 +1,61 @@ -import React, { useState, useEffect } from 'react'; +import React, { useState, useEffect, useCallback } from 'react'; import { getAudioContext, initializeAudioOutput } from '@strudel.cycles/webaudio'; import { SelectInput } from './SelectInput'; -async function setAudioDevice(id) { - const audioCtx = getAudioContext(); - await audioCtx.setSinkId(id); - await initializeAudioOutput(); -} +const initdevices = new Map(); export function AudioDeviceSelector({ audioDeviceName, onChange }) { - const [options, setOptions] = useState({}); - const [optionsInitialized, setOptionsInitialized] = useState(false); + const [devices, setDevices] = useState(initdevices); + const devicesInitialized = devices.size > 0; - async function initializeOptions() { + const setAudioDevice = useCallback(async (id) => { + const audioCtx = getAudioContext(); + await audioCtx.setSinkId(id); + initializeAudioOutput(); + }); + const initializedevices = useCallback(async () => { await navigator.mediaDevices.getUserMedia({ audio: true }); - let devices = await navigator.mediaDevices.enumerateDevices(); - devices = devices.filter((device) => device.kind === 'audiooutput' && device.deviceId !== 'default'); - const optionsArray = []; - devices.forEach((device) => { - optionsArray.push([device.deviceId, device.label]); + let mediaDevices = await navigator.mediaDevices.enumerateDevices(); + mediaDevices = mediaDevices.filter((device) => device.kind === 'audiooutput' && device.deviceId !== 'default'); + const devicesMap = new Map(); + mediaDevices.forEach((device) => { + devicesMap.set(device.label, device.deviceId); }); - const options = Object.fromEntries(optionsArray); - setOptions(options); - setOptionsInitialized(true); - return options; - } + setDevices(devicesMap); + return devicesMap; + }, []); useEffect(() => { - if (!audioDeviceName.length || optionsInitialized) { + if (!audioDeviceName.length || devicesInitialized) { return; } - - (async () => { - const options = await initializeOptions(); - - const deviceID = Object.keys(options).find((id) => options[id] === audioDeviceName); - + initializedevices().then((devices) => { + const deviceID = devices.get(audioDeviceName); if (deviceID == null) { onChange(''); return; } - - await setAudioDevice(deviceID); - })(); + setAudioDevice(deviceID); + }); }, []); const onClick = () => { - if (optionsInitialized) { + if (devicesInitialized) { return; } - (async () => { - await initializeOptions(); - })(); + initializedevices(); }; - const onDeviceChange = (deviceID) => { - (async () => { - const deviceName = options[deviceID]; - onChange(deviceName); - await setAudioDevice(deviceID); - })(); + const onDeviceChange = (deviceName) => { + if (!devicesInitialized) { + return; + } + const deviceID = devices.get(deviceName); + onChange(deviceName); + deviceID && setAudioDevice(deviceID); }; - return ( - options[id] === audioDeviceName)} - onChange={onDeviceChange} - /> - ); + const options = new Set(); + + Array.from(devices.keys()).forEach((deviceName) => { + options.add({ id: deviceName, label: deviceName }); + }); + return ; } diff --git a/website/src/repl/panel/SelectInput.jsx b/website/src/repl/panel/SelectInput.jsx index c0a952b0..53f958b8 100644 --- a/website/src/repl/panel/SelectInput.jsx +++ b/website/src/repl/panel/SelectInput.jsx @@ -1,14 +1,15 @@ import React from 'react'; - -export function SelectInput({ value, options, onChange }) { +// value: ID, options: Set<{id: ID, label: string}>, onChange: ID => null, onClick: event => void +export function SelectInput({ value, options, onChange, onClick }) { return (