#![doc(html_root_url = "https://docs.rs/reaper-macros/0.1.0")]
use darling::FromMeta;
use proc_macro::TokenStream;
use quote::quote;
#[proc_macro_attribute]
pub fn reaper_extension_plugin(attr: TokenStream, input: TokenStream) -> TokenStream {
let args = syn::parse_macro_input!(attr as syn::AttributeArgs);
let args = match ReaperExtensionPluginMacroArgs::from_list(&args) {
Ok(v) => v,
Err(e) => {
return e.write_errors().into();
}
};
let main_function = syn::parse_macro_input!(input as syn::ItemFn);
match main_function.sig.inputs.len() {
0 => {
generate_high_level_plugin_code(args, main_function)
}
1 => {
generate_low_level_plugin_code(main_function)
}
_ => panic!("REAPER extension plugin function must have "),
}
}
fn generate_low_level_plugin_code(main_function: syn::ItemFn) -> TokenStream {
let main_function_name = &main_function.sig.ident;
let tokens = quote! {
#[no_mangle]
extern "C" fn ReaperPluginEntry(h_instance: ::reaper_low::raw::HINSTANCE, rec: *mut ::reaper_low::raw::reaper_plugin_info_t) -> ::std::os::raw::c_int {
::reaper_low::bootstrap_extension_plugin(h_instance, rec, #main_function_name)
}
#main_function
};
tokens.into()
}
fn generate_high_level_plugin_code(
args: ReaperExtensionPluginMacroArgs,
main_function: syn::ItemFn,
) -> TokenStream {
let email_address = args
.email_address
.expect("E-mail address for error reports missing");
let main_function_name = &main_function.sig.ident;
let tokens = quote! {
#[::reaper_macros::reaper_extension_plugin]
fn low_level_plugin_main(context: &::reaper_low::ReaperPluginContext) -> Result<(), Box<dyn std::error::Error>> {
::reaper_high::Reaper::setup_with_defaults(context, #email_address);
#main_function_name()
}
#main_function
};
tokens.into()
}
#[derive(Default, Debug, FromMeta)]
#[darling(default)]
struct ReaperExtensionPluginMacroArgs {
email_address: Option<String>,
}
#[cfg(doctest)]
doc_comment::doctest!("../../../README.md");