Allow .zip bundle uploads for all File plugin controls.

This commit is contained in:
Robin Davies
2024-08-21 21:04:59 -04:00
parent 060d02a2f8
commit 4a31015cc5
4 changed files with 282 additions and 331 deletions
+2 -3
View File
@@ -1,14 +1,13 @@
# Release Notes # Release Notes
## PiPedal 1.2.41 ## PiPedal 1.2.41 Release
Version 1.2 is officially released.
This version includes the following new features: This version includes the following new features:
- Supports Raspberry Pi 5. - Supports Raspberry Pi 5.
- Supports Rasberry Pi OS Bookworm. - Supports Rasberry Pi OS Bookworm.
- TooB ML allows uploading of models. See below for further details. - TooB ML allows uploading of models. See below for further details.
- TooB ML allows uploading of model collections contained in .zip files.
- TooBML support for large models (e.g. GuitarML Proteus models) - TooBML support for large models (e.g. GuitarML Proteus models)
- Upload .zip file bundles to all File plugin controls.
- Uploads can be organized into sub-directories. - Uploads can be organized into sub-directories.
- Various minor improvements to TooB plugin user interfaces. - Various minor improvements to TooB plugin user interfaces.
+5 -3
View File
@@ -370,7 +370,7 @@ export default withStyles(styles, { withTheme: true })(
<Link underline="hover" <Link underline="hover"
color="inherit" color="inherit"
key="1" onClick={() => { this.navigate(""); }} key="1" onClick={() => { this.navigate(""); }}
sx={{ display: 'flex', alignItems: 'center' }} sx={{ display: 'flex', alignItems: 'center',cursor: "default" }}
> >
<HomeIcon sx={{ mr: 0.6 }} fontSize="inherit" /> <HomeIcon sx={{ mr: 0.6 }} fontSize="inherit" />
Home Home
@@ -383,7 +383,7 @@ export default withStyles(styles, { withTheme: true })(
target = pathConcat(target, directories[i]); target = pathConcat(target, directories[i]);
let myTarget = target; let myTarget = target;
breadcrumbs.push(( breadcrumbs.push((
<Link underline="hover" key={(i + 1).toString()} <Link underline="hover" key={(i + 1).toString()} style={{cursor: "default"}}
color="inherit" onClick={() => { this.navigate(myTarget) }}> color="inherit" onClick={() => { this.navigate(myTarget) }}>
{directories[i]} {directories[i]}
</Link> </Link>
@@ -392,7 +392,9 @@ export default withStyles(styles, { withTheme: true })(
{ {
let lastdirectory = directories[directories.length - 1]; let lastdirectory = directories[directories.length - 1];
breadcrumbs.push(( breadcrumbs.push((
<Typography noWrap key={directories.length.toString()} color="text.secondary"> {lastdirectory}</Typography> <Typography noWrap key={directories.length.toString()}
style={{cursor: "default"}}
color="text.secondary"> {lastdirectory}</Typography>
)); ));
} }
+261 -309
View File
@@ -26,7 +26,7 @@ interface Deserializable<T> {
} }
export class Port implements Deserializable<Port> { export class Port implements Deserializable<Port> {
deserialize(input: any): Port { deserialize(input: any): Port {
this.port_index = input.port_index; this.port_index = input.port_index;
this.symbol = input.symbol; this.symbol = input.symbol;
@@ -54,28 +54,27 @@ export class Port implements Deserializable<Port> {
static deserialize_array(input: any): Port[] { static deserialize_array(input: any): Port[] {
let result: Port[] = []; let result: Port[] = [];
for (let i = 0; i < input.length; ++i) for (let i = 0; i < input.length; ++i) {
{
result[i] = new Port().deserialize(input[i]); result[i] = new Port().deserialize(input[i]);
} }
return result; return result;
} }
port_index: number = -1; port_index: number = -1;
symbol: string = ""; symbol: string = "";
name: string = ""; name: string = "";
min_value: number = 0; min_value: number = 0;
max_value: number = 1; max_value: number = 1;
default_value: number = 0.5; default_value: number = 0.5;
scale_points: ScalePoint[] = []; scale_points: ScalePoint[] = [];
is_input: boolean = false; is_input: boolean = false;
is_output: boolean = false is_output: boolean = false
is_control_port: boolean = false; is_control_port: boolean = false;
is_audio_port: boolean = false; is_audio_port: boolean = false;
is_atom_port: boolean = false; is_atom_port: boolean = false;
is_valid: boolean = false; is_valid: boolean = false;
supports_midi: boolean = false; supports_midi: boolean = false;
supports_time_position: boolean = false; supports_time_position: boolean = false;
port_group: string = ""; port_group: string = "";
comment: string = ""; comment: string = "";
is_bypass: boolean = false; is_bypass: boolean = false;
is_program_controller: boolean = false; is_program_controller: boolean = false;
@@ -91,10 +90,9 @@ export class PortGroup {
return this; return this;
} }
static deserialize_array(input: any) : PortGroup[] { static deserialize_array(input: any): PortGroup[] {
let result: PortGroup[] = []; let result: PortGroup[] = [];
for (let i = 0; i < input.length; ++i) for (let i = 0; i < input.length; ++i) {
{
result.push(new PortGroup().deserialize(input[i])); result.push(new PortGroup().deserialize(input[i]));
} }
return result; return result;
@@ -114,67 +112,71 @@ export class UiFileType {
this.mimeType = input.mimeType; this.mimeType = input.mimeType;
return this; return this;
} }
static deserialize_array(input: any): UiFileType[] static deserialize_array(input: any): UiFileType[] {
{
let result: UiFileType[] = []; let result: UiFileType[] = [];
for (let i = 0; i < input.length; ++i) for (let i = 0; i < input.length; ++i) {
{
result[i] = new UiFileType().deserialize(input[i]); result[i] = new UiFileType().deserialize(input[i]);
} }
return result; return result;
} }
private static IsAndroid() : boolean private static IsAndroid(): boolean {
{
return /Android/i.test(navigator.userAgent); return /Android/i.test(navigator.userAgent);
} }
static MergeMimeTypes(fileTypes: UiFileType[]): string static MergeMimeTypes(fileTypes: UiFileType[]): string {
{
if (fileTypes.length === 0) { if (fileTypes.length === 0) {
return ""; return "";
} }
let result = fileTypes[0].mimeType; if (this.IsAndroid()) {
for (let i = 1; i < fileTypes.length; ++i) return ""; // allow selection of .zip files, plus whatever. We'll catch it later.
{
let fileType = fileTypes[i];
if (fileType.mimeType !== result)
{
if (result.startsWith("audio/") && fileType.mimeType.startsWith("audio/"))
{
result = "audio/*";
} else if (result.startsWith("video/") && fileType.mimeType.startsWith("video/"))
{
result = "video/*";
} else if (result.startsWith("text/") && fileType.mimeType.startsWith("text/"))
{
result = "text/*";
} else {
result = "application/octet-stream";
}
}
}
if (this.IsAndroid())
{
if (result.startsWith("audio/")) result = "audio/*";
if (result.startsWith("video/")) result = "video/*";
if (result.startsWith("text/")) result = "text/*";
} else { } else {
// chrome desktop thinks "application/octet-stream" is .exe, .com, or .bat. // chrome desktop thinks "application/octet-stream" is .exe, .com, or .bat.
// Feed it file extensions isntead. // Feed it file extensions isntead.
if (result === "application/octet-stream") let result = "";
{ for (let i = 0; i < fileTypes.length; ++i) {
result = ""; let fileType = fileTypes[i];
for (let i = 0; i < fileTypes.length; ++i) if (fileType.fileExtension !== "") {
{ if (result.length !== 0) // prefer file extensions.
if (i !== 0)
{ {
result += ','; result += ",";
result += fileType.fileExtension;
}
} else {
if (fileType.mimeType !== result) {
let t = "";
if (result.startsWith("audio/") && fileType.mimeType.startsWith("audio/")) {
t = "audio/*";
} else if (result.startsWith("video/") && fileType.mimeType.startsWith("video/")) {
t = "video/*";
} else if (result.startsWith("text/") && fileType.mimeType.startsWith("text/")) {
t = "text/*";
}
if (t.length !== 0) {
if (result.length !== 0) {
result += ",";
}
result += t;
}
} }
result += fileTypes[i].fileExtension;
} }
} }
let hasZip = false;
let types = result.split(",");
for (let thisType of types) {
if (thisType === ".zip") {
hasZip = true;
break;
}
}
// add .zip files
if (!hasZip) {
if (result.length !== 0) {
result += ",.zip";
}
}
return result;
} }
return result;
} }
name: string = ""; name: string = "";
fileExtension: string = ""; fileExtension: string = "";
@@ -182,19 +184,16 @@ export class UiFileType {
} }
export class UiPropertyNotification { export class UiPropertyNotification {
deserialize(input: any): UiPropertyNotification deserialize(input: any): UiPropertyNotification {
{
this.portIndex = input.portIndex; this.portIndex = input.portIndex;
this.symbol = input.symbol; this.symbol = input.symbol;
this.plugin = input.plugin; this.plugin = input.plugin;
this.protocol = input.protocol; this.protocol = input.protocol;
return this; return this;
} }
static deserialize_array(input: any): UiPropertyNotification[] static deserialize_array(input: any): UiPropertyNotification[] {
{
let result: UiPropertyNotification[] = []; let result: UiPropertyNotification[] = [];
for (let i = 0; i < input.length; ++i) for (let i = 0; i < input.length; ++i) {
{
result[i] = new UiPropertyNotification().deserialize(input[i]); result[i] = new UiPropertyNotification().deserialize(input[i]);
} }
return result; return result;
@@ -207,8 +206,7 @@ export class UiPropertyNotification {
}; };
export class UiFrequencyPlot { export class UiFrequencyPlot {
deserialize(input: any): UiFrequencyPlot deserialize(input: any): UiFrequencyPlot {
{
this.patchProperty = input.patchProperty; this.patchProperty = input.patchProperty;
this.index = input.index; this.index = input.index;
this.portGroup = input.portGroup; this.portGroup = input.portGroup;
@@ -220,11 +218,9 @@ export class UiFrequencyPlot {
this.width = input.width; this.width = input.width;
return this; return this;
} }
static deserialize_array(input: any): UiFrequencyPlot[] static deserialize_array(input: any): UiFrequencyPlot[] {
{
let result: UiFrequencyPlot[] = []; let result: UiFrequencyPlot[] = [];
for (let i = 0; i < input.length; ++i) for (let i = 0; i < input.length; ++i) {
{
result[i] = new UiFrequencyPlot().deserialize(input[i]); result[i] = new UiFrequencyPlot().deserialize(input[i]);
} }
return result; return result;
@@ -242,78 +238,73 @@ export class UiFrequencyPlot {
}; };
export class UiFileProperty { export class UiFileProperty {
deserialize(input: any): UiFileProperty deserialize(input: any): UiFileProperty {
{ this.label = input.label;
this.label = input.label; this.fileTypes = UiFileType.deserialize_array(input.fileTypes);
this.fileTypes = UiFileType.deserialize_array(input.fileTypes); this.patchProperty = input.patchProperty;
this.patchProperty = input.patchProperty; this.directory = input.directory;
this.directory = input.directory; this.index = input.index;
this.index = input.index; this.portGroup = input.portGroup;
this.portGroup = input.portGroup; this.resourceDirectory = input.resourceDirectory ?? "";
this.resourceDirectory = input.resourceDirectory??""; return this;
return this; }
} static deserialize_array(input: any): UiFileProperty[] {
static deserialize_array(input: any): UiFileProperty[] let result: UiFileProperty[] = [];
{ for (let i = 0; i < input.length; ++i) {
let result: UiFileProperty[] = []; result[i] = new UiFileProperty().deserialize(input[i]);
for (let i = 0; i < input.length; ++i)
{
result[i] = new UiFileProperty().deserialize(input[i]);
}
return result;
} }
return result;
}
private static getFileExtension(name: string): string { private static getFileExtension(name: string): string {
let pos = name.lastIndexOf('.'); let pos = name.lastIndexOf('.');
let filenamePos = name.lastIndexOf('/') +1; let filenamePos = name.lastIndexOf('/') + 1;
filenamePos = Math.max(name.lastIndexOf('\\')+1); filenamePos = Math.max(name.lastIndexOf('\\') + 1);
filenamePos = Math.max(name.lastIndexOf(':')+1); filenamePos = Math.max(name.lastIndexOf(':') + 1);
if (pos < filenamePos) if (pos < filenamePos) {
{
return "";
}
if (pos !== -1) {
return name.substring(pos);
}
return ""; return "";
} }
wantsFile(filename: string) : boolean { if (pos !== -1) {
if (this.fileTypes.length === 0) { return name.substring(pos);
}
return "";
}
wantsFile(filename: string): boolean {
if (this.fileTypes.length === 0) {
return true;
}
let extension = UiFileProperty.getFileExtension(filename);
if (extension === ".zip") {
return true;
}
for (let fileType of this.fileTypes) {
if (fileType.fileExtension === extension) {
return true; return true;
} }
let extension = UiFileProperty.getFileExtension(filename); if (fileType.fileExtension === "*" || fileType.fileExtension === "") {
for (let fileType of this.fileTypes) return true;
{
if (fileType.fileExtension === extension )
{
return true;
}
if (fileType.fileExtension === "*" || fileType.fileExtension === "")
{
return true;
}
} }
return false;
} }
return false;
}
label: string = ""; label: string = "";
fileTypes: UiFileType[] = []; fileTypes: UiFileType[] = [];
patchProperty: string = ""; patchProperty: string = "";
directory: string = ""; directory: string = "";
index: number = -1; index: number = -1;
portGroup: string = ""; portGroup: string = "";
resourceDirectory: string = ""; resourceDirectory: string = "";
}; };
export class Lv2Plugin implements Deserializable<Lv2Plugin> { export class Lv2Plugin implements Deserializable<Lv2Plugin> {
deserialize(input: any): Lv2Plugin deserialize(input: any): Lv2Plugin {
{
this.uri = input.uri; this.uri = input.uri;
this.name = input.name; this.name = input.name;
this.brand = input.name? input.name: ""; this.brand = input.name ? input.name : "";
this.label = input.label? input.label: this.name; this.label = input.label ? input.label : this.name;
this.plugin_class = input.plugin_class; this.plugin_class = input.plugin_class;
this.supported_features = input.supported_features; this.supported_features = input.supported_features;
this.required_features = input.required_features; this.required_features = input.required_features;
@@ -321,23 +312,20 @@ export class Lv2Plugin implements Deserializable<Lv2Plugin> {
this.author_name = input.author_name; this.author_name = input.author_name;
this.author_homepage = input.author_homepage; this.author_homepage = input.author_homepage;
this.comment = input.comment; this.comment = input.comment;
this.ports= Port.deserialize_array(input.ports); this.ports = Port.deserialize_array(input.ports);
this.port_groups = PortGroup.deserialize_array(input.port_groups); this.port_groups = PortGroup.deserialize_array(input.port_groups);
if (input.fileProperties) if (input.fileProperties) {
{
this.fileProperties = UiFileProperty.deserialize_array(input.fileProperties) this.fileProperties = UiFileProperty.deserialize_array(input.fileProperties)
} else { } else {
this.fileProperties = []; this.fileProperties = [];
} }
if (input.frequencyPlots) if (input.frequencyPlots) {
{
this.frequencyPlots = UiFrequencyPlot.deserialize_array(input.frequencyPlots) this.frequencyPlots = UiFrequencyPlot.deserialize_array(input.frequencyPlots)
} else { } else {
this.frequencyPlots = []; this.frequencyPlots = [];
} }
if (input.uiPortNotifications) if (input.uiPortNotifications) {
{
this.uiPortNotifications = UiPropertyNotification.deserialize_array(input.uiPortNotifications); this.uiPortNotifications = UiPropertyNotification.deserialize_array(input.uiPortNotifications);
} else { } else {
this.uiPortNotifications = []; this.uiPortNotifications = [];
@@ -346,36 +334,34 @@ export class Lv2Plugin implements Deserializable<Lv2Plugin> {
} }
static EmptyFeatures: string[] = []; static EmptyFeatures: string[] = [];
uri: string = ""; uri: string = "";
name: string = ""; name: string = "";
brand: string = ""; brand: string = "";
label: string = ""; label: string = "";
plugin_class: string = ""; plugin_class: string = "";
supported_features: string[] = Lv2Plugin.EmptyFeatures; supported_features: string[] = Lv2Plugin.EmptyFeatures;
required_features: string[] = Lv2Plugin.EmptyFeatures; required_features: string[] = Lv2Plugin.EmptyFeatures;
optional_features: string[] = Lv2Plugin.EmptyFeatures; optional_features: string[] = Lv2Plugin.EmptyFeatures;
author_name: string = ""; author_name: string = "";
author_homepage: string = ""; author_homepage: string = "";
comment: string = ""; comment: string = "";
ports: Port[] = Port.EmptyPorts; ports: Port[] = Port.EmptyPorts;
port_groups: PortGroup[] = []; port_groups: PortGroup[] = [];
fileProperties: UiFileProperty[] = []; fileProperties: UiFileProperty[] = [];
frequencyPlots: UiFrequencyPlot[] = []; frequencyPlots: UiFrequencyPlot[] = [];
uiPortNotifications: UiPropertyNotification[] = []; uiPortNotifications: UiPropertyNotification[] = [];
} }
export class ScalePoint implements Deserializable<ScalePoint> { export class ScalePoint implements Deserializable<ScalePoint> {
deserialize(input: any): ScalePoint { deserialize(input: any): ScalePoint {
this.value = input.value; this.value = input.value;
this.label = input.label; this.label = input.label;
return this; return this;
} }
static deserialize_array(input: any): ScalePoint[] static deserialize_array(input: any): ScalePoint[] {
{
let result: ScalePoint[] = []; let result: ScalePoint[] = [];
for (let i = 0; i < input.length; ++i) for (let i = 0; i < input.length; ++i) {
{
result[i] = new ScalePoint().deserialize(input[i]); result[i] = new ScalePoint().deserialize(input[i]);
} }
return result; return result;
@@ -386,8 +372,8 @@ export class ScalePoint implements Deserializable<ScalePoint> {
export enum PluginType { export enum PluginType {
// Reserved types used in pedalboards. // Reserved types used in pedalboards.
None="", None = "",
InvalidPlugin= "InvalidPlugin", InvalidPlugin = "InvalidPlugin",
Plugin = "Plugin", Plugin = "Plugin",
AllpassPlugin = "AllpassPlugin", AllpassPlugin = "AllpassPlugin",
@@ -428,7 +414,7 @@ export enum PluginType {
UtilityPlugin = "UtilityPlugin", UtilityPlugin = "UtilityPlugin",
WaveshaperPlugin = "WaveshaperPlugin", WaveshaperPlugin = "WaveshaperPlugin",
// psuedo plugin type for the Amps node of the filter dialog. // psuedo plugin type for the Amps node of the filter dialog.
PiPedalAmpsNode = "PiPedalAmpsNode", PiPedalAmpsNode = "PiPedalAmpsNode",
// pseudo plugin types for splitter. // pseudo plugin types for splitter.
@@ -457,9 +443,8 @@ export enum ControlType {
OutputSelect OutputSelect
} }
export class UiControl implements Deserializable<UiControl> { export class UiControl implements Deserializable<UiControl> {
deserialize(input: any): UiControl deserialize(input: any): UiControl {
{
this.symbol = input.symbol; this.symbol = input.symbol;
this.name = input.name; this.name = input.name;
this.index = input.index; this.index = input.index;
@@ -480,27 +465,23 @@ export class UiControl implements Deserializable<UiControl> {
this.units = input.units as Units; this.units = input.units as Units;
this.comment = input.comment ?? ""; this.comment = input.comment ?? "";
this.is_bypass = input.is_bypass ? true: false; this.is_bypass = input.is_bypass ? true : false;
this.is_program_controller = input.is_program_controller? true: false; this.is_program_controller = input.is_program_controller ? true : false;
this.custom_units = input.custom_units ?? ""; this.custom_units = input.custom_units ?? "";
this.connection_optional = input.connection_optional ? true: false; this.connection_optional = input.connection_optional ? true : false;
if (this.is_bypass) if (this.is_bypass) {
{
this.not_on_gui = true; this.not_on_gui = true;
} }
this.controlType = ControlType.Dial; this.controlType = ControlType.Dial;
if (!this.is_input) if (!this.is_input) {
{ if (this.units === Units.midiNote) {
if (this.units === Units.midiNote)
{
this.controlType = ControlType.Tuner; this.controlType = ControlType.Tuner;
} else if (this.units === Units.db) } else if (this.units === Units.db) {
{
this.controlType = ControlType.DbVu; this.controlType = ControlType.DbVu;
} else if (this.enumeration_property) { } else if (this.enumeration_property) {
this.controlType = ControlType.OutputSelect; this.controlType = ControlType.OutputSelect;
@@ -508,45 +489,36 @@ export class UiControl implements Deserializable<UiControl> {
this.controlType = ControlType.Vu; this.controlType = ControlType.Vu;
} }
} }
if (this.isValidEnumeration()) if (this.isValidEnumeration()) {
{
this.controlType = ControlType.Select; this.controlType = ControlType.Select;
if (this.scale_points.length === 2) if (this.scale_points.length === 2) {
{
this.controlType = ControlType.ABSwitch; this.controlType = ControlType.ABSwitch;
} }
} else { } else {
if (this.toggled_property || (this.integer_property && this.min_value === 0 && this.max_value === 1)) if (this.toggled_property || (this.integer_property && this.min_value === 0 && this.max_value === 1)) {
{
this.controlType = ControlType.OnOffSwitch; this.controlType = ControlType.OnOffSwitch;
} }
} }
return this; return this;
} }
applyProperties(properties: Partial<UiControl>): UiControl applyProperties(properties: Partial<UiControl>): UiControl {
{ return { ...this, ...properties };
return {...this,...properties};
} }
private hasScalePoint(value: number): boolean { private hasScalePoint(value: number): boolean {
for (let scale_point of this.scale_points) for (let scale_point of this.scale_points) {
{
if (scale_point.value === value) return true; if (scale_point.value === value) return true;
} }
return false; return false;
} }
private isValidEnumeration() : boolean { private isValidEnumeration(): boolean {
if (this.enumeration_property) return true; if (this.enumeration_property) return true;
if (this.toggled_property && this.min_value === 0 && this.max_value === 1) if (this.toggled_property && this.min_value === 0 && this.max_value === 1) {
{ if (this.hasScalePoint(this.min_value) && this.hasScalePoint(this.max_value)) {
if (this.hasScalePoint(this.min_value) && this.hasScalePoint(this.max_value))
{
return true; return true;
} }
} }
if (this.integer_property && this.min_value === 0 && this.max_value === 1) if (this.integer_property && this.min_value === 0 && this.max_value === 1) {
{ if (this.hasScalePoint(this.min_value) && this.hasScalePoint(this.max_value)) {
if (this.hasScalePoint(this.min_value) && this.hasScalePoint(this.max_value))
{
return true; return true;
} }
} }
@@ -557,23 +529,22 @@ export class UiControl implements Deserializable<UiControl> {
static deserialize_array(input: any): UiControl[] { static deserialize_array(input: any): UiControl[] {
let result: UiControl[] = []; let result: UiControl[] = [];
for (let i = 0; i < input.length; ++i) for (let i = 0; i < input.length; ++i) {
{
result[i] = new UiControl().deserialize(input[i]); result[i] = new UiControl().deserialize(input[i]);
} }
return result; return result;
} }
symbol: string = ""; symbol: string = "";
name: string = ""; name: string = "";
index: number = -1; index: number = -1;
is_input: boolean = true; is_input: boolean = true;
min_value: number = 0; min_value: number = 0;
max_value: number = 1; max_value: number = 1;
default_value:number = 0.5; default_value: number = 0.5;
is_logarithmic: boolean = false; is_logarithmic: boolean = false;
display_priority: number = -1; display_priority: number = -1;
range_steps: number = 0; range_steps: number = 0;
integer_property:boolean = false; integer_property: boolean = false;
enumeration_property: boolean = false; enumeration_property: boolean = false;
trigger: boolean = false; trigger: boolean = false;
not_on_gui: boolean = false; not_on_gui: boolean = false;
@@ -589,16 +560,13 @@ export class UiControl implements Deserializable<UiControl> {
// Return the value of the closest scale_point. // Return the value of the closest scale_point.
clampSelectValue(value: number): number{ clampSelectValue(value: number): number {
if (this.scale_points.length !== 0) if (this.scale_points.length !== 0) {
{
let minError = 1.0E100; let minError = 1.0E100;
let bestValue = value; let bestValue = value;
for (let i = 0; i < this.scale_points.length; ++i) for (let i = 0; i < this.scale_points.length; ++i) {
{ let error = Math.abs(this.scale_points[i].value - value);
let error = Math.abs(this.scale_points[i].value-value); if (error < minError) {
if (error < minError)
{
minError = error; minError = error;
bestValue = this.scale_points[i].value; bestValue = this.scale_points[i].value;
} }
@@ -609,20 +577,20 @@ export class UiControl implements Deserializable<UiControl> {
} }
} }
isHidden() : boolean { isHidden(): boolean {
return this.not_on_gui || (this.connection_optional && !this.is_input); return this.not_on_gui || (this.connection_optional && !this.is_input);
} }
isOnOffSwitch() : boolean { isOnOffSwitch(): boolean {
return this.controlType === ControlType.OnOffSwitch; return this.controlType === ControlType.OnOffSwitch;
} }
isAbToggle(): boolean { isAbToggle(): boolean {
return this.controlType === ControlType.ABSwitch; return this.controlType === ControlType.ABSwitch;
} }
isSelect() : boolean { isSelect(): boolean {
return this.controlType === ControlType.Select; return this.controlType === ControlType.Select;
} }
isOutputSelect() : boolean { isOutputSelect(): boolean {
return !this.is_input && this.controlType === ControlType.OutputSelect; return !this.is_input && this.controlType === ControlType.OutputSelect;
} }
@@ -630,23 +598,23 @@ export class UiControl implements Deserializable<UiControl> {
isLamp(): boolean { isLamp(): boolean {
return this.toggled_property && this.scale_points.length === 0 && !this.is_input; return this.toggled_property && this.scale_points.length === 0 && !this.is_input;
} }
isDial() : boolean { isDial(): boolean {
return this.controlType === ControlType.Dial; return this.controlType === ControlType.Dial;
} }
isTuner() : boolean { isTuner(): boolean {
return this.controlType === ControlType.Tuner; return this.controlType === ControlType.Tuner;
} }
isVu() : boolean { isVu(): boolean {
return this.controlType === ControlType.Vu; return this.controlType === ControlType.Vu;
} }
isDbVu() : boolean { isDbVu(): boolean {
return this.controlType === ControlType.DbVu; return this.controlType === ControlType.DbVu;
} }
valueToRange(value: number): number { valueToRange(value: number): number {
if (this.toggled_property) return value === 0 ? 0: 1; if (this.toggled_property) return value === 0 ? 0 : 1;
if (this.integer_property || this.enumeration_property) { if (this.integer_property || this.enumeration_property) {
value = Math.round(value); value = Math.round(value);
@@ -659,11 +627,11 @@ export class UiControl implements Deserializable<UiControl> {
return range; return range;
} }
rangeToValue(range: number) : number { rangeToValue(range: number): number {
if (range < 0) range = 0; if (range < 0) range = 0;
if (range > 1) range = 1; if (range > 1) range = 1;
if (this.toggled_property) return range === 0? 0: 1; if (this.toggled_property) return range === 0 ? 0 : 1;
let value = range * (this.max_value - this.min_value) + this.min_value; let value = range * (this.max_value - this.min_value) + this.min_value;
if (this.integer_property || this.enumeration_property) { if (this.integer_property || this.enumeration_property) {
@@ -680,11 +648,9 @@ export class UiControl implements Deserializable<UiControl> {
value = Math.round(value); value = Math.round(value);
} }
for (let i = 0; i < this.scale_points.length; ++i) for (let i = 0; i < this.scale_points.length; ++i) {
{
let scalePoint = this.scale_points[i]; let scalePoint = this.scale_points[i];
if (scalePoint.value === value) if (scalePoint.value === value) {
{
return scalePoint.label; return scalePoint.label;
} }
} }
@@ -738,8 +704,7 @@ export class UiControl implements Deserializable<UiControl> {
} }
return text; return text;
} }
formatShortValue(value: number): string formatShortValue(value: number): string {
{
if (this.enumeration_property) { if (this.enumeration_property) {
for (let i = 0; i < this.scale_points.length; ++i) { for (let i = 0; i < this.scale_points.length; ++i) {
let scale_point = this.scale_points[i]; let scale_point = this.scale_points[i];
@@ -766,12 +731,11 @@ export class UiControl implements Deserializable<UiControl> {
export class UiPlugin implements Deserializable<UiPlugin> { export class UiPlugin implements Deserializable<UiPlugin> {
deserialize(input: any): UiPlugin deserialize(input: any): UiPlugin {
{
this.uri = input.uri; this.uri = input.uri;
this.name = input.name; this.name = input.name;
this.brand = input.brand ? input.brand: ""; this.brand = input.brand ? input.brand : "";
this.label = input.label? input.label: this.name; this.label = input.label ? input.label : this.name;
this.plugin_type = input.plugin_type as PluginType; this.plugin_type = input.plugin_type as PluginType;
this.plugin_display_type = input.plugin_display_type; this.plugin_display_type = input.plugin_display_type;
this.author_name = input.author_name; this.author_name = input.author_name;
@@ -783,14 +747,12 @@ export class UiPlugin implements Deserializable<UiPlugin> {
this.description = input.description; this.description = input.description;
this.controls = UiControl.deserialize_array(input.controls); this.controls = UiControl.deserialize_array(input.controls);
this.port_groups = PortGroup.deserialize_array(input.port_groups); this.port_groups = PortGroup.deserialize_array(input.port_groups);
if (input.fileProperties) if (input.fileProperties) {
{
this.fileProperties = UiFileProperty.deserialize_array(input.fileProperties) this.fileProperties = UiFileProperty.deserialize_array(input.fileProperties)
} else { } else {
this.fileProperties = []; this.fileProperties = [];
} }
if (input.frequencyPlots) if (input.frequencyPlots) {
{
this.frequencyPlots = UiFrequencyPlot.deserialize_array(input.frequencyPlots) this.frequencyPlots = UiFrequencyPlot.deserialize_array(input.frequencyPlots)
} else { } else {
this.frequencyPlots = []; this.frequencyPlots = [];
@@ -802,8 +764,7 @@ export class UiPlugin implements Deserializable<UiPlugin> {
} }
static deserialize_array(input: any): UiPlugin[] { static deserialize_array(input: any): UiPlugin[] {
let result: UiPlugin[] = []; let result: UiPlugin[] = [];
for (let i = 0; i < input.length; ++i) for (let i = 0; i < input.length; ++i) {
{
result[i] = new UiPlugin().deserialize(input[i]); result[i] = new UiPlugin().deserialize(input[i]);
} }
return result; return result;
@@ -814,190 +775,181 @@ export class UiPlugin implements Deserializable<UiPlugin> {
} }
getControl(key: string): UiControl | undefined { getControl(key: string): UiControl | undefined {
for (let i = 0; i < this.controls.length; ++i) for (let i = 0; i < this.controls.length; ++i) {
{
let control = this.controls[i]; let control = this.controls[i];
if (control.symbol === key) if (control.symbol === key) {
{
return control; return control;
} }
} }
return undefined; return undefined;
} }
getPortGroupByUri(uri: string) :PortGroup | null getPortGroupByUri(uri: string): PortGroup | null {
{ for (let i = 0; i < this.port_groups.length; ++i) {
for (let i = 0; i < this.port_groups.length; ++i)
{
let port_group = this.port_groups[i]; let port_group = this.port_groups[i];
if (port_group.uri === uri) if (port_group.uri === uri) {
{
return port_group; return port_group;
} }
} }
return null; return null;
} }
getPortGroupBySymbol(symbol: string): PortGroup | null getPortGroupBySymbol(symbol: string): PortGroup | null {
{ for (let i = 0; i < this.port_groups.length; ++i) {
for (let i = 0; i < this.port_groups.length; ++i)
{
let port_group = this.port_groups[i]; let port_group = this.port_groups[i];
if (port_group.symbol === symbol) if (port_group.symbol === symbol) {
{
return port_group; return port_group;
} }
} }
return null; return null;
} }
uri: string = ""; uri: string = "";
name: string = ""; name: string = "";
brand: string = ""; brand: string = "";
label: string = ""; label: string = "";
plugin_type: PluginType = PluginType.InvalidPlugin; plugin_type: PluginType = PluginType.InvalidPlugin;
plugin_display_type: string = ""; plugin_display_type: string = "";
author_name: string = ""; author_name: string = "";
author_homepage: string = ""; author_homepage: string = "";
audio_inputs: number = 0; audio_inputs: number = 0;
audio_outputs: number = 0; audio_outputs: number = 0;
has_midi_input: number = 0; has_midi_input: number = 0;
has_midi_output: number = 0; has_midi_output: number = 0;
description: string = ""; description: string = "";
controls: UiControl[] = []; controls: UiControl[] = [];
port_groups: PortGroup[] = []; port_groups: PortGroup[] = [];
fileProperties: UiFileProperty[] = []; fileProperties: UiFileProperty[] = [];
frequencyPlots: UiFrequencyPlot[] = []; frequencyPlots: UiFrequencyPlot[] = [];
is_vst3 : boolean = false; is_vst3: boolean = false;
} }
export function makeSplitUiPlugin(): UiPlugin export function makeSplitUiPlugin(): UiPlugin {
{
return new UiPlugin().deserialize({ return new UiPlugin().deserialize({
uri: "uri://two-play/pipedal/pedalboard#Split", uri: "uri://two-play/pipedal/pedalboard#Split",
name: "Split", name: "Split",
brand: "", brand: "",
label: "", label: "",
plugin_type: PluginType.SplitA, plugin_type: PluginType.SplitA,
plugin_display_type: "Split", plugin_display_type: "Split",
author_name: "", author_name: "",
author_homepage: "", author_homepage: "",
audio_inputs: 1, audio_inputs: 1,
audio_outputs: 1, audio_outputs: 1,
has_midi_input: 0, has_midi_input: 0,
has_midi_output: 0, has_midi_output: 0,
description: "", description: "",
controls: [ controls: [
new UiControl().applyProperties({ new UiControl().applyProperties({
symbol: "splitType", symbol: "splitType",
name: "Type", name: "Type",
index: 0, index: 0,
is_input: true, is_input: true,
min_value: 0.0, min_value: 0.0,
max_value: 2.0, max_value: 2.0,
enumeration_property: true, enumeration_property: true,
scale_points: [ scale_points: [
new ScalePoint().deserialize({value: 0, label: "A/B"}), new ScalePoint().deserialize({ value: 0, label: "A/B" }),
new ScalePoint().deserialize({value: 1, label: "mix"}), new ScalePoint().deserialize({ value: 1, label: "mix" }),
new ScalePoint().deserialize({value: 1, label: "L/R"}), new ScalePoint().deserialize({ value: 1, label: "L/R" }),
], ],
is_bypass: false, is_bypass: false,
is_program_controller: false, is_program_controller: false,
custom_units: "", custom_units: "",
connection_optional: false, connection_optional: false,
}) , }),
new UiControl().applyProperties({ new UiControl().applyProperties({
symbol: "select", symbol: "select",
name: "Select", name: "Select",
index: 1, index: 1,
is_input: true, is_input: true,
min_value: 0.0, min_value: 0.0,
max_value: 1.0, max_value: 1.0,
enumeration_property: true, enumeration_property: true,
scale_points: [ scale_points: [
new ScalePoint().deserialize({value: 0, label: "A"}), new ScalePoint().deserialize({ value: 0, label: "A" }),
new ScalePoint().deserialize({value: 1, label: "B"}), new ScalePoint().deserialize({ value: 1, label: "B" }),
], ],
is_bypass: false, is_bypass: false,
is_program_controller: false, is_program_controller: false,
custom_units: "", custom_units: "",
connection_optional: false, connection_optional: false,
}) , }),
new UiControl().applyProperties({ new UiControl().applyProperties({
symbol: "mix", symbol: "mix",
name: "Mix", name: "Mix",
index: 2, index: 2,
is_input: true, is_input: true,
min_value: -1.0, min_value: -1.0,
max_value: 1.0, max_value: 1.0,
is_bypass: false, is_bypass: false,
is_program_controller: false, is_program_controller: false,
custom_units: "", custom_units: "",
connection_optional: false, connection_optional: false,
}) , }),
new UiControl().applyProperties({ new UiControl().applyProperties({
symbol: "panL", symbol: "panL",
name: "Pan Top", name: "Pan Top",
index: 3, index: 3,
is_input: true, is_input: true,
min_value: -1.0, min_value: -1.0,
max_value: 1.0, max_value: 1.0,
is_bypass: false, is_bypass: false,
is_program_controller: false, is_program_controller: false,
custom_units: "", custom_units: "",
connection_optional: false, connection_optional: false,
}) , }),
new UiControl().applyProperties({ new UiControl().applyProperties({
symbol: "volL", symbol: "volL",
name: "Vol Top", name: "Vol Top",
index: 4, index: 4,
is_input: true, is_input: true,
min_value: -60.0, min_value: -60.0,
max_value: 12.0, max_value: 12.0,
is_bypass: false, is_bypass: false,
is_program_controller: false, is_program_controller: false,
custom_units: "", custom_units: "",
connection_optional: false, connection_optional: false,
}) , }),
new UiControl().applyProperties({ new UiControl().applyProperties({
symbol: "panR", symbol: "panR",
name: "Pan Bottom", name: "Pan Bottom",
index: 5, index: 5,
is_input: true, is_input: true,
min_value: -1.0, min_value: -1.0,
max_value: 1.0, max_value: 1.0,
is_bypass: false, is_bypass: false,
is_program_controller: false, is_program_controller: false,
custom_units: "", custom_units: "",
connection_optional: false, connection_optional: false,
}) , }),
new UiControl().applyProperties({ new UiControl().applyProperties({
symbol: "volR", symbol: "volR",
name: "Vol Bottom", name: "Vol Bottom",
index: 6, index: 6,
is_input: true, is_input: true,
min_value: -60.0, min_value: -60.0,
max_value: 12.0, max_value: 12.0,
is_bypass: false, is_bypass: false,
is_program_controller: false, is_program_controller: false,
custom_units: "", custom_units: "",
connection_optional: false, connection_optional: false,
}) })
], ],
port_groups: [], port_groups: [],
fileProperties: [], fileProperties: [],
frequencyPlots: [], frequencyPlots: [],
is_vst3 : false, is_vst3: false,
} }
); );
-2
View File
@@ -1,5 +1,3 @@
- change icons on gallery in index.html
- provide direct link to docs on both landing pages.
- feature: redo ./makepackage so that it runs without sudo. - feature: redo ./makepackage so that it runs without sudo.
- Bug: text Cursor hovering over the breadcrumb bar in file property dialog. - Bug: text Cursor hovering over the breadcrumb bar in file property dialog.
- Bug: Turning off wifi-direct sould re-enable NetworkManager. - Bug: Turning off wifi-direct sould re-enable NetworkManager.