Thread-safety at LV2 level
This commit is contained in:
parent
c110acc966
commit
1d6b06aa2e
2 changed files with 63 additions and 9 deletions
|
|
@ -22,25 +22,25 @@ add_library(${LV2PLUGIN_PRJ_NAME} MODULE
|
||||||
${PROJECT_NAME}.c
|
${PROJECT_NAME}.c
|
||||||
atomic_compat.h
|
atomic_compat.h
|
||||||
${LV2PLUGIN_TTL_SRC_FILES})
|
${LV2PLUGIN_TTL_SRC_FILES})
|
||||||
target_link_libraries(${LV2PLUGIN_PRJ_NAME} ${PROJECT_NAME}::${PROJECT_NAME})
|
target_link_libraries(${LV2PLUGIN_PRJ_NAME} PRIVATE sfizz::sfizz sfizz::spin_mutex)
|
||||||
|
|
||||||
if(SFIZZ_LV2_UI)
|
if(SFIZZ_LV2_UI)
|
||||||
add_library(${LV2PLUGIN_PRJ_NAME}_ui MODULE
|
add_library(${LV2PLUGIN_PRJ_NAME}_ui MODULE
|
||||||
${PROJECT_NAME}_ui.cpp
|
${PROJECT_NAME}_ui.cpp
|
||||||
vstgui_helpers.h
|
vstgui_helpers.h
|
||||||
vstgui_helpers.cpp)
|
vstgui_helpers.cpp)
|
||||||
target_link_libraries(${LV2PLUGIN_PRJ_NAME}_ui sfizz::editor sfizz::vstgui)
|
target_link_libraries(${LV2PLUGIN_PRJ_NAME}_ui PRIVATE sfizz::editor sfizz::vstgui)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Explicitely strip all symbols on Linux but lv2_descriptor()
|
# Explicitely strip all symbols on Linux but lv2_descriptor()
|
||||||
# MacOS linker does not support this apparently https://bugs.webkit.org/show_bug.cgi?id=144555
|
# MacOS linker does not support this apparently https://bugs.webkit.org/show_bug.cgi?id=144555
|
||||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||||
file(COPY lv2.version DESTINATION ${CMAKE_BINARY_DIR}/lv2)
|
file(COPY lv2.version DESTINATION ${CMAKE_BINARY_DIR}/lv2)
|
||||||
target_link_libraries(${LV2PLUGIN_PRJ_NAME} "-Wl,--version-script=lv2.version")
|
target_link_libraries(${LV2PLUGIN_PRJ_NAME} PRIVATE "-Wl,--version-script=lv2.version")
|
||||||
# target_link_libraries(${LV2PLUGIN_PRJ_NAME} "-Wl,-u,lv2_descriptor")
|
# target_link_libraries(${LV2PLUGIN_PRJ_NAME} "-Wl,-u,lv2_descriptor")
|
||||||
if(SFIZZ_LV2_UI)
|
if(SFIZZ_LV2_UI)
|
||||||
file(COPY lv2ui.version DESTINATION ${CMAKE_BINARY_DIR}/lv2)
|
file(COPY lv2ui.version DESTINATION ${CMAKE_BINARY_DIR}/lv2)
|
||||||
target_link_libraries(${LV2PLUGIN_PRJ_NAME}_ui "-Wl,--version-script=lv2ui.version")
|
target_link_libraries(${LV2PLUGIN_PRJ_NAME}_ui PRIVATE "-Wl,--version-script=lv2ui.version")
|
||||||
# target_link_libraries(${LV2PLUGIN_PRJ_NAME}_ui "-Wl,-u,lv2ui_descriptor")
|
# target_link_libraries(${LV2PLUGIN_PRJ_NAME}_ui "-Wl,-u,lv2ui_descriptor")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
|
||||||
64
lv2/sfizz.c
64
lv2/sfizz.c
|
|
@ -53,6 +53,8 @@
|
||||||
|
|
||||||
#include <ardour/lv2_extensions.h>
|
#include <ardour/lv2_extensions.h>
|
||||||
|
|
||||||
|
#include <spin_mutex.h>
|
||||||
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <sfizz.h>
|
#include <sfizz.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
@ -160,6 +162,7 @@ typedef struct
|
||||||
// Sfizz related data
|
// Sfizz related data
|
||||||
sfizz_synth_t *synth;
|
sfizz_synth_t *synth;
|
||||||
sfizz_client_t *client;
|
sfizz_client_t *client;
|
||||||
|
spin_mutex_t *synth_mutex;
|
||||||
bool expect_nominal_block_length;
|
bool expect_nominal_block_length;
|
||||||
char sfz_file_path[MAX_PATH_SIZE];
|
char sfz_file_path[MAX_PATH_SIZE];
|
||||||
char scala_file_path[MAX_PATH_SIZE];
|
char scala_file_path[MAX_PATH_SIZE];
|
||||||
|
|
@ -599,6 +602,7 @@ instantiate(const LV2_Descriptor *descriptor,
|
||||||
|
|
||||||
self->synth = sfizz_create_synth();
|
self->synth = sfizz_create_synth();
|
||||||
self->client = sfizz_create_client(self);
|
self->client = sfizz_create_client(self);
|
||||||
|
self->synth_mutex = spin_mutex_create();
|
||||||
sfizz_set_broadcast_callback(self->synth, &sfizz_lv2_receive_message, self);
|
sfizz_set_broadcast_callback(self->synth, &sfizz_lv2_receive_message, self);
|
||||||
sfizz_set_receive_callback(self->client, &sfizz_lv2_receive_message);
|
sfizz_set_receive_callback(self->client, &sfizz_lv2_receive_message);
|
||||||
|
|
||||||
|
|
@ -617,6 +621,7 @@ static void
|
||||||
cleanup(LV2_Handle instance)
|
cleanup(LV2_Handle instance)
|
||||||
{
|
{
|
||||||
sfizz_plugin_t *self = (sfizz_plugin_t *)instance;
|
sfizz_plugin_t *self = (sfizz_plugin_t *)instance;
|
||||||
|
spin_mutex_destroy(self->synth_mutex);
|
||||||
sfizz_delete_client(self->client);
|
sfizz_delete_client(self->client);
|
||||||
sfizz_free(self->synth);
|
sfizz_free(self->synth);
|
||||||
free(self);
|
free(self);
|
||||||
|
|
@ -876,8 +881,14 @@ static void
|
||||||
run(LV2_Handle instance, uint32_t sample_count)
|
run(LV2_Handle instance, uint32_t sample_count)
|
||||||
{
|
{
|
||||||
sfizz_plugin_t *self = (sfizz_plugin_t *)instance;
|
sfizz_plugin_t *self = (sfizz_plugin_t *)instance;
|
||||||
if (!self->control_port || !self->notify_port)
|
assert(self->control_port && self->notify_port);
|
||||||
|
|
||||||
|
if (!spin_mutex_trylock(self->synth_mutex))
|
||||||
|
{
|
||||||
|
for (int channel = 0; channel < 2; ++channel)
|
||||||
|
memset(self->output_buffers[channel], 0, sample_count * sizeof(float));
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Set up forge to write directly to notify output port.
|
// Set up forge to write directly to notify output port.
|
||||||
const size_t notify_capacity = self->notify_port->atom.size;
|
const size_t notify_capacity = self->notify_port->atom.size;
|
||||||
|
|
@ -1048,6 +1059,8 @@ run(LV2_Handle instance, uint32_t sample_count)
|
||||||
// Render the block
|
// Render the block
|
||||||
sfizz_render_block(self->synth, self->output_buffers, 2, (int)sample_count);
|
sfizz_render_block(self->synth, self->output_buffers, 2, (int)sample_count);
|
||||||
|
|
||||||
|
spin_mutex_unlock(self->synth_mutex);
|
||||||
|
|
||||||
if (self->midnam && atomic_exchange(&self->must_update_midnam, 0))
|
if (self->midnam && atomic_exchange(&self->must_update_midnam, 0))
|
||||||
{
|
{
|
||||||
self->midnam->update(self->midnam->handle);
|
self->midnam->update(self->midnam->handle);
|
||||||
|
|
@ -1099,7 +1112,9 @@ lv2_set_options(LV2_Handle instance, const LV2_Options_Option *options)
|
||||||
if (opt->key == self->sample_rate_uri)
|
if (opt->key == self->sample_rate_uri)
|
||||||
{
|
{
|
||||||
sfizz_lv2_parse_sample_rate(self, opt);
|
sfizz_lv2_parse_sample_rate(self, opt);
|
||||||
|
spin_mutex_lock(self->synth_mutex);
|
||||||
sfizz_set_sample_rate(self->synth, self->sample_rate);
|
sfizz_set_sample_rate(self->synth, self->sample_rate);
|
||||||
|
spin_mutex_unlock(self->synth_mutex);
|
||||||
}
|
}
|
||||||
else if (!self->expect_nominal_block_length && opt->key == self->max_block_length_uri)
|
else if (!self->expect_nominal_block_length && opt->key == self->max_block_length_uri)
|
||||||
{
|
{
|
||||||
|
|
@ -1109,7 +1124,9 @@ lv2_set_options(LV2_Handle instance, const LV2_Options_Option *options)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
self->max_block_size = *(int *)opt->value;
|
self->max_block_size = *(int *)opt->value;
|
||||||
|
spin_mutex_lock(self->synth_mutex);
|
||||||
sfizz_set_samples_per_block(self->synth, self->max_block_size);
|
sfizz_set_samples_per_block(self->synth, self->max_block_size);
|
||||||
|
spin_mutex_unlock(self->synth_mutex);
|
||||||
}
|
}
|
||||||
else if (opt->key == self->nominal_block_length_uri)
|
else if (opt->key == self->nominal_block_length_uri)
|
||||||
{
|
{
|
||||||
|
|
@ -1119,7 +1136,9 @@ lv2_set_options(LV2_Handle instance, const LV2_Options_Option *options)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
self->max_block_size = *(int *)opt->value;
|
self->max_block_size = *(int *)opt->value;
|
||||||
|
spin_mutex_lock(self->synth_mutex);
|
||||||
sfizz_set_samples_per_block(self->synth, self->max_block_size);
|
sfizz_set_samples_per_block(self->synth, self->max_block_size);
|
||||||
|
spin_mutex_unlock(self->synth_mutex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return LV2_OPTIONS_SUCCESS;
|
return LV2_OPTIONS_SUCCESS;
|
||||||
|
|
@ -1263,6 +1282,7 @@ restore(LV2_Handle instance,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync the parameters to the synth
|
// Sync the parameters to the synth
|
||||||
|
spin_mutex_lock(self->synth_mutex);
|
||||||
|
|
||||||
// Load an empty file to remove the default sine, and then the new file.
|
// Load an empty file to remove the default sine, and then the new file.
|
||||||
sfizz_load_string(self->synth, "empty.sfz", "");
|
sfizz_load_string(self->synth, "empty.sfz", "");
|
||||||
|
|
@ -1299,6 +1319,8 @@ restore(LV2_Handle instance,
|
||||||
lv2_log_note(&self->logger, "[sfizz] Restoring the oversampling to %d\n", self->oversampling);
|
lv2_log_note(&self->logger, "[sfizz] Restoring the oversampling to %d\n", self->oversampling);
|
||||||
sfizz_set_oversampling_factor(self->synth, self->oversampling);
|
sfizz_set_oversampling_factor(self->synth, self->oversampling);
|
||||||
|
|
||||||
|
spin_mutex_unlock(self->synth_mutex);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1419,7 +1441,12 @@ work(LV2_Handle instance,
|
||||||
if (atom->type == self->sfizz_sfz_file_uri)
|
if (atom->type == self->sfizz_sfz_file_uri)
|
||||||
{
|
{
|
||||||
const char *sfz_file_path = LV2_ATOM_BODY_CONST(atom);
|
const char *sfz_file_path = LV2_ATOM_BODY_CONST(atom);
|
||||||
if (!sfizz_lv2_load_file(self, sfz_file_path)) {
|
|
||||||
|
spin_mutex_lock(self->synth_mutex);
|
||||||
|
bool success = sfizz_lv2_load_file(self, sfz_file_path);
|
||||||
|
spin_mutex_unlock(self->synth_mutex);
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
lv2_log_error(&self->logger,
|
lv2_log_error(&self->logger,
|
||||||
"[sfizz] Error with %s; no file should be loaded\n", sfz_file_path);
|
"[sfizz] Error with %s; no file should be loaded\n", sfz_file_path);
|
||||||
}
|
}
|
||||||
|
|
@ -1430,7 +1457,12 @@ work(LV2_Handle instance,
|
||||||
else if (atom->type == self->sfizz_scala_file_uri)
|
else if (atom->type == self->sfizz_scala_file_uri)
|
||||||
{
|
{
|
||||||
const char *scala_file_path = LV2_ATOM_BODY_CONST(atom);
|
const char *scala_file_path = LV2_ATOM_BODY_CONST(atom);
|
||||||
if (sfizz_lv2_load_scala_file(self, scala_file_path)) {
|
|
||||||
|
spin_mutex_lock(self->synth_mutex);
|
||||||
|
bool success = sfizz_lv2_load_scala_file(self, scala_file_path);
|
||||||
|
spin_mutex_unlock(self->synth_mutex);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
lv2_log_note(&self->logger, "[sfizz] Scala file loaded: %s\n", scala_file_path);
|
lv2_log_note(&self->logger, "[sfizz] Scala file loaded: %s\n", scala_file_path);
|
||||||
} else {
|
} else {
|
||||||
lv2_log_error(&self->logger,
|
lv2_log_error(&self->logger,
|
||||||
|
|
@ -1443,7 +1475,11 @@ work(LV2_Handle instance,
|
||||||
else if (atom->type == self->sfizz_num_voices_uri)
|
else if (atom->type == self->sfizz_num_voices_uri)
|
||||||
{
|
{
|
||||||
const int num_voices = *(const int *)LV2_ATOM_BODY_CONST(atom);
|
const int num_voices = *(const int *)LV2_ATOM_BODY_CONST(atom);
|
||||||
|
|
||||||
|
spin_mutex_lock(self->synth_mutex);
|
||||||
sfizz_set_num_voices(self->synth, num_voices);
|
sfizz_set_num_voices(self->synth, num_voices);
|
||||||
|
spin_mutex_unlock(self->synth_mutex);
|
||||||
|
|
||||||
if (sfizz_get_num_voices(self->synth) == num_voices) {
|
if (sfizz_get_num_voices(self->synth) == num_voices) {
|
||||||
lv2_log_note(&self->logger, "[sfizz] Number of voices changed to: %d\n", num_voices);
|
lv2_log_note(&self->logger, "[sfizz] Number of voices changed to: %d\n", num_voices);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1453,7 +1489,11 @@ work(LV2_Handle instance,
|
||||||
else if (atom->type == self->sfizz_preload_size_uri)
|
else if (atom->type == self->sfizz_preload_size_uri)
|
||||||
{
|
{
|
||||||
const unsigned int preload_size = *(const unsigned int *)LV2_ATOM_BODY_CONST(atom);
|
const unsigned int preload_size = *(const unsigned int *)LV2_ATOM_BODY_CONST(atom);
|
||||||
|
|
||||||
|
spin_mutex_lock(self->synth_mutex);
|
||||||
sfizz_set_preload_size(self->synth, preload_size);
|
sfizz_set_preload_size(self->synth, preload_size);
|
||||||
|
spin_mutex_unlock(self->synth_mutex);
|
||||||
|
|
||||||
if (sfizz_get_preload_size(self->synth) == preload_size) {
|
if (sfizz_get_preload_size(self->synth) == preload_size) {
|
||||||
lv2_log_note(&self->logger, "[sfizz] Preload size changed to: %d\n", preload_size);
|
lv2_log_note(&self->logger, "[sfizz] Preload size changed to: %d\n", preload_size);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1464,7 +1504,11 @@ work(LV2_Handle instance,
|
||||||
{
|
{
|
||||||
const sfizz_oversampling_factor_t oversampling =
|
const sfizz_oversampling_factor_t oversampling =
|
||||||
*(const sfizz_oversampling_factor_t *)LV2_ATOM_BODY_CONST(atom);
|
*(const sfizz_oversampling_factor_t *)LV2_ATOM_BODY_CONST(atom);
|
||||||
|
|
||||||
|
spin_mutex_lock(self->synth_mutex);
|
||||||
sfizz_set_oversampling_factor(self->synth, oversampling);
|
sfizz_set_oversampling_factor(self->synth, oversampling);
|
||||||
|
spin_mutex_unlock(self->synth_mutex);
|
||||||
|
|
||||||
if (sfizz_get_oversampling_factor(self->synth) == oversampling) {
|
if (sfizz_get_oversampling_factor(self->synth) == oversampling) {
|
||||||
lv2_log_note(&self->logger, "[sfizz] Oversampling changed to: %d\n", oversampling);
|
lv2_log_note(&self->logger, "[sfizz] Oversampling changed to: %d\n", oversampling);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1482,7 +1526,12 @@ work(LV2_Handle instance,
|
||||||
lv2_log_note(&self->logger,
|
lv2_log_note(&self->logger,
|
||||||
"[sfizz] File %s seems to have been updated, reloading\n",
|
"[sfizz] File %s seems to have been updated, reloading\n",
|
||||||
self->sfz_file_path);
|
self->sfz_file_path);
|
||||||
if (!sfizz_lv2_load_file(self, self->sfz_file_path)) {
|
|
||||||
|
spin_mutex_lock(self->synth_mutex);
|
||||||
|
bool success = sfizz_lv2_load_file(self, self->sfz_file_path);
|
||||||
|
spin_mutex_unlock(self->synth_mutex);
|
||||||
|
|
||||||
|
if (!success) {
|
||||||
lv2_log_error(&self->logger,
|
lv2_log_error(&self->logger,
|
||||||
"[sfizz] Error with %s; no file should be loaded\n", self->sfz_file_path);
|
"[sfizz] Error with %s; no file should be loaded\n", self->sfz_file_path);
|
||||||
}
|
}
|
||||||
|
|
@ -1493,7 +1542,12 @@ work(LV2_Handle instance,
|
||||||
lv2_log_note(&self->logger,
|
lv2_log_note(&self->logger,
|
||||||
"[sfizz] Scala file %s seems to have been updated, reloading\n",
|
"[sfizz] Scala file %s seems to have been updated, reloading\n",
|
||||||
self->scala_file_path);
|
self->scala_file_path);
|
||||||
if (sfizz_lv2_load_scala_file(self, self->scala_file_path)) {
|
|
||||||
|
spin_mutex_lock(self->synth_mutex);
|
||||||
|
bool success = sfizz_lv2_load_scala_file(self, self->scala_file_path);
|
||||||
|
spin_mutex_unlock(self->synth_mutex);
|
||||||
|
|
||||||
|
if (success) {
|
||||||
lv2_log_note(&self->logger, "[sfizz] Scala file loaded: %s\n", self->scala_file_path);
|
lv2_log_note(&self->logger, "[sfizz] Scala file loaded: %s\n", self->scala_file_path);
|
||||||
} else {
|
} else {
|
||||||
lv2_log_error(&self->logger,
|
lv2_log_error(&self->logger,
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue