feat: Split toggle - show input/output as separate nodes
- Toggle button next to 'Merge Nodes' in toolbar - When active: skips merge rules, each PipeWire node shown separately - Green=output, red=input (no confusing duplex merging) - Defaults to off (merged mode)
This commit is contained in:
@@ -42,6 +42,7 @@
|
|||||||
let showProfileDialog = $state(false);
|
let showProfileDialog = $state(false);
|
||||||
let showRuleDialog = $state(false);
|
let showRuleDialog = $state(false);
|
||||||
let showVirtualMenu = $state(false);
|
let showVirtualMenu = $state(false);
|
||||||
|
let splitNodes = $state(false);
|
||||||
let showNetworkDialog = $state<{ type: string } | null>(null);
|
let showNetworkDialog = $state<{ type: string } | null>(null);
|
||||||
let netHost = $state('127.0.0.1');
|
let netHost = $state('127.0.0.1');
|
||||||
let netPort = $state('4713');
|
let netPort = $state('4713');
|
||||||
@@ -138,25 +139,26 @@
|
|||||||
// Filter hidden nodes
|
// Filter hidden nodes
|
||||||
let visible = n.filter(nd => !isNodeHidden(nd.name));
|
let visible = n.filter(nd => !isNodeHidden(nd.name));
|
||||||
|
|
||||||
// Merge nodes by prefix
|
// Merge nodes by prefix (unless split mode)
|
||||||
const merged = new Map<string, typeof visible[0]>();
|
if (!splitNodes) {
|
||||||
for (const nd of visible) {
|
const merged = new Map<string, typeof visible[0]>();
|
||||||
const mergedName = getMergedName(nd.name);
|
for (const nd of visible) {
|
||||||
const existing = merged.get(mergedName);
|
const mergedName = getMergedName(nd.name);
|
||||||
if (existing) {
|
const existing = merged.get(mergedName);
|
||||||
existing.port_ids = [...new Set([...existing.port_ids, ...nd.port_ids])];
|
if (existing) {
|
||||||
existing.name = mergedName;
|
existing.port_ids = [...new Set([...existing.port_ids, ...nd.port_ids])];
|
||||||
// If merged node has both input and output ports, mark as duplex
|
existing.name = mergedName;
|
||||||
const mergedInPorts = existing.port_ids.map(pid => portMap.get(pid)).filter((p): p is Port => !!p && p.mode === 'input');
|
const mergedInPorts = existing.port_ids.map(pid => portMap.get(pid)).filter((p): p is Port => !!p && p.mode === 'input');
|
||||||
const mergedOutPorts = existing.port_ids.map(pid => portMap.get(pid)).filter((p): p is Port => !!p && p.mode === 'output');
|
const mergedOutPorts = existing.port_ids.map(pid => portMap.get(pid)).filter((p): p is Port => !!p && p.mode === 'output');
|
||||||
if (mergedInPorts.length > 0 && mergedOutPorts.length > 0) {
|
if (mergedInPorts.length > 0 && mergedOutPorts.length > 0) {
|
||||||
existing.mode = 'duplex';
|
existing.mode = 'duplex';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
merged.set(mergedName, { ...nd, name: mergedName });
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
merged.set(mergedName, { ...nd, name: mergedName });
|
|
||||||
}
|
}
|
||||||
|
visible = Array.from(merged.values());
|
||||||
}
|
}
|
||||||
visible = Array.from(merged.values());
|
|
||||||
|
|
||||||
const out = visible.filter(nd => nd.mode === 'output');
|
const out = visible.filter(nd => nd.mode === 'output');
|
||||||
const inp = visible.filter(nd => nd.mode === 'input');
|
const inp = visible.filter(nd => nd.mode === 'input');
|
||||||
@@ -464,6 +466,7 @@
|
|||||||
<!-- Dialogs -->
|
<!-- Dialogs -->
|
||||||
<button onclick={() => { showHideDialog = !showHideDialog; showMergeDialog = false; showProfileDialog = false; showRuleDialog = false; }} title="Node hiding rules">Hide Nodes</button>
|
<button onclick={() => { showHideDialog = !showHideDialog; showMergeDialog = false; showProfileDialog = false; showRuleDialog = false; }} title="Node hiding rules">Hide Nodes</button>
|
||||||
<button onclick={() => { showMergeDialog = !showMergeDialog; showHideDialog = false; showProfileDialog = false; showRuleDialog = false; }} title="Node merging rules">Merge Nodes</button>
|
<button onclick={() => { showMergeDialog = !showMergeDialog; showHideDialog = false; showProfileDialog = false; showRuleDialog = false; }} title="Node merging rules">Merge Nodes</button>
|
||||||
|
<button class="toggle" class:active={splitNodes} onclick={() => { splitNodes = !splitNodes; }} title="Show input/output as separate nodes">Split</button>
|
||||||
<button onclick={() => { showRuleDialog = !showRuleDialog; showHideDialog = false; showMergeDialog = false; showProfileDialog = false; }} title="Manage patchbay rules">Rules</button>
|
<button onclick={() => { showRuleDialog = !showRuleDialog; showHideDialog = false; showMergeDialog = false; showProfileDialog = false; }} title="Manage patchbay rules">Rules</button>
|
||||||
<button onclick={() => { showProfileDialog = !showProfileDialog; showHideDialog = false; showMergeDialog = false; showRuleDialog = false; }} title="Save/load profiles">Profiles</button>
|
<button onclick={() => { showProfileDialog = !showProfileDialog; showHideDialog = false; showMergeDialog = false; showRuleDialog = false; }} title="Save/load profiles">Profiles</button>
|
||||||
<button onclick={() => { showVirtualMenu = !showVirtualMenu; showHideDialog = false; showMergeDialog = false; showProfileDialog = false; showRuleDialog = false; }} title="Add virtual device">+ Add</button>
|
<button onclick={() => { showVirtualMenu = !showVirtualMenu; showHideDialog = false; showMergeDialog = false; showProfileDialog = false; showRuleDialog = false; }} title="Add virtual device">+ Add</button>
|
||||||
|
|||||||
Reference in New Issue
Block a user