Operator SDK
Build MIDI processing and UI modes for the Operator device
Loading...
Searching...
No Matches
OperatorApi Struct Reference

The function table a mode calls into. More...

#include <mode_api.h>

Public Attributes

bool(* send_midi )(uint8_t output_idx, uint8_t status, uint8_t data1, uint8_t data2)
 Queue a 1 to 3 byte MIDI message for output.
bool(* send_midi_direct )(uint8_t output_idx, uint8_t status, uint8_t data1, uint8_t data2)
 Queue a 1 to 3 byte MIDI message straight to the output.
bool(* send_midi_from )(uint8_t input_idx, uint8_t status, uint8_t data1, uint8_t data2)
 Queue a 1 to 3 byte MIDI message caused by one this mode was handed.
int32_t(* send_sysex )(uint8_t output_idx, const uint8_t *data, uint16_t len, uint8_t flags)
 Queue a system-exclusive message, or a fragment of one, for output.
bool(* output_active )(uint8_t output_idx)
 Report whether an output can currently emit MIDI.
uint32_t(* get_tick )()
 Monotonic microsecond counter since boot.
uint32_t(* get_pulse_count )()
 Monotonic 24 PPQ pulse counter since boot.
void(* set_clock_period_us )(uint32_t period_us)
 Program the internal clock generator's period.
int32_t(* storage_read )(const char *path, uint8_t *buf, uint32_t size)
 Read up to size bytes from a scoped path into buf.
int32_t(* storage_file_open )(const char *path)
 Open a handle for streaming reads under a scoped path.
int32_t(* storage_file_read )(int32_t handle, uint8_t *buf, uint32_t size)
 Read up to size bytes from an open handle.
int32_t(* storage_file_seek )(int32_t handle, uint32_t offset)
 Move an open handle's read cursor.
int32_t(* storage_file_close )(int32_t handle)
 Close an open handle.
int32_t(* storage_file_open_write )(const char *path, uint8_t open_mode)
 Open a handle for streaming writes under a scoped path.
int32_t(* storage_file_write )(int32_t handle, const uint8_t *buf, uint32_t size)
 Write size bytes from buf to an open write handle.
int32_t(* storage_delete )(const char *path)
 Delete a file under a scoped path.
int32_t(* storage_enumerate )(const char *pattern, char *out, uint32_t out_size)
 List the mode's stored files into out as NUL-separated names.
void(* draw_rect )(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
 Draw a 1 pixel outline rectangle.
void(* fill_rect )(uint16_t x, uint16_t y, uint16_t w, uint16_t h, bool on)
 Draw a filled rectangle of on or off pixels.
void(* draw_text )(uint16_t x, uint16_t y, const char *text)
 Draw text in the 5x7 standard font.
void(* draw_text_large )(uint16_t x, uint16_t y, const char *text)
 Draw text in the 8x12 large font.
void(* draw_bitmap )(uint16_t x, uint16_t y, const uint8_t *data, uint16_t w, uint16_t h)
 Draw a packed 1-bit bitmap.
void(* set_pixel )(uint16_t x, uint16_t y, bool on)
 Turn a single pixel on or off.
void(* log )(LogLevel level, const char *message)
 Emit a log line, viewable in the Log Monitor view.
int32_t(* get_param_value )(uint8_t param_id)
 Read the current int32 value of a declarative parameter.
void(* set_param_value )(uint8_t param_id, int32_t value)
 Write a declarative parameter value.
int32_t(* get_param_filename )(uint8_t param_id, char *buf, uint32_t buf_size)
 Resolve a FilePicker parameter to its selected filename.
uint8_t(* get_clock_state )()
 Read the current clock authority state.

Detailed Description

The function table a mode calls into.

Entries are grouped by concern: MIDI I/O, Timing, Storage (scoped read and write), Display, Logging, Parameters, and Clock. SDK version 1 defines 28 entries, and their order below is part of the ABI.

Member Data Documentation

◆ draw_bitmap

void(* OperatorApi::draw_bitmap) (uint16_t x, uint16_t y, const uint8_t *data, uint16_t w, uint16_t h)

Draw a packed 1-bit bitmap.

Parameters
xLeft edge in pixels.
yTop edge in pixels.
dataPage-addressed 1-bit pixel data.
wBitmap width in pixels.
hBitmap height in pixels.

◆ draw_rect

void(* OperatorApi::draw_rect) (uint16_t x, uint16_t y, uint16_t w, uint16_t h)

Draw a 1 pixel outline rectangle.

Parameters
xLeft edge in pixels.
yTop edge in pixels.
wWidth in pixels.
hHeight in pixels.

◆ draw_text

void(* OperatorApi::draw_text) (uint16_t x, uint16_t y, const char *text)

Draw text in the 5x7 standard font.

Parameters
xLeft edge of the first glyph in pixels.
yTop edge in pixels.
textNUL-terminated string to draw.

◆ draw_text_large

void(* OperatorApi::draw_text_large) (uint16_t x, uint16_t y, const char *text)

Draw text in the 8x12 large font.

Parameters
xLeft edge of the first glyph in pixels.
yTop edge in pixels.
textNUL-terminated string to draw.

◆ fill_rect

void(* OperatorApi::fill_rect) (uint16_t x, uint16_t y, uint16_t w, uint16_t h, bool on)

Draw a filled rectangle of on or off pixels.

Parameters
xLeft edge in pixels.
yTop edge in pixels.
wWidth in pixels.
hHeight in pixels.
onTrue sets the pixels, false clears them.

◆ get_clock_state

uint8_t(* OperatorApi::get_clock_state) ()

Read the current clock authority state.

Returns
One of OpClockState as a uint8_t.

◆ get_param_filename

int32_t(* OperatorApi::get_param_filename) (uint8_t param_id, char *buf, uint32_t buf_size)

Resolve a FilePicker parameter to its selected filename.

Copies the null-terminated filename into buf, truncated to buf_size with the NUL always preserved when buf_size is greater than 0. Prefer the typed param<FilePickerSpec>() accessor from <operator_sdk/params.h>, which wraps this entry and returns a FilePickerValue.

Parameters
param_idThe FilePicker parameter id.
bufDestination buffer for the filename.
buf_sizeSize of buf.
Returns
Bytes written excluding the NUL (0 means no file picked yet), or -1 on a validation error.

◆ get_param_value

int32_t(* OperatorApi::get_param_value) (uint8_t param_id)

Read the current int32 value of a declarative parameter.

Parameters
param_idThe parameter's value slot index.
Returns
The current value.

◆ get_pulse_count

uint32_t(* OperatorApi::get_pulse_count) ()

Monotonic 24 PPQ pulse counter since boot.

Advances when the current clock source emits a clock message.

Returns
The pulse count.

◆ get_tick

uint32_t(* OperatorApi::get_tick) ()

Monotonic microsecond counter since boot.

Returns
Microseconds since boot.

◆ log

void(* OperatorApi::log) (LogLevel level, const char *message)

Emit a log line, viewable in the Log Monitor view.

Parameters
levelA LogLevel severity (op::LogLevel::Debug / Info / Warn / Error). The Log Monitor renders it as a D / I / W / E prefix and can filter on it.
messageNull-terminated text to log.

◆ output_active

bool(* OperatorApi::output_active) (uint8_t output_idx)

Report whether an output can currently emit MIDI.

True when output_idx is in range, is not user-disabled, and is present. The USB output reports true while USB MIDI is active. A mode rotating between outputs uses this to pick one that can take the message.

Parameters
output_idxOutput index to query.
Returns
True if the output can emit MIDI right now.

◆ send_midi

bool(* OperatorApi::send_midi) (uint8_t output_idx, uint8_t status, uint8_t data1, uint8_t data2)

Queue a 1 to 3 byte MIDI message for output.

The message joins that output's traffic, so the modes loaded after this one there are handed it and can transform it, hold it back, or answer it.

The output takes it only if it passes that kind of message, so one set to pass clock alone takes no notes. Timing clock (0xF8) goes to the output on its own and joins no mode's batch.

Parameters
output_idxOutput for global modes (0..7 = OUT 1..8, 8 = USB). Ignored for output modes, which always reach their bound output.
statusMIDI status byte.
data1First data byte.
data2Second data byte (ignored for 1 and 2 byte messages).
Returns
True if the message was queued, false if it was dropped.

◆ send_midi_direct

bool(* OperatorApi::send_midi_direct) (uint8_t output_idx, uint8_t status, uint8_t data1, uint8_t data2)

Queue a 1 to 3 byte MIDI message straight to the output.

The modes loaded after this one on that output are never handed it, so it reaches the wire untouched. This suits a timing reference or a tap reporting what an output is doing.

Only those modes are skipped. The output still takes the message only if it passes that kind of message.

Parameters
output_idxOutput for global modes (0..7 = OUT 1..8, 8 = USB). Ignored for output modes, which always reach their bound output.
statusMIDI status byte.
data1First data byte.
data2Second data byte (ignored for 1 and 2 byte messages).
Returns
True if the message was queued, false if it was dropped.

◆ send_midi_from

bool(* OperatorApi::send_midi_from) (uint8_t input_idx, uint8_t status, uint8_t data1, uint8_t data2)

Queue a 1 to 3 byte MIDI message caused by one this mode was handed.

The message joins the traffic on the input named by input_idx, so it is routed exactly as a message arriving there would be.

It carries input_idx as its port, and the global modes loaded after this one are handed it.

Global modes only. An output mode runs once routing has decided where everything goes, so the call is refused there and answers false.

Parameters
input_idxInput the causing message arrived on (0..3 = IN 1..4, 4 = USB).
statusMIDI status byte.
data1First data byte.
data2Second data byte (ignored for 1 and 2 byte messages).
Returns
True if the message was queued, false if it was dropped.

◆ send_sysex

int32_t(* OperatorApi::send_sysex) (uint8_t output_idx, const uint8_t *data, uint16_t len, uint8_t flags)

Queue a system-exclusive message, or a fragment of one, for output.

A short message goes out in a single call. A long one is built up over several calls, and flags says where each call sits in the message.

  • kSysExStart together with kSysExEnd sends a whole message.
  • kSysExStart on its own opens a message that later calls continue.
  • Neither bit set continues the open message with more bytes.
  • kSysExEnd on its own closes it.

Everything sent between the opening and the closing call reaches the output as one message. Each call queues its whole fragment or queues nothing at all, so a call answered with kOutputBusy leaves the open message untouched and the same fragment goes out again on a later process().

One call carries at most 253 payload bytes to a physical output and 448 to the USB output, so 253 bytes per call reaches any output. A message longer than that goes out over several calls.

A message ends by itself after a full second in which none of it reached the output. A refused call sends nothing, so it counts towards that second, and a retry that keeps being refused ends the message it is retrying. Calls after that answer -1 and a new message has to be opened.

Parameters
output_idxOutput index. An output mode passes its own bound output.
dataThe message bytes, without the opening 0xF0 and the closing 0xF7, which are added around the message.
lenNumber of bytes in data. Zero pairs with kSysExEnd to close a message that has no bytes left to send.
flagsWhere this call sits in the message (see the list above).
Returns
len when the whole fragment was queued (0 when the call only closes the message), kOutputBusy when the output could not take it right now, kOutputTooLarge when the fragment is bigger than that output can ever carry, or -1 for an invalid output, an output not set to pass system-exclusive, a mode not allowed to send SysEx, or a call continuing a message that is over.

◆ set_clock_period_us

void(* OperatorApi::set_clock_period_us) (uint32_t period_us)

Program the internal clock generator's period.

Only effective when the caller is a clock generating mode and Clock Source is set to Mode. A period of 0 disables the clock, and setting the same period again is a no-op.

Parameters
period_usClock period in microseconds.

◆ set_param_value

void(* OperatorApi::set_param_value) (uint8_t param_id, int32_t value)

Write a declarative parameter value.

The new value is published within one frame.

Parameters
param_idThe parameter's value slot index.
valueThe value to store.

◆ set_pixel

void(* OperatorApi::set_pixel) (uint16_t x, uint16_t y, bool on)

Turn a single pixel on or off.

Out-of-range coordinates are a no-op.

Parameters
xColumn in pixels.
yRow in pixels.
onTrue sets the pixel, false clears it.

◆ storage_delete

int32_t(* OperatorApi::storage_delete) (const char *path)

Delete a file under a scoped path.

Parameters
pathRelative path under the mode's storage area.
Returns
0 on success, -1 on error, or kStorageBusy while the device is busy with flash.

◆ storage_enumerate

int32_t(* OperatorApi::storage_enumerate) (const char *pattern, char *out, uint32_t out_size)

List the mode's stored files into out as NUL-separated names.

Parameters
patternExtension filter (for example ".scl"), or empty for all files.
outDestination buffer for the packed name list. The list is clipped to fit.
out_sizeSize of out.
Returns
The number of entries listed, -1 on error, or kStorageBusy while the device is busy with flash.

◆ storage_file_close

int32_t(* OperatorApi::storage_file_close) (int32_t handle)

Close an open handle.

This is not idempotent: closing an already closed handle returns -1.

Parameters
handleA handle from storage_file_open.
Returns
0 on success, or -1 on an invalid handle.

◆ storage_file_open

int32_t(* OperatorApi::storage_file_open) (const char *path)

Open a handle for streaming reads under a scoped path.

The handle stays valid across process() calls until it is closed or the mode is destroyed (which auto-closes it).

Parameters
pathRelative path under the mode's storage area.
Returns
A non-negative handle on success, or -1 on error.

◆ storage_file_open_write

int32_t(* OperatorApi::storage_file_open_write) (const char *path, uint8_t open_mode)

Open a handle for streaming writes under a scoped path.

The handle stays valid across process() calls until it is closed or the mode is destroyed (which auto-closes it).

Parameters
pathRelative path under the mode's storage area.
open_modekStorageOpenTruncate creates or overwrites from empty, kStorageOpenOverwrite overwrites in place from offset 0.
Returns
A non-negative handle on success, -1 on error, or kStorageBusy while the device is busy with flash.

◆ storage_file_read

int32_t(* OperatorApi::storage_file_read) (int32_t handle, uint8_t *buf, uint32_t size)

Read up to size bytes from an open handle.

Parameters
handleA handle from storage_file_open.
bufDestination buffer.
sizeMaximum bytes to read.
Returns
Bytes read (may be less than size near the end of file), 0 at end of file, or -1 on error.

◆ storage_file_seek

int32_t(* OperatorApi::storage_file_seek) (int32_t handle, uint32_t offset)

Move an open handle's read cursor.

Seeking past the end of the file is allowed, and later reads return 0.

Parameters
handleA handle from storage_file_open.
offsetNew absolute read offset.
Returns
0 on success, or -1 on error.

◆ storage_file_write

int32_t(* OperatorApi::storage_file_write) (int32_t handle, const uint8_t *buf, uint32_t size)

Write size bytes from buf to an open write handle.

Parameters
handleA handle from storage_file_open_write.
bufSource bytes.
sizeNumber of bytes to write.
Returns
Bytes written, -1 on error, kStorageBusy while the device is busy with flash, or kStorageNoSpace when the store is full.

◆ storage_read

int32_t(* OperatorApi::storage_read) (const char *path, uint8_t *buf, uint32_t size)

Read up to size bytes from a scoped path into buf.

Parameters
pathRelative path under the mode's storage area.
bufDestination buffer.
sizeMaximum bytes to read.
Returns
Bytes read, or a negative error code.

The documentation for this struct was generated from the following file: