From 80011274f2849c109a716c811167f9b553e7273b Mon Sep 17 00:00:00 2001 From: Shawn Date: Mon, 8 Jun 2026 10:39:38 -0400 Subject: [PATCH] Add 4CM routing fields to Preset data model MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add routing_mode (mono/4cm) and routing_breakpoint (default 7) to Preset - Serialize/deserialize in _preset_to_dict / _preset_from_dict - Backward compatible — old presets default to mono/7 - Add get_4cm_config() / set_4cm_config() helpers on PresetManager - set_4cm_config validates mode and saves back to disk - All 48 related tests pass (46 preset + 2 integration activation) --- src/presets/manager.py | 36 ++++++++++++++++++++++++++++++++++++ src/presets/types.py | 4 ++++ 2 files changed, 40 insertions(+) diff --git a/src/presets/manager.py b/src/presets/manager.py index 97b9c23..e8599ee 100644 --- a/src/presets/manager.py +++ b/src/presets/manager.py @@ -44,6 +44,8 @@ def _preset_to_dict(preset: Preset) -> dict: "bank": preset.bank, "program": preset.program, "master_volume": preset.master_volume, + "routing_mode": preset.routing_mode, + "routing_breakpoint": preset.routing_breakpoint, "tuner_enabled": preset.tuner_enabled, "chain": [ { @@ -99,6 +101,8 @@ def _preset_from_dict(data: dict) -> Preset: chain=chain, midi_mappings=midi_mappings, master_volume=data.get("master_volume", 0.8), + routing_mode=data.get("routing_mode", "mono"), + routing_breakpoint=data.get("routing_breakpoint", 7), tuner_enabled=data.get("tuner_enabled", False), ) @@ -332,6 +336,38 @@ class PresetManager: logger.info("Reordered preset at (%d,%d) → (%d,%d)", bank, program, bank, new_program) + # ── 4CM routing config ────────────────────────────────────────────── + + def get_4cm_config(self, preset: Preset) -> tuple[str, int]: + """Return (routing_mode, routing_breakpoint) from a preset. + + Returns: + Tuple of ``(routing_mode, routing_breakpoint)``. + """ + return (preset.routing_mode, preset.routing_breakpoint) + + def set_4cm_config( + self, preset: Preset, mode: str, breakpoint: int = 7 + ) -> None: + """Set 4CM routing configuration on a preset in-place and save it. + + Args: + preset: The preset to modify. + mode: ``\"mono\"`` or ``\"4cm\"``. + breakpoint: Chain index where the pre/post split occurs + (default 7 = after IR_CAB, before mod FX). + + Raises: + ValueError: If ``mode`` is not ``\"mono\"`` or ``\"4cm\"``. + """ + if mode not in ("mono", "4cm"): + raise ValueError(f"routing_mode must be 'mono' or '4cm', got {mode!r}") + preset.routing_mode = mode + preset.routing_breakpoint = breakpoint + self.save(preset) + logger.info("Set 4CM config on '%s': mode=%s breakpoint=%d", + preset.name, mode, breakpoint) + # ── Bank management ───────────────────────────────────────────────────── def list_banks(self) -> list[Bank]: diff --git a/src/presets/types.py b/src/presets/types.py index d1cc783..0534009 100644 --- a/src/presets/types.py +++ b/src/presets/types.py @@ -60,6 +60,10 @@ class Preset: master_volume: float = 0.8 tuner_enabled: bool = False + # 4-Cable Method routing + routing_mode: str = "mono" # "mono" or "4cm" + routing_breakpoint: int = 7 # chain index where pre/post split occurs + @dataclass class Bank: