Browse Source

instantiate plugins with carla

master
Alexandros Theodotou 7 months ago
parent
commit
4326b246b7
Signed by: alex GPG Key ID: 022EAE42313D70F3
  1. 6
      README.md
  2. 8
      carla_api_tester.c
  3. 419
      carla_api_tester_app.c
  4. 22
      carla_api_tester_app.h
  5. 21
      meson.build

6
README.md

@ -0,0 +1,6 @@
Carla API Tester
================
Usage
carla-api-tester.gtk3 --format=lv2 --plugin=urn:zamaudio:ZamGate --bridge=none

8
carla_api_tester.c

@ -11,6 +11,7 @@ static char * arg0 = NULL;
static char * format = NULL;
static char * plugin = NULL;
static char * bridge = NULL;
static bool woe32_binary = false;
int main(int argc, char **argv)
{
@ -30,6 +31,11 @@ int main(int argc, char **argv)
G_OPTION_ARG_STRING, &bridge,
"Bridge type (none/ui/full)",
"BRIDGE-TYPE" },
{ "woe32-binary", 0, G_OPTION_FLAG_NONE,
G_OPTION_ARG_NONE, &woe32_binary,
"Whether the plugin is a Windows 32-bit "
"binary",
NULL },
{ NULL },
};
@ -87,7 +93,7 @@ int main(int argc, char **argv)
carla_api_tester_app =
carla_api_tester_app_new (
plugin, format, bridge);
plugin, format, bridge, woe32_binary);
g_message ("running app...");
int ret =

419
carla_api_tester_app.c

@ -12,7 +12,219 @@ CarlaApiTesterApp * carla_api_tester_app = NULL;
G_DEFINE_TYPE (
CarlaApiTesterApp, carla_api_tester_app,
GTK_TYPE_APPLICATION);
GTK_TYPE_APPLICATION)
/**
* Tick callback for the plugin UI.
*/
static int
carla_plugin_tick_cb (
GtkWidget * widget,
GdkFrameClock * frame_clock,
CarlaApiTesterApp * self)
{
self->native_plugin_descriptor->ui_idle (
self->native_plugin_handle);
return G_SOURCE_CONTINUE;
}
static uint32_t
host_get_buffer_size (
NativeHostHandle handle)
{
uint32_t buffer_size = 512;
return buffer_size;
}
static double
host_get_sample_rate (
NativeHostHandle handle)
{
double sample_rate = 44000.0;
return sample_rate;
}
static bool
host_is_offline (
NativeHostHandle handle)
{
return false;
}
static const NativeTimeInfo*
host_get_time_info (
CarlaApiTesterApp * self)
{
return &self->time_info;
}
static bool
host_write_midi_event (
CarlaApiTesterApp * self,
const NativeMidiEvent * event)
{
g_message ("write midi event");
return 0;
}
static void
host_ui_parameter_changed (
CarlaApiTesterApp * self,
uint32_t index,
float value)
{
g_message ("handle ui param changed");
}
static void
host_ui_custom_data_changed (
CarlaApiTesterApp * self,
const char* key,
const char* value)
{
}
static void
host_ui_closed (
CarlaApiTesterApp * self)
{
g_message ("ui closed");
}
static intptr_t
host_dispatcher (
CarlaApiTesterApp * self,
NativeHostDispatcherOpcode opcode,
int32_t index,
intptr_t value,
void* ptr,
float opt)
{
/* TODO */
g_message ("host dispatcher (opcode %d)", opcode);
switch (opcode)
{
case NATIVE_HOST_OPCODE_HOST_IDLE:
/* some expensive computation is happening.
* this is used so that the GTK ui does not
* block */
/* note: disabled because some logic depends
* on this plugin being activated */
#if 0
while (gtk_events_pending ())
{
gtk_main_iteration ();
}
#endif
break;
#if 0
case NATIVE_HOST_OPCODE_INTERNAL_PLUGIN:
/* falktx: you will need to call the new
* juce functions, then return 1 on the
* INTERNAL_PLUGIN host opcode.
* when that opcode returns 1, carla-plugin
* will let the host do the juce idling
* which is for the best here, since you want
* to show UIs without carla itself */
return 1;
break;
#endif
case NATIVE_HOST_OPCODE_GET_FILE_PATH:
g_debug ("get file path");
g_return_val_if_fail (ptr, 0);
if (!strcmp ((char *) ptr, "carla"))
{
g_debug ("ptr is carla");
}
break;
case NATIVE_HOST_OPCODE_UI_RESIZE:
g_debug ("ui resize");
/* TODO handle UI resize */
break;
case NATIVE_HOST_OPCODE_UI_TOUCH_PARAMETER:
g_debug ("ui touch");
break;
case NATIVE_HOST_OPCODE_UI_UNAVAILABLE:
/* TODO handle UI close */
g_debug ("UI unavailable");
break;
default:
break;
}
return 0;
}
static void
engine_callback (
CarlaApiTesterApp * self,
EngineCallbackOpcode action,
uint plugin_id,
int val1,
int val2,
int val3,
float valf,
const char * val_str)
{
switch (action)
{
case ENGINE_CALLBACK_UI_STATE_CHANGED:
switch (val1)
{
case 0:
case -1:
g_message ("plugin became hidden");
break;
case 1:
g_message ("plugin became visible");
break;
}
break;
default:
break;
}
}
static PluginType
get_plugin_type_from_str (
const char * str)
{
if (!strcmp (str, "lv2"))
{
return PLUGIN_LV2;
}
else if (!strcmp (str, "ladspa"))
{
return PLUGIN_LADSPA;
}
else if (!strcmp (str, "dssi"))
{
return PLUGIN_DSSI;
}
else if (!strcmp (str, "vst2"))
{
return PLUGIN_VST2;
}
else if (!strcmp (str, "vst3"))
{
return PLUGIN_VST3;
}
else if (!strcmp (str, "au"))
{
return PLUGIN_AU;
}
else if (!strcmp (str, "sfz"))
{
return PLUGIN_SFZ;
}
else if (!strcmp (str, "sf2"))
{
return PLUGIN_SF2;
}
}
/*
* Called after startup if no filename is passed on
@ -24,6 +236,207 @@ carla_api_tester_app_activate (
{
g_message ("Activating...");
CarlaApiTesterApp * self =
CARLA_API_TESTER_APP (_app);
self->native_host_descriptor.handle = self;
self->native_host_descriptor.uiName =
"Carla API tester";
self->native_host_descriptor.uiParentId = 0;
/* set resources dir */
const char * carla_filename =
carla_get_library_filename ();
char * tmp = g_path_get_dirname (carla_filename);
char * dir = g_path_get_dirname (tmp);
g_free (tmp);
tmp = g_path_get_dirname (dir);
g_free (dir);
dir = tmp;
self->native_host_descriptor.resourceDir =
g_build_filename (
dir, "share", "carla", "resources", NULL);
g_free (dir);
self->native_host_descriptor.get_buffer_size =
host_get_buffer_size;
self->native_host_descriptor.get_sample_rate =
host_get_sample_rate;
self->native_host_descriptor.is_offline =
host_is_offline;
self->native_host_descriptor.get_time_info =
(const NativeTimeInfo * (*)(void *))
host_get_time_info;
self->native_host_descriptor.write_midi_event =
(_Bool (*)(void *, const NativeMidiEvent *))
host_write_midi_event;
self->native_host_descriptor.
ui_parameter_changed =
(void (*)(void *, uint32_t, float))
host_ui_parameter_changed;
self->native_host_descriptor.
ui_custom_data_changed =
(intptr_t (*)(void *, NativeHostDispatcherOpcode, int32_t, intptr_t, void *, float))
host_ui_custom_data_changed;
self->native_host_descriptor.ui_closed =
(void (*)(void *))
host_ui_closed;
self->native_host_descriptor.ui_open_file =
NULL;
self->native_host_descriptor.ui_save_file =
NULL;
self->native_host_descriptor.dispatcher =
(intptr_t (*)(CarlaApiTesterApp *, NativeHostDispatcherOpcode, int32_t, intptr_t, void *, float))
host_dispatcher;
self->time_info.bbt.valid = 1;
/* instantiate the plugin to get its info */
self->native_plugin_descriptor =
carla_get_native_rack_plugin ();
self->native_plugin_handle =
self->native_plugin_descriptor->instantiate (
&self->native_host_descriptor);
self->host_handle =
carla_create_native_plugin_host_handle (
self->native_plugin_descriptor,
self->native_plugin_handle);
/* set binary paths */
g_message (
"setting carla engine option "
"[ENGINE_OPTION_PATH_BINARIES] to '%s'",
CONFIGURE_BINDIR);
carla_set_engine_option (
self->host_handle,
ENGINE_OPTION_PATH_BINARIES, 0,
CONFIGURE_BINDIR);
#if 0
/* set lv2 path */
carla_set_engine_option (
self->host_handle,
ENGINE_OPTION_PLUGIN_PATH, PLUGIN_LV2,
PLUGIN_MANAGER->lv2_path);
/* set UI scale factor */
carla_set_engine_option (
self->host_handle,
ENGINE_OPTION_FRONTEND_UI_SCALE,
(int)
((float) self->plugin->ui_scale_factor *
1000.f),
NULL);
/* set whether UI should stay on top */
if (!ZRYTHM_TESTING &&
g_settings_get_boolean (
S_P_PLUGINS_UIS, "stay-on-top"))
{
carla_set_engine_option (
self->host_handle,
ENGINE_OPTION_UIS_ALWAYS_ON_TOP, true,
NULL);
}
#endif
g_message (
"%s: using bridge mode %s", __func__,
self->bridge);
if (!strcmp (self->bridge, "full"))
{
carla_set_engine_option (
self->host_handle,
ENGINE_OPTION_PREFER_PLUGIN_BRIDGES,
true, NULL);
}
else if (!strcmp (self->bridge, "ui"))
{
carla_set_engine_option (
self->host_handle,
ENGINE_OPTION_PREFER_UI_BRIDGES,
true, NULL);
}
int ret = -1;
PluginType type =
get_plugin_type_from_str (self->format);
if (!strcmp (self->format, "lv2") ||
!strcmp (self->format, "au"))
{
g_message ("uri %s", self->plugin);
ret =
carla_add_plugin (
self->host_handle,
self->woe32_binary ?
BINARY_WIN32 : BINARY_NATIVE,
type, NULL, "name",
self->plugin, 0, NULL, 0);
}
else if (!strcmp (self->format, "vst2") ||
!strcmp (self->format, "vst3"))
{
ret =
carla_add_plugin (
self->host_handle,
self->woe32_binary ?
BINARY_WIN32 : BINARY_NATIVE,
type, self->plugin, "name",
/* TODO UNIQUE ID */
"name", 0, NULL, 0);
}
else if (!strcmp (self->format, "dssi") ||
!strcmp (self->format, "ladspa"))
{
ret =
carla_add_plugin (
self->host_handle, BINARY_NATIVE,
type, self->plugin, "name",
self->plugin, 0, NULL, 0);
}
else if (!strcmp (self->format, "sfz") ||
!strcmp (self->format, "sf2"))
{
ret =
carla_add_plugin (
self->host_handle,
BINARY_NATIVE,
type, self->plugin, "name",
"name", 0, NULL, 0);
}
else
{
g_error ("unknown format %s", self->format);
}
if (ret != 1)
{
g_error (
"Error adding carla plugin: %s",
carla_get_last_error (self->host_handle));
}
/* enable various messages */
#define ENABLE_OPTION(x) \
carla_set_option ( \
self->host_handle, 0, \
PLUGIN_OPTION_##x, true)
ENABLE_OPTION (FORCE_STEREO);
ENABLE_OPTION (SEND_CONTROL_CHANGES);
ENABLE_OPTION (SEND_CHANNEL_PRESSURE);
ENABLE_OPTION (SEND_NOTE_AFTERTOUCH);
ENABLE_OPTION (SEND_PITCHBEND);
ENABLE_OPTION (SEND_ALL_SOUND_OFF);
ENABLE_OPTION (SEND_PROGRAM_CHANGES);
/* add engine callback */
carla_set_engine_callback (
self->host_handle, engine_callback, self);
g_message ("done");
}
@ -120,7 +533,8 @@ CarlaApiTesterApp *
carla_api_tester_app_new (
const char * plugin,
const char * format,
const char * bridge)
const char * bridge,
bool woe32_binary)
{
CarlaApiTesterApp * self = g_object_new (
CARLA_API_TESTER_APP_TYPE,
@ -134,6 +548,7 @@ carla_api_tester_app_new (
self->bridge = bridge;
self->plugin = plugin;
self->format = format;
self->woe32_binary = woe32_binary;
/* add shutdown handler */
g_signal_connect (

22
carla_api_tester_app.h

@ -1,6 +1,9 @@
#ifndef __CARLA_API_TESTER_APP_H__
#define __CARLA_API_TESTER_APP_H__
#include <CarlaHost.h>
#include <CarlaNativePlugin.h>
#include <CarlaUtils.h>
#include <gtk/gtk.h>
#define CARLA_API_TESTER_APP_TYPE \
@ -18,11 +21,19 @@ G_DECLARE_FINAL_TYPE (
*/
struct _CarlaApiTesterApp
{
GtkApplication parent;
GtkApplication parent;
const char * plugin;
const char * format;
const char * bridge;
const char * plugin;
const char * format;
const char * bridge;
bool woe32_binary;
NativePluginHandle native_plugin_handle;
NativeHostDescriptor native_host_descriptor;
const NativePluginDescriptor * native_plugin_descriptor;
NativeTimeInfo time_info;
CarlaHostHandle host_handle;
};
/**
@ -37,6 +48,7 @@ CarlaApiTesterApp *
carla_api_tester_app_new (
const char * plugin,
const char * format,
const char * bridge);
const char * bridge,
bool woe32_binary);
#endif /* __CARLA_API_TESTER_APP_H__ */

21
meson.build

@ -1,11 +1,16 @@
project('carla-api-tester', 'c',
version : '0.1',
default_options : ['warning_level=3'])
default_options : [
'warning_level=3',
'c_std=gnu11',
])
prefix = get_option ('prefix')
bindir = prefix / get_option ('bindir')
libdir = prefix / get_option ('libdir')
cc = meson.get_compiler ('c')
os_darwin = false
os_linux = false
os_freebsd = false
@ -28,10 +33,23 @@ else
error ('unknown host system ' + host_machine.system ())
endif
test_cflags = [
'-Wno-missing-field-initializers',
'-Wno-unused-parameter',
]
cflags = cc.get_supported_arguments (
test_cflags)
add_project_arguments (
cflags,
language: [ 'c' ]
)
cdata = configuration_data ()
cdata.set_quoted (
'ISSUE_TRACKER_URL',
'https://todo.sr.ht/~alextee/zrythm-bug')
cdata.set_quoted (
'CONFIGURE_BINDIR', bindir)
gtk_dep = dependency (
'gtk+-3.0', version: '>=3.22')
@ -93,6 +111,7 @@ exe = executable (
'carla_api_tester.c',
],
dependencies: [
carla_host_plugin_dep,
gtk_dep,
],
install: true)

Loading…
Cancel
Save