// Copyright (c) 2022 Robin Davies // // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal in // the Software without restriction, including without limitation the rights to // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of // the Software, and to permit persons to whom the Software is furnished to do so, // subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import React from 'react'; import { useState } from 'react'; import Button from '@mui/material/Button'; import List from '@mui/material/List'; import ListItemButton from '@mui/material/ListItemButton'; import DialogTitle from '@mui/material/DialogTitle'; import DialogContent from '@mui/material/DialogContent'; import DialogActions from '@mui/material/DialogActions'; import FormControlLabel from '@mui/material/FormControlLabel'; import Typography from '@mui/material/Typography'; import Checkbox from '@mui/material/Checkbox'; import { AlsaSequencerConfiguration, AlsaSequencerPortSelection } from './AlsaSequencer'; import DialogEx from './DialogEx'; import { PiPedalModel, PiPedalModelFactory } from './PiPedalModel'; export interface SelectMidiChannelsDialogProps { open: boolean; onClose: () => void; } interface DialogItem { id: string; name: string; sortOrder: number offline: boolean; }; function SelectMidiChannelsDialog(props: SelectMidiChannelsDialogProps) { //const classes = useStyles(); const { open, onClose } = props; const [availablePorts, setAvailablePorts] = useState(null); const [configuration, setConfiguration] = useState(null); const [allPorts, setAllPorts] = useState(null); const [model] = useState(PiPedalModelFactory.getInstance()); const [changed, setChanged] = useState(false); const [ readyToDisplay, setReadyToDisplay ] = useState(false); React.useEffect(() => { if (open) { setReadyToDisplay(false); model.getAlsaSequencerPorts().then((ports) => { setAvailablePorts(ports); }).catch((error) => { model.showAlert(error); setReadyToDisplay(true); setAvailablePorts(null); }); model.getAlsaSequencerConfiguration().then((config) => { setConfiguration(config); }).catch((error) => { model.showAlert(error); setReadyToDisplay(true); setConfiguration(null); }); return () => { } } else { return () => { }; } }, [open]); React.useEffect(() => { if (availablePorts !== null && configuration !== null) { let result: DialogItem[] = []; setReadyToDisplay(true); for (let port of availablePorts) { result.push({ id: port.id, name: port.name, sortOrder: port.sortOrder, offline: false }); } // include ports that have been previously selected but are not in the current list of available ports for (let port of configuration.connections) { if (!availablePorts.some((p) => p.id === port.id)) { result.push( { id: port.id, name: port.name, sortOrder: port.sortOrder, offline: true } ); } } result.sort((a, b) => { return a.sortOrder - b.sortOrder; }); setAllPorts(result); } else { setAllPorts(null); } }, [availablePorts, configuration]); const isChecked = (value: DialogItem) => { if (availablePorts === null || configuration === null) { return false; } return configuration.connections.some((port) => port.id === value.id); }; const setChecked = (value_: DialogItem, checked: boolean) => { if (availablePorts === null || configuration === null) { return; } let value = new AlsaSequencerPortSelection(); value.id = value_.id; value.name = value_.name; value.sortOrder = value_.sortOrder; let newConnections = configuration.connections.slice(); if (checked) { newConnections.push(value); } else { newConnections = newConnections.filter((port) => port.id !== value.id); } let newConfiguration = new AlsaSequencerConfiguration(); newConfiguration.connections = newConnections; setConfiguration(newConfiguration); }; let toggleSelect = (value: DialogItem) => { if (availablePorts === null || configuration === null) { return; } if (!isChecked(value)) { setChecked(value, true); } else { setChecked(value, false); } setChanged(true); }; const handleClose = (): void => { onClose(); }; const handleOk = (): void => { if (changed && configuration !== null) { model.setAlsaSequencerConfiguration(configuration); } onClose(); }; return ( Select MIDI Inputs {allPorts !== null && allPorts.length === 0 && ( No MIDI devices found. )} {allPorts != null && allPorts.map((port) => ( toggleSelect(port)} /> } label={ (
{port.name} {port.offline && ( (offline) )}
)} />
) )}
); } export default SelectMidiChannelsDialog;