|
|
|
@ -12,7 +12,219 @@ CarlaApiTesterApp * carla_api_tester_app = NULL;
@@ -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 (
@@ -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 *
@@ -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 (
@@ -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 ( |
|
|
|
|