Skip to content

Remote control

HotPunch can be driven from outside itself two ways — a MIDI controller and an OSC controller — and they are the same job: a physical button somewhere in the gallery that does what a button in HotPunch does. They are documented together because the important things about them are the same things, and because the differences between them are the part that bites.

The rule that holds for both: remote control is another door into the same room, not a back door. Nothing you send over MIDI or OSC skips the checks that stop you going live without a licence, without a mixer, or with the ISO Review window open.

What you need

  • MIDI: a control surface with a MIDI output that HotPunch's machine can see — a Stream Deck with a MIDI plugin, a small note-sending pad, a lighting desk. Notes only.
  • OSC: anything that can send OSC over UDP to a port on the HotPunch machine — Bitfocus Companion is the intended case, and a Companion module exists as a separate project.
  • A network you trust. See Nobody is checking who you are.

Neither is licence-gated. Both are configured per project.

Which one to use

MIDI OSC
Commands available 4 15
Per-M/E break no yes
Cue navigation, follow-playhead, transport stop no yes
State feedback to the controller none yes
Debounce against double triggers 200 ms per command none
GO LIVE behaviour instant, one message arm-to-confirm, two messages

If your surface can speak OSC, speak OSC. MIDI is the shorter road for the four things it does.


MIDI

The four commands

Label What it does
ON AIR Standby → Live, and Live → Standby
BREAK Live → Break, and Break → Live
PLAY/STOP Play / pause the active timeline
LOCK TC Arm or disarm the timecode lock

That is the whole list. There is no per-M/E break, no cue navigation, and no MIDI output at all — HotPunch never lights up your controller's LEDs, because it never sends MIDI.

Binding

Settings > MIDI. Choose the input device, then, for each command, a note number and a channel (or "Any"). Press Learn on a row and the next note you play fills both fields.

  • Note-on messages only. Control changes are ignored entirely; if your surface sends CC, it will not work and nothing will say so.
  • A note-on with velocity zero — how some devices spell note-off — is ignored.
  • Changes apply as you make them, and are saved in the project.
  • Learn has no timeout and no cancel. Once armed it waits until a note arrives or you press Learn on another row.

The MIDI Monitor at the bottom of the tab prints what it receives. It is the only way to find out whether your surface is sending what you think it is sending, and it is worth ten minutes before a show.

Warning

MIDI bindings are not restored on their own when you launch HotPunch or open a project. They are applied when the MIDI tab applies them — which means opening Settings > MIDI and pressing OK or Apply once, in each session, before the bindings do anything. Until you do, the device is not even opened and the monitor stays empty. Make it part of your setup routine.

A device that is unplugged and plugged back in is reopened automatically within a couple of seconds, provided it had been opened in the first place.

Repeated triggers

Each command ignores a repeat within 200 ms of itself. The window is per command, not global, so hammering BREAK does not swallow a PLAY that arrives at the same moment. The value is fixed and there is no control for it.

ON AIR is not the GO LIVE button

The GO LIVE button uses arm-to-confirm: press once to arm, again within three seconds to confirm, in both directions. See Go live.

MIDI ON AIR does not. One note and you are live. One note and the show ends. This is deliberate — a physical button that needs a double press is a physical button that gets pressed once in an emergency — but it means the note you bind to ON AIR is the most dangerous note on your surface, and it should not be next to anything else you press.

It is still gated. A MIDI ON AIR that cannot go live is refused with the same Cannot Go Live dialog you would get from the button, for the same reasons: ISO Review window open, licence, no show selected, no protocol engine, engine not connected. And an unstarted Show Pass refuses the first attempt and opens its dialog, exactly as it does from the button — see The Show Pass case.

Two differences from the button that are worth knowing:

  • The button also waits for media to finish loading before it will arm. The MIDI command does not consult that, so a MIDI ON AIR fired while audio is still being prefetched goes live anyway.
  • From Break, the MIDI ON AIR key does nothing at all. The button ends the show from Break; the MIDI command has no branch for it. To end a show that is in Break, use the button, or exit Break first.

BREAK and LOCK TC

BREAK toggles global break only. Coming out of Break re-runs the full set of live preconditions, so it can be refused — most usefully when the mixer connection is what put you in Break in the first place, and has not come back.

LOCK TC does nothing when the sync source is Off, silently and without a log line, because the button it presses is not on screen. If your remote lock appears dead, check the sync source first. See Timecode sync.

PLAY/STOP is a pause toggle, not a stop: it never rewinds to zero, because in Live that would punch the first cue of the timeline. It works in every operational state.


OSC

Turning it on

Settings > Tally / Web > Enable OSC remote control, with a port next to it. Off by default, port 8010, saved in the project.

What it accepts

Addresses are matched exactly — no patterns, no wildcards. Anything else is dropped without comment.

Address Arguments Effect
/hotpunch/subscribe int port, string ip Register for state feedback (see below)
/hotpunch/transport/play Play / pause toggle
/hotpunch/transport/toggle The same play / pause toggle
/hotpunch/transport/stop Stop the active timeline
/hotpunch/golive Arm, then confirm, GO LIVE or END LIVE
/hotpunch/endlive End the show immediately
/hotpunch/break/all Enter / leave global Break
/hotpunch/break/me1 Enter / leave Break on M/E 1
/hotpunch/break/me2 Enter / leave Break on M/E 2
/hotpunch/cue/next Move the playhead to the next cue
/hotpunch/cue/prev Move the playhead to the previous cue
/hotpunch/sync Arm / disarm the timecode lock
/hotpunch/follow Toggle follow-playhead

Warning

Every one of these is a toggle. Some of them accept an integer argument and HotPunch parses it, but nothing reads it: /hotpunch/break/all 1 behaves exactly like a bare /hotpunch/break/all, so sending it while break is already on turns break off.

When you build controller buttons, build toggles with feedback — the state messages below tell you which way the switch is currently thrown. Do not build separate "on" and "off" buttons; they will fight each other.

Two more things the table does not show: /transport/play cannot force play, it toggles, so it is indistinguishable from /transport/toggle; and cue navigation is refused while you are Live, because the playhead is not yours to move on air. It works in Break.

GO LIVE over OSC, and the shared arm

/hotpunch/golive goes through the same arm-to-confirm as the button: the first message arms it for three seconds, the second confirms. /hotpunch/endlive does not — one message and the show ends.

The arm state lives on the on-screen button, which has a consequence: an OSC go-live arms the button in the app, and an operator standing at the machine can confirm your remote arm by clicking it. That also works the other way round. Two people, one arm.

When the button is not armable — media still loading, no engine, licence, ISO Review open — an OSC /hotpunch/golive is refused silently: no dialog, no log line, nothing on the controller except a state that fails to change. Read the machine, not the button.

State feedback

Feedback is unicast to whoever asked for it. Send:

/hotpunch/subscribe  <int: your port>  <string: your IP>

Both arguments are required — HotPunch cannot read the sender's address off an incoming OSC packet, so you have to tell it where to reply.

Warning

A subscription lapses after ten seconds. Only another /hotpunch/subscribe renews it; inbound commands do not, and neither does the outgoing heartbeat. A controller that subscribes once at startup goes dark ten seconds later. Re-send the subscribe message on a timer — every few seconds is fine.

There is no working unsubscribe. Stop renewing and the subscription expires by itself.

Subscribers receive the following, whenever something changes and again every two seconds regardless:

Address Type Values
/hotpunch/state/mode string offline, standby, live, break
/hotpunch/state/armed int GO LIVE is armed and counting down
/hotpunch/state/playing int The timeline is running
/hotpunch/state/sync int The timecode lock is armed
/hotpunch/state/follow int Follow-playhead is on
/hotpunch/state/dualme int Dual M/E is enabled
/hotpunch/state/break/all int Global break is active
/hotpunch/state/break/me1 int M/E 1 is broken
/hotpunch/state/break/me2 int M/E 2 is broken
/hotpunch/state/avail/break_all int Whether the global break command would do anything
/hotpunch/state/avail/break_me1 int Whether the M/E 1 break command would do anything
/hotpunch/state/avail/break_me2 int Whether the M/E 2 break command would do anything
/hotpunch/state/heartbeat int A counter that increases every two seconds

The avail/* messages are what you use to grey out buttons that cannot act right now. The heartbeat is what you use to notice that HotPunch stopped talking to you — it is the only message that changes when nothing else does.

Nobody is checking who you are

The OSC listener binds the port on every interface and accepts anything that arrives. There is no authentication, no allow-list, and no rate limit. Anyone who can reach that port can end your show with one packet.

Put it on the production network, not on anything reachable from a guest VLAN or the internet, and turn it off when you are not using it. This is not paranoia about attackers — it is about the laptop in the corner running a stale Companion page that still has your show in its config.


Where the arming rules differ

Collected in one table, because it is the thing that surprises people:

Action Button MIDI OSC
Go live arm, then confirm one message arm, then confirm
End live arm, then confirm one message one message (/endlive)
End live from Break yes no yes
Refusal is visible tooltip on the disabled button dialog silent

What is identical everywhere: the preconditions. Licence, show selected, engine connected, ISO Review closed, Show Pass started. No route bypasses them, and each of them is documented in If GO LIVE will not arm.