Count & Display State¶
Our SimpleAction reacts to presses but forgets everything between them. Let's build a second action that remembers something: a counter that goes up each time you press it and shows the number on the key.
This introduces two ideas: keeping state on your action, and drawing text with set_label. It also gives you practice adding a second action to a plugin.
1. Add a new directory¶
Every action should live in its own subdirectory of actions.
counter in the actions directory. Feel free to change the name or path as long as it's inside the plugin's dir.
2. Create a new file for the action¶
This creates an empty filecounter.py. In the next steps we'll fill it.
3. Programming the new action¶
Let's add a basic action to counter.py:
# Import StreamController modules
from src.backend.PluginManager.ActionCore import ActionCore
class Counter(ActionCore):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
That's a valid action already, it just doesn't do anything yet, and it isn't registered, so it won't show up in the UI.
4. Register the action¶
All actions have to be registered in the plugin's plugin base, here in main.py.
First, import the new action below the import of SimpleAction:
ActionHolder for it and add it to the plugin:
# Import StreamController modules
from src.backend.PluginManager.PluginBase import PluginBase
from src.backend.PluginManager.ActionHolder import ActionHolder
from src.backend.PluginManager.ActionInputSupport import ActionInputSupport
from src.backend.DeckManagement.InputIdentifier import Input
# Import actions
from .actions.SimpleAction.SimpleAction import SimpleAction
from .actions.counter.counter import Counter
class PluginTemplate(PluginBase):
def __init__(self):
super().__init__()
## Register actions
self.simple_action_holder = ActionHolder(
plugin_base = self,
action_core = SimpleAction,
action_id_suffix = "SimpleAction",
action_name = "Simple Action",
action_support = {
Input.Key: ActionInputSupport.SUPPORTED,
Input.Dial: ActionInputSupport.SUPPORTED,
Input.Touchscreen: ActionInputSupport.UNSUPPORTED,
}
)
self.add_action_holder(self.simple_action_holder)
self.counter_action_holder = ActionHolder(
plugin_base = self,
action_core = Counter,
action_id_suffix = "Counter",
action_name = "Counter",
action_support = {
Input.Key: ActionInputSupport.SUPPORTED,
Input.Dial: ActionInputSupport.SUPPORTED,
Input.Touchscreen: ActionInputSupport.UNSUPPORTED,
}
)
self.add_action_holder(self.counter_action_holder)
# Register plugin
self.register(
plugin_name = "Template",
github_repo = "https://github.com/StreamController/PluginTemplate",
plugin_version = "1.0.0",
app_version = "1.5.0-beta.14"
)
Note
The full action_id (formed as <plugin_id>::<action_id_suffix>) must be unique within your plugin.
5. Do something!!!¶
An action that does nothing is pointless, let's make it count presses and show the number on the input.
1. Add a counter variable and an event assigner¶
Actions react to input by registering an EventAssigner. We bind our handler to the key and dial "down" events so the counter works on both keys and dials:
# Import StreamController modules
from src.backend.PluginManager.ActionCore import ActionCore
from src.backend.PluginManager.EventAssigner import EventAssigner
from src.backend.DeckManagement.InputIdentifier import Input
class Counter(ActionCore):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.counter: int = 0
self.add_event_assigner(EventAssigner(
id="increment",
ui_label="Increment",
default_events=[Input.Key.Events.DOWN, Input.Dial.Events.DOWN],
callback=self.on_increment
))
2. Increment the counter and update the label¶
...
def on_increment(self, data):
self.counter += 1
self.set_center_label(str(self.counter))
3. Show the initial counter on load¶
4. The result¶
The final counter.py looks like this:
# Import StreamController modules
from src.backend.PluginManager.ActionCore import ActionCore
from src.backend.PluginManager.EventAssigner import EventAssigner
from src.backend.DeckManagement.InputIdentifier import Input
class Counter(ActionCore):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.counter: int = 0
self.add_event_assigner(EventAssigner(
id="increment",
ui_label="Increment",
default_events=[Input.Key.Events.DOWN, Input.Dial.Events.DOWN],
callback=self.on_increment
))
def on_ready(self):
self.set_center_label(str(self.counter))
def on_increment(self, data):
self.counter += 1
self.set_center_label(str(self.counter))
Tip
Because we registered the handler as an event assigner with a ui_label, the user can remap what triggers the increment (for example to a long press or a dial turn) right from the action's settings. See Handling Input & Events.