import React from 'react'; import { Popover, Box, Typography, FormControl, Select, MenuItem, Button, IconButton, Tooltip, Divider, ToggleButton, ToggleButtonGroup, Alert, } from '@mui/material'; import { Trash2 as DeleteIcon, X as CloseIcon } from 'lucide-react'; import { useMidi, formatMidi } from './MidiContext'; import { perfTokens } from '../theme'; const CHANNEL_OPTIONS = [ { value: 0, label: 'Any' }, ...Array.from({ length: 16 }, (_, i) => ({ value: i + 1, label: `Ch ${i + 1}` })), ]; export default function MidiConfigMenu({ anchorEl, open, onClose }) { const ctx = useMidi(); if (!ctx) return null; const { config, inputs, supported, permissionError, setDevice, setChannelFilter, setTakeover, clearMapping, clearAll, } = ctx; const sortedMappings = [...config.mappings].sort((a, b) => a.label.localeCompare(b.label)); return ( MIDI Settings {!supported && ( {permissionError || 'Web MIDI is not available in this browser. Try Chrome / Edge / Electron.'} )} Input device {config.deviceName && !inputs.some(i => i.name === config.deviceName) && ( Saved device "{config.deviceName}" not connected )} Channel filter Takeover { if (v) setTakeover(v); }} fullWidth sx={{ height: 40 }} > Jump Pickup Mappings ({config.mappings.length}) {sortedMappings.length === 0 ? ( No mappings yet. Enable MIDI mode (the MIDI button), click a control, then move a hardware knob, fader, or button. ) : ( sortedMappings.map((m) => ( {m.label} {formatMidi(m.midi)} clearMapping(m.controlId)} sx={{ color: 'text.disabled', '&:hover': { color: 'error.main' } }} > )) )} Pickup = ignore the hardware until its position matches the on-screen value (no jumps). Right-click a control while in MIDI mode to clear its mapping. ); }