SSkilltecabyclaudinhocode
Enviar skill
← Voltar para o catálogo

roneat-plugin-dev

Desenvolvimento

Expert guide for creating plugins for Roneat Studio Pro — a professional Roneat Ek (Cambodian xylophone) score editor. Use when the user asks to build, write, scaffold, or debug a plugin for Roneat Studio Pro. Covers plugin structure, the roneat_api Python API (score editing, audio playback, UI injection, theme/language control), plugin.json manifests, lifecycle hooks, sandboxing/permissions, pack

1estrelas
Ver no GitHub ↗Autor: Vagabond404

Roneat Studio Pro — Plugin Development

Plugin Architecture Overview

Plugins are isolated Python packages dropped into the app's plugins/ directory. The host app scans that folder on startup, validates plugin.json, dynamically loads the Python entry point, and routes lifecycle events via hooks.

The sandbox restricts os, shutil, subprocess, socket, urllib, requests, and http unless the matching permission is declared in plugin.json.

Plugin install path: %APPDATA%\RoneatStudioPro\plugins\ (runtime) or <project_root>/plugins/ (dev).


Plugin Structure

my-plugin/
├── plugin.json       # Manifest (required)
├── __init__.py       # Entry point (required)
└── assets/           # Optional: icons, data files

Distribute as my-plugin.zip — the zip must contain the folder (e.g. my-plugin/plugin.json).


plugin.json — Manifest Reference

{
  "id":          "my-plugin",
  "name":        "My Plugin",
  "version":     "1.0.0",
  "author":      "Your Name",
  "description": "Brief description of what this plugin does.",
  "entry_point": "__init__.py",
  "permissions": [],
  "dependencies": [],
  "hooks": {
    "on_load":       "on_load",
    "on_app_start":  "on_app_start",
    "on_unload":     "on_unload"
  }
}

Required fields: id, name, version, author, entry_point.

For all fields and optional hooks (on_project_save, on_project_open), see references/manifest.md.


roneat_api — Python API

Import the injected virtual package at the top of your entry point. Do not install it via pip — it is injected at runtime by the host app.

import roneat_api.score   as score
import roneat_api.audio   as audio
import roneat_api.ui      as ui
import roneat_api.project as project
import roneat_api.core    as core

Key namespaces at a glance

NamespacePurpose
roneat_api.scoreRead/write the musical score text
roneat_api.audioPlay notes/frequencies, stop playback
roneat_api.uiInject tabs, buttons, dialogs, toasts; control theme/language
roneat_api.projectGet project data, trigger save/load
roneat_api.coreRead app settings

For the full API reference with signatures and examples, see references/api.md.


Lifecycle Hooks

Hooks are Python functions in your entry point. Map them in plugin.json under "hooks".

HookWhen it fires
on_loadPlugin module loaded (app may not have UI yet)
on_app_startApp window fully built; use this to inject UI
on_unloadPlugin disabled/uninstalled
on_project_saveUser saves a project — receives data dict
on_project_openUser opens a project — receives data dict
# __init__.py — minimal lifecycle skeleton
import roneat_api.ui as ui

def on_load():
    pass  # Module is ready; avoid UI calls here

def on_app_start():
    ui.show_toast("My Plugin loaded!", level="info")

def on_unload():
    pass  # Cleanup if needed

Injecting UI

All UI injection must happen inside on_app_start.

Add a Custom Tab

import customtkinter as ctk
import roneat_api.ui as ui

class MyTab(ctk.CTkFrame):
    def __init__(self, master, **kwargs):
        super().__init__(master, **kwargs)
        ctk.CTkLabel(self, text="Hello from my plugin!").pack(pady=20)

def on_app_start():
    ui.add_custom_tab(
        tab_id="my_tab",
        label="My Tab",
        icon="🎵",
        widget_class=MyTab
    )

Open a Custom Window

def open_window():
    win = ui.create_window("My Tool", width=500, height=400)
    # win is a ctk.CTkToplevel; add widgets normally

Show Feedback

ui.show_toast("Done!", level="info")           # Bottom toast
ui.show_dialog("Error", "Something failed", dialog_type="error")

Permissions Reference

Declare only the permissions your plugin actually uses:

PermissionUnlocks
"file_system"os, shutil, pathlib, io
"network"socket, urllib, requests, http
"system"Implied by file_system; covers subprocess
"permissions": ["file_system"]

Packaging & Installation

  1. Zip the plugin folder (not its contents directly):
    my-plugin/
    ├── plugin.json
    └── __init__.py
    → my-plugin.zip
    
  2. Open Roneat Studio Pro → Plugins tab → Install Plugin.
  3. Select my-plugin.zip. The plugin appears in the list immediately.
  4. Enable/Disable/Reload/Uninstall from the same tab.

Full Example: Score Transpose Plugin

See references/example_transpose.md for a complete, annotated, production-quality plugin that reads the score, transposes all notes up by N steps, and re-writes the score — with a custom tab UI.


Common Pitfalls

  • UI in on_load → Crashes. Always use on_app_start for UI.
  • Importing restricted modules without permissionsImportError with a security warning; plugin auto-disabled.
  • Long-running tasks in hooks → Use threading.Thread(daemon=True) to avoid freezing the UI.
  • Assuming roneat_api is installable → It is not a PyPI package. It is injected by the host at runtime only.
  • Missing required manifest fields → Plugin silently fails to load.

Como adicionar

/plugin marketplace add Vagabond404/Roneat-Studio-Pro-Plugin-Creator

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Comentários · Nenhum comentário

Entre para comentar. Entrar

  • Ainda não há comentários. Seja o primeiro.