Side-chains
This commit is contained in:
@@ -47,6 +47,7 @@ export class Port implements Deserializable<Port> {
|
||||
this.scale_points = ScalePoint.deserialize_array(input.scale_points);
|
||||
this.is_input = input.is_input;
|
||||
this.is_output = input.is_output;
|
||||
this.is_sidechain = input.is_sidechain;
|
||||
this.is_control_port = input.is_control_port;
|
||||
this.is_audio_port = input.is_audio_port;
|
||||
this.is_atom_port = input.is_atom_port;
|
||||
@@ -80,6 +81,7 @@ export class Port implements Deserializable<Port> {
|
||||
is_output: boolean = false
|
||||
is_control_port: boolean = false;
|
||||
is_audio_port: boolean = false;
|
||||
is_sidechain: boolean = false;
|
||||
is_atom_port: boolean = false;
|
||||
is_valid: boolean = false;
|
||||
supports_midi: boolean = false;
|
||||
@@ -92,9 +94,11 @@ export class Port implements Deserializable<Port> {
|
||||
|
||||
export class PortGroup {
|
||||
deserialize(input: any): PortGroup {
|
||||
this.isA = input.isA;
|
||||
this.uri = input.uri;
|
||||
this.symbol = input.symbol;
|
||||
this.name = input.name;
|
||||
this.sideChainof = input.sideChainOf;
|
||||
this.parent_group = input.parent_group;
|
||||
this.program_list_id = input.program_list_id ?? -1;
|
||||
|
||||
@@ -108,9 +112,12 @@ export class PortGroup {
|
||||
return result;
|
||||
}
|
||||
|
||||
isA: string[] = [];
|
||||
uri: string = "";
|
||||
symbol: string = "";
|
||||
name: string = "";
|
||||
sideChainof: string = "";
|
||||
|
||||
parent_group: string = "";
|
||||
program_list_id: number = -1;
|
||||
};
|
||||
@@ -967,6 +974,8 @@ export class UiPlugin implements Deserializable<UiPlugin> {
|
||||
this.author_name = input.author_name;
|
||||
this.author_homepage = input.author_homepage;
|
||||
this.audio_inputs = input.audio_inputs;
|
||||
this.audio_side_chain_inputs = input.audio_side_chain_inputs ?? 0;
|
||||
this.audio_side_chain_title = input.audio_side_chain_title ?? "";
|
||||
this.audio_outputs = input.audio_outputs;
|
||||
this.has_midi_input = input.has_midi_input;
|
||||
this.has_midi_output = input.has_midi_output;
|
||||
@@ -1057,7 +1066,9 @@ export class UiPlugin implements Deserializable<UiPlugin> {
|
||||
author_name: string = "";
|
||||
author_homepage: string = "";
|
||||
audio_inputs: number = 0;
|
||||
audio_side_chain_inputs: number = 0;
|
||||
audio_outputs: number = 0;
|
||||
audio_side_chain_title: string = "";
|
||||
has_midi_input: number = 0;
|
||||
has_midi_output: number = 0;
|
||||
description: string = "";
|
||||
@@ -1084,6 +1095,7 @@ export function makeSplitUiPlugin(): UiPlugin {
|
||||
author_name: "",
|
||||
author_homepage: "",
|
||||
audio_inputs: 1,
|
||||
audio_side_chain_inputs: 0,
|
||||
audio_outputs: 1,
|
||||
has_midi_input: 0,
|
||||
has_midi_output: 0,
|
||||
|
||||
@@ -81,6 +81,7 @@ export class PedalboardItem implements Deserializable<PedalboardItem> {
|
||||
this.pathProperties = input.pathProperties;
|
||||
this.useModUi = input.useModUi ?? false;
|
||||
this.iconColor = input.iconColor??"";
|
||||
this.sideChainInputId = input.sideChainInputId ?? -1;
|
||||
|
||||
return this;
|
||||
}
|
||||
@@ -217,6 +218,7 @@ export class PedalboardItem implements Deserializable<PedalboardItem> {
|
||||
pathProperties: {[Name: string]: string} = {};
|
||||
useModUi: boolean = false; // true if this item should use the mod-ui.
|
||||
iconColor: string = "";
|
||||
sideChainInputId: number = -1; // -1 means no sidechain input.
|
||||
};
|
||||
|
||||
export class SnapshotValue {
|
||||
|
||||
@@ -550,19 +550,16 @@ export class PiPedalModel //implements PiPedalModel
|
||||
);
|
||||
zoomedUiControl: ObservableProperty<ZoomedControlInfo | undefined> = new ObservableProperty<ZoomedControlInfo | undefined>(undefined);
|
||||
|
||||
uiPluginsByUri: Map<string, UiPlugin> = new Map<string, UiPlugin>();
|
||||
|
||||
svgImgUrl(svgImage: string): string {
|
||||
//return this.varServerUrl + "img/" + svgImage;
|
||||
// return this.varServerUrl + "img/" + svgImage;
|
||||
return "img/" + svgImage;
|
||||
}
|
||||
|
||||
|
||||
getUiPlugin(uri: string): UiPlugin | null {
|
||||
let plugins: UiPlugin[] = this.ui_plugins.get();
|
||||
|
||||
for (let plugin of plugins) {
|
||||
if (plugin.uri === uri) return plugin;
|
||||
}
|
||||
return null;
|
||||
return this.uiPluginsByUri.get(uri) ?? null;
|
||||
}
|
||||
|
||||
androidHost?: AndroidHostInterface;
|
||||
@@ -1210,6 +1207,11 @@ export class PiPedalModel //implements PiPedalModel
|
||||
this.ui_plugins.set(
|
||||
UiPlugin.deserialize_array(await this.getWebSocket().request<any>("plugins"))
|
||||
);
|
||||
// index ui plugins.
|
||||
this.uiPluginsByUri = new Map<string, UiPlugin>();
|
||||
for (let i of this.ui_plugins.get()) {
|
||||
this.uiPluginsByUri.set(i.uri, i);
|
||||
}
|
||||
this.setModelPedalboard(
|
||||
new Pedalboard().deserialize(
|
||||
await this.getWebSocket().request<Pedalboard>("currentPedalboard")
|
||||
@@ -3552,6 +3554,20 @@ export class PiPedalModel //implements PiPedalModel
|
||||
copyPresetsToBank(bankInstanceId: number, presets: number[]): Promise<number> {
|
||||
return nullCast(this.webSocket).request<number>("copyPresetsToBank", {bankInstanceId: bankInstanceId, presets: presets});
|
||||
}
|
||||
setPedalboardSideChainInput(instanceId: number, sideChainInputId: number): void {
|
||||
let pedalboard = this.pedalboard.get().clone();
|
||||
let pedalboardItem = pedalboard.getItem(instanceId);
|
||||
if (!pedalboardItem)
|
||||
{
|
||||
return;
|
||||
}
|
||||
pedalboardItem.sideChainInputId = sideChainInputId;
|
||||
pedalboardItem.instanceId = ++pedalboard.nextInstanceId;
|
||||
pedalboard.selectedPlugin = pedalboardItem.instanceId;
|
||||
this.setModelPedalboard(pedalboard);
|
||||
this.updateServerPedalboard();
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
let instance: PiPedalModel | undefined = undefined;
|
||||
|
||||
@@ -37,6 +37,7 @@ import {
|
||||
} from './Pedalboard';
|
||||
import PluginControl from './PluginControl';
|
||||
import ResizeResponsiveComponent from './ResizeResponsiveComponent';
|
||||
import SideChainSelectControl from './SideChainSelectControl';
|
||||
import VuMeter from './VuMeter';
|
||||
import { nullCast } from './Utility'
|
||||
import { PiPedalStateError } from './PiPedalError';
|
||||
@@ -66,6 +67,11 @@ export interface ICustomizationHost {
|
||||
isLandscapeGrid(): boolean;
|
||||
}
|
||||
|
||||
interface SideChainSelectItem {
|
||||
instanceId: number;
|
||||
title: string;
|
||||
}
|
||||
|
||||
function makeIoPluginInfo(name: string, uri: string): UiPlugin {
|
||||
let result = new UiPlugin();
|
||||
result.name = name;
|
||||
@@ -371,7 +377,7 @@ type PluginControlViewState = {
|
||||
|
||||
const PluginControlView =
|
||||
withTheme(withStyles(
|
||||
class extends ResizeResponsiveComponent<PluginControlViewProps, PluginControlViewState> implements ICustomizationHost {
|
||||
class extends ResizeResponsiveComponent<PluginControlViewProps, PluginControlViewState> {
|
||||
model: PiPedalModel;
|
||||
|
||||
constructor(props: PluginControlViewProps) {
|
||||
@@ -553,6 +559,68 @@ const PluginControlView =
|
||||
}
|
||||
}
|
||||
|
||||
private getSidechainSelectItems(): SideChainSelectItem[] {
|
||||
let myInstanceId = this.props.item.instanceId;
|
||||
|
||||
let items: SideChainSelectItem[] = [];
|
||||
items.push({ instanceId: -1, title: "None" });
|
||||
items.push({ instanceId: -2, title: "Input" });
|
||||
|
||||
let pedalboard = this.model.pedalboard.get();
|
||||
if (!pedalboard) return items;
|
||||
|
||||
let it = pedalboard.itemsGenerator();
|
||||
|
||||
let found = false;
|
||||
while (true) {
|
||||
let v = it.next();
|
||||
if (v.done) {
|
||||
break;
|
||||
}
|
||||
let pedalboardItem = v.value;
|
||||
if (pedalboardItem.isSplit()) {
|
||||
continue;
|
||||
}
|
||||
if (pedalboardItem.instanceId === myInstanceId) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
if (pedalboardItem.uri.length === 0) {
|
||||
continue;
|
||||
}
|
||||
let pluginInfo = this.model.getUiPlugin(pedalboardItem.uri);
|
||||
if (!pluginInfo) continue;
|
||||
let name = pluginInfo.name;
|
||||
if (pedalboardItem.title.length !== 0) {
|
||||
name = pedalboardItem.title;
|
||||
}
|
||||
items.push({ instanceId: pedalboardItem.instanceId, title: name });
|
||||
}
|
||||
if (!found) {
|
||||
return [{ instanceId: -1, title: "None" }];
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
private makeSideChainSelect(uiPlugin: UiPlugin) {
|
||||
let items = this.getSidechainSelectItems();
|
||||
let selectedInstanceId = this.props.item.sideChainInputId;
|
||||
let title = uiPlugin.audio_side_chain_title ? uiPlugin.audio_side_chain_title : "Side chain";
|
||||
|
||||
return (
|
||||
<SideChainSelectControl
|
||||
title={title}
|
||||
selectItems={items}
|
||||
selectedInstanceId={selectedInstanceId}
|
||||
onChanged={(instanceId: number) => {
|
||||
this.model.setPedalboardSideChainInput(this.props.item.instanceId, instanceId);
|
||||
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
isLandscapeGrid(): boolean {
|
||||
return this.state.landscapeGrid;
|
||||
}
|
||||
@@ -575,7 +643,7 @@ const PluginControlView =
|
||||
}
|
||||
return (
|
||||
<div key={key} className={!isLandscapeGrid ? classes.portGroup : classes.portGroupLandscape}
|
||||
style={{ borderWidth: (controlGroup.name === "" ? 0: undefined) }}
|
||||
style={{ borderWidth: (controlGroup.name === "" ? 0 : undefined) }}
|
||||
>
|
||||
{controlGroup.name !== "" && (
|
||||
<div className={classes.portGroupTitle}>
|
||||
@@ -711,6 +779,11 @@ const PluginControlView =
|
||||
);
|
||||
}
|
||||
}
|
||||
if (plugin.audio_side_chain_inputs !== 0) {
|
||||
|
||||
result.push(this.makeSideChainSelect(plugin));
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
import React, { Component } from 'react';
|
||||
import { Theme } from '@mui/material/styles';
|
||||
import WithStyles from './WithStyles';
|
||||
import {createStyles} from './WithStyles';
|
||||
import { createStyles } from './WithStyles';
|
||||
|
||||
import { withStyles } from "tss-react/mui";
|
||||
import { UiControl } from './Lv2Plugin';
|
||||
@@ -47,8 +47,7 @@ const defaultVuColors: VuColor[] = [
|
||||
|
||||
function getVuColor(vuColors: VuColor[], levelDb: number): string {
|
||||
let ix = 0;
|
||||
for (let i = 0; i < vuColors.length; ++i)
|
||||
{
|
||||
for (let i = 0; i < vuColors.length; ++i) {
|
||||
let c = vuColors[i];
|
||||
if (levelDb > c.minDb && levelDb <= c.maxDb) {
|
||||
ix = i;
|
||||
@@ -122,18 +121,18 @@ const styles = (theme: Theme) => createStyles({
|
||||
}),
|
||||
|
||||
titleSection: css({
|
||||
flex: "0 0 auto", alignSelf:"stretch", marginBottom: 8, marginLeft: 0, marginRight: 0
|
||||
flex: "0 0 auto", alignSelf: "stretch", marginBottom: 8, marginLeft: 0, marginRight: 0
|
||||
}),
|
||||
|
||||
midSection: css({
|
||||
flex: "1 1 1", display: "flex",flexFlow: "column nowrap",alignContent: "center",justifyContent: "center"
|
||||
flex: "1 1 1", display: "flex", flexFlow: "column nowrap", alignContent: "center", justifyContent: "center"
|
||||
}),
|
||||
|
||||
editSection: css({
|
||||
flex: "0 0 28", position: "relative", width: 60, height: 28, minHeight: 28
|
||||
}),
|
||||
editSectionNoContent: css({
|
||||
flex: "0 0 28", position: "relative", width: 1, height: 28, minHeight: 28
|
||||
flex: "0 0 28", position: "relative", width: 1, height: 28, minHeight: 28
|
||||
})
|
||||
|
||||
});
|
||||
@@ -153,12 +152,12 @@ const PluginOutputControl =
|
||||
class extends Component<PluginOutputControlProps, PluginOutputControlState> {
|
||||
|
||||
private model: PiPedalModel;
|
||||
private vuRef: React.RefObject<HTMLDivElement|null>;
|
||||
private progressRef: React.RefObject<HTMLDivElement|null>;
|
||||
private dbVuRef: React.RefObject<HTMLDivElement|null>;
|
||||
private dbVuTelltaleRef: React.RefObject<HTMLDivElement|null>;
|
||||
private dbVuTextRef: React.RefObject<HTMLDivElement|null>;
|
||||
private lampRef: React.RefObject<HTMLDivElement|null>;
|
||||
private vuRef: React.RefObject<HTMLDivElement | null>;
|
||||
private progressRef: React.RefObject<HTMLDivElement | null>;
|
||||
private dbVuRef: React.RefObject<HTMLDivElement | null>;
|
||||
private dbVuTelltaleRef: React.RefObject<HTMLDivElement | null>;
|
||||
private dbVuTextRef: React.RefObject<HTMLDivElement | null>;
|
||||
private lampRef: React.RefObject<HTMLDivElement | null>;
|
||||
|
||||
|
||||
constructor(props: PluginOutputControlProps) {
|
||||
@@ -210,7 +209,7 @@ const PluginOutputControl =
|
||||
}
|
||||
}
|
||||
|
||||
private PROGRESS_WIDTH = 40-4;
|
||||
private PROGRESS_WIDTH = 40 - 4;
|
||||
private VU_HEIGHT = 60 - 4;
|
||||
private DB_VU_HEIGHT = 60 - 4;
|
||||
private animationHandle: number | undefined = undefined;
|
||||
@@ -240,26 +239,23 @@ const PluginOutputControl =
|
||||
}
|
||||
if (this.dbVuTextRef.current) {
|
||||
let text: string;
|
||||
if (this.dbVuTelltale <= this.props.uiControl.min_value)
|
||||
{
|
||||
if (this.dbVuTelltale <= this.props.uiControl.min_value) {
|
||||
text = "-";
|
||||
} else {
|
||||
if (Math.abs(this.dbVuTelltale) >= 99.5)
|
||||
{
|
||||
if (Math.abs(this.dbVuTelltale) >= 99.5) {
|
||||
text = Math.round(this.dbVuTelltale).toString();
|
||||
} else {
|
||||
text = this.dbVuTelltale.toFixed(1);
|
||||
}
|
||||
if (!text.startsWith("-")) {
|
||||
text = '+'+text;
|
||||
}
|
||||
text = '+' + text;
|
||||
}
|
||||
}
|
||||
if (this.lastDbText !== text)
|
||||
{
|
||||
if (this.lastDbText !== text) {
|
||||
this.lastDbText = text;
|
||||
this.dbVuTextRef.current.innerText = text;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.animationHandle = undefined;
|
||||
this.updateDbVuTelltale();
|
||||
}
|
||||
@@ -322,7 +318,7 @@ const PluginOutputControl =
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else if (this.vuRef.current) {
|
||||
let control = this.props.uiControl;
|
||||
let range = (value - control.min_value) / (control.max_value - control.min_value);
|
||||
@@ -389,8 +385,7 @@ const PluginOutputControl =
|
||||
if (value > control.max_value) {
|
||||
value = control.max_value;
|
||||
}
|
||||
if (value < control.min_value)
|
||||
{
|
||||
if (value < control.min_value) {
|
||||
value = control.min_value;
|
||||
}
|
||||
let y = (control.max_value - value) * this.DB_VU_HEIGHT / (control.max_value - control.min_value);
|
||||
@@ -439,13 +434,13 @@ const PluginOutputControl =
|
||||
} else if (control.isProgress()) {
|
||||
item_width = undefined;
|
||||
return (
|
||||
<div className={classes.controlFrame}
|
||||
<div className={classes.controlFrame}
|
||||
style={{ width: item_width }}>
|
||||
{/* TITLE SECTION */}
|
||||
<div className={classes.titleSection}
|
||||
style={{ width: "100%" }}>
|
||||
<div className={classes.titleSection}
|
||||
style={{ width: "100%" }}>
|
||||
<ControlTooltip uiControl={control}>
|
||||
<Typography variant="caption" display="block" style={{
|
||||
<Typography variant="caption" display="block" style={{
|
||||
width: "100%",
|
||||
textAlign: "center"
|
||||
}}> {control.name === "" ? "\u00A0" : control.name}</Typography>
|
||||
@@ -453,15 +448,18 @@ const PluginOutputControl =
|
||||
</div>
|
||||
{/* CONTROL SECTION */}
|
||||
|
||||
<div className={classes.midSection}
|
||||
<div className={classes.midSection}
|
||||
style={{ flex: "1 1 1", display: "flex", justifyContent: "center", alignItems: "start", flexFlow: "row nowrap" }}>
|
||||
<div style={{ width: this.PROGRESS_WIDTH+2, height: 12, marginLeft: 8, marginRight: 8, background: "#181818", }}>
|
||||
<div style={{ height: 8, width: this.PROGRESS_WIDTH, overflow: "hidden", position: "absolute",
|
||||
margin: "1px 1px 1px 1px", background: "#282828" }}>
|
||||
<div ref={this.progressRef} style={{ height: 10, width: this.PROGRESS_WIDTH, position: "absolute", marginTop: 0, background: "#0C0" }} />
|
||||
<div style={{ height: 10, width: this.PROGRESS_WIDTH, position: "absolute",
|
||||
<div style={{ width: this.PROGRESS_WIDTH + 2, height: 12, marginLeft: 8, marginRight: 8, background: "#181818", }}>
|
||||
<div style={{
|
||||
height: 8, width: this.PROGRESS_WIDTH, overflow: "hidden", position: "absolute",
|
||||
margin: "1px 1px 1px 1px", background: "#282828"
|
||||
}}>
|
||||
<div ref={this.progressRef} style={{ height: 10, width: this.PROGRESS_WIDTH, position: "absolute", marginTop: 0, background: "#0C0" }} />
|
||||
<div style={{
|
||||
height: 10, width: this.PROGRESS_WIDTH, position: "absolute",
|
||||
boxShadow: "inset 0px 2px 4px #000D", background: "transparent"
|
||||
}} />
|
||||
}} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -478,45 +476,48 @@ const PluginOutputControl =
|
||||
let vuColors = defaultVuColors;
|
||||
|
||||
return (
|
||||
<div className={classes.controlFrame}
|
||||
<div className={classes.controlFrame}
|
||||
style={{ width: item_width }}>
|
||||
{/* TITLE SECTION */}
|
||||
<div className={classes.titleSection}
|
||||
style={{ width: "100%" }}>
|
||||
<ControlTooltip uiControl={control}>
|
||||
<Typography variant="caption" display="block" style={{
|
||||
width: "100%",
|
||||
textAlign: "center"
|
||||
}}> {control.name === "" ? "\u00A0" : control.name}</Typography>
|
||||
</ControlTooltip>
|
||||
<div className={classes.titleSection}
|
||||
style={{ width: "100%" }}>
|
||||
<Typography variant="caption" display="block" style={{
|
||||
width: "100%",
|
||||
textAlign: "center"
|
||||
}}> {control.name === "" ? "\u00A0" : control.name}</Typography>
|
||||
</div>
|
||||
{/* CONTROL SECTION */}
|
||||
|
||||
<div className={classes.midSection}
|
||||
<div className={classes.midSection}
|
||||
style={{ flex: "1 1 1", display: "flex", justifyContent: "center", alignItems: "start", flexFlow: "row nowrap" }}>
|
||||
<div style={{ width: 8, height: this.DB_VU_HEIGHT + 4, background: "#000", }}>
|
||||
<div style={{ height: this.DB_VU_HEIGHT, width: 4, overflow: "hidden", position: "absolute", margin: 2 }}>
|
||||
<div style={{ width: 4, height: this.DB_VU_HEIGHT, position: "absolute", left: 0, top: 0 }}>
|
||||
{
|
||||
vuColors.map((vuColor,ix)=>{
|
||||
let top = Math.floor(this.dbVuMap(vuColor.maxDb));
|
||||
let bottom = Math.ceil(this.dbVuMap(vuColor.minDb))+1;
|
||||
<ControlTooltip uiControl={control}>
|
||||
|
||||
return (
|
||||
<div key={ix}
|
||||
style={{ position: "absolute", width: 4, height: (bottom-top),
|
||||
top: top, left:0, background: vuColor.color }} />
|
||||
);
|
||||
})
|
||||
}
|
||||
<div style={{ width: 8, height: this.DB_VU_HEIGHT + 4, background: "#000", }}>
|
||||
<div style={{ height: this.DB_VU_HEIGHT, width: 4, overflow: "hidden", position: "absolute", margin: 2 }}>
|
||||
<div style={{ width: 4, height: this.DB_VU_HEIGHT, position: "absolute", left: 0, top: 0 }}>
|
||||
{
|
||||
vuColors.map((vuColor, ix) => {
|
||||
let top = Math.floor(this.dbVuMap(vuColor.maxDb));
|
||||
let bottom = Math.ceil(this.dbVuMap(vuColor.minDb)) + 1;
|
||||
|
||||
return (
|
||||
<div key={ix}
|
||||
style={{
|
||||
position: "absolute", width: 4, height: (bottom - top),
|
||||
top: top, left: 0, background: vuColor.color
|
||||
}} />
|
||||
);
|
||||
})
|
||||
}
|
||||
</div>
|
||||
|
||||
<div ref={this.dbVuRef} style={{
|
||||
width: 4, position: "absolute", marginTop: 0, height: this.VU_HEIGHT, background: "#000"
|
||||
}} />
|
||||
<div ref={this.dbVuTelltaleRef} style={{ width: 4, position: "absolute", marginTop: 100, height: 3, background: "#C00" }} />
|
||||
</div>
|
||||
|
||||
<div ref={this.dbVuRef} style={{
|
||||
width: 4, position: "absolute", marginTop: 0, height: this.VU_HEIGHT, background: "#000"
|
||||
}} />
|
||||
<div ref={this.dbVuTelltaleRef} style={{ width: 4, position: "absolute", marginTop: 100, height: 3, background: "#C00" }} />
|
||||
</div>
|
||||
</div>
|
||||
</ControlTooltip>
|
||||
|
||||
</div>
|
||||
<div className={classes.editSection}>
|
||||
@@ -533,26 +534,28 @@ const PluginOutputControl =
|
||||
else if (control.isVu()) {
|
||||
item_width = undefined;
|
||||
return (
|
||||
<div className={classes.controlFrame} style={{ width: item_width}}>
|
||||
<div className={classes.controlFrame} style={{ width: item_width }}>
|
||||
{/* TITLE SECTION */}
|
||||
<div className={classes.titleSection}
|
||||
<div className={classes.titleSection}
|
||||
style={{ width: "100%" }}>
|
||||
<ControlTooltip uiControl={control}>
|
||||
<Typography noWrap display="block" variant="caption" style={{
|
||||
width: item_width,
|
||||
textAlign: "center"
|
||||
}}> {control.name === "" ? "\u00A0" : control.name}</Typography>
|
||||
</ControlTooltip>
|
||||
|
||||
<Typography noWrap display="block" variant="caption" style={{
|
||||
width: item_width,
|
||||
textAlign: "center"
|
||||
}}> {control.name === "" ? "\u00A0" : control.name}</Typography>
|
||||
|
||||
</div>
|
||||
{/* CONTROL SECTION */}
|
||||
|
||||
<div className={classes.midSection}
|
||||
style={{ display: "flex", justifyContent: "center", alignItems: "start", flexFlow: "row nowrap" }}>
|
||||
<div style={{ width: 8, height: this.VU_HEIGHT + 4, background: "#000", }}>
|
||||
<div style={{ height: this.VU_HEIGHT, overflow: "hidden", position: "absolute", margin: 2 }}>
|
||||
<div ref={this.vuRef} style={{ width: 4, height: this.VU_HEIGHT, background: "#0C0", }} />
|
||||
style={{ display: "flex", justifyContent: "center", alignItems: "start", flexFlow: "row nowrap" }}>
|
||||
<ControlTooltip uiControl={control}>
|
||||
<div style={{ width: 8, height: this.VU_HEIGHT + 4, background: "#000", }}>
|
||||
<div style={{ height: this.VU_HEIGHT, overflow: "hidden", position: "absolute", margin: 2 }}>
|
||||
<div ref={this.vuRef} style={{ width: 4, height: this.VU_HEIGHT, background: "#0C0", }} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ControlTooltip>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -575,11 +578,11 @@ const PluginOutputControl =
|
||||
}
|
||||
return (
|
||||
<div className={classes.controlFrame}
|
||||
style={{width: attachedLamp? 15: item_width}}
|
||||
>
|
||||
style={{ width: attachedLamp ? 15 : item_width }}
|
||||
>
|
||||
{/* TITLE SECTION */}
|
||||
<div className={classes.titleSection}
|
||||
style={{ flex: "0 0 auto", width: "100%"}}>
|
||||
<div className={classes.titleSection}
|
||||
style={{ flex: "0 0 auto", width: "100%" }}>
|
||||
<ControlTooltip uiControl={control}>
|
||||
<Typography noWrap variant="caption" display="block" style={{
|
||||
width: "100%",
|
||||
@@ -589,7 +592,7 @@ const PluginOutputControl =
|
||||
</div>
|
||||
{/* CONTROL SECTION */}
|
||||
|
||||
<div className={classes.midSection}
|
||||
<div className={classes.midSection}
|
||||
style={{
|
||||
display: "flex", justifyContent: "center", alignItems: "center", flexFlow: "row nowrap",
|
||||
}}>
|
||||
@@ -613,23 +616,23 @@ const PluginOutputControl =
|
||||
);
|
||||
} if (control.isOutputText()) {
|
||||
return (
|
||||
<div className={classes.controlFrame}
|
||||
style={{ display: "flex", flexDirection: "column", width: item_width }}>
|
||||
<div className={classes.controlFrame}
|
||||
style={{ display: "flex", flexDirection: "column", width: item_width }}>
|
||||
{/* TITLE SECTION */}
|
||||
<div className={classes.titleSection}
|
||||
<div className={classes.titleSection}
|
||||
style={{ flex: "0 0 auto", width: "100%" }}>
|
||||
<ControlTooltip uiControl={control}>
|
||||
<Typography noWrap variant="caption" display="block" style={{
|
||||
width: "100%",
|
||||
textAlign: "left"
|
||||
}}> {control.name === "" ? "\u00A0": control.name}</Typography>
|
||||
}}> {control.name === "" ? "\u00A0" : control.name}</Typography>
|
||||
</ControlTooltip>
|
||||
</div>
|
||||
|
||||
{/* CONTROL SECTION */}
|
||||
|
||||
<div className={classes.midSection} style={{
|
||||
display: "flex", justifyContent: "center",
|
||||
display: "flex", justifyContent: "center",
|
||||
flexFlow: "row nowrap", paddingTop: 6
|
||||
|
||||
}}>
|
||||
@@ -646,10 +649,10 @@ const PluginOutputControl =
|
||||
|
||||
} else {
|
||||
return (
|
||||
<div className={classes.controlFrame}
|
||||
style={{ display: "flex", flexDirection: "column", width: item_width }}>
|
||||
<div className={classes.controlFrame}
|
||||
style={{ display: "flex", flexDirection: "column", width: item_width }}>
|
||||
{/* TITLE SECTION */}
|
||||
<div className={classes.titleSection}
|
||||
<div className={classes.titleSection}
|
||||
style={{ flex: "0 0 auto", width: "100%" }}>
|
||||
<ControlTooltip uiControl={control}>
|
||||
<Typography noWrap variant="caption" display="block" style={{
|
||||
@@ -660,7 +663,7 @@ const PluginOutputControl =
|
||||
</div>
|
||||
{/* CONTROL SECTION */}
|
||||
|
||||
<div className={classes.midSection}
|
||||
<div className={classes.midSection}
|
||||
style={{ display: "flex", justifyContent: "start", alignItems: "center", flexFlow: "row nowrap" }}>
|
||||
<Typography noWrap variant="caption" display="block" style={{ width: "100%" }}>
|
||||
{text}
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) Robin E. R. Davies
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
* of the Software, and to permit persons to whom the Software is furnished to do
|
||||
* so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
import { Component } from 'react';
|
||||
import { Theme } from '@mui/material/styles';
|
||||
import { css } from '@emotion/react';
|
||||
|
||||
import Typography from '@mui/material/Typography';
|
||||
import { PiPedalModel, PiPedalModelFactory, State } from './PiPedalModel';
|
||||
import Select from '@mui/material/Select';
|
||||
import MenuItem from '@mui/material/MenuItem';
|
||||
|
||||
|
||||
export const StandardItemSize = { width: 80, height: 140 }
|
||||
|
||||
|
||||
import { withStyles } from "tss-react/mui";
|
||||
import WithStyles from './WithStyles';
|
||||
import { withTheme } from './WithStyles';
|
||||
|
||||
const styles = (theme: Theme) => {
|
||||
return {
|
||||
frame: css({
|
||||
position: "relative",
|
||||
margin: "12px"
|
||||
}),
|
||||
controlFrame: css({
|
||||
display: "flex", flexDirection: "column", alignItems: "start", justifyContent: "space-between", height: 116
|
||||
}),
|
||||
displayValue: css({
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 4,
|
||||
textAlign: "center",
|
||||
background: theme.mainBackground,
|
||||
color: theme.palette.text.secondary,
|
||||
// zIndex: -1,
|
||||
}),
|
||||
titleSection: css({
|
||||
flex: "0 0 auto", alignSelf: "stretch", marginBottom: 8, marginLeft: 8, marginRight: 0
|
||||
}),
|
||||
midSection: css({
|
||||
flex: "1 1 1", display: "flex", flexFlow: "column nowrap", alignContent: "center", justifyContent: "center"
|
||||
}),
|
||||
editSection: css({
|
||||
flex: "0 0 0", position: "relative", width: 60, height: 28, minHeight: 28
|
||||
})
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
export interface SideChainSelectControlProps extends WithStyles<typeof styles> {
|
||||
title: string;
|
||||
selectItems: { instanceId: number, title: string }[];
|
||||
selectedInstanceId: number;
|
||||
onChanged(instanceId: number): void;
|
||||
theme: Theme;
|
||||
}
|
||||
type SideChainSelectControlState = {
|
||||
};
|
||||
|
||||
const SideChainSelectControl =
|
||||
withTheme(withStyles(
|
||||
class extends Component<SideChainSelectControlProps, SideChainSelectControlState> {
|
||||
|
||||
model: PiPedalModel;
|
||||
|
||||
|
||||
constructor(props: SideChainSelectControlProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
};
|
||||
this.model = PiPedalModelFactory.getInstance();
|
||||
this.onStateChanged = this.onStateChanged.bind(this);
|
||||
}
|
||||
|
||||
|
||||
onStateChanged(state: State) {
|
||||
}
|
||||
mounted: boolean = false;
|
||||
componentDidMount() {
|
||||
this.model.state.addOnChangedHandler(this.onStateChanged);
|
||||
this.mounted = true;
|
||||
}
|
||||
componentWillUnmount() {
|
||||
this.mounted = false;
|
||||
this.model.state.removeOnChangedHandler(this.onStateChanged);
|
||||
}
|
||||
componentDidUpdate(prevProps: Readonly<SideChainSelectControlProps>, prevState: Readonly<SideChainSelectControlState>, snapshot?: any): void {
|
||||
}
|
||||
|
||||
render() {
|
||||
//const classes = withStyles.getClasses(this.props);
|
||||
|
||||
const classes = withStyles.getClasses(this.props);
|
||||
|
||||
return (
|
||||
<div className={classes.controlFrame}
|
||||
style={{ width: 120 }}>
|
||||
{/* TITLE SECTION */}
|
||||
<div className={classes.titleSection}
|
||||
>
|
||||
<Typography variant="caption" display="block" noWrap style={{
|
||||
width: "100%",
|
||||
textAlign: "start"
|
||||
}}> {this.props.title}</Typography>
|
||||
</div>
|
||||
{/* CONTROL SECTION */}
|
||||
|
||||
<div className={classes.midSection} style={{ width: "100%", paddingLeft: 8 }}>
|
||||
<Select
|
||||
variant="standard"
|
||||
onChange={(event) => {
|
||||
this.props.onChanged(event.target.value as number);
|
||||
}}
|
||||
value={this.props.selectedInstanceId}
|
||||
style={{ width: "100%", fontSize: "0.8rem" }}
|
||||
>
|
||||
{this.props.selectItems.map((item) => {
|
||||
return (
|
||||
<MenuItem key={item.instanceId} value={item.instanceId}
|
||||
selected={item.instanceId === this.props.selectedInstanceId}>
|
||||
{item.title}
|
||||
</MenuItem>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
|
||||
</div>
|
||||
|
||||
{/* LABEL/EDIT SECTION*/}
|
||||
<div className={classes.editSection} >
|
||||
</div>
|
||||
</div >
|
||||
);
|
||||
}
|
||||
}
|
||||
, styles)
|
||||
)
|
||||
;
|
||||
export default SideChainSelectControl;
|
||||
Reference in New Issue
Block a user