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