Skip to content

Commit

Permalink
Adding initial LV2 support for jackrack module
Browse files Browse the repository at this point in the history
  • Loading branch information
mr.fantastic committed May 24, 2024
1 parent 857e358 commit 189bbf4
Show file tree
Hide file tree
Showing 21 changed files with 3,932 additions and 1 deletion.
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ option(SWIG_PHP "Enable SWIG PHP bindings" OFF)
option(SWIG_PYTHON "Enable SWIG Python bindings" OFF)
option(SWIG_RUBY "Enable SWIG Ruby bindings" OFF)
option(SWIG_TCL "Enable SWIG Tcl bindings" OFF)
option(USE_LV2 "Enable LV2 features" ON)

if(WIN32)
option(WINDOWS_DEPLOY "Install exes/libs directly to prefix (no subdir /bin)" ON)
Expand Down Expand Up @@ -247,6 +248,10 @@ if(MOD_JACKRACK)
list(APPEND MLT_SUPPORTED_COMPONENTS jackrack)
endif()

if(USE_LV2)
pkg_check_modules(lilv IMPORTED_TARGET lilv-0)
endif()

if(MOD_KDENLIVE)
list(APPEND MLT_SUPPORTED_COMPONENTS kdenlive)
endif()
Expand Down Expand Up @@ -629,5 +634,6 @@ add_feature_info("SWIG: PHP" SWIG_PHP "")
add_feature_info("SWIG: Python" SWIG_PYTHON "")
add_feature_info("SWIG: Ruby" SWIG_RUBY "")
add_feature_info("SWIG: Tcl" SWIG_TCL "")
add_feature_info("lv2: LV2 Plugins support" USE_LV2 "")

feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)
12 changes: 12 additions & 0 deletions src/modules/jackrack/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ if(TARGET JACK::JACK)
install(FILES consumer_jack.yml DESTINATION ${MLT_INSTALL_DATA_DIR}/jackrack)
endif()

if(USE_LV2)
target_compile_definitions(mltjackrack PRIVATE WITH_LV2)
install(FILES filter_lv2.yml producer_lv2.yml DESTINATION ${MLT_INSTALL_DATA_DIR}/jackrack)
endif()

if(GPL AND TARGET PkgConfig::xml AND TARGET PkgConfig::glib AND ladspa_h_FOUND)
target_sources(mltjackrack PRIVATE
jack_rack.c jack_rack.h
Expand All @@ -40,6 +45,13 @@ if(GPL AND TARGET PkgConfig::xml AND TARGET PkgConfig::glib AND ladspa_h_FOUND)
target_sources(mltjackrack PRIVATE filter_jackrack.c)
install(FILES filter_jackrack.yml DESTINATION ${MLT_INSTALL_DATA_DIR}/jackrack)
endif()

if(USE_LV2 AND TARGET PkgConfig::lilv)
target_link_libraries(mltjackrack PRIVATE PkgConfig::lilv)
target_sources(mltjackrack PRIVATE filter_lv2.c producer_lv2.c lv2_rack.c lv2_plugin.c lv2_process.c lv2_plugin_settings.c)
install(FILES filter_lv2.yml producer_lv2.yml DESTINATION ${MLT_INSTALL_DATA_DIR}/jackrack)
endif()

endif()

set_target_properties(mltjackrack PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${MLT_MODULE_OUTPUT_DIRECTORY}")
Expand Down
229 changes: 228 additions & 1 deletion src/modules/jackrack/factory.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* factory.c -- the factory method interfaces
* Copyright (C) 2003-2022 Meltytech, LLC
* Copyright (C) 2003-2024 Meltytech, LLC
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -49,8 +49,38 @@ extern mlt_producer producer_ladspa_init(mlt_profile profile,
const char *id,
char *arg);

#ifdef WITH_LV2

#include <lv2.h>

/* lv2 extenstions */
#include <lv2/atom/atom.h>
#include <lv2/midi/midi.h>
#include <lv2/port-groups/port-groups.h>
#include <lv2/port-props/port-props.h>
#include <lv2/presets/presets.h>
#include <lv2/resize-port/resize-port.h>
#include <lv2/ui/ui.h>
#include <lv2/worker/worker.h>

#include <lilv/lilv.h>

extern mlt_filter filter_lv2_init(mlt_profile profile,
mlt_service_type type,
const char *id,
char *arg);
extern mlt_producer producer_lv2_init(mlt_profile profile,
mlt_service_type type,
const char *id,
char *arg);
#endif

plugin_mgr_t *g_jackrack_plugin_mgr = NULL;

#ifdef WITH_LV2
lv2_mgr_t *g_lv2_plugin_mgr = NULL;
#endif

static void add_port_to_metadata(mlt_properties p, plugin_desc_t *desc, int j)
{
LADSPA_Data sample_rate = 48000;
Expand Down Expand Up @@ -211,8 +241,172 @@ static mlt_properties metadata(mlt_service_type type, const char *id, char *data
return result;
}

#ifdef WITH_LV2

static void lv2_add_port_to_metadata(mlt_properties p, lv2_plugin_desc_t *desc, int j)
{
LADSPA_PortRangeHintDescriptor hint_descriptor = desc->port_range_hints[j].HintDescriptor;

mlt_properties_set(p, "title", desc->port_names[j]);
if (LADSPA_IS_HINT_INTEGER(hint_descriptor)) {
mlt_properties_set(p, "type", "integer");
mlt_properties_set_int(p,
"default",
(int) desc->def_values[j]);
mlt_properties_set_double(p,
"minimum",
(int) desc->min_values[j]);
mlt_properties_set_double(p,
"maximum",
(int) desc->max_values[j]);
} else if (LADSPA_IS_HINT_TOGGLED(hint_descriptor)) {
mlt_properties_set(p, "type", "boolean");
mlt_properties_set_int(p,
"default",
desc->def_values[j]);
} else {
mlt_properties_set(p, "type", "float");
mlt_properties_set_double(p,
"default",
desc->def_values[j]);
mlt_properties_set_double(p,
"minimum",
desc->min_values[j]);
mlt_properties_set_double(p,
"maximum",
desc->max_values[j]);

}

if (LADSPA_IS_HINT_ENUMERATION(hint_descriptor))
{
/* WIP */
}

if (LADSPA_IS_HINT_LOGARITHMIC(hint_descriptor))
mlt_properties_set(p, "scale", "log");
mlt_properties_set(p, "mutable", "yes");
mlt_properties_set(p, "animation", "yes");
}

static mlt_properties lv2_metadata(mlt_service_type type, const char *id, char *data)
{
char file[PATH_MAX];
if (type == mlt_service_filter_type) {

snprintf(file,
PATH_MAX,
"%s/lv2/%s",
mlt_environment("MLT_DATA"),
strncmp(id, "lv2.", 4) ? data : "filter_lv2.yml");
} else {
snprintf(file,
PATH_MAX,
"%s/lv2/%s",
mlt_environment("MLT_DATA"),
strncmp(id, "lv2.", 4) ? data : "producer_lv2.yml");
}
mlt_properties result = mlt_properties_parse_yaml(file);

if (!strncmp(id, "lv2.", 4)) {
// Annotate the yaml properties with lv2 control port info.
lv2_plugin_desc_t *desc = lv2_mgr_get_any_desc(g_lv2_plugin_mgr, (char *) &id[4]);

if (desc) {

mlt_properties params = mlt_properties_new();
mlt_properties p;
char key[20];
int i;

mlt_properties_set(result, "identifier", id);
mlt_properties_set(result, "title", desc->name);
mlt_properties_set(result, "creator", desc->maker ? desc->maker : "unknown");
mlt_properties_set(result, "description", "LADSPA plugin");
mlt_properties_set_data(result,
"parameters",
params,
0,
(mlt_destructor) mlt_properties_close,
NULL);
for (i = 0; i < desc->control_port_count; i++) {
int j = desc->control_port_indicies[i];
p = mlt_properties_new();
snprintf(key, sizeof(key), "%d", mlt_properties_count(params));
mlt_properties_set_data(params,
key,
p,
0,
(mlt_destructor) mlt_properties_close,
NULL);
snprintf(key, sizeof(key), "%d", j);
mlt_properties_set(p, "identifier", key);
lv2_add_port_to_metadata(p, desc, j);
mlt_properties_set(p, "mutable", "yes");
}
for (i = 0; i < desc->status_port_count; i++) {
int j = desc->status_port_indicies[i];
p = mlt_properties_new();
snprintf(key, sizeof(key), "%d", mlt_properties_count(params));
mlt_properties_set_data(params,
key,
p,
0,
(mlt_destructor) mlt_properties_close,
NULL);
snprintf(key, sizeof(key), "%d[*]", j);
mlt_properties_set(p, "identifier", key);
lv2_add_port_to_metadata(p, desc, j);
mlt_properties_set(p, "readonly", "yes");
}

p = mlt_properties_new();
snprintf(key, sizeof(key), "%d", mlt_properties_count(params));
mlt_properties_set_data(params, key, p, 0, (mlt_destructor) mlt_properties_close, NULL);
mlt_properties_set(p, "identifier", "instances");
mlt_properties_set(p, "title", "Instances");
mlt_properties_set(p,
"description",
"The number of instances of the plugin that are in use.\n"
"MLT will create the number of plugins that are required "
"to support the number of audio channels.\n"
"Status parameters (readonly) are provided for each instance "
"and are accessed by specifying the instance number after the "
"identifier (starting at zero).\n"
"e.g. 9[0] provides the value of status 9 for the first instance.");
mlt_properties_set(p, "type", "integer");
mlt_properties_set(p, "readonly", "yes");

if (type == mlt_service_filter_type) {

p = mlt_properties_new();
snprintf(key, sizeof(key), "%d", mlt_properties_count(params));
mlt_properties_set_data(params,
key,
p,
0,
(mlt_destructor) mlt_properties_close,
NULL);
mlt_properties_set(p, "identifier", "wetness");
mlt_properties_set(p, "title", "Wet/Dry");
mlt_properties_set(p, "type", "float");
mlt_properties_set_double(p, "default", 1);
mlt_properties_set_double(p, "minimum", 0);
mlt_properties_set_double(p, "maximum", 1);
mlt_properties_set(p, "mutable", "yes");
mlt_properties_set(p, "animation", "yes");
}
}
}

return result;
}

#endif

MLT_REPOSITORY
{

#ifdef GPL
GSList *list;
g_jackrack_plugin_mgr = plugin_mgr_new();
Expand All @@ -235,6 +429,39 @@ MLT_REPOSITORY
}
mlt_factory_register_for_clean_up(g_jackrack_plugin_mgr, (mlt_destructor) plugin_mgr_destroy);

#ifdef WITH_LV2
g_lv2_plugin_mgr = lv2_mgr_new();

for (list = g_lv2_plugin_mgr->all_plugins; list; list = g_slist_next(list)) {

lv2_plugin_desc_t *desc = (lv2_plugin_desc_t *) list->data;
char *s = NULL;
s = calloc(1, strlen("lv2.") + strlen (desc->uri) + 1);

sprintf(s, "lv2.%s", desc->uri);

char *str_ptr = strchr(s, ':');
while (str_ptr != NULL)
{
*str_ptr++ = '<';
str_ptr = strchr(str_ptr, ':');
}

if (desc->has_input) {
MLT_REGISTER(mlt_service_filter_type, s, filter_lv2_init);
MLT_REGISTER_METADATA(mlt_service_filter_type, s, lv2_metadata, NULL);
} else {
MLT_REGISTER(mlt_service_producer_type, s, producer_lv2_init);
MLT_REGISTER_METADATA(mlt_service_producer_type, s, lv2_metadata, NULL);
}

if (s)
{
free(s);
}
}
#endif

#ifdef WITH_JACK
MLT_REGISTER(mlt_service_filter_type, "jack", filter_jackrack_init);
MLT_REGISTER_METADATA(mlt_service_filter_type, "jack", metadata, "filter_jack.yml");
Expand Down
Loading

0 comments on commit 189bbf4

Please sign in to comment.