Plugins
Plugins
Starting with version 0.8.0
, the first draft of creating custom plugins were introduced.
They are meant as a way for developers to add extra functionality to PianoRhythm. Each plugin is instantiated
in its own iframe sandbox with access to a limited API to the client's internal PianoRhythm.
As of 5/1/2023, this plugin architecture is still in a initial draft state so it's still experimental.
Plugins are currently not synced and uploaded to your account in the cloud.
They are only stored locally on the client. You can actually find the raw objects
in the IndexedDB: plugin-management -> plugins
.
Creating Plugins
To get started with creating your first plugin, you'll see it under the Plugins
menu in the settings modal.
Once you click on the Create New Plugin
button, a modal will pop up with different tabs to edit code
, html
, and the css
of the plugin. The code
section displays a typescript code editor while the other tabs are in similar fashion.
Every plugin must have a Main
class. As noted in the screenshot, in the constructor of the class is an object model that is injected.
It represents an API with certain access to the PianoRhythm client. With it, you'll have certain methods like sending note data to the
audio engine, fetching data like the current users and/or rooms, and more.
For example, if you wanted to trigger a note on event, you can do:
class Main {
/** The core plugin app. */
#app: IPianoRhythmPluginApp;
constructor(app: IPianoRhythmPluginApp) {
this.#app = app;
}
onStart() {
console.log("Plugin Started");
//Signature: noteOn(channel: number, key: number, velocity: number): void
this.#app.noteOn(0, 60, 127);
}
...
Any chat messages emitted by your plugin will be tagged with PLUGIN
to let other users be able to
differentiate you and your plugin.
Plugins that emit chat messages or notes will be disabled in public lobbies in the near feature.
Editor
The editor is pretty basic so don't expect any fancy tooling like proper intellisense. There's a basic autocompletion for the API that is injected but that's about it. However, there are some autogenerated type docs for the API and associated types: IPianoRhythmPluginAPI
The autocompletion for the API is currently tied to the variable name app
. Changing the variable name
will inactivate the autocompletion.
HTML Tab
The html section allows you to create and describe the structure of your plugin.
CSS Tab
The css section allows you to describe the presentation of your plugin. Because of the nature of the iframe and css, manipulating the position and dimensions of your plugin could be tricky. I still need to research to find a better format. In the mean time, there are methods you can run with the api to edit the position and dimensions of your plugin:
...
onStart() {
console.log("Plugin Started");
//signature: setContainerPosition(x: string | number, y: string | number): void { }
this.#app.setContainerPosition(400, 400);
//signature: setContainerDimensions(width: string | number, height: string | number): void { }
this.#app.setContainerDimensions(100, 100);
}
...
Meta Tab
As of now, plugins are only processed locally on your client. In the future, there'll be a plugin store where you
can share and publish your plugin for other users to use. It'll go through a verification process and must be approved
before it others can download it. The Meta
tab will allow you to add more meta description about your plugin.
Lifecycles
There are also certain life cycle and other hooks implemented. The primary ones being onStart
and onStop
.
Those two methods are called when the plugin is initialized and stopped, respectively.
The other hooks such as onChatMessageAddedEvent
are automatically called within the app.
Hopefully the name of the methods are self explanatory. If not, then experiment with the code to see what happens!
Compilation
When you are ready to test your plugin, just click on the compilation
button.
If they are no syntax issues or missing requirements, then it should succesfully compile.
Then from there, you can press execute
to load and run the plugin into PianoRhythm.
If any runtime errors occur, then you can check the console logs in the browser's dev tools (ctrl + shift + i). Otherwise, you'll see a list of your plugins that were loaded succesfully:
Post Load
For loaded plugins, you can simply click on the UI element to trigger a menu that will allow you to edit
, unload
, or remove
the plugin.
The edit
button will retrigger the modal for the code editors.
The unload
button will stop the plugin and put it into an inactive
state. Once unloaded, you can reload it and it'll be put in an active
state.
The remove
button will stop the plugin and remove it from the list.
Types
You can find the associated types here: