Skip to content

Commit

Permalink
Complete example of a CLAP plugin based on template. (#1)
Browse files Browse the repository at this point in the history
- Swaps left and right audio channels.
- Logs (CLAP) note on/off messages.
  • Loading branch information
odiroot authored Jan 17, 2024
1 parent 5f0de10 commit 224eabf
Show file tree
Hide file tree
Showing 8 changed files with 333 additions and 57 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ V_SRC = $(wildcard $(SOURCEDIR)/*.v)
DEBUG ?= 0
RELEASE ?= 0
ifeq ($(DEBUG),1)
V_FLAGS = -cg -show-c-output
V_FLAGS = -cg -show-c-output -trace-calls
else ifeq ($(RELEASE),1)
V_FLAGS = -prod -skip-unused -cflags -fvisibility=hidden
endif
Expand Down
98 changes: 86 additions & 12 deletions src/c_abi.v
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ module plugin
#include "clap/clap.h"

enum ClapProcessStatus {
clap_process_error = 0
clap_process_continue = 1
clap_process_continue_if_not_quiet = 2
clap_process_tail = 3
clap_process_sleep = 4
error = 0
@continue = 1
continue_if_not_quiet = 2
tail = 3
sleep = 4
}

type C.clap_id = u32

@[typedef]
struct C.clap_version_t {
major u32 = u32(C.CLAP_VERSION_MAJOR)
Expand All @@ -37,10 +39,10 @@ struct C.clap_plugin_t {
desc &C.clap_plugin_descriptor_t @[required]
plugin_data voidptr @[required]

init fn (&C.clap_plugin_t) bool @[required]
destroy fn (&C.clap_plugin_t) @[required]
activate fn (&C.clap_plugin_t, f64, u32, u32) bool @[required]
deactivate fn (&C.clap_plugin_t) @[required]
init fn (&C.clap_plugin_t) bool @[required]
destroy fn (&C.clap_plugin_t) @[required]
activate fn (&C.clap_plugin_t, f64, u32, u32) bool @[required]
deactivate fn (&C.clap_plugin_t) @[required]
start_processing fn (&C.clap_plugin_t) bool
stop_processing fn (&C.clap_plugin_t)
reset fn (&C.clap_plugin_t)
Expand All @@ -49,9 +51,10 @@ struct C.clap_plugin_t {
on_main_thread fn (&C.clap_plugin_t)
}

@[typedef]
@[heap; typedef]
struct C.clap_host_t {
clap_version C.clap_version_t
clap_version C.clap_version_t
get_extension fn (&C.clap_host_t, &char) voidptr
}

@[typedef]
Expand All @@ -70,8 +73,79 @@ struct C.clap_plugin_entry_t {
}

@[typedef]
struct C.clap_process_t
struct C.clap_process_t {
steady_time i64
frames_count u32
transport &C.clap_event_transport_t
audio_inputs &C.clap_audio_buffer_t
audio_inputs_count u32
audio_outputs_count u32
in_events &C.clap_input_events_t
out_events &C.clap_output_events_t
mut:
audio_outputs &C.clap_audio_buffer_t
}

@[typedef]
struct C.clap_event_transport_t {}

@[typedef]
struct C.clap_audio_buffer_t {
channel_count u32
latency u32
constant_mask u64
mut:
data32 &&f32
data64 &&f64
}

@[typedef]
struct C.clap_input_events_t {
ctx voidptr
size fn (&C.clap_input_events_t) u32
// TODO: How to avoid `voidptr` and use header/event structs instead?
get fn (&C.clap_input_events_t, u32) voidptr
}

@[typedef]
struct C.clap_event_header_t {
size u32
time u32
space_id u16
@type u16
flags u32
}

// TODO: Why doesn't typedef C structs work here?
struct ClapEventNote {
C.clap_event_header_t
note_id int
port_index i16
channel i16
key i16
velocity f64
}

enum ClapEventType as u16 {
note_on = 0
note_off = 1
note_choke = 2
note_end = 3
note_expression = 4
param_value = 5
param_mod = 6
param_gesture_begin = 7
param_gesture_end = 8
transport = 9
midi = 10
midi_sysex = 11
midi2 = 12
}

@[typedef]
struct C.clap_output_events_t {}

const clap_plugin_factory_id = unsafe { (&char(C.CLAP_PLUGIN_FACTORY_ID)).vstring() }
const clap_core_event_space_id = u16(C.CLAP_CORE_EVENT_SPACE_ID)

fn C.clap_version_is_compatible(C.clap_version_t) bool
29 changes: 29 additions & 0 deletions src/ext_audio_ports.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
module plugin

const clap_ext_audio_ports = unsafe { (&char(C.CLAP_EXT_AUDIO_PORTS)).vstring() }
const clap_port_stereo = unsafe { (&char(C.CLAP_PORT_STEREO)).vstring() }
const clap_port_mono = unsafe { (&char(C.CLAP_PORT_MONO)).vstring() }

@[typedef]
struct C.clap_audio_port_info_t {
mut:
id C.clap_id
name [256]char
flags u32
channel_count u32
port_type &char
in_place_pair C.clap_id
}

@[typedef]
struct C.clap_plugin_audio_ports_t {
count fn (&C.clap_plugin_t, bool) u32
get fn (&C.clap_plugin_t, u32, bool, &C.clap_audio_port_info_t) bool
}

enum ClapAudioPortFlags as u32 {
is_main = 1 << 0
supports_64_bits = 1 << 1
prefers_64_bits = 1 << 2
requires_common_sample_size = 1 << 3
}
8 changes: 8 additions & 0 deletions src/ext_latency.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module plugin

const clap_ext_latency = unsafe { (&char(C.CLAP_EXT_LATENCY)).vstring() }

@[typedef]
struct C.clap_plugin_latency_t {
get fn (&C.clap_plugin_t) u32
}
25 changes: 25 additions & 0 deletions src/ext_note_ports.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
module plugin

const clap_ext_note_ports = unsafe { (&char(C.CLAP_EXT_NOTE_PORTS)).vstring() }

@[typedef]
struct C.clap_note_port_info_t {
mut:
id C.clap_id
supported_dialects u32
preferred_dialect u32
name [256]char
}

@[typedef]
struct C.clap_plugin_note_ports_t {
count fn (&C.clap_plugin_t, bool) u32
get fn (&C.clap_plugin_t, u32, bool, &C.clap_note_port_info_t) bool
}

enum ClapNoteDialect as u32 {
clap = 1 << 0
midi = 1 << 1
midi_mpe = 1 << 2
midi2 = 1 << 3
}
2 changes: 1 addition & 1 deletion src/main.v
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ module plugin
// Remove "const" so you get:
// CLAP_EXPORT extern clap_plugin_entry_t clap_entry;
@[markused]
__global clap_entry = _plugin_entry
__global clap_entry = plugin_entry
Loading

0 comments on commit 224eabf

Please sign in to comment.