From db5affbbf58a1281c34525cc4909b7260c944aee Mon Sep 17 00:00:00 2001 From: Ales Tsurko Date: Fri, 22 May 2020 16:55:05 +0300 Subject: [PATCH] Decouple from cxx crate (#97) - rename ffi::Message into FlMessage - restructure lib.rs --- Cargo.toml | 3 +- build.rs | 5 +- src/cxx/wrapper.cpp | 43 +-- src/cxx/wrapper.h | 37 ++- src/host.rs | 65 ++-- src/lib.rs | 699 +++++++++++++++++++++--------------------- src/plugin.rs | 42 +-- src/plugin/message.rs | 242 +++++++-------- src/voice.rs | 41 ++- 9 files changed, 574 insertions(+), 603 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ed700d1..aad3b77 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,12 +8,11 @@ edition = "2018" [dependencies] bitflags = "1.2" -cxx = "0.2" hresult = "0.0.1" log = "0.4" [build-dependencies] -cxx = "0.2" +cc = { version = "1.0", features = ["parallel"] } [dev-dependencies] bincode = "1.2" diff --git a/build.rs b/build.rs index ecb45a3..8a7ef55 100644 --- a/build.rs +++ b/build.rs @@ -1,13 +1,12 @@ fn main() { - cxx::Build::new() - .bridge("src/lib.rs") + cc::Build::new() .include("src/cxx") .file("src/cxx/fp_plugclass.cpp") .file("src/cxx/wrapper.cpp") + .cpp(true) .flag("-std=c++11") .compile("fpsdk"); - println!("cargo:rerun-if-changed=src/lib.rs"); println!("cargo:rerun-if-changed=src/cxx/fp_plugclass.h"); println!("cargo:rerun-if-changed=src/cxx/wrapper.h"); println!("cargo:rerun-if-changed=src/cxx/wrapper.cpp"); diff --git a/src/cxx/wrapper.cpp b/src/cxx/wrapper.cpp index 5a9fb7c..e877d8b 100644 --- a/src/cxx/wrapper.cpp +++ b/src/cxx/wrapper.cpp @@ -1,7 +1,8 @@ #include "wrapper.h" #include "fp_plugclass.h" -#include "src/lib.rs.h" +#include <_types/_uint8_t.h> #include +#include intptr_t init_p_notes_params(int target, int flags, int ch_num, int pat_num, TNoteParams *notes, int len) { @@ -18,13 +19,6 @@ intptr_t init_p_notes_params(int target, int flags, int ch_num, int pat_num, return (intptr_t)params; } -TimeSignature time_sig_from_raw(intptr_t raw_time_sig) { - PTimeSigInfo time_sig = (TTimeSigInfo *)raw_time_sig; - - return {(uint32_t)time_sig->StepsPerBar, (uint32_t)time_sig->StepsPerBeat, - (uint32_t)time_sig->PPQ}; -} - char *alloc_real_cstr(char *rust_cstr) { char *result = (char *)malloc(strlen(rust_cstr) + 1); strcpy(result, rust_cstr); @@ -67,11 +61,6 @@ void *create_plug_instance_c(void *host, intptr_t tag, void *adapter) { free_rbox_raw(info); - int ver = ((TFruityPlugHost *)host)->HostVersion; - std::string sver = std::to_string(ver); - fplog(rust::Str(sver.c_str())); - fplog(rust::Str("host version above")); - PluginWrapper *wrapper = new PluginWrapper( (TFruityPlugHost *)host, tag, (PluginAdapter *)adapter, c_info); @@ -109,14 +98,14 @@ intptr_t _stdcall PluginWrapper::Dispatcher(intptr_t id, intptr_t index, // host->Dispatcher(HostTag, FHD_WantMIDIInput, 0, value); // } - Message message = {id, index, value}; + FlMessage message = {id, index, value}; return plugin_dispatcher(adapter, message); } void _stdcall PluginWrapper::GetName(int section, int index, int value, char *name) { - Message message = { + FlMessage message = { (intptr_t)section, (intptr_t)index, (intptr_t)value, @@ -129,7 +118,7 @@ void _stdcall PluginWrapper::GetName(int section, int index, int value, int _stdcall PluginWrapper::ProcessEvent(int event_id, int event_value, int flags) { - Message message = { + FlMessage message = { (intptr_t)event_id, (intptr_t)event_value, (intptr_t)flags, @@ -141,7 +130,7 @@ int _stdcall PluginWrapper::ProcessEvent(int event_id, int event_value, } int _stdcall PluginWrapper::ProcessParam(int index, int value, int rec_flags) { - Message message = { + FlMessage message = { (intptr_t)index, (intptr_t)value, (intptr_t)rec_flags, @@ -194,7 +183,7 @@ void _stdcall PluginWrapper::Voice_Kill(TVoiceHandle handle) { int _stdcall PluginWrapper::Voice_ProcessEvent(TVoiceHandle handle, int event_id, int event_value, int flags) { - Message message = { + FlMessage message = { (intptr_t)event_id, (intptr_t)event_value, (intptr_t)flags, @@ -213,15 +202,7 @@ void _stdcall PluginWrapper::NewTick() { plugin_tick(adapter); } void _stdcall PluginWrapper::MIDITick() { plugin_midi_tick(adapter); } -void _stdcall PluginWrapper::MIDIIn(int &msg) { - MidiMessage message = { - (uint8_t)(msg & 0xff), - (uint8_t)((msg >> 8) & 0xff), - (uint8_t)((msg >> 16) & 0xff), - (int)((msg >> 24) & 0xff), - }; - plugin_midi_in(adapter, message); -} +void _stdcall PluginWrapper::MIDIIn(int &msg) { plugin_midi_in(adapter, msg); } void _stdcall PluginWrapper::MsgIn(intptr_t msg) { plugin_loop_in(adapter, msg); @@ -231,7 +212,7 @@ int _stdcall PluginWrapper::OutputVoice_ProcessEvent(TOutVoiceHandle handle, int event_id, int event_value, int flags) { - Message message = { + FlMessage message = { (intptr_t)event_id, (intptr_t)event_value, (intptr_t)flags, @@ -245,7 +226,7 @@ void _stdcall PluginWrapper::OutputVoice_Kill(TVoiceHandle handle) { } // host -intptr_t host_on_message(void *host, TPluginTag tag, Message message) { +intptr_t host_on_message(void *host, TPluginTag tag, FlMessage message) { return ((TFruityPlugHost *)host) ->Dispatcher(tag, message.id, message.index, message.value); } @@ -353,7 +334,7 @@ bool prompt_show(void *host, int x, int y, char *msg, char *result, // Host voice-related -intptr_t host_on_voice_event(void *host, intptr_t tag, Message message) { +intptr_t host_on_voice_event(void *host, intptr_t tag, FlMessage message) { return ((TFruityPlugHost *)host) ->Voice_ProcessEvent((TOutVoiceHandle)tag, message.id, message.index, message.value); @@ -381,7 +362,7 @@ void host_kill_out_voice(void *host, intptr_t tag) { ((TFruityPlugHost *)host)->OutputVoice_Kill((TOutVoiceHandle)tag); } -intptr_t host_on_out_voice_event(void *host, intptr_t tag, Message message) { +intptr_t host_on_out_voice_event(void *host, intptr_t tag, FlMessage message) { return ((TFruityPlugHost *)host) ->OutputVoice_ProcessEvent((TOutVoiceHandle)tag, message.id, message.index, message.value); diff --git a/src/cxx/wrapper.h b/src/cxx/wrapper.h index 4435ec4..78abd69 100644 --- a/src/cxx/wrapper.h +++ b/src/cxx/wrapper.h @@ -1,12 +1,14 @@ #pragma once #include "fp_plugclass.h" -#include "rust/cxx.h" -struct Message; -struct MidiMessage; struct PluginAdapter; -struct TimeSignature; + +struct FlMessage { + intptr_t id; + intptr_t index; + intptr_t value; +}; // from plugin.rs struct Info { @@ -74,18 +76,20 @@ class PluginWrapper : public TFruityPlug { PluginAdapter *adapter; }; -TimeSignature time_sig_from_raw(intptr_t raw_time_sig); - // Unsafe Rust FFI // // PluginAdapter methods extern "C" void *create_plug_instance_c(void *host, intptr_t tag, void *adapter); extern "C" Info *plugin_info(PluginAdapter *adapter); -extern "C" intptr_t plugin_dispatcher(PluginAdapter *adapter, Message message); -extern "C" intptr_t plugin_process_event(PluginAdapter *adapter, Message event); -extern "C" intptr_t plugin_process_param(PluginAdapter *adapter, Message event); -extern "C" char *plugin_name_of(const PluginAdapter *adapter, Message message); +extern "C" intptr_t plugin_dispatcher(PluginAdapter *adapter, + FlMessage message); +extern "C" intptr_t plugin_process_event(PluginAdapter *adapter, + FlMessage event); +extern "C" intptr_t plugin_process_param(PluginAdapter *adapter, + FlMessage event); +extern "C" char *plugin_name_of(const PluginAdapter *adapter, + FlMessage message); extern "C" void plugin_idle(PluginAdapter *adapter); extern "C" void plugin_tick(PluginAdapter *adapter); extern "C" void plugin_midi_tick(PluginAdapter *adapter); @@ -94,7 +98,7 @@ extern "C" void plugin_eff_render(PluginAdapter *adapter, int len); extern "C" void plugin_gen_render(PluginAdapter *adapter, float dest[1][2], int len); -extern "C" void plugin_midi_in(PluginAdapter *adapter, MidiMessage message); +extern "C" void plugin_midi_in(PluginAdapter *adapter, int &message); extern "C" void plugin_save_state(PluginAdapter *adapter, IStream *istream); extern "C" void plugin_load_state(PluginAdapter *adapter, IStream *istream); extern "C" void plugin_loop_in(PluginAdapter *adapter, intptr_t message); @@ -105,10 +109,10 @@ extern "C" intptr_t voice_handler_trigger(PluginAdapter *adapter, Params params, extern "C" void voice_handler_release(PluginAdapter *adapter, void *voice); extern "C" void voice_handler_kill(PluginAdapter *adapter, void *voice); extern "C" intptr_t voice_handler_on_event(PluginAdapter *adapter, void *voice, - Message message); + FlMessage message); extern "C" void out_voice_handler_kill(PluginAdapter *adapter, intptr_t tag); extern "C" intptr_t out_voice_handler_on_event(PluginAdapter *adapter, - intptr_t tag, Message message); + intptr_t tag, FlMessage message); // IStream extern "C" int32_t istream_read(void *istream, uint8_t *data, uint32_t size, @@ -118,7 +122,7 @@ extern "C" int32_t istream_write(void *istream, const uint8_t *data, // Host extern "C" intptr_t host_on_message(void *host, TPluginTag tag, - Message message); + FlMessage message); extern "C" void host_on_parameter(void *host, TPluginTag tag, int index, int value); extern "C" void host_on_controller(void *host, TPluginTag tag, intptr_t index, @@ -154,15 +158,16 @@ extern "C" bool prompt_show(void *host, int x, int y, char *msg, char *result, extern "C" void host_release_voice(void *host, intptr_t tag); extern "C" void host_kill_voice(void *host, intptr_t tag); extern "C" intptr_t host_on_voice_event(void *host, intptr_t tag, - Message message); + FlMessage message); extern "C" intptr_t host_trig_out_voice(void *host, Params *params, int32_t index, intptr_t tag); extern "C" void host_release_out_voice(void *host, intptr_t tag); extern "C" void host_kill_out_voice(void *host, intptr_t tag); extern "C" intptr_t host_on_out_voice_event(void *host, intptr_t tag, - Message message); + FlMessage message); // Utility +extern "C" void fplog(const char *msg); extern "C" intptr_t init_p_notes_params(int target, int flags, int ch_num, int pat_num, TNoteParams *notes, int len); diff --git a/src/host.rs b/src/host.rs index c595690..3bfc020 100644 --- a/src/host.rs +++ b/src/host.rs @@ -13,8 +13,8 @@ use log::trace; use crate::plugin::{self, message}; use crate::voice::{self, SendVoiceHandler, Voice}; use crate::{ - ffi, intptr_t, AsRawPtr, FromRawPtr, MidiMessage, ProcessModeFlags, TimeSignature, Transport, - ValuePtr, WAVETABLE_SIZE, + intptr_t, AsRawPtr, FlMessage, FromRawPtr, MidiMessage, ProcessModeFlags, TTimeSigInfo, + TimeSignature, Transport, ValuePtr, WAVETABLE_SIZE, }; /// Plugin host. @@ -40,7 +40,7 @@ impl Host { // Get the version of FL Studio. It is stored in one integer. If the version of FL Studio // would be 1.2.3 for example, `version` would be 1002003 // pub fn version(&self) -> i32 { - // todo!() + // todo!() // } /// Send message to host. @@ -98,8 +98,8 @@ impl Host { /// about can be linked to a MIDI controller. /// - `"^b"` - informs the user that the parameter is recordable. /// - `"^c"` - shows a little smiley. No real use, just for fun. - /// - `"^d"` - shows a mouse with the right button clicked, to denote a control that has a popup - /// menu. + /// - `"^d"` - shows a mouse with the right button clicked, to denote a control that has a + /// popup menu. /// - `"^e"` - shows an unhappy smiley, to use when something went wrong. /// - `"^f"` - shows a left-pointing arrow /// - `"^g"` - shows a double right-pointing arrow, for fast forward @@ -311,6 +311,7 @@ impl Host { } } +#[no_mangle] extern "C" { fn host_on_parameter(host: *mut c_void, tag: intptr_t, index: c_int, value: c_int); fn host_on_controller(host: *mut c_void, tag: intptr_t, index: intptr_t, value: intptr_t); @@ -421,16 +422,17 @@ impl SendVoiceHandler for Voicer { /// Tell the host that some event has happened concerning the specified voice. fn on_event(&mut self, tag: voice::Tag, event: voice::Event) -> Option { - Option::::from(event).map(|value| { + Option::::from(event).map(|value| { ValuePtr(unsafe { host_on_voice_event(*self.host_ptr.get_mut(), tag.0, value) }) }) } } +#[no_mangle] extern "C" { fn host_release_voice(host: *mut c_void, tag: intptr_t); fn host_kill_voice(host: *mut c_void, tag: intptr_t); - fn host_on_voice_event(host: *mut c_void, tag: intptr_t, message: ffi::Message) -> intptr_t; + fn host_on_voice_event(host: *mut c_void, tag: intptr_t, message: FlMessage) -> intptr_t; } /// Use this for operations with output voices (i.e. for VFX inside [patcher]( @@ -497,7 +499,7 @@ impl SendVoiceHandler for OutVoicer { trace!("send event {:?} for out voice {:?}", event, tag); let host_ptr = *self.host_ptr.get_mut(); self.voices.get_mut(&tag).and_then(|voice| { - Option::::from(event).map(|message| { + Option::::from(event).map(|message| { ValuePtr(unsafe { host_on_out_voice_event(host_ptr, voice.inner_tag().0, message) }) }) }) @@ -550,8 +552,7 @@ extern "C" { ) -> intptr_t; fn host_release_out_voice(host: *mut c_void, tag: intptr_t); fn host_kill_out_voice(host: *mut c_void, tag: intptr_t); - fn host_on_out_voice_event(host: *mut c_void, tag: intptr_t, message: ffi::Message) - -> intptr_t; + fn host_on_out_voice_event(host: *mut c_void, tag: intptr_t, message: FlMessage) -> intptr_t; } /// Message from the host to the plugin @@ -715,8 +716,8 @@ pub enum Message<'a> { Unknown, } -impl From for Message<'_> { - fn from(message: ffi::Message) -> Self { +impl From for Message<'_> { + fn from(message: FlMessage) -> Self { trace!("host::Message::from {:?}", message); let result = match message.id { @@ -733,7 +734,7 @@ impl From for Message<'_> { 11 => Message::SetEnabled(message.value != 0), 12 => Message::SetPlaying(message.value != 0), 13 => Message::SongPosChanged, - 14 => Message::SetTimeSig(ffi::time_sig_from_raw(message.value)), + 14 => Message::SetTimeSig(TTimeSigInfo::from_raw_ptr(message.value).into()), 15 => Message::CollectFile(message.index as usize), 16 => Message::SetInternalParam, 17 => Message::SetNumSends(message.value as u64), @@ -743,7 +744,7 @@ impl From for Message<'_> { 21 => Message::SetIdleTime(message.value as u64), 22 => Message::SetFocus(message.value != 0), 23 => Message::Transport(message.into()), - 24 => Message::MidiIn((message.value as u64).into()), + 24 => Message::MidiIn((message.value as c_int).into()), 25 => Message::RoutingChanged, 26 => Message::GetParamInfo(message.index as usize), 27 => Message::ProjLoaded, @@ -761,7 +762,7 @@ impl From for Message<'_> { } impl Message<'_> { - fn from_show_editor(message: ffi::Message) -> Self { + fn from_show_editor(message: FlMessage) -> Self { if message.value == 1 { Message::ShowEditor(None) } else { @@ -769,12 +770,12 @@ impl Message<'_> { } } - fn from_process_mode(message: ffi::Message) -> Self { + fn from_process_mode(message: FlMessage) -> Self { let flags = ProcessModeFlags::from_bits_truncate(message.value); Message::ProcessMode(flags) } - fn from_chan_sample_changed(message: ffi::Message) -> Self { + fn from_chan_sample_changed(message: FlMessage) -> Self { let slice = unsafe { std::slice::from_raw_parts_mut(message.value as *mut f32, WAVETABLE_SIZE) }; Message::ChanSampleChanged(slice) @@ -835,8 +836,8 @@ pub enum GetName { Unknown, } -impl From for GetName { - fn from(message: ffi::Message) -> Self { +impl From for GetName { + fn from(message: FlMessage) -> Self { trace!("GetName::from {:?}", message); let result = match message.id { @@ -859,55 +860,55 @@ impl From for GetName { } } -impl From for Option { +impl From for Option { fn from(value: GetName) -> Self { match value { - GetName::Param(index) => Some(ffi::Message { + GetName::Param(index) => Some(FlMessage { id: 0, index: index.as_raw_ptr(), value: 0, }), - GetName::ParamValue(index, value) => Some(ffi::Message { + GetName::ParamValue(index, value) => Some(FlMessage { id: 1, index: index.as_raw_ptr(), value, }), - GetName::Semitone(index, value) => Some(ffi::Message { + GetName::Semitone(index, value) => Some(FlMessage { id: 2, index: index.as_raw_ptr(), value: value.as_raw_ptr(), }), - GetName::Patch(index) => Some(ffi::Message { + GetName::Patch(index) => Some(FlMessage { id: 3, index: index.as_raw_ptr(), value: 0, }), - GetName::VoiceLevel(index) => Some(ffi::Message { + GetName::VoiceLevel(index) => Some(FlMessage { id: 4, index: index.as_raw_ptr(), value: 0, }), - GetName::VoiceLevelHint(index) => Some(ffi::Message { + GetName::VoiceLevelHint(index) => Some(FlMessage { id: 5, index: index.as_raw_ptr(), value: 0, }), - GetName::Preset(index) => Some(ffi::Message { + GetName::Preset(index) => Some(FlMessage { id: 6, index: index.as_raw_ptr(), value: 0, }), - GetName::OutCtrl(index) => Some(ffi::Message { + GetName::OutCtrl(index) => Some(FlMessage { id: 7, index: index.as_raw_ptr(), value: 0, }), - GetName::VoiceColor(index) => Some(ffi::Message { + GetName::VoiceColor(index) => Some(FlMessage { id: 8, index: index.as_raw_ptr(), value: 0, }), - GetName::OutVoice(index) => Some(ffi::Message { + GetName::OutVoice(index) => Some(FlMessage { id: 9, index: index.as_raw_ptr(), value: 0, @@ -952,8 +953,8 @@ pub enum Event { Unknown, } -impl From for Event { - fn from(message: ffi::Message) -> Self { +impl From for Event { + fn from(message: FlMessage) -> Self { trace!("Event::from {:?}", message); let result = match message.id { diff --git a/src/lib.rs b/src/lib.rs index 88418ff..fbf9f05 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -48,65 +48,17 @@ unreachable_pub )] -/// Used internally for C++ <-> Rust interoperability. Shouldn't be used directly. -#[doc(hidden)] -#[cxx::bridge] -pub mod ffi { - /// Time signature. - pub struct TimeSignature { - /// Steps per bar. - pub steps_per_bar: u32, - /// Steps per beat. - pub steps_per_beat: u32, - /// Pulses per quarter note. - pub ppq: u32, - } - - /// MIDI message. - pub struct MidiMessage { - pub status: u8, - pub data1: u8, - pub data2: u8, - pub port: u8, - } - - #[derive(Clone)] - pub struct Message { - pub id: isize, - pub index: isize, - pub value: isize, - } - - extern "C" { - include!("wrapper.h"); - - pub fn time_sig_from_raw(raw_time_sig: isize) -> TimeSignature; - } - - extern "Rust" { - type PluginAdapter; - - fn fplog(message: &str); - // Used for debugging - fn print_adapter(adapter: &PluginAdapter); - } -} - pub mod host; pub mod plugin; pub mod voice; use std::ffi::{CStr, CString}; -use std::fmt; use std::mem; use std::os::raw::{c_char, c_int, c_void}; use bitflags::bitflags; use log::{debug, error}; -pub use ffi::{MidiMessage, TimeSignature}; -use plugin::PluginAdapter; - /// Current FL SDK version. pub const CURRENT_SDK_VERSION: u32 = 1; @@ -142,49 +94,12 @@ macro_rules! implement_tag { }; } -fn fplog(message: &str) { - debug!("{}", message); -} - -fn print_adapter(adapter: &PluginAdapter) { - debug!("{:?}", adapter); -} - -/// FFI to free rust's Box::into_raw pointer. -/// -/// It supposed to be used internally. Don't use it. -/// -/// # Safety -/// -/// Unsafe -#[doc(hidden)] -#[no_mangle] -pub unsafe extern "C" fn free_rbox_raw(raw_ptr: *mut c_void) { - let _ = Box::from_raw(raw_ptr); -} - -/// FFI to free rust's CString pointer. -/// -/// It supposed to be used internally. Don't use it. -/// -/// # Safety -/// -/// Unsafe -#[doc(hidden)] -#[no_mangle] -pub unsafe extern "C" fn free_rstring(raw_str: *mut c_char) { - let _ = CString::from_raw(raw_str); -} - -/// FFI to make C string (`char *`) managed by C side. Because `char *` produced by -/// `CString::into_raw` leads to memory leak: -/// -/// > The pointer which this function returns must be returned to Rust and reconstituted using -/// > from_raw to be properly deallocated. Specifically, one should not use the standard C free() -/// > function to deallocate this string. -#[no_mangle] -extern "C" { - fn alloc_real_cstr(raw_str: *mut c_char) -> *mut c_char; +#[derive(Debug, Clone)] +#[repr(C)] +struct FlMessage { + id: intptr_t, + index: intptr_t, + value: intptr_t, } /// For types, which can be represented as `intptr_t`. @@ -244,6 +159,17 @@ impl AsRawPtr for String { } } +/// FFI to make C string (`char *`) managed by C side. Because `char *` produced by +/// `CString::into_raw` leads to memory leak: +/// +/// > The pointer which this function returns must be returned to Rust and reconstituted using +/// > from_raw to be properly deallocated. Specifically, one should not use the standard C free() +/// > function to deallocate this string. +#[no_mangle] +extern "C" { + fn alloc_real_cstr(raw_str: *mut c_char) -> *mut c_char; +} + /// For conversion from `intptr_t`. pub trait FromRawPtr { /// Conversion method. @@ -318,6 +244,310 @@ impl FromRawPtr for ValuePtr { } } +/// Time signature. +#[derive(Debug, Clone)] +pub struct TimeSignature { + /// Steps per bar. + pub steps_per_bar: u32, + /// Steps per beat. + pub steps_per_beat: u32, + /// Pulses per quarter note. + pub ppq: u32, +} + +impl From for TimeSignature { + fn from(value: TTimeSigInfo) -> Self { + Self { + steps_per_bar: value.steps_per_bar as u32, + steps_per_beat: value.steps_per_beat as u32, + ppq: value.ppq as u32, + } + } +} + +#[repr(C)] +struct TTimeSigInfo { + steps_per_bar: c_int, + steps_per_beat: c_int, + ppq: c_int, +} + +impl FromRawPtr for TTimeSigInfo { + fn from_raw_ptr(raw_ptr: intptr_t) -> Self { + let sig_ptr = raw_ptr as *mut c_void as *mut TTimeSigInfo; + unsafe { + Self { + steps_per_beat: (*sig_ptr).steps_per_beat, + steps_per_bar: (*sig_ptr).steps_per_bar, + ppq: (*sig_ptr).ppq, + } + } + } +} + +/// Time format. +#[derive(Debug)] +pub enum TimeFormat { + /// Beats. + Beats, + /// Absolute ms. + AbsoluteMs, + /// Running ms. + RunningMs, + /// Time since sound card restart (in ms). + RestartMs, +} + +impl From for u8 { + fn from(format: TimeFormat) -> Self { + match format { + TimeFormat::Beats => 0, + TimeFormat::AbsoluteMs => 1, + TimeFormat::RunningMs => 2, + TimeFormat::RestartMs => 3, + } + } +} + +/// Time +/// +/// The first value is mixing time. +/// +/// The second value is offset in samples. +#[derive(Debug, Default)] +#[repr(C)] +pub struct Time(pub f64, pub f64); + +impl FromRawPtr for Time { + fn from_raw_ptr(value: intptr_t) -> Self { + unsafe { *Box::from_raw(value as *mut c_void as *mut Time) } + } +} + +/// Song time in **bar:step:tick** format. +#[allow(missing_docs)] +#[derive(Clone, Debug, Default)] +#[repr(C)] +pub struct SongTime { + pub bar: i32, + pub step: i32, + pub tick: i32, +} + +impl FromRawPtr for SongTime { + fn from_raw_ptr(value: intptr_t) -> Self { + unsafe { *Box::from_raw(value as *mut c_void as *mut Self) } + } +} + +/// Name of the color (or MIDI channel) in Piano Roll. +#[derive(Debug)] +pub struct NameColor { + /// User-defined name (can be empty). + pub name: String, + /// Visible name (can be guessed). + pub vis_name: String, + /// Color/MIDI channel index. + pub color: u8, + /// Real index of the item (can be used to translate plugin's own in/out into real mixer track + /// number). + pub index: usize, +} + +/// Type used in FFI for [`NameColor`](struct.NameColor.html). +#[repr(C)] +pub struct TNameColor { + name: [u8; 256], + vis_name: [u8; 256], + color: c_int, + index: c_int, +} + +impl From for NameColor { + fn from(name_color: TNameColor) -> Self { + Self { + name: String::from_utf8_lossy(&name_color.name[..]).to_string(), + vis_name: String::from_utf8_lossy(&name_color.vis_name[..]).to_string(), + color: name_color.color as u8, + index: name_color.index as usize, + } + } +} + +impl From for TNameColor { + fn from(name_color: NameColor) -> Self { + let mut name = [0_u8; 256]; + name.copy_from_slice(name_color.name.as_bytes()); + let mut vis_name = [0_u8; 256]; + vis_name.copy_from_slice(name_color.vis_name.as_bytes()); + Self { + name, + vis_name, + color: name_color.color as c_int, + index: name_color.index as c_int, + } + } +} + +impl FromRawPtr for TNameColor { + fn from_raw_ptr(value: intptr_t) -> Self { + unsafe { *Box::from_raw(value as *mut Self) } + } +} + +/// MIDI message. +#[derive(Debug)] +pub struct MidiMessage { + /// Status byte. + pub status: u8, + /// First data byte. + pub data1: u8, + /// Second data byte. + pub data2: u8, + /// Port number. + pub port: u8, +} + +impl From<&mut c_int> for MidiMessage { + fn from(value: &mut c_int) -> Self { + Self { + status: (*value & 0xff) as u8, + data1: ((*value >> 8) & 0xff) as u8, + data2: ((*value >> 16) & 0xff) as u8, + port: ((*value >> 24) & 0xff) as u8, + } + } +} + +impl From for MidiMessage { + fn from(value: c_int) -> Self { + Self { + status: (value & 0xff) as u8, + data1: ((value >> 8) & 0xff) as u8, + data2: ((value >> 16) & 0xff) as u8, + port: ((value >> 24) & 0xff) as u8, + } + } +} + +/// Collection of notes, which you can add to the piano roll using +/// [`Host::on_message`](host/struct.Host.html#on_message.new) with message +/// [`plugin::Message::AddToPianoRoll`](../plugin/enum.Message.html#variant.AddToPianoRoll). +#[derive(Debug)] +pub struct Notes { + // 0=step seq (not supported yet), 1=piano roll + //target: i32, + /// Notes. + pub notes: Vec, + /// See [`NotesFlags`](struct.NotesFlags.html). + pub flags: NotesFlags, + /// Pattern number. `None` for current. + pub pattern: Option, + /// Channel number. `None` for plugin's channel, or selected channel if plugin is an effect. + pub channel: Option, +} + +/// This type represents a note in [`Notes`](struct.Notes.html). +#[derive(Debug)] +#[repr(C)] +pub struct Note { + /// Position in PPQ. + pub position: i32, + /// Length in PPQ. + pub length: i32, + /// Pan in range -100..100. + pub pan: i32, + /// Volume. + pub vol: i32, + /// Note number. + pub note: i16, + /// Color or MIDI channel in range of 0..15. + pub color: i16, + /// Fine pitch in range -1200..1200. + pub pitch: i32, + /// Mod X or filter cutoff frequency. + pub mod_x: f32, + /// Mod Y or filter resonance (Q). + pub mod_y: f32, +} + +bitflags! { + /// Notes parameters flags + pub struct NotesFlags: isize { + /// Delete everything currently on the piano roll before adding the notes. + const EMPTY_FIRST = 1; + /// Put the new notes in the piano roll selection, if there is one. + const USE_SELECTION = 2; + } +} + +// This type in FL SDK is what we represent as Notes. Here we use it for FFI, to send it to C++. +#[repr(C)] +struct TNotesParams { + target: c_int, + flags: c_int, + pat_num: c_int, + chan_num: c_int, + count: c_int, + notes: *mut Note, +} + +impl From for TNotesParams { + fn from(mut notes: Notes) -> Self { + notes.notes.shrink_to_fit(); + let notes_ptr = notes.notes.as_mut_ptr(); + let len = notes.notes.len(); + mem::forget(notes.notes); + + Self { + target: 1, + flags: notes.flags.bits() as c_int, + pat_num: notes.pattern.map(|v| v as c_int).unwrap_or(-1), + chan_num: notes.channel.map(|v| v as c_int).unwrap_or(-1), + count: len as c_int, + notes: notes_ptr, + } + } +} + +/// Describes an item that should be added to a control's right-click popup menu. +#[derive(Debug)] +pub struct ParamMenuEntry { + /// Name. + pub name: String, + /// Flags. + pub flags: ParamMenuItemFlags, +} + +bitflags! { + /// Parameter popup menu item flags + pub struct ParamMenuItemFlags: i32 { + /// The item is disabled + const DISABLED = 1; + /// The item is checked + const CHECKED = 2; + } +} + +impl ParamMenuEntry { + fn from_ffi(ffi_t: *mut TParamMenuEntry) -> Self { + Self { + name: unsafe { CString::from_raw((*ffi_t).name) } + .to_string_lossy() + .to_string(), + flags: ParamMenuItemFlags::from_bits(unsafe { (*ffi_t).flags }) + .unwrap_or_else(ParamMenuItemFlags::empty), + } + } +} + +#[derive(Debug)] +#[repr(C)] +struct TParamMenuEntry { + name: *mut c_char, + flags: c_int, +} + bitflags! { /// Parameter flags. pub struct ParameterFlags: isize { @@ -508,8 +738,8 @@ pub enum Transport { Unknown, } -impl From for Transport { - fn from(message: ffi::Message) -> Self { +impl From for Transport { + fn from(message: FlMessage) -> Self { match message.index { 0 => Transport::Jog(Jog(message.value as i64)), 1 => Transport::Jog2(Jog(message.value as i64)), @@ -589,140 +819,6 @@ pub struct Hold(pub bool); #[derive(Debug)] pub struct Jog(pub i64); -/// Song time in **bar:step:tick** format. -#[allow(missing_docs)] -#[derive(Clone, Debug, Default)] -#[repr(C)] -pub struct SongTime { - pub bar: i32, - pub step: i32, - pub tick: i32, -} - -impl FromRawPtr for SongTime { - fn from_raw_ptr(value: intptr_t) -> Self { - unsafe { *Box::from_raw(value as *mut c_void as *mut Self) } - } -} - -/// Collection of notes, which you can add to the piano roll using -/// [`Host::on_message`](host/struct.Host.html#on_message.new) with message -/// [`plugin::Message::AddToPianoRoll`](../plugin/enum.Message.html#variant.AddToPianoRoll). -#[derive(Debug)] -pub struct Notes { - // 0=step seq (not supported yet), 1=piano roll - //target: i32, - /// Notes. - pub notes: Vec, - /// See [`NotesFlags`](struct.NotesFlags.html). - pub flags: NotesFlags, - /// Pattern number. `None` for current. - pub pattern: Option, - /// Channel number. `None` for plugin's channel, or selected channel if plugin is an effect. - pub channel: Option, -} - -/// This type represents a note in [`Notes`](struct.Notes.html). -#[derive(Debug)] -#[repr(C)] -pub struct Note { - /// Position in PPQ. - pub position: i32, - /// Length in PPQ. - pub length: i32, - /// Pan in range -100..100. - pub pan: i32, - /// Volume. - pub vol: i32, - /// Note number. - pub note: i16, - /// Color or MIDI channel in range of 0..15. - pub color: i16, - /// Fine pitch in range -1200..1200. - pub pitch: i32, - /// Mod X or filter cutoff frequency. - pub mod_x: f32, - /// Mod Y or filter resonance (Q). - pub mod_y: f32, -} - -bitflags! { - /// Notes parameters flags - pub struct NotesFlags: isize { - /// Delete everything currently on the piano roll before adding the notes. - const EMPTY_FIRST = 1; - /// Put the new notes in the piano roll selection, if there is one. - const USE_SELECTION = 2; - } -} - -// This type in FL SDK is what we represent as Notes. Here we use it for FFI, to send it to C++. -#[repr(C)] -struct TNotesParams { - target: c_int, - flags: c_int, - pat_num: c_int, - chan_num: c_int, - count: c_int, - notes: *mut Note, -} - -impl From for TNotesParams { - fn from(mut notes: Notes) -> Self { - notes.notes.shrink_to_fit(); - let notes_ptr = notes.notes.as_mut_ptr(); - let len = notes.notes.len(); - mem::forget(notes.notes); - - Self { - target: 1, - flags: notes.flags.bits() as c_int, - pat_num: notes.pattern.map(|v| v as c_int).unwrap_or(-1), - chan_num: notes.channel.map(|v| v as c_int).unwrap_or(-1), - count: len as c_int, - notes: notes_ptr, - } - } -} - -/// Describes an item that should be added to a control's right-click popup menu. -#[derive(Debug)] -pub struct ParamMenuEntry { - /// Name. - pub name: String, - /// Flags. - pub flags: ParamMenuItemFlags, -} - -bitflags! { - /// Parameter popup menu item flags - pub struct ParamMenuItemFlags: i32 { - /// The item is disabled - const DISABLED = 1; - /// The item is checked - const CHECKED = 2; - } -} - -impl ParamMenuEntry { - fn from_ffi(ffi_t: *mut TParamMenuEntry) -> Self { - Self { - name: unsafe { CString::from_raw((*ffi_t).name) } - .to_string_lossy() - .to_string(), - flags: ParamMenuItemFlags::from_bits(unsafe { (*ffi_t).flags }) - .unwrap_or_else(ParamMenuItemFlags::empty), - } - } -} - -#[derive(Debug)] -#[repr(C)] -struct TParamMenuEntry { - name: *mut c_char, - flags: c_int, -} - bitflags! { /// Message box flags (see /// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox). @@ -901,138 +997,31 @@ impl FromRawPtr for MessageBoxResult { } } -/// Time format. -#[derive(Debug)] -pub enum TimeFormat { - /// Beats. - Beats, - /// Absolute ms. - AbsoluteMs, - /// Running ms. - RunningMs, - /// Time since sound card restart (in ms). - RestartMs, -} - -impl From for u8 { - fn from(format: TimeFormat) -> Self { - match format { - TimeFormat::Beats => 0, - TimeFormat::AbsoluteMs => 1, - TimeFormat::RunningMs => 2, - TimeFormat::RestartMs => 3, - } - } +#[no_mangle] +unsafe extern "C" fn fplog(message: *const c_char) { + debug!("{}", CStr::from_ptr(message).to_string_lossy()); } -/// Time +/// FFI to free rust's Box::into_raw pointer. /// -/// The first value is mixing time. +/// It supposed to be used internally. Don't use it. /// -/// The second value is offset in samples. -#[derive(Debug, Default)] -#[repr(C)] -pub struct Time(pub f64, pub f64); - -impl FromRawPtr for Time { - fn from_raw_ptr(value: intptr_t) -> Self { - unsafe { *Box::from_raw(value as *mut c_void as *mut Time) } - } -} - -/// Name of the color (or MIDI channel) in Piano Roll. -#[derive(Debug)] -pub struct NameColor { - /// User-defined name (can be empty). - pub name: String, - /// Visible name (can be guessed). - pub vis_name: String, - /// Color/MIDI channel index. - pub color: u8, - /// Real index of the item (can be used to translate plugin's own in/out into real mixer track - /// number). - pub index: usize, -} - -/// Type used in FFI for [`NameColor`](struct.NameColor.html). -#[repr(C)] -pub struct TNameColor { - name: [u8; 256], - vis_name: [u8; 256], - color: c_int, - index: c_int, -} - -impl FromRawPtr for TNameColor { - fn from_raw_ptr(value: intptr_t) -> Self { - unsafe { *Box::from_raw(value as *mut Self) } - } -} - -impl From for NameColor { - fn from(name_color: TNameColor) -> Self { - Self { - name: String::from_utf8_lossy(&name_color.name[..]).to_string(), - vis_name: String::from_utf8_lossy(&name_color.vis_name[..]).to_string(), - color: name_color.color as u8, - index: name_color.index as usize, - } - } -} - -impl From for TNameColor { - fn from(name_color: NameColor) -> Self { - let mut name = [0_u8; 256]; - name.copy_from_slice(name_color.name.as_bytes()); - let mut vis_name = [0_u8; 256]; - vis_name.copy_from_slice(name_color.vis_name.as_bytes()); - Self { - name, - vis_name, - color: name_color.color as c_int, - index: name_color.index as c_int, - } - } -} - -impl From for MidiMessage { - fn from(value: u64) -> Self { - MidiMessage { - status: (value & 0xff) as u8, - data1: ((value >> 8) & 0xff) as u8, - data2: ((value >> 16) & 0xff) as u8, - port: 0, - } - } -} - -impl fmt::Debug for MidiMessage { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("MidiMessage") - .field("status", &self.status) - .field("data1", &self.data1) - .field("data2", &self.data2) - .field("port", &self.port) - .finish() - } -} - -impl fmt::Debug for TimeSignature { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("TimeSignature") - .field("steps_per_bar", &self.steps_per_bar) - .field("steps_per_beat", &self.steps_per_beat) - .field("ppq", &self.ppq) - .finish() - } +/// # Safety +/// +/// Unsafe +#[no_mangle] +unsafe extern "C" fn free_rbox_raw(raw_ptr: *mut c_void) { + let _ = Box::from_raw(raw_ptr); } -impl fmt::Debug for ffi::Message { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("Message") - .field("id", &self.id) - .field("index", &self.index) - .field("value", &self.value) - .finish() - } +/// FFI to free rust's CString pointer. +/// +/// It supposed to be used internally. Don't use it. +/// +/// # Safety +/// +/// Unsafe +#[no_mangle] +unsafe extern "C" fn free_rstring(raw_str: *mut c_char) { + let _ = CString::from_raw(raw_str); } diff --git a/src/plugin.rs b/src/plugin.rs index 5b4c9f4..08fd783 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -4,7 +4,7 @@ pub mod message; use std::ffi::CString; use std::io::{self, Read, Write}; -use std::os::raw::{c_char, c_void}; +use std::os::raw::{c_char, c_int, c_void}; use std::panic::RefUnwindSafe; use hresult::HRESULT; @@ -13,7 +13,7 @@ use log::{debug, error}; use crate::host::{self, Event, GetName, Host}; use crate::voice::ReceiveVoiceHandler; use crate::{ - alloc_real_cstr, ffi, intptr_t, AsRawPtr, MidiMessage, ProcessParamFlags, ValuePtr, + alloc_real_cstr, FlMessage, intptr_t, AsRawPtr, MidiMessage, ProcessParamFlags, ValuePtr, CURRENT_SDK_VERSION, }; @@ -450,7 +450,7 @@ pub struct PluginAdapter(pub Box); /// Unsafe #[doc(hidden)] #[no_mangle] -pub unsafe extern "C" fn plugin_info(adapter: *mut PluginAdapter) -> *mut Info { +unsafe extern "C" fn plugin_info(adapter: *mut PluginAdapter) -> *mut Info { Box::into_raw(Box::new((*adapter).0.info())) } @@ -463,9 +463,9 @@ pub unsafe extern "C" fn plugin_info(adapter: *mut PluginAdapter) -> *mut Info { /// Unsafe #[doc(hidden)] #[no_mangle] -pub unsafe extern "C" fn plugin_dispatcher( +unsafe extern "C" fn plugin_dispatcher( adapter: *mut PluginAdapter, - message: ffi::Message, + message: FlMessage, ) -> intptr_t { (*adapter).0.on_message(message.into()).as_raw_ptr() } @@ -479,9 +479,9 @@ pub unsafe extern "C" fn plugin_dispatcher( /// Unsafe #[doc(hidden)] #[no_mangle] -pub unsafe extern "C" fn plugin_name_of( +unsafe extern "C" fn plugin_name_of( adapter: *const PluginAdapter, - message: ffi::Message, + message: FlMessage, ) -> *mut c_char { let name = CString::new((*adapter).0.name_of(message.into())).unwrap_or_else(|e| { error!("{}", e); @@ -499,9 +499,9 @@ pub unsafe extern "C" fn plugin_name_of( /// Unsafe #[doc(hidden)] #[no_mangle] -pub unsafe extern "C" fn plugin_process_event( +unsafe extern "C" fn plugin_process_event( adapter: *mut PluginAdapter, - event: ffi::Message, + event: FlMessage, ) -> intptr_t { (*adapter).0.process_event(event.into()); 0 @@ -516,9 +516,9 @@ pub unsafe extern "C" fn plugin_process_event( /// Unsafe #[doc(hidden)] #[no_mangle] -pub unsafe extern "C" fn plugin_process_param( +unsafe extern "C" fn plugin_process_param( adapter: *mut PluginAdapter, - message: ffi::Message, + message: FlMessage, ) -> intptr_t { (*adapter) .0 @@ -539,7 +539,7 @@ pub unsafe extern "C" fn plugin_process_param( /// Unsafe #[doc(hidden)] #[no_mangle] -pub unsafe extern "C" fn plugin_idle(adapter: *mut PluginAdapter) { +unsafe extern "C" fn plugin_idle(adapter: *mut PluginAdapter) { (*adapter).0.idle(); } @@ -552,7 +552,7 @@ pub unsafe extern "C" fn plugin_idle(adapter: *mut PluginAdapter) { /// Unsafe #[doc(hidden)] #[no_mangle] -pub unsafe extern "C" fn plugin_tick(adapter: *mut PluginAdapter) { +unsafe extern "C" fn plugin_tick(adapter: *mut PluginAdapter) { (*adapter).0.tick(); } @@ -565,7 +565,7 @@ pub unsafe extern "C" fn plugin_tick(adapter: *mut PluginAdapter) { /// Unsafe #[doc(hidden)] #[no_mangle] -pub unsafe extern "C" fn plugin_midi_tick(adapter: *mut PluginAdapter) { +unsafe extern "C" fn plugin_midi_tick(adapter: *mut PluginAdapter) { (*adapter).0.midi_tick(); } @@ -578,7 +578,7 @@ pub unsafe extern "C" fn plugin_midi_tick(adapter: *mut PluginAdapter) { /// Unsafe #[doc(hidden)] #[no_mangle] -pub unsafe extern "C" fn plugin_eff_render( +unsafe extern "C" fn plugin_eff_render( adapter: *mut PluginAdapter, source: *const [f32; 2], dest: *mut [f32; 2], @@ -598,7 +598,7 @@ pub unsafe extern "C" fn plugin_eff_render( /// Unsafe #[doc(hidden)] #[no_mangle] -pub unsafe extern "C" fn plugin_gen_render( +unsafe extern "C" fn plugin_gen_render( adapter: *mut PluginAdapter, dest: *mut [f32; 2], length: i32, @@ -616,8 +616,8 @@ pub unsafe extern "C" fn plugin_gen_render( /// Unsafe #[doc(hidden)] #[no_mangle] -pub unsafe extern "C" fn plugin_midi_in(adapter: *mut PluginAdapter, message: MidiMessage) { - (*adapter).0.midi_in(message); +unsafe extern "C" fn plugin_midi_in(adapter: *mut PluginAdapter, message: &mut c_int) { + (*adapter).0.midi_in(message.into()); } /// [`Plugin::save_state`](trait.Plugin.html#tymethod.save_state) FFI. @@ -629,7 +629,7 @@ pub unsafe extern "C" fn plugin_midi_in(adapter: *mut PluginAdapter, message: Mi /// Unsafe #[doc(hidden)] #[no_mangle] -pub unsafe extern "C" fn plugin_save_state(adapter: *mut PluginAdapter, stream: *mut c_void) { +unsafe extern "C" fn plugin_save_state(adapter: *mut PluginAdapter, stream: *mut c_void) { (*adapter).0.save_state(StateWriter(stream)); } @@ -642,7 +642,7 @@ pub unsafe extern "C" fn plugin_save_state(adapter: *mut PluginAdapter, stream: /// Unsafe #[doc(hidden)] #[no_mangle] -pub unsafe extern "C" fn plugin_load_state(adapter: *mut PluginAdapter, stream: *mut c_void) { +unsafe extern "C" fn plugin_load_state(adapter: *mut PluginAdapter, stream: *mut c_void) { (*adapter).0.load_state(StateReader(stream)); } @@ -655,6 +655,6 @@ pub unsafe extern "C" fn plugin_load_state(adapter: *mut PluginAdapter, stream: /// Unsafe #[doc(hidden)] #[no_mangle] -pub unsafe extern "C" fn plugin_loop_in(adapter: *mut PluginAdapter, message: intptr_t) { +unsafe extern "C" fn plugin_loop_in(adapter: *mut PluginAdapter, message: intptr_t) { (*adapter).0.loop_in(ValuePtr(message)); } diff --git a/src/plugin/message.rs b/src/plugin/message.rs index 25c7fbb..da71b52 100644 --- a/src/plugin/message.rs +++ b/src/plugin/message.rs @@ -5,7 +5,7 @@ use std::os::raw::{c_int, c_void}; use crate::host::{GetName, Host}; use crate::plugin; use crate::{ - ffi, intptr_t, AsRawPtr, MessageBoxFlags, MessageBoxResult, NameColor, Note, Notes, + intptr_t, AsRawPtr, FlMessage, MessageBoxFlags, MessageBoxResult, NameColor, Note, Notes, ParamMenuEntry, SongTime, TNameColor, TParamMenuEntry, Tag, Time, TimeFormat, ValuePtr, }; @@ -47,7 +47,7 @@ macro_rules! impl_message_ty { } extern "C" { - fn host_on_message(host: *mut c_void, plugin_tag: Tag, message: ffi::Message) -> intptr_t; + fn host_on_message(host: *mut c_void, plugin_tag: Tag, message: FlMessage) -> intptr_t; } /// Tells the host that the user has clicked an item of the control popup menu. @@ -60,9 +60,9 @@ pub struct ParamMenu(pub usize, pub usize); impl_message!(ParamMenu); -impl From for ffi::Message { +impl From for FlMessage { fn from(message: ParamMenu) -> Self { - ffi::Message { + FlMessage { id: 0, index: message.0.as_raw_ptr(), value: message.1.as_raw_ptr(), @@ -76,9 +76,9 @@ pub struct EditorResized; impl_message!(EditorResized); -impl From for ffi::Message { +impl From for FlMessage { fn from(_message: EditorResized) -> Self { - ffi::Message { + FlMessage { id: 2, index: 0, value: 0, @@ -93,12 +93,12 @@ pub struct NamesChanged(pub GetName); impl_message!(NamesChanged); -impl From for ffi::Message { +impl From for FlMessage { fn from(message: NamesChanged) -> Self { - ffi::Message { + FlMessage { id: 3, index: 0, - value: Option::::from(message.0) + value: Option::::from(message.0) .map(|msg| msg.id) .unwrap_or_default(), } @@ -112,9 +112,9 @@ pub struct ActivateMidi; impl_message!(ActivateMidi); -impl From for ffi::Message { +impl From for FlMessage { fn from(_: ActivateMidi) -> Self { - ffi::Message { + FlMessage { id: 4, index: 0, value: 0, @@ -132,9 +132,9 @@ pub struct WantMidiInput(pub bool); impl_message!(WantMidiInput); -impl From for ffi::Message { +impl From for FlMessage { fn from(message: WantMidiInput) -> Self { - ffi::Message { + FlMessage { id: 5, index: 0, value: message.0.as_raw_ptr(), @@ -155,9 +155,9 @@ pub struct KillAutomation(pub usize, pub usize); impl_message!(KillAutomation); -impl From for ffi::Message { +impl From for FlMessage { fn from(message: KillAutomation) -> Self { - ffi::Message { + FlMessage { id: 8, index: message.0.as_raw_ptr(), value: message.1.as_raw_ptr(), @@ -174,9 +174,9 @@ pub struct SetNumPresets(pub usize); impl_message!(SetNumPresets); -impl From for ffi::Message { +impl From for FlMessage { fn from(message: SetNumPresets) -> Self { - ffi::Message { + FlMessage { id: 9, index: 0, value: message.0.as_raw_ptr(), @@ -192,9 +192,9 @@ pub struct SetNewName(pub String); impl_message!(SetNewName); -impl From for ffi::Message { +impl From for FlMessage { fn from(message: SetNewName) -> Self { - ffi::Message { + FlMessage { id: 10, index: 0, value: message.0.as_raw_ptr(), @@ -208,9 +208,9 @@ pub struct VstiIdle; impl_message!(VstiIdle); -impl From for ffi::Message { +impl From for FlMessage { fn from(_message: VstiIdle) -> Self { - ffi::Message { + FlMessage { id: 11, index: 0, value: 0, @@ -237,9 +237,9 @@ pub enum WantIdle { impl_message!(WantIdle); -impl From for ffi::Message { +impl From for FlMessage { fn from(message: WantIdle) -> Self { - ffi::Message { + FlMessage { id: 13, index: 0, value: message.into(), @@ -267,9 +267,9 @@ pub struct LocateDataFile(pub String); impl_message_ty!(LocateDataFile, String); -impl From for ffi::Message { +impl From for FlMessage { fn from(message: LocateDataFile) -> Self { - ffi::Message { + FlMessage { id: 14, index: 0, value: message.0.as_raw_ptr(), @@ -289,17 +289,17 @@ impl Message for TicksToTime { type Return = SongTime; fn send(self, tag: plugin::Tag, host: &mut Host) -> Self::Return { - let message = ffi::Message::from(self); + let message = FlMessage::from(self); let time_ptr = message.index; unsafe { host_on_message(*host.host_ptr.get_mut(), tag.0, message) }; ValuePtr(time_ptr).get::() } } -impl From for ffi::Message { +impl From for FlMessage { fn from(message: TicksToTime) -> Self { let time = SongTime::default(); - ffi::Message { + FlMessage { id: 16, index: (Box::into_raw(Box::new(time)) as *mut c_void).as_raw_ptr(), value: message.0.as_raw_ptr(), @@ -313,7 +313,7 @@ pub struct AddToPianoRoll(pub Notes); impl_message!(AddToPianoRoll); -impl From for ffi::Message { +impl From for FlMessage { fn from(mut message: AddToPianoRoll) -> Self { message.0.notes.shrink_to_fit(); let notes_ptr = message.0.notes.as_mut_ptr(); @@ -330,7 +330,7 @@ impl From for ffi::Message { ) }; - ffi::Message { + FlMessage { id: 17, index: 0, value: p_notes_params, @@ -368,7 +368,7 @@ impl Message for GetParamMenuEntry { type Return = Option; fn send(self, tag: plugin::Tag, host: &mut Host) -> Self::Return { - let message = ffi::Message::from(self); + let message = FlMessage::from(self); let result = unsafe { host_on_message(*host.host_ptr.get_mut(), tag.0, message) }; if (result as *mut c_void).is_null() { @@ -381,9 +381,9 @@ impl Message for GetParamMenuEntry { } } -impl From for ffi::Message { +impl From for FlMessage { fn from(message: GetParamMenuEntry) -> Self { - ffi::Message { + FlMessage { id: 18, index: message.0.as_raw_ptr(), value: message.1.as_raw_ptr(), @@ -405,9 +405,9 @@ pub struct MessageBox(pub String, pub String, pub MessageBoxFlags); impl_message_ty!(MessageBox, MessageBoxResult); -impl From for ffi::Message { +impl From for FlMessage { fn from(message: MessageBox) -> Self { - ffi::Message { + FlMessage { id: 19, index: format!("{}|{}", message.0, message.1).as_raw_ptr(), value: message.2.as_raw_ptr(), @@ -427,9 +427,9 @@ pub struct NoteOn(pub u8, pub u8, pub u8); impl_message!(NoteOn); -impl From for ffi::Message { +impl From for FlMessage { fn from(message: NoteOn) -> Self { - ffi::Message { + FlMessage { id: 20, index: dword_from_note_and_ch(message.0, message.1).as_raw_ptr(), value: message.2.as_raw_ptr(), @@ -445,9 +445,9 @@ pub struct NoteOff(pub u8); impl_message!(NoteOff); -impl From for ffi::Message { +impl From for FlMessage { fn from(message: NoteOff) -> Self { - ffi::Message { + FlMessage { id: 21, index: message.0.as_raw_ptr(), value: 0, @@ -464,9 +464,9 @@ pub struct OnHintDirect(pub String); impl_message!(OnHintDirect); -impl From for ffi::Message { +impl From for FlMessage { fn from(message: OnHintDirect) -> Self { - ffi::Message { + FlMessage { id: 22, index: 0, value: message.0.as_raw_ptr(), @@ -484,9 +484,9 @@ pub struct SetNewColor(pub u8); impl_message!(SetNewColor); -impl From for ffi::Message { +impl From for FlMessage { fn from(message: SetNewColor) -> Self { - ffi::Message { + FlMessage { id: 23, index: 0, value: message.0.as_raw_ptr(), @@ -499,9 +499,9 @@ impl From for ffi::Message { // #[derive(Debug)] // pub struct GetInstance; -// impl From for ffi::Message { +// impl From for FlMessage { // fn from(_: GetInstance) -> Self { -// ffi::Message { +// FlMessage { // id: 24, // index: 0, // value: 0, @@ -520,9 +520,9 @@ pub struct KillIntCtrl(pub usize, pub usize); impl_message!(KillIntCtrl); -impl From for ffi::Message { +impl From for FlMessage { fn from(message: KillIntCtrl) -> Self { - ffi::Message { + FlMessage { id: 25, index: message.0.as_raw_ptr(), value: message.1.as_raw_ptr(), @@ -539,9 +539,9 @@ pub struct SetNumParams(pub usize); impl_message!(SetNumParams); -impl From for ffi::Message { +impl From for FlMessage { fn from(message: SetNumParams) -> Self { - ffi::Message { + FlMessage { id: 27, index: 0, value: message.0.as_raw_ptr(), @@ -560,9 +560,9 @@ pub struct PackDataFile(pub String); impl_message_ty!(PackDataFile, String); -impl From for ffi::Message { +impl From for FlMessage { fn from(message: PackDataFile) -> Self { - ffi::Message { + FlMessage { id: 28, index: 0, value: message.0.as_raw_ptr(), @@ -579,9 +579,9 @@ pub struct GetProgPath; impl_message_ty!(GetProgPath, String); -impl From for ffi::Message { +impl From for FlMessage { fn from(_: GetProgPath) -> Self { - ffi::Message { + FlMessage { id: 29, index: 0, value: 0, @@ -597,9 +597,9 @@ pub struct SetLatency(pub u32); impl_message!(SetLatency); -impl From for ffi::Message { +impl From for FlMessage { fn from(message: SetLatency) -> Self { - ffi::Message { + FlMessage { id: 30, index: 0, value: message.0.as_raw_ptr(), @@ -613,9 +613,9 @@ pub struct CallDownloader; impl_message!(CallDownloader); -impl From for ffi::Message { +impl From for FlMessage { fn from(_: CallDownloader) -> Self { - ffi::Message { + FlMessage { id: 31, index: 0, value: 0, @@ -634,9 +634,9 @@ pub struct EditSample(pub String, pub bool); impl_message!(EditSample); -impl From for ffi::Message { +impl From for FlMessage { fn from(message: EditSample) -> Self { - ffi::Message { + FlMessage { id: 32, index: message.1.as_raw_ptr(), value: message.0.as_raw_ptr(), @@ -656,9 +656,9 @@ pub struct SetThreadSafe(pub bool); impl_message!(SetThreadSafe); -impl From for ffi::Message { +impl From for FlMessage { fn from(message: SetThreadSafe) -> Self { - ffi::Message { + FlMessage { id: 33, index: 0, value: message.0.as_raw_ptr(), @@ -675,9 +675,9 @@ pub struct SmartDisable(pub bool); impl_message!(SmartDisable); -impl From for ffi::Message { +impl From for FlMessage { fn from(message: SmartDisable) -> Self { - ffi::Message { + FlMessage { id: 34, index: 0, value: message.0.as_raw_ptr(), @@ -694,9 +694,9 @@ pub struct SetUid(pub String); impl_message!(SetUid); -impl From for ffi::Message { +impl From for FlMessage { fn from(message: SetUid) -> Self { - ffi::Message { + FlMessage { id: 35, index: 0, value: message.0.as_raw_ptr(), @@ -722,22 +722,22 @@ impl Message for GetMixingTime { } } -fn get_time_send>(msg: T, tag: plugin::Tag, host: &mut Host) -> Time { - let message: ffi::Message = msg.into(); +fn get_time_send>(msg: T, tag: plugin::Tag, host: &mut Host) -> Time { + let message: FlMessage = msg.into(); let time_ptr = message.value; unsafe { host_on_message(*host.host_ptr.get_mut(), tag.0, message) }; ValuePtr(time_ptr).get::