Update sidechain references after topology change.

This commit is contained in:
Robin E. R. Davies
2025-09-30 21:25:08 -04:00
parent 25494d6f3c
commit aa26fb2fea
3 changed files with 101 additions and 12 deletions
+35
View File
@@ -394,6 +394,7 @@ export class Pedalboard implements Deserializable<Pedalboard> {
pathProperties: {[Name: string]: string} = {}; pathProperties: {[Name: string]: string} = {};
selectedPlugin: number = -1; selectedPlugin: number = -1;
// yields all items in the pedalboard, including split items. Splits are yielded before their children.
*itemsGenerator(): Generator<PedalboardItem, void, undefined> { *itemsGenerator(): Generator<PedalboardItem, void, undefined> {
let it = itemGenerator_(this.items); let it = itemGenerator_(this.items);
while (true) while (true)
@@ -403,6 +404,16 @@ export class Pedalboard implements Deserializable<Pedalboard> {
yield v.value; yield v.value;
} }
} }
// same as itemsGenerator, but yields split items after their chains.
*itemsGeneratorSplitAfter(): Generator<PedalboardItem, void, undefined> {
let it = itemGeneratorSplitAfter_(this.items);
while (true)
{
let v = it.next();
if (v.done) break;
yield v.value;
}
}
makeSnapshot(): Snapshot { makeSnapshot(): Snapshot {
let result = new Snapshot(); let result = new Snapshot();
@@ -793,4 +804,28 @@ function* itemGenerator_(items: PedalboardItem[]): Generator<PedalboardItem, voi
} }
} }
function* itemGeneratorSplitAfter_(items: PedalboardItem[]): Generator<PedalboardItem, void, undefined> {
for (let i = 0; i < items.length; ++i) {
let item = items[i];
if (item.uri === SPLIT_PEDALBOARD_ITEM_URI) {
let splitItem = item as PedalboardSplitItem;
let it = itemGenerator_(splitItem.topChain);
while (true) {
let v = it.next();
if (v.done) break;
yield v.value;
}
it = itemGenerator_(splitItem.bottomChain);
while (true) {
let v = it.next();
if (v.done) break;
yield v.value;
}
}
yield item;
}
}
+56 -7
View File
@@ -659,6 +659,7 @@ export class PiPedalModel //implements PiPedalModel
} }
private setModelPedalboard(pedalboard: Pedalboard) { private setModelPedalboard(pedalboard: Pedalboard) {
this.removeInvalidSidechains(pedalboard);
this.pedalboard.set(pedalboard); this.pedalboard.set(pedalboard);
this.selectedSnapshot.set(pedalboard.selectedSnapshot); this.selectedSnapshot.set(pedalboard.selectedSnapshot);
this.updateEnabledItems(pedalboard); this.updateEnabledItems(pedalboard);
@@ -1763,13 +1764,17 @@ export class PiPedalModel //implements PiPedalModel
} }
let it = newPedalboard.itemsGenerator(); let it = newPedalboard.itemsGenerator();
let oldInstanceId = -1;
let newInstanceId = -1;
while (true) { while (true) {
let v = it.next(); let v = it.next();
if (v.done) break; if (v.done) break;
let item = v.value; let item = v.value;
if (item.instanceId === itemId) { if (item.instanceId === itemId) {
oldInstanceId = item.instanceId;
item.deserialize(new PedalboardItem()); // skeezy way to re-initialize. item.deserialize(new PedalboardItem()); // skeezy way to re-initialize.
item.instanceId = ++newPedalboard.nextInstanceId; item.instanceId = ++newPedalboard.nextInstanceId;
newInstanceId = item.instanceId;
item.uri = selectedUri; item.uri = selectedUri;
item.pluginName = plugin.name; item.pluginName = plugin.name;
item.controlValues = this.getDefaultValues(item.uri); item.controlValues = this.getDefaultValues(item.uri);
@@ -1784,6 +1789,9 @@ export class PiPedalModel //implements PiPedalModel
item.pathProperties[fileProperty.patchProperty] = "null"; item.pathProperties[fileProperty.patchProperty] = "null";
} }
newPedalboard.selectedPlugin = item.instanceId; newPedalboard.selectedPlugin = item.instanceId;
if (oldInstanceId !== -1) {
this.updateSidechainReferences(newPedalboard, oldInstanceId, newInstanceId);
}
this.setModelPedalboard(newPedalboard); this.setModelPedalboard(newPedalboard);
this.updateServerPedalboard() this.updateServerPedalboard()
return item.instanceId; return item.instanceId;
@@ -1938,6 +1946,9 @@ export class PiPedalModel //implements PiPedalModel
newPedalboard.replaceItem(fromInstanceId, emptyItem); newPedalboard.replaceItem(fromInstanceId, emptyItem);
newPedalboard.replaceItem(toInstanceId, fromItem); newPedalboard.replaceItem(toInstanceId, fromItem);
newPedalboard.selectedPlugin = fromItem.instanceId; newPedalboard.selectedPlugin = fromItem.instanceId;
if (!toItem.isEmpty()) {
this.updateSidechainReferences(newPedalboard, toItem.instanceId, fromItem.instanceId);
}
this.setModelPedalboard(newPedalboard); this.setModelPedalboard(newPedalboard);
this.updateServerPedalboard(); this.updateServerPedalboard();
@@ -3545,29 +3556,67 @@ export class PiPedalModel //implements PiPedalModel
} }
requestBankPresets(bankInstanceId: number): Promise<PresetIndexEntry[]> { requestBankPresets(bankInstanceId: number): Promise<PresetIndexEntry[]> {
return nullCast(this.webSocket).request<PresetIndexEntry[]>("requestBankPresets", {bankInstanceId: bankInstanceId}); return nullCast(this.webSocket).request<PresetIndexEntry[]>("requestBankPresets", { bankInstanceId: bankInstanceId });
} }
importPresetsFromBank(bankInstanceId: number, presets: number[]): Promise<number> { importPresetsFromBank(bankInstanceId: number, presets: number[]): Promise<number> {
return nullCast(this.webSocket).request<number>("importPresetsFromBank", {bankInstanceId: bankInstanceId, presets: presets}); return nullCast(this.webSocket).request<number>("importPresetsFromBank", { bankInstanceId: bankInstanceId, presets: presets });
} }
copyPresetsToBank(bankInstanceId: number, presets: number[]): Promise<number> { copyPresetsToBank(bankInstanceId: number, presets: number[]): Promise<number> {
return nullCast(this.webSocket).request<number>("copyPresetsToBank", {bankInstanceId: bankInstanceId, presets: presets}); return nullCast(this.webSocket).request<number>("copyPresetsToBank", { bankInstanceId: bankInstanceId, presets: presets });
} }
setPedalboardSideChainInput(instanceId: number, sideChainInputId: number): void { setPedalboardSideChainInput(instanceId: number, sideChainInputId: number): void {
let pedalboard = this.pedalboard.get().clone(); let pedalboard = this.pedalboard.get().clone();
let pedalboardItem = pedalboard.getItem(instanceId); let pedalboardItem = pedalboard.getItem(instanceId);
if (!pedalboardItem) if (!pedalboardItem) {
{
return; return;
} }
pedalboardItem.sideChainInputId = sideChainInputId; pedalboardItem.sideChainInputId = sideChainInputId;
pedalboardItem.instanceId = ++pedalboard.nextInstanceId; let oldId = pedalboardItem.instanceId;
let newId = ++pedalboard.nextInstanceId;
pedalboardItem.instanceId = newId; // force reload of pedalboard.
pedalboard.selectedPlugin = pedalboardItem.instanceId; pedalboard.selectedPlugin = pedalboardItem.instanceId;
this.updateSidechainReferences(pedalboard, oldId, newId);
this.setModelPedalboard(pedalboard); this.setModelPedalboard(pedalboard);
this.updateServerPedalboard(); this.updateServerPedalboard();
} }
removeInvalidSidechains(pedalboard: Pedalboard) {
let it = pedalboard.itemsGeneratorSplitAfter();
let previousItemIds: Set<number> = new Set<number>();
previousItemIds.add(-2); // start is visible.
while (true) {
let r = it.next();
if (r.done) {
break;
}
let item = r.value;
if (item.sideChainInputId !== -1) {
if (!previousItemIds.has(item.sideChainInputId)) {
item.sideChainInputId = -1;
}
}
if (!item.isEmpty()) { // empty items are not valid sidechain targets.
previousItemIds.add(item.instanceId);
}
}
}
updateSidechainReferences(pedalboard: Pedalboard, oldItemId: number, newItemId: number) {
let it = pedalboard.itemsGenerator();
while (true) {
let r = it.next();
if (r.done) break;
let item = r.value;
if (item.sideChainInputId === oldItemId) {
item.sideChainInputId = newItemId;
}
}
this.removeInvalidSidechains(pedalboard);
}
}; };
let instance: PiPedalModel | undefined = undefined; let instance: PiPedalModel | undefined = undefined;
+10 -5
View File
@@ -24,7 +24,7 @@ import CloseIcon from '@mui/icons-material/Close';
import AppBar from '@mui/material/AppBar'; import AppBar from '@mui/material/AppBar';
import Toolbar from '@mui/material/Toolbar'; import Toolbar from '@mui/material/Toolbar';
import CssBaseline from '@mui/material/CssBaseline'; import CssBaseline from '@mui/material/CssBaseline';
import {createStyles} from './WithStyles'; import { createStyles } from './WithStyles';
import { withStyles } from "tss-react/mui"; import { withStyles } from "tss-react/mui";
import IconButtonEx from './IconButtonEx'; import IconButtonEx from './IconButtonEx';
@@ -148,10 +148,12 @@ const SnapshotEditor = withStyles(
this.model_.zoomedUiControl.addOnChangedHandler( this.model_.zoomedUiControl.addOnChangedHandler(
() => { () => {
this.setState({ if (this.mounted93) {
zoomedControlOpen: this.model_.zoomedUiControl.get() !== undefined, this.setState({
zoomedControlInfo: this.model_.zoomedUiControl.get() zoomedControlOpen: this.model_.zoomedUiControl.get() !== undefined,
}); zoomedControlInfo: this.model_.zoomedUiControl.get()
});
}
} }
); );
@@ -182,9 +184,11 @@ const SnapshotEditor = withStyles(
this.setState({ isFullScreen: !this.state.isFullScreen }); this.setState({ isFullScreen: !this.state.isFullScreen });
} }
private mounted93: boolean = false;
componentDidMount() { componentDidMount() {
super.componentDidMount(); super.componentDidMount();
this.mounted93 = true;
this.model_.showStatusMonitor.addOnChangedHandler(this.showStatusMonitorHandler); this.model_.showStatusMonitor.addOnChangedHandler(this.showStatusMonitorHandler);
} }
@@ -206,6 +210,7 @@ const SnapshotEditor = withStyles(
} }
componentWillUnmount() { componentWillUnmount() {
this.mounted93 = false;
super.componentWillUnmount(); super.componentWillUnmount();
this.model_.banks.removeOnChangedHandler(this.showStatusMonitorHandler); this.model_.banks.removeOnChangedHandler(this.showStatusMonitorHandler);
} }