From 14cd6eda83004b9e89073758e310271916c86105 Mon Sep 17 00:00:00 2001 From: Michal Odnous Date: Tue, 23 Jan 2024 22:20:58 +0000 Subject: [PATCH] Use plugin struct methods instead of static methods. Now that this is fixed: https://github.com/vlang/v/pull/20630 --- CHANGELOG.md | 1 + src/plugin.v | 71 +++++++++++++++++++++++++++++----------------------- src/setup.v | 20 +++++++-------- 3 files changed, 51 insertions(+), 41 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 09dca73..5bfedd2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Changed * Plugin version is now source from V mod file. +* CLAP plugin functions are directly V plugin structs methods (closures). ## [0.1.2] - 2024-01-20 ### Changed diff --git a/src/plugin.v b/src/plugin.v index f3a52f3..fd7e320 100644 --- a/src/plugin.v +++ b/src/plugin.v @@ -2,6 +2,7 @@ import log // This should be the actual implementation of the plugin with // all the interesting logic like DSP, UI, etc. +@[heap] struct MinimalPlugin { host &C.clap_host_t mut: @@ -14,31 +15,30 @@ fn from_clap(clap_plugin &C.clap_plugin_t) &MinimalPlugin { return unsafe { &MinimalPlugin(clap_plugin.plugin_data) } } -fn MinimalPlugin.init(clap_plugin &C.clap_plugin_t) bool { +fn (mp MinimalPlugin) init(clap_plugin &C.clap_plugin_t) bool { return true } -fn MinimalPlugin.destroy(clap_plugin &C.clap_plugin_t) { +fn (mp MinimalPlugin) destroy(clap_plugin &C.clap_plugin_t) { // Cleanup plugin members here. } -fn MinimalPlugin.activate(clap_plugin &C.clap_plugin_t, sample_rate f64, min_frames_count u32, max_frames_count u32) bool { - mut p := from_clap(clap_plugin) - p.sample_rate = sample_rate +fn (mut mp MinimalPlugin) activate(clap_plugin &C.clap_plugin_t, sample_rate f64, min_frames_count u32, max_frames_count u32) bool { + mp.sample_rate = sample_rate return true } -fn MinimalPlugin.deactivate(clap_plugin &C.clap_plugin_t) { +fn (mp MinimalPlugin) deactivate(clap_plugin &C.clap_plugin_t) { } -fn MinimalPlugin.start_processing(clap_plugin &C.clap_plugin_t) bool { +fn (mp MinimalPlugin) start_processing(clap_plugin &C.clap_plugin_t) bool { return true } -fn MinimalPlugin.stop_processing(clap_plugin &C.clap_plugin_t) { +fn (mp MinimalPlugin) stop_processing(clap_plugin &C.clap_plugin_t) { } -fn MinimalPlugin.reset(clap_plugin &C.clap_plugin_t) { +fn (mp MinimalPlugin) reset(clap_plugin &C.clap_plugin_t) { // Cleanup plugin members here. } @@ -66,34 +66,38 @@ fn (mp MinimalPlugin) process_event(header &C.clap_event_header_t) { } } -fn MinimalPlugin.process(clap_plugin &C.clap_plugin_t, mut process C.clap_process_t) ClapProcessStatus { - p := from_clap(clap_plugin) +fn (mp MinimalPlugin) process(clap_plugin &C.clap_plugin_t, mut process C.clap_process_t) ClapProcessStatus { + frame_count := process.frames_count + event_count := process.in_events.size(process.in_events) - nframes := process.frames_count - nev := process.in_events.size(process.in_events) + mut event_index := u32(0) + mut next_frame := if event_count > 0 { 0 } else { frame_count } - mut ev_index := u32(0) - mut next_ev_frame := if nev > 0 { 0 } else { nframes } + for i := 0; i < frame_count; { + for event_index < event_count { + // Handle every event at frame i. + if next_frame != i { + break + } - for i := 0; i < nframes; { - for ev_index < nev && next_ev_frame == i { - header := process.in_events.get(process.in_events, ev_index) + header := process.in_events.get(process.in_events, event_index) if header.time != i { - next_ev_frame = header.time + next_frame = header.time break } - p.process_event(header) - ev_index++ + mp.process_event(header) + event_index++ - if ev_index == nev { - next_ev_frame = nframes + // Event list exhausted. + if event_index == event_count { + next_frame = frame_count break } } - for ; i < next_ev_frame; i++ { + for ; i < next_frame; i++ { // In general: // mut inputs := []C.clap_audio_buffer_t{cap: int(process.audio_inputs_count)} // for k := 0; k < process.audio_inputs_count; k++ { @@ -103,23 +107,26 @@ fn MinimalPlugin.process(clap_plugin &C.clap_plugin_t, mut process C.clap_proces input_right := unsafe { process.audio_inputs[0].data32[1][i] } // Swap left and right channels. - unsafe { process.audio_outputs[0].data32[0][i] = input_right } - unsafe { process.audio_outputs[0].data32[1][i] = input_left } + unsafe { + process.audio_outputs[0].data32[0][i] = input_right + } + unsafe { + process.audio_outputs[0].data32[1][i] = input_left + } } } return ClapProcessStatus.@continue } -fn MinimalPlugin.get_extension(clap_plugin &C.clap_plugin_t, id &char) voidptr { +fn (mp MinimalPlugin) get_extension(clap_plugin &C.clap_plugin_t, id &char) voidptr { v_id := unsafe { cstring_to_vstring(id) } match v_id { clap_ext_latency { return &C.clap_plugin_latency_t{ - get: fn (clap_plugin &C.clap_plugin_t) u32 { - p := from_clap(clap_plugin) - return p.latency + get: fn [mp] (clap_plugin &C.clap_plugin_t) u32 { + return mp.latency } } } @@ -162,11 +169,13 @@ fn MinimalPlugin.get_extension(clap_plugin &C.clap_plugin_t, id &char) voidptr { } info.id = 0 + // vfmt off info.supported_dialects = ( u32(ClapNoteDialect.clap) | u32(ClapNoteDialect.midi_mpe) | u32(ClapNoteDialect.midi2) ) + // vfmt on info.preferred_dialect = u32(ClapNoteDialect.clap) port_name := 'Example note port' @@ -185,5 +194,5 @@ fn MinimalPlugin.get_extension(clap_plugin &C.clap_plugin_t, id &char) voidptr { } } -fn MinimalPlugin.on_main_thread(clap_plugin &C.clap_plugin_t) { +fn (mp MinimalPlugin) on_main_thread(clap_plugin &C.clap_plugin_t) { } diff --git a/src/setup.v b/src/setup.v index 5c656a2..9fd3436 100644 --- a/src/setup.v +++ b/src/setup.v @@ -41,16 +41,16 @@ fn create_plugin(factory &C.clap_plugin_factory_t, host &C.clap_host_t, plugin_i desc: &_plugin_descriptor // It always carries a pointer to our custom structure. plugin_data: main_plugin - init: MinimalPlugin.init - destroy: MinimalPlugin.destroy - activate: MinimalPlugin.activate - deactivate: MinimalPlugin.deactivate - start_processing: MinimalPlugin.start_processing - stop_processing: MinimalPlugin.stop_processing - reset: MinimalPlugin.reset - process: MinimalPlugin.process - get_extension: MinimalPlugin.get_extension - on_main_thread: MinimalPlugin.on_main_thread + init: main_plugin.init + destroy: main_plugin.destroy + activate: main_plugin.activate + deactivate: main_plugin.deactivate + start_processing: main_plugin.start_processing + stop_processing: main_plugin.stop_processing + reset: main_plugin.reset + process: main_plugin.process + get_extension: main_plugin.get_extension + on_main_thread: main_plugin.on_main_thread } return clap_plugin