Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save nicola-lunghi/696ae98e39a48430d4249e72a1fcda99 to your computer and use it in GitHub Desktop.

Select an option

Save nicola-lunghi/696ae98e39a48430d4249e72a1fcda99 to your computer and use it in GitHub Desktop.
patch to icon scripts to enable track selection using the encoders
From c6d4bfc0bd06271878b7d4e3815b152d61d4bdc0 Mon Sep 17 00:00:00 2001
From: Nicola Lunghi <nick83ola@gmail.com>
Date: Tue, 19 May 2026 17:43:07 +0200
Subject: [PATCH] mode: add vol_vpot and pan_vpot handlers
This is the sum of two commits:
Add vol_vpot handler so track_vol_mode encoders control volume
Previously track_vol_mode had no vpot entry in manager_capabilities,
so it fell back to standard_vpot (pan). Now vol_vpot is wired in for
track_vol_mode, and track_pan_mode is explicitly mapped to standard_vpot.
standard_mode encoder press selects track; pan_vpot handles track_pan_mode reset
- standard_vpot press now selects the corresponding track
- pan_vpot.py is a new handler for track_pan_mode with the original
press-to-reset-pan behavior (and press-to-unity-gain in flip mode)
---
.../v1_core/manager_capabilities.py | 15 ++-
.../v1_handlers/pan_vpot.py | 91 +++++++++++++++++++
.../v1_handlers/standard_vpot.py | 21 +----
.../v1_handlers/vol_vpot.py | 66 ++++++++++++++
4 files changed, 170 insertions(+), 23 deletions(-)
create mode 100644 Icon_V_and_P_Series_Ableton/v1_handlers/pan_vpot.py
create mode 100644 Icon_V_and_P_Series_Ableton/v1_handlers/vol_vpot.py
diff --git a/Icon_V_and_P_Series_Ableton/v1_core/manager_capabilities.py b/Icon_V_and_P_Series_Ableton/v1_core/manager_capabilities.py
index da68ba3..b138431 100644
--- a/Icon_V_and_P_Series_Ableton/v1_core/manager_capabilities.py
+++ b/Icon_V_and_P_Series_Ableton/v1_core/manager_capabilities.py
@@ -2,10 +2,13 @@
from ..v1_handlers import (
standard_bank,
standard_vpot,
+ pan_vpot,
+ vol_vpot,
plugin_vpot,
plugin2_vpot,
send_vpot,
input_vpot,
+ vol_vpot,
standard_fader,
send_fader,
standard_fader_m,
@@ -64,11 +67,13 @@ bank_manager_capabilities = {
# Vpot manager
vpot_manager_capabilities = {
- "standard_mode": standard_vpot,
- "plugin_mode": plugin_vpot,
- "plugin2_mode": plugin2_vpot,
- "send_mode": send_vpot,
- "input_mode": input_vpot,
+ "standard_mode": standard_vpot,
+ "track_pan_mode": pan_vpot,
+ "track_vol_mode": vol_vpot,
+ "plugin_mode": plugin_vpot,
+ "plugin2_mode": plugin2_vpot,
+ "send_mode": send_vpot,
+ "input_mode": input_vpot,
}
# Fader manager
diff --git a/Icon_V_and_P_Series_Ableton/v1_handlers/pan_vpot.py b/Icon_V_and_P_Series_Ableton/v1_handlers/pan_vpot.py
new file mode 100644
index 0000000..b0518b3
--- /dev/null
+++ b/Icon_V_and_P_Series_Ableton/v1_handlers/pan_vpot.py
@@ -0,0 +1,91 @@
+# === FLIP MODE SWITCH ===
+from ..v1_core.switch_manager import get as flip_state
+
+# === ADJUST: HARDWARE → DAW (Hardware CH 0–7)
+def adjust(payload):
+ D1 = payload["data1"]
+ D2 = payload["data2"]
+ HT = payload["tracks"]
+ DM = payload["daw_map"]
+ AD = payload["addr"]
+ TT = payload["temp_text"]
+
+ flip_mode = flip_state("flip")
+
+ OS = D1 - AD.PAN1_OS
+ DT = DM.DAW_TRACK(HT[OS])
+ POS1 = DM.PAN_GET(DT) if not flip_mode else DM.FADER_GET(DT)
+ DIR = -1.0 if (D2 & AD.PAN_DIR) else 1.0
+ STEP = 0.05
+ POS2 = float(POS1) + (DIR * STEP)
+ CLAMP = max(-1.0 if not flip_mode else 0.0, min(1.0, POS2))
+
+ if not flip_mode:
+ DM.PAN_SET(DT, CLAMP)
+ TT.SHOW_TEMP(OS, "Pan:", DM.TRACK_PAN(DT))
+ else:
+ DM.FADER_SET(DT, CLAMP)
+ TT.SHOW_TEMP(OS, "Vol:", DM.TRACK_DB(DT))
+
+# === PRESS: HARDWARE (Hardware CH 0–7) — center pan / unity gain
+def press(payload):
+ DM = payload["daw_map"]
+ D1 = payload["data1"]
+ TT = payload["temp_text"]
+ AD = payload["addr"]
+ HT = payload["tracks"]
+
+ flip_mode = flip_state("flip")
+
+ OS = D1 - AD.PAN2_OS
+ DT = DM.DAW_TRACK(HT[OS])
+
+ if not flip_mode:
+ DM.PAN_SET(DT, 0.00)
+ TT.SHOW_TEMP(OS, "Pan:", DM.TRACK_PAN(DT))
+ else:
+ DM.FADER_SET(DT, 0.85)
+ TT.SHOW_TEMP(OS, "Vol:", DM.TRACK_DB(DT))
+
+# === REFRESH: DAW → HARDWARE (Hardware CH 0–7)
+def refresh(payload):
+ HT = payload["tracks"]
+ DM = payload["daw_map"]
+ AD = payload["addr"]
+
+ flip_mode = flip_state("flip")
+
+ MODE = AD.MODE_PAN << 4
+ FDPV = 16383.0
+ PDPV = 10
+
+ for i in range(8):
+ CC = AD.VPOT_CC
+
+ if not DM.HAS_AUDIO(payload, i):
+ if not flip_mode:
+ DM.SEND_DAW(payload, DM._3_BYTE_MSG(CC, AD.VPOT_OS + i, 0x00))
+ else:
+ DM.SEND_DAW(payload, DM._3_BYTE_MSG(AD.PITCH_BEND_OS + i, 0, 0))
+ else:
+ DT = DM.DAW_TRACK(HT[i])
+ VALUE = DM.PAN_GET(DT)
+ CLAMP = max(-1.0, min(1.0, VALUE))
+ NV = (CLAMP + 1.0) / 2
+ POS = int(NV * PDPV) if not flip_mode else int(NV * FDPV + 0.5)
+ D1 = AD.VPOT_OS + i if not flip_mode else POS & 0x7F
+ D2 = MODE | (1 + POS) if not flip_mode else (POS >> 7) & 0x7F
+
+ if not flip_mode:
+ DM.SEND_DAW(payload, DM._3_BYTE_MSG(CC, D1, D2))
+ else:
+ DM.SEND_DAW(payload, DM._3_BYTE_MSG(AD.PITCH_BEND_OS + i, D1, D2))
+
+# === RESET: DAW → HARDWARE (Hardware CH 0–7)
+def reset(payload):
+ DM = payload["daw_map"]
+ AD = payload["addr"]
+
+ CC = AD.VPOT_CC
+ for i in range(8):
+ DM.SEND_DAW(payload, DM._3_BYTE_MSG(CC, AD.VPOT_OS + i, 0x00))
diff --git a/Icon_V_and_P_Series_Ableton/v1_handlers/standard_vpot.py b/Icon_V_and_P_Series_Ableton/v1_handlers/standard_vpot.py
index 40be4c9..2c147df 100644
--- a/Icon_V_and_P_Series_Ableton/v1_handlers/standard_vpot.py
+++ b/Icon_V_and_P_Series_Ableton/v1_handlers/standard_vpot.py
@@ -71,29 +71,14 @@ def refresh(payload):
else: # FLIP ON
DM.SEND_DAW(payload, DM._3_BYTE_MSG(AD.PITCH_BEND_OS + i, D1, D2))
-# === PRESS: HARDWARE (Hardware CH 0–7) — center pan
+# === PRESS: HARDWARE (Hardware CH 0–7) — select track
def press(payload):
- # PAYLOAD IMPORTS
DM = payload["daw_map"]
D1 = payload["data1"]
- TT = payload["temp_text"]
AD = payload["addr"]
- HT = payload["tracks"]
-
- # === FLIP MODE SWITCH ===
- flip_mode = flip_state("flip")
-
- # CALCULATIONS
- OS = D1 - AD.PAN2_OS # Offset - Hardware Track
- DT = DM.DAW_TRACK(HT[OS]) # Which Daw Track / Hardware Track Combination
- # SEND: DAW → HARDWARE
- if not flip_mode: # FLIP OFF
- DM.PAN_SET(DT, 0.00)
- TT.SHOW_TEMP(OS, "Pan:", DM.TRACK_PAN(DT)) # TEMP TEXT
- else: # FLIP ON
- DM.FADER_SET(DT, 0.85)
- TT.SHOW_TEMP(OS, "Vol:", DM.TRACK_DB(DT)) # TEMP TEXT
+ OS = D1 - AD.PAN2_OS
+ DM.SELECT_SET(payload, OS)
# === RESET: DAW → HARDWARE (Hardware CH 0–7)
def reset(payload):
diff --git a/Icon_V_and_P_Series_Ableton/v1_handlers/vol_vpot.py b/Icon_V_and_P_Series_Ableton/v1_handlers/vol_vpot.py
new file mode 100644
index 0000000..60a07ad
--- /dev/null
+++ b/Icon_V_and_P_Series_Ableton/v1_handlers/vol_vpot.py
@@ -0,0 +1,66 @@
+# === ADJUST: HARDWARE → DAW (Hardware CH 0–7)
+def adjust(payload):
+ D1 = payload["data1"]
+ D2 = payload["data2"]
+ HT = payload["tracks"]
+ DM = payload["daw_map"]
+ AD = payload["addr"]
+ TT = payload["temp_text"]
+
+ OS = D1 - AD.PAN1_OS
+ DT = DM.DAW_TRACK(HT[OS])
+ POS1 = DM.FADER_GET(DT)
+ DIR = -1.0 if (D2 & AD.PAN_DIR) else 1.0
+ STEP = 0.05
+ POS2 = float(POS1) + (DIR * STEP)
+ CLAMP = max(0.0, min(1.0, POS2))
+
+ DM.FADER_SET(DT, CLAMP)
+ TT.SHOW_TEMP(OS, "Vol:", DM.TRACK_DB(DT))
+
+# === PRESS: HARDWARE (Hardware CH 0–7) — reset to unity gain
+def press(payload):
+ DM = payload["daw_map"]
+ D1 = payload["data1"]
+ TT = payload["temp_text"]
+ AD = payload["addr"]
+ HT = payload["tracks"]
+
+ OS = D1 - AD.PAN2_OS
+ DT = DM.DAW_TRACK(HT[OS])
+
+ DM.FADER_SET(DT, 0.85)
+ TT.SHOW_TEMP(OS, "Vol:", DM.TRACK_DB(DT))
+
+# === REFRESH: DAW → HARDWARE (Hardware CH 0–7)
+def refresh(payload):
+ HT = payload["tracks"]
+ DM = payload["daw_map"]
+ AD = payload["addr"]
+
+ MODE = AD.MODE_DOT << 4 # fill-from-left, suits a 0–1 fader range
+ PDPV = 10 # 11 discrete positions (0–10)
+
+ for i in range(8):
+ CC = AD.VPOT_CC
+
+ if not DM.HAS_AUDIO(payload, i):
+ DM.SEND_DAW(payload, DM._3_BYTE_MSG(CC, AD.VPOT_OS + i, 0x00))
+ else:
+ DT = DM.DAW_TRACK(HT[i])
+ VALUE = DM.FADER_GET(DT)
+ CLAMP = max(0.0, min(1.0, VALUE))
+ POS = int(CLAMP * PDPV)
+ D1 = AD.VPOT_OS + i
+ D2 = MODE | (1 + POS)
+
+ DM.SEND_DAW(payload, DM._3_BYTE_MSG(CC, D1, D2))
+
+# === RESET: DAW → HARDWARE (Hardware CH 0–7)
+def reset(payload):
+ DM = payload["daw_map"]
+ AD = payload["addr"]
+
+ CC = AD.VPOT_CC
+ for i in range(8):
+ DM.SEND_DAW(payload, DM._3_BYTE_MSG(CC, AD.VPOT_OS + i, 0x00))
--
2.54.0.windows.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment