diff --git a/website/src/repl/Repl.jsx b/website/src/repl/Repl.jsx
index a5bfffd4..6bfabc58 100644
--- a/website/src/repl/Repl.jsx
+++ b/website/src/repl/Repl.jsx
@@ -24,6 +24,7 @@ import { code2hash, hash2code } from './helpers.mjs';
import { isTauri } from '../tauri.mjs';
import { useWidgets } from '@strudel.cycles/react/src/hooks/useWidgets.mjs';
import { writeText } from '@tauri-apps/api/clipboard';
+import { defaultAudioDeviceName, getAudioDevices, setAudioDevice } from './panel/AudioDeviceSelector';
const { latestCode } = settingsMap.get();
@@ -132,6 +133,7 @@ export function Repl({ embedded = false }) {
panelPosition,
isZen,
activePattern,
+ audioDeviceName,
} = useSettings();
const paintOptions = useMemo(() => ({ fontFamily }), [fontFamily]);
@@ -171,8 +173,9 @@ export function Repl({ embedded = false }) {
paintOptions,
});
- // init code
+ //on first load...
useEffect(() => {
+ // init code
initCode().then((decoded) => {
let msg;
if (decoded) {
@@ -188,6 +191,16 @@ export function Repl({ embedded = false }) {
logger(`Welcome to Strudel! ${msg} Press play or hit ctrl+enter to run it!`, 'highlight');
setPending(false);
});
+ // Initialize user audio device if it has been saved to settings
+ if (audioDeviceName !== defaultAudioDeviceName) {
+ getAudioDevices().then((devices) => {
+ const deviceID = devices.get(audioDeviceName);
+ if (deviceID == null) {
+ return;
+ }
+ setAudioDevice(deviceID);
+ });
+ }
}, []);
// keyboard shortcuts
diff --git a/website/src/repl/panel/AudioDeviceSelector.jsx b/website/src/repl/panel/AudioDeviceSelector.jsx
index 603c4537..d39e58d2 100644
--- a/website/src/repl/panel/AudioDeviceSelector.jsx
+++ b/website/src/repl/panel/AudioDeviceSelector.jsx
@@ -1,56 +1,44 @@
-import React, { useState, useEffect, useCallback } from 'react';
+import React, { useState } from 'react';
import { getAudioContext, initializeAudioOutput } from '@strudel.cycles/webaudio';
import { SelectInput } from './SelectInput';
const initdevices = new Map();
-const defaultDeviceName = 'System Standard';
+export const defaultAudioDeviceName = 'System Standard';
+
+export const getAudioDevices = async () => {
+ await navigator.mediaDevices.getUserMedia({ audio: true });
+ let mediaDevices = await navigator.mediaDevices.enumerateDevices();
+ mediaDevices = mediaDevices.filter((device) => device.kind === 'audiooutput' && device.deviceId !== 'default');
+ const devicesMap = new Map();
+ devicesMap.set(defaultAudioDeviceName, '');
+ mediaDevices.forEach((device) => {
+ devicesMap.set(device.label, device.deviceId);
+ });
+ return devicesMap;
+};
+
+export const setAudioDevice = async (id) => {
+ 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) {
+ await audioCtx.setSinkId(id);
+ }
+ initializeAudioOutput();
+};
+
// Allows the user to select an audio interface for Strudel to play through
export function AudioDeviceSelector({ audioDeviceName, onChange }) {
const [devices, setDevices] = useState(initdevices);
const devicesInitialized = devices.size > 0;
- const setAudioDevice = useCallback(async (id) => {
- 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) {
- await audioCtx.setSinkId(id);
- }
- initializeAudioOutput();
- });
- const initializedevices = useCallback(async () => {
- await navigator.mediaDevices.getUserMedia({ audio: true });
- let mediaDevices = await navigator.mediaDevices.enumerateDevices();
- mediaDevices = mediaDevices.filter((device) => device.kind === 'audiooutput' && device.deviceId !== 'default');
- const devicesMap = new Map();
- devicesMap.set(defaultDeviceName, '');
- mediaDevices.forEach((device) => {
- devicesMap.set(device.label, device.deviceId);
- });
- setDevices(devicesMap);
- return devicesMap;
- }, []);
-
- // on first load, check if there is a cached audio device name in settings and initialize it
- useEffect(() => {
- if (!audioDeviceName.length || devicesInitialized) {
- return;
- }
- initializedevices().then((devices) => {
- const deviceID = devices.get(audioDeviceName);
- if (deviceID == null) {
- onChange(defaultDeviceName);
- return;
- }
- setAudioDevice(deviceID);
- });
- }, []);
-
const onClick = () => {
if (devicesInitialized) {
return;
}
- initializedevices();
+ getAudioDevices().then((devices) => {
+ setDevices(devices);
+ });
};
const onDeviceChange = (deviceName) => {
if (!devicesInitialized) {
@@ -64,13 +52,5 @@ export function AudioDeviceSelector({ audioDeviceName, onChange }) {
Array.from(devices.keys()).forEach((deviceName) => {
options.set(deviceName, deviceName);
});
- return (
-
- );
+ return ;
}
diff --git a/website/src/repl/panel/SelectInput.jsx b/website/src/repl/panel/SelectInput.jsx
index 3c3fb84e..1bbb6d84 100644
--- a/website/src/repl/panel/SelectInput.jsx
+++ b/website/src/repl/panel/SelectInput.jsx
@@ -8,6 +8,7 @@ export function SelectInput({ value, options, onChange, onClick }) {
value={value ?? ''}
onChange={(e) => onChange(e.target.value)}
>
+ {options.size == 0 && }
{Array.from(options.keys()).map((id) => (