aboutsummaryrefslogtreecommitdiffstats
path: root/src/jack.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/jack.c')
-rw-r--r--src/jack.c509
1 files changed, 226 insertions, 283 deletions
diff --git a/src/jack.c b/src/jack.c
index de8517a..6228dfb 100644
--- a/src/jack.c
+++ b/src/jack.c
@@ -1,21 +1,25 @@
-// Copyright 2007-2022 David Robillard <d@drobilla.net>
+// Copyright 2007-2024 David Robillard <d@drobilla.net>
// SPDX-License-Identifier: ISC
#include "backend.h"
-#include "frontend.h"
+#include "comm.h"
+#include "jack_impl.h"
#include "jalv_config.h"
-#include "jalv_internal.h"
#include "log.h"
#include "lv2_evbuf.h"
-#include "port.h"
+#include "process.h"
+#include "process_setup.h"
+#include "settings.h"
+#include "string_utils.h"
#include "types.h"
+#include "urids.h"
-#include "lilv/lilv.h"
-#include "lv2/atom/atom.h"
-#include "lv2/atom/forge.h"
-#include "lv2/urid/urid.h"
-#include "zix/sem.h"
+#include <lilv/lilv.h>
+#include <lv2/atom/atom.h>
+#include <lv2/atom/forge.h>
+#include <lv2/urid/urid.h>
+#include <zix/sem.h>
#include <jack/jack.h>
#include <jack/midiport.h>
@@ -26,7 +30,6 @@
# include <jack/metadata.h>
#endif
-#include <ctype.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
@@ -39,147 +42,145 @@
# define REALTIME
#endif
-struct JalvBackendImpl {
- jack_client_t* client; ///< Jack client
- bool is_internal_client; ///< Running inside jackd
-};
-
-/// Internal Jack client initialization entry point
-int
-jack_initialize(jack_client_t* client, const char* load_init);
-
-/// Internal Jack client finalization entry point
-void
-jack_finish(void* arg);
+/// Maximum supported latency in frames (at most 2^24 so all integers work)
+static const float max_latency = 16777216.0f;
/// Jack buffer size callback
static int
-jack_buffer_size_cb(jack_nframes_t nframes, void* data)
+buffer_size_cb(jack_nframes_t nframes, void* data)
{
- Jalv* const jalv = (Jalv*)data;
- jalv->block_length = nframes;
- jalv->buf_size_set = true;
+ JalvBackend* const backend = (JalvBackend*)data;
+ JalvSettings* const settings = backend->settings;
+ JalvProcess* const proc = backend->process;
+
+ settings->block_length = nframes;
#if USE_JACK_PORT_TYPE_GET_BUFFER_SIZE
- jalv->midi_buf_size = jack_port_type_get_buffer_size(jalv->backend->client,
- JACK_DEFAULT_MIDI_TYPE);
+ settings->midi_buf_size =
+ jack_port_type_get_buffer_size(backend->client, JACK_DEFAULT_MIDI_TYPE);
#endif
- jalv_allocate_port_buffers(jalv);
+ if (proc->run_state == JALV_RUNNING) {
+ jalv_process_activate(proc, backend->urids, proc->instance, settings);
+ }
return 0;
}
/// Jack shutdown callback
static void
-jack_shutdown_cb(void* data)
+shutdown_cb(void* data)
{
- Jalv* const jalv = (Jalv*)data;
- jalv_frontend_close(jalv);
- zix_sem_post(&jalv->done);
+ JalvBackend* const backend = (JalvBackend*)data;
+ zix_sem_post(backend->done);
}
-/// Jack process callback
-static REALTIME int
-jack_process_cb(jack_nframes_t nframes, void* data)
+static void
+forge_position(LV2_Atom_Forge* const forge,
+ const JalvURIDs* const urids,
+ const jack_transport_state_t state,
+ const jack_position_t pos)
{
- Jalv* const jalv = (Jalv*)data;
- jack_client_t* client = jalv->backend->client;
+ LV2_Atom_Forge_Frame frame;
+ lv2_atom_forge_object(forge, &frame, 0, urids->time_Position);
+ lv2_atom_forge_key(forge, urids->time_frame);
+ lv2_atom_forge_long(forge, pos.frame);
+ lv2_atom_forge_key(forge, urids->time_speed);
+ lv2_atom_forge_float(forge, (state == JackTransportRolling) ? 1.0 : 0.0);
+ if ((pos.valid & JackPositionBBT)) {
+ lv2_atom_forge_key(forge, urids->time_barBeat);
+ lv2_atom_forge_float(forge, pos.beat - 1 + (pos.tick / pos.ticks_per_beat));
+ lv2_atom_forge_key(forge, urids->time_bar);
+ lv2_atom_forge_long(forge, pos.bar - 1);
+ lv2_atom_forge_key(forge, urids->time_beatUnit);
+ lv2_atom_forge_int(forge, pos.beat_type);
+ lv2_atom_forge_key(forge, urids->time_beatsPerBar);
+ lv2_atom_forge_float(forge, pos.beats_per_bar);
+ lv2_atom_forge_key(forge, urids->time_beatsPerMinute);
+ lv2_atom_forge_float(forge, pos.beats_per_minute);
+ }
+}
- // Get Jack transport position
- jack_position_t pos;
- const bool rolling =
- (jack_transport_query(client, &pos) == JackTransportRolling);
+static int
+process_silent(JalvProcess* const proc, const jack_nframes_t nframes)
+{
+ for (uint32_t p = 0U; p < proc->num_ports; ++p) {
+ const JalvProcessPort* const port = &proc->ports[p];
+ jack_port_t* const jport = (jack_port_t*)proc->ports[p].sys_port;
+ if (jport && port->flow == FLOW_OUTPUT) {
+ void* const buf = jack_port_get_buffer(jport, nframes);
+ if (port->type == TYPE_EVENT) {
+ jack_midi_clear_buffer(buf);
+ } else {
+ memset(buf, '\0', nframes * sizeof(float));
+ }
+ }
+ }
+ return jalv_bypass(proc, nframes);
+}
+
+static bool
+process_transport(JalvProcess* const proc,
+ const jack_transport_state_t state,
+ const jack_position_t pos,
+ const jack_nframes_t nframes)
+{
// If transport state is not as expected, then something has changed
+ const bool rolling = state == JackTransportRolling;
const bool has_bbt = (pos.valid & JackPositionBBT);
const bool xport_changed =
- (rolling != jalv->rolling || pos.frame != jalv->position ||
- (has_bbt && pos.beats_per_minute != jalv->bpm));
+ (rolling != proc->rolling || pos.frame != proc->position ||
+ (has_bbt && pos.beats_per_minute != proc->bpm));
- uint8_t pos_buf[256];
- LV2_Atom* lv2_pos = (LV2_Atom*)pos_buf;
- if (xport_changed) {
- // Build an LV2 position object to report change to plugin
- lv2_atom_forge_set_buffer(&jalv->forge, pos_buf, sizeof(pos_buf));
- LV2_Atom_Forge* forge = &jalv->forge;
- LV2_Atom_Forge_Frame frame;
- lv2_atom_forge_object(forge, &frame, 0, jalv->urids.time_Position);
- lv2_atom_forge_key(forge, jalv->urids.time_frame);
- lv2_atom_forge_long(forge, pos.frame);
- lv2_atom_forge_key(forge, jalv->urids.time_speed);
- lv2_atom_forge_float(forge, rolling ? 1.0 : 0.0);
- if (has_bbt) {
- lv2_atom_forge_key(forge, jalv->urids.time_barBeat);
- lv2_atom_forge_float(forge,
- pos.beat - 1 + (pos.tick / pos.ticks_per_beat));
- lv2_atom_forge_key(forge, jalv->urids.time_bar);
- lv2_atom_forge_long(forge, pos.bar - 1);
- lv2_atom_forge_key(forge, jalv->urids.time_beatUnit);
- lv2_atom_forge_int(forge, pos.beat_type);
- lv2_atom_forge_key(forge, jalv->urids.time_beatsPerBar);
- lv2_atom_forge_float(forge, pos.beats_per_bar);
- lv2_atom_forge_key(forge, jalv->urids.time_beatsPerMinute);
- lv2_atom_forge_float(forge, pos.beats_per_minute);
- }
+ // Update transport state to expected values for next cycle
+ proc->position = rolling ? pos.frame + nframes : pos.frame;
+ proc->bpm = has_bbt ? pos.beats_per_minute : proc->bpm;
+ proc->rolling = rolling;
+
+ return xport_changed;
+}
- jalv_dump_atom(jalv, stdout, "Position", lv2_pos, 32);
+/// Jack process callback
+static REALTIME int
+process_cb(jack_nframes_t nframes, void* data)
+{
+ JalvBackend* const backend = (JalvBackend*)data;
+ const JalvURIDs* const urids = backend->urids;
+ JalvProcess* const proc = backend->process;
+ jack_client_t* const client = backend->client;
+ uint64_t pos_buf[64] = {0U};
+ LV2_Atom* const lv2_pos = (LV2_Atom*)pos_buf;
+
+ // If execution is paused, emit silence and return
+ if (proc->run_state == JALV_PAUSED) {
+ return process_silent(proc, nframes);
}
- // Update transport state to expected values for next cycle
- jalv->position = rolling ? pos.frame + nframes : pos.frame;
- jalv->bpm = has_bbt ? pos.beats_per_minute : jalv->bpm;
- jalv->rolling = rolling;
-
- switch (jalv->play_state) {
- case JALV_PAUSE_REQUESTED:
- jalv->play_state = JALV_PAUSED;
- zix_sem_post(&jalv->paused);
- break;
- case JALV_PAUSED:
- for (uint32_t p = 0; p < jalv->num_ports; ++p) {
- jack_port_t* jport = jalv->ports[p].sys_port;
- if (jport && jalv->ports[p].flow == FLOW_OUTPUT) {
- void* buf = jack_port_get_buffer(jport, nframes);
- if (jalv->ports[p].type == TYPE_EVENT) {
- jack_midi_clear_buffer(buf);
- } else {
- memset(buf, '\0', nframes * sizeof(float));
- }
- }
- }
- return 0;
- default:
- break;
+ // Get transport state and position
+ jack_position_t pos = {0U};
+ const jack_transport_state_t state = jack_transport_query(client, &pos);
+
+ // Check if transport is discontinuous from last time and update state
+ const bool xport_changed = process_transport(proc, state, pos, nframes);
+ if (xport_changed) {
+ // Build an LV2 position object to report change to plugin
+ lv2_atom_forge_set_buffer(&proc->forge, (uint8_t*)pos_buf, sizeof(pos_buf));
+ forge_position(&proc->forge, urids, state, pos);
}
// Prepare port buffers
- for (uint32_t p = 0; p < jalv->num_ports; ++p) {
- struct Port* port = &jalv->ports[p];
- if (port->type == TYPE_AUDIO && port->sys_port) {
- // Connect plugin port directly to Jack port buffer
- lilv_instance_connect_port(
- jalv->instance, p, jack_port_get_buffer(port->sys_port, nframes));
-#if USE_JACK_METADATA
- } else if (port->type == TYPE_CV && port->sys_port) {
+ for (uint32_t p = 0; p < proc->num_ports; ++p) {
+ JalvProcessPort* const port = &proc->ports[p];
+ if (port->sys_port && (port->type == TYPE_AUDIO || port->type == TYPE_CV)) {
// Connect plugin port directly to Jack port buffer
lilv_instance_connect_port(
- jalv->instance, p, jack_port_get_buffer(port->sys_port, nframes));
-#endif
+ proc->instance, p, jack_port_get_buffer(port->sys_port, nframes));
} else if (port->type == TYPE_EVENT && port->flow == FLOW_INPUT) {
lv2_evbuf_reset(port->evbuf, true);
-
- // Write transport change event if applicable
LV2_Evbuf_Iterator iter = lv2_evbuf_begin(port->evbuf);
- if (xport_changed) {
- lv2_evbuf_write(
- &iter, 0, 0, lv2_pos->type, lv2_pos->size, LV2_ATOM_BODY(lv2_pos));
- }
- if (jalv->request_update) {
- // Plugin state has changed, request an update
- const LV2_Atom_Object get = {
- {sizeof(LV2_Atom_Object_Body), jalv->urids.atom_Object},
- {0, jalv->urids.patch_Get}};
+ if (port->is_primary && xport_changed) {
+ // Write new transport position
lv2_evbuf_write(
- &iter, 0, 0, get.atom.type, get.atom.size, LV2_ATOM_BODY_CONST(&get));
+ &iter, 0, 0, lv2_pos->type, lv2_pos->size, LV2_ATOM_BODY(lv2_pos));
}
if (port->sys_port) {
@@ -189,7 +190,7 @@ jack_process_cb(jack_nframes_t nframes, void* data)
jack_midi_event_t ev;
jack_midi_event_get(&ev, buf, i);
lv2_evbuf_write(
- &iter, ev.time, 0, jalv->urids.midi_MidiEvent, ev.size, ev.buffer);
+ &iter, ev.time, 0, urids->midi_MidiEvent, ev.size, ev.buffer);
}
}
} else if (port->type == TYPE_EVENT) {
@@ -197,20 +198,28 @@ jack_process_cb(jack_nframes_t nframes, void* data)
lv2_evbuf_reset(port->evbuf, false);
}
}
- jalv->request_update = false;
// Run plugin for this cycle
- const bool send_ui_updates = jalv_run(jalv, nframes);
+ const bool send_ui_updates = jalv_run(proc, nframes);
// Deliver MIDI output and UI events
- for (uint32_t p = 0; p < jalv->num_ports; ++p) {
- struct Port* const port = &jalv->ports[p];
+ for (uint32_t p = 0; p < proc->num_ports; ++p) {
+ JalvProcessPort* const port = &proc->ports[p];
if (port->flow == FLOW_OUTPUT && port->type == TYPE_CONTROL &&
- lilv_port_has_property(
- jalv->plugin, port->lilv_port, jalv->nodes.lv2_reportsLatency)) {
- if (jalv->plugin_latency != port->control) {
- jalv->plugin_latency = port->control;
- jack_recompute_total_latencies(client);
+ port->reports_latency) {
+ // Get the latency in frames from the control output truncated to integer
+ const float value = proc->controls_buf[p];
+ const uint32_t frames =
+ (value >= 0.0f && value <= max_latency) ? (uint32_t)value : 0U;
+
+ if (proc->plugin_latency != frames) {
+ // Update the cached value and notify the UI if the latency changed
+ proc->plugin_latency = frames;
+
+ const JalvLatencyChange body = {frames};
+ const JalvMessageHeader header = {LATENCY_CHANGE, sizeof(body)};
+ jalv_write_split_message(
+ proc->plugin_to_ui, &header, sizeof(header), &body, sizeof(body));
}
} else if (port->flow == FLOW_OUTPUT && port->type == TYPE_EVENT) {
void* buf = NULL;
@@ -230,38 +239,41 @@ jack_process_cb(jack_nframes_t nframes, void* data)
void* body = NULL;
lv2_evbuf_get(i, &frames, &subframes, &type, &size, &body);
- if (buf && type == jalv->urids.midi_MidiEvent) {
+ if (buf && type == urids->midi_MidiEvent) {
// Write MIDI event to Jack output
jack_midi_event_write(buf, frames, body, size);
}
- if (jalv->has_ui) {
+ if (proc->has_ui) {
// Forward event to UI
- jalv_write_event(jalv, jalv->plugin_to_ui, p, size, type, body);
+ jalv_write_event(proc->plugin_to_ui, p, size, type, body);
}
}
} else if (send_ui_updates && port->flow == FLOW_OUTPUT &&
port->type == TYPE_CONTROL) {
- jalv_write_control(jalv, jalv->plugin_to_ui, p, port->control);
+ jalv_write_control(proc->plugin_to_ui, p, proc->controls_buf[p]);
}
}
return 0;
}
-/// Calculate latency assuming all ports depend on each other
+/// Jack latency callback
static void
-jack_latency_cb(jack_latency_callback_mode_t mode, void* data)
+latency_cb(const jack_latency_callback_mode_t mode, void* const data)
{
- Jalv* const jalv = (Jalv*)data;
- const enum PortFlow flow =
+ // Calculate latency assuming all ports depend on each other
+
+ const JalvBackend* const backend = (JalvBackend*)data;
+ const JalvProcess* const proc = backend->process;
+ const PortFlow flow =
((mode == JackCaptureLatency) ? FLOW_INPUT : FLOW_OUTPUT);
// First calculate the min/max latency of all feeding ports
uint32_t ports_found = 0;
jack_latency_range_t range = {UINT32_MAX, 0};
- for (uint32_t p = 0; p < jalv->num_ports; ++p) {
- struct Port* port = &jalv->ports[p];
+ for (uint32_t p = 0; p < proc->num_ports; ++p) {
+ JalvProcessPort* const port = &proc->ports[p];
if (port->sys_port && port->flow == flow) {
jack_latency_range_t r;
jack_port_get_latency_range(port->sys_port, mode, &r);
@@ -280,12 +292,12 @@ jack_latency_cb(jack_latency_callback_mode_t mode, void* data)
}
// Add the plugin's own latency
- range.min += jalv->plugin_latency;
- range.max += jalv->plugin_latency;
+ range.min += proc->plugin_latency;
+ range.max += proc->plugin_latency;
// Tell Jack about it
- for (uint32_t p = 0; p < jalv->num_ports; ++p) {
- struct Port* port = &jalv->ports[p];
+ for (uint32_t p = 0; p < proc->num_ports; ++p) {
+ const JalvProcessPort* const port = &proc->ports[p];
if (port->sys_port && port->flow == flow) {
jack_port_set_latency_range(port->sys_port, mode, &range);
}
@@ -293,21 +305,9 @@ jack_latency_cb(jack_latency_callback_mode_t mode, void* data)
}
static jack_client_t*
-jack_create_client(Jalv* jalv)
+create_client(const char* const name, const bool exact_name)
{
- jack_client_t* client = NULL;
-
- // Determine the name of the JACK client
- char* jack_name = NULL;
- if (jalv->opts.name) {
- // Name given on command line
- jack_name = jalv_strdup(jalv->opts.name);
- } else {
- // Use plugin name
- LilvNode* name = lilv_plugin_get_name(jalv->plugin);
- jack_name = jalv_strdup(lilv_node_as_string(name));
- lilv_node_free(name);
- }
+ char* const jack_name = jalv_strdup(name);
// Truncate client name to suit JACK if necessary
if (strlen(jack_name) >= (unsigned)jack_client_name_size() - 1) {
@@ -315,12 +315,8 @@ jack_create_client(Jalv* jalv)
}
// Connect to JACK
- if (!client) {
- client = jack_client_open(
- jack_name,
- (jalv->opts.name_exact ? JackUseExactName : JackNullOption),
- NULL);
- }
+ jack_client_t* const client = jack_client_open(
+ jack_name, (exact_name ? JackUseExactName : JackNullOption), NULL);
free(jack_name);
@@ -328,84 +324,93 @@ jack_create_client(Jalv* jalv)
}
JalvBackend*
-jalv_backend_init(Jalv* jalv)
+jalv_backend_allocate(void)
+{
+ return (JalvBackend*)calloc(1, sizeof(JalvBackend));
+}
+
+void
+jalv_backend_free(JalvBackend* const backend)
+{
+ free(backend);
+}
+
+int
+jalv_backend_open(JalvBackend* const backend,
+ const JalvURIDs* const urids,
+ JalvSettings* const settings,
+ JalvProcess* const process,
+ ZixSem* const done,
+ const char* const name,
+ const bool exact_name)
{
jack_client_t* const client =
- jalv->backend ? jalv->backend->client : jack_create_client(jalv);
+ backend->client ? backend->client : create_client(name, exact_name);
if (!client) {
- return NULL;
+ return 1;
}
- jalv_log(JALV_LOG_INFO, "JACK Name: %s\n", jack_get_client_name(client));
+ jalv_log(JALV_LOG_INFO, "JACK name: %s\n", jack_get_client_name(client));
// Set audio engine properties
- jalv->sample_rate = (float)jack_get_sample_rate(client);
- jalv->block_length = jack_get_buffer_size(client);
- jalv->midi_buf_size = 4096;
+ settings->sample_rate = (float)jack_get_sample_rate(client);
+ settings->block_length = jack_get_buffer_size(client);
+ settings->midi_buf_size = 4096;
#if USE_JACK_PORT_TYPE_GET_BUFFER_SIZE
- jalv->midi_buf_size =
+ settings->midi_buf_size =
jack_port_type_get_buffer_size(client, JACK_DEFAULT_MIDI_TYPE);
#endif
// Set JACK callbacks
- void* const arg = (void*)jalv;
- jack_set_process_callback(client, &jack_process_cb, arg);
- jack_set_buffer_size_callback(client, &jack_buffer_size_cb, arg);
- jack_on_shutdown(client, &jack_shutdown_cb, arg);
- jack_set_latency_callback(client, &jack_latency_cb, arg);
-
- if (jalv->backend) {
- /* Internal JACK client, jalv->backend->is_internal_client was already set
- in jack_initialize() when allocating the backend. */
- return jalv->backend;
- }
-
- // External JACK client, allocate and return opaque backend
- JalvBackend* backend = (JalvBackend*)calloc(1, sizeof(JalvBackend));
+ void* const arg = (void*)backend;
+ jack_set_process_callback(client, &process_cb, arg);
+ jack_set_buffer_size_callback(client, &buffer_size_cb, arg);
+ jack_on_shutdown(client, &shutdown_cb, arg);
+ jack_set_latency_callback(client, &latency_cb, arg);
+
+ backend->urids = urids;
+ backend->settings = settings;
+ backend->process = process;
+ backend->done = done;
backend->client = client;
backend->is_internal_client = false;
- return backend;
+ return 0;
}
void
-jalv_backend_close(Jalv* jalv)
+jalv_backend_close(JalvBackend* const backend)
{
- if (jalv->backend) {
- if (!jalv->backend->is_internal_client) {
- jack_client_close(jalv->backend->client);
- }
-
- free(jalv->backend);
- jalv->backend = NULL;
+ if (backend && backend->client && !backend->is_internal_client) {
+ jack_client_close(backend->client);
}
}
void
-jalv_backend_activate(Jalv* jalv)
+jalv_backend_activate(JalvBackend* const backend)
{
- jack_activate(jalv->backend->client);
+ jack_activate(backend->client);
}
void
-jalv_backend_deactivate(Jalv* jalv)
+jalv_backend_deactivate(JalvBackend* const backend)
{
- if (jalv->backend && !jalv->backend->is_internal_client) {
- jack_deactivate(jalv->backend->client);
+ if (!backend->is_internal_client && backend->client) {
+ jack_deactivate(backend->client);
}
}
void
-jalv_backend_activate_port(Jalv* jalv, uint32_t port_index)
+jalv_backend_activate_port(JalvBackend* const backend,
+ JalvProcess* const proc,
+ const uint32_t port_index)
{
- jack_client_t* client = jalv->backend->client;
- struct Port* const port = &jalv->ports[port_index];
-
- const LilvNode* sym = lilv_port_get_symbol(jalv->plugin, port->lilv_port);
+ jack_client_t* const client = backend->client;
+ JalvProcessPort* const port = &proc->ports[port_index];
// Connect unsupported ports to NULL (known to be optional by this point)
if (port->flow == FLOW_UNKNOWN || port->type == TYPE_UNKNOWN) {
- lilv_instance_connect_port(jalv->instance, port_index, NULL);
+ lilv_instance_connect_port(proc->instance, port_index, NULL);
return;
}
@@ -415,17 +420,20 @@ jalv_backend_activate_port(Jalv* jalv, uint32_t port_index)
// Connect the port based on its type
switch (port->type) {
+ case TYPE_UNKNOWN:
+ break;
case TYPE_CONTROL:
- lilv_instance_connect_port(jalv->instance, port_index, &port->control);
+ lilv_instance_connect_port(
+ proc->instance, port_index, &proc->controls_buf[port_index]);
break;
case TYPE_AUDIO:
port->sys_port = jack_port_register(
- client, lilv_node_as_string(sym), JACK_DEFAULT_AUDIO_TYPE, jack_flags, 0);
+ client, port->symbol, JACK_DEFAULT_AUDIO_TYPE, jack_flags, 0);
break;
#if USE_JACK_METADATA
case TYPE_CV:
port->sys_port = jack_port_register(
- client, lilv_node_as_string(sym), JACK_DEFAULT_AUDIO_TYPE, jack_flags, 0);
+ client, port->symbol, JACK_DEFAULT_AUDIO_TYPE, jack_flags, 0);
if (port->sys_port) {
jack_set_property(client,
jack_port_uuid(port->sys_port),
@@ -436,17 +444,11 @@ jalv_backend_activate_port(Jalv* jalv, uint32_t port_index)
break;
#endif
case TYPE_EVENT:
- if (lilv_port_supports_event(
- jalv->plugin, port->lilv_port, jalv->nodes.midi_MidiEvent)) {
- port->sys_port = jack_port_register(client,
- lilv_node_as_string(sym),
- JACK_DEFAULT_MIDI_TYPE,
- jack_flags,
- 0);
+ if (port->supports_midi) {
+ port->sys_port = jack_port_register(
+ client, port->symbol, JACK_DEFAULT_MIDI_TYPE, jack_flags, 0);
}
break;
- default:
- break;
}
#if USE_JACK_METADATA
@@ -461,78 +463,19 @@ jalv_backend_activate_port(Jalv* jalv, uint32_t port_index)
"http://www.w3.org/2001/XMLSchema#integer");
// Set port pretty name to label
- LilvNode* name = lilv_port_get_name(jalv->plugin, port->lilv_port);
- jack_set_property(client,
- jack_port_uuid(port->sys_port),
- JACK_METADATA_PRETTY_NAME,
- lilv_node_as_string(name),
- "text/plain");
- lilv_node_free(name);
- }
-#endif
-}
-
-int
-jack_initialize(jack_client_t* const client, const char* const load_init)
-{
- const size_t args_len = strlen(load_init);
- if (args_len > JACK_LOAD_INIT_LIMIT) {
- jalv_log(JALV_LOG_ERR, "Too many arguments given\n");
- return -1;
- }
-
- Jalv* const jalv = (Jalv*)calloc(1, sizeof(Jalv));
- if (!jalv) {
- return -1;
- }
-
- if (!(jalv->backend = (JalvBackend*)calloc(1, sizeof(JalvBackend)))) {
- free(jalv);
- return -1;
- }
-
- jalv->backend->client = client;
- jalv->backend->is_internal_client = true;
-
- // Build full command line with "program" name for building argv
- const size_t cmd_len = strlen("jalv ") + args_len;
- char* const cmd = (char*)calloc(cmd_len + 1, 1);
- memcpy(cmd, "jalv ", strlen("jalv ") + 1);
- memcpy(cmd + 5, load_init, args_len + 1);
-
- // Build argv
- int argc = 0;
- char** argv = NULL;
- char* tok = cmd;
- for (size_t i = 0; i <= cmd_len; ++i) {
- if (isspace(cmd[i]) || !cmd[i]) {
- argv = (char**)realloc(argv, sizeof(char*) * ++argc);
- cmd[i] = '\0';
- argv[argc - 1] = tok;
- tok = cmd + i + 1;
+ if (port->label) {
+ jack_set_property(client,
+ jack_port_uuid(port->sys_port),
+ JACK_METADATA_PRETTY_NAME,
+ port->label,
+ "text/plain");
}
}
-
- const int err = jalv_open(jalv, &argc, &argv);
- if (err) {
- jalv_backend_close(jalv);
- free(jalv);
- }
-
- free(argv);
- free(cmd);
- return err;
+#endif
}
void
-jack_finish(void* const arg)
+jalv_backend_recompute_latencies(JalvBackend* const backend)
{
- Jalv* const jalv = (Jalv*)arg;
- if (jalv) {
- if (jalv_close(jalv)) {
- jalv_log(JALV_LOG_ERR, "Failed to close Jalv\n");
- }
-
- free(jalv);
- }
+ jack_recompute_total_latencies(backend->client);
}