Blog Millumin 12 min read

Millumin + Gamepad: Driving Interactions From a DualSense

Millumin routes every control through one Interactions panel of inputs, transformers and actions. How a game controller fits that model, and what changes.

By Aidxn Design

Millumin does something most VJ and media-server software does not: it refuses to have separate mapping systems. There is no MIDI learn page, no OSC page, no DMX page, no sensor page. There is one panel — Interactions — and every control route in the project goes through it, whether the signal came from a lighting desk, a phone, an Arduino or a thumbstick. That design choice is the single most important thing to understand before you plug a game controller into Millumin, because it means mapping a gamepad is not about MIDI at all. It is about building interactions, and interactions have a middle stage that most software does not give you.

TL;DR
  • Two shortcuts run the whole workflow: CMD+K for the device panel, CMD+M for the Interactions panel — both documented in Millumin's own help.
  • Every interaction is input → transformer → action. The transformer stage is where gamepad mapping gets good.
  • Toggle and switch transformers turn momentary buttons into latched states without touching the controller config.
  • Millumin speaks MIDI, OSC, DMX (Art-Net / sACN / USB), MSC and electronics through the same panel.
  • Setup time: about 15 minutes from a cold install to a stick driving a layer parameter.

Why does Millumin's interaction model matter for a gamepad?

Because the transformer stage lets you reshape a raw controller value inside Millumin, which removes most of the reasons people fight their mapping.

Millumin's documentation describes an interaction as three parts: the input — the signal that triggers the interaction, which may carry a value such as a MIDI fader going from 0 to 127; the transformer, which can change the value of the input; and the action, which performs a change in the Millumin project. Five transformer types are documented, including switch and toggle for alternating between two values, and an accumulator for gradually increasing values.

Compare that to the usual arrangement, where mapping is a direct wire from message to parameter and any reshaping has to happen at the controller. In Millumin you can take a plain momentary button press and turn it into a latch, or take a repeated button press and turn it into a counter that steps a value upward, without the bridge or the controller knowing anything about it. For gamepad work that is a genuine advantage, because a gamepad has a lot of momentary buttons and most of the useful show states are not momentary.

It also means the mapping is portable. Build an interaction around a toggle transformer and it behaves identically whether the input is a DualSense face button, a Launchpad pad, or a note from a lighting desk. The behaviour lives in the project, not in the hardware.

Signal flow diagram: Controller to Bridge to Virtual MIDI port to Millumin input to Transformer to Action. Controller HID reports Bridge translation Virtual MIDI port IAC on macOS Millumin input Interactions panel Transformer scales and shapes Action layer, column, property
The transformer stage is what makes Millumin different — the same input drives a different result depending on what you put between it and the action.

How do you get the controller into Millumin in the first place?

A bridge converts the controller's HID stream into MIDI on a named virtual port, and Millumin enables that port as a MIDI source in the device panel.

Millumin, like every host in this category, does not read gamepad HID directly — it reads MIDI, OSC and DMX. The bridge sits in between. If the mechanics of that conversion are new to you, what a DualSense bridge actually does explains why the operating system keeps HID and MIDI apart in the first place, and how to create a virtual MIDI port covers the OS-level step.

On the Millumin side the device panel opens with CMD+K. Under MIDI, Millumin lets you enable or disable sources and destinations independently — note that distinction, because enabling the destination and not the source is a classic five-minute waste of time. The same panel also hosts OSC (one listener, multiple senders, with Bonjour auto-completion and OSCQuery support), DMX over Art-Net, sACN or USB interfaces, and Arduino/Teensy boards, per Millumin's devices documentation.

Once the source is enabled, everything else happens in Interactions.

What should each gamepad input control in a Millumin project?

Continuous layer and mapping parameters on the analog inputs, column and timeline triggers on the face buttons, and navigation on the d-pad.

ControlInput typeTransformerActionWhy this pairing
R2 analog triggerCCNone (direct value)Master opacity or effect intensitySpring return to zero means the effect always ends cleanly, with no chance of walking away with it engaged.
L2 analog triggerCCNoneLayer blend amountMirrors R2 so both hands have an identical gesture on opposite sides of the composition.
Left stick XCCScalingMapping point X nudgeRaw MIDI range across a full surface is far too coarse — scale it down so a full stick deflection moves a few pixels, not a few hundred.
Left stick YCCScalingMapping point Y nudgeSame reasoning. Corner-pinning wants fine control, not fast control.
Right stick XCCNoneColour / hue parameterA circular parameter on a circular control reads correctly to the hand.
Right stick YCCNonePlayback ratePush forward to speed up is the one stick convention everybody already shares.
Touchpad X / YCC pairNoneEffect XY originThe only genuine 2D absolute surface on the device. Do not waste it on two unrelated 1D parameters.
CrossNoteNoneLaunch next columnThe most-used action belongs on the most-reachable button.
CircleNoteToggleFreeze current columnA state, so it latches. The transformer does the latching, not the controller.
SquareNoteToggleEffect bypassAnother genuine state. Grouped with Circle so both latching controls sit together.
TriangleNoteNoneStop all / return to neutralMomentary by design. Your recovery action should never be something that can be left on.
D-pad up / downNoteNonePrevious / next boardNavigation on the directional control. Obvious, and obvious is what you want at 1am.
D-pad left / rightNoteAccumulatorStep a numeric value down / upThis is what accumulator transformers are for — repeated presses walking a value instead of jumping it.
L1NoteNoneShift layer (held)Hold-to-shift beats latch-to-shift because you cannot forget it is engaged.
R1NoteToggleBlackoutA state you must be able to set and leave. Put it under the finger that is already resting there.

Notice how many entries have a transformer. That is the Millumin-specific part of this mapping, and it is why a map built for Millumin looks different from the same show built in Resolume, where the equivalent behaviour lives in the shortcut mode rather than in a separate stage.

Can a gamepad usefully drive projection mapping points?

Yes, with a scaling transformer, and it is one of the better uses of a controller in this whole category.

Corner-pinning a projection surface with a trackpad is miserable work. You are dragging a point a few pixels at a time, you cannot see the surface because your head is behind the laptop, and every drag is a fresh grab-and-release. A thumbstick solves two of those problems at once: it is proportional, so a small deflection is a slow nudge and a big deflection is a fast move, and it is one-handed, so you can stand where you can actually see the projection.

The catch is scale. A MIDI CC's 128 steps spread across a 4K surface is 30-odd pixels per step, which is uselessly coarse for the final alignment. Two fixes, in order of preference. First, use a transformer to scale the stick's contribution right down so full deflection is a handful of pixels per second — you give up speed and gain the precision that actually matters. Second, if you need both speed and precision, bind a shift button that swaps between a coarse and a fine interaction.

The structural approach to surfaces themselves is documented on Millumin's mapping page, which is worth reading before you decide which points are worth putting on a controller at all. For the equivalent workflow in a dedicated mapping tool, see MadMapper with a DualSense.

Where does MIDI Show Control fit?

MSC is for when Millumin is a follower rather than a leader, and a gamepad usually sits alongside it rather than replacing it.

Millumin documents settings for receiving MIDI Show Control commands such as GO and STOP, which can trigger columns and timelines. In a theatre context that typically means a stage manager's desk or a cue system is the master clock for the show and Millumin obeys it. That is the correct architecture for anything with a script — you do not want a VJ improvising cue positions in a show with actors hitting marks.

The gamepad's role in that world is the secondary surface: the things that are not on the cue sheet. Manual overrides, a blackout, a live busking layer during a scene change, an operator-driven intensity ride while the structural cues stay on MSC. Keep those two populations of control strictly separate — anything that appears in the stage manager's book belongs on MSC, anything that is operator discretion belongs on the pad. Mixing them is how you end up with two sources of truth for the same cue.

If the cue stack itself is the thing you want on a controller, that is a different article: QLab gamepad MIDI show control covers the cue-firing side, and the theatre cue stack covers the operator ergonomics.

MIDI or OSC into Millumin — which should you use?

MIDI for triggering and anything coarse, OSC for continuous parameters where you can see the 7-bit stepping.

Millumin supports one OSC listener and multiple OSC senders, with Bonjour auto-completion for addresses and ports and OSCQuery support for inter-application communication. That is a strong OSC implementation by the standards of this software category, and it matters for exactly one class of problem: long, slow parameter sweeps.

A MIDI CC carries 128 values. Ride an opacity from 0 to 100% over ninety seconds and you will see 128 discrete steps, because you are moving roughly one step per second and the human eye is extremely good at spotting that. Ride the same parameter over two seconds and nobody will ever know. So the rule is practical rather than ideological: if the sweep is slow and the parameter is visually smooth, consider OSC; otherwise MIDI is fine and simpler.

OSC output from Universal Controller MIDI is a Pro-tier feature, while the free tier covers one controller on one port with three saved presets over MIDI. Start on MIDI — you will know within a rehearsal whether stepping is a real problem for your material. The full trade-off is in OSC versus MIDI from a gamepad, and the networking side in the Open Stage Control hybrid rig.

What goes wrong, and in what order should you check it?

Source not enabled, interaction created but never tested, and a virtual port that renamed itself — in that order, every time.

  • Nothing arrives at all. Check the device panel (CMD+K) and confirm the MIDI source is enabled, not just the destination. Then confirm the bridge is running and that exactly one instance of it is. Two instances fighting over one port name is a reliable way to lose an afternoon — the missing-port decision tree walks the rest of it.
  • Some controls work and others do not. Almost always interactions that were created in the panel and never exercised with the panel closed. Run every control once, deliberately, before you call a map finished.
  • A button does the thing twice. You have both a note-on and a note-off reaching the action. Add a transformer, or configure the bridge to send the note cleanly — the input reference covers which inputs are prone to this.
  • Everything worked yesterday and nothing works today. The virtual port name changed, so Millumin sees a new, disabled device. Name your ports explicitly and stop recreating them; the discipline is covered per-OS in the macOS IAC Driver guide.
  • A stick drifts a parameter with nobody touching it. That is controller-side, not Millumin-side. Set a deadzone at the bridge; the stick drift guide explains why a slightly wider deadzone on an older pad is the right answer rather than a filter in the project.

How do you keep an interaction list readable six months later?

By designing the interaction list the same way you would design a script — grouped by purpose, named deliberately, and small enough to read in one screen.

The Interactions panel's great strength is that it is one place. Its corresponding weakness is that it is one place, so an undisciplined project accumulates thirty interactions from four different sources and becomes unreadable. Millumin's architecture does not stop you doing that; only your own habits do.

Three habits that pay for themselves. Group by purpose, not by device. All the playback interactions together, all the parameter rides together, all the mapping nudges together — regardless of whether the input was a gamepad, a phone or a lighting desk. In performance you think in terms of what a control does, not where it came from.

Delete aggressively. An interaction you built during an experiment and never removed will eventually fire during a show, probably at the worst moment, and you will spend the next twenty minutes wondering why a layer keeps changing opacity on its own. If an interaction has not been used in the last two rehearsals, it does not belong in the project.

Document the physical side externally. Millumin knows that note 60 does something. It does not know that note 60 is the Cross button, and neither will you in six months. Keep a short table — control, note or CC, what it does — somewhere outside the software, and update it in the same session you change a mapping rather than promising yourself you will do it later.

The reward for this discipline is specific: a project you can hand to somebody else, or pick up after a gap, without reverse-engineering your own work. That matters much more in Millumin's world — theatre, dance, installation — than it does in a club, because those projects get revived, toured and reconstructed in a way that a one-night VJ set never does.

FAQ

How do you connect a MIDI controller to Millumin?

Open the device panel with CMD+K and enable your MIDI source, then open the Interactions panel with CMD+M and create an interaction that captures the incoming message. All control routing in Millumin lives in that one interactions panel.

What is an interaction in Millumin?

An interaction is a three-part route made of an input, an optional transformer and an action. The input is the incoming signal such as a MIDI fader, the transformer reshapes its value, and the action is the change performed in the Millumin project.

Can Millumin use a game controller as a MIDI device?

Yes, once a bridge converts the controller HID stream into MIDI on a virtual port. Millumin then sees an ordinary MIDI source and cannot tell the difference between that and a hardware controller.

How do I make a gamepad button latch instead of being momentary in Millumin?

Add a toggle or switch transformer to the interaction. Millumin documents these as the transformers to use when you want to alternate between two values, which turns a momentary note into a latched state without changing anything on the controller.

Does Millumin support MIDI Show Control?

Yes. Millumin documents settings for receiving MIDI Show Control commands such as GO and STOP, which can trigger columns and timelines — useful when a stage manager desk is the master and the gamepad is a secondary surface.

Can a gamepad control Millumin mapping points?

Mapping points are controllable from the interactions system, so a stick axis can nudge a surface corner. Expect to add a transformer to scale the movement, because a raw MIDI range across a full projection surface is far too coarse for fine corner-pinning.

Should I use MIDI or OSC from a gamepad into Millumin?

MIDI for triggering and coarse parameters, OSC when you need fine continuous resolution — Millumin supports an OSC listener alongside MIDI. OSC output from the bridge is a Pro-tier feature, so start on MIDI and move up only if you see stepping.

Get a controller into the Interactions panel tonight

Millumin's single-panel model means one good mapping session gives you a control surface that works the same whether the signal came from a thumbstick or a lighting desk. Download Universal Controller MIDI, create one named virtual port, enable it as a source with CMD+K, and start building interactions.

Keep reading

More setup walkthroughs