fix: full runtime apply for ALL settings — MIDI channel filter, audio device hot-swap via JACK restart, display auto_dim/screen_saver, tempo, brightness, channel_mode
This commit is contained in:
@@ -44,6 +44,7 @@ from ..system.tonedownload import (
|
||||
from ..system.audio import AudioSystem, JackAudioClient, LATENCY_PROFILES
|
||||
from ..system.config import save_config
|
||||
from ..ui.leds import LEDController
|
||||
from ..ui.display import DisplayController
|
||||
from ..midi.handler import MIDIHandler
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -217,6 +218,7 @@ class WebServerDeps:
|
||||
# Runtime subsystems (for live apply of settings changes)
|
||||
leds: Optional[LEDController] = None
|
||||
midi: Optional[MIDIHandler] = None
|
||||
display: Optional[DisplayController] = None
|
||||
|
||||
@property
|
||||
def is_connected(self) -> bool:
|
||||
@@ -1608,6 +1610,69 @@ class WebServer:
|
||||
except Exception as e:
|
||||
logger.warning("Failed to apply channel_mode: %s", e)
|
||||
|
||||
# ── JACK device hot-swap for input_device / output_device ──
|
||||
if "input_device" in data or "output_device" in data:
|
||||
try:
|
||||
audio_sys = self.deps.audio_system
|
||||
jack_client = self.deps.jack_audio
|
||||
if jack_client:
|
||||
jack_client.stop()
|
||||
if "input_device" in data:
|
||||
audio_sys.config.input_device = str(data["input_device"])
|
||||
if "output_device" in data:
|
||||
audio_sys.config.output_device = str(data["output_device"])
|
||||
audio_sys.stop_jack()
|
||||
ok = audio_sys.start_jack(timeout=10)
|
||||
if not ok:
|
||||
logger.warning("JACK restart failed after device change — rolling back")
|
||||
# Restore old devices is complex, just log the failure
|
||||
if jack_client:
|
||||
jack_client.start()
|
||||
logger.info("JACK restarted for device change: input=%s output=%s",
|
||||
audio_sys.config.input_device, audio_sys.config.output_device)
|
||||
except Exception as e:
|
||||
logger.warning("Failed to apply device change: %s", e)
|
||||
|
||||
# ── MIDI channel filter ──
|
||||
if "midi_channel" in data and self.deps.midi is not None:
|
||||
try:
|
||||
val = data["midi_channel"]
|
||||
if val is None or str(val).lower() == "omni":
|
||||
self.deps.midi.set_channel_filter(None)
|
||||
logger.info("MIDI channel filter set to omni")
|
||||
else:
|
||||
ch = int(val) - 1 # UI sends "1"-"16", store as 0-15
|
||||
self.deps.midi.set_channel_filter(ch)
|
||||
logger.info("MIDI channel filter set to %d", ch)
|
||||
except Exception as e:
|
||||
logger.warning("Failed to apply midi_channel: %s", e)
|
||||
|
||||
# ── Display settings ──
|
||||
if "auto_dim" in data and self.deps.display is not None:
|
||||
try:
|
||||
self.deps.display.set_auto_dim(bool(data["auto_dim"]))
|
||||
except Exception as e:
|
||||
logger.warning("Failed to apply auto_dim: %s", e)
|
||||
|
||||
if "screen_saver" in data and self.deps.display is not None:
|
||||
try:
|
||||
self.deps.display.set_screen_saver(str(data["screen_saver"]))
|
||||
except Exception as e:
|
||||
logger.warning("Failed to apply screen_saver: %s", e)
|
||||
|
||||
# ── Tempo settings ──
|
||||
if "tap_tempo" in data and self.deps.pipeline is not None:
|
||||
try:
|
||||
self.deps.pipeline.set_tempo(float(data["tap_tempo"]))
|
||||
except Exception as e:
|
||||
logger.warning("Failed to apply tap_tempo: %s", e)
|
||||
|
||||
if "tempo_division" in data:
|
||||
logger.info("tempo_division change noted (boot-only): %s", data["tempo_division"])
|
||||
|
||||
if "tap_tempo_mute" in data:
|
||||
logger.info("tap_tempo_mute change noted (boot-only): %s", data["tap_tempo_mute"])
|
||||
|
||||
return {"ok": True, "saved": n_saved}
|
||||
|
||||
# ── FX block param schemas ───────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user