Interim checking, Convolution Reverb
This commit is contained in:
@@ -60,9 +60,9 @@ add_custom_command(
|
||||
src/PiPedalError.tsx
|
||||
src/IControlViewFactory.tsx
|
||||
src/Lv2Plugin.tsx
|
||||
src/PedalBoard.tsx
|
||||
src/Pedalboard.tsx
|
||||
src/AndroidHost.tsx
|
||||
src/PedalBoardView.tsx
|
||||
src/PedalboardView.tsx
|
||||
src/PresetDialog.tsx
|
||||
src/AppThemed.tsx
|
||||
src/ZoomedDial.tsx
|
||||
|
||||
@@ -162,15 +162,18 @@ const AboutDialog = withStyles(styles, { withTheme: true })(
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
super.componentDidMount?.();
|
||||
this.mounted = true;
|
||||
this.updateNotifications();
|
||||
this.startFossRequest();
|
||||
}
|
||||
componentWillUnmount() {
|
||||
super.componentWillUnmount?.();
|
||||
this.mounted = false;
|
||||
this.updateNotifications();
|
||||
}
|
||||
componentDidUpdate() {
|
||||
componentDidUpdate(prevProps: Readonly<AboutDialogProps>, prevState: Readonly<AboutDialogState>, snapshot: any): void {
|
||||
super.componentDidUpdate?.(prevProps,prevState,snapshot);
|
||||
this.updateNotifications();
|
||||
}
|
||||
|
||||
@@ -196,7 +199,7 @@ const AboutDialog = withStyles(styles, { withTheme: true })(
|
||||
>
|
||||
<ArrowBackIcon />
|
||||
</IconButton>
|
||||
<Typography variant="h6" className={classes.dialogTitle}>
|
||||
<Typography noWrap variant="h6" className={classes.dialogTitle}>
|
||||
About
|
||||
</Typography>
|
||||
</Toolbar>
|
||||
@@ -208,28 +211,28 @@ const AboutDialog = withStyles(styles, { withTheme: true })(
|
||||
}}
|
||||
>
|
||||
<div style={{ margin: 24 }}>
|
||||
<Typography display="block" variant="h6" color="textPrimary">
|
||||
<Typography noWrap display="block" variant="h6" color="textPrimary">
|
||||
PiPedal <span style={{ fontSize: "0.7em" }}>
|
||||
{(this.model.serverVersion ? this.model.serverVersion.serverVersion : "")
|
||||
+ (this.model.serverVersion?.debug ? " (Debug)" : "")}
|
||||
</span>
|
||||
</Typography>
|
||||
<Typography display="block" variant="body2" style={{ marginBottom: 12 }} >
|
||||
<Typography noWrap display="block" variant="body2" style={{ marginBottom: 12 }} >
|
||||
Copyright © 2022 Robin Davies.
|
||||
</Typography>
|
||||
{this.model.isAndroidHosted() && (
|
||||
<Typography display="block" variant="body2" style={{ marginBottom: 0 }} >
|
||||
<Typography noWrap display="block" variant="body2" style={{ marginBottom: 0 }} >
|
||||
{this.model.getAndroidHostVersion()}
|
||||
</Typography>
|
||||
)}
|
||||
|
||||
{this.model.isAndroidHosted() && (
|
||||
<Typography display="block" variant="body2" style={{ marginBottom: 12 }} >
|
||||
<Typography noWrap display="block" variant="body2" style={{ marginBottom: 12 }} >
|
||||
Copyright © 2022 Robin Davies.
|
||||
</Typography>
|
||||
)}
|
||||
<Divider />
|
||||
<Typography display="block" variant="caption" >
|
||||
<Typography noWrap display="block" variant="caption" >
|
||||
ADDRESSES
|
||||
</Typography>
|
||||
<div style={{marginBottom: 16}}>
|
||||
|
||||
+7
-12
@@ -398,7 +398,7 @@ const AppThemed = withStyles(appStyles)(class extends ResizeResponsiveComponent<
|
||||
|
||||
}
|
||||
|
||||
handDisplayOnboarding() {
|
||||
handleDisplayOnboarding() {
|
||||
this.setState({
|
||||
isDrawerOpen: false,
|
||||
isSettingsDialogOpen: true,
|
||||
@@ -502,7 +502,7 @@ const AppThemed = withStyles(appStyles)(class extends ResizeResponsiveComponent<
|
||||
|
||||
this.model_.errorMessage.addOnChangedHandler(this.errorChangeHandler_);
|
||||
this.model_.state.addOnChangedHandler(this.stateChangeHandler_);
|
||||
this.model_.pedalBoard.addOnChangedHandler(this.presetChangedHandler);
|
||||
this.model_.pedalboard.addOnChangedHandler(this.presetChangedHandler);
|
||||
this.model_.alertMessage.addOnChangedHandler(this.alertMessageChangedHandler);
|
||||
this.model_.banks.addOnChangedHandler(this.banksChangedHandler);
|
||||
this.model_.showStatusMonitor.addOnChangedHandler(this.showStatusMonitorHandler);
|
||||
@@ -529,7 +529,7 @@ const AppThemed = withStyles(appStyles)(class extends ResizeResponsiveComponent<
|
||||
super.componentWillUnmount();
|
||||
this.model_.errorMessage.removeOnChangedHandler(this.errorChangeHandler_);
|
||||
this.model_.state.removeOnChangedHandler(this.stateChangeHandler_);
|
||||
this.model_.pedalBoard.removeOnChangedHandler(this.presetChangedHandler);
|
||||
this.model_.pedalboard.removeOnChangedHandler(this.presetChangedHandler);
|
||||
this.model_.banks.removeOnChangedHandler(this.banksChangedHandler);
|
||||
this.model_.banks.removeOnChangedHandler(this.showStatusMonitorHandler);
|
||||
|
||||
@@ -575,7 +575,6 @@ const AppThemed = withStyles(appStyles)(class extends ResizeResponsiveComponent<
|
||||
this.setState({ errorMessage: message });
|
||||
}
|
||||
|
||||
onboardingShown: boolean = false;
|
||||
|
||||
setDisplayState(newState: State): void {
|
||||
this.updateOverscroll();
|
||||
@@ -586,13 +585,9 @@ const AppThemed = withStyles(appStyles)(class extends ResizeResponsiveComponent<
|
||||
});
|
||||
if (newState === State.Ready)
|
||||
{
|
||||
if (!this.onboardingShown)
|
||||
if (this.model_.isOnboarding())
|
||||
{
|
||||
this.onboardingShown = true;
|
||||
if (!this.model_.hasConfiguration())
|
||||
{
|
||||
this.handDisplayOnboarding();
|
||||
}
|
||||
this.handleDisplayOnboarding();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -867,7 +862,7 @@ const AppThemed = withStyles(appStyles)(class extends ResizeResponsiveComponent<
|
||||
<div className={classes.loadingBoxItem}>
|
||||
<CircularProgress color="inherit" className={classes.loadingBoxItem} />
|
||||
</div>
|
||||
<Typography variant="body2" className={classes.progressText}>
|
||||
<Typography noWrap variant="body2" className={classes.progressText}>
|
||||
{this.state.displayState === State.ApplyingChanges ? "Applying\u00A0changes..." : "Reconnecting..."}
|
||||
</Typography>
|
||||
</div>
|
||||
@@ -905,7 +900,7 @@ const AppThemed = withStyles(appStyles)(class extends ResizeResponsiveComponent<
|
||||
<div className={classes.loadingBoxItem}>
|
||||
<CircularProgress color="inherit" className={classes.loadingBoxItem} />
|
||||
</div>
|
||||
<Typography variant="body2" className={classes.loadingBoxItem}>
|
||||
<Typography noWrap variant="body2" className={classes.loadingBoxItem}>
|
||||
Loading...
|
||||
</Typography>
|
||||
</div>
|
||||
|
||||
@@ -298,7 +298,7 @@ const BankDialog = withStyles(styles, { withTheme: true })(
|
||||
<img src="img/ic_bank.svg" className={classes.itemIcon} alt="" />
|
||||
</div>
|
||||
<div className={classes.itemLabel}>
|
||||
<Typography>
|
||||
<Typography noWrap>
|
||||
{bankEntry.name}
|
||||
</Typography>
|
||||
</div>
|
||||
@@ -410,7 +410,7 @@ const BankDialog = withStyles(styles, { withTheme: true })(
|
||||
>
|
||||
<ArrowBackIcon />
|
||||
</IconButton>
|
||||
<Typography variant="h6" className={classes.dialogTitle}>
|
||||
<Typography noWrap variant="h6" className={classes.dialogTitle}>
|
||||
Banks
|
||||
</Typography>
|
||||
<IconButton color="inherit" onClick={(e) => this.showActionBar(true)} >
|
||||
@@ -433,7 +433,7 @@ const BankDialog = withStyles(styles, { withTheme: true })(
|
||||
</IconButton>
|
||||
|
||||
)}
|
||||
<Typography variant="h6" className={classes.dialogTitle}>
|
||||
<Typography noWrap variant="h6" className={classes.dialogTitle}>
|
||||
Banks
|
||||
</Typography>
|
||||
{(this.state.banks.getEntry(this.state.selectedItem) != null)
|
||||
|
||||
@@ -21,7 +21,7 @@ import React from 'react';
|
||||
import { PiPedalModel, PiPedalModelFactory } from './PiPedalModel';
|
||||
|
||||
|
||||
import {PedalBoardItem, PedalBoardSplitItem} from './PedalBoard';
|
||||
import {PedalboardItem, PedalboardSplitItem} from './Pedalboard';
|
||||
import PluginControlView from './PluginControlView';
|
||||
import SplitControlView from './SplitControlView';
|
||||
import Typography from '@mui/material/Typography';
|
||||
@@ -47,38 +47,38 @@ let pluginFactories: IControlViewFactory[] = [
|
||||
];
|
||||
|
||||
|
||||
export function GetControlView(pedalBoardItem?: PedalBoardItem| null): React.ReactNode
|
||||
export function GetControlView(pedalboardItem?: PedalboardItem| null): React.ReactNode
|
||||
{
|
||||
let model: PiPedalModel = PiPedalModelFactory.getInstance();
|
||||
|
||||
if (!pedalBoardItem) {
|
||||
if (!pedalboardItem) {
|
||||
return (<div/>);
|
||||
}
|
||||
if (pedalBoardItem.isSplit())
|
||||
if (pedalboardItem.isSplit())
|
||||
{
|
||||
return (
|
||||
<SplitControlView item={pedalBoardItem as PedalBoardSplitItem} instanceId={pedalBoardItem!.instanceId}
|
||||
<SplitControlView item={pedalboardItem as PedalboardSplitItem} instanceId={pedalboardItem!.instanceId}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
for (let i = 0; i < pluginFactories.length; ++i)
|
||||
{
|
||||
let factory = pluginFactories[i];
|
||||
if (factory.uri === pedalBoardItem.uri)
|
||||
if (factory.uri === pedalboardItem.uri)
|
||||
{
|
||||
return factory.Create(model,pedalBoardItem);
|
||||
return factory.Create(model,pedalboardItem);
|
||||
}
|
||||
}
|
||||
let uiPlugin = model.getUiPlugin(pedalBoardItem.uri);
|
||||
let uiPlugin = model.getUiPlugin(pedalboardItem.uri);
|
||||
if (!uiPlugin)
|
||||
{
|
||||
<div style={{paddingLeft: 40, paddingRight: 40}}>
|
||||
<Typography color="error" variant="h6" >Missing plugin.</Typography>
|
||||
<Typography>The plugin '{pedalBoardItem.pluginName}' ({pedalBoardItem.uri}) is not currently installed.</Typography>
|
||||
<Typography>The plugin '{pedalboardItem.pluginName}' ({pedalboardItem.uri}) is not currently installed.</Typography>
|
||||
</div>
|
||||
} else {
|
||||
return (
|
||||
<PluginControlView instanceId={pedalBoardItem.instanceId} item={pedalBoardItem} />
|
||||
<PluginControlView instanceId={pedalboardItem.instanceId} item={pedalboardItem} />
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+23
-41
@@ -47,12 +47,9 @@ function peekDialogStack(): string {
|
||||
return "";
|
||||
}
|
||||
|
||||
let ignoreNextPop = false;
|
||||
|
||||
function popDialogStack(ignoreNextPop_: boolean): void {
|
||||
function popDialogStack(): void {
|
||||
if (dialogStack.length !== 0)
|
||||
{
|
||||
ignoreNextPop = ignoreNextPop_;
|
||||
dialogStack.splice(dialogStack.length-1,1);
|
||||
}
|
||||
}
|
||||
@@ -76,27 +73,23 @@ class DialogEx extends React.Component<DialogExProps,DialogExState> {
|
||||
mounted: boolean = false;
|
||||
|
||||
hasHooks: boolean = false;
|
||||
|
||||
stateWasPopped: boolean = false;
|
||||
handlePopState(e: any): any {
|
||||
|
||||
handlePopState(e: any): any
|
||||
{
|
||||
let shouldClose = (peekDialogStack() === this.props.tag);
|
||||
if (shouldClose)
|
||||
{
|
||||
if (ignoreNextPop)
|
||||
{
|
||||
ignoreNextPop = false;
|
||||
} else {
|
||||
if (!this.stateWasPopped)
|
||||
{
|
||||
this.stateWasPopped = true;
|
||||
|
||||
if (this.props.onClose)
|
||||
{
|
||||
popDialogStack(false);
|
||||
this.props.onClose(e,"backdropClick");
|
||||
}
|
||||
if (!this.stateWasPopped)
|
||||
{
|
||||
this.stateWasPopped = true;
|
||||
popDialogStack();
|
||||
if (this.props.open) {
|
||||
this.props.onClose?.(e,"backdropClick");
|
||||
}
|
||||
}
|
||||
window.removeEventListener("popstate",this.handlePopState);
|
||||
e.stopPropagation();
|
||||
}
|
||||
}
|
||||
@@ -111,49 +104,35 @@ class DialogEx extends React.Component<DialogExProps,DialogExState> {
|
||||
{
|
||||
this.stateWasPopped = false;
|
||||
window.addEventListener("popstate",this.handlePopState);
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
let state = history.state;
|
||||
if (!state)
|
||||
{
|
||||
state = {};
|
||||
}
|
||||
state[this.props.tag] = true;
|
||||
|
||||
|
||||
pushDialogStack(this.props.tag);
|
||||
let state: {tag: string} = {tag: this.props.tag};
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
history.pushState(
|
||||
state,
|
||||
"",
|
||||
"" //"#" + this.props.tag
|
||||
"#" + this.props.tag
|
||||
);
|
||||
} else {
|
||||
if (!this.stateWasPopped)
|
||||
{
|
||||
this.stateWasPopped = true;
|
||||
popDialogStack(true);
|
||||
// eslint-disable-next-line no-restricted-globals
|
||||
history.back();
|
||||
}
|
||||
window.removeEventListener("popstate",this.handlePopState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
componentDidMount()
|
||||
{
|
||||
if (super.componentDidMount)
|
||||
{
|
||||
super.componentDidMount();
|
||||
}
|
||||
super.componentDidMount?.();
|
||||
|
||||
this.mounted = true;
|
||||
this.updateHooks();
|
||||
}
|
||||
componentWillUnmount()
|
||||
{
|
||||
if (super.componentWillUnmount)
|
||||
{
|
||||
super.componentWillUnmount();
|
||||
}
|
||||
super.componentWillUnmount?.();
|
||||
this.mounted = false;
|
||||
this.updateHooks();
|
||||
}
|
||||
@@ -162,12 +141,15 @@ class DialogEx extends React.Component<DialogExProps,DialogExState> {
|
||||
{
|
||||
this.updateHooks();
|
||||
}
|
||||
|
||||
myOnClose(event:{}, reason: "backdropClick" | "escapeKeyDown")
|
||||
{
|
||||
if (this.props.onClose) this.props.onClose(event,reason);
|
||||
}
|
||||
|
||||
render() {
|
||||
let { tag, ...extra} = this.props;
|
||||
let { tag,onClose, ...extra} = this.props;
|
||||
return (
|
||||
<Dialog {...extra}>
|
||||
<Dialog {...extra} onClose={(event,reason)=>{ this.myOnClose(event,reason);}}>
|
||||
{this.props.children}
|
||||
</Dialog>
|
||||
);
|
||||
|
||||
@@ -22,33 +22,20 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
import React, { TouchEvent, PointerEvent, ReactNode, Component, SyntheticEvent } from 'react';
|
||||
import React, { Component, SyntheticEvent } from 'react';
|
||||
import { Theme } from '@mui/material/styles';
|
||||
import { WithStyles } from '@mui/styles';
|
||||
import createStyles from '@mui/styles/createStyles';
|
||||
import withStyles from '@mui/styles/withStyles';
|
||||
import { PiPedalFileProperty, PiPedalFileType } from './Lv2Plugin';
|
||||
import { PiPedalFileProperty } from './Lv2Plugin';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import Input from '@mui/material/Input';
|
||||
import Select from '@mui/material/Select';
|
||||
import Switch from '@mui/material/Switch';
|
||||
import Utility, { nullCast } from './Utility';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
import { PiPedalModel, PiPedalModelFactory } from './PiPedalModel';
|
||||
import { PiPedalModel, PiPedalModelFactory, ListenHandle, StateChangedHandle } from './PiPedalModel';
|
||||
import ButtonBase from '@mui/material/ButtonBase'
|
||||
import MoreHorizIcon from '@mui/icons-material/MoreHoriz';
|
||||
|
||||
const MIN_ANGLE = -135;
|
||||
const MAX_ANGLE = 135;
|
||||
const FONT_SIZE = "0.8em";
|
||||
|
||||
|
||||
|
||||
const SELECTED_OPACITY = 0.8;
|
||||
const DEFAULT_OPACITY = 0.6;
|
||||
const RANGE_SCALE = 120; // 120 pixels to move from 0 to 1.
|
||||
const FINE_RANGE_SCALE = RANGE_SCALE * 10; // 1200 pixels to move from 0 to 1.
|
||||
const ULTRA_FINE_RANGE_SCALE = RANGE_SCALE * 50; // 12000 pixels to move from 0 to 1.
|
||||
|
||||
|
||||
export const StandardItemSize = { width: 80, height: 140 }
|
||||
@@ -88,13 +75,12 @@ const styles = (theme: Theme) => createStyles({
|
||||
export interface FilePropertyControlProps extends WithStyles<typeof styles> {
|
||||
instanceId: number;
|
||||
fileProperty: PiPedalFileProperty;
|
||||
value: string;
|
||||
onFileClick: (fileProperty: PiPedalFileProperty,value: string) => void;
|
||||
onFileClick: (fileProperty: PiPedalFileProperty, value: string) => void;
|
||||
theme: Theme;
|
||||
}
|
||||
type FilePropertyControlState = {
|
||||
error: boolean;
|
||||
showDialog: boolean;
|
||||
value: string;
|
||||
};
|
||||
|
||||
const FilePropertyControl =
|
||||
@@ -110,13 +96,75 @@ const FilePropertyControl =
|
||||
|
||||
this.state = {
|
||||
error: false,
|
||||
showDialog: false
|
||||
value: "",
|
||||
};
|
||||
this.model = PiPedalModelFactory.getInstance();
|
||||
if (this.props.fileProperty.patchProperty !== "") {
|
||||
this.subscribeToPropertyGet();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
private propertyGetHandle?: ListenHandle;
|
||||
|
||||
refreshPatchProperty()
|
||||
{
|
||||
this.model.getPatchProperty(this.props.instanceId, this.props.fileProperty.patchProperty)
|
||||
.then(
|
||||
(json: any) => {
|
||||
if (json && json.otype_ === "Path") {
|
||||
let path = json.value as string;
|
||||
this.setState({ value: path });
|
||||
}
|
||||
}
|
||||
)
|
||||
.catch(
|
||||
(error: Error) => {
|
||||
this.model.showAlert(error.toString());
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
stateChangedHandle?: StateChangedHandle;
|
||||
|
||||
subscribeToPropertyGet() {
|
||||
// this.propertyGetHandle = this.model.listenForAtomOutput(this.props.instanceId,(instanceId,atomOutput)=>{
|
||||
// // PARSE THE OBJECT!
|
||||
// // this.setState({value: atomOutput?.value as string});
|
||||
// });
|
||||
if (this.stateChangedHandle)
|
||||
{
|
||||
this.model.removeLv2StateChangedListener(this.stateChangedHandle);
|
||||
}
|
||||
this.refreshPatchProperty();
|
||||
this.stateChangedHandle = this.model.addLv2StateChangedListener(
|
||||
this.props.instanceId,
|
||||
() => {
|
||||
this.refreshPatchProperty();
|
||||
});
|
||||
}
|
||||
unsubscribeToPropertyGet() {
|
||||
if (this.stateChangedHandle)
|
||||
{
|
||||
this.model.removeLv2StateChangedListener(this.stateChangedHandle);
|
||||
}
|
||||
}
|
||||
componentDidMount() {
|
||||
this.subscribeToPropertyGet();
|
||||
}
|
||||
componentWillUnmount() {
|
||||
this.unsubscribeToPropertyGet();
|
||||
}
|
||||
componentDidUpdate(prevProps: Readonly<FilePropertyControlProps>, prevState: Readonly<FilePropertyControlState>, snapshot?: any): void {
|
||||
if (prevProps.fileProperty.patchProperty !== this.props.fileProperty.patchProperty
|
||||
|| prevProps.instanceId !== this.props.instanceId) {
|
||||
this.setState({ value: "" });
|
||||
this.unsubscribeToPropertyGet();
|
||||
this.subscribeToPropertyGet();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inputChanged: boolean = false;
|
||||
|
||||
onDrag(e: SyntheticEvent) {
|
||||
@@ -124,40 +172,36 @@ const FilePropertyControl =
|
||||
}
|
||||
|
||||
onFileClick() {
|
||||
this.props.onFileClick(this.props.fileProperty,this.props.value);
|
||||
this.props.onFileClick(this.props.fileProperty, this.state.value);
|
||||
}
|
||||
private fileNameOnly(path: string): string {
|
||||
let slashPos = path.lastIndexOf('/');
|
||||
if (slashPos < 0)
|
||||
{
|
||||
if (slashPos < 0) {
|
||||
slashPos = 0;
|
||||
} else {
|
||||
++slashPos;
|
||||
}
|
||||
let extPos = path.lastIndexOf('.');
|
||||
if (extPos < 0 || extPos < slashPos)
|
||||
{
|
||||
if (extPos < 0 || extPos < slashPos) {
|
||||
extPos = path.length;
|
||||
}
|
||||
}
|
||||
|
||||
return path.substring(slashPos,extPos);
|
||||
return path.substring(slashPos, extPos);
|
||||
|
||||
}
|
||||
}
|
||||
render() {
|
||||
let classes = this.props.classes;
|
||||
//let classes = this.props.classes;
|
||||
let fileProperty = this.props.fileProperty;
|
||||
|
||||
let value = this.props.value;
|
||||
if (!value || value.length === 0)
|
||||
{
|
||||
let value = this.fileNameOnly(this.state.value);
|
||||
if (!value || value.length === 0) {
|
||||
value = "\u00A0";
|
||||
}
|
||||
value = this.fileNameOnly(value);
|
||||
|
||||
let item_width = 264;
|
||||
|
||||
return (
|
||||
<div style={{ display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "flex-start", width: item_width, margin: 8, paddingLeft: 8}}>
|
||||
<div style={{ display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "flex-start", width: item_width, margin: 8, paddingLeft: 8 }}>
|
||||
{/* TITLE SECTION */}
|
||||
<div style={{ flex: "0 0 auto", width: "100%", marginBottom: 8, marginLeft: 0, marginRight: 0 }}>
|
||||
<Typography variant="caption" display="block" noWrap style={{
|
||||
@@ -169,13 +213,13 @@ const FilePropertyControl =
|
||||
|
||||
<div style={{ flex: "0 0 auto", width: "100%" }}>
|
||||
|
||||
<ButtonBase style={{ width: "100%", borderRadius: "4px 4px 0px 0px", overflow: "hidden",marginTop: 8}} onClick={()=> {this.onFileClick()}} >
|
||||
<div style={{width: "100%", background: "rgba(0,0,0,0.07)", borderRadius: "4px 4px 0px 0px"}}>
|
||||
<ButtonBase style={{ width: "100%", borderRadius: "4px 4px 0px 0px", overflow: "hidden", marginTop: 8 }} onClick={() => { this.onFileClick() }} >
|
||||
<div style={{ width: "100%", background: "rgba(0,0,0,0.07)", borderRadius: "4px 4px 0px 0px" }}>
|
||||
<div style={{ display: "flex", alignItems: "center", flexFlow: "row nowrap" }}>
|
||||
<Typography noWrap={true} style={{ flex: "1 1 100%", textAlign: "start", verticalAlign: "center", paddingTop: 4,paddingBottom: 4,paddingLeft: 4}}
|
||||
<Typography noWrap={true} style={{ flex: "1 1 100%", textAlign: "start", verticalAlign: "center", paddingTop: 4, paddingBottom: 4, paddingLeft: 4 }}
|
||||
variant='caption'
|
||||
>{value}</Typography>
|
||||
<MoreHorizIcon style={{ flex: "0 0 auto", width: "16px", height: "16px", verticalAlign: "center",opacity: 0.5, marginRight: 4 }} />
|
||||
>{value}</Typography>
|
||||
<MoreHorizIcon style={{ flex: "0 0 auto", width: "16px", height: "16px", verticalAlign: "center", opacity: 0.5, marginRight: 4 }} />
|
||||
</div>
|
||||
<div style={{ height: "1px", width: "100%", background: "black" }}> </div>
|
||||
</div>
|
||||
|
||||
@@ -23,35 +23,27 @@ import { PiPedalModel, PiPedalModelFactory } from './PiPedalModel';
|
||||
|
||||
|
||||
import Button from '@mui/material/Button';
|
||||
import Radio from '@mui/material/Radio';
|
||||
import List from '@mui/material/List';
|
||||
import ListItem from '@mui/material/ListItem';
|
||||
import ListItemButton from '@mui/material/ListItemButton';
|
||||
import ListItemIcon from '@mui/material/ListItemIcon';
|
||||
import ListItemText from '@mui/material/ListItemText';
|
||||
import FileUploadIcon from '@mui/icons-material/FileUpload';
|
||||
import AudioFileIcon from '@mui/icons-material/AudioFile';
|
||||
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
||||
|
||||
import Dialog from '@mui/material/Dialog';
|
||||
import DialogActions from '@mui/material/DialogActions';
|
||||
import DialogTitle from '@mui/material/DialogTitle';
|
||||
import DialogContent from '@mui/material/DialogContent';
|
||||
import DeleteIcon from '@mui/icons-material/Delete';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
|
||||
import ResizeResponsiveComponent from './ResizeResponsiveComponent';
|
||||
import { PiPedalFileProperty, PiPedalFileType } from './Lv2Plugin';
|
||||
import { PiPedalFileProperty } from './Lv2Plugin';
|
||||
import ButtonBase from '@mui/material/ButtonBase';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import DialogEx from './DialogEx';
|
||||
import { ModelTraining } from '@mui/icons-material';
|
||||
|
||||
export interface FilePropertyDialogProps {
|
||||
open: boolean,
|
||||
fileProperty: PiPedalFileProperty,
|
||||
selectedFile: string,
|
||||
onOk: (fileProperty: PiPedalFileProperty, selectedItem: string) => void,
|
||||
onClose: () => void
|
||||
onCancel: () => void
|
||||
};
|
||||
|
||||
export interface FilePropertyDialogState {
|
||||
@@ -82,7 +74,23 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
|
||||
private mounted: boolean = false;
|
||||
private model: PiPedalModel;
|
||||
|
||||
private lastFileProperty: PiPedalFileProperty = new PiPedalFileProperty();
|
||||
|
||||
private requestFiles() {
|
||||
if (!this.props.open)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (this.props.fileProperty.directory === "")
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (this.lastFileProperty === this.props.fileProperty)
|
||||
{
|
||||
return;
|
||||
}
|
||||
this.lastFileProperty = this.props.fileProperty;
|
||||
|
||||
this.model.requestFileList(this.props.fileProperty)
|
||||
.then((files) => {
|
||||
if (this.mounted)
|
||||
@@ -108,6 +116,11 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
|
||||
this.mounted = false;
|
||||
}
|
||||
componentDidUpdate(prevProps: Readonly<FilePropertyDialogProps>, prevState: Readonly<FilePropertyDialogState>, snapshot?: any): void {
|
||||
super.componentDidUpdate?.(prevProps,prevState,snapshot);
|
||||
if (prevProps.fileProperty !== this.props.fileProperty)
|
||||
{
|
||||
this.requestFiles()
|
||||
}
|
||||
}
|
||||
|
||||
private fileNameOnly(path: string): string {
|
||||
@@ -142,29 +155,39 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
|
||||
this.setState({ selectedFile: selectedFile, hasSelection: this.isFileInList(this.state.files,selectedFile) })
|
||||
}
|
||||
|
||||
mapKey: number = 0;
|
||||
render() {
|
||||
|
||||
return (
|
||||
<DialogEx onClose={() => this.props.onClose()} open={this.props.open} tag="FilePropertyDialog" fullWidth maxWidth="xl" style={{ height: "90%" }}
|
||||
this.mapKey = 0;
|
||||
return this.props.open &&
|
||||
(
|
||||
<DialogEx onClose={() => this.props.onCancel()} open={this.props.open} tag="FilePropertyDialog" fullWidth maxWidth="xl" style={{ height: "90%" }}
|
||||
PaperProps={{ style: { minHeight: "90%", maxHeight: "90%", overflowY: "visible" } }}
|
||||
>
|
||||
<DialogTitle >{this.props.fileProperty.name}</DialogTitle>
|
||||
<DialogTitle >
|
||||
<div>
|
||||
<IconButton edge="start" color="inherit" onClick={()=> {this.props.onCancel();}} aria-label="back"
|
||||
>
|
||||
<ArrowBackIcon fontSize="small" style={{opacity: "0.6"}} />
|
||||
</IconButton>
|
||||
<Typography display="inline" >{this.props.fileProperty.name}</Typography>
|
||||
</div>
|
||||
</DialogTitle>
|
||||
<div style={{ flex: "0 0 auto", height: "1px", background: "rgba(0,0,0,0.2" }}> </div>
|
||||
<div style={{ flex: "1 1 auto", height: "300", display: "flex", flexFlow: "row nowrap", overflowX: "auto", overflowY: "visible" }}>
|
||||
<div style={{ flex: "1 1 100%", display: "flex", flexFlow: "column wrap", justifyContent: "start", alignItems: "flex-start" }}>
|
||||
<div style={{ flex: "1 1 100%", display: "flex", flexFlow: "column wrap", justifyContent: "start", alignItems: "flex-start",paddingLeft: 16,paddingTop:16 }}>
|
||||
{
|
||||
this.state.files.map(
|
||||
(value: string, index: number) => {
|
||||
let selected = value === this.state.selectedFile;
|
||||
let selectBg = selected ? "rgba(0,0,0,0.15)" : "rgba(0,0,0,0.0)";
|
||||
return (
|
||||
<ButtonBase
|
||||
style={{ width: "320px", flex: "0 0 48px", position: "relative" }}
|
||||
<ButtonBase key={ this.mapKey++ }
|
||||
style={{ width: "320px", flex: "0 0 48px", position: "relative"}}
|
||||
onClick={() => this.onSelect(value)}
|
||||
>
|
||||
<div style={{ position: "absolute", background: selectBg, width: "100%", height: "100%" }} />
|
||||
<div style={{ position: "absolute", background: selectBg, width: "100%", height: "100%", borderRadius: 4 }} />
|
||||
<div style={{ display: "flex", flexFlow: "row nowrap", justifyContent: "start", alignItems: "center", width: "100%", height: "100%" }}>
|
||||
<AudioFileIcon style={{ flex: "0 0 auto", opacity: 0.7, marginRight: 8, marginLeft: 4 }} />
|
||||
<AudioFileIcon style={{ flex: "0 0 auto", opacity: 0.7, marginRight: 8, marginLeft: 8 }} />
|
||||
<Typography noWrap style={{ flex: "1 1 auto", textAlign: "left" }}>{this.fileNameOnly(value)}</Typography>
|
||||
</div>
|
||||
</ButtonBase>
|
||||
@@ -181,14 +204,14 @@ export default class FilePropertyDialog extends ResizeResponsiveComponent<FilePr
|
||||
<input hidden accept="audio/x-wav" name="Upload Impuse File" type="file" multiple />
|
||||
Upload
|
||||
</Button>
|
||||
<IconButton style={{visibility: (this.state.hasSelection? "visible": "hidden")}} aria-label="delete selected file" component="label">
|
||||
<DeleteIcon />
|
||||
<IconButton style={{visibility: (this.state.hasSelection? "visible": "hidden")}} aria-label="delete selected file" component="label" color="primary" >
|
||||
<DeleteIcon fontSize='small' />
|
||||
</IconButton>
|
||||
<div style={{ flex: "1 1 auto" }}> </div>
|
||||
<Button onClick={() => this.props.onClose()} aria-label="cancel">
|
||||
<Button onClick={() => {this.props.onCancel();}} aria-label="cancel">
|
||||
Cancel
|
||||
</Button>
|
||||
<Button style={{ flex: "0 0 auto" }} onClick={() => this.props.onClose()} color="secondary" disabled={!this.state.hasSelection} aria-label="select">
|
||||
<Button style={{ flex: "0 0 auto" }} onClick={() => {this.props.onOk(this.props.fileProperty,this.state.selectedFile);}} color="secondary" disabled={!this.state.hasSelection} aria-label="select">
|
||||
Select
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -203,7 +203,7 @@ const FullScreenIME =
|
||||
justifyContent: "center", alignItems: "center"
|
||||
}}
|
||||
>
|
||||
<Typography variant="body2">{this.props.caption}</Typography>
|
||||
<Typography noWrap variant="body2">{this.props.caption}</Typography>
|
||||
<Input key={value}
|
||||
type="number"
|
||||
defaultValue={control.formatShortValue(value)}
|
||||
|
||||
@@ -26,7 +26,7 @@ import withStyles from '@mui/styles/withStyles';
|
||||
|
||||
import IControlViewFactory from './IControlViewFactory';
|
||||
import { PiPedalModelFactory, PiPedalModel } from "./PiPedalModel";
|
||||
import { PedalBoardItem } from './PedalBoard';
|
||||
import { PedalboardItem } from './Pedalboard';
|
||||
import PluginControlView, { ControlGroup,ControlViewCustomization } from './PluginControlView';
|
||||
import GxTunerControl from './GxTunerControl';
|
||||
|
||||
@@ -40,7 +40,7 @@ const styles = (theme: Theme) => createStyles({
|
||||
|
||||
interface GxTunerProps extends WithStyles<typeof styles> {
|
||||
instanceId: number;
|
||||
item: PedalBoardItem;
|
||||
item: PedalboardItem;
|
||||
isToobTuner: boolean;
|
||||
|
||||
}
|
||||
@@ -115,8 +115,8 @@ const GxTunerView =
|
||||
export class GxTunerViewFactory implements IControlViewFactory {
|
||||
uri: string = GXTUNER_URI;
|
||||
|
||||
Create(model: PiPedalModel, pedalBoardItem: PedalBoardItem): React.ReactNode {
|
||||
return (<GxTunerView isToobTuner={false} instanceId={pedalBoardItem.instanceId} item={pedalBoardItem} />);
|
||||
Create(model: PiPedalModel, pedalboardItem: PedalboardItem): React.ReactNode {
|
||||
return (<GxTunerView isToobTuner={false} instanceId={pedalboardItem.instanceId} item={pedalboardItem} />);
|
||||
}
|
||||
|
||||
|
||||
@@ -126,8 +126,8 @@ export class GxTunerViewFactory implements IControlViewFactory {
|
||||
export class ToobTunerViewFactory implements IControlViewFactory {
|
||||
uri: string = TOOBTUNER_URI;
|
||||
|
||||
Create(model: PiPedalModel, pedalBoardItem: PedalBoardItem): React.ReactNode {
|
||||
return (<GxTunerView isToobTuner={true} instanceId={pedalBoardItem.instanceId} item={pedalBoardItem} />);
|
||||
Create(model: PiPedalModel, pedalboardItem: PedalboardItem): React.ReactNode {
|
||||
return (<GxTunerView isToobTuner={true} instanceId={pedalboardItem.instanceId} item={pedalboardItem} />);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -19,13 +19,13 @@
|
||||
|
||||
import React from 'react';
|
||||
import { PiPedalModel } from "./PiPedalModel";
|
||||
import { PedalBoardItem } from './PedalBoard';
|
||||
import { PedalboardItem } from './Pedalboard';
|
||||
|
||||
|
||||
|
||||
interface IControlViewFactory {
|
||||
uri: string;
|
||||
Create(model: PiPedalModel,pedalBoardItem: PedalBoardItem): React.ReactNode;
|
||||
Create(model: PiPedalModel,pedalboardItem: PedalboardItem): React.ReactNode;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
export default class JackServerSettings {
|
||||
deserialize(input: any) : JackServerSettings{
|
||||
this.valid = input.valid;
|
||||
this.isOnboarding = input.isOnboarding;
|
||||
this.isJackAudio = input.isJackAudio;
|
||||
this.rebootRequired = input.rebootRequired;
|
||||
this.alsaDevice = input.alsaDevice?? "";
|
||||
@@ -44,6 +45,7 @@ export default class JackServerSettings {
|
||||
return new JackServerSettings().deserialize(this);
|
||||
}
|
||||
valid: boolean = false;
|
||||
isOnboarding: boolean = true;
|
||||
rebootRequired = false;
|
||||
isJackAudio = false;
|
||||
alsaDevice: string = "";
|
||||
@@ -54,7 +56,7 @@ export default class JackServerSettings {
|
||||
getSummaryText() {
|
||||
if (this.valid) {
|
||||
let device = this.alsaDevice;
|
||||
if (device.startsWith("hw:")) device = device.substr(3);
|
||||
if (device.startsWith("hw:")) device = device.substring(3);
|
||||
return device + " - Rate: " + this.sampleRate + " BufferSize: " + this.bufferSize + " Buffers: " + this.numberOfBuffers;
|
||||
} else {
|
||||
return "Not configured";
|
||||
|
||||
@@ -134,8 +134,8 @@ const JackServerSettingsDialog = withStyles(styles)(
|
||||
|
||||
}
|
||||
if (result.sampleRate === 0) result.sampleRate = 48000;
|
||||
if (result.bufferSize === 0) result.bufferSize = 64;
|
||||
if (result.numberOfBuffers === 0) result.numberOfBuffers = 2;
|
||||
if (result.bufferSize === 0) result.bufferSize = 16;
|
||||
if (result.numberOfBuffers === 0) result.numberOfBuffers = 3;
|
||||
result.sampleRate = selectedDevice.closestSampleRate(result.sampleRate);
|
||||
result.bufferSize = selectedDevice.closestBufferSize(result.bufferSize);
|
||||
result.valid = true;
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
// Copyright (c) 2023 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.
|
||||
|
||||
|
||||
// Utility class for constructing Json atoms.
|
||||
class JsonAtom {
|
||||
static Property(value: string): any
|
||||
{
|
||||
return {
|
||||
"otype_": "Property",
|
||||
"value": value
|
||||
};
|
||||
}
|
||||
static Bool(value: boolean): any
|
||||
{
|
||||
return {
|
||||
"otype_": "Bool",
|
||||
"value": value
|
||||
};
|
||||
}
|
||||
static Int(value: number): any
|
||||
{
|
||||
return {
|
||||
"otype_": "Int",
|
||||
"value": value
|
||||
};
|
||||
}
|
||||
static Long(value: number): any
|
||||
{
|
||||
return {
|
||||
"otype_": "Long",
|
||||
"value": value
|
||||
};
|
||||
}
|
||||
static Float(value: number): any
|
||||
{
|
||||
return value;
|
||||
}
|
||||
static Double(value: number): any
|
||||
{
|
||||
return {
|
||||
"otype_": "Double",
|
||||
"value": value
|
||||
};
|
||||
}
|
||||
static String(value: string): any
|
||||
{
|
||||
return value;
|
||||
}
|
||||
static Path(value: string): any
|
||||
{
|
||||
return {
|
||||
"otype_": "Path",
|
||||
"value": value
|
||||
};
|
||||
}
|
||||
static Uri(value: string): any
|
||||
{
|
||||
return {
|
||||
"otype_": "URI",
|
||||
"value": value
|
||||
};
|
||||
}
|
||||
static Urid(value: string): any
|
||||
{
|
||||
return {
|
||||
"otype_": "URID",
|
||||
"value": value
|
||||
};
|
||||
}
|
||||
static Object(type: string): any
|
||||
{
|
||||
return {
|
||||
"otype_": type
|
||||
};
|
||||
}
|
||||
static Tuple(values: any[]): any
|
||||
{
|
||||
return {
|
||||
"otype_": "Tuple",
|
||||
"value": values
|
||||
};
|
||||
}
|
||||
static IntVector(values: []): any
|
||||
{
|
||||
return {
|
||||
"otype_": "Vector",
|
||||
"vtype_": "Int",
|
||||
"value": values
|
||||
};
|
||||
}
|
||||
static LongVector(values: []): any
|
||||
{
|
||||
return {
|
||||
"otype_": "Vector",
|
||||
"vtype_": "Long",
|
||||
"value": values
|
||||
};
|
||||
}
|
||||
|
||||
static FloatVector(values: []): any
|
||||
{
|
||||
return {
|
||||
"otype_": "Vector",
|
||||
"vtype_": "Float",
|
||||
"value": values
|
||||
};
|
||||
}
|
||||
static DoubleVector(values: []): any
|
||||
{
|
||||
return {
|
||||
"otype_": "Vector",
|
||||
"vtype_": "Float",
|
||||
"value": values
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
export default JsonAtom;
|
||||
+32
-2
@@ -123,13 +123,37 @@ export class PiPedalFileType {
|
||||
name: string = "";
|
||||
fileExtension: string = "";
|
||||
}
|
||||
|
||||
export class UiPropertyNotification {
|
||||
deserialize(input: any): UiPropertyNotification
|
||||
{
|
||||
this.portIndex = input.portIndex;
|
||||
this.symbol = input.symbol;
|
||||
this.plugin = input.plugin;
|
||||
this.protocol = input.protocol;
|
||||
return this;
|
||||
}
|
||||
static deserialize_array(input: any): UiPropertyNotification[]
|
||||
{
|
||||
let result: UiPropertyNotification[] = [];
|
||||
for (let i = 0; i < input.length; ++i)
|
||||
{
|
||||
result[i] = new UiPropertyNotification().deserialize(input[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
portIndex: number = -1;
|
||||
symbol: string = "";
|
||||
plugin: string = "";
|
||||
protocol: string = "";
|
||||
|
||||
};
|
||||
export class PiPedalFileProperty {
|
||||
deserialize(input: any): PiPedalFileProperty
|
||||
{
|
||||
this.name = input.name;
|
||||
this.fileTypes = PiPedalFileType.deserialize_array(input.fileTypes);
|
||||
this.patchProperty = input.patchProperty;
|
||||
this.defaultFile = input.defaultFile;
|
||||
this.directory = input.directory;
|
||||
return this;
|
||||
}
|
||||
@@ -147,7 +171,6 @@ export class PiPedalFileProperty {
|
||||
fileTypes: PiPedalFileType[] = [];
|
||||
patchProperty: string = "";
|
||||
directory: string = "";
|
||||
defaultFile: string = "";
|
||||
|
||||
};
|
||||
export class Lv2Plugin implements Deserializable<Lv2Plugin> {
|
||||
@@ -170,6 +193,12 @@ export class Lv2Plugin implements Deserializable<Lv2Plugin> {
|
||||
} else {
|
||||
this.fileProperties = [];
|
||||
}
|
||||
if (input.uiPortNotifications)
|
||||
{
|
||||
this.uiPortNotifications = UiPropertyNotification.deserialize_array(input.uiPortNotifications);
|
||||
} else {
|
||||
this.uiPortNotifications = [];
|
||||
}
|
||||
return this;
|
||||
}
|
||||
static EmptyFeatures: string[] = [];
|
||||
@@ -186,6 +215,7 @@ export class Lv2Plugin implements Deserializable<Lv2Plugin> {
|
||||
ports: Port[] = Port.EmptyPorts;
|
||||
port_groups: PortGroup[] = [];
|
||||
fileProperties: PiPedalFileProperty[] = [];
|
||||
uiPortNotifications: UiPropertyNotification[] = [];
|
||||
}
|
||||
|
||||
|
||||
|
||||
+58
-58
@@ -24,15 +24,15 @@ import createStyles from '@mui/styles/createStyles';
|
||||
import withStyles from '@mui/styles/withStyles';
|
||||
import { PiPedalModel, PiPedalModelFactory } from './PiPedalModel';
|
||||
import {
|
||||
PedalBoard, PedalBoardItem, PedalBoardSplitItem, SplitType
|
||||
} from './PedalBoard';
|
||||
Pedalboard, PedalboardItem, PedalboardSplitItem, SplitType
|
||||
} from './Pedalboard';
|
||||
import Button from '@mui/material/Button';
|
||||
import InputIcon from '@mui/icons-material/Input';
|
||||
import LoadPluginDialog from './LoadPluginDialog';
|
||||
import Switch from '@mui/material/Switch';
|
||||
import Typography from '@mui/material/Typography';
|
||||
|
||||
import PedalBoardView from './PedalBoardView';
|
||||
import PedalboardView from './PedalboardView';
|
||||
import { PiPedalStateError } from './PiPedalError';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import AddIcon from '@mui/icons-material/Add';
|
||||
@@ -58,11 +58,11 @@ const styles = ({ palette }: Theme) => createStyles({
|
||||
position: "absolute", display: "flex", flexDirection: "column", flexWrap: "nowrap",
|
||||
justifyContent: "flex-start", left: "0px", top: "0px", bottom: "0px", right: "0px", overflow: "hidden"
|
||||
},
|
||||
pedalBoardScroll: {
|
||||
pedalboardScroll: {
|
||||
position: "relative", width: "100%",
|
||||
flex: "0 0 auto", overflow: "auto", maxHeight: 220
|
||||
},
|
||||
pedalBoardScrollSmall: {
|
||||
pedalboardScrollSmall: {
|
||||
position: "relative", width: "100%",
|
||||
flex: "1 1 1px", overflow: "auto"
|
||||
},
|
||||
@@ -97,7 +97,7 @@ interface MainProps extends WithStyles<typeof styles> {
|
||||
interface MainState {
|
||||
selectedPedal: number;
|
||||
loadDialogOpen: boolean;
|
||||
pedalBoard: PedalBoard;
|
||||
pedalboard: Pedalboard;
|
||||
addMenuAnchorEl: HTMLElement | null;
|
||||
splitControlBar: boolean;
|
||||
horizontalScrollLayout: boolean;
|
||||
@@ -116,13 +116,13 @@ export const MainPage =
|
||||
constructor(props: MainProps) {
|
||||
super(props);
|
||||
this.model = PiPedalModelFactory.getInstance();
|
||||
let pedalboard = this.model.pedalBoard.get();
|
||||
let pedalboard = this.model.pedalboard.get();
|
||||
let selectedPedal = pedalboard.getFirstSelectableItem();
|
||||
|
||||
this.state = {
|
||||
selectedPedal: selectedPedal,
|
||||
loadDialogOpen: false,
|
||||
pedalBoard: pedalboard,
|
||||
pedalboard: pedalboard,
|
||||
addMenuAnchorEl: null,
|
||||
splitControlBar: this.windowSize.width < SPLIT_CONTROLBAR_THRESHHOLD,
|
||||
horizontalScrollLayout: this.windowSize.height < HORIZONTAL_CONTROL_SCROLL_HEIGHT_BREAK,
|
||||
@@ -135,31 +135,31 @@ export const MainPage =
|
||||
this.onLoadClick = this.onLoadClick.bind(this);
|
||||
this.onLoadOk = this.onLoadOk.bind(this);
|
||||
this.onLoadCancel = this.onLoadCancel.bind(this);
|
||||
this.onPedalBoardChanged = this.onPedalBoardChanged.bind(this);
|
||||
this.onPedalboardChanged = this.onPedalboardChanged.bind(this);
|
||||
this.handleEnableCurrentItemChanged = this.handleEnableCurrentItemChanged.bind(this);
|
||||
}
|
||||
|
||||
onInsertPedal(instanceId: number) {
|
||||
this.setAddMenuAnchorEl(null);
|
||||
let newId = this.model.addPedalBoardItem(instanceId, false);
|
||||
let newId = this.model.addPedalboardItem(instanceId, false);
|
||||
this.setSelection(newId);
|
||||
}
|
||||
onAppendPedal(instanceId: number) {
|
||||
this.setAddMenuAnchorEl(null);
|
||||
let newId = this.model.addPedalBoardItem(instanceId, true);
|
||||
let newId = this.model.addPedalboardItem(instanceId, true);
|
||||
|
||||
this.setSelection(newId);
|
||||
|
||||
}
|
||||
onInsertSplit(instanceId: number) {
|
||||
this.setAddMenuAnchorEl(null);
|
||||
let newId = this.model.addPedalBoardSplitItem(instanceId, false);
|
||||
let newId = this.model.addPedalboardSplitItem(instanceId, false);
|
||||
this.setSelection(newId);
|
||||
|
||||
}
|
||||
onAppendSplit(instanceId: number) {
|
||||
this.setAddMenuAnchorEl(null);
|
||||
let newId = this.model.addPedalBoardSplitItem(instanceId, true);
|
||||
let newId = this.model.addPedalboardSplitItem(instanceId, true);
|
||||
this.setSelection(newId);
|
||||
|
||||
}
|
||||
@@ -182,16 +182,16 @@ export const MainPage =
|
||||
}
|
||||
handleEnableCurrentItemChanged(event: any): void {
|
||||
let newValue = event.target.checked;
|
||||
let item = this.getSelectedPedalBoardItem();
|
||||
let item = this.getSelectedPedalboardItem();
|
||||
if (item != null) {
|
||||
this.model.setPedalBoardItemEnabled(item.getInstanceId(), newValue);
|
||||
this.model.setPedalboardItemEnabled(item.getInstanceId(), newValue);
|
||||
|
||||
}
|
||||
}
|
||||
handleSelectPluginPreset(instanceId: number, presetInstanceId: number) {
|
||||
this.model.loadPluginPreset(instanceId, presetInstanceId);
|
||||
}
|
||||
onPedalBoardChanged(value: PedalBoard) {
|
||||
onPedalboardChanged(value: Pedalboard) {
|
||||
let selectedItem = -1;
|
||||
if (value.hasItem(this.state.selectedPedal))
|
||||
{
|
||||
@@ -200,12 +200,12 @@ export const MainPage =
|
||||
selectedItem = value.getFirstSelectableItem();
|
||||
}
|
||||
this.setState({
|
||||
pedalBoard: value,
|
||||
pedalboard: value,
|
||||
selectedPedal: selectedItem
|
||||
});
|
||||
}
|
||||
onDeletePedal(instanceId: number): void {
|
||||
let result = this.model.deletePedalBoardPedal(instanceId);
|
||||
let result = this.model.deletePedalboardPedal(instanceId);
|
||||
if (result != null) {
|
||||
this.setState({ selectedPedal: result });
|
||||
}
|
||||
@@ -213,10 +213,10 @@ export const MainPage =
|
||||
|
||||
componentDidMount() {
|
||||
super.componentDidMount();
|
||||
this.model.pedalBoard.addOnChangedHandler(this.onPedalBoardChanged);
|
||||
this.model.pedalboard.addOnChangedHandler(this.onPedalboardChanged);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
this.model.pedalBoard.removeOnChangedHandler(this.onPedalBoardChanged);
|
||||
this.model.pedalboard.removeOnChangedHandler(this.onPedalboardChanged);
|
||||
super.componentWillUnmount();
|
||||
}
|
||||
updateResponsive() {
|
||||
@@ -241,14 +241,14 @@ export const MainPage =
|
||||
}
|
||||
onPedalDoubleClick(selectedId: number): void {
|
||||
this.setSelection(selectedId);
|
||||
let item = this.getPedalBoardItem(selectedId);
|
||||
let item = this.getPedalboardItem(selectedId);
|
||||
if (item != null) {
|
||||
if (item.isSplit()) {
|
||||
let split = item as PedalBoardSplitItem;
|
||||
let split = item as PedalboardSplitItem;
|
||||
if (split.getSplitType() === SplitType.Ab) {
|
||||
let cv = split.getToggleAbControlValue();
|
||||
if (split.instanceId === undefined) throw new PiPedalStateError("Split without valid id.");
|
||||
this.model.setPedalBoardControlValue(split.instanceId, cv.key, cv.value);
|
||||
this.model.setPedalboardControl(split.instanceId, cv.key, cv.value);
|
||||
}
|
||||
} else {
|
||||
this.setState({ loadDialogOpen: true });
|
||||
@@ -261,7 +261,7 @@ export const MainPage =
|
||||
onLoadOk(selectedUri: string): void {
|
||||
this.setState({ loadDialogOpen: false });
|
||||
let itemId = this.state.selectedPedal;
|
||||
let newSelectedItem = this.model.loadPedalBoardPlugin(itemId, selectedUri);
|
||||
let newSelectedItem = this.model.loadPedalboardPlugin(itemId, selectedUri);
|
||||
this.setState({ selectedPedal: newSelectedItem });
|
||||
}
|
||||
|
||||
@@ -269,12 +269,12 @@ export const MainPage =
|
||||
this.setState({ loadDialogOpen: true });
|
||||
}
|
||||
|
||||
getPedalBoardItem(selectedId?: number): PedalBoardItem | null {
|
||||
getPedalboardItem(selectedId?: number): PedalboardItem | null {
|
||||
if (selectedId === undefined) return null;
|
||||
|
||||
let pedalBoard = this.model.pedalBoard.get();
|
||||
if (!pedalBoard) return null;
|
||||
let it = pedalBoard.itemsGenerator();
|
||||
let pedalboard = this.model.pedalboard.get();
|
||||
if (!pedalboard) return null;
|
||||
let it = pedalboard.itemsGenerator();
|
||||
if (!selectedId) return null;
|
||||
while (true) {
|
||||
let v = it.next();
|
||||
@@ -290,32 +290,32 @@ export const MainPage =
|
||||
}
|
||||
|
||||
onPedalboardPropertyChanged(instanceId: number, key: string, value: number) {
|
||||
this.model.setPedalBoardControlValue(instanceId, key, value);
|
||||
this.model.setPedalboardControl(instanceId, key, value);
|
||||
}
|
||||
getSelectedPedalBoardItem(): PedalBoardItem | null {
|
||||
return this.getPedalBoardItem(this.state.selectedPedal);
|
||||
getSelectedPedalboardItem(): PedalboardItem | null {
|
||||
return this.getPedalboardItem(this.state.selectedPedal);
|
||||
}
|
||||
getSelectedUri(): string {
|
||||
let pedalBoardItem = this.getSelectedPedalBoardItem();
|
||||
if (pedalBoardItem == null) return "";
|
||||
return pedalBoardItem.uri;
|
||||
let pedalboardItem = this.getSelectedPedalboardItem();
|
||||
if (pedalboardItem == null) return "";
|
||||
return pedalboardItem.uri;
|
||||
}
|
||||
titleBar(pedalBoardItem: PedalBoardItem | null): React.ReactNode {
|
||||
titleBar(pedalboardItem: PedalboardItem | null): React.ReactNode {
|
||||
let title = "";
|
||||
let author = "";
|
||||
let pluginUri = "";
|
||||
let presetsUri = "";
|
||||
let missing = false;
|
||||
if (pedalBoardItem) {
|
||||
if (pedalBoardItem.isEmpty()) {
|
||||
if (pedalboardItem) {
|
||||
if (pedalboardItem.isEmpty()) {
|
||||
title = "";
|
||||
} else if (pedalBoardItem.isSplit()) {
|
||||
} else if (pedalboardItem.isSplit()) {
|
||||
title = "Split";
|
||||
} else {
|
||||
let uiPlugin = this.model.getUiPlugin(pedalBoardItem.uri);
|
||||
let uiPlugin = this.model.getUiPlugin(pedalboardItem.uri);
|
||||
if (!uiPlugin) {
|
||||
missing = true;
|
||||
title = pedalBoardItem?.pluginName ?? "Missing plugin";
|
||||
title = pedalboardItem?.pluginName ?? "Missing plugin";
|
||||
} else {
|
||||
title = uiPlugin.name;
|
||||
author = uiPlugin.author_name;
|
||||
@@ -362,7 +362,7 @@ export const MainPage =
|
||||
<PluginInfoDialog plugin_uri={pluginUri} />
|
||||
</div>
|
||||
<div style={{ flex: "0 0 auto" }}>
|
||||
<PluginPresetSelector pluginUri={presetsUri} instanceId={pedalBoardItem?.instanceId ?? 0}
|
||||
<PluginPresetSelector pluginUri={presetsUri} instanceId={pedalboardItem?.instanceId ?? 0}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -373,8 +373,8 @@ export const MainPage =
|
||||
|
||||
render() {
|
||||
let classes = this.props.classes;
|
||||
let pedalBoard = this.model.pedalBoard.get();
|
||||
let pedalBoardItem = this.getSelectedPedalBoardItem();
|
||||
let pedalboard = this.model.pedalboard.get();
|
||||
let pedalboardItem = this.getSelectedPedalboardItem();
|
||||
let uiPlugin = null;
|
||||
let bypassVisible = false;
|
||||
let bypassChecked = false;
|
||||
@@ -384,20 +384,20 @@ export const MainPage =
|
||||
let missing = false;
|
||||
let pluginUri = "#error";
|
||||
|
||||
if (pedalBoardItem) {
|
||||
canDelete = pedalBoard.canDeleteItem(pedalBoardItem.instanceId);
|
||||
instanceId = pedalBoardItem.instanceId;
|
||||
if (pedalBoardItem.isEmpty()) {
|
||||
if (pedalboardItem) {
|
||||
canDelete = pedalboard.canDeleteItem(pedalboardItem.instanceId);
|
||||
instanceId = pedalboardItem.instanceId;
|
||||
if (pedalboardItem.isEmpty()) {
|
||||
canAdd = true;
|
||||
} else if (pedalBoardItem.isSplit()) {
|
||||
} else if (pedalboardItem.isSplit()) {
|
||||
canAdd = true;
|
||||
} else {
|
||||
pluginUri = pedalBoardItem.uri;
|
||||
pluginUri = pedalboardItem.uri;
|
||||
uiPlugin = this.model.getUiPlugin(pluginUri);
|
||||
canAdd = true;
|
||||
if (uiPlugin) {
|
||||
bypassVisible = true;
|
||||
bypassChecked = pedalBoardItem.isEnabled;
|
||||
bypassChecked = pedalboardItem.isEnabled;
|
||||
} else {
|
||||
missing = true;
|
||||
}
|
||||
@@ -407,9 +407,9 @@ export const MainPage =
|
||||
|
||||
return (
|
||||
<div className={classes.frame}>
|
||||
<div id="pedalBoardScroll" className={horizontalScrollLayout ? classes.pedalBoardScrollSmall : classes.pedalBoardScroll}
|
||||
<div id="pedalboardScroll" className={horizontalScrollLayout ? classes.pedalboardScrollSmall : classes.pedalboardScroll}
|
||||
style={{ maxHeight: horizontalScrollLayout ? undefined : this.state.screenHeight / 2 }}>
|
||||
<PedalBoardView key={pluginUri} selectedId={this.state.selectedPedal}
|
||||
<PedalboardView key={pluginUri} selectedId={this.state.selectedPedal}
|
||||
onSelectionChanged={this.onSelectionChanged}
|
||||
onDoubleClick={this.onPedalDoubleClick}
|
||||
hasTinyToolBar={this.props.hasTinyToolBar}
|
||||
@@ -427,7 +427,7 @@ export const MainPage =
|
||||
</div>
|
||||
</div>
|
||||
{
|
||||
(!this.state.splitControlBar) && this.titleBar(pedalBoardItem)
|
||||
(!this.state.splitControlBar) && this.titleBar(pedalboardItem)
|
||||
}
|
||||
<div style={{ flex: "1 1 1px" }}>
|
||||
|
||||
@@ -453,7 +453,7 @@ export const MainPage =
|
||||
</div>
|
||||
<div style={{ flex: "0 0 auto", display: canDelete ? "block" : "none", paddingRight: 8 }}>
|
||||
<IconButton
|
||||
onClick={() => { this.onDeletePedal(pedalBoardItem?.instanceId ?? -1) }}
|
||||
onClick={() => { this.onDeletePedal(pedalboardItem?.instanceId ?? -1) }}
|
||||
size="large">
|
||||
<img src="/img/old_delete_outline_black_24dp.svg" alt="Delete" style={{ width: 24, height: 24, opacity: 0.6 }} />
|
||||
</IconButton>
|
||||
@@ -464,7 +464,7 @@ export const MainPage =
|
||||
color="primary"
|
||||
size="small"
|
||||
onClick={this.onLoadClick}
|
||||
disabled={this.state.selectedPedal === -1 || (this.getSelectedPedalBoardItem()?.isSplit() ?? true)}
|
||||
disabled={this.state.selectedPedal === -1 || (this.getSelectedPedalboardItem()?.isSplit() ?? true)}
|
||||
startIcon={<InputIcon />}
|
||||
style={{ borderRadius: 24, paddingLeft: 18, paddingRight: 18, textTransform: "none"}}
|
||||
>
|
||||
@@ -485,7 +485,7 @@ export const MainPage =
|
||||
this.state.splitControlBar && (
|
||||
<div className={classes.splitControlBar}>
|
||||
{
|
||||
this.titleBar(pedalBoardItem)
|
||||
this.titleBar(pedalboardItem)
|
||||
}
|
||||
</div>
|
||||
)
|
||||
@@ -495,12 +495,12 @@ export const MainPage =
|
||||
missing ? (
|
||||
<div style={{marginLeft: 100,marginTop: 20}}>
|
||||
<Typography variant="body1" paragraph={true}>Error: Plugin is not installed.</Typography>
|
||||
<Typography variant="body2" paragraph={true}>{pluginUri}</Typography>
|
||||
<Typography noWrap variant="body2" paragraph={true}>{pluginUri}</Typography>
|
||||
</div>
|
||||
|
||||
):
|
||||
(
|
||||
GetControlView(pedalBoardItem)
|
||||
GetControlView(pedalboardItem)
|
||||
)
|
||||
}
|
||||
</div>
|
||||
|
||||
@@ -139,8 +139,8 @@ const MidiBindingView =
|
||||
render() {
|
||||
let classes = this.props.classes;
|
||||
let midiBinding = this.props.midiBinding;
|
||||
let pedalBoardItem = this.model.pedalBoard.get().getItem(this.props.instanceId);
|
||||
let uiPlugin = this.model.getUiPlugin(pedalBoardItem.uri);
|
||||
let pedalboardItem = this.model.pedalboard.get().getItem(this.props.instanceId);
|
||||
let uiPlugin = this.model.getUiPlugin(pedalboardItem.uri);
|
||||
if (!uiPlugin) {
|
||||
return (<div />);
|
||||
}
|
||||
@@ -267,7 +267,7 @@ const MidiBindingView =
|
||||
(canTrigger) &&
|
||||
(
|
||||
<div className={classes.controlDiv2} >
|
||||
<Typography style={{paddingTop: 12, paddingBottom: 12}}>(Trigger)</Typography>
|
||||
<Typography noWrap style={{paddingTop: 12, paddingBottom: 12}}>(Trigger)</Typography>
|
||||
</div>
|
||||
)
|
||||
|
||||
|
||||
@@ -123,8 +123,8 @@ export const MidiBindingDialog =
|
||||
{
|
||||
this.cancelListenForControl();
|
||||
|
||||
let pedalBoard = this.model.pedalBoard.get();
|
||||
let item = pedalBoard.getItem(instanceId);
|
||||
let pedalboard = this.model.pedalboard.get();
|
||||
let item = pedalboard.getItem(instanceId);
|
||||
if (!item) return;
|
||||
|
||||
let binding = item.getMidiBinding(symbol);
|
||||
@@ -181,7 +181,7 @@ export const MidiBindingDialog =
|
||||
let classes = this.props.classes;
|
||||
let result: React.ReactNode[] = [];
|
||||
|
||||
let pedalboard = this.model.pedalBoard.get();
|
||||
let pedalboard = this.model.pedalboard.get();
|
||||
let iter = pedalboard.itemsGenerator();
|
||||
while (true) {
|
||||
let v = iter.next();
|
||||
@@ -285,7 +285,7 @@ export const MidiBindingDialog =
|
||||
size="large">
|
||||
<ArrowBackIcon />
|
||||
</IconButton>
|
||||
<Typography variant="h6" className={classes.dialogTitle}>
|
||||
<Typography noWrap variant="h6" className={classes.dialogTitle}>
|
||||
Preset MIDI Bindings
|
||||
</Typography>
|
||||
</Toolbar>
|
||||
|
||||
@@ -57,30 +57,9 @@ export class ControlValue implements Deserializable<ControlValue> {
|
||||
value: number;
|
||||
|
||||
}
|
||||
export class PropertyValue implements Deserializable<PropertyValue> {
|
||||
deserialize(input: any): PropertyValue {
|
||||
this.propertyUri = input.propertyUri;
|
||||
this.value = input.value;
|
||||
return this;
|
||||
}
|
||||
static deserializeArray(input: any[]): PropertyValue[] {
|
||||
let result: PropertyValue[] = [];
|
||||
for (let i = 0; i < input.length; ++i) {
|
||||
result[i] = new PropertyValue().deserialize(input[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
setValue(value: number) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
propertyUri: string = "";
|
||||
value: any = null;
|
||||
|
||||
}
|
||||
|
||||
export class PedalBoardItem implements Deserializable<PedalBoardItem> {
|
||||
deserializePedalBoardItem(input: any): PedalBoardItem {
|
||||
export class PedalboardItem implements Deserializable<PedalboardItem> {
|
||||
deserializePedalboardItem(input: any): PedalboardItem {
|
||||
this.instanceId = input.instanceId ?? -1;
|
||||
this.uri = input.uri;
|
||||
this.pluginName = input.pluginName;
|
||||
@@ -88,24 +67,24 @@ export class PedalBoardItem implements Deserializable<PedalBoardItem> {
|
||||
this.midiBindings = MidiBinding.deserialize_array(input.midiBindings);
|
||||
|
||||
this.controlValues = ControlValue.deserializeArray(input.controlValues);
|
||||
this.propertyValues = PropertyValue.deserializeArray(input.propertyValues);
|
||||
this.vstState = input.vstState ?? "";
|
||||
this.lv2State = input.lv2State;
|
||||
return this;
|
||||
}
|
||||
deserialize(input: any): PedalBoardItem {
|
||||
return this.deserializePedalBoardItem(input);
|
||||
deserialize(input: any): PedalboardItem {
|
||||
return this.deserializePedalboardItem(input);
|
||||
}
|
||||
static deserializeArray(input: any): PedalBoardItem[] {
|
||||
let result: PedalBoardItem[] = [];
|
||||
static deserializeArray(input: any): PedalboardItem[] {
|
||||
let result: PedalboardItem[] = [];
|
||||
for (let i = 0; i < input.length; ++i) {
|
||||
let inputItem: any = input[i];
|
||||
let uri: string = inputItem.uri as string;
|
||||
let outputItem: PedalBoardItem;
|
||||
let outputItem: PedalboardItem;
|
||||
|
||||
if (uri === SPLIT_PEDALBOARD_ITEM_URI) {
|
||||
outputItem = new PedalBoardSplitItem().deserialize(inputItem);
|
||||
outputItem = new PedalboardSplitItem().deserialize(inputItem);
|
||||
} else {
|
||||
outputItem = new PedalBoardItem().deserialize(inputItem);
|
||||
outputItem = new PedalboardItem().deserialize(inputItem);
|
||||
}
|
||||
result[i] = outputItem;
|
||||
|
||||
@@ -158,17 +137,6 @@ export class PedalBoardItem implements Deserializable<PedalBoardItem> {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
setPropertyValue(propertyUri: string, value: any): boolean {
|
||||
for (let i = 0; i < this.propertyValues.length; ++i) {
|
||||
let v = this.propertyValues[i];
|
||||
if (v.propertyUri === propertyUri) {
|
||||
if (v.value === value) return false;
|
||||
v.value = value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
setMidiBinding(midiBinding: MidiBinding): boolean {
|
||||
if (this.midiBindings)
|
||||
{
|
||||
@@ -209,16 +177,16 @@ export class PedalBoardItem implements Deserializable<PedalBoardItem> {
|
||||
}
|
||||
|
||||
|
||||
static EmptyArray: PedalBoardItem[] = [];
|
||||
static EmptyArray: PedalboardItem[] = [];
|
||||
|
||||
instanceId: number = -1;
|
||||
isEnabled: boolean = false;
|
||||
uri: string = "";
|
||||
pluginName?: string;
|
||||
controlValues: ControlValue[] = ControlValue.EmptyArray;
|
||||
propertyValues: PropertyValue[] = [];
|
||||
midiBindings: MidiBinding[] = [];
|
||||
vstState: string = "";
|
||||
lv2State: any = {};
|
||||
};
|
||||
|
||||
|
||||
@@ -230,7 +198,7 @@ export enum SplitType {
|
||||
|
||||
|
||||
|
||||
export class PedalBoardSplitItem extends PedalBoardItem {
|
||||
export class PedalboardSplitItem extends PedalboardItem {
|
||||
static PANL_KEY: string = "panL";
|
||||
static PANR_KEY: string = "panR";
|
||||
static VOLL_KEY: string = "volL";
|
||||
@@ -241,15 +209,15 @@ export class PedalBoardSplitItem extends PedalBoardItem {
|
||||
static SELECT_KEY: string = "select";
|
||||
|
||||
|
||||
deserialize(input: any): PedalBoardSplitItem {
|
||||
this.deserializePedalBoardItem(input);
|
||||
this.topChain = PedalBoardItem.deserializeArray(input.topChain);
|
||||
this.bottomChain = PedalBoardItem.deserializeArray(input.bottomChain);
|
||||
deserialize(input: any): PedalboardSplitItem {
|
||||
this.deserializePedalboardItem(input);
|
||||
this.topChain = PedalboardItem.deserializeArray(input.topChain);
|
||||
this.bottomChain = PedalboardItem.deserializeArray(input.bottomChain);
|
||||
|
||||
return this;
|
||||
}
|
||||
getSplitType(): SplitType {
|
||||
let rawValue = this.getControlValue(PedalBoardSplitItem.TYPE_KEY);
|
||||
let rawValue = this.getControlValue(PedalboardSplitItem.TYPE_KEY);
|
||||
|
||||
if (rawValue < 1) return SplitType.Ab;
|
||||
if (rawValue < 2) return SplitType.Mix;
|
||||
@@ -263,43 +231,43 @@ export class PedalBoardSplitItem extends PedalBoardItem {
|
||||
|
||||
}
|
||||
getMixControl(): ControlValue {
|
||||
return this.getControl(PedalBoardSplitItem.MIX_KEY);
|
||||
return this.getControl(PedalboardSplitItem.MIX_KEY);
|
||||
}
|
||||
getMix(): number {
|
||||
return this.getControlValue(PedalBoardSplitItem.MIX_KEY);
|
||||
return this.getControlValue(PedalboardSplitItem.MIX_KEY);
|
||||
}
|
||||
isASelected(): boolean {
|
||||
return this.getSplitType() !== SplitType.Ab || this.getControlValue(PedalBoardSplitItem.SELECT_KEY) === 0;
|
||||
return this.getSplitType() !== SplitType.Ab || this.getControlValue(PedalboardSplitItem.SELECT_KEY) === 0;
|
||||
}
|
||||
isBSelected(): boolean {
|
||||
return this.getSplitType() !== SplitType.Ab || this.getControlValue(PedalBoardSplitItem.SELECT_KEY) !== 0;
|
||||
return this.getSplitType() !== SplitType.Ab || this.getControlValue(PedalboardSplitItem.SELECT_KEY) !== 0;
|
||||
}
|
||||
|
||||
topChain: PedalBoardItem[] = PedalBoardItem.EmptyArray;
|
||||
bottomChain: PedalBoardItem[] = PedalBoardItem.EmptyArray;
|
||||
topChain: PedalboardItem[] = PedalboardItem.EmptyArray;
|
||||
bottomChain: PedalboardItem[] = PedalboardItem.EmptyArray;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
export class PedalBoard implements Deserializable<PedalBoard> {
|
||||
export class Pedalboard implements Deserializable<Pedalboard> {
|
||||
|
||||
deserialize(input: any): PedalBoard {
|
||||
deserialize(input: any): Pedalboard {
|
||||
this.name = input.name;
|
||||
this.items = PedalBoardItem.deserializeArray(input.items);
|
||||
this.items = PedalboardItem.deserializeArray(input.items);
|
||||
this.nextInstanceId = input.nextInstanceId ?? -1;
|
||||
return this;
|
||||
}
|
||||
|
||||
clone(): PedalBoard {
|
||||
return new PedalBoard().deserialize(this);
|
||||
clone(): Pedalboard {
|
||||
return new Pedalboard().deserialize(this);
|
||||
}
|
||||
name: string = "";
|
||||
items: PedalBoardItem[] = [];
|
||||
items: PedalboardItem[] = [];
|
||||
nextInstanceId: number = -1;
|
||||
|
||||
*itemsGenerator(): Generator<PedalBoardItem, void, undefined> {
|
||||
*itemsGenerator(): Generator<PedalboardItem, void, undefined> {
|
||||
let it = itemGenerator_(this.items);
|
||||
while (true)
|
||||
{
|
||||
@@ -335,7 +303,7 @@ export class PedalBoard implements Deserializable<PedalBoard> {
|
||||
|
||||
}
|
||||
|
||||
maybeGetItem(instanceId: number): PedalBoardItem | null{
|
||||
maybeGetItem(instanceId: number): PedalboardItem | null{
|
||||
let it = this.itemsGenerator();
|
||||
while (true)
|
||||
{
|
||||
@@ -348,7 +316,7 @@ export class PedalBoard implements Deserializable<PedalBoard> {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
getItem(instanceId: number): PedalBoardItem {
|
||||
getItem(instanceId: number): PedalboardItem {
|
||||
let it = this.itemsGenerator();
|
||||
while (true)
|
||||
{
|
||||
@@ -361,7 +329,7 @@ export class PedalBoard implements Deserializable<PedalBoard> {
|
||||
}
|
||||
throw new PiPedalArgumentError("Item not found.");
|
||||
}
|
||||
deleteItem_(instanceId: number,items: PedalBoardItem[]): number | null
|
||||
deleteItem_(instanceId: number,items: PedalboardItem[]): number | null
|
||||
{
|
||||
for (let i = 0; i < items.length; ++i)
|
||||
{
|
||||
@@ -383,7 +351,7 @@ export class PedalBoard implements Deserializable<PedalBoard> {
|
||||
} else {
|
||||
if (item.isSplit())
|
||||
{
|
||||
let splitItem = item as PedalBoardSplitItem;
|
||||
let splitItem = item as PedalboardSplitItem;
|
||||
let t = this.deleteItem_(instanceId,splitItem.topChain);
|
||||
if (t != null) return t;
|
||||
|
||||
@@ -395,7 +363,7 @@ export class PedalBoard implements Deserializable<PedalBoard> {
|
||||
return null;
|
||||
}
|
||||
|
||||
canDeleteItem_(instanceId: number,items: PedalBoardItem[]): boolean
|
||||
canDeleteItem_(instanceId: number,items: PedalboardItem[]): boolean
|
||||
{
|
||||
for (let i = 0; i < items.length; ++i)
|
||||
{
|
||||
@@ -407,7 +375,7 @@ export class PedalBoard implements Deserializable<PedalBoard> {
|
||||
}
|
||||
if (item.isSplit())
|
||||
{
|
||||
let splitItem = item as PedalBoardSplitItem;
|
||||
let splitItem = item as PedalboardSplitItem;
|
||||
if (this.canDeleteItem_(instanceId,splitItem.topChain))
|
||||
{
|
||||
return true;
|
||||
@@ -436,15 +404,15 @@ export class PedalBoard implements Deserializable<PedalBoard> {
|
||||
if (!item) return false;
|
||||
return item.setMidiBinding(midiBinding);
|
||||
}
|
||||
addToStart(item: PedalBoardItem)
|
||||
addToStart(item: PedalboardItem)
|
||||
{
|
||||
this.items.splice(0,0,item);
|
||||
}
|
||||
addToEnd(item: PedalBoardItem)
|
||||
addToEnd(item: PedalboardItem)
|
||||
{
|
||||
this.items.splice(this.items.length,0,item);
|
||||
}
|
||||
static _addRelative(items: PedalBoardItem[],newItem: PedalBoardItem, instanceId: number, addBefore: boolean): boolean
|
||||
static _addRelative(items: PedalboardItem[],newItem: PedalboardItem, instanceId: number, addBefore: boolean): boolean
|
||||
{
|
||||
for (let i = 0; i < items.length; ++i)
|
||||
{
|
||||
@@ -461,7 +429,7 @@ export class PedalBoard implements Deserializable<PedalBoard> {
|
||||
}
|
||||
if (item.isSplit())
|
||||
{
|
||||
let split = item as PedalBoardSplitItem;
|
||||
let split = item as PedalboardSplitItem;
|
||||
if (this._addRelative(split.topChain,newItem,instanceId,addBefore))
|
||||
{
|
||||
return true;
|
||||
@@ -476,19 +444,19 @@ export class PedalBoard implements Deserializable<PedalBoard> {
|
||||
|
||||
}
|
||||
|
||||
addBefore(item: PedalBoardItem, instanceId: number)
|
||||
addBefore(item: PedalboardItem, instanceId: number)
|
||||
{
|
||||
if (item.instanceId === instanceId) return;
|
||||
let result = PedalBoard._addRelative(this.items,item, instanceId, true);
|
||||
let result = Pedalboard._addRelative(this.items,item, instanceId, true);
|
||||
if (!result) {
|
||||
throw new PiPedalArgumentError("instanceId not found.");
|
||||
}
|
||||
|
||||
}
|
||||
addAfter(item: PedalBoardItem, instanceId: number)
|
||||
addAfter(item: PedalboardItem, instanceId: number)
|
||||
{
|
||||
if (item.instanceId === instanceId) return;
|
||||
let result = PedalBoard._addRelative(this.items,item, instanceId, false);
|
||||
let result = Pedalboard._addRelative(this.items,item, instanceId, false);
|
||||
if (!result) {
|
||||
throw new PiPedalArgumentError("instanceId not found.");
|
||||
}
|
||||
@@ -520,8 +488,8 @@ export class PedalBoard implements Deserializable<PedalBoard> {
|
||||
}
|
||||
}
|
||||
}
|
||||
createEmptySplit(): PedalBoardSplitItem {
|
||||
let result: PedalBoardSplitItem = new PedalBoardSplitItem();
|
||||
createEmptySplit(): PedalboardSplitItem {
|
||||
let result: PedalboardSplitItem = new PedalboardSplitItem();
|
||||
result.uri = SPLIT_PEDALBOARD_ITEM_URI;
|
||||
result.instanceId = ++this.nextInstanceId;
|
||||
result.pluginName = "";
|
||||
@@ -529,13 +497,13 @@ export class PedalBoard implements Deserializable<PedalBoard> {
|
||||
result.topChain = [ this.createEmptyItem()];
|
||||
result.bottomChain = [ this.createEmptyItem()];
|
||||
result.controlValues = [
|
||||
new ControlValue(PedalBoardSplitItem.TYPE_KEY, 0),
|
||||
new ControlValue(PedalBoardSplitItem.SELECT_KEY,0),
|
||||
new ControlValue(PedalBoardSplitItem.MIX_KEY,0),
|
||||
new ControlValue(PedalBoardSplitItem.PANL_KEY,0),
|
||||
new ControlValue(PedalBoardSplitItem.VOLL_KEY,-3),
|
||||
new ControlValue(PedalBoardSplitItem.PANR_KEY,0),
|
||||
new ControlValue(PedalBoardSplitItem.VOLR_KEY,-3)
|
||||
new ControlValue(PedalboardSplitItem.TYPE_KEY, 0),
|
||||
new ControlValue(PedalboardSplitItem.SELECT_KEY,0),
|
||||
new ControlValue(PedalboardSplitItem.MIX_KEY,0),
|
||||
new ControlValue(PedalboardSplitItem.PANL_KEY,0),
|
||||
new ControlValue(PedalboardSplitItem.VOLL_KEY,-3),
|
||||
new ControlValue(PedalboardSplitItem.PANR_KEY,0),
|
||||
new ControlValue(PedalboardSplitItem.VOLR_KEY,-3)
|
||||
];
|
||||
|
||||
|
||||
@@ -543,8 +511,8 @@ export class PedalBoard implements Deserializable<PedalBoard> {
|
||||
|
||||
|
||||
}
|
||||
createEmptyItem(): PedalBoardItem {
|
||||
let result: PedalBoardItem = new PedalBoardItem();
|
||||
createEmptyItem(): PedalboardItem {
|
||||
let result: PedalboardItem = new PedalboardItem();
|
||||
result.uri = EMPTY_PEDALBOARD_ITEM_URI;
|
||||
result.instanceId = ++this.nextInstanceId;
|
||||
result.pluginName = "";
|
||||
@@ -552,7 +520,7 @@ export class PedalBoard implements Deserializable<PedalBoard> {
|
||||
|
||||
return result;
|
||||
}
|
||||
setItemEmpty(item: PedalBoardItem)
|
||||
setItemEmpty(item: PedalboardItem)
|
||||
{
|
||||
item.uri = EMPTY_PEDALBOARD_ITEM_URI;
|
||||
item.instanceId = ++this.nextInstanceId;
|
||||
@@ -562,7 +530,7 @@ export class PedalBoard implements Deserializable<PedalBoard> {
|
||||
|
||||
}
|
||||
|
||||
_replaceItem(items: PedalBoardItem[], instanceId: number, newItem: PedalBoardItem): boolean {
|
||||
_replaceItem(items: PedalboardItem[], instanceId: number, newItem: PedalboardItem): boolean {
|
||||
for (let i = 0; i < items.length; ++i)
|
||||
{
|
||||
let item = items[i];
|
||||
@@ -573,7 +541,7 @@ export class PedalBoard implements Deserializable<PedalBoard> {
|
||||
}
|
||||
if (items[i].isSplit())
|
||||
{
|
||||
let splitItem = item as PedalBoardSplitItem;
|
||||
let splitItem = item as PedalboardSplitItem;
|
||||
if (this._replaceItem(splitItem.topChain,instanceId,newItem))
|
||||
return true;
|
||||
if (this._replaceItem(splitItem.bottomChain,instanceId,newItem))
|
||||
@@ -585,7 +553,7 @@ export class PedalBoard implements Deserializable<PedalBoard> {
|
||||
return false;
|
||||
}
|
||||
|
||||
replaceItem(instanceId: number, newItem: PedalBoardItem)
|
||||
replaceItem(instanceId: number, newItem: PedalboardItem)
|
||||
{
|
||||
let result = this._replaceItem(this.items,instanceId,newItem);
|
||||
if (!result)
|
||||
@@ -593,7 +561,7 @@ export class PedalBoard implements Deserializable<PedalBoard> {
|
||||
throw new PiPedalArgumentError("instanceId not found.");
|
||||
}
|
||||
}
|
||||
_addItem(items: PedalBoardItem[], newItem: PedalBoardItem, instanceId: number, append: boolean)
|
||||
_addItem(items: PedalboardItem[], newItem: PedalboardItem, instanceId: number, append: boolean)
|
||||
{
|
||||
for (let i = 0; i < items.length; ++i)
|
||||
{
|
||||
@@ -611,27 +579,27 @@ export class PedalBoard implements Deserializable<PedalBoard> {
|
||||
}
|
||||
if (item.isSplit())
|
||||
{
|
||||
let splitItem = item as PedalBoardSplitItem;
|
||||
let splitItem = item as PedalboardSplitItem;
|
||||
if (this._addItem(splitItem.topChain,newItem,instanceId,append)) return true;
|
||||
if (this._addItem(splitItem.bottomChain,newItem,instanceId,append)) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addItem(newItem: PedalBoardItem, instanceId: number, append: boolean): void
|
||||
addItem(newItem: PedalboardItem, instanceId: number, append: boolean): void
|
||||
{
|
||||
this._addItem(this.items,newItem,instanceId,append);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function* itemGenerator_(items: PedalBoardItem[]): Generator<PedalBoardItem, void, undefined> {
|
||||
function* itemGenerator_(items: PedalboardItem[]): Generator<PedalboardItem, void, undefined> {
|
||||
for (let i = 0; i < items.length; ++i) {
|
||||
let item = items[i];
|
||||
yield item;
|
||||
if (item.uri === SPLIT_PEDALBOARD_ITEM_URI) {
|
||||
|
||||
let splitItem = item as PedalBoardSplitItem;
|
||||
let splitItem = item as PedalboardSplitItem;
|
||||
|
||||
let it = itemGenerator_(splitItem.topChain);
|
||||
while (true) {
|
||||
@@ -36,8 +36,8 @@ import Utility from './Utility'
|
||||
|
||||
|
||||
import {
|
||||
PedalBoard, PedalBoardItem, PedalBoardSplitItem, SplitType,
|
||||
} from './PedalBoard';
|
||||
Pedalboard, PedalboardItem, PedalboardSplitItem, SplitType,
|
||||
} from './Pedalboard';
|
||||
|
||||
const START_PEDALBOARD_ITEM_URI = "uri://two-play/pipedal/pedalboard#Start";
|
||||
const END_PEDALBOARD_ITEM_URI = "uri://two-play/pipedal/pedalboard#End";
|
||||
@@ -69,7 +69,7 @@ function CalculateConnection(numberOfInputs: number, numberOfOutputs: number)
|
||||
return result;
|
||||
}
|
||||
|
||||
const pedalBoardStyles = (theme: Theme) => createStyles({
|
||||
const pedalboardStyles = (theme: Theme) => createStyles({
|
||||
scrollContainer: {
|
||||
},
|
||||
|
||||
@@ -177,7 +177,7 @@ const pedalBoardStyles = (theme: Theme) => createStyles({
|
||||
|
||||
export type OnSelectHandler = (selectedPedal: number) => void;
|
||||
|
||||
interface PedalBoardProps extends WithStyles<typeof pedalBoardStyles> {
|
||||
interface PedalboardProps extends WithStyles<typeof pedalboardStyles> {
|
||||
theme: Theme;
|
||||
selectedId?: number;
|
||||
onSelectionChanged?: OnSelectHandler;
|
||||
@@ -190,14 +190,14 @@ interface LayoutSize {
|
||||
height: number;
|
||||
}
|
||||
|
||||
type PedalBoardState = {
|
||||
pedalBoard?: PedalBoard;
|
||||
type PedalboardState = {
|
||||
pedalboard?: Pedalboard;
|
||||
};
|
||||
|
||||
const EMPTY_PEDALS: PedalLayout[] = [];
|
||||
|
||||
|
||||
function makeChain(model: PiPedalModel, uiItems?: PedalBoardItem[]): PedalLayout[] {
|
||||
function makeChain(model: PiPedalModel, uiItems?: PedalboardItem[]): PedalLayout[] {
|
||||
let result: PedalLayout[] = [];
|
||||
if (uiItems) {
|
||||
for (let i = 0; i < uiItems.length; ++i) {
|
||||
@@ -219,7 +219,7 @@ class PedalLayout {
|
||||
numberOfInputs: number = 2;
|
||||
numberOfOutputs: number = 2;
|
||||
|
||||
pedalItem?: PedalBoardItem;
|
||||
pedalItem?: PedalboardItem;
|
||||
|
||||
// Split Layout only.
|
||||
topChildren: PedalLayout[] = EMPTY_PEDALS;
|
||||
@@ -245,7 +245,7 @@ class PedalLayout {
|
||||
t.numberOfOutputs = 0;
|
||||
return t;
|
||||
}
|
||||
constructor(model?: PiPedalModel, pedalItem?: PedalBoardItem) {
|
||||
constructor(model?: PiPedalModel, pedalItem?: PedalboardItem) {
|
||||
if (model === undefined && pedalItem === undefined) {
|
||||
return;
|
||||
}
|
||||
@@ -255,7 +255,7 @@ class PedalLayout {
|
||||
this.pedalItem = pedalItem;
|
||||
this.uri = pedalItem.uri;
|
||||
if (pedalItem.isSplit()) {
|
||||
let splitter = pedalItem as PedalBoardSplitItem;
|
||||
let splitter = pedalItem as PedalboardSplitItem;
|
||||
|
||||
this.pluginType = PluginType.UtilityPlugin;
|
||||
this.topChildren = makeChain(model, splitter.topChain);
|
||||
@@ -350,9 +350,9 @@ class LayoutParams {
|
||||
}
|
||||
|
||||
|
||||
const PedalBoardView =
|
||||
withStyles(pedalBoardStyles, { withTheme: true })(
|
||||
class extends Component<PedalBoardProps, PedalBoardState>
|
||||
const PedalboardView =
|
||||
withStyles(pedalboardStyles, { withTheme: true })(
|
||||
class extends Component<PedalboardProps, PedalboardState>
|
||||
{
|
||||
model: PiPedalModel;
|
||||
|
||||
@@ -360,15 +360,15 @@ const PedalBoardView =
|
||||
scrollRef: React.RefObject<HTMLDivElement>;
|
||||
|
||||
|
||||
constructor(props: PedalBoardProps) {
|
||||
constructor(props: PedalboardProps) {
|
||||
super(props);
|
||||
this.model = PiPedalModelFactory.getInstance();
|
||||
|
||||
if (!props.selectedId) props.selectedId = -1;
|
||||
this.state = {
|
||||
pedalBoard: this.model.pedalBoard.get(),
|
||||
pedalboard: this.model.pedalboard.get(),
|
||||
};
|
||||
this.onPedalBoardChanged = this.onPedalBoardChanged.bind(this);
|
||||
this.onPedalboardChanged = this.onPedalboardChanged.bind(this);
|
||||
this.frameRef = React.createRef();
|
||||
this.scrollRef = React.createRef();
|
||||
this.handleTouchStart = this.handleTouchStart.bind(this);
|
||||
@@ -402,11 +402,11 @@ const PedalBoardView =
|
||||
if (item.isSplitter() && item.pedalItem) {
|
||||
if (item.bounds.contains(clientX, clientY)) {
|
||||
if (clientX < item.bounds.x + CELL_WIDTH / 2) {
|
||||
this.model.movePedalBoardItemBefore(instanceId, item.pedalItem.instanceId);
|
||||
this.model.movePedalboardItemBefore(instanceId, item.pedalItem.instanceId);
|
||||
this.setSelection(instanceId);
|
||||
return;
|
||||
} else if (clientX > item.bounds.right - CELL_WIDTH / 2) {
|
||||
this.model.movePedalBoardItemAfter(instanceId, item.pedalItem.instanceId);
|
||||
this.model.movePedalboardItemAfter(instanceId, item.pedalItem.instanceId);
|
||||
this.setSelection(instanceId);
|
||||
return;
|
||||
|
||||
@@ -420,7 +420,7 @@ const PedalBoardView =
|
||||
if (clientX < item.topChildren[0].bounds.x) {
|
||||
let topPedalItem = item.topChildren[0].pedalItem;
|
||||
if (topPedalItem) {
|
||||
this.model.movePedalBoardItemBefore(instanceId, topPedalItem.instanceId);
|
||||
this.model.movePedalboardItemBefore(instanceId, topPedalItem.instanceId);
|
||||
this.setSelection(instanceId);
|
||||
return;
|
||||
}
|
||||
@@ -428,7 +428,7 @@ const PedalBoardView =
|
||||
let lastTop = item.topChildren[item.topChildren.length - 1];
|
||||
if (clientX >= lastTop.bounds.right && clientX < item.bounds.right - CELL_WIDTH / 2) {
|
||||
if (lastTop.pedalItem) {
|
||||
this.model.movePedalBoardItemAfter(instanceId, lastTop.pedalItem.instanceId);
|
||||
this.model.movePedalboardItemAfter(instanceId, lastTop.pedalItem.instanceId);
|
||||
this.setSelection(instanceId);
|
||||
return;
|
||||
}
|
||||
@@ -441,7 +441,7 @@ const PedalBoardView =
|
||||
if (clientX < item.bottomChildren[0].bounds.x) {
|
||||
let bottomPedalItem = item.bottomChildren[0].pedalItem;
|
||||
if (bottomPedalItem) {
|
||||
this.model.movePedalBoardItemBefore(instanceId, bottomPedalItem.instanceId);
|
||||
this.model.movePedalboardItemBefore(instanceId, bottomPedalItem.instanceId);
|
||||
this.setSelection(instanceId);
|
||||
return;
|
||||
}
|
||||
@@ -450,7 +450,7 @@ const PedalBoardView =
|
||||
if (clientX >= lastBottom.bounds.right && clientX < item.bounds.right-CELL_WIDTH/2)
|
||||
{
|
||||
if (lastBottom.pedalItem) {
|
||||
this.model.movePedalBoardItemAfter(instanceId, lastBottom.pedalItem.instanceId);
|
||||
this.model.movePedalboardItemAfter(instanceId, lastBottom.pedalItem.instanceId);
|
||||
this.setSelection(instanceId);
|
||||
return;
|
||||
}
|
||||
@@ -461,11 +461,11 @@ const PedalBoardView =
|
||||
|
||||
} else if (item.bounds.contains(clientX, clientY)) {
|
||||
if (item.isStart()) {
|
||||
this.model.movePedalBoardItemToStart(instanceId);
|
||||
this.model.movePedalboardItemToStart(instanceId);
|
||||
this.setSelection(instanceId);
|
||||
return;
|
||||
} else if (item.isEnd()) {
|
||||
this.model.movePedalBoardItemToEnd(instanceId);
|
||||
this.model.movePedalboardItemToEnd(instanceId);
|
||||
this.setSelection(instanceId);
|
||||
return;
|
||||
} else {
|
||||
@@ -473,11 +473,11 @@ const PedalBoardView =
|
||||
{
|
||||
let margin = (CELL_WIDTH - FRAME_SIZE) / 2;
|
||||
if (clientX < item.bounds.x + margin) {
|
||||
this.model.movePedalBoardItemBefore(instanceId, item.pedalItem.instanceId);
|
||||
this.model.movePedalboardItemBefore(instanceId, item.pedalItem.instanceId);
|
||||
} else if (clientX > item.bounds.right - margin) {
|
||||
this.model.movePedalBoardItemAfter(instanceId, item.pedalItem.instanceId);
|
||||
this.model.movePedalboardItemAfter(instanceId, item.pedalItem.instanceId);
|
||||
} else {
|
||||
this.model.movePedalBoardItem(instanceId, item.pedalItem.instanceId);
|
||||
this.model.movePedalboardItem(instanceId, item.pedalItem.instanceId);
|
||||
}
|
||||
this.setSelection(instanceId);
|
||||
return;
|
||||
@@ -487,23 +487,23 @@ const PedalBoardView =
|
||||
}
|
||||
}
|
||||
// delete the plugin.
|
||||
let newId = this.model.setPedalBoardItemEmpty(instanceId);
|
||||
let newId = this.model.setPedalboardItemEmpty(instanceId);
|
||||
this.setSelection(newId);
|
||||
|
||||
}
|
||||
|
||||
onPedalBoardChanged(value?: PedalBoard) {
|
||||
this.setState({ pedalBoard: value });
|
||||
onPedalboardChanged(value?: Pedalboard) {
|
||||
this.setState({ pedalboard: value });
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.scrollRef.current!.addEventListener("touchstart",this.handleTouchStart, {passive: false});
|
||||
this.model.pedalBoard.addOnChangedHandler(this.onPedalBoardChanged);
|
||||
this.model.pedalboard.addOnChangedHandler(this.onPedalboardChanged);
|
||||
|
||||
}
|
||||
componentWillUnmount() {
|
||||
this.scrollRef.current!.removeEventListener("touchstart",this.handleTouchStart);
|
||||
this.model.pedalBoard.removeOnChangedHandler(this.onPedalBoardChanged);
|
||||
this.model.pedalboard.removeOnChangedHandler(this.onPedalboardChanged);
|
||||
}
|
||||
|
||||
offsetLayout_(layoutItems: PedalLayout[], offset: number): void {
|
||||
@@ -523,7 +523,7 @@ const PedalBoardView =
|
||||
if (layoutItem.pedalItem === undefined) {
|
||||
throw new Error("Invalid splitter");
|
||||
}
|
||||
let split = layoutItem.pedalItem as PedalBoardSplitItem;
|
||||
let split = layoutItem.pedalItem as PedalboardSplitItem;
|
||||
if (split.getSplitType() === SplitType.Ab) {
|
||||
if (split.isASelected()) {
|
||||
return "img/fx_split_a.svg";
|
||||
@@ -706,7 +706,7 @@ const PedalBoardView =
|
||||
let yTop = item.topConnectorY;
|
||||
let yBottom = item.bottomConnectorY;
|
||||
//let isStereo = item.stereoOutput;
|
||||
let split = item.pedalItem as PedalBoardSplitItem;
|
||||
let split = item.pedalItem as PedalboardSplitItem;
|
||||
|
||||
let topEnabled = enabled && split.isASelected();
|
||||
let bottomEnabled = enabled && split.isBSelected();
|
||||
@@ -889,7 +889,7 @@ const PedalBoardView =
|
||||
// actually not here anymore. :-/ It has a reactive definition in MainPage.tsx now.
|
||||
while (el)
|
||||
{
|
||||
if (el.id === "pedalBoardScroll")
|
||||
if (el.id === "pedalboardScroll")
|
||||
{
|
||||
return el as HTMLDivElement;
|
||||
}
|
||||
@@ -930,7 +930,7 @@ const PedalBoardView =
|
||||
for (let i = 0; i < length; ++i) {
|
||||
let item = layoutChain[i];
|
||||
if (item.isSplitter()) {
|
||||
let splitter = item.pedalItem as PedalBoardSplitItem;
|
||||
let splitter = item.pedalItem as PedalboardSplitItem;
|
||||
this.renderSplitConnectors(output, item, enabled, i === length - 1 && shortSplitOutput,);
|
||||
this.renderConnectors(output, item.topChildren, enabled && splitter.isASelected(), false);
|
||||
this.renderConnectors(output, item.bottomChildren, enabled && splitter.isBSelected(), false);
|
||||
@@ -942,15 +942,14 @@ const PedalBoardView =
|
||||
}
|
||||
}
|
||||
renderConnectorFrame(layoutChain: PedalLayout[], layoutSize: LayoutSize): ReactNode {
|
||||
let output: ReactNode[] = [];
|
||||
this.renderConnectors(output, layoutChain, true, false);
|
||||
|
||||
let outputs: ReactNode[] = [];
|
||||
this.renderConnectors(outputs, layoutChain, true, false);
|
||||
return (
|
||||
<svg width={layoutSize.width} height={layoutSize.height}
|
||||
xmlns="http://www.w3.org/2000/svg" viewBox={"0 0 " + layoutSize.width + " " + layoutSize.height}>
|
||||
<g fill="none">
|
||||
{
|
||||
output
|
||||
outputs
|
||||
}
|
||||
</g>
|
||||
|
||||
@@ -1065,7 +1064,7 @@ const PedalBoardView =
|
||||
let topInputs = item.topChildren[0].numberOfInputs;
|
||||
let bottomInputs = item.bottomChildren[0].numberOfInputs;
|
||||
|
||||
let splitItem = item.pedalItem as PedalBoardSplitItem;
|
||||
let splitItem = item.pedalItem as PedalboardSplitItem;
|
||||
if (splitItem.getSplitType() !== SplitType.Lr)
|
||||
{
|
||||
item.numberOfInputs = CalculateConnection(item.numberOfInputs, Math.max(topInputs,bottomInputs));
|
||||
@@ -1102,7 +1101,7 @@ const PedalBoardView =
|
||||
for (let i = 0; i < layoutChain.length; ++i) {
|
||||
let item = layoutChain[i];
|
||||
if (item.isSplitter()) {
|
||||
let splitter = item.pedalItem as PedalBoardSplitItem;
|
||||
let splitter = item.pedalItem as PedalboardSplitItem;
|
||||
item.numberOfInputs = numberOfInputs;
|
||||
|
||||
let chainInputs = numberOfInputs;
|
||||
@@ -1156,7 +1155,7 @@ const PedalBoardView =
|
||||
render() {
|
||||
const { classes } = this.props;
|
||||
|
||||
let layoutChain = makeChain(this.model, this.state.pedalBoard?.items);
|
||||
let layoutChain = makeChain(this.model, this.state.pedalboard?.items);
|
||||
let start = PedalLayout.Start();
|
||||
let end = PedalLayout.End();
|
||||
if (layoutChain.length !== 0)
|
||||
@@ -1187,4 +1186,4 @@ const PedalBoardView =
|
||||
}
|
||||
);
|
||||
|
||||
export default PedalBoardView
|
||||
export default PedalboardView
|
||||
+423
-372
File diff suppressed because it is too large
Load Diff
@@ -23,10 +23,10 @@ import { WithStyles } from '@mui/styles';
|
||||
import createStyles from '@mui/styles/createStyles';
|
||||
import withStyles from '@mui/styles/withStyles';
|
||||
import { PiPedalModel, PiPedalModelFactory } from './PiPedalModel';
|
||||
import { UiPlugin, UiControl, PiPedalFileProperty,PiPedalFileType } from './Lv2Plugin';
|
||||
import { UiPlugin, UiControl, PiPedalFileProperty} from './Lv2Plugin';
|
||||
import {
|
||||
PedalBoard, PedalBoardItem, ControlValue,PropertyValue
|
||||
} from './PedalBoard';
|
||||
Pedalboard, PedalboardItem, ControlValue
|
||||
} from './Pedalboard';
|
||||
import PluginControl from './PluginControl';
|
||||
import ResizeResponsiveComponent from './ResizeResponsiveComponent';
|
||||
import VuMeter from './VuMeter';
|
||||
@@ -36,6 +36,7 @@ import Typography from '@mui/material/Typography';
|
||||
import FullScreenIME from './FullScreenIME';
|
||||
import FilePropertyControl from './FilePropertyControl';
|
||||
import FilePropertyDialog from './FilePropertyDialog';
|
||||
import JsonAtom from './JsonAtom';
|
||||
|
||||
|
||||
export const StandardItemSize = { width: 80, height: 110 };
|
||||
@@ -188,7 +189,7 @@ export interface ControlViewCustomization {
|
||||
export interface PluginControlViewProps extends WithStyles<typeof styles> {
|
||||
theme: Theme;
|
||||
instanceId: number;
|
||||
item: PedalBoardItem;
|
||||
item: PedalboardItem;
|
||||
customization?: ControlViewCustomization;
|
||||
customizationId?: number;
|
||||
}
|
||||
@@ -224,35 +225,32 @@ const PluginControlView =
|
||||
dialogFileValue: ""
|
||||
|
||||
}
|
||||
this.onPedalBoardChanged = this.onPedalBoardChanged.bind(this);
|
||||
this.onPedalboardChanged = this.onPedalboardChanged.bind(this);
|
||||
this.onControlValueChanged = this.onControlValueChanged.bind(this);
|
||||
this.onPreviewChange = this.onPreviewChange.bind(this);
|
||||
}
|
||||
|
||||
|
||||
onPreviewChange(key: string, value: number): void {
|
||||
this.model.previewPedalBoardValue(this.props.instanceId, key, value);
|
||||
this.model.previewPedalboardValue(this.props.instanceId, key, value);
|
||||
}
|
||||
|
||||
onControlValueChanged(key: string, value: number): void {
|
||||
this.model.setPedalBoardControlValue(this.props.instanceId, key, value);
|
||||
}
|
||||
onPropertyValueChanged(propertyUri: string, value: any): void {
|
||||
this.model.setPedalBoardPropertyValue(this.props.instanceId, propertyUri, value);
|
||||
this.model.setPedalboardControl(this.props.instanceId, key, value);
|
||||
}
|
||||
|
||||
onPedalBoardChanged(value?: PedalBoard) {
|
||||
//let item = this.model.pedalBoard.get().maybeGetItem(this.props.instanceId);
|
||||
//this.setState({ pedalBoardItem: item });
|
||||
onPedalboardChanged(value?: Pedalboard) {
|
||||
//let item = this.model.pedalboard.get().maybeGetItem(this.props.instanceId);
|
||||
//this.setState({ pedalboardItem: item });
|
||||
}
|
||||
|
||||
|
||||
componentDidMount() {
|
||||
super.componentDidMount();
|
||||
this.model.pedalBoard.addOnChangedHandler(this.onPedalBoardChanged);
|
||||
this.model.pedalboard.addOnChangedHandler(this.onPedalboardChanged);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
this.model.pedalBoard.removeOnChangedHandler(this.onPedalBoardChanged);
|
||||
this.model.pedalboard.removeOnChangedHandler(this.onPedalboardChanged);
|
||||
super.componentWillUnmount();
|
||||
}
|
||||
|
||||
@@ -285,22 +283,10 @@ const PluginControlView =
|
||||
});
|
||||
}
|
||||
|
||||
makeFilePropertyUI(fileProperty: PiPedalFileProperty, propertyValues: PropertyValue[]): ReactNode {
|
||||
let propertyValue: PropertyValue | undefined = undefined;
|
||||
for (let i = 0; i < propertyValues.length; ++i) {
|
||||
if (propertyValues[i].propertyUri === fileProperty.patchProperty) {
|
||||
propertyValue = propertyValues[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!propertyValue) {
|
||||
propertyValue = new PropertyValue();
|
||||
propertyValue.value = fileProperty.defaultFile;
|
||||
propertyValue.propertyUri = fileProperty.patchProperty;
|
||||
}
|
||||
makeFilePropertyUI(fileProperty: PiPedalFileProperty): ReactNode {
|
||||
return ((
|
||||
|
||||
<FilePropertyControl instanceId={this.props.instanceId} value={propertyValue.value}
|
||||
<FilePropertyControl instanceId={this.props.instanceId}
|
||||
fileProperty={fileProperty}
|
||||
onFileClick={(fileProperty,selectedFile) => {
|
||||
this.setState({showFileDialog: true,dialogFileProperty: fileProperty,dialogFileValue: selectedFile});
|
||||
@@ -333,7 +319,7 @@ const PluginControlView =
|
||||
|
||||
}
|
||||
|
||||
getStandardControlNodes(plugin: UiPlugin, controlValues: ControlValue[],propertyValues: PropertyValue[]): ControlNodes {
|
||||
getStandardControlNodes(plugin: UiPlugin, controlValues: ControlValue[]): ControlNodes {
|
||||
let result: ControlNodes = [];
|
||||
|
||||
for (let i = 0; i < plugin.controls.length; ++i) {
|
||||
@@ -350,7 +336,7 @@ const PluginControlView =
|
||||
pluginControl = plugin.controls[i];
|
||||
if (!pluginControl.not_on_gui) {
|
||||
groupControls.push(
|
||||
this.makeStandardControl(pluginControl, controlValues)
|
||||
this.makeStandardControl(pluginControl,controlValues)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -359,7 +345,7 @@ const PluginControlView =
|
||||
)
|
||||
} else {
|
||||
result.push(
|
||||
this.makeStandardControl(pluginControl, controlValues)
|
||||
this.makeStandardControl(pluginControl,controlValues)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -367,7 +353,7 @@ const PluginControlView =
|
||||
for (let i = 0; i < plugin.fileProperties.length; ++i) {
|
||||
let fileProperty = plugin.fileProperties[i];
|
||||
result.push(
|
||||
this.makeFilePropertyUI(fileProperty, propertyValues)
|
||||
this.makeFilePropertyUI(fileProperty)
|
||||
);
|
||||
}
|
||||
return result;
|
||||
@@ -383,7 +369,7 @@ const PluginControlView =
|
||||
}
|
||||
|
||||
onImeValueChange(key: string, value: number) {
|
||||
this.model.setPedalBoardControlValue(this.props.instanceId, key, value);
|
||||
this.model.setPedalboardControl(this.props.instanceId, key, value);
|
||||
this.onImeClose();
|
||||
}
|
||||
onImeClose() {
|
||||
@@ -427,7 +413,7 @@ const PluginControlView =
|
||||
result.push((
|
||||
<div className={!isLandscapeGrid ? classes.portGroup : classes.portGroupLandscape}>
|
||||
<div className={classes.portGroupTitle}>
|
||||
<Typography variant="caption">{controlGroup.name}</Typography>
|
||||
<Typography noWrap variant="caption">{controlGroup.name}</Typography>
|
||||
</div>
|
||||
<div className={classes.portGroupControls} >
|
||||
{
|
||||
@@ -452,16 +438,15 @@ const PluginControlView =
|
||||
|
||||
render(): ReactNode {
|
||||
let classes = this.props.classes;
|
||||
let pedalBoardItem = this.model.pedalBoard.get().getItem(this.props.instanceId);
|
||||
let pedalboardItem = this.model.pedalboard.get().getItem(this.props.instanceId);
|
||||
|
||||
if (!pedalBoardItem)
|
||||
if (!pedalboardItem)
|
||||
return (<div className={classes.frame} ></div>);
|
||||
|
||||
let controlValues = pedalBoardItem.controlValues;
|
||||
let propertyValues = pedalBoardItem.propertyValues;
|
||||
let controlValues = pedalboardItem.controlValues;
|
||||
|
||||
|
||||
let plugin: UiPlugin = nullCast(this.model.getUiPlugin(pedalBoardItem.uri));
|
||||
let plugin: UiPlugin = nullCast(this.model.getUiPlugin(pedalboardItem.uri));
|
||||
|
||||
|
||||
controlValues = this.filterNotOnGui(controlValues, plugin);
|
||||
@@ -472,7 +457,7 @@ const PluginControlView =
|
||||
let vuMeterRClass = this.state.landscapeGrid ? classes.vuMeterRLandscape : classes.vuMeterR;
|
||||
let controlNodes: ControlNodes;
|
||||
|
||||
controlNodes = this.getStandardControlNodes(plugin, controlValues,propertyValues);
|
||||
controlNodes = this.getStandardControlNodes(plugin, controlValues);
|
||||
|
||||
if (this.props.customization) {
|
||||
// allow wrapper class to insert/remove/rebuild controls.
|
||||
@@ -484,10 +469,10 @@ const PluginControlView =
|
||||
return (
|
||||
<div className={classes.frame}>
|
||||
<div className={classes.vuMeterL}>
|
||||
<VuMeter display="input" instanceId={pedalBoardItem.instanceId} />
|
||||
<VuMeter display="input" instanceId={pedalboardItem.instanceId} />
|
||||
</div>
|
||||
<div className={vuMeterRClass}>
|
||||
<VuMeter display="output" instanceId={pedalBoardItem.instanceId} />
|
||||
<VuMeter display="output" instanceId={pedalboardItem.instanceId} />
|
||||
</div>
|
||||
<div className={gridClass} >
|
||||
{
|
||||
@@ -503,9 +488,21 @@ const PluginControlView =
|
||||
<FilePropertyDialog open={this.state.showFileDialog}
|
||||
fileProperty={this.state.dialogFileProperty}
|
||||
selectedFile={this.state.dialogFileValue}
|
||||
onClose={()=> { this.setState({ showFileDialog: false});}}
|
||||
onCancel={()=> { this.setState({ showFileDialog: false});}}
|
||||
onOk={(fileProperty,selectedFile)=> {
|
||||
this.model.setPedalBoardPropertyValue(this.props.instanceId,fileProperty.patchProperty,selectedFile)
|
||||
|
||||
this.model.setPatchProperty(
|
||||
this.props.instanceId,
|
||||
fileProperty.patchProperty,
|
||||
JsonAtom.Path(selectedFile)
|
||||
)
|
||||
.then( () => {
|
||||
|
||||
})
|
||||
.catch((error) =>
|
||||
{
|
||||
this.model.showAlert("setPatchProperty failed: " +error);
|
||||
});
|
||||
this.setState({ showFileDialog: false});}
|
||||
}
|
||||
/>
|
||||
|
||||
@@ -259,7 +259,7 @@ const PluginPresetsDialog = withStyles(styles, { withTheme: true })(
|
||||
<img src="img/ic_pluginpreset2.svg" className={classes.itemIcon} alt="" />
|
||||
</div>
|
||||
<div className={classes.itemLabel}>
|
||||
<Typography>
|
||||
<Typography> noWrap
|
||||
{presetEntry.label}
|
||||
</Typography>
|
||||
</div>
|
||||
@@ -312,8 +312,8 @@ const PluginPresetsDialog = withStyles(styles, { withTheme: true })(
|
||||
this.setState({ renameOpen: false });
|
||||
}
|
||||
getPluginUri() : string {
|
||||
let pedalBoardItem = this.model.pedalBoard.get().getItem(this.props.instanceId);
|
||||
return pedalBoardItem.uri;
|
||||
let pedalboardItem = this.model.pedalboard.get().getItem(this.props.instanceId);
|
||||
return pedalboardItem.uri;
|
||||
}
|
||||
handleCopy() {
|
||||
let item = this.props.presets.getItem(this.state.selectedItem);
|
||||
@@ -359,7 +359,7 @@ const PluginPresetsDialog = withStyles(styles, { withTheme: true })(
|
||||
>
|
||||
<ArrowBackIcon />
|
||||
</IconButton>
|
||||
<Typography variant="h6" className={classes.dialogTitle}>
|
||||
<Typography noWrap variant="h6" className={classes.dialogTitle}>
|
||||
{title}
|
||||
</Typography>
|
||||
<IconButton color="inherit" onClick={(e) => this.showActionBar(true)} >
|
||||
|
||||
@@ -497,6 +497,10 @@ const SettingsDialog = withStyles(styles, { withTheme: true })(
|
||||
|
||||
}
|
||||
|
||||
onOnboardingContinue() {
|
||||
this.model.setOnboarding(false);
|
||||
this.props.onClose();
|
||||
}
|
||||
render() {
|
||||
let classes = this.props.classes;
|
||||
let isConfigValid = this.state.jackConfiguration.isValid;
|
||||
@@ -544,40 +548,41 @@ const SettingsDialog = withStyles(styles, { withTheme: true })(
|
||||
}}
|
||||
>
|
||||
<div >
|
||||
{this.props.onboarding ?
|
||||
{this.props.onboarding &&
|
||||
(
|
||||
<div>
|
||||
<Typography display="block" variant="caption" color="textSecondary" style={{paddingLeft: 24,paddingBottom: 8 }}>
|
||||
<Typography display="block" variant="body1" color="textSecondary" style={{paddingLeft: 24,paddingBottom: 8 }}>
|
||||
Select and configure an audio device. You may optionally configure MIDI inputs, and set up a Wi-Fi Direct Hotspot now as well.
|
||||
</Typography>
|
||||
<Typography display="block" variant="caption" color="textSecondary" style={{paddingLeft: 24,paddingBottom: 8 }}>
|
||||
<Typography display="block" variant="body1" color="textSecondary" style={{paddingLeft: 24,paddingBottom: 8 }}>
|
||||
Access and modify these settings later by selecting the <i>Settings</i> menu item on the main menu.
|
||||
</Typography>
|
||||
</div>
|
||||
):
|
||||
(
|
||||
<div>
|
||||
|
||||
<Typography className={classes.sectionHead} display="block" variant="caption" color="secondary">
|
||||
STATUS
|
||||
</Typography>
|
||||
{(!isConfigValid) ?
|
||||
(
|
||||
<div style={{ paddingLeft: 48, position: "relative", top: -12 }}>
|
||||
<Typography display="block" variant="caption" color="textSecondary">Status: <span style={{ color: "#F00" }}>Not configured.</span></Typography>
|
||||
<Typography display="block" variant="caption" color="textSecondary">Governor: </Typography>
|
||||
</div>
|
||||
) :
|
||||
(
|
||||
<div style={{ paddingLeft: 48, position: "relative", top: -12 }}>
|
||||
{JackHostStatus.getDisplayView("", this.state.jackStatus)}
|
||||
{JackHostStatus.getCpuInfo("Governor:\u00A0", this.state.jackStatus)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
<Divider />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div>
|
||||
<Typography className={classes.sectionHead} display="block" variant="caption" color="secondary">
|
||||
STATUS
|
||||
</Typography>
|
||||
{(!isConfigValid) ?
|
||||
(
|
||||
<div style={{ paddingLeft: 48, position: "relative", top: -12 }}>
|
||||
<Typography display="block" variant="caption" color="textSecondary">Status: <span style={{ color: "#F00" }}>Not configured.</span></Typography>
|
||||
{(!this.props.onboarding) && (
|
||||
<Typography display="block" variant="caption" color="textSecondary">Governor: </Typography>
|
||||
)}
|
||||
</div>
|
||||
) :
|
||||
(
|
||||
<div style={{ paddingLeft: 48, position: "relative", top: -12 }}>
|
||||
{JackHostStatus.getDisplayView("", this.state.jackStatus)}
|
||||
{ (!this.props.onboarding) && JackHostStatus.getCpuInfo("Governor:\u00A0", this.state.jackStatus)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
|
||||
{this.state.jackConfiguration.errorState !== "" &&
|
||||
(
|
||||
<div style={{ paddingLeft: 48, position: "relative", top: -12 }}>
|
||||
@@ -782,7 +787,7 @@ const SettingsDialog = withStyles(styles, { withTheme: true })(
|
||||
<Divider/>
|
||||
<div style={{display: "grid", placeContent: "end", maxWidth: 550, marginLeft: 16,marginRight: 16,
|
||||
marginTop: 16,marginBottom: 16}}>
|
||||
<Button variant="outlined" disabled={this.state.continueDisabled} style={{width: 120}}>Continue</Button>
|
||||
<Button variant="outlined" onClick={()=> {this.onOnboardingContinue()}} disabled={this.state.continueDisabled} style={{width: 120}}>Continue</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -25,8 +25,8 @@ import withStyles from '@mui/styles/withStyles';
|
||||
import { PiPedalModel, PiPedalModelFactory } from './PiPedalModel';
|
||||
import { UiPlugin } from './Lv2Plugin';
|
||||
import {
|
||||
PedalBoard, PedalBoardSplitItem, ControlValue,
|
||||
} from './PedalBoard';
|
||||
Pedalboard, PedalboardSplitItem, ControlValue,
|
||||
} from './Pedalboard';
|
||||
import PluginControl from './PluginControl';
|
||||
import ResizeResponsiveComponent from './ResizeResponsiveComponent';
|
||||
import VuMeter from './VuMeter';
|
||||
@@ -97,7 +97,7 @@ const styles = (theme: Theme) => createStyles({
|
||||
interface SplitControlViewProps extends WithStyles<typeof styles> {
|
||||
theme: Theme;
|
||||
instanceId: number;
|
||||
item: PedalBoardSplitItem;
|
||||
item: PedalboardSplitItem;
|
||||
}
|
||||
type SplitControlViewState = {
|
||||
landscapeGrid: boolean;
|
||||
@@ -117,32 +117,32 @@ const SplitControlView =
|
||||
landscapeGrid: false
|
||||
|
||||
}
|
||||
this.onPedalBoardChanged = this.onPedalBoardChanged.bind(this);
|
||||
this.onPedalboardChanged = this.onPedalboardChanged.bind(this);
|
||||
this.onValueChanged = this.onValueChanged.bind(this);
|
||||
this.onPreviewChange = this.onPreviewChange.bind(this);
|
||||
}
|
||||
|
||||
|
||||
onPreviewChange(key: string, value: number): void {
|
||||
this.model.previewPedalBoardValue(this.props.instanceId, key, value);
|
||||
this.model.previewPedalboardValue(this.props.instanceId, key, value);
|
||||
}
|
||||
|
||||
onValueChanged(key: string, value: number): void {
|
||||
this.model.setPedalBoardControlValue(this.props.instanceId, key, value);
|
||||
this.model.setPedalboardControl(this.props.instanceId, key, value);
|
||||
}
|
||||
|
||||
onPedalBoardChanged(value?: PedalBoard) {
|
||||
//let item = this.model.pedalBoard.get().maybeGetItem(this.props.instanceId);
|
||||
//this.setState({ pedalBoardItem: item });
|
||||
onPedalboardChanged(value?: Pedalboard) {
|
||||
//let item = this.model.pedalboard.get().maybeGetItem(this.props.instanceId);
|
||||
//this.setState({ pedalboardItem: item });
|
||||
}
|
||||
|
||||
|
||||
componentDidMount() {
|
||||
super.componentDidMount();
|
||||
this.model.pedalBoard.addOnChangedHandler(this.onPedalBoardChanged);
|
||||
this.model.pedalboard.addOnChangedHandler(this.onPedalboardChanged);
|
||||
}
|
||||
componentWillUnmount() {
|
||||
this.model.pedalBoard.removeOnChangedHandler(this.onPedalBoardChanged);
|
||||
this.model.pedalboard.removeOnChangedHandler(this.onPedalboardChanged);
|
||||
super.componentWillUnmount();
|
||||
}
|
||||
|
||||
@@ -162,29 +162,29 @@ const SplitControlView =
|
||||
|
||||
render(): ReactNode {
|
||||
let classes = this.props.classes;
|
||||
let pedalBoardItem = this.model.pedalBoard.get().getItem(this.props.instanceId);
|
||||
let pedalboardItem = this.model.pedalboard.get().getItem(this.props.instanceId);
|
||||
|
||||
if (!pedalBoardItem)
|
||||
if (!pedalboardItem)
|
||||
return (<div className={classes.frame}></div>);
|
||||
|
||||
|
||||
let gridClass = this.state.landscapeGrid ? classes.landscapeGrid : classes.normalGrid;
|
||||
let vuMeterRClass = this.state.landscapeGrid ? classes.vuMeterRLandscape : classes.vuMeterR;
|
||||
let typeValue = pedalBoardItem.getControl(PedalBoardSplitItem.TYPE_KEY);
|
||||
let mixValue = pedalBoardItem.getControl(PedalBoardSplitItem.MIX_KEY);
|
||||
let selectValue = pedalBoardItem.getControl(PedalBoardSplitItem.SELECT_KEY);
|
||||
let panLValue = pedalBoardItem.getControl(PedalBoardSplitItem.PANL_KEY);
|
||||
let volumeLValue = pedalBoardItem.getControl(PedalBoardSplitItem.VOLL_KEY);
|
||||
let panRValue = pedalBoardItem.getControl(PedalBoardSplitItem.PANR_KEY);
|
||||
let volumeRValue = pedalBoardItem.getControl(PedalBoardSplitItem.VOLR_KEY);
|
||||
let typeValue = pedalboardItem.getControl(PedalboardSplitItem.TYPE_KEY);
|
||||
let mixValue = pedalboardItem.getControl(PedalboardSplitItem.MIX_KEY);
|
||||
let selectValue = pedalboardItem.getControl(PedalboardSplitItem.SELECT_KEY);
|
||||
let panLValue = pedalboardItem.getControl(PedalboardSplitItem.PANL_KEY);
|
||||
let volumeLValue = pedalboardItem.getControl(PedalboardSplitItem.VOLL_KEY);
|
||||
let panRValue = pedalboardItem.getControl(PedalboardSplitItem.PANR_KEY);
|
||||
let volumeRValue = pedalboardItem.getControl(PedalboardSplitItem.VOLR_KEY);
|
||||
|
||||
return (
|
||||
<div className={classes.frame}>
|
||||
<div className={classes.vuMeterL}>
|
||||
<VuMeter display="input" instanceId={pedalBoardItem.instanceId} />
|
||||
<VuMeter display="input" instanceId={pedalboardItem.instanceId} />
|
||||
</div>
|
||||
<div className={vuMeterRClass}>
|
||||
<VuMeter display="output" instanceId={pedalBoardItem.instanceId} />
|
||||
<VuMeter display="output" instanceId={pedalboardItem.instanceId} />
|
||||
</div>
|
||||
<div className={gridClass} >
|
||||
<div style={{ flex: "0 0 auto" }}>
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
import {UiControl,ScalePoint} from './Lv2Plugin';
|
||||
import {PedalBoardSplitItem} from './PedalBoard';
|
||||
import {PedalboardSplitItem} from './Pedalboard';
|
||||
import Units from './Units'
|
||||
|
||||
|
||||
|
||||
export const SplitTypeControl: UiControl = new UiControl().deserialize({
|
||||
symbol: PedalBoardSplitItem.TYPE_KEY,
|
||||
symbol: PedalboardSplitItem.TYPE_KEY,
|
||||
name: "Type",
|
||||
index: 0,
|
||||
min_value: 0,
|
||||
@@ -47,7 +47,7 @@ export const SplitTypeControl: UiControl = new UiControl().deserialize({
|
||||
});
|
||||
|
||||
export const SplitAbControl: UiControl = new UiControl().deserialize({
|
||||
symbol: PedalBoardSplitItem.SELECT_KEY,
|
||||
symbol: PedalboardSplitItem.SELECT_KEY,
|
||||
name: "Select",
|
||||
index: 1,
|
||||
min_value: 0,
|
||||
@@ -70,7 +70,7 @@ export const SplitAbControl: UiControl = new UiControl().deserialize({
|
||||
|
||||
|
||||
export const SplitMixControl: UiControl = new UiControl().deserialize({
|
||||
symbol: PedalBoardSplitItem.MIX_KEY,
|
||||
symbol: PedalboardSplitItem.MIX_KEY,
|
||||
name: "Mix",
|
||||
index: 2,
|
||||
min_value: -1,
|
||||
@@ -87,7 +87,7 @@ export const SplitMixControl: UiControl = new UiControl().deserialize({
|
||||
});
|
||||
|
||||
export const SplitPanLeftControl: UiControl = new UiControl().deserialize({
|
||||
symbol: PedalBoardSplitItem.PANL_KEY,
|
||||
symbol: PedalboardSplitItem.PANL_KEY,
|
||||
name: "Pan Top",
|
||||
index: 3,
|
||||
min_value: -1,
|
||||
@@ -104,7 +104,7 @@ export const SplitPanLeftControl: UiControl = new UiControl().deserialize({
|
||||
});
|
||||
|
||||
export const SplitVolLeftControl: UiControl = new UiControl().deserialize({
|
||||
symbol: PedalBoardSplitItem.VOLL_KEY,
|
||||
symbol: PedalboardSplitItem.VOLL_KEY,
|
||||
name: "Vol Top",
|
||||
index: 4,
|
||||
min_value: -60,
|
||||
@@ -128,7 +128,7 @@ export const SplitVolLeftControl: UiControl = new UiControl().deserialize({
|
||||
|
||||
|
||||
export const SplitPanRightControl: UiControl = new UiControl().deserialize({
|
||||
symbol: PedalBoardSplitItem.PANR_KEY,
|
||||
symbol: PedalboardSplitItem.PANR_KEY,
|
||||
name: "Pan Bottom",
|
||||
index: 5,
|
||||
min_value: -1,
|
||||
@@ -145,7 +145,7 @@ export const SplitPanRightControl: UiControl = new UiControl().deserialize({
|
||||
});
|
||||
|
||||
export const SplitVolRightControl: UiControl = new UiControl().deserialize({
|
||||
symbol: PedalBoardSplitItem.VOLR_KEY,
|
||||
symbol: PedalboardSplitItem.VOLR_KEY,
|
||||
name: "Vol Bottom",
|
||||
index: 6,
|
||||
min_value: -60,
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
import StringBuilder from './StringBuilder';
|
||||
|
||||
class SvgPathBuilder {
|
||||
_sb: StringBuilder = new StringBuilder();
|
||||
private _sb: StringBuilder = new StringBuilder();
|
||||
|
||||
moveTo(x: number, y: number): SvgPathBuilder
|
||||
{
|
||||
@@ -37,7 +37,7 @@ class SvgPathBuilder {
|
||||
this._sb.append('C').append(x1).append(',').append(y1)
|
||||
.append(' ').append(x2).append(',').append(y2)
|
||||
.append(' ').append(x).append(',').append(y).append(' ');
|
||||
|
||||
return this;
|
||||
}
|
||||
closePath(): SvgPathBuilder {
|
||||
this._sb.append("Z ");
|
||||
|
||||
@@ -26,7 +26,7 @@ import withStyles from '@mui/styles/withStyles';
|
||||
|
||||
import IControlViewFactory from './IControlViewFactory';
|
||||
import { PiPedalModelFactory, PiPedalModel } from "./PiPedalModel";
|
||||
import { PedalBoardItem } from './PedalBoard';
|
||||
import { PedalboardItem } from './Pedalboard';
|
||||
import PluginControlView, { ControlGroup,ControlViewCustomization } from './PluginControlView';
|
||||
import ToobFrequencyResponseView from './ToobFrequencyResponseView';
|
||||
|
||||
@@ -37,7 +37,7 @@ const styles = (theme: Theme) => createStyles({
|
||||
|
||||
interface ToobCabSimProps extends WithStyles<typeof styles> {
|
||||
instanceId: number;
|
||||
item: PedalBoardItem;
|
||||
item: PedalboardItem;
|
||||
|
||||
}
|
||||
interface ToobCabSimState {
|
||||
@@ -83,8 +83,8 @@ const ToobCabSimView =
|
||||
class ToobCabSimViewFactory implements IControlViewFactory {
|
||||
uri: string = "http://two-play.com/plugins/toob-cab-sim";
|
||||
|
||||
Create(model: PiPedalModel, pedalBoardItem: PedalBoardItem): React.ReactNode {
|
||||
return (<ToobCabSimView instanceId={pedalBoardItem.instanceId} item={pedalBoardItem} />);
|
||||
Create(model: PiPedalModel, pedalboardItem: PedalboardItem): React.ReactNode {
|
||||
return (<ToobCabSimView instanceId={pedalboardItem.instanceId} item={pedalboardItem} />);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -30,14 +30,15 @@ import Utility from './Utility';
|
||||
import SvgPathBuilder from './SvgPathBuilder';
|
||||
|
||||
|
||||
|
||||
const FREQUENCY_RESPONSE_VECTOR_URI = "http://two-play.com/plugins/toob#frequencyResponseVector";
|
||||
|
||||
const PLOT_WIDTH = StandardItemSize.width*2-16;
|
||||
const PLOT_HEIGHT = StandardItemSize.height-12;
|
||||
const PLOT_WIDTH = StandardItemSize.width * 2 - 16;
|
||||
const PLOT_HEIGHT = StandardItemSize.height - 12;
|
||||
|
||||
const styles = (theme: Theme) => createStyles({
|
||||
frame: {
|
||||
width: PLOT_WIDTH, height: PLOT_HEIGHT, background: "#444",
|
||||
width: PLOT_WIDTH, height: PLOT_HEIGHT, background: "#444",
|
||||
borderRadius: 6,
|
||||
marginTop: 12, marginLeft: 8, marginRight: 8,
|
||||
boxShadow: "1px 4px 8px #000 inset"
|
||||
@@ -73,33 +74,31 @@ const ToobFrequencyResponseView =
|
||||
};
|
||||
|
||||
this.pathRef = React.createRef();
|
||||
this.onPedalBoardChanged = this.onPedalBoardChanged.bind(this);
|
||||
this.onPedalboardChanged = this.onPedalboardChanged.bind(this);
|
||||
this.onStateChanged = this.onStateChanged.bind(this);
|
||||
}
|
||||
|
||||
onStateChanged()
|
||||
{
|
||||
if (this.model.state.get() === State.Ready)
|
||||
{
|
||||
onStateChanged() {
|
||||
if (this.model.state.get() === State.Ready) {
|
||||
this.requestDeferred = false;
|
||||
this.requestOutstanding = false;
|
||||
this.updateAllWaveShapes(); // after a reconnect.
|
||||
}
|
||||
}
|
||||
onPedalBoardChanged()
|
||||
{
|
||||
onPedalboardChanged() {
|
||||
this.updateAllWaveShapes();
|
||||
}
|
||||
componentDidMount()
|
||||
{
|
||||
private mounted: boolean = false;
|
||||
componentDidMount() {
|
||||
this.mounted = true;
|
||||
this.model.state.addOnChangedHandler(this.onStateChanged);
|
||||
this.model.pedalBoard.addOnChangedHandler(this.onPedalBoardChanged);
|
||||
this.model.pedalboard.addOnChangedHandler(this.onPedalboardChanged);
|
||||
this.updateAllWaveShapes();
|
||||
}
|
||||
componentWillUnmount()
|
||||
{
|
||||
componentWillUnmount() {
|
||||
this.mounted = false;
|
||||
this.model.state.removeOnChangedHandler(this.onStateChanged);
|
||||
this.model.pedalBoard.removeOnChangedHandler(this.onPedalBoardChanged);
|
||||
this.model.pedalboard.removeOnChangedHandler(this.onPedalboardChanged);
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
@@ -113,24 +112,23 @@ const ToobFrequencyResponseView =
|
||||
dbTickSpacingOpt: number = 10;
|
||||
|
||||
|
||||
MIN_DB_AF: number = Math.pow(10,-192/20);
|
||||
MIN_DB_AF: number = Math.pow(10, -192 / 20);
|
||||
fMin: number = 30;
|
||||
fMax: number = 20000;
|
||||
logMin: number = Math.log(this.fMin);
|
||||
logMax: number = Math.log(this.fMax);
|
||||
|
||||
|
||||
// Size of the SVG element.
|
||||
xMin: number = 0;
|
||||
xMax: number = PLOT_WIDTH+4;
|
||||
xMax: number = PLOT_WIDTH + 4;
|
||||
yMin: number = 0;
|
||||
yMax: number = PLOT_HEIGHT;
|
||||
dbTickSpacing: number = this.dbTickSpacingOpt;
|
||||
|
||||
toX(frequency: number): number
|
||||
{
|
||||
|
||||
toX(frequency: number): number {
|
||||
var logV = Math.log(frequency);
|
||||
return (this.xMax-this.xMin) * (logV-this.logMin)/(this.logMax-this.logMin) + this.xMin;
|
||||
|
||||
return (this.xMax - this.xMin) * (logV - this.logMin) / (this.logMax - this.logMin) + this.xMin;
|
||||
|
||||
}
|
||||
toY(value: number): number {
|
||||
value = Math.abs(value);
|
||||
@@ -139,24 +137,23 @@ const ToobFrequencyResponseView =
|
||||
if (value < this.MIN_DB_AF) {
|
||||
db = -192.0;
|
||||
} else {
|
||||
db = 20*Math.log10(value);
|
||||
db = 20 * Math.log10(value);
|
||||
}
|
||||
var y = (db-this.dbMin)/(this.dbMax-this.dbMin)*(this.yMax-this.yMin) + this.yMin;
|
||||
var y = (db - this.dbMin) / (this.dbMax - this.dbMin) * (this.yMax - this.yMin) + this.yMin;
|
||||
return y;
|
||||
}
|
||||
|
||||
onFrequencyResponseUpdated(data: number[]) {
|
||||
if (!this.mounted) return;
|
||||
let pathBuilder = new SvgPathBuilder();
|
||||
if (data.length > 2)
|
||||
{
|
||||
pathBuilder.moveTo(this.toX(data[0]),this.toY(data[1]))
|
||||
for (let i = 2; i < data.length; i += 2)
|
||||
{
|
||||
pathBuilder.lineTo(this.toX(data[i]),this.toY(data[i+1]));
|
||||
if (data.length > 2) {
|
||||
pathBuilder.moveTo(this.toX(data[0]), this.toY(data[1]))
|
||||
for (let i = 2; i < data.length; i += 2) {
|
||||
pathBuilder.lineTo(this.toX(data[i]), this.toY(data[i + 1]));
|
||||
}
|
||||
}
|
||||
this.currentPath = pathBuilder.toString();
|
||||
this.setState({path: this.currentPath});
|
||||
this.setState({ path: this.currentPath });
|
||||
|
||||
}
|
||||
|
||||
@@ -166,21 +163,23 @@ const ToobFrequencyResponseView =
|
||||
return;
|
||||
}
|
||||
this.requestOutstanding = true;
|
||||
this.model.getLv2Parameter<number[]>(this.props.instanceId, FREQUENCY_RESPONSE_VECTOR_URI)
|
||||
.then((data) => {
|
||||
this.onFrequencyResponseUpdated(data);
|
||||
if (this.requestDeferred) {
|
||||
Utility.delay(10) // take breath
|
||||
.then(
|
||||
() => {
|
||||
this.requestOutstanding = false;
|
||||
this.requestDeferred = false;
|
||||
this.updateAllWaveShapes();
|
||||
}
|
||||
this.model.getPatchProperty<any>(this.props.instanceId, FREQUENCY_RESPONSE_VECTOR_URI)
|
||||
.then((json) => {
|
||||
if (json && json.otype_ === "Vector" && json.vtype_ === "Float") {
|
||||
this.onFrequencyResponseUpdated(json.value as number[]);
|
||||
if (this.requestDeferred) {
|
||||
Utility.delay(10) // take breath
|
||||
.then(
|
||||
() => {
|
||||
this.requestOutstanding = false;
|
||||
this.requestDeferred = false;
|
||||
this.updateAllWaveShapes();
|
||||
}
|
||||
|
||||
);
|
||||
} else {
|
||||
this.requestOutstanding = false;
|
||||
);
|
||||
} else {
|
||||
this.requestOutstanding = false;
|
||||
}
|
||||
}
|
||||
}).catch(error => {
|
||||
// assume the connection was lost. We'll get saved by a reconnect.
|
||||
@@ -201,42 +200,36 @@ const ToobFrequencyResponseView =
|
||||
grid(): React.ReactNode[] {
|
||||
let result: React.ReactNode[] = [];
|
||||
|
||||
|
||||
for (var db = Math.ceil(this.dbMax/this.dbTickSpacing)*this.dbTickSpacing; db < this.dbMin; db += this.dbTickSpacing )
|
||||
{
|
||||
var y = (db-this.dbMin)/(this.dbMax-this.dbMin)*(this.yMax-this.yMin);
|
||||
if (db === 0)
|
||||
{
|
||||
result.push(
|
||||
this.majorGridLine(this.xMin,y,this.xMax,y)
|
||||
);
|
||||
|
||||
for (var db = Math.ceil(this.dbMax / this.dbTickSpacing) * this.dbTickSpacing; db < this.dbMin; db += this.dbTickSpacing) {
|
||||
var y = (db - this.dbMin) / (this.dbMax - this.dbMin) * (this.yMax - this.yMin);
|
||||
if (db === 0) {
|
||||
result.push(
|
||||
this.majorGridLine(this.xMin, y, this.xMax, y)
|
||||
);
|
||||
|
||||
} else {
|
||||
result.push(
|
||||
this.gridLine(this.xMin,y,this.xMax,y)
|
||||
);
|
||||
result.push(
|
||||
this.gridLine(this.xMin, y, this.xMax, y)
|
||||
);
|
||||
}
|
||||
}
|
||||
let decade0 = Math.pow(10,Math.floor(Math.log10(this.fMin)));
|
||||
for (var decade = decade0; decade < this.fMax; decade *= 10)
|
||||
{
|
||||
for (var i = 1; i <= 10; ++i)
|
||||
{
|
||||
var f = decade*i;
|
||||
if (f > this.fMin && f < this.fMax)
|
||||
{
|
||||
let decade0 = Math.pow(10, Math.floor(Math.log10(this.fMin)));
|
||||
for (var decade = decade0; decade < this.fMax; decade *= 10) {
|
||||
for (var i = 1; i <= 10; ++i) {
|
||||
var f = decade * i;
|
||||
if (f > this.fMin && f < this.fMax) {
|
||||
var x = this.toX(f);
|
||||
if (i === 10)
|
||||
{
|
||||
result.push(this.majorGridLine(x,this.yMin,x,this.yMax));
|
||||
if (i === 10) {
|
||||
result.push(this.majorGridLine(x, this.yMin, x, this.yMax));
|
||||
|
||||
} else {
|
||||
result.push(this.gridLine(x,this.yMin,x,this.yMax));
|
||||
result.push(this.gridLine(x, this.yMin, x, this.yMax));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
dbMin: number = 5;
|
||||
@@ -244,20 +237,20 @@ const ToobFrequencyResponseView =
|
||||
|
||||
render() {
|
||||
// deliberately reversed to flip up and down.
|
||||
this.dbMax = this.props.minDb ?? this.dbMinDefault;
|
||||
this.dbMax = this.props.minDb ?? this.dbMinDefault;
|
||||
this.dbMin = this.props.maxDb ?? this.dbMaxDefault;
|
||||
|
||||
this.fMin = this.props.minFrequency ?? 30;
|
||||
this.fMax = this.props.maxFrequency ?? 20000;
|
||||
this.logMin = Math.log(this.fMin);
|
||||
this.logMax = Math.log(this.fMax);
|
||||
|
||||
|
||||
|
||||
|
||||
let classes = this.props.classes;
|
||||
return (
|
||||
<div className={classes.frame} >
|
||||
<svg width={PLOT_WIDTH} height={PLOT_HEIGHT} viewBox={"0 0 " + PLOT_WIDTH + " " + PLOT_HEIGHT} stroke="#0F8" fill="none" strokeWidth="2.5" opacity="0.6">
|
||||
{ this.grid() }
|
||||
{this.grid()}
|
||||
<path d={this.state.path} ref={this.pathRef} />
|
||||
</svg>
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import withStyles from '@mui/styles/withStyles';
|
||||
|
||||
import IControlViewFactory from './IControlViewFactory';
|
||||
import { PiPedalModelFactory, PiPedalModel } from "./PiPedalModel";
|
||||
import { PedalBoardItem } from './PedalBoard';
|
||||
import { PedalboardItem } from './Pedalboard';
|
||||
import PluginControlView, { ControlGroup,ControlViewCustomization } from './PluginControlView';
|
||||
import ToobFrequencyResponseView from './ToobFrequencyResponseView';
|
||||
|
||||
@@ -37,7 +37,7 @@ const styles = (theme: Theme) => createStyles({
|
||||
|
||||
interface ToobInputStageProps extends WithStyles<typeof styles> {
|
||||
instanceId: number;
|
||||
item: PedalBoardItem;
|
||||
item: PedalboardItem;
|
||||
|
||||
}
|
||||
interface ToobInputStageState {
|
||||
@@ -84,8 +84,8 @@ const ToobInputStageView =
|
||||
class ToobInputStageViewFactory implements IControlViewFactory {
|
||||
uri: string = "http://two-play.com/plugins/toob-input_stage";
|
||||
|
||||
Create(model: PiPedalModel, pedalBoardItem: PedalBoardItem): React.ReactNode {
|
||||
return (<ToobInputStageView instanceId={pedalBoardItem.instanceId} item={pedalBoardItem} />);
|
||||
Create(model: PiPedalModel, pedalboardItem: PedalboardItem): React.ReactNode {
|
||||
return (<ToobInputStageView instanceId={pedalboardItem.instanceId} item={pedalboardItem} />);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import withStyles from '@mui/styles/withStyles';
|
||||
|
||||
import IControlViewFactory from './IControlViewFactory';
|
||||
import { PiPedalModelFactory, PiPedalModel,MonitorPortHandle } from "./PiPedalModel";
|
||||
import { PedalBoardItem } from './PedalBoard';
|
||||
import { PedalboardItem } from './Pedalboard';
|
||||
import PluginControlView, { ControlGroup,ControlViewCustomization } from './PluginControlView';
|
||||
import ToobFrequencyResponseView from './ToobFrequencyResponseView';
|
||||
|
||||
@@ -37,7 +37,7 @@ const styles = (theme: Theme) => createStyles({
|
||||
|
||||
interface ToobMLProps extends WithStyles<typeof styles> {
|
||||
instanceId: number;
|
||||
item: PedalBoardItem;
|
||||
item: PedalboardItem;
|
||||
|
||||
}
|
||||
interface ToobMLState {
|
||||
@@ -135,8 +135,8 @@ const ToobMLView =
|
||||
class ToobMLViewFactory implements IControlViewFactory {
|
||||
uri: string = "http://two-play.com/plugins/toob-ml";
|
||||
|
||||
Create(model: PiPedalModel, pedalBoardItem: PedalBoardItem): React.ReactNode {
|
||||
return (<ToobMLView instanceId={pedalBoardItem.instanceId} item={pedalBoardItem} />);
|
||||
Create(model: PiPedalModel, pedalboardItem: PedalboardItem): React.ReactNode {
|
||||
return (<ToobMLView instanceId={pedalboardItem.instanceId} item={pedalboardItem} />);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -26,18 +26,19 @@ import withStyles from '@mui/styles/withStyles';
|
||||
|
||||
import IControlViewFactory from './IControlViewFactory';
|
||||
import { PiPedalModelFactory, PiPedalModel, State,ListenHandle } from "./PiPedalModel";
|
||||
import { PedalBoardItem } from './PedalBoard';
|
||||
import { PedalboardItem } from './Pedalboard';
|
||||
import PluginControlView, { ControlGroup,ControlViewCustomization } from './PluginControlView';
|
||||
import ToobWaveShapeView, {BidirectionalVuPeak} from './ToobWaveShapeView';
|
||||
|
||||
|
||||
let POWERSTAGE_UI_URI = "http://two-play.com/plugins/toob-power-stage-2#uiState";
|
||||
|
||||
const styles = (theme: Theme) => createStyles({
|
||||
});
|
||||
|
||||
interface ToobPowerstage2Props extends WithStyles<typeof styles> {
|
||||
instanceId: number;
|
||||
item: PedalBoardItem;
|
||||
item: PedalboardItem;
|
||||
|
||||
}
|
||||
interface ToobPowerstage2State {
|
||||
@@ -60,18 +61,11 @@ const ToobPowerstage2View =
|
||||
uiState: [0,0,0,0,0,0,0,0]
|
||||
}
|
||||
this.onStateChanged = this.onStateChanged.bind(this);
|
||||
this.onAtomOutput = this.onAtomOutput.bind(this);
|
||||
}
|
||||
|
||||
listeningForOutput: boolean = false;
|
||||
atomOutputHandle?: ListenHandle;
|
||||
|
||||
onAtomOutput(instanceId: number, atomOutput: any): void {
|
||||
if (atomOutput.lv2Type === "http://two-play.com/plugins/toob-power-stage-2#uiState" )
|
||||
{
|
||||
this.setState({uiState: atomOutput.data as number[]});
|
||||
}
|
||||
}
|
||||
maybeListenForAtomOutput(): void {
|
||||
let listenForOutput = this.isReady && this.isControlMounted;
|
||||
|
||||
@@ -80,11 +74,22 @@ const ToobPowerstage2View =
|
||||
this.listeningForOutput = listenForOutput;
|
||||
if (listenForOutput)
|
||||
{
|
||||
this.atomOutputHandle = this.model.listenForAtomOutput(this.props.instanceId,this.onAtomOutput);
|
||||
this.atomOutputHandle = this.model.monitorPatchProperty(
|
||||
this.props.instanceId,
|
||||
POWERSTAGE_UI_URI,
|
||||
(instanceId: number, propertyUri: string, json: any) => {
|
||||
if (json.otype_ === "Vector")
|
||||
{
|
||||
this.setState({uiState: json.value as number[]});
|
||||
}
|
||||
});
|
||||
|
||||
// discard the output as we will be getting it through monitorPatchProperty as well.
|
||||
this.model.getPatchProperty(this.props.instanceId,POWERSTAGE_UI_URI);
|
||||
} else {
|
||||
if (this.atomOutputHandle)
|
||||
{
|
||||
this.model.cancelListenForAtomOutput(this.atomOutputHandle);
|
||||
this.model.cancelMonitorPatchProperty(this.atomOutputHandle);
|
||||
this.atomOutputHandle = undefined;
|
||||
}
|
||||
|
||||
@@ -180,8 +185,8 @@ const ToobPowerstage2View =
|
||||
class ToobPowerstage2ViewFactory implements IControlViewFactory {
|
||||
uri: string = "http://two-play.com/plugins/toob-power-stage-2";
|
||||
|
||||
Create(model: PiPedalModel, pedalBoardItem: PedalBoardItem): React.ReactNode {
|
||||
return (<ToobPowerstage2View instanceId={pedalBoardItem.instanceId} item={pedalBoardItem} />);
|
||||
Create(model: PiPedalModel, pedalboardItem: PedalboardItem): React.ReactNode {
|
||||
return (<ToobPowerstage2View instanceId={pedalboardItem.instanceId} item={pedalboardItem} />);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import withStyles from '@mui/styles/withStyles';
|
||||
|
||||
import IControlViewFactory from './IControlViewFactory';
|
||||
import { PiPedalModelFactory, PiPedalModel } from "./PiPedalModel";
|
||||
import { PedalBoardItem } from './PedalBoard';
|
||||
import { PedalboardItem } from './Pedalboard';
|
||||
import PluginControlView, { ControlGroup,ControlViewCustomization } from './PluginControlView';
|
||||
import ToobSpectrumResponseView from './ToobSpectrumResponseView';
|
||||
|
||||
@@ -38,7 +38,7 @@ const styles = (theme: Theme) => createStyles({
|
||||
|
||||
interface ToobSpectrumAnalyzerProps extends WithStyles<typeof styles> {
|
||||
instanceId: number;
|
||||
item: PedalBoardItem;
|
||||
item: PedalboardItem;
|
||||
|
||||
}
|
||||
interface ToobSpectrumAnalyzerState {
|
||||
@@ -84,8 +84,8 @@ const ToobSpectrumAnalyzerView =
|
||||
class ToobSpectrumAnalyzerViewFactory implements IControlViewFactory {
|
||||
uri: string = "http://two-play.com/plugins/toob-spectrum";
|
||||
|
||||
Create(model: PiPedalModel, pedalBoardItem: PedalBoardItem): React.ReactNode {
|
||||
return (<ToobSpectrumAnalyzerView instanceId={pedalBoardItem.instanceId} item={pedalBoardItem} />);
|
||||
Create(model: PiPedalModel, pedalboardItem: PedalboardItem): React.ReactNode {
|
||||
return (<ToobSpectrumAnalyzerView instanceId={pedalboardItem.instanceId} item={pedalboardItem} />);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -25,22 +25,30 @@ import { WithStyles } from '@mui/styles';
|
||||
import createStyles from '@mui/styles/createStyles';
|
||||
import withStyles from '@mui/styles/withStyles';
|
||||
|
||||
import { PiPedalModelFactory, PiPedalModel, State,ListenHandle } from "./PiPedalModel";
|
||||
import { PiPedalModelFactory, PiPedalModel, State, ListenHandle } from "./PiPedalModel";
|
||||
import { StandardItemSize } from './PluginControlView';
|
||||
import Utility from './Utility';
|
||||
// import { setInterval,clearInterval } from 'timers'; // no longer requires polyfill (webpack >= 5)
|
||||
|
||||
|
||||
const SPECTRUM_RESPONSE_VECTOR_URI = "http://two-play.com/plugins/toob#spectrumResponse";
|
||||
|
||||
const PLOT_WIDTH = StandardItemSize.width*3-16;
|
||||
const PLOT_HEIGHT = StandardItemSize.height-12;
|
||||
|
||||
import SvgPathBuilder from './SvgPathBuilder'
|
||||
|
||||
const SPECTRUM_RESPONSE_URI = "http://two-play.com/plugins/toob#spectrumResponse";
|
||||
const SPECTRUM_ENABLE_URI = "http://two-play.com/plugins/toob#spectrumEnable";
|
||||
|
||||
const PLOT_WIDTH = StandardItemSize.width * 3 - 16;
|
||||
const PLOT_HEIGHT = StandardItemSize.height - 12;
|
||||
|
||||
const styles = (theme: Theme) => createStyles({
|
||||
frame: {
|
||||
width: PLOT_WIDTH, height: PLOT_HEIGHT, background: "#444",
|
||||
width: PLOT_WIDTH, height: PLOT_HEIGHT, background: "#333",
|
||||
borderRadius: 6,
|
||||
marginTop: 12, marginLeft: 8, marginRight: 8,
|
||||
overflow: "hidden"
|
||||
},
|
||||
frameShadow: {
|
||||
width: PLOT_WIDTH, height: PLOT_HEIGHT,
|
||||
borderRadius: 6,
|
||||
boxShadow: "1px 4px 8px #000 inset"
|
||||
},
|
||||
});
|
||||
@@ -51,6 +59,7 @@ interface ToobSpectrumResponseProps extends WithStyles<typeof styles> {
|
||||
}
|
||||
interface ToobSpectrumResponseState {
|
||||
path: string;
|
||||
holdPath: string;
|
||||
minF: number;
|
||||
maxF: number;
|
||||
}
|
||||
@@ -72,9 +81,8 @@ const ToobSpectrumResponseView =
|
||||
let minF = 60;
|
||||
let maxF = 18000;
|
||||
|
||||
let plugin = this.model.pedalBoard.get()?.maybeGetItem(this.props.instanceId);
|
||||
if (plugin)
|
||||
{
|
||||
let plugin = this.model.pedalboard.get()?.maybeGetItem(this.props.instanceId);
|
||||
if (plugin) {
|
||||
minF = plugin.getControlValue("minF");
|
||||
maxF = plugin.getControlValue("maxF");
|
||||
}
|
||||
@@ -82,62 +90,59 @@ const ToobSpectrumResponseView =
|
||||
|
||||
this.state = {
|
||||
path: "",
|
||||
holdPath: "",
|
||||
minF: minF,
|
||||
maxF: maxF
|
||||
};
|
||||
|
||||
this.onPedalBoardChanged = this.onPedalBoardChanged.bind(this);
|
||||
this.onPedalboardChanged = this.onPedalboardChanged.bind(this);
|
||||
this.onStateChanged = this.onStateChanged.bind(this);
|
||||
}
|
||||
|
||||
onStateChanged()
|
||||
{
|
||||
if (this.model.state.get() === State.Ready)
|
||||
{
|
||||
onStateChanged() {
|
||||
if (this.model.state.get() === State.Ready) {
|
||||
this.requestDeferred = false;
|
||||
this.requestOutstanding = false;
|
||||
|
||||
let plugin = this.model.pedalBoard.get()?.maybeGetItem(this.props.instanceId);
|
||||
if (plugin)
|
||||
{
|
||||
let plugin = this.model.pedalboard.get()?.maybeGetItem(this.props.instanceId);
|
||||
if (plugin) {
|
||||
let minF = plugin.getControlValue("minF");
|
||||
let maxF = plugin.getControlValue("maxF");
|
||||
this.setState({minF: minF, maxF: maxF});
|
||||
this.setState({ minF: minF, maxF: maxF });
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
this.isReady = this.model.state.get() === State.Ready;
|
||||
|
||||
this.maybeStartClock(); // after a reconnect.
|
||||
this.maybeStartMonitoring(); // after a reconnect.
|
||||
}
|
||||
onPedalBoardChanged()
|
||||
{
|
||||
this.maybeStartClock();
|
||||
let plugin = this.model.pedalBoard.get()?.maybeGetItem(this.props.instanceId);
|
||||
if (plugin)
|
||||
{
|
||||
onPedalboardChanged() {
|
||||
// rebind our monitoring hooks.
|
||||
this.maybeStartMonitoring(false);
|
||||
this.maybeStartMonitoring(true);
|
||||
|
||||
let plugin = this.model.pedalboard.get()?.maybeGetItem(this.props.instanceId);
|
||||
if (plugin) {
|
||||
let minF = plugin.getControlValue("minF");
|
||||
let maxF = plugin.getControlValue("maxF");
|
||||
this.setState({minF: minF, maxF: maxF});
|
||||
this.setState({ minF: minF, maxF: maxF });
|
||||
}
|
||||
}
|
||||
|
||||
mounted: boolean = false;
|
||||
isReady: boolean = false;
|
||||
componentDidMount()
|
||||
{
|
||||
componentDidMount() {
|
||||
this.model.state.addOnChangedHandler(this.onStateChanged);
|
||||
this.model.pedalBoard.addOnChangedHandler(this.onPedalBoardChanged);
|
||||
this.model.pedalboard.addOnChangedHandler(this.onPedalboardChanged);
|
||||
this.mounted = true;
|
||||
this.isReady = this.model.state.get() === State.Ready;
|
||||
this.maybeStartClock();
|
||||
this.maybeStartMonitoring();
|
||||
}
|
||||
componentWillUnmount()
|
||||
{
|
||||
componentWillUnmount() {
|
||||
this.mounted = false;
|
||||
this.maybeStartClock();
|
||||
this.maybeStartMonitoring();
|
||||
this.model.state.removeOnChangedHandler(this.onStateChanged);
|
||||
this.model.pedalBoard.removeOnChangedHandler(this.onPedalBoardChanged);
|
||||
this.model.pedalboard.removeOnChangedHandler(this.onPedalboardChanged);
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
@@ -147,77 +152,50 @@ const ToobSpectrumResponseView =
|
||||
|
||||
// Size of the SVG element.
|
||||
xMin: number = 0;
|
||||
xMax: number = PLOT_WIDTH+4;
|
||||
xMax: number = PLOT_WIDTH + 4;
|
||||
yMin: number = 0;
|
||||
yMax: number = PLOT_HEIGHT;
|
||||
|
||||
onSpectrumResponseUpdated(svgPath: string) {
|
||||
this.setState({path: svgPath});
|
||||
onSpectrumResponseUpdated(svgPath: string, holdSvgPath: string) {
|
||||
this.setState({ path: svgPath, holdPath: holdSvgPath });
|
||||
|
||||
}
|
||||
|
||||
isTicking : boolean = false;
|
||||
hClock?: NodeJS.Timeout;
|
||||
hAtomOutput?: ListenHandle;
|
||||
private isMonitoring: boolean = false;
|
||||
private hClock?: NodeJS.Timeout;
|
||||
private hAtomOutput?: ListenHandle;
|
||||
|
||||
maybeStartClock() {
|
||||
let shouldTick = this.isReady && this.mounted;
|
||||
private maybeStartMonitoring(wantsMonitoring: boolean = true) {
|
||||
let shouldMonitor = this.isReady && this.mounted && wantsMonitoring;
|
||||
|
||||
if (shouldTick !== this.isTicking)
|
||||
{
|
||||
this.isTicking = shouldTick;
|
||||
if (shouldTick)
|
||||
{
|
||||
this.hAtomOutput = this.model.listenForAtomOutput(this.props.instanceId,
|
||||
(instanceId,atomOutput)=> {
|
||||
this.onSpectrumResponseUpdated(atomOutput.value as string);
|
||||
if (this.requestDeferred) {
|
||||
Utility.delay(30) // take breath
|
||||
.then(
|
||||
() => {
|
||||
this.requestOutstanding = false;
|
||||
this.requestDeferred = false;
|
||||
this.requestSpectrum();
|
||||
}
|
||||
|
||||
);
|
||||
} else {
|
||||
this.requestOutstanding = false;
|
||||
if (shouldMonitor !== this.isMonitoring) {
|
||||
this.isMonitoring = shouldMonitor;
|
||||
if (shouldMonitor) {
|
||||
this.hAtomOutput = this.model.monitorPatchProperty(
|
||||
this.props.instanceId,
|
||||
SPECTRUM_RESPONSE_URI,
|
||||
(instanceId, propertyUri, json) => {
|
||||
if (propertyUri === SPECTRUM_RESPONSE_URI && json.otype_ === "Tuple") {
|
||||
let values = json.value as string[];
|
||||
this.onSpectrumResponseUpdated(values[0], values[1]);
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
this.hClock = setInterval(()=> {
|
||||
this.requestSpectrum();
|
||||
},
|
||||
1000/15);
|
||||
}
|
||||
);
|
||||
this.model.setPatchProperty(this.props.instanceId, SPECTRUM_ENABLE_URI, true)
|
||||
.catch((error)=> {});
|
||||
} else {
|
||||
if (this.hAtomOutput)
|
||||
{
|
||||
this.model.cancelListenForAtomOutput(this.hAtomOutput);
|
||||
|
||||
this.model.setPatchProperty(this.props.instanceId, SPECTRUM_ENABLE_URI, false)
|
||||
.catch((error)=> {}); // e.g. plugin not found.
|
||||
|
||||
|
||||
|
||||
if (this.hAtomOutput) {
|
||||
this.model.cancelMonitorPatchProperty(this.hAtomOutput);
|
||||
this.hAtomOutput = undefined;
|
||||
}
|
||||
if (this.hClock)
|
||||
{
|
||||
clearInterval(this.hClock);
|
||||
this.hClock = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
requestSpectrum() {
|
||||
if (this.requestOutstanding) { // throttling.
|
||||
this.requestDeferred = true;
|
||||
return;
|
||||
}
|
||||
this.requestOutstanding = true;
|
||||
this.model.getLv2Parameter<string>(this.props.instanceId, SPECTRUM_RESPONSE_VECTOR_URI)
|
||||
.then((data) => {
|
||||
}).catch(error => {
|
||||
// assume the connection was lost. We'll get saved by a reconnect.
|
||||
});
|
||||
}
|
||||
|
||||
numPoints = 200;
|
||||
@@ -228,22 +206,21 @@ const ToobSpectrumResponseView =
|
||||
logMaxF = Math.log(this.maxF);
|
||||
|
||||
toX(f: number): number {
|
||||
let width = PLOT_WIDTH-8;
|
||||
return (Math.log(f)-this.logMinF)*width/(this.logMaxF-this.logMinF);
|
||||
let width = PLOT_WIDTH - 8;
|
||||
return (Math.log(f) - this.logMinF) * width / (this.logMaxF - this.logMinF);
|
||||
}
|
||||
grid(): React.ReactNode[] {
|
||||
let result: React.ReactNode[] = [];
|
||||
let width = PLOT_WIDTH-8;
|
||||
let height = PLOT_HEIGHT-8;
|
||||
|
||||
for (let db = -20; db >= -100; db -= 20)
|
||||
{
|
||||
let y = height*db/-100;
|
||||
result.push(
|
||||
(
|
||||
<line x1={0} y1={y} x2={width} y2={y} key={"db" + db} />
|
||||
)
|
||||
);
|
||||
private minorGrid(): string {
|
||||
|
||||
let ss = new SvgPathBuilder();
|
||||
|
||||
let width = PLOT_WIDTH;
|
||||
let height = PLOT_HEIGHT;
|
||||
|
||||
for (let db = -20; db >= -100; db -= 20) {
|
||||
let y = height * db / -100;
|
||||
ss.moveTo(0,y);
|
||||
ss.lineTo(width,y);
|
||||
}
|
||||
|
||||
let minF = this.state.minF;
|
||||
@@ -252,54 +229,86 @@ const ToobSpectrumResponseView =
|
||||
this.maxF = maxF;
|
||||
this.logMinF = Math.log(this.minF);
|
||||
this.logMaxF = Math.log(this.maxF);
|
||||
|
||||
for (let decade = 10; decade < 100000; decade *= 10)
|
||||
{
|
||||
for (let minorTick = 1; minorTick <= 5; ++ minorTick)
|
||||
{
|
||||
let f = decade*minorTick;
|
||||
if (f > minF && f < maxF)
|
||||
{
|
||||
|
||||
for (let decade = 10; decade < 100000; decade *= 10) {
|
||||
for (let minorTick = 1; minorTick <= 5; ++minorTick) {
|
||||
let f = decade * minorTick;
|
||||
if (f > minF && f < maxF) {
|
||||
let x = this.toX(f);
|
||||
if (minorTick === 1)
|
||||
{
|
||||
result.push(
|
||||
(
|
||||
<line x1={x} y1={0} x2={x} y2={height} key={"hgrid"+f} strokeWidth={1}/>
|
||||
)
|
||||
);
|
||||
if (minorTick === 1) {
|
||||
ss.moveTo(x,0);
|
||||
ss.lineTo(x,height);
|
||||
} else {
|
||||
result.push(
|
||||
(
|
||||
<line x1={x} y1={0} x2={x} y2={height} key={"hgrid"+f} />
|
||||
)
|
||||
);
|
||||
ss.moveTo(x,0);
|
||||
ss.lineTo(x,height);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return ss.toString();
|
||||
}
|
||||
|
||||
private majorGrid(): string {
|
||||
|
||||
let ss = new SvgPathBuilder();
|
||||
|
||||
let height = PLOT_HEIGHT;
|
||||
|
||||
let minF = this.state.minF;
|
||||
let maxF = this.state.maxF;
|
||||
this.minF = minF;
|
||||
this.maxF = maxF;
|
||||
this.logMinF = Math.log(this.minF);
|
||||
this.logMaxF = Math.log(this.maxF);
|
||||
|
||||
for (let decade = 10; decade < 100000; decade *= 10) {
|
||||
if (decade > minF && decade < maxF)
|
||||
{
|
||||
let x = this.toX(decade);
|
||||
ss.moveTo(x,0);
|
||||
ss.lineTo(x,height);
|
||||
}
|
||||
}
|
||||
return ss.toString();
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
let classes = this.props.classes;
|
||||
return (
|
||||
<div className={classes.frame} style={{position: "relative"}} >
|
||||
<div style={{position: "absolute", left: 4, top: 4}}>
|
||||
<svg width={PLOT_WIDTH-8} height={PLOT_HEIGHT-8} stroke="#888" strokeWidth="0.5" opacity="1"
|
||||
>
|
||||
{this.grid()}
|
||||
<div className={classes.frame} style={{ position: "relative" }} >
|
||||
{/* <div style={{ position: "absolute", left: 0, top: 0 }}>
|
||||
<svg fill="#660" width={PLOT_WIDTH } height={PLOT_HEIGHT} preserveAspectRatio='none'
|
||||
viewBox={"0 0 " + this.numPoints + " " + 1000} stroke="none" strokeWidth="2.5" opacity="1.0"
|
||||
>
|
||||
<path d={this.state.holdPath} />
|
||||
</svg>
|
||||
</div> */}
|
||||
|
||||
<div style={{ position: "absolute", left: 0, top: 0 }}>
|
||||
<svg fill="#0C4" width={PLOT_WIDTH } height={PLOT_HEIGHT } preserveAspectRatio='none'
|
||||
viewBox={"0 0 " + this.numPoints + " " + 1000} stroke="none" strokeWidth="2.5" opacity="1.0"
|
||||
>
|
||||
<path d={this.state.path} />
|
||||
</svg>
|
||||
</div>
|
||||
<div style={{position: "absolute", left: 4, top: 4}}>
|
||||
<svg width={PLOT_WIDTH-8} height={PLOT_HEIGHT-8} preserveAspectRatio='none' viewBox={"0 0 " + this.numPoints + " " + 1000} stroke="none" fill="#0FC" strokeWidth="2.5" opacity="0.6"
|
||||
>
|
||||
<path d={this.state.path} />
|
||||
<div style={{ position: "absolute", left: 0, top: 0 }}>
|
||||
<svg width={PLOT_WIDTH } height={PLOT_HEIGHT} stroke="#FFF" strokeWidth="0.9" opacity="0.3"
|
||||
>
|
||||
<path d={this.minorGrid()} />
|
||||
</svg>
|
||||
</div>
|
||||
<div style={{ position: "absolute", left: 0, top: 0 }}>
|
||||
<svg width={PLOT_WIDTH} height={PLOT_HEIGHT} stroke="#FFF" strokeWidth="0.9" opacity="0.5"
|
||||
>
|
||||
<path d={this.majorGrid()} />
|
||||
</svg>
|
||||
</div>
|
||||
<div className={classes.frameShadow} style={{ position: "absolute", left: 0, top: 0, right: 0, bottom: 0 }}>
|
||||
</div>
|
||||
|
||||
|
||||
</div>);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ import withStyles from '@mui/styles/withStyles';
|
||||
|
||||
import IControlViewFactory from './IControlViewFactory';
|
||||
import { PiPedalModelFactory, PiPedalModel,ControlValueChangedHandle } from "./PiPedalModel";
|
||||
import { PedalBoardItem } from './PedalBoard';
|
||||
import { PedalboardItem } from './Pedalboard';
|
||||
import PluginControlView, { ControlGroup,ControlViewCustomization } from './PluginControlView';
|
||||
import ToobFrequencyResponseView from './ToobFrequencyResponseView';
|
||||
|
||||
@@ -37,7 +37,7 @@ const styles = (theme: Theme) => createStyles({
|
||||
|
||||
interface ToobToneStackProps extends WithStyles<typeof styles> {
|
||||
instanceId: number;
|
||||
item: PedalBoardItem;
|
||||
item: PedalboardItem;
|
||||
|
||||
}
|
||||
interface ToobToneStackState {
|
||||
@@ -117,8 +117,8 @@ const ToobToneStackView =
|
||||
class ToobToneStackViewFactory implements IControlViewFactory {
|
||||
uri: string = "http://two-play.com/plugins/toob-tone-stack";
|
||||
|
||||
Create(model: PiPedalModel, pedalBoardItem: PedalBoardItem): React.ReactNode {
|
||||
return (<ToobToneStackView instanceId={pedalBoardItem.instanceId} item={pedalBoardItem} />);
|
||||
Create(model: PiPedalModel, pedalboardItem: PedalboardItem): React.ReactNode {
|
||||
return (<ToobToneStackView instanceId={pedalboardItem.instanceId} item={pedalboardItem} />);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -128,7 +128,7 @@ const ToobWaveShapeView =
|
||||
data: []
|
||||
};
|
||||
|
||||
this.onPedalBoardChanged = this.onPedalBoardChanged.bind(this);
|
||||
this.onPedalboardChanged = this.onPedalboardChanged.bind(this);
|
||||
this.onStateChanged = this.onStateChanged.bind(this);
|
||||
this.onControlValueChanged = this.onControlValueChanged.bind(this);
|
||||
this.isReady = this.model.state.get() === State.Ready;
|
||||
@@ -147,7 +147,7 @@ const ToobWaveShapeView =
|
||||
}
|
||||
}
|
||||
}
|
||||
onPedalBoardChanged() {
|
||||
onPedalboardChanged() {
|
||||
this.updateWaveShape();
|
||||
}
|
||||
_valueChangedHandle?: ControlValueChangedHandle;
|
||||
@@ -158,7 +158,7 @@ const ToobWaveShapeView =
|
||||
componentDidMount() {
|
||||
this.mounted = true;
|
||||
this.model.state.addOnChangedHandler(this.onStateChanged);
|
||||
this.model.pedalBoard.addOnChangedHandler(this.onPedalBoardChanged);
|
||||
this.model.pedalboard.addOnChangedHandler(this.onPedalboardChanged);
|
||||
this._valueChangedHandle = this.model.addControlValueChangeListener(
|
||||
this.props.instanceId,
|
||||
this.onControlValueChanged);
|
||||
@@ -180,7 +180,7 @@ const ToobWaveShapeView =
|
||||
this._valueChangedHandle = undefined;
|
||||
}
|
||||
this.model.state.removeOnChangedHandler(this.onStateChanged);
|
||||
this.model.pedalBoard.removeOnChangedHandler(this.onPedalBoardChanged);
|
||||
this.model.pedalboard.removeOnChangedHandler(this.onPedalboardChanged);
|
||||
}
|
||||
|
||||
onControlValueChanged(key: string, value: number) {
|
||||
@@ -230,21 +230,27 @@ const ToobWaveShapeView =
|
||||
return;
|
||||
}
|
||||
this.requestOutstanding = true;
|
||||
this.model.getLv2Parameter<number[]>(this.props.instanceId, WAVESHAPE_VECTOR_URI + this.props.controlNumber)
|
||||
.then((data) => {
|
||||
this.onWaveShapeUpdated(data);
|
||||
if (this.requestDeferred) {
|
||||
Utility.delay(10) // take breath
|
||||
.then(
|
||||
() => {
|
||||
this.requestOutstanding = false;
|
||||
this.requestDeferred = false;
|
||||
this.updateWaveShape();
|
||||
}
|
||||
this.model.getPatchProperty<any>(this.props.instanceId, WAVESHAPE_VECTOR_URI + this.props.controlNumber)
|
||||
.then((json) => {
|
||||
if (!this.mounted) return;
|
||||
|
||||
if (json.otype_ === "Vector" && json.vtype_ === "Float")
|
||||
{
|
||||
let data = json.value;
|
||||
this.onWaveShapeUpdated(data);
|
||||
if (this.requestDeferred) {
|
||||
Utility.delay(10) // take breath
|
||||
.then(
|
||||
() => {
|
||||
this.requestOutstanding = false;
|
||||
this.requestDeferred = false;
|
||||
this.updateWaveShape();
|
||||
}
|
||||
|
||||
);
|
||||
} else {
|
||||
this.requestOutstanding = false;
|
||||
);
|
||||
} else {
|
||||
this.requestOutstanding = false;
|
||||
}
|
||||
}
|
||||
}).catch(error => {
|
||||
// assume the connection was lost. We'll get saved by a reconnect.
|
||||
|
||||
@@ -170,8 +170,8 @@ const ZoomedDial = withStyles(styles, { withTheme: true })(
|
||||
let uiControl = this.props.controlInfo.uiControl;
|
||||
let instanceId = this.props.controlInfo.instanceId;
|
||||
if (instanceId === -1) return 0;
|
||||
let pedalBoardItem = this.model.pedalBoard.get()?.getItem(instanceId);
|
||||
let value: number = pedalBoardItem?.getControlValue(uiControl.symbol) ?? 0;
|
||||
let pedalboardItem = this.model.pedalboard.get()?.getItem(instanceId);
|
||||
let value: number = pedalboardItem?.getControlValue(uiControl.symbol) ?? 0;
|
||||
this.defaultValue = value;
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -94,8 +94,8 @@ const ZoomedUiControl = withStyles(styles, { withTheme: true })(
|
||||
let uiControl = this.props.controlInfo.uiControl;
|
||||
let instanceId = this.props.controlInfo.instanceId;
|
||||
if (instanceId === -1) return 0;
|
||||
let pedalBoardItem = this.model.pedalBoard.get()?.getItem(instanceId);
|
||||
let value: number = pedalBoardItem?.getControlValue(uiControl.symbol) ?? 0;
|
||||
let pedalboardItem = this.model.pedalboard.get()?.getItem(instanceId);
|
||||
let value: number = pedalboardItem?.getControlValue(uiControl.symbol) ?? 0;
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -105,7 +105,7 @@ const ZoomedUiControl = withStyles(styles, { withTheme: true })(
|
||||
let v = Number.parseFloat(val.toString());
|
||||
this.setState({ value: v });
|
||||
if (this.props.controlInfo) {
|
||||
this.model.setPedalBoardControlValue(
|
||||
this.model.setPedalboardControl(
|
||||
this.props.controlInfo.instanceId,
|
||||
this.props.controlInfo.uiControl.symbol,
|
||||
v);
|
||||
@@ -116,7 +116,7 @@ const ZoomedUiControl = withStyles(styles, { withTheme: true })(
|
||||
let v = checked ? 1: 0;
|
||||
this.setState({ value: v });
|
||||
if (this.props.controlInfo) {
|
||||
this.model.setPedalBoardControlValue(
|
||||
this.model.setPedalboardControl(
|
||||
this.props.controlInfo.instanceId,
|
||||
this.props.controlInfo.uiControl.symbol,
|
||||
v);
|
||||
@@ -247,7 +247,7 @@ const ZoomedUiControl = withStyles(styles, { withTheme: true })(
|
||||
onSetValue={(v) => {
|
||||
this.setState({ value: v });
|
||||
if (this.props.controlInfo) {
|
||||
this.model.setPedalBoardControlValue(
|
||||
this.model.setPedalboardControl(
|
||||
this.props.controlInfo.instanceId,
|
||||
this.props.controlInfo.uiControl.symbol,
|
||||
v);
|
||||
|
||||
+2
-2
@@ -31,8 +31,8 @@ src/MidiBinding.tsx
|
||||
src/PiPedalError.tsx
|
||||
src/IControlViewFactory.tsx
|
||||
src/Lv2Plugin.tsx
|
||||
src/PedalBoard.tsx
|
||||
src/PedalBoardView.tsx
|
||||
src/Pedalboard.tsx
|
||||
src/PedalboardView.tsx
|
||||
src/PresetDialog.tsx
|
||||
src/AppThemed.tsx
|
||||
src/ZoomedDial.tsx
|
||||
|
||||
Reference in New Issue
Block a user