1 /*
2 Copyright 2007-2016 David Robillard <d@drobilla.net>
3
4 Permission to use, copy, modify, and/or distribute this software for any
5 purpose with or without fee is hereby granted, provided that the above
6 copyright notice and this permission notice appear in all copies.
7
8 THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include "jalv_config.h"
18 #include "jalv_internal.h"
19 #include "lv2_evbuf.h"
20
21 #include "lilv/lilv.h"
22 #include "lv2/atom/atom.h"
23 #include "lv2/atom/forge.h"
24 #include "sratom/sratom.h"
25 #include "zix/ring.h"
26 #include "zix/sem.h"
27
28 #include <jack/jack.h>
29 #include <jack/midiport.h>
30 #include <jack/transport.h>
31 #include <jack/types.h>
32
33 #ifdef HAVE_JACK_METADATA
34 # include <jack/metadata.h>
35 #endif
36
37 #include <ctype.h>
38 #include <stdbool.h>
39 #include <stdint.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43
44 struct JalvBackend {
45 jack_client_t* client; ///< Jack client
46 bool is_internal_client; ///< Running inside jackd
47 };
48
49 /** Internal Jack client initialization entry point */
50 int jack_initialize(jack_client_t* client, const char* load_init);
51
52 /** Internal Jack client finalization entry point */
53 void jack_finish(void* arg);
54
55 /** Jack buffer size callback. */
56 static int
jack_buffer_size_cb(jack_nframes_t nframes,void * data)57 jack_buffer_size_cb(jack_nframes_t nframes, void* data)
58 {
59 Jalv* const jalv = (Jalv*)data;
60 jalv->block_length = nframes;
61 jalv->buf_size_set = true;
62 #ifdef HAVE_JACK_PORT_TYPE_GET_BUFFER_SIZE
63 jalv->midi_buf_size = jack_port_type_get_buffer_size(
64 jalv->backend->client, JACK_DEFAULT_MIDI_TYPE);
65 #endif
66 jalv_allocate_port_buffers(jalv);
67 return 0;
68 }
69
70 /** Jack shutdown callback. */
71 static void
jack_shutdown_cb(void * data)72 jack_shutdown_cb(void* data)
73 {
74 Jalv* const jalv = (Jalv*)data;
75 jalv_close_ui(jalv);
76 zix_sem_post(&jalv->done);
77 }
78
79 /** Jack process callback. */
80 static REALTIME int
jack_process_cb(jack_nframes_t nframes,void * data)81 jack_process_cb(jack_nframes_t nframes, void* data)
82 {
83 Jalv* const jalv = (Jalv*)data;
84 jack_client_t* client = jalv->backend->client;
85
86 /* Get Jack transport position */
87 jack_position_t pos;
88 const bool rolling = (jack_transport_query(client, &pos)
89 == JackTransportRolling);
90
91 /* If transport state is not as expected, then something has changed */
92 const bool xport_changed = (rolling != jalv->rolling ||
93 pos.frame != jalv->position ||
94 pos.beats_per_minute != jalv->bpm);
95
96 uint8_t pos_buf[256];
97 LV2_Atom* lv2_pos = (LV2_Atom*)pos_buf;
98 if (xport_changed) {
99 /* Build an LV2 position object to report change to plugin */
100 lv2_atom_forge_set_buffer(&jalv->forge, pos_buf, sizeof(pos_buf));
101 LV2_Atom_Forge* forge = &jalv->forge;
102 LV2_Atom_Forge_Frame frame;
103 lv2_atom_forge_object(forge, &frame, 0, jalv->urids.time_Position);
104 lv2_atom_forge_key(forge, jalv->urids.time_frame);
105 lv2_atom_forge_long(forge, pos.frame);
106 lv2_atom_forge_key(forge, jalv->urids.time_speed);
107 lv2_atom_forge_float(forge, rolling ? 1.0 : 0.0);
108 if (pos.valid & JackPositionBBT) {
109 lv2_atom_forge_key(forge, jalv->urids.time_barBeat);
110 lv2_atom_forge_float(
111 forge, pos.beat - 1 + (pos.tick / pos.ticks_per_beat));
112 lv2_atom_forge_key(forge, jalv->urids.time_bar);
113 lv2_atom_forge_long(forge, pos.bar - 1);
114 lv2_atom_forge_key(forge, jalv->urids.time_beatUnit);
115 lv2_atom_forge_int(forge, pos.beat_type);
116 lv2_atom_forge_key(forge, jalv->urids.time_beatsPerBar);
117 lv2_atom_forge_float(forge, pos.beats_per_bar);
118 lv2_atom_forge_key(forge, jalv->urids.time_beatsPerMinute);
119 lv2_atom_forge_float(forge, pos.beats_per_minute);
120 }
121
122 if (jalv->opts.dump) {
123 char* str = sratom_to_turtle(
124 jalv->sratom, &jalv->unmap, "time:", NULL, NULL,
125 lv2_pos->type, lv2_pos->size, LV2_ATOM_BODY(lv2_pos));
126 jalv_ansi_start(stdout, 36);
127 printf("\n## Position ##\n%s\n", str);
128 jalv_ansi_reset(stdout);
129 free(str);
130 }
131 }
132
133 /* Update transport state to expected values for next cycle */
134 jalv->position = rolling ? pos.frame + nframes : pos.frame;
135 jalv->bpm = pos.beats_per_minute;
136 jalv->rolling = rolling;
137
138 switch (jalv->play_state) {
139 case JALV_PAUSE_REQUESTED:
140 jalv->play_state = JALV_PAUSED;
141 zix_sem_post(&jalv->paused);
142 break;
143 case JALV_PAUSED:
144 for (uint32_t p = 0; p < jalv->num_ports; ++p) {
145 jack_port_t* jport = jalv->ports[p].sys_port;
146 if (jport && jalv->ports[p].flow == FLOW_OUTPUT) {
147 void* buf = jack_port_get_buffer(jport, nframes);
148 if (jalv->ports[p].type == TYPE_EVENT) {
149 jack_midi_clear_buffer(buf);
150 } else {
151 memset(buf, '\0', nframes * sizeof(float));
152 }
153 }
154 }
155 return 0;
156 default:
157 break;
158 }
159
160 /* Prepare port buffers */
161 for (uint32_t p = 0; p < jalv->num_ports; ++p) {
162 struct Port* port = &jalv->ports[p];
163 if (port->type == TYPE_AUDIO && port->sys_port) {
164 /* Connect plugin port directly to Jack port buffer */
165 lilv_instance_connect_port(
166 jalv->instance, p,
167 jack_port_get_buffer(port->sys_port, nframes));
168 #ifdef HAVE_JACK_METADATA
169 } else if (port->type == TYPE_CV && port->sys_port) {
170 /* Connect plugin port directly to Jack port buffer */
171 lilv_instance_connect_port(
172 jalv->instance, p,
173 jack_port_get_buffer(port->sys_port, nframes));
174 #endif
175 } else if (port->type == TYPE_EVENT && port->flow == FLOW_INPUT) {
176 lv2_evbuf_reset(port->evbuf, true);
177
178 /* Write transport change event if applicable */
179 LV2_Evbuf_Iterator iter = lv2_evbuf_begin(port->evbuf);
180 if (xport_changed) {
181 lv2_evbuf_write(&iter, 0, 0,
182 lv2_pos->type, lv2_pos->size,
183 (const uint8_t*)LV2_ATOM_BODY(lv2_pos));
184 }
185
186 if (jalv->request_update) {
187 /* Plugin state has changed, request an update */
188 const LV2_Atom_Object get = {
189 { sizeof(LV2_Atom_Object_Body), jalv->urids.atom_Object },
190 { 0, jalv->urids.patch_Get } };
191 lv2_evbuf_write(&iter, 0, 0,
192 get.atom.type, get.atom.size,
193 (const uint8_t*)LV2_ATOM_BODY_CONST(&get));
194 }
195
196 if (port->sys_port) {
197 /* Write Jack MIDI input */
198 void* buf = jack_port_get_buffer(port->sys_port, nframes);
199 for (uint32_t i = 0; i < jack_midi_get_event_count(buf); ++i) {
200 jack_midi_event_t ev;
201 jack_midi_event_get(&ev, buf, i);
202 lv2_evbuf_write(&iter,
203 ev.time, 0,
204 jalv->urids.midi_MidiEvent,
205 ev.size, ev.buffer);
206 }
207 }
208 } else if (port->type == TYPE_EVENT) {
209 /* Clear event output for plugin to write to */
210 lv2_evbuf_reset(port->evbuf, false);
211 }
212 }
213 jalv->request_update = false;
214
215 /* Run plugin for this cycle */
216 const bool send_ui_updates = jalv_run(jalv, nframes);
217
218 /* Deliver MIDI output and UI events */
219 for (uint32_t p = 0; p < jalv->num_ports; ++p) {
220 struct Port* const port = &jalv->ports[p];
221 if (port->flow == FLOW_OUTPUT && port->type == TYPE_CONTROL &&
222 lilv_port_has_property(jalv->plugin, port->lilv_port,
223 jalv->nodes.lv2_reportsLatency)) {
224 if (jalv->plugin_latency != port->control) {
225 jalv->plugin_latency = port->control;
226 jack_recompute_total_latencies(client);
227 }
228 } else if (port->flow == FLOW_OUTPUT && port->type == TYPE_EVENT) {
229 void* buf = NULL;
230 if (port->sys_port) {
231 buf = jack_port_get_buffer(port->sys_port, nframes);
232 jack_midi_clear_buffer(buf);
233 }
234
235 for (LV2_Evbuf_Iterator i = lv2_evbuf_begin(port->evbuf);
236 lv2_evbuf_is_valid(i);
237 i = lv2_evbuf_next(i)) {
238 // Get event from LV2 buffer
239 uint32_t frames = 0;
240 uint32_t subframes = 0;
241 uint32_t type = 0;
242 uint32_t size = 0;
243 uint8_t* body = NULL;
244 lv2_evbuf_get(i, &frames, &subframes, &type, &size, &body);
245
246 if (buf && type == jalv->urids.midi_MidiEvent) {
247 // Write MIDI event to Jack output
248 jack_midi_event_write(buf, frames, body, size);
249 }
250
251 if (jalv->has_ui) {
252 // Forward event to UI
253 jalv_send_to_ui(jalv, p, type, size, body);
254 }
255 }
256 } else if (send_ui_updates &&
257 port->flow == FLOW_OUTPUT && port->type == TYPE_CONTROL) {
258 char buf[sizeof(ControlChange) + sizeof(float)];
259 ControlChange* ev = (ControlChange*)buf;
260 ev->index = p;
261 ev->protocol = 0;
262 ev->size = sizeof(float);
263 *(float*)ev->body = port->control;
264 if (zix_ring_write(jalv->plugin_events, buf, sizeof(buf))
265 < sizeof(buf)) {
266 fprintf(stderr, "Plugin => UI buffer overflow!\n");
267 }
268 }
269 }
270
271 return 0;
272 }
273
274 /** Calculate latency assuming all ports depend on each other. */
275 static void
jack_latency_cb(jack_latency_callback_mode_t mode,void * data)276 jack_latency_cb(jack_latency_callback_mode_t mode, void* data)
277 {
278 Jalv* const jalv = (Jalv*)data;
279 const enum PortFlow flow = ((mode == JackCaptureLatency)
280 ? FLOW_INPUT : FLOW_OUTPUT);
281
282 /* First calculate the min/max latency of all feeding ports */
283 uint32_t ports_found = 0;
284 jack_latency_range_t range = { UINT32_MAX, 0 };
285 for (uint32_t p = 0; p < jalv->num_ports; ++p) {
286 struct Port* port = &jalv->ports[p];
287 if (port->sys_port && port->flow == flow) {
288 jack_latency_range_t r;
289 jack_port_get_latency_range(port->sys_port, mode, &r);
290 if (r.min < range.min) { range.min = r.min; }
291 if (r.max > range.max) { range.max = r.max; }
292 ++ports_found;
293 }
294 }
295
296 if (ports_found == 0) {
297 range.min = 0;
298 }
299
300 /* Add the plugin's own latency */
301 range.min += jalv->plugin_latency;
302 range.max += jalv->plugin_latency;
303
304 /* Tell Jack about it */
305 for (uint32_t p = 0; p < jalv->num_ports; ++p) {
306 struct Port* port = &jalv->ports[p];
307 if (port->sys_port && port->flow == flow) {
308 jack_port_set_latency_range(port->sys_port, mode, &range);
309 }
310 }
311 }
312
313 static jack_client_t*
jack_create_client(Jalv * jalv)314 jack_create_client(Jalv* jalv)
315 {
316 jack_client_t* client = NULL;
317
318 /* Determine the name of the JACK client */
319 char* jack_name = NULL;
320 if (jalv->opts.name) {
321 /* Name given on command line */
322 jack_name = jalv_strdup(jalv->opts.name);
323 } else {
324 /* Use plugin name */
325 LilvNode* name = lilv_plugin_get_name(jalv->plugin);
326 jack_name = jalv_strdup(lilv_node_as_string(name));
327 lilv_node_free(name);
328 }
329
330 /* Truncate client name to suit JACK if necessary */
331 if (strlen(jack_name) >= (unsigned)jack_client_name_size() - 1) {
332 jack_name[jack_client_name_size() - 1] = '\0';
333 }
334
335 /* Connect to JACK */
336 if (!client) {
337 client = jack_client_open(
338 jack_name,
339 (jalv->opts.name_exact ? JackUseExactName : JackNullOption),
340 NULL);
341 }
342
343 free(jack_name);
344
345 return client;
346 }
347
348 JalvBackend*
jalv_backend_init(Jalv * jalv)349 jalv_backend_init(Jalv* jalv)
350 {
351 jack_client_t* const client =
352 jalv->backend ? jalv->backend->client : jack_create_client(jalv);
353
354 if (!client) {
355 return NULL;
356 }
357
358 printf("JACK Name: %s\n", jack_get_client_name(client));
359
360 /* Set audio engine properties */
361 jalv->sample_rate = (float)jack_get_sample_rate(client);
362 jalv->block_length = jack_get_buffer_size(client);
363 jalv->midi_buf_size = 4096;
364 #ifdef HAVE_JACK_PORT_TYPE_GET_BUFFER_SIZE
365 jalv->midi_buf_size = jack_port_type_get_buffer_size(
366 client, JACK_DEFAULT_MIDI_TYPE);
367 #endif
368
369 /* Set JACK callbacks */
370 void* const arg = (void*)jalv;
371 jack_set_process_callback(client, &jack_process_cb, arg);
372 jack_set_buffer_size_callback(client, &jack_buffer_size_cb, arg);
373 jack_on_shutdown(client, &jack_shutdown_cb, arg);
374 jack_set_latency_callback(client, &jack_latency_cb, arg);
375
376 if (jalv->backend) {
377 /* Internal JACK client, jalv->backend->is_internal_client was already
378 set in jack_initialize() when allocating the backend */
379 return jalv->backend;
380 }
381
382 /* External JACK client, allocate and return opaque backend */
383 JalvBackend* backend = (JalvBackend*)calloc(1, sizeof(JalvBackend));
384 backend->client = client;
385 backend->is_internal_client = false;
386 return backend;
387 }
388
389 void
jalv_backend_close(Jalv * jalv)390 jalv_backend_close(Jalv* jalv)
391 {
392 if (jalv->backend) {
393 if (!jalv->backend->is_internal_client) {
394 jack_client_close(jalv->backend->client);
395 }
396
397 free(jalv->backend);
398 jalv->backend = NULL;
399 }
400 }
401
402 void
jalv_backend_activate(Jalv * jalv)403 jalv_backend_activate(Jalv* jalv)
404 {
405 jack_activate(jalv->backend->client);
406 }
407
408 void
jalv_backend_deactivate(Jalv * jalv)409 jalv_backend_deactivate(Jalv* jalv)
410 {
411 if (jalv->backend && !jalv->backend->is_internal_client) {
412 jack_deactivate(jalv->backend->client);
413 }
414 }
415
416 void
jalv_backend_activate_port(Jalv * jalv,uint32_t port_index)417 jalv_backend_activate_port(Jalv* jalv, uint32_t port_index)
418 {
419 jack_client_t* client = jalv->backend->client;
420 struct Port* const port = &jalv->ports[port_index];
421
422 const LilvNode* sym = lilv_port_get_symbol(jalv->plugin, port->lilv_port);
423
424 /* Connect unsupported ports to NULL (known to be optional by this point) */
425 if (port->flow == FLOW_UNKNOWN || port->type == TYPE_UNKNOWN) {
426 lilv_instance_connect_port(jalv->instance, port_index, NULL);
427 return;
428 }
429
430 /* Build Jack flags for port */
431 enum JackPortFlags jack_flags = (port->flow == FLOW_INPUT)
432 ? JackPortIsInput
433 : JackPortIsOutput;
434
435 /* Connect the port based on its type */
436 switch (port->type) {
437 case TYPE_CONTROL:
438 lilv_instance_connect_port(jalv->instance, port_index, &port->control);
439 break;
440 case TYPE_AUDIO:
441 port->sys_port = jack_port_register(
442 client, lilv_node_as_string(sym),
443 JACK_DEFAULT_AUDIO_TYPE, jack_flags, 0);
444 break;
445 #ifdef HAVE_JACK_METADATA
446 case TYPE_CV:
447 port->sys_port = jack_port_register(
448 client, lilv_node_as_string(sym),
449 JACK_DEFAULT_AUDIO_TYPE, jack_flags, 0);
450 if (port->sys_port) {
451 jack_set_property(client, jack_port_uuid(port->sys_port),
452 "http://jackaudio.org/metadata/signal-type", "CV",
453 "text/plain");
454 }
455 break;
456 #endif
457 case TYPE_EVENT:
458 if (lilv_port_supports_event(
459 jalv->plugin, port->lilv_port, jalv->nodes.midi_MidiEvent)) {
460 port->sys_port = jack_port_register(
461 client, lilv_node_as_string(sym),
462 JACK_DEFAULT_MIDI_TYPE, jack_flags, 0);
463 }
464 break;
465 default:
466 break;
467 }
468
469 #ifdef HAVE_JACK_METADATA
470 if (port->sys_port) {
471 // Set port order to index
472 char index_str[16];
473 snprintf(index_str, sizeof(index_str), "%u", port_index);
474 jack_set_property(client, jack_port_uuid(port->sys_port),
475 "http://jackaudio.org/metadata/order", index_str,
476 "http://www.w3.org/2001/XMLSchema#integer");
477
478 // Set port pretty name to label
479 LilvNode* name = lilv_port_get_name(jalv->plugin, port->lilv_port);
480 jack_set_property(client, jack_port_uuid(port->sys_port),
481 JACK_METADATA_PRETTY_NAME, lilv_node_as_string(name),
482 "text/plain");
483 lilv_node_free(name);
484 }
485 #endif
486 }
487
488 int
jack_initialize(jack_client_t * const client,const char * const load_init)489 jack_initialize(jack_client_t* const client, const char* const load_init)
490 {
491 const size_t args_len = strlen(load_init);
492 if (args_len > JACK_LOAD_INIT_LIMIT) {
493 fprintf(stderr, "error: Too many arguments given\n");
494 return -1;
495 }
496
497 Jalv* const jalv = (Jalv*)calloc(1, sizeof(Jalv));
498 if (!jalv) {
499 return -1;
500 }
501
502 if (!(jalv->backend = (JalvBackend*)calloc(1, sizeof(JalvBackend)))) {
503 free(jalv);
504 return -1;
505 }
506
507 jalv->backend->client = client;
508 jalv->backend->is_internal_client = true;
509
510 /* Build full command line with "program" name for building argv */
511 const size_t cmd_len = strlen("jalv ") + args_len;
512 char* const cmd = (char*)calloc(cmd_len + 1, 1);
513 snprintf(cmd, cmd_len + 1, "jalv %s", load_init);
514
515 /* Build argv */
516 int argc = 0;
517 char** argv = NULL;
518 char* tok = cmd;
519 for (size_t i = 0; i <= cmd_len; ++i) {
520 if (isspace(cmd[i]) || !cmd[i]) {
521 argv = (char**)realloc(argv, sizeof(char*) * ++argc);
522 cmd[i] = '\0';
523 argv[argc - 1] = tok;
524 tok = cmd + i + 1;
525 }
526 }
527
528 const int err = jalv_open(jalv, &argc, &argv);
529 if (err) {
530 jalv_backend_close(jalv);
531 free(jalv);
532 }
533
534 free(argv);
535 free(cmd);
536 return err;
537 }
538
539 void
jack_finish(void * const arg)540 jack_finish(void* const arg)
541 {
542 Jalv* const jalv = (Jalv*)arg;
543 if (jalv) {
544 if (jalv_close(jalv)) {
545 fprintf(stderr, "Failed to close Jalv\n");
546 }
547
548 free(jalv);
549 }
550 }
551