Skip to main content

Crate nobble_addon_sdk

Crate nobble_addon_sdk 

Source
Expand description

Write a Nobble addon.

An addon is whatever knows how to make another application do something — skip a track, switch an OBS scene, start a Fusion 360 command. You implement Addon, hand it to run, and the daemon does the rest.

use nobble_addon_sdk::{Addon, AddonAction, AddonError, Availability, Invocation, Trigger, run};

struct Hello;

const ACTIONS: &[AddonAction] = &[AddonAction {
    id: "wave",
    name: "Wave",
    description: "Says hello.",
    trigger: Trigger::Momentary,
    params: &[],
    // Everything this action does not need. Finishing a declaration with
    // `..BASE` is how a later field costs you nothing.
    ..AddonAction::BASE
}];

impl Addon for Hello {
    fn id(&self) -> &'static str { "hello" }
    fn name(&self) -> &'static str { "Hello" }
    fn description(&self) -> &'static str { "An addon that waves." }
    fn actions(&self) -> &'static [AddonAction] { ACTIONS }
    fn availability(&self) -> Availability { Availability::Ready }
    fn perform(&mut self, action: &str, _i: &Invocation<'_>) -> Result<(), AddonError> {
        match action {
            "wave" => Ok(()),
            other => Err(AddonError::NoSuchAction(other.to_owned())),
        }
    }
}

fn main() { run(Hello); }

§Why this is a separate process

ADR-0016. An addon runs as a child of the daemon and speaks the protocol in protocol over its stdin and stdout. That is what makes FR-045 true — a crash, a hang or a leak in your addon cannot reach input, MIDI, or anybody else’s addon — and it is what lets Credentials be scoped to you rather than handed out as a key to everyone’s.

You do not write any of that. run owns the loop and the framing; you write the trait.

§What is deliberately not here

No device, input, layout or module types. An addon contributes actions, signals, settings and configuration UI (FR-047) and has no business knowing what an InputId is. If you find yourself needing one, that is a gap in this SDK to be reported rather than routed around — FR-050 says official addons get no private interfaces either, so the gap is real for everyone.

Modules§

protocol
What crosses the pipe between the daemon and an addon.

Structs§

AddonAction
One thing an addon can be asked to do.
AddonChoice
One option a user can pick.
AddonChoices
A named list of options an addon offers, which a parameter can draw from.
AddonParam
One thing an action needs to know, declared so an interface can ask for it.
AddonSetting
One thing an addon needs configuring once, rather than per key.
AddonSignal
A named boolean fact an addon publishes about its target.
Choice
One option from a live source.
DeviceAction
One thing an addon names and the device does, with no addon running.
Invocation
What an action was given when it ran.

Enums§

AddonError
Why performing an action failed.
Availability
Whether an addon can act at the moment.
DeviceKeystroke
One keystroke, exactly as the device will send it.
ParamKind
What a parameter holds, so an interface can offer the right editor.
ParamValue
What one parameter holds: a value, or several.
Permission
Something an addon needs to be allowed to do (FR-046).
Reading
What an addon’s signals read at one moment.
Trigger
What kind of input an action expects.

Constants§

FADER_MAX
Full scale for a 14-bit fader value.

Traits§

Addon
Something that can act on another application’s behalf.
Credentials
Where an addon keeps its own credentials (ADR-0013, FR-046).
Store
Somewhere to remember things that are not secrets (ADR-0027).

Functions§

app_matches
Whether something the platform named is the application a binding meant.
run
Serve an addon on stdin and stdout, until told to stop.

Type Aliases§

CredentialHandle
A shared Credentials, because an addon needs it after configuration too.
StoreHandle
A shared Store, for the same reason CredentialHandle is shared.