Documentation

These guides cover how TDMap works once it's in your project: MIDI modes (relative and 14-bit), multi-device banks with hardware bank sync, bulk operator mapping, Pro workflows (function, slot, and modify modes), button scripts, and the public TDMap API.

New to TDMap? Start with Why MIDI mapping in TD is painful (about 13 min video, plus free alternatives), then Install TDMap to add the component to your project, and The TDMap button to open the interface. Prefer the full walkthrough? See the video tutorial (46 min on YouTube). Pick any topic from the sidebar, or press Ctrl+K to search.

MIDI channels, CC, and note indices in TDMap are 1-based (1–16 and 1–128), matching TouchDesigner. See Assigning parameters → MIDI numbering.

Reference#

Quick links to the settings and the script API:

Full video tutorial

~46 min on YouTube. Play below, or expand the chapter list to jump to a segment. Each doc topic also has timestamp links further down.

Open on YouTube ↗
Chapter list (23)
TimeChapterDocs
Introduction
Install & project setup Install TDMap, The TDMap button
Authentication & trial Install TDMap
UI walkthrough The TDMap button, Preferences, Keyboard shortcuts, Clearing mappings, MIDI Device Manager
Devices, presets & custom layouts Devices & library, Factory presets, MIDI Device Manager, 14-bit MIDI
Unassigned MIDI Unassigned MIDI, The TDMap button
Assigning parameters Assigning parameters, Hover mode
Bulk operator assign Bulk operator assign
Retargeting paths Banks & retargeting
Undo Preferences
Absolute controls, 14-bit, filter & easing Filter, pickup & easing, 14-bit MIDI
Buttons & count mode Buttons, Count & set value
Relative encoders Relative knobs
Alternate knob Alternate knob
Piano keys & velocity Buttons
Function mode Functions
Button scripts Button scripts
Slot mode Slot mode (◈)
Modify mode Modifiers
Banks & hardware bank sync Banks & retargeting
Public API & callbacks Public interface, Callbacks
In-app updates Install TDMap
Closing tips Install TDMap

MIDI mapping in TouchDesigner#

Wiring MIDI In CHOPs, Math, Logic, exports, and expressions per control works for a one-off knob. It does not stay workable when you remap hardware, restart the project, or add banks and several controllers. The video above walks through that problem on a demo network, compares two free mapping tools, and shows what TDMap adds when you need more.

Free alternatives#

TDMap was inspired by community mapping tools that came first. If you want something narrower and free, start here:

  • Galileo Mapper (PlusPlusOne GmbH): one component, Learn on, drag a parameter, move a fader or knob. Great for quick absolute knob and fader mapping. No toggle buttons, 14-bit MIDI, relative encoders, or MIDI feedback in the same package.
  • Zuweiser (Markus Heckmann): hover a parameter, move a control, get an export bind. Lookup curves and a multiplier source CHOP for ganged controls. No pickup (values can jump), and the same gaps on buttons, 14-bit, relative encoders, and MIDI out as most lightweight mappers.

Both are solid when you only need a subset of that. TDMap targets full rigs: multi-device grids, banks, all control types, config library, in-app updates, and the Pro behavior layers (filter, pickup, slot mode, modify, and more). See Install TDMap when you are ready to try it.

More video#

Install TDMap#

Video tutorial

This page spans several parts of the video tutorial. Jump to:

TDMap ships as a single .tox component that you drop into a TouchDesigner project. Download TDMap.tox from the home page, then follow the steps below to add it and connect your hardware.

Requirements#

  • TouchDesigner 2023.12120 or newer.
  • TouchDesigner 2025.32460 or newer if you want the optimized native 14-bit MIDI path (older builds fall back to a legacy pipeline). See 14-bit MIDI.

Adding the component#

  1. Drag TDMap.tox onto the project root (/). Keep one instance per project.
  2. Pulse Externalize on the TDMap COMP (see below). Do this once, right after the first drop and before you save the project as a TouchDesigner startup file or build a template .toe you reuse across sessions.
  3. TouchDesigner loads the component and adds the TDMap button to the top-right of its UI. Click that button to open the TDMap web interface.
  4. Click the devices icon in the toolbar to open the MIDI Device Manager. Add each controller as an input (and output for LED feedback), plug in your hardware, then click Check MIDI Devices so TDMap registers them.

TDMap edits the same /local/midi/device table that TouchDesigner uses, so you don't need TD's separate MIDI Device Mapper.

Externalize#

Externalize is a pulse parameter on the TDMap component (open the COMP's parameter dialog: middle-click the TDMap button, or select /TDMap in the network). Pulse it once after your first install.

What it does:

  • Saves TDMap to {app.userPaletteFolder}/TDMap/TDMap.tox (TouchDesigner's user palette folder).
  • Switches the COMP in your project to an external reference (externaltox + Enable External .tox), so the project points at that palette file instead of embedding a copy inside the .toe.
  • If the config sibling (TDMap_Config) is not linked yet, pulses Configrepocreate so mappings are stored in an external config COMP on disk as well.

Why pulse it before a startup project:

TouchDesigner's Edit → Preferences → General → Start Up File (or a custom template .toe you open every day) should reference TDMap externally, not embed a frozen copy of the download. Externalizing first means:

  • In-place updates from TDMap's updater repoint the same palette path and reload; every project that references it picks up the new build.
  • One palette install can back multiple .toe files (show file, template, startup project) without duplicating the component.

If you already mapped before externalizing, your layouts are kept; externalizing does not wipe assignments. It is still best to externalize immediately after the first drop so you never save a startup .toe with an embedded copy by accident.

Typical order: download → drop on / → pulse Externalize → save startup / template project -> create devices -> map controllers.

First mapping#

  1. Drag a parameter from TouchDesigner onto the TDMap button, then move a control on your controller. TDMap detects the control type and creates the mapping. See Assigning parameters.
  2. Create a device to lay your controls out in a grid. See Devices & library.
  3. Run Learn All CC (right-click the grid) to capture your whole controller at once.

Your mappings are safe across updates. TDMap stores device, bank, and parameter mappings in a separate TDMap_Config component. Pulse Externalize after the first drop so both TDMap and the config sibling live as external .tox files under your palette folder; in-app updates then swap the palette copy without touching your saved layouts.

The TDMap button#

Video tutorial

This page spans several parts of the video tutorial. Jump to:

Installing TDMap adds a button to the top-right corner of the TouchDesigner UI. Use it to open the TDMap interface, queue parameters for mapping, and toggle Learn without reaching for the keyboard. If you haven't added TDMap yet, see Install TDMap.

What each input does#

Input What it does
Left-click Opens the TDMap web interface in a floating window (same as Alt+Shift+D).
Drag and drop Drop a parameter to queue it for mapping, or drop a whole operator or COMP onto the TDMap COMP to bulk-assign its parameters. See Assigning parameters and Bulk operator assign.
Right-click Toggles global Learn mode (same as Ctrl+L or the toolbar L button).
Middle-click Opens this component's parameter dialog in TouchDesigner.

Button color#

The button's color tells you which mode TDMap is in:

  • Blue: idle. TDMap is running and ready, with no learning or pickup in progress.
  • Yellow: Learn is active. The next MIDI message you send creates or retargets a mapping. Toggle it off with a right-click, Ctrl+L, or the toolbar L button.
  • Pink: pickup is waiting. One or more controls hold their parameter until you move the hardware through the current value, so banks and presets don't jump. The web interface highlights which slots are waiting in the grid. See Filter, pickup & easing.

Parameter dialog tint (optional)#

While Learn is active, TDMap can also tint TouchDesigner's parameter dialog yellow (on by default in Preferences). That redraws TD's UI and can drop frames on heavy projects. Turn the pref off if you'd rather skip it; the button color above still shows Learn and pickup state.

Devices & library#

Video tutorial

This topic is covered in the video tutorial at:

Each device is one MIDI controller layout: grid size, default MIDI channel, physical midi_id, an optional piano keyboard, and one or more banks of mappings. Create devices with + Device (empty grid), or import a factory or saved preset from the toolbar Library.

Add Device & library load#

The Add Device dialog walks through name, MIDI device, channel, grid rows/columns, and optional piano keys. Expand Advanced to set:

  • Default ownerComp: the script namespace root for button scripts on this device (overridable per bank and per slot).
  • Hardware bank sync (SysEx template): a device-wide hex template for controllers that switch banks via SysEx (same format as ⚙ Device settings).

Load and Load as… from the library open the same dialog with the preset's name, channel, grid, keys, and Advanced fields pre-filled. MIDI device names are fuzzy-matched to your system's configured devices (for example, Arturia MiniLab resolves to Minilab3 MIDI).

Factory presets#

TDMap ships ready-made layouts for popular controllers (APC40 MkII, Launch Control family, Arturia MiniLab, Intech grids, Midi Fighter Twister, Traktor F1, and more). Open Device Manager → Library → Factory Presets and click Load or Load as…. You don't need a preset to map hardware: any controller works through Unassigned MIDI first.

Full list, load workflow, and per-device notes: Factory presets.

What the library saves#

Saved device configs and global configs persist outside the TDMap COMP, so mappings survive component updates. A device bundle includes:

  • Grid layout, default MIDI channel, midi_id, and piano keyboard settings
  • Device script_owner_comp, bank_sysex_template, and bank_sysex_index_base
  • Per-bank assignments, hover, slot-mode / function / modify data, push assignments (including Alternate Knob), slot names, and per-bank hardware sync (SysEx / CC / Note)
  • Per-bank script_owner_comp defaults and bank MIDI overrides

Global configs (including the default auto-saved layout) also store midi_device_rows — a snapshot of TouchDesigner's /local/midi/device table (input, output, and channel per MIDI device ID). Use MIDI Device Manager → Restore from saved… to re-apply that wiring on a new machine or after TD clears the table.

Factory presets are layout templates shipped inside the .tox (see Factory presets for the full device list). Script-mode slots revert to assignment when saved as factory. Your own saved layouts keep script text. Export and import library JSON from the Library panel to back up or share bundles between machines.

Right-click a device tab for Save config, Retarget paths, Clear all params / Clear all assignments (see Clearing mappings), or Remove device.

Factory presets#

Video tutorial

This topic is covered in the video tutorial at:

TDMap ships factory presets inside the .tox: pre-built slot grids with MIDI routing for common controllers. They are layout templates (assignments are yours to fill). Load one when you want a head start; you don't need a preset to use TDMap at all.

Any controller works without a preset#

Plug in any class-compliant MIDI hardware TouchDesigner can see and start mapping immediately:

  1. Toggle Learn and move your controls. With Smart Learn on (default), TDMap classifies knobs, faders, buttons, and relative encoders automatically.
  2. Captured controls land in the Unassigned panel until you promote them.
  3. Click + Create Device on an unassigned group when you want a named grid, or use + Device to define rows, columns, and MIDI channel first.

No factory preset, no manual CC spreadsheet, no CHOP wiring. Factory layouts are optional shortcuts for hardware TDMap already knows well.

Loading a factory preset#

  1. Open the Device Manager (toolbar devices icon).
  2. Open the Library tab → Factory Presets.
  3. Click Load to create a new device from the template, or Load as… to review name, MIDI device, channel, and grid size before confirming. Apply to… copies only the slot layout onto an existing device.

Load as… fuzzy-matches the preset name to your TouchDesigner MIDI device list (for example, Arturia MiniLab Mk IIMinilab3 MIDI). Confirm the MIDI Device dropdown before you finish.

Factory presets are layout templates: script mode slots revert to assignment when saved back as factory. Your own saved library configs keep script text.

Included factory layouts#

The list below is what ships in the current .tox. Names link to the hardware. Intech presets expand for Grid Editor, Profile Cloud, and setup notes.

Intech Grid devices. Intech hardware is highly configurable using their Grid Editor. The three Intech factory presets below are layouts created for those devices; matching profiles live on the Intech Profile Cloud under the same names as the TDMap factory device. Drop a cloud profile onto your device, then Load the TDMap factory preset to map and extend that layout in TouchDesigner.

Intech EN16 Rel

Sixteen relative encoders in a 4×4 grid. All slots use relative protocol; set global or per-slot step mode in Preferences or the inspector if you want fixed steps.

Intech EF44 Rel+14bit

Relative encoders with 14-bit enabled on the fine controls. Read 14-bit MIDI before adding another control on the same channel at MSB + 32.

Intech TEK2 RelSlots

Relative encoder layout with slot-mode (◈) controls pre-placed for instrument-style parameter switching (Pro). Assign slot targets after load, or clear slot mode if you only need direct parameter maps.

Intech VSN1 integration. On the Intech Studio VSN1, TDMap can drive the built-in LCD and button LEDs when Grid Editor stays connected (websocket port 9642). Install the TDMap Grid package in Grid Editor and import the matching cloud profile on the device. On the TDMap COMP, point Vsn1 at the VSN1 manager component in your network and turn on Show on display so TDMap pushes the active parameter to the hardware screen as you map and adjust. This pairs well with Hover mode: the VSN1 display follows whatever parameter you are pointing at in TouchDesigner.

Missing your controller? If you build a solid device layout for hardware that isn't listed here, email dan+tdmap@functionstore.xyz with your TDMap_Config COMP (export the device bundle or send the relevant saved layout). If it fits the factory bar, we'll add it to a future .tox release.

See also: Devices & library, Unassigned MIDI, Assigning parameters.

Assigning parameters#

Video tutorial

This topic is covered in the video tutorial at:

There are three ways to assign a TD parameter to a slot: type the path, use PAR learn, or drag and drop from TouchDesigner. Learn (toolbar L or per-slot LRN) wires MIDI CC / note indices. To map without a device grid first, see Unassigned MIDI. To map a whole operator at once, see Bulk operator assign.

MIDI numbering#

TDMap uses 1-based indices everywhere in the UI and API, matching TouchDesigner's MIDI In DAT and MIDI CHOPs:

  • Channels: 1–16 (not 0–15).
  • CC indices: 1–128 (CC 0 in some tools is 1 in TDMap).
  • Note numbers: 1–128 (same numbering TD reports on the wire).

Grid cards and the inspector Ch / CC fields follow this convention. Learn and LRN write the values TDMap expects, so you rarely need to convert by hand.

Type the path#

Click the assignment area on a slot card (or open the inspector) and enter the operator path (for example /project1/geo1) and parameter name (for example tx), then click Set. Clear removes that assignment.

PAR learn (hover + adjust)#

PAR learn captures whatever parameter you're pointing at in the TouchDesigner UI, with no typing.

  1. Click PAR on the slot (or on a specific assignment pill in multi mode); it turns green.
  2. Hover a parameter in TouchDesigner.
  3. Either change the parameter's value (type, drag, and so on) or turn the physical encoder for that slot, and the hovered parameter is assigned on the first value change.
  4. PAR mode exits after one successful capture.

In multi-assignment mode: PAR on an existing pill replaces that index; PAR on + Assign appends a new one.

Drag and drop from TouchDesigner#

  1. In the browser, hover the slot card you want to assign (or hover an assignment row in the inspector for a specific multi index).
  2. Drag a parameter from a TD parameter panel and drop it onto the TDMap COMP (or onto the TDMap button to queue it; see below).
  3. The parameter lands on the slot you last hovered. The browser doesn't need focus; the hover target sticks until you hover something else.

You can also drag assignment pills between slots (move, or Shift-drag to copy). Slot-mode ◈ pills and regular par chips swap when dropped on the right targets.

Reveal in network editor#

Middle-click any par chip (assignment pill on a card, inspector row, slot pill, or Function-mode target) to pan the last network editor pane you used in TouchDesigner to that parameter's owner operator.

Left-click and drag still move or copy assignments; middle-click is navigation only. The browser panel doesn't need focus.

To open a new floating network editor on every middle-click instead of following your last pane, turn on Middle-click "show in pane" (floating) under Preferences.

Range, clamp & default#

Every knob/fader assignment has its own value mapping, set under the pill in the inspector:

Field What it does
Min / Max The parameter range the control sweeps between. Defaults to the parameter's own normMin / normMax; set custom values to map MIDI into a narrower (or inverted) window.
Default The value used by reset actions and reset note-off mode. Defaults to the parameter's nominal default; override to pin your own.
Clamp When on, values stay within Min/Max. With clamp off, a relative encoder can keep pushing past the edges (or use wrap / zigzag via Count).

In multi-assignment mode each parameter gets its own Min / Max / Default, so one control can drive several pars across different ranges. These mappings compose with the Pro filter, pickup & easing settings.

Param queue#

When a parameter drop has no hovered slot, it enters the Param Queue above the grid instead of assigning immediately.

Control Action
Assign the highlighted item to the currently selected slot
drag handle Drag onto any slot card or inspector assignment row
Remove one item
Clear Empty the queue

Dropping onto the TDMap button (not the COMP) also queues the parameter; open the UI and assign from there.

MIDI Learn: per-slot LRN#

LRN on a slot captures the next MIDI message as that slot's CC or note index:

  1. Click LRN on the slot; it turns green.
  2. Move the matching encoder or press the button on your controller.
  3. The index field updates (flashes green). LRN overwrites an existing index.

MIDI Learn: global (toolbar L)#

Learn mode arms MIDI capture for the whole grid:

Control Action
Toolbar L Toggle global Learn on/off
Ctrl+L / ⌘L Same (Keyboard In CHOP; works when the panel is unfocused)
Ctrl+Shift+L Momentary Learn (on while held)
TDMap button right-click Toggle Learn

With Learn on, the next MIDI traffic can create or retarget slots (behavior depends on grid state and Smart Learn; see Preferences). The TDMap button turns yellow while Learn is active, and pink when pickup is waiting.

TDMap can also tint TouchDesigner's parameter dialog yellow during Learn (on by default). That redraws TD's UI and can drop frames; turn it off under Preferences → Tint TD parameter dialog while learning. The TDMap button color is unchanged. See The TDMap button.

Queue learn#

Click LRN in the queue header (or enable Auto-enable Learn when items enter queue in Preferences):

  1. The first queue item is highlighted.
  2. Touch any control on your controller; the slot that receives the MIDI message gets that parameter.
  3. The item is removed and the next queue item becomes active.
  4. Queue learn stops when the queue is empty, or click LRN again to cancel.

If the MIDI message hits a control in the Unassigned panel, the assignment lands there instead of on the active device grid.

Smart Learn#

Smart Learn (Preferences → Smart Learn, on by default) watches the first few movements of each control during queue learn or Smart create and picks slot type and MIDI protocol for you.

Detects Sets
Absolute sweep across the byte Knob or fader (absolute)
Relative ticks (two's complement or offset-binary) Knob with Rel on and the matching step mode
MSB + LSB pair on the same control 14b fader
Note or CC press/release pattern Button: gate, latch, or velocity hardware; toggle action on latches
Varying note velocities on repeated presses Velocity hardware (pads / aftertouch-style keys)

When it runs

  • Queue learn: each new MIDI index you touch while the queue is active.
  • Smart create: toggling Learn when the grid still has empty cells or slots without a CC (midi_idx empty). TDMap walks the grid row-major, creating a slot in the next empty cell or wiring CC into an existing unmapped card.
  • Grid full: overflow slots go to Unassigned MIDI instead of stopping.

Learn-all behavior (toolbar L on a fully mapped grid): Smart create is skipped, and Learn steps through every slot in order to re-learn CC indices only. Slot types stay as they are.

Push-knob pairing: after Smart Learn creates a knob, a note on the same channel within a short window can auto-enable push on that slot (pairs a pad with the encoder you just learned).

Turn Smart Learn off in Preferences if you prefer to set Rel, 14b, and button hardware types manually; per-slot LRN still works.

Unassigned MIDI#

Video tutorial

This topic is covered in the video tutorial at:

You don't need a prepared device layout to start mapping. When MIDI arrives from hardware that doesn't match any slot on your registered devices, TDMap captures it in the Unassigned panel below the grid.

This is the recommended way to explore a new controller: plug it in, turn Learn on, move your controls, then organize the slots TDMap captured.

What shows up in Unassigned#

Source What happens
Learn with no matching slot Smart Learn (when enabled) creates a temporary slot in a hidden _unassigned_{id} store for that physical MIDI device
Grid full during Smart Learn New controls overflow into Unassigned instead of failing silently
Queue learn on an unassigned target Parameter assignment lands on the unassigned slot that received the MIDI message
Raw traffic with no device match Unmatched CC / note messages are tracked per hardware midi_id and channel

Controls are grouped by MIDI hardware (the name from TouchDesigner's MIDI device table). Each group shows how many unassigned slots exist for that controller.

Working with unassigned cards#

Unassigned cards behave like regular slot cards:

  • PAR: assign a hovered TouchDesigner parameter (same as on the main grid).
  • LRN: capture the next MIDI message as this control's index.
  • drag handle: drag onto a slot or empty cell on a registered device to move the control into that device's grid.
  • Select a card to inspect it in the right-hand panel.

Use Clear on a group header to dismiss every unassigned control from that hardware. The global Clear at the bottom of the panel removes all unassigned entries.

Create Device from Unassigned#

When you're ready to keep a layout:

  1. Open the Unassigned section for your controller.
  2. Click + Create Device on that group's header.

TDMap creates a new registered device (named after the hardware), copies all unassigned slots from that midi_id into its grid, selects the new device, and removes them from Unassigned. Set grid size and bank details afterward in Device settings if needed.

Alternatively, create a device first (+ Device in the toolbar), then drag unassigned cards onto it one at a time.

Typical workflow (no layout yet)#

  1. Register the MIDI hardware in TouchDesigner (MIDI Device Mapper) if it isn't already listed.
  2. Open TDMap and toggle Learn (toolbar L or right-click the TDMap button).
  3. Move each knob, fader, and button. With Smart Learn on (default in Preferences), TDMap classifies control type and protocol automatically.
  4. Assign parameters with PAR, drag-and-drop, or queue learn.
  5. Click + Create Device when the unassigned set looks complete, or drag cards onto an existing device.

14-bit conflicts apply in Unassigned too: a pulsing on an unassigned card means that CC collides with a 14-bit MSB/LSB pair on the same hardware. Fix the CC or channel before promoting the control to a device.

When you already have devices#

Unassigned isn't only for first-time setup. Overflow during Smart Learn on a full grid lands here. You can also drag individual controls between devices via the Unassigned panel when reorganizing.

See also: Assigning parameters (PAR, drag, Learn), Factory presets, Devices & library, and Bulk operator assign.

Bulk operator assign#

Video tutorial

This topic is covered in the video tutorial at:

Map an entire operator or COMP onto your existing controller layout in one step. Drag an operator or COMP from the TouchDesigner network onto the TDMap COMP (the web UI must be connected). A centered dialog offers Retarget and Assign. Click Or click to assign if you prefer not to drop on the Assign panel.

Bulk assign only uses controls that already exist on the device grid. It doesn't add slots, change CC numbers, or auto-expand the layout; it fills empty Par and Slot mode controls (assignment or slot push mode on buttons). On knobs and faders, the encoder primary axis stays eligible even when the push section is in function, slot (◈), alternate knob (⇧), or script mode; Modify on the primary axis still blocks assign. Function, Modify, Encoder, and Script button push modes are skipped for button slots.

Which parameters are collected#

Parameters are walked in TouchDesigner page order (the same order as the parameter dialog). Pages named About, Info, or Common are skipped.

Drop Included parameters
COMP Custom parameters only (customPars and parGroup members).
Operator All supported parameters on built-in and custom pages.

Unsupported types and parameters blocked by Protect read-only & disabled pars (Preferences) are omitted. Internal __ parameters are never included.

How parameters map to controls#

Parameter kind Target
Toggle, Pulse, Momentary Button slots first; if the button pool is exhausted on this pass, falls back to a knob or fader.
Menu, StrMenu Button slots first with Count enabled (steps menu index each press); knob/fader fallback if no buttons remain.
Float, Int, and other continuous types Knob or fader slots.

Empty controls are filled first. When every matching slot on the bank already has an assignment, the confirm dialog lists the occupied controls and lets you choose whether to replace them or assign only the empties.

Toggle / pulse / momentary pars assigned to a button get the matching button action automatically when Auto-toggle on assignment is enabled in Preferences (default on).

Menu and StrMenu pars assigned to a button automatically enable Count mode so each press steps the menu index.

Grid sections#

Many hardware layouts use blank space between groups of controls. In TDMap, insert an empty row or column via the grid + context menu (right-click the fill handle between cells). That line has no slots; it's a visual divider only.

Bulk assign respects those dividers. The grid is split into rectangular sections between empty rows and columns. Parameters fill the top-left section first (row-major within the block), then the section to its right, then the next row of sections, before spilling into a later region of the same bank.

For example, an empty column between cols 2 and 3 creates left and right panels. Every parameter assigned to the current bank lands in the left panel before any use the right panel, even if empty buttons exist on both sides.

Confirm dialog: parameters & strategy#

The confirm dialog lists every collected parameter with checkboxes; uncheck any you want to skip. Parameters are grouped by TD page, and each page has its own checkbox to toggle the whole group (indeterminate when only some are selected). Use All / None for the full list. The plan updates live as you change the selection.

Assignment strategy (collapsed by default) exposes the layout rules used while planning:

  • Prefer buttons for menu / toggle / pulse: route those parameter kinds to button slots first (off = treat them like continuous pars on knobs/faders).
  • Allow knob/fader fallback: when button slots are full, button-kind pars may use a knob or fader (only applies when the button preference is on).
  • Section-aware fill order: respect empty row/column dividers when filling the grid (off = simple grid order).
  • Fill direction: choose row by row or column by column, then set direction along each axis (eight combinations total). A 3×3 preview in the confirm dialog shows fill order (1→9). Section-aware fill still walks sections top-left → right → down before spilling within a bank.
  • Also map to alternate knob: optional second pass (default off) that fills push assignments on push-enabled knobs/faders, even when Alternate Knob isn't enabled yet. Knob-kind parameters only; button/menu pars still prefer buttons on the primary axis.
  • Piano / keyboard keys: Grid only (default) skips piano key slots; After grid spills button-kind parameters onto keys once grid buttons are full (low note first); Keys only assigns only to piano keys. Key options require the device piano keyboard to be enabled.
  • Multi-select: with several grid slots selected (Ctrl/Shift-click), bulk assign targets those controls in selection order by default. The confirm dialog also offers normal bank fill.

Confirm dialog: where to assign#

The plan runs against the target device and that device's active bank. In multi-device view, use the device picker in the Assign panel (it defaults to the grid section under your cursor when the dialog opens). The backend switches device/bank context before planning, so slot fit and overflow are per device layout.

Target Behavior
Current bank Fill empty Par/Slot controls on this bank. Optional overflow handling below.
Empty bank(s) first, then create if needed Skips the current bank. Uses existing empty banks on the device, then creates new banks until everything fits or capacity runs out.
Alternate bank Shown when another bank already has enough free button and knob slots for the full parameter list.

Overflow on the current bank#

When not everything fits on the active bank:

  • Skip: assign only what fits here; leave the rest unmapped.
  • Spill to empty banks only: chain across banks that have no assignments yet (same device).
  • Empty bank(s) first, create more if needed: same as spill, but creates additional banks when required.

The result line in the dialog reports how many parameters landed on each bank and how many couldn't be placed.

Retarget in the same dialog#

The Retarget panel is the same find/replace workflow as elsewhere: drop onto Find or Replace to prefill from the dragged path. It's handy when you meant to rewrite paths from an old operator tree rather than map the dropped COMP fresh. Full retargeting scopes: Banks & retargeting.

Single parameter drops use the normal assigning parameters workflow: hover a card in the web UI and drop one parameter onto the TDMap COMP (or onto the TDMap button to queue). Bulk assign is only for whole-operator / COMP drags.

Banks & retargeting#

Video tutorial

This page spans several parts of the video tutorial. Jump to:

Each device (one MIDI controller layout) can have multiple banks: alternate mapping layers on the same physical controls. Switch banks with the tabs above the grid; in multi-device view, a global bank switch moves every device that has that bank index.

What's shared vs per-bank: the slot grid and device-default MIDI routing (channel, CC/note index, and Note vs CC message type) are shared unless you add a bank override. Each bank stores its own parameter assignments. Locked slots are the exception: they carry their full slot config into every bank (see below).

Managing banks#

  • Create: the + Bank button opens the add-bank dialog. Start Empty or Duplicate an existing bank. On Empty, check Snapshot current routing on all slots when creating this bank to copy the active bank's MIDI routing into the new bank and optionally set one MIDI channel for overridden slots.
  • Duplicate: on a tab, or right-click → Duplicate, copies all assignments into a new bank (handy for A/B tweaks).
  • Rename: double-click a tab, or right-click → Rename.
  • Bank settings: right-click a bank tab → Bank settings… (name, hardware bank sync, bulk MIDI channel for overridden slots, and default ownerComp for scripts; see below and Button scripts).
  • Device settings: on the device tab (grid size, MIDI device / channel, piano keys; Advanced adds the default ownerComp for button scripts and a device-wide bank SysEx template). The same Advanced block opens when you + Device or Load as… from the library. Right-click grid + fill handles to insert or delete rows/columns; empty lines divide layout sections used by bulk operator assign.
  • Clear mappings: Clear params vs Clear all assignments on bank and device tabs; slot-level Clear params on cards and rows.
  • Remove: on a tab when more than one bank exists, or right-click → Remove bank.

Save and recall whole device layouts (including banks, hardware sync, and script ownerComp defaults) from the toolbar Library; see Devices & library. Switch banks from the UI tabs, keyboard shortcuts, slot Function → Bank actions (Pro), or the public API. Hardware sync is covered below.

Hardware bank sync#

Keep TDMap and a controller that exposes multiple banks in sync, for example the Novation Launch Control XL bank buttons sending SysEx.

  • Device-wide SysEx template: ⚙ Device settingsHardware bank sync (SysEx template). Enter the hex body without F0/F7. Use ?? where the bank index byte goes (for example 00 20 29 02 0a 77 ??).
  • Per-bank override: Bank settings…Hardware bank sync: Off, SysEx, CC, or Note. Per-bank SysEx replaces the device template for that bank. Use LRN to capture the next bank-change message from the controller.
  • Outbound: when TDMap selects a bank (UI tab, shortcut, slot function, or script), it sends that bank's sync message so the hardware follows.
  • Inbound: a matching SysEx, CC, or Note switches TDMap to that bank automatically.

Bank tabs show a dashed border when sync is configured (device template and/or per-bank sync). Echo from your own outbound SysEx is suppressed so TDMap doesn't loop.

Retargeting#

Retargeting bulk-updates the operator paths stored in bank tables. It's useful when you rename or move COMPs in TouchDesigner and don't want to re-assign every slot by hand.

  • From a slot: right-click a mapped card → Retarget paths. Prefills Find from the assignment's current path.
  • From a bank: right-click a bank tab → Retarget (this bank), Retarget (all banks), or Retarget (all devices).
  • From the inspector: retarget a single assignment from the right-hand panel.

Enter a Find prefix and a Replace prefix, then pick a scope: This parameter (one assignment), Current bank, All banks on the device, or All devices. For example, /project1/synthA/project1/synthB rewrites every mapping that pointed at the old COMP tree.

Find can be a literal substring or a segment glob (if it contains *, ?, or [). For example, /noise*/noise1 rewrites /noise2/tx to /noise1/tx, keeping the tail of the path.

For scripted migrations (show files, scene changes), the public RetargetBanks() method does the same find/replace with device/bank name patterns; see Public interface.

Bank MIDI overrides#

By default, each slot's MIDI channel, CC or note index, and message type (Note vs CC on buttons and push axes) come from the device default (⚙ Device settings → MIDI channel) and are shared across all banks. A bank override stores different routing for the same slot position on one bank only, so one physical control can use a different channel, index, or message type per bank without duplicating the device layout.

  • Per slot: right-click a card → Override MIDI for bank, or use Override for this bank in the inspector. Set channel, CC/note index, and Note vs CC as needed. The card shows an override indicator while the active bank has custom routing for that slot.
  • Whole bank: right-click the active bank tab. Override all in this bank freezes every slot's current MIDI as a bank-local override; Clear all bank overrides reverts those slots to the device default.
  • Bulk channel: once slots are overridden, open Bank settings…MIDI channel (overridden slots) and save to move every override in that bank to the same channel (push routing follows when present). Non-overridden slots keep using the device default channel.
  • Reset one slot: right-click → Reset bank override (only shown when that slot is overridden).

Propagate routing between banks#

When several banks use overrides with different CC/note indices, message types, or channels, copying routing by hand is tedious, especially after MIDI LRN on one bank.

  • After LRN: when you finish learning on a bank and other banks on the same device still differ, TDMap offers to copy the learned routing to them (confirm first).
  • On demand: right-click a bank tab → Propagate routing to other banks…
  • Choose what to copy and which target banks receive it:
    • CC / note indices (midi_idx, push index)
    • Note / CC (message type) (button and push input type)
    • MIDI channels (primary and push channel) Each axis has its own checkbox and bank list. CC / note indices is on when that axis differs. Note / CC and MIDI channels start off when indices also differ; they're checked automatically when they're the only difference.

Only banks whose effective routing differs from the source are listed. Deliberate per-bank assignments aren't changed unless you confirm.

Bank tabs with any overrides show a visual marker (has overrides in the tab tooltip). Overrides affect routing only; parameter assignments still live in each bank's table unless you change them separately. To change the MIDI channel for all banks at once (no per-bank overrides), edit the device default in Device settings instead.

Slot locking#

The 🔒 lock on a slot (card corner, list view, or inspector) is different from bank overrides: a locked slot keeps its mapping content (primary and push assignments, function / slot / modify modes, alternate-knob assignments, and related settings) when you switch banks. Unlocked slots load whatever that bank stores for that grid position.

Stays per bank even when locked: MIDI routing overrides (channel, index, hover, Note vs CC), and slot-mode inject parameters (the par a slot-mode button writes into its target). Those follow the bank you switch to.

Typical use: lock transport or master-volume slots so they stay identical on every bank, while other knobs swap mappings per bank. If the bank you're switching to has a MIDI override for a locked slot, that override still applies on top for channel, index, hover, and message-type routing.

Per-bank feel overrides Pro#

Step size, pickup, and filter can be set per slot with an override flag in the inspector. When enabled, those values are stored per bank (like assignments) instead of following the device default. This is useful when one bank needs tighter encoder steps or different pickup behavior without touching the others.

Not the same thing: Device default channel (Device settings) is the shared routing baseline. Bank MIDI overrides change which hardware message drives a slot on specific banks (channel, index, hover, and Note vs CC). Range overrides (min / max / default on an assignment) clamp how a parameter responds. Feel overrides change encoder/button behavior per bank. Slot lock freezes mapping content across banks while routing overrides stay per bank. Hardware bank sync only switches banks; it doesn't change slot CC routing.

Clearing mappings#

Video tutorial

This topic is covered in the video tutorial at:

TDMap separates parameter mappings (which TouchDesigner parameters a control drives) from behavior modes (function, slot, modify, script) and from MIDI routing (CC / note / channel). Two clear tiers let you wipe mappings without losing your hardware layout.

Clear params Clear all assignments
Removes Regular assignment pars; push assignment pars (including Alternate Knob); slot-mode ◈ pars (including push-target pills) Everything in Clear params, plus function / slot / modify / script mode config (push_mode → Assignment, function fields cleared, modify targets removed)
Keeps Slot cards on the grid, MIDI CC / note / channel, bank overrides, hover, slot names, lock state, button hardware type & action, relative / 14-bit / feel settings

Where to use each tier:

Scope Clear params Clear all assignments
One slot Right-click card → Clear params Not available (use bank or device tier)
Row / column Right-click a grid + fill handle → Clear params Not available
Multi-select Right-click selection → Clear parameters Not available
Active bank Right-click bank tab → Clear params Right-click bank tab → Clear all assignments
Whole device Right-click device tab → Clear all params Right-click device tab → Clear all assignments

Menu items show a tooltip on hover with the same summary. Locked slots still follow normal bank-switch rules; clearing a bank doesn't delete locked slot configs from other banks.

Not the same thing:

  • Clear CC / Clear all CC: removes the learned MIDI index only; parameter assignments stay.
  • Clear all bank overrides: reverts per-bank MIDI routing to the device default; assignments stay.
  • Clear all in row / column / grid (fill-handle menu or corner ⠿ menu): deletes slot cards from the layout (remove_slot), which isn't assignment clearing.
  • Param queue → Clear: empties the queue, not slot mappings.
  • Inspector assignment Clear on one pill: removes that primary assignment index only. Use card Clear params for push, slot-mode, and alternate-assignment data on the same slot.

Relative knobs#

Video tutorial

This topic is covered in the video tutorial at:

Most MIDI encoders are endless: they spin forever and report only how much you turned, not an absolute position. To put a knob in relative mode, turn Rel on in the inspector (or enable relative during smart-learn). Faders are always absolute: they have a fixed travel and map position directly.

Why relative mode fits TouchDesigner#

TouchDesigner parameters live on wildly different scales: a toggle is 0/1, a translate might be −10…10, a uniform scale might be 0…2, a custom par might span thousands. An absolute encoder assumes one fixed hardware position always means the same value, which is fine for a volume fader but awkward for general network editing.

Relative mode adds or subtracts a step on each detent instead of jumping to a mapped position. The same physical knob can nudge a tiny float par and a huge int par without reconfiguring, because step size and adaptive scaling handle the range. You can also keep turning past min/max when clamp is off, or use wrap/zigzag modes per assignment.

Absolute vs relative#

Mode Hardware Behavior
Absolute (Rel off) Faders; encoders that send 0–127 position MIDI value maps to a position in the parameter range (optionally with pickup, easing, 14-bit).
Relative (Rel on) Endless encoders (offset or 2's complement) Each tick steps the current value up or down. No fixed "center" on the hardware.

Step size#

  • Adaptive (default): step scales with the assignment's min/max, so one detent covers a consistent fraction of the range.
  • Fixed: adds the literal step value every tick (global step in the toolbar, or per-slot override in Settings).
  • Push-Step (Pro, button function): hold push and twist to bump global step coarser / finer / fixed while held.
  • Alternate Knob (Pro, Alternate knob): hold or toggle push to drive a second push assignment, with optional separate step / filter / easing for that axis.

MIDI protocol#

In Preferences and per-slot Settings:

  • Offset: standard relative encoding centered at 64. Turning clockwise sends values above 64, counter-clockwise below.
  • 2's complement: an alternate relative encoding used by some controllers. Enable the matching protocol toggle if your encoder direction is wrong, or use Rel invert per slot.

Relative and 14-bit are mutually exclusive, since 14-bit is for absolute high-resolution faders only.

Hover + relative: with Hover enabled and no assignment, a relative knob still steps whatever parameter your mouse is over in TouchDesigner. This is handy for quick tweaks without mapping every par.

14-bit MIDI#

Video tutorial

This page spans several parts of the video tutorial. Jump to:

14-bit faders use two CCs per control: the MSB on the configured index and the LSB on index + 32 (standard MIDI convention). Enable 14-bit in the inspector (absolute knobs/faders only, not available in relative mode). TDMap routes the combined high-resolution value through TouchDesigner's 14-bit CHOP; raw MSB/LSB bytes are suppressed so they can't double-fire the slot or collide with other mappings.

TouchDesigner reports CC indices 1-based (1–128). See MIDI numbering for channels and note indices too. The smallest LSB index is 33 (paired with MSB 1). Index 32 is the last legal MSB, not an LSB.

Two routing paths#

Path When Value
14-bit CHOP Slot has 14-bit enabled Combined 0–1 normalized value from TD's 14-bit CHOP
Raw CC (7-bit) 14-bit is off Integer 0–127 from the MIDI In DAT on the mapped CC index (MSB only in practice)

LSB index collisions (MSB + 32)#

If a 14-bit fader sits at CC N and another slot is mapped to CC N + 32 on the same MIDI channel and same physical MIDI device (midi_id in Device settings), the second slot won't receive MIDI. The 14-bit fader takes priority on that hardware. Different controllers (different midi_id) never suppress each other; identical CC numbers on two devices are fine.

Why: many 14-bit controllers send the MSB byte only when its 7-bit value changes (every 128 steps in the 16384-step range). Between those boundaries the hardware often sends only the LSB byte, which is identical on the wire to "user moved a standalone control at CC N + 32." There's no way to tell the two apart from the bytes alone, so the rule is: if a 14-bit slot is configured at the MSB, every LSB byte on that channel belongs to it.

What is / isn't silenced#

Silenced (raw CC path) Not affected
Knobs and faders at MSB + 32 without 14-bit enabled Note buttons (a different MIDI message type)
Buttons with CC message type at MSB + 32 The 14-bit owner (it uses the CHOP path, not raw bytes at the LSB index)

Smart-learn window#

Before 14-bit is confirmed on a slot, an existing standalone at MSB + 32 may still receive MIDI when only LSB bytes arrive in a frame with no MSB byte. Once you enable 14-bit on the MSB slot, suppression becomes permanent.

Warnings in the UI#

When a collision exists on the same physical MIDI device:

  • The conflicting slot's card shows a pulsing badge next to its LRN button (main grid and Unassigned panel).
  • Selecting either side (the 14-bit owner or the silenced standalone) shows an explicit warning row at the top of the inspector.

Fixes#

  • Move the standalone slot to a non-colliding CC or a different channel.
  • Disable 14-bit on the MSB slot (you'll get 7-bit MSB resolution only).

Input range: toggling 14-bit auto-updates the default From range ceiling (0–127 ↔ 0–16383) when it was still at the natural max. Narrow custom from-windows are preserved. TouchDesigner 2025.32460+ is recommended for native 14-bit CHOP support; older builds fall back to a per-channel legacy pipeline.

Hover mode#

Video tutorial

This topic is covered in the video tutorial at:

Hover mode lets a control drive whatever parameter your mouse is pointing at in the TouchDesigner UI, with no fixed assignment needed. It's the fastest way to tweak a parameter you haven't mapped: point at it, turn the knob (or move the fader), and TDMap writes to it live.

How it works#

Toggle Hover on a slot in the inspector (the inline switch on the assignment row). When the slot has no assignment, the physical control writes to whatever parameter is currently under your cursor in TD. As soon as you hover a different parameter, the control follows it.

  • Works on knobs and faders: absolute controls drive the hovered parameter's value directly, and a relative knob steps the hovered parameter on each detent.
  • Only active while the slot is unmapped. If the slot has a real assignment, that assignment wins and Hover does nothing.
  • Range, clamp, and easing don't apply in hover mode; the hovered parameter is driven across its own natural range.

MIDI feedback#

When Hover is on and the slot has no assignment, MIDI Out feedback mirrors whatever parameter is currently under your cursor in TouchDesigner:

  • Knobs and faders: motor faders and LED rings jump to the hovered parameter's current value. Point at a different parameter and the hardware updates to match (as long as per-slot MIDI feedback is enabled).
  • Buttons: pad LEDs reflect the hovered parameter's state (toggle on/off, momentary level, and so on) using the slot's Action setting.

When nothing valid is hovered, feedback clears to the empty-slot state. Assign the parameter normally and feedback follows the fixed assignment again.

When to use it#

Use a dedicated hover knob as a "scratchpad" control while building a patch: leave one encoder in Hover mode and point at any parameter to nudge it without committing a mapping. Once you settle on what you want mapped, assign it properly with PAR learn or drag-and-drop.

Buttons#

Video tutorial

This page spans several parts of the video tutorial. Jump to:

A button slot maps a press (and sometimes a release or a velocity) to a TouchDesigner parameter. Two settings describe a button: its hardware type (what the controller physically sends) and its action (what you want the press to do). Smart Learn usually sets both for you. See Assigning parameters.

Hardware type#

What the physical button or pad emits. Smart Learn sets it automatically, or you can pick it per-slot in the inspector.

Type What the hardware sends
Gate (Press/Rel) A press signal (value > 0) and a release signal (value = 0). For example, Note On / Note Off, or CC 127 / CC 0.
Latch Alternating press signals only; the hardware tracks on/off internally.
Trigger A single press signal, with no release message.
Velocity Gate-like, but each press carries a continuous value (note velocity or CC value). Drives the parameter through the absolute knob/fader pipeline (range / clamp / easing).

Action#

For gate / latch / trigger hardware, the action is what a press does. Pick it in the inspector Action row.

Action Behavior
Toggle Flip the parameter on/off each press. Reads the parameter's current value: number pars flip between min and max, menus between first and last item.
Mom (momentary) On while held, off on release. Degrades to Toggle on latch / trigger hardware (no release message); the inspector shows a ⚠ when the combo can't do true momentary.
Pulse Fire par.pulse() once per press, for pulse-style custom parameters.
Set Max Set the parameter to its maximum on press, and ignore release.

When you assign a pulse / toggle / momentary parameter to a button, Auto-toggle on assignment (Preferences, on by default) picks the matching action for you.

To step a value on each press (page a menu, bump an integer) instead of toggling, use Count. See Count & set value. For one-shot actions like reset, randomize, or bank switch, flip the button to Function mode (Pro). See Functions.

Velocity pads & note-off#

Velocity hardware (drum pads, aftertouch-style keys) sends a value with every press, so it drives the parameter through the same range / clamp / easing pipeline as a knob or fader: a soft hit lands low in the range, a hard hit lands high. The action selector is hidden for velocity hardware. Instead, a Note Off mode row controls what happens on release (value = 0):

Note Off mode On release
Hold (default) The parameter stays at the last velocity.
Reset Re-apply with value 0 through any range override, so the parameter goes to its configured minimum.
Reset to default Restore the parameter's nominal default value.

Piano keys#

Devices with a piano keyboard enabled (set in ⚙ Device settings or when you + Device) get a piano panel above or below the grid. Each key is a note-addressed button slot. Assign a parameter to a key the same way as a grid card: drag a TD parameter onto the key, use PAR learn, or queue-learn and press the physical key. Keys honor velocity hardware, so velocity-sensitive keyboards can drive parameters by how hard you play. The Oct ± buttons shift which notes the active zone displays; hardware routing always uses the real incoming note regardless of the displayed octave.

Bulk operator assign can also fill piano keys. See the Piano / keyboard keys strategy option in Bulk operator assign.

Count & set value#

Video tutorial

This topic is covered in the video tutorial at:

Two of the most useful button workflows: one steps a mapped parameter on every press, and the other jumps to a fixed value without leaving assignment mode behind.

Count (assignment mode)#

Map a button to a parameter as usual, then enable Count on that assignment in the inspector (below the min / max / default fields). Each button press adds the Step amount to the parameter instead of driving it like a momentary or toggle.

Setting What it does
Step Amount added per press. Negative values subtract.
Wrap Clamp (stop at bounds), Loop (wrap to the opposite end), or Zigzag (reverse direction at each bound).
Range Auto uses the parameter's own min/max (or full menu index range). Set custom min/max to limit the count window.

Works on numeric parameters and menus (steps by menu index). Toggles and pulses flip on each press. Use Count when you want a hardware button to page through menu items, bump an integer par, or step through a range, without switching the slot to Function mode. It's also available on a push-knob's push side when it's in assignment mode.

Auto range, the Switch TOP Index special case. A Switch TOP's Index parameter reports a generic numeric normMax that has nothing to do with how many inputs are actually wired. So when Range is Auto (no custom max) and the count target is a single-input Switch TOP's Index, TDMap resolves the max to len(inputs) − 1 (the index of the last connected input) instead of the parameter's normMax. This makes a Count button page cleanly through exactly the inputs that exist, and Loop wraps back to the first. Wire or unwire inputs and the auto range follows. Setting a custom min/max overrides this; multi-input Switch TOPs and other parameters use their normal min/max.

Set value (function mode) Pro#

Flip the slot (or push-knob push) to Function in the inspector, choose Set value, and type the value to write. On press, TDMap sets the target parameter to that value. No hover is required if you pin a Target list; otherwise it uses Hovered (whatever your mouse is over in TD when you press).

The value field follows the target parameter type: numbers for float/int pars, true / false for toggles, a menu item name for menus, and any non-empty text to fire a pulse. Pair with Target mode to build a row of scene-recall buttons, each writing a known value to a fixed list of parameters with one press.

Count vs set value: Count steps a mapped parameter by a delta every press. Set value is a function that writes an absolute value (or fires a pulse) to hovered or pinned targets, so the slot doesn't need a par assignment for the targets you're writing to.

Other function-mode actions (reset, randomize, bank switch, callbacks, and so on) are listed under Functions.

Button scripts#

Video tutorial

This topic is covered in the video tutorial at:

Run Python directly from a mapped button, knob, fader, or push-knob, with no external DAT and no wiring a CHOP Execute. Flip the slot to Script in the inspector (alongside Assignment, and on buttons also Function, Slot, and Modify). Scripts are stored per slot in your TDMap config, compiled in memory, and fire on MIDI like built-in function buttons.

Setup#

  1. Select a button, knob, or fader slot (or a push-knob's push row).
  2. In the inspector, choose Script from the mode row.
  3. Optionally set ownerComp, the COMP that me, ownerComp, and relative op('child') resolve from. Empty inherits bankdevice → project root (/). Bank defaults live in Bank settings… → Advanced; device defaults in ⚙ Device settings → Advanced.
  4. Edit the script inline, or open Full editor… for a larger pane (Ctrl+S / ⌘+S to save). Changes auto-save after a short debounce.

Callbacks#

These use CHOP Execute-style names. Define only the ones you need:

Callback When it fires Arguments
onOffToOn MIDI value crosses from 0 to > 0 val, prev, ownerComp, source
onOnToOff MIDI value crosses from > 0 to 0 val, prev, ownerComp, source
onValueChange Any MIDI value change val, prev, ownerComp, source
whileOn Every frame while held (> 0) val, ownerComp, source
whileOff Every frame while released (0) val, ownerComp, source

val / prev are normalized 0–1 (using from_min / from_max when set). source is the same identity dict as lifecycle callbacks and function-mode Callback: device, slot, channel, index, message type, is_push, and the callback name. Knobs and faders fire onValueChange only. Compile and runtime errors log to the Textport with the slot number.

What your script can touch#

Scripts run in an ownerComp-scoped namespace, plus the TDMap public API:

  • me / ownerComp: the resolved COMP (see inheritance above).
  • op('child'): relative to ownerComp; paths starting with / are absolute.
  • op.Shortcut: global OP shortcuts (for example op.A) still work.
  • ext, parent: on ownerComp (not TDMap internals).
  • TDMap: Learn, SelectBank, CreateBank, RemoveBank, RetargetBanks, SetOwnerComp, AssignSlot, config load/save, and so on. These are the same methods as the public interface. Omit device for every device where applicable; AssignSlot always needs one.
  • absTime, app, ui, project: TouchDesigner globals.

Script vs Callback vs public interface#

  • Script mode: Python lives in the slot, edited in the web UI, ideal for one-off hardware behavior tied to a specific button. Call TDMap.* directly from callbacks.
  • Function → Callback: one named function in TDMap_callbacks (Integration → Create Callbacks), reused across many slots with string args.
  • Public interface: call the same TDMap methods from outside TDMap via op.TDMap.Method(...). Active-agnostic: omit device for every device where applicable; omit bank on SendAllFeedback / AssignSlot for each device's active bank.

Presets: factory device presets are layout templates, so script-mode slots revert to assignment when saved as factory. Your own saved layouts keep script text. Push-knob scripts set source['is_push'] to true.

Filter, pickup & easing#

Video tutorial

This topic is covered in the video tutorial at:

Three feel layers shape how an absolute knob or fader moves a parameter. Each has a global default (Preferences) and a per-slot override in the inspector Settings section. They apply to absolute controls (faders and non-relative knobs); velocity pads run through the same pipeline.

Filter (smoothing) Pro#

Exponential smoothing glued onto parameter changes. It eases the jump between incoming MIDI values so motion looks fluid instead of stepped.

  • Global filter in Preferences sets the default amount for new slots.
  • Per slot, enable Filter in Settings and drag the slider: 0 is instant (no smoothing), higher is smoother and slower to settle (up to 0.99).
  • Useful for low-resolution 7-bit faders driving visible geometry, or any parameter where you want to hide the 128-step quantization.

Pickup mode Pro#

With pickup on, an absolute control waits to match the parameter's current value before it starts driving, so switching banks or loading a config doesn't snap the parameter to wherever the hardware happens to be sitting.

  • Global pickup in Preferences sets the default; Pickup in slot Settings overrides per slot.
  • While a control waits to be "picked up," the TDMap button turns pink and the grid highlights which slots are waiting. Move the control through the current value to engage it.
  • A Toggle pickup keyboard shortcut flips the global setting live. See Keyboard shortcuts.

Pickup is for absolute controls only. Relative encoders never jump, so they don't need it.

Easing curves Pro#

Reshape the response of an absolute control across its range with a non-linear curve. Instead of a straight line from min to max, the value follows the chosen easing: slow-in, fast-out, S-curve, overshoot, bounce, and more.

  • 31 curves: linear plus in / out / in-out variants of Sine, Quad, Cubic, Quart, Quint, Expo, Circ, Back, Elastic, and Bounce (based on easings.net).
  • Pick the curve with the easing picker in slot Settings. In multi-assignment slots you can set the override per parameter, so one control can drive several pars with different feels.
  • Easing maps the normalized 0–1 input through the curve, then into the assignment's range / clamp, so it composes with range overrides and filter.

Alternate Knob (Pro) can use separate filter and easing overrides for the push assignment axis while alternate mode is active. Those live under Push → Settings, not in the main slot Settings block.

Order of operations: raw MIDI → range / clamp → easing curve → filter (smoothing) → parameter. Modifiers (Pro) act on the value after range mapping, before it reaches the parameter.

Slot mode (◈)#

Video tutorial

This topic is covered in the video tutorial at:

Slot mode turns a button (or a push-knob's push) into a parameter hot-swapper. It carries one saved parameter (the slot par) and injects it into another control's assignment when you press. The encoder or fader on the target slot then drives that injected par until you swap again or clear it.

Think of it as reusable par presets wired to hardware: one physical button holds geo1.tx, another holds light1.dimmer, and both can push their par onto the same knob row when you need it, without duplicating MIDI mappings or rebuilding the bank.

Setup#

  1. Select a button (or enable push on a knob) and choose Slot in the inspector mode row.
  2. Assign the slot par (the pill with the ◈ badge): use PAR learn, type it in, or drag from another card. This is what gets injected, not what the button drives directly.
  3. Pick a target: the device, bank, and row/col of the knob, fader, or button that should receive the injection. Drag the slot-mode card onto a target, or use the target fields in the inspector.

Press behavior#

Gesture Result
Quick tap On release (shorter than the slot-learn hold time), inject the slot par into the target's assignment. The target's encoder immediately controls that parameter.
Hold After the hold threshold (Preferences → Slot-learn hold time), hover a TD parameter to capture it as the new slot par, without injecting yet.
Hold + no hover (2× hold time) Clears the slot par assignment.
Learn on + hover on press Assigns the hovered par to the slot par pill; suppresses inject on that press.

Optional push-target par on push-knobs: a second pill injects into the target's push assignment when the target has push enabled.

Visual cues#

  • Purple border: this card is a slot-mode control.
  • Purple tint on a target: something in slot mode is pointing at it.
  • ◈ badge + par name: the current slot par. Drag the pill onto another slot-mode control to swap slot pars, or onto a normal slot to set it as a regular assignment.

Cross-device / cross-bank#

Targets can live on another device or bank. TDMap writes the injection into that bank's table so the mapping persists when you switch back. LED feedback on slot-mode buttons follows the reference pattern: empty / occupied / active, depending on whether the target currently has that par loaded.

Slot mode vs Function → Target: function buttons with pinned control targets fire one-shot actions (reset, set value, and so on) at press time. Slot mode re-wires another control's ongoing MIDI mapping. Use slot mode when you want a knob to keep driving the injected par after the button press.

Modifiers#

Video tutorial

This topic is covered in the video tutorial at:

A modifier is a control that transforms another slot's output instead of (or in addition to) writing its own parameter. Use it for performance macros: scale a fader's range with a second encoder, bump a value with Add, or gate an effect with a button.

Two ways to be a modifier#

Source Setup Amount
Knob / fader Inspector → mode Modify (replaces assignment on the primary axis). Faders in modify mode still read absolute position as the amount. Encoder turn (relative) or fader position (absolute) sets modify_amount 0–1 continuously.
Button (or push-knob push) Mode Modify on the button / push row. Gate hardware: on = amount 1.0, off = 0.0. Toggle / momentary / velocity behave like normal button actions but drive modifier amount instead of a par.

Depth (inspector slider, default 100%) caps how strong this modifier ever is on all targets below: effective strength = live amount × depth × per-target Strength. Add, Sub, and Bipolar can also use Step: Range | Flat (+ Δ when flat) per target row.

Targets & operations#

Add one or more modify targets: drag another card onto the modifier, or pick device / bank / row / col in the inspector. Each target picks an operation applied to that slot's numeric output (after range mapping, before the value hits the TD parameter):

Operation At amount 0 / neutral Effect as amount rises
Scale Identity at 1.0 Pulls the value toward min as amount decreases; at 0 the output sits at min.
Add / Sub No offset (neutral = 0) Adds or subtracts a fraction of the parameter range, or a fixed par-unit delta when Step is Flat.
Divide Identity Compresses range, which is useful for tapering sensitivity.
Bipolar Center (neutral = 50%) 0% = −one step, 50% = no change, 100% = +one step. Step uses assignment range or a flat delta.

Multiple modifiers can target the same slot; operations chain in registration order. Modifiers can't target other modifiers (no chaining through modifier slots).

Visual cues#

  • Modifier cards show a badge and list their targets in the inspector.
  • Target cards gain a modifier tint when something is affecting them.
  • The modifier amount bar in the UI reflects live modify_amount (useful when driving amount from a relative encoder).

Modify vs Assignment: assignment mode writes MIDI directly to a parameter. Modify mode only adjusts other slots that already have assignments. Pair a mapped fader (target) with a relative encoder (modifier) for live "macro" control without touching the target's MIDI learn.

Functions#

Video tutorial

This topic is covered in the video tutorial at:

A button doesn't have to be a MIDI mapping. Flip its mode to Function in the inspector and it becomes an action button: tap it to reset, snapshot, randomize, switch banks, open an editor, and so on. Or choose Script to run your own Python per slot; see Button scripts. The same modes apply to a push-knob's push. Most function actions are one-line picks in a dropdown: pick the action, optionally pick what it operates on, done.

Picking what the action operates on#

Actions that change a parameter need to know which parameter. Four ways to point at one, shown as tabs above the action:

  • Hovered: whatever your mouse is over in TouchDesigner the moment you press the button. Great for "fix-it" buttons (reset, randomize, snapshot) that you point at things.
  • Adjusted: the last parameter you twisted via MIDI. Lets one button always undo / randomize / re-default whatever you most recently touched.
  • Knob: the push-knob's own assigned parameter. Only on push-knobs.
  • Target: a fixed list of parameters you pin in advance. Two flavors, mixable in the same list:
    • Par target: drag a TD parameter onto the pill. Sticks to that exact parameter.
    • Control target: drag another card onto the pill (or click "+ Add Control Target"). Resolves to whatever that other control is currently driving, so renaming or reassigning the target control transparently changes what this button operates on. Same idea as Slot mode and Modify targets.

Actions iterate the whole list: point one Reset button at six targets to reset all of them with one press.

Things buttons can do#

Everything below is a one-line pick in the inspector's Function dropdown. Where a function has variants, they show as a row of buttons right under the dropdown.

Set, reset, snapshot, randomize a parameter#

All of these take a target: pick Hovered, Adjusted, Knob (push-knobs only), or Target (a pinned list of par or control targets; drag pars / cards onto the pill). See Picking what the action operates on above.

Function Options What it does
Reset Target picker (Hovered / Adjusted / Knob / Target). Send the parameter back to its default value.
Set as default Target picker. Make the current value the new default. Useful for pinning your "happy place" on the fly (custom pars only).
Set current as min Target picker. Pin the current value as the bottom of the parameter's range.
Set current as max Target picker. Pin the current value as the top of the parameter's range.
Toggle clamp Target picker. Flip min/max clamping on or off without changing the values.
Randomize Target picker. Roll a random value in range. Int/float pars try to differ from the current value; toggles get a random T/F; pulses fire ~50% of the time; menus pick a different item.
Set value Value field (type follows the parameter: number, bool, menu name, pulse fire) plus an optional explicit Target list. Write a fixed value to the parameter. Without an explicit target, uses Hovered. See Count & set value for a full walkthrough.
Set step size Step field (a number input that scrolls in ×10 / ÷10 increments per click as a convenience). Set the global step size for relative encoders. Wires straight into the same step value as the toolbar's global setting.
Navigate banks & open editors#
Function Options What it does
Bank Pro Next / Previous / Switch + device picker (current / all / named device). Switch adds a bank dropdown (0-based index). Step through or jump banks on the chosen device(s). Next/Previous wrap around. All devices switches every device at once.
Open editor Hovered / Selected / Parent / Adjusted. Pop the TouchDesigner Component Editor (custom-parameter setup) for a COMP and jump to the relevant page and parameter. Hovered uses the par under your mouse. Selected uses the currently selected COMP in the last network editor pane. Parent opens the parent COMP of the selected op. Adjusted uses the owner of the last MIDI-adjusted parameter.
Open parameters Selected / Parent / Adjusted. Pop TouchDesigner's standard Parameters window. Works for any op kind (not just COMPs). Selected uses the network-pane selection. Parent uses the parent of that selection. Adjusted uses the last MIDI-adjusted parameter's owner.
Promote to parent (bind) Hovered / Adjusted. Promote the targeted parameter to its owner's parent COMP and bind it back, via the bundled CustomParPromoter child COMP. If the par is part of a multi-par group (XYZ, and so on) that's already mapped on a TDMap slot, the whole pargroup is promoted as a unit. Any TDMap mappings that referenced the original par get re-targeted to the new promoted par automatically.
Learn a new mapping#
Function Options What it does
Par Learn Momentary / Toggle. Momentary learns while held; Toggle flips learn on or off each press. Activate learn from hardware, then hover a TD parameter, and the slot binds to it. Same as the inspector's PAR button, but as a hardware shortcut.
Fire your own code#
Function Options What it does
Callback Function name plus up to two string arguments. Calls a Python function in TDMap_callbacks by name (create it from Integration → Create Callbacks). Invoked as fn(source, arg1, arg2), where source is a dict identifying which control fired (device, slot, channel, CC, value, and so on) so one callback can serve many slots and tell them apart at runtime.

For per-slot Python with CHOP Execute-style callbacks (onOffToOn, whileOn, and so on) edited inline in the inspector, use Script mode instead. See Button scripts.

Encoder-specific (push on a push-knob)#
Function Options What it does
Push-Step (hold + twist) Coarser (×10) / Finer (÷10) / Fixed. Fixed reveals a step-size field used while held. Hold the push, twist the encoder to change global step size on the fly.

Push-Step vs Alternate Knob: Push-Step adjusts how big each relative tick is (global step). Alternate Knob maps the encoder to a second parameter while push is held or toggled. You can use both on different slots, but not as the same push mode on one slot.

Alternate knob#

Video tutorial

This topic is covered in the video tutorial at:

Alternate Knob (Pro) lets a single push-enabled knob or fader drive two parameters. Normally the encoder moves the primary assignment in the Par section. While alternate mode is active, twists move the push assignment instead. One physical control, two mapped parameters.

Setup#

  1. Enable Push on the slot and assign at least one parameter under Push → Par (the alternate assignment).
  2. Turn on Alternate Knob under the push Assignment section. TDMap sets Hold as the default Action when push hardware is Gate (press and release). For latch or press-only hardware it defaults to Toggle.
  3. Open Push → Settings if it didn't expand already. Under Action, choose how alternate mode turns on and off:
Action Behavior Hardware
Hold Alternate mode is on only while you hold the push button. Gate (Press/Rel) only. Without a release message, Hold would behave like Toggle, so TDMap hides it for other hardware types.
Toggle Each push flips alternate mode on or off until you press again. All push hardware types.

Velocity push hardware isn't offered in Alternate Knob mode. The push button only switches which assignment the encoder drives.

Which assignment moves#

  • Alternate off: MIDI updates the primary assignment. Range, clamp, and feel come from the main Par row and the slot Settings section (filter, pickup, easing; step size when Rel is on).
  • Alternate on: MIDI updates the push assignment instead. Set that parameter's range and clamp on the push Par row. Feel for this axis is configured under Push → Settings (below).
  • Alternate state is per slot and clears when you change banks.

Alternate feel (Push → Settings)#

While alternate mode is active you can use different motion settings than the primary axis. The Encoder feel (while alternate active) block is under Push → Settings:

Control type Overrides available
Relative knob (Rel on) Step (adaptive or fixed step size) and Filter
Absolute knob or fader Filter and Easing curve

Each override is optional: leave its toggle off to keep using the primary axis feel for that layer. Global defaults still apply when an override is off.

This is separate from the primary slot Settings block. Tuning step on the main axis doesn't change alternate step unless you enable the alternate Step override.

Visual cues#

The push row on the card shows a badge with the push parameter name. The row glows while alternate mode is active so you can see which assignment the encoder is driving.

Alternate Knob vs other push modes#

Feature What it does
Alternate Knob Swaps this slot's encoder between its own primary and push assignments.
Slot mode (◈) Injects a saved parameter into another control's assignment.
Push-Step (button functions) Hold push and twist to change global step size (coarser / finer / fixed). Doesn't require a second mapped parameter.

Use Alternate Knob when one encoder should reach two pars. Use Slot mode when one button should retarget a different control. Use Push-Step when you only need temporary step scaling.

Preferences#

Video tutorial

This page spans several parts of the video tutorial. Jump to:

Open the gear icon in the toolbar to find these. All preferences persist across sessions in a single tdmap-prefs.json file next to your configs.

Defaults for new controls#

Default push modeAssignment / Function / Slot / Modify: what a brand-new button or newly enabled push-knob starts in. If you mostly use buttons for actions, set this to Function.
Default function & valueWhen the default push mode is Function, also pick the function name (e.g. Reset, Randomize) and any value it needs. New buttons pre-fill with these.
Multi-assignment by defaultNew slots start in multi-assignment mode (one slot drives many pars). Off by default.
MIDI feedback by defaultNewly created slots have MIDI Out feedback enabled. Useful if all your controllers have motorized faders or LED rings.

Behavior#

Auto-toggle on assignmentWhen you assign a pulse / toggle / momentary par to a button, automatically pick the matching button action, so you don't have to think about it.
Smart LearnWhen learning a control, watch the first few movements and auto-classify it as knob / fader / relative encoder / button (gate, latch, or velocity) plus MIDI protocol. Runs during queue learn and Smart create. See Assigning parameters and Unassigned MIDI.
Auto-save layoutPersist every change to the global config the moment it happens, with no manual save. Includes a snapshot of TouchDesigner's /local/midi/device table (midi_device_rows) for Restore from saved….
Prompt to restore MIDI device table on startupWhen on, offers to sync TD's MIDI device table from the saved layout after load (confirm before applying). Off by default. See MIDI Device Manager.
Protect read-only & disabled parsBlock MIDI value writes to parameters TouchDesigner marks as read-only or disabled (mapping stays, value writes don't fire).
Tint TD parameter dialog while learningOn by default. While Learn (or per-slot par learn) is active, TDMap tints TouchDesigner's parameter dialog yellow. That forces TD to redraw its UI and can drop frames on heavy projects. Turn off anytime in Preferences; the TDMap button (top-right) still turns yellow when Learn is active.
Loop menusMenu parameters wrap around at both ends when stepped past the edges (off = clamp).
MIDI-control string menusAllow MIDI to drive string-style menus (StrMenu). Off by default since the values are arbitrary strings, not ordered.
Middle-click "show in pane" (floating)Off by default: middle-clicking a par chip pans the last network editor pane you used in TD to that operator (see Reveal in network editor). When on, each middle-click opens a new floating network editor instead.

Feel#

Global filter ProDefault exponential-smoothing amount for new slots. Per-slot override available in the inspector.
Global step / step modeDefault relative-encoder step size and adaptive vs fixed step. Per-slot override available.
Global pickup ProDefault pickup for new slots (absolute controls wait to match current value before taking over).

Controller undo#

MIDI-driven parameter value changes register in TouchDesigner's native undo (Edit → Undo, or Ctrl+Z / ⌘Z in TD). Twist a mapped fader, then undo in TouchDesigner and the parameter returns to where it was before that gesture.

What is covered: knobs, faders, relative encoders, buttons (toggle, momentary, pulse, set, count), velocity mapping, modify-target writes, function-mode value changes, and hover fallback — any path that writes an assigned parameter from MIDI.

What is not covered: TDMap layout and config edits (assignments, CC indices, ranges, slot types, bank layout, and so on). Those are saved to your config, not pushed onto TD's undo stack.

Group window (undo timeout)#

TDMap does not register an undo step on every MIDI tick. That would flood TouchDesigner's undo history during a long fader sweep.

Instead, for each slot:

  1. On the first write in a gesture, TDMap captures the parameter's current value.
  2. Each further write restarts an idle timer (default 1000 ms; range 200–2000 ms).
  3. Only when the control has been still for the full timeout does TDMap commit one undo entry (initial value → final value) to TouchDesigner's undo stack.

So a continuous knob sweep becomes a single Ctrl+Z step, not hundreds. Two separate gestures separated by the timeout become two undo steps. Each slot groups independently.

Toggle undo on or off and set the timeout from the toolbar button (click to enable; when on, click again to open the timeout slider). Settings persist in tdmap-prefs.json. On by default.

Workflow#

Controller undoToolbar : enable/disable MIDI par-value undo and set the group window (200–2000 ms). See Controller undo above.
Slot-learn hold timeHow long you have to hold a slot button before "slot learn" mode arms.
Theme & zoomLight / dark theme, and a CEF-safe zoom (CSS transform, not browser zoom) so the panel renders sharply in any TD pane size.
Interactive tourReplay the onboarding walkthrough any time.

Keyboard shortcuts are configured under Preferences → Keyboard Shortcuts; see Keyboard shortcuts for the default combos and rebinding notes.

Keyboard shortcuts#

Video tutorial

This topic is covered in the video tutorial at:

Shortcuts are handled in TouchDesigner via the Keyboard In CHOP, so they work even when the TDMap panel isn't focused. Open Preferences → Keyboard Shortcuts to rebind. Combos persist in your global config.

Action Default What it does
Open UI Alt + Shift + D Open the TDMap web UI in a floating window (same as left-clicking the TDMap button in TouchDesigner).
Learn (toggle) Ctrl + L Flip global Learn mode on or off. Same as right-clicking the TDMap button or the toolbar L button.
Learn (momentary) Ctrl + Shift + L Learn on while held, off on key release; good for quick one-off captures without leaving Learn armed.
Toggle step mode (adaptive / fixed) Pro None Flip the global relative-encoder step mode between adaptive and fixed. No default; assign your own.
Toggle pickup Pro None Flip global pickup on or off. With pickup on, absolute controls wait for the hardware to match the current parameter value before they start driving it.
Bank Switch (custom) None Add with + Add bank shortcut. Each row pins a device and bank target (index, Next, or Previous) to a combo.

Undo (TouchDesigner)#

TDMap registers mapped parameter value changes on TouchDesigner's undo stack. Use TouchDesigner's normal undo: Ctrl+Z / ⌘Z, or Edit → Undo. TDMap groups rapid movement into one step after an idle group window (toolbar ; default 1000 ms). Mapping and layout edits are not undoable this way. See Preferences → Controller undo.

On macOS, Cmd is treated as Ctrl for the shortcuts above (Ctrl+L → ⌘L). Shortcuts are suppressed while typing in a text field. The five built-in rows above can be cleared but not deleted; bank-switch rows are fully removable.

Public interface#

Video tutorial

This topic is covered in the video tutorial at:

The TDMap component is shipped locked so its internals can't be edited from outside callers. You still get a clean Python API on the COMP: call methods from any TouchDesigner script via op.TDMap.

Design rules#

Active-agnostic. Public calls never read or depend on which device/bank tab is open in the web UI. Each device keeps its own active bank in device_config (updated by SelectBank, hardware bank sync, shortcuts, and so on). That's runtime state, not UI chrome.

Device scoping. Where a method accepts device:

| Omit device | Every device | | Exact name | One device ('knobs') | | tdu.match pattern | All matching devices ('Launch*', '*') |

AssignSlot is the exception: it always requires an explicit device name (one grid cell on one device).

Bank scoping varies by method; see the table below. When omitted, SendAllFeedback and AssignSlot use each device's active bank, not bank index 0.

Wildcards (tdu.match).

Method device pattern bank / banks pattern
RetargetBanks multi-match banks string → all matching banks per device; list → union of resolved indices
SelectBank, RemoveBank, AssignSlot, SendAllFeedback, SetOwnerComp multi-match (except AssignSlot device: exact name only) string → exact name first, then first tdu.match hit per device

Naming rules. Device identifiers in the public API are the sanitized TD operator names (Launch_Control_XL, not the display label); punctuation and wildcards are stripped when a device is created. Bank names must not contain *, ?, [, or ] so literal names never collide with patterns. Existing banks with those characters still work for exact-name lookups; renames that add metacharacters are rejected.

So RetargetBanks(..., banks='Bank *') retargets every bank whose name matches; SelectBank('Bank *') switches to the first matching bank per device.

Batching. Calls from op.TDMap queue per frame and dispatch at frame end (in order). Use op.TDMap.extFlush() to force an early dispatch. Treat methods as commands; return values may not be available until after dispatch.

Entry point. Call op.TDMap.Method(...) from any TouchDesigner script. Live OP and Par handles resolve automatically; AssignSlot takes a Par (row/col 1-based).

SelectDevice exists on the engine for UI navigation only; it's not part of the public API.

Quick examples#

tdmap = op.TDMap

tdmap.SendAllFeedback()                         # all devices, each active bank
tdmap.SelectBank('Live')                        # all devices, bank named Live
tdmap.SelectBank('Live', device='Launch*')    # matching devices only
tdmap.RetargetBanks('/old', '/new')            # all devices, all banks
tdmap.RetargetBanks('/old', '/new', device='knobs', banks='Bank *')
tdmap.AssignSlot(op.synth.par.level, device='knobs', row=1, col=1)  # active bank
tdmap.AssignSlot(op.synth.par.level, device='knobs', row=1, col=1, bank=2)
tdmap.SetOwnerComp('/project/show')
tdmap.SetDefaultGlobalConfig('live_set.json')

Method reference#

Mapping#

Method Signature Returns Notes
RetargetBanks (find, replace, device=None, banks=None) int cells rewritten Omit device / banks → all. find literal or path-glob; replace can be an OP (resolved to path).
SetOwnerComp (owner_comp, device=None, bank=None, slot=None) devices updated '' clears. bank+slot = per-slot override; bank alone = per-bank default; neither = device default.
AssignSlot (par, device, row, col, bank=None, is_push=False) bool device required. Row/col 1-based (r2·c1). Omit bank → active bank.
Learn (active=None) None None toggles; True/False sets global learn mode.

Banks#

Method Signature Returns Notes
SelectBank (bank, device=None) None Switches virtual mapping layer (MIDI routing + feedback). bank = index or name/pattern (first hit).
CreateBank (name='', device=None) last idx Auto-name when name=''.
RemoveBank (bank, device=None) None Can't remove a device's last bank.

Library#

Method Signature Returns
LoadGlobalConfig (filename) None
SaveGlobalConfig (filename=None) filename written
SetDefaultGlobalConfig (filename) bool

Lifecycle#

Method Signature Returns
CreateDevice (name, channel=1, midi_id=1) None
RemoveDevice (name) None

Feedback#

Method Signature Returns Notes
SendAllFeedback (device=None, bank=None) None Omit both → all devices, each active bank. Pass bank=0 to force bank index 0.

Debug#

Method Signature
Test ()

Callbacks#

TDMap can run Python in TDMap_callbacks, a Text DAT you add to your project via Integration → Create Callbacks. Add functions there to react to mapping changes, bank switches, MIDI-driven writes, button presses, and more. Function-mode slots can also call user-named functions from the same file.

The onValueChange return value can override or suppress default MIDI LED feedback.

Setup, event list, source fields, examples, and caveats: Callbacks.

Callbacks#

Video tutorial

This topic is covered in the video tutorial at:

Callbacks let you run your own Python when something happens inside TDMap: a knob moves a parameter, a bank switches, a mapping is learned, a config is saved, and so on. TDMap ships only the locked .tox; callback code lives in TDMap_callbacks, a Text DAT you add to your project via Integration → Create Callbacks.

Getting started#

  1. Select the TDMap component and open its parameter dialog (middle-click the TDMap button, or select /TDMap in the network).
  2. Open the Integration parameter page.
  3. Pulse Create Callbacks.

TouchDesigner creates TDMap_callbacks next to TDMap with starter functions and comments. Uncomment or replace the stubs, add your own logic, and save. TDMap picks up changes on the next cook; you don't wire a CHOP Execute or call into the locked engine by hand.

If you pulse Create Callbacks again and TDMap_callbacks already exists, TDMap reuses it (your edits are kept).

There are two ways to use this file:

Flavor When it runs What you do
Lifecycle Automatically on TDMap events (mapping, banks, MIDI writes, and so on) Define a function with the fixed name from the table below (onReady, onValueChange, …). Delete or rename a stub to opt out.
User-named When a hardware control in Function → Callback mode fires Pick the function name (and optional args) in the web UI inspector.

Errors in your callback code are logged to the Textport; they don't stop MIDI routing or the mapping UI.

For Python on one slot only, edited inside the web UI, see Button scripts. Callbacks here are for project-wide hooks and functions shared across many controls.

When to use which#

Goal Use
Log or fan out every MIDI-driven parameter write onValueChange
Run setup once when TDMap has finished loading onReady
Sync external show logic to bank or device changes onBankChange, onDeviceChange
Track assignments as users map in the UI onParLearn, onParUnlearn
React when slots are added or removed onSlotCreate, onSlotRemove
Custom hardware LED feedback onValueChange return value (see below)
One button action reused on many controls Function → Callback + a user-named function
One button, self-contained script Script mode on that slot

When you open a project, TDMap does not replay learn/create events for mappings that already exist. The first lifecycle event on load is onReady, after TDMap is ready to use.


User-named callbacks#

In the web UI, set a button or knob to Function mode, choose Callback, and enter a function name plus optional arg1 / arg2 strings. When the control fires, TDMap calls that function in TDMap_callbacks:

def my_callback(source, arg1=None, arg2=None):
    ...

source describes which control fired (device, slot, MIDI channel/index, and so on). It includes value (raw MIDI byte 0–127). One function can serve many slots; read source['device'], source['slot'], source['index'], etc. to tell them apart.

See Functions for the inspector workflow.


Lifecycle events#

Event Arguments Typical use
onReady() none One-shot startup when TDMap is ready (devices, banks, MIDI).
onValueChange(source, par, value, normalized) per-control dict, Par, final written value, 0–1 normalized React to every MIDI write; custom LED feedback (see below). Runs often while a knob moves.
onBankChange(device, prev_bank, new_bank) device dict, two {idx, name} bank dicts Sync when the active bank changes.
onDeviceChange(prev_device, new_device) two device dicts React when the active device tab changes.
onParLearn(source, par) per-control dict, assigned Par New mapping; source['is_push'] is the push axis.
onParUnlearn(source, par) per-control dict, cleared Par Mapping removed (once per cleared assignment).
onSlotCreate(source) per-control dict New slot on the grid (Smart Learn, manual add, preset load).
onSlotRemove(source) per-control dict Slot deleted (fires before removal).
onButtonPress(source, value) per-control dict, MIDI byte Button or push press.
onButtonRelease(source) per-control dict Gate hardware release only.
onConfigSave(config) {name, scope} Library, factory, or global config saved.
onConfigLoad(config) {name, scope} Config loaded.

TDMap_callbacks includes a DEBUG_LIFECYCLE flag at the top. Set it to True while wiring logic to print a trace line from each stub.


source dict (per-control events)#

Key Description
device TDMap device name (Unassigned slots use a special _unassigned_… name).
display_name User label; falls back to device.
midi_id Physical MIDI device id (−1 if unknown).
bank_idx, bank_name Active bank when the event fired.
channel MIDI channel 1–16.
index CC or note number (−1 if not assigned yet).
msg_type 'cc' or 'note'.
is_push True if the push axis fired.
slot Slot id inside TDMap.
row, col Grid position (−1 if unplaced).
slot_name, slot_type User name; 'knob', 'fader', or 'button'.
owner_comp, owner_comp_path, … Script namespace COMP (same idea as button scripts).

Device dict (bank/device events): device, display_name, midi_id.

Bank dict: idx, name.

Config dict: name, scope ('library', 'factory', or 'global').


onValueChange LED feedback override#

After your callback returns, TDMap normally sends MIDI feedback so controller LEDs track the parameter. Your return value can change that:

Return What TDMap does
None or anything not listed below Default LED feedback
False No feedback (you drive MIDI out yourself)
(midi_id, channel, index, msg_type, value) Send this one message instead
[(...), (...), ...] Send each tuple (RGB LEDs, mixed CC + sysex, and so on)

For msg_type='sysex', value is the byte list for midiout.sendExclusive (TouchDesigner adds F0/F7 framing).

def onValueChange(source, par, value, normalized):
    return (source['midi_id'], source['channel'], 50, 'cc', 127 - value)
def onValueChange(source, par, value, normalized):
    op('my_midi_out').sendControl(1, 60, value / 127)
    return False

Keep onValueChange fast; it runs on every movement frame.


Caveats#

  • Modify mode: when a modifier drives another slot's parameter, onValueChange fires for the target being written, not the modifier knob that moved.
  • Slot mode: parameter injects from slot-mode buttons do not fire onValueChange. Use onButtonPress on the slot-mode control if you need those events.
  • Broken assignments: if an operator was deleted before unlearn, onParUnlearn may not run. Also handle onSlotRemove if you track every assignment.
  • Latch / trigger buttons: only onButtonPress; no release event.