2 stable releases

1.1.0 Mar 3, 2024
1.0.0 Mar 3, 2024

#2773 in Rust patterns


Used in mist

MIT/Apache

88KB
2K SLoC

mist-pdk

Crates.io docs.rs

This is a crate used to simplify mist plugin development in rust. All you have to do is implement the trait MistPlugin for your custom struct type, and call the generate_plugin! macro to generate the boilerplate for you.

Plugin development

To create a plugin, create a new crate with cargo new --lib, and in Cargo.toml, set the crate type to cdylib.

[lib]
crate-type = ["cdylib"]

Then add mist-pdk as a dependency.

[dependencies]
mist-pdk = "1.0"

Writing the plugin is as simple as creating a struct to hold any state you might need between updates, and implementing MistPlugin for this struct. The init function is used to instantiate your struct, and is the only one that does not provide a default implementation because of this. The update function will be called each frame (about every 1/60 second) during the lifetime of your plugin, and gives you a RunUpdate from which you can determine the current status of the timer. If your plugin will control mist operation, you can return a StateChangeRequest from update to request that the timer change state. The default implementation of update simply returns StateChangeRequest::None. Finally, you can use the shutdown function to deinitialize anything from your plugin that you need to. By default, it does nothing.

Once you have implemented the plugin, you can call generate_plugin! passing in the name of your plugin struct, and the rest will be handled automatically.

Plugin lifecycle

A mist plugin is a (platform-specific) dynamic library that is loaded at runtime by the main mist application. Each time the user opens a new split file in mist (i.e. on program start and any times beyond that where a new file is loaded), the plugin is reloaded. On load, mist checks the version of the pdk that the plugin was compiled with by calling the version function from the plugin, which returns a u16 with upper 8 bits for major version and lower 8 for the minor version. This function is automatically generated by generate_plugin. This version check is done to ensure that mist's idea of the plugin's function signatures matches with the actual plugin's functions.

Then, the init function from the plugin is called once, passing in a reference to the newly opened run. The responsibility of the init function is to initialize any state that the plugin needs, and instantiate the plugin struct itself. Each frame after this (except for time while dialog boxes are open), the update function from the plugin will be called with a reference to the RunUpdate generated on that frame. The update function can then return a StateChangeRequest to mist, which will request the timer to either make a change, or be ignored in the case of StateChangeRequest::None.

When the split file is closed (i.e. on timer exit or when the user decides to open a new split file), mist calls the shutdown function from the plugin once. After this, the plugin will be unloaded and memory will be freed.

Dependencies

~230–690KB
~16K SLoC