Skip to content

React to Input

Remember this block we skipped in the action?

self.add_event_assigner(EventAssigner(
    id="simple_action_pressed",
    ui_label="Pressed",
    default_events=[Input.Key.Events.DOWN, Input.Dial.Events.DOWN],
    callback=self.on_pressed
))

This is how your action reacts to input. When the button goes down, on_pressed runs. That's why you saw Pressed printed in your terminal.

Event assigners

You react to input by registering event assigners. Each one connects a callback to one or more input events:

def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)

    self.add_event_assigner(EventAssigner(
        id="simple_action_pressed",   # unique name within the action
        ui_label="Pressed",           # shown to the user (see "Remapping" below)
        default_events=[Input.Key.Events.DOWN, Input.Dial.Events.DOWN],
        callback=self.on_pressed
    ))

def on_pressed(self, data):
    print("Pressed")

The interesting part is default_events: it's a list, so one assigner can react to several events. Here on_pressed fires on both a key press and a dial press, which is why the same action works on a normal button and on a Stream Deck + dial.

The available events

Events live on the input type they belong to:

Input Events you can use
Input.Key.Events DOWN, UP, SHORT_UP, HOLD_START, HOLD_STOP
Input.Dial.Events the key events, plus TURN_CW, TURN_CCW, SHORT_TOUCH_PRESS, LONG_TOUCH_PRESS
Input.Touchscreen.Events DRAG_LEFT, DRAG_RIGHT

Make the dial do its own thing

Reacting the same way to a key and a dial press is fine, but a dial can also turn. Let's give turning its own behaviour by adding two more assigners:

self.add_event_assigner(EventAssigner(
    id="turn_up",
    ui_label="Turn up",
    default_event=Input.Dial.Events.TURN_CW,
    callback=self.on_turn_up
))
self.add_event_assigner(EventAssigner(
    id="turn_down",
    ui_label="Turn down",
    default_event=Input.Dial.Events.TURN_CCW,
    callback=self.on_turn_down
))

(Use default_event for a single event, or default_events=[...] for several.)

Letting the user remap events

Every assigner you give a ui_label automatically shows up in the action's settings, where the user can reassign it to a different event, for example moving "Pressed" from a short press to a long press. You get this for free; there's no UI to write.

Declaring input support

One loose end: in main.py we told StreamController which inputs the action supports:

action_support = {
    Input.Key: ActionInputSupport.SUPPORTED,
    Input.Dial: ActionInputSupport.SUPPORTED,
    Input.Touchscreen: ActionInputSupport.UNSUPPORTED,
}
  • SUPPORTED: you've tested it on this input.
  • UNTESTED: it might work; the UI warns the user.
  • UNSUPPORTED: it can't be placed on this input.

Since we just added dial-turning, Input.Dial: SUPPORTED is well earned.

Next: let's let the user configure the action, add a setting.


Coming from an older plugin?

Older actions overrode fixed on_key_down / on_key_up methods on ActionBase. Event assigners replace that approach and are what make dials and the touchscreen possible. The old methods still work on ActionBase if you ever meet them in existing code.