Operator SDK
Build MIDI processing and UI modes for the Operator device
Loading...
Searching...
No Matches
mode_api.h File Reference

The Operator function table a mode calls into, plus the mode export signatures and the input gesture ABI. More...

#include <cstdint>

Classes

struct  OpMidiMessage
 A single MIDI message passed to a mode's process function. More...
struct  OperatorApi
 The function table a mode calls into. More...

Namespaces

namespace  op
 Root namespace for the Operator SDK.

Typedefs

typedef void(* ModeInitFn) (const OperatorApi *api)
 Signature of a mode's mode_init export, called once at load with the API table.
typedef void(* ModeProcessFn) (OpMidiMessage *msgs, uint8_t count, uint32_t tick)
 Signature of a mode's mode_process export, called with the incoming MIDI messages.
typedef void(* ModeDestroyFn) (void)
 Signature of a mode's mode_destroy export, called once at unload.
typedef void(* ModeMigrateConfigFn) (const uint8_t *old_data, uint16_t old_version)
 Signature of a mode's mode_migrate_config export, called to upgrade persisted config.
typedef void(* ModeUiRenderFn) (void)
 Signature of a mode's mode_ui_render export, called each frame to draw the custom UI.
typedef void(* ModeUiGestureFn) (uint8_t encoder_id, uint8_t gesture, uint8_t gesture_type, int16_t value)
 Signature of a mode's mode_ui_gesture export, a flat input event handler.
typedef bool(* ModeOnSysexFn) (uint8_t port, const uint8_t *data, uint16_t len, uint8_t flags)
 Signature of a mode's SysEx handler, called with inbound SysEx.
typedef void(* ModeOnSelectFn) (void)
 Signature of the callback an Action parameter runs.
using op::LogLevel = ::LogLevel
 Scoped alias for the log severity enum, so mode code writes op::LogLevel::Warn alongside the other op:: scoped enums.

Enumerations

enum  OpClockState : uint8_t
 Clock authority state returned by get_clock_state. More...
enum class  LogLevel : uint8_t
 Severity level for a log line passed to OperatorApi::log. More...
enum class  op::Gesture : uint8_t
 Physical gesture kind for an input event. More...
enum class  op::GestureType : uint8_t
 Input-map resolved gesture type for an input event. More...

Variables

static const uint16_t kOperatorSdkVersion = 1
 The current SDK and function table version.
static const int32_t kStorageBusy = -2
 Storage result meaning the device is busy with flash right now.
static const int32_t kStorageNoSpace = -3
 Storage result meaning the store is out of space.
static const int32_t kOutputBusy = -2
 send_sysex result meaning the output cannot take the fragment now.
static const int32_t kOutputTooLarge = -3
 send_sysex result meaning the fragment is bigger than the output can carry.
static const uint8_t kStorageOpenTruncate = 0
 open_mode that creates the file, or overwrites an existing one from empty.
static const uint8_t kStorageOpenOverwrite = 1
 open_mode that keeps the existing bytes and writes in place from offset 0.
static const uint8_t kSysExStart = 0x01
 mode_on_sysex flags bit marking the first fragment of a message.
static const uint8_t kSysExEnd = 0x02
 mode_on_sysex flags bit marking the last fragment of a message.
static const uint8_t kEncoderLeft = 0
 Encoder id for the left encoder, passed to mode_ui_gesture.
static const uint8_t kEncoderRight = 1
 Encoder id for the right encoder, passed to mode_ui_gesture.

Detailed Description

The Operator function table a mode calls into, plus the mode export signatures and the input gesture ABI.

OperatorApi is the versioned struct of function pointers the firmware hands a mode at init. A mode keeps the pointer and calls through it to send MIDI, read timing and clock state, read and write scoped storage, draw to the display, log, and read and write its declarative parameters. A mode resolves an entry by its position, so the table only ever grows. New entries are appended, and existing ones keep their position and their type. A mode built against one SDK release keeps loading on later firmware, which offers it entries it never calls.

Typedef Documentation

◆ ModeOnSelectFn

typedef void(* ModeOnSelectFn) (void)

Signature of the callback an Action parameter runs.

Declaring the button with op::params::Action wires it up.

◆ ModeOnSysexFn

typedef bool(* ModeOnSysexFn) (uint8_t port, const uint8_t *data, uint16_t len, uint8_t flags)

Signature of a mode's SysEx handler, called with inbound SysEx.

The handler runs only when the mode declares HANDLES_SYSEX. A short message arrives in a single call carrying both flag bits. A long one arrives as several fragments across multiple calls, in order, the first flagged kSysExStart and the last kSysExEnd. port is the input the message arrived on, whichever kind of mode receives it, so a mode reassembling a dump can keep two senders apart. Returning true on the fragment flagged kSysExStart consumes the message, so it is not sent on and no later mode in the chain sees the rest of it. Returning false lets it continue to the outputs. A mode that exports no handler passes every message. The decision is read on the start fragment and held through kSysExEnd, so the return value of a later fragment is ignored.

◆ ModeUiGestureFn

typedef void(* ModeUiGestureFn) (uint8_t encoder_id, uint8_t gesture, uint8_t gesture_type, int16_t value)

Signature of a mode's mode_ui_gesture export, a flat input event handler.

gesture_type carries the meaning resolved through the input map (Scroll, Change, Enter, Back), which is what most modes read. encoder_id and gesture carry the raw event for a mode that wants map-independent behavior. value is the signed rotation step with acceleration applied for a rotate, and 0 for presses.

Enumeration Type Documentation

◆ LogLevel

enum class LogLevel : uint8_t
strong

Severity level for a log line passed to OperatorApi::log.

A mode picks the level that matches the message's importance. The Log Monitor view renders one letter per level (D / I / W / E) and can filter by level, so choosing an accurate level makes a mode's output easier to read and filter. Prefer the scoped alias op::LogLevel.

◆ OpClockState

enum OpClockState : uint8_t

Clock authority state returned by get_clock_state.

A mode polls this to decide whether the pulse counter is advancing, whether it should generate its own timing, and whether the user has delegated clock authority to a loaded mode.

Variable Documentation

◆ kOperatorSdkVersion

const uint16_t kOperatorSdkVersion = 1
static

The current SDK and function table version.

A mode built against this version or an earlier one runs here.

◆ kOutputBusy

const int32_t kOutputBusy = -2
static

send_sysex result meaning the output cannot take the fragment now.

Returned by send_sysex when the fragment plus its opening and closing bytes will not fit right now. Nothing was queued and the open message is left intact, so the same fragment goes out again on a later process().

◆ kOutputTooLarge

const int32_t kOutputTooLarge = -3
static

send_sysex result meaning the fragment is bigger than the output can carry.

Returned by send_sysex when the fragment plus its opening and closing bytes is larger than the output can ever carry, so the message needs splitting into smaller ones. A retry answers the same however long the wait. Nothing was queued and any open message is left intact.

◆ kStorageBusy

const int32_t kStorageBusy = -2
static

Storage result meaning the device is busy with flash right now.

Any storage call can answer it when the other core is mid-write. A call answered with it succeeds on a later process().

◆ kStorageNoSpace

const int32_t kStorageNoSpace = -3
static

Storage result meaning the store is out of space.

Returned by storage_file_write. The store stays full until the user frees space on it.

◆ kSysExStart

const uint8_t kSysExStart = 0x01
static

mode_on_sysex flags bit marking the first fragment of a message.

The consume-or-pass choice is made on this fragment and held through kSysExEnd, so the message is handled whole either way.