Skip to content

Plugin Development Guide

Lurmog edited this page Oct 18, 2025 · 1 revision

🧩 Andromeda Plugin Development Guide

Plugin directory:
/assets/plugins/

Want to create your own plugin for Andromeda? You’re in the right place!


🧠 Prerequisites

Before starting, make sure you:

  • Have at least basic knowledge of Lua scripting.


🚀 Starter Plugin Template

If you’re unsure how a plugin is structured, here’s a minimal working example:

local P = {}

-- Required fields P.plugin_name = "My plugin" P.plugin_type = "manipulate"

-- Optional fields P.dialog_fields = {} P.plugin_info = { author = "me", description = "This is an example plugin." }

function on_apply(notes) print("Hello, Andromeda!") end

P.on_apply = on_apply return P

💡 Tip: You can use this template as a base for your custom plugins.


⚙️ Plugin Fields Reference

P.plugin_name : string

  • Required.

  • The display name shown in the menu bar and dialog window title.

P.plugin_type : string

  • Required.

  • Defines the plugin category.

  • Must be one of:

    • "manipulate"

    • "generate"

P.plugin_info : table

  • Optional.

  • Describes the plugin in more detail.

    P.plugin_info = {
        author = "me",
        description = "Adds sparkle to your MIDI data."
    }
    

P.dialog_fields : table

  • Optional.

  • Defines UI input fields for your plugin.

  • If undefined or empty, the plugin runs immediately when selected.


🧱 P.dialog_fields Structure

The dialog_fields table lets you define interactive UI elements.
Each entry must be a table describing one field.

Below are all supported field types:


🏷️ Label

Used to display static text.

{
    type = "label",
    label = "Hello world!"
}

🔢 Number

Used for numeric input, with optional range constraints.
Each number field must have a unique name.

nolimit_number = {
    type = "number",
    label = "Number with no limits",
    value = 47
},

minmax_number = { type = "number", label = "Min/max range example", value = 1, range = { min = -10, max = 10 } },


🎚️ Slider

Similar to a number field, but uses a graphical slider.

slider_number = {
    type = "slider",
    label = "A slider!",
    value = 0.0,
    step = 0.1, -- optional
    range = {   -- optional
        min = -10, -- defaults to 0
        max = 10   -- defaults to 1
    }
},

📝 Text Edit

Allows users to input or edit text.

textfield = {
    type = "textedit",
    label = "Enter some text here",
    value = "blah blah blah"
},

✅ Toggle

A simple checkbox.

toggleable = {
    type = "toggle",
    label = "Enable feature",
    value = true
},

⬇️ Dropdown

A dropdown selector with labeled options.

dropdown_thing = {
    type = "dropdown",
    label = "A dropdown",
    value = 0, -- zero-based index of the current option
    value_labels = { -- required, must have at least one
        "Option A",
        "Option B",
        "Option C"
    }
}

─ Separator

Separators are simply empty tables — used to visually space elements.

{}

🧰 The andromeda Object

The global andromeda object provides helper functions, mainly for playback-related plugins.

Function Description
andromeda:ticks_to_secs(ticks) Converts MIDI ticks → seconds (from tick 0).
andromeda:secs_to_ticks(secs) Converts seconds → MIDI ticks (from time 0).
andromeda:get_ppq() Returns the project’s PPQ value.
andromeda:get_playhead_tick_pos() Returns the playhead position in ticks.
andromeda:get_playhead_secs_pos() Returns the playhead position in seconds.

🧩 Summary

  • Plugins live in: /assets/plugins/

  • Required fields: plugin_name, plugin_type, and on_apply

  • Optional fields: plugin_info, dialog_fields

  • Dialog fields build the plugin’s UI dynamically

  • Use the andromeda object for timing and playback utilities