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 #define _POSIX_C_SOURCE 200809L /* for mkdtemp */
18 #define _DARWIN_C_SOURCE /* for mkdtemp on OSX */
19
20 #include "jalv_config.h"
21 #include "jalv_internal.h"
22 #include "lv2_evbuf.h"
23 #include "worker.h"
24
25 #include "lilv/lilv.h"
26 #include "lv2/atom/atom.h"
27 #include "lv2/atom/forge.h"
28 #include "lv2/atom/util.h"
29 #include "lv2/buf-size/buf-size.h"
30 #include "lv2/core/lv2.h"
31 #include "lv2/data-access/data-access.h"
32 #include "lv2/log/log.h"
33 #include "lv2/midi/midi.h"
34 #include "lv2/options/options.h"
35 #include "lv2/parameters/parameters.h"
36 #include "lv2/patch/patch.h"
37 #include "lv2/port-groups/port-groups.h"
38 #include "lv2/port-props/port-props.h"
39 #include "lv2/presets/presets.h"
40 #include "lv2/resize-port/resize-port.h"
41 #include "lv2/state/state.h"
42 #include "lv2/time/time.h"
43 #include "lv2/ui/ui.h"
44 #include "lv2/urid/urid.h"
45 #include "lv2/worker/worker.h"
46 #include "serd/serd.h"
47 #include "sratom/sratom.h"
48 #include "symap.h"
49 #include "zix/common.h"
50 #include "zix/ring.h"
51 #include "zix/sem.h"
52
53 #ifdef HAVE_SUIL
54 #include "suil/suil.h"
55 #endif
56
57 #ifdef _WIN32
58 # include <io.h> /* for _mktemp */
59 # define snprintf _snprintf
60 #endif
61
62 #include <assert.h>
63 #include <math.h>
64 #include <signal.h>
65 #include <stdbool.h>
66 #include <stdint.h>
67 #include <stdio.h>
68 #include <stdlib.h>
69 #include <string.h>
70 #include <sys/stat.h>
71
72 #define NS_RDF "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
73 #define NS_XSD "http://www.w3.org/2001/XMLSchema#"
74
75 #ifndef MIN
76 # define MIN(a, b) (((a) < (b)) ? (a) : (b))
77 #endif
78
79 #ifndef MAX
80 # define MAX(a, b) (((a) > (b)) ? (a) : (b))
81 #endif
82
83 #ifndef ARRAY_SIZE
84 # define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
85 #endif
86
87 /* Size factor for UI ring buffers. The ring size is a few times the size of
88 an event output to give the UI a chance to keep up. Experiments with Ingen,
89 which can highly saturate its event output, led me to this value. It
90 really ought to be enough for anybody(TM).
91 */
92 #define N_BUFFER_CYCLES 16
93
94 static ZixSem* exit_sem = NULL; /**< Exit semaphore used by signal handler*/
95
96 static LV2_URID
map_uri(LV2_URID_Map_Handle handle,const char * uri)97 map_uri(LV2_URID_Map_Handle handle,
98 const char* uri)
99 {
100 Jalv* jalv = (Jalv*)handle;
101 zix_sem_wait(&jalv->symap_lock);
102 const LV2_URID id = symap_map(jalv->symap, uri);
103 zix_sem_post(&jalv->symap_lock);
104 return id;
105 }
106
107 static const char*
unmap_uri(LV2_URID_Unmap_Handle handle,LV2_URID urid)108 unmap_uri(LV2_URID_Unmap_Handle handle,
109 LV2_URID urid)
110 {
111 Jalv* jalv = (Jalv*)handle;
112 zix_sem_wait(&jalv->symap_lock);
113 const char* uri = symap_unmap(jalv->symap, urid);
114 zix_sem_post(&jalv->symap_lock);
115 return uri;
116 }
117
118 #define NS_EXT "http://lv2plug.in/ns/ext/"
119
120 /** These features have no data */
121 static const LV2_Feature static_features[] = {
122 { LV2_STATE__loadDefaultState, NULL },
123 { LV2_BUF_SIZE__powerOf2BlockLength, NULL },
124 { LV2_BUF_SIZE__fixedBlockLength, NULL },
125 { LV2_BUF_SIZE__boundedBlockLength, NULL } };
126
127 /** Return true iff Jalv supports the given feature. */
128 static bool
feature_is_supported(Jalv * jalv,const char * uri)129 feature_is_supported(Jalv* jalv, const char* uri)
130 {
131 if (!strcmp(uri, "http://lv2plug.in/ns/lv2core#isLive") ||
132 !strcmp(uri, "http://lv2plug.in/ns/lv2core#inPlaceBroken")) {
133 return true;
134 }
135
136 for (const LV2_Feature*const* f = jalv->feature_list; *f; ++f) {
137 if (!strcmp(uri, (*f)->URI)) {
138 return true;
139 }
140 }
141 return false;
142 }
143
144 /** Abort and exit on error */
145 static void
die(const char * msg)146 die(const char* msg)
147 {
148 fprintf(stderr, "%s\n", msg);
149 exit(EXIT_FAILURE);
150 }
151
152 /**
153 Create a port structure from data description. This is called before plugin
154 and Jack instantiation. The remaining instance-specific setup
155 (e.g. buffers) is done later in activate_port().
156 */
157 static void
create_port(Jalv * jalv,uint32_t port_index,float default_value)158 create_port(Jalv* jalv,
159 uint32_t port_index,
160 float default_value)
161 {
162 struct Port* const port = &jalv->ports[port_index];
163
164 port->lilv_port = lilv_plugin_get_port_by_index(jalv->plugin, port_index);
165 port->sys_port = NULL;
166 port->evbuf = NULL;
167 port->buf_size = 0;
168 port->index = port_index;
169 port->control = 0.0f;
170 port->flow = FLOW_UNKNOWN;
171
172 const bool optional = lilv_port_has_property(
173 jalv->plugin, port->lilv_port, jalv->nodes.lv2_connectionOptional);
174
175 /* Set the port flow (input or output) */
176 if (lilv_port_is_a(jalv->plugin, port->lilv_port, jalv->nodes.lv2_InputPort)) {
177 port->flow = FLOW_INPUT;
178 } else if (lilv_port_is_a(jalv->plugin, port->lilv_port,
179 jalv->nodes.lv2_OutputPort)) {
180 port->flow = FLOW_OUTPUT;
181 } else if (!optional) {
182 die("Mandatory port has unknown type (neither input nor output)");
183 }
184
185 const bool hidden = !jalv->opts.show_hidden &&
186 lilv_port_has_property(jalv->plugin,
187 port->lilv_port,
188 jalv->nodes.pprops_notOnGUI);
189
190 /* Set control values */
191 if (lilv_port_is_a(jalv->plugin, port->lilv_port, jalv->nodes.lv2_ControlPort)) {
192 port->type = TYPE_CONTROL;
193 port->control = isnan(default_value) ? 0.0f : default_value;
194 if (!hidden) {
195 add_control(&jalv->controls, new_port_control(jalv, port->index));
196 }
197 } else if (lilv_port_is_a(jalv->plugin, port->lilv_port,
198 jalv->nodes.lv2_AudioPort)) {
199 port->type = TYPE_AUDIO;
200 #ifdef HAVE_JACK_METADATA
201 } else if (lilv_port_is_a(jalv->plugin, port->lilv_port,
202 jalv->nodes.lv2_CVPort)) {
203 port->type = TYPE_CV;
204 #endif
205 } else if (lilv_port_is_a(jalv->plugin, port->lilv_port,
206 jalv->nodes.atom_AtomPort)) {
207 port->type = TYPE_EVENT;
208 } else if (!optional) {
209 die("Mandatory port has unknown data type");
210 }
211
212 LilvNode* min_size = lilv_port_get(
213 jalv->plugin, port->lilv_port, jalv->nodes.rsz_minimumSize);
214 if (min_size && lilv_node_is_int(min_size)) {
215 port->buf_size = lilv_node_as_int(min_size);
216 jalv->opts.buffer_size = MAX(
217 jalv->opts.buffer_size, port->buf_size * N_BUFFER_CYCLES);
218 }
219 lilv_node_free(min_size);
220 }
221
222 /**
223 Create port structures from data (via create_port()) for all ports.
224 */
225 void
jalv_create_ports(Jalv * jalv)226 jalv_create_ports(Jalv* jalv)
227 {
228 jalv->num_ports = lilv_plugin_get_num_ports(jalv->plugin);
229 jalv->ports = (struct Port*)calloc(jalv->num_ports, sizeof(struct Port));
230 float* default_values = (float*)calloc(
231 lilv_plugin_get_num_ports(jalv->plugin), sizeof(float));
232 lilv_plugin_get_port_ranges_float(jalv->plugin, NULL, NULL, default_values);
233
234 for (uint32_t i = 0; i < jalv->num_ports; ++i) {
235 create_port(jalv, i, default_values[i]);
236 }
237
238 const LilvPort* control_input = lilv_plugin_get_port_by_designation(
239 jalv->plugin, jalv->nodes.lv2_InputPort, jalv->nodes.lv2_control);
240 if (control_input) {
241 const uint32_t index = lilv_port_get_index(jalv->plugin, control_input);
242 if (jalv->ports[index].type == TYPE_EVENT) {
243 jalv->control_in = index;
244 } else {
245 fprintf(stderr,
246 "warning: Non-event port %u has lv2:control designation, "
247 "ignored\n",
248 index);
249 }
250 }
251
252 free(default_values);
253 }
254
255 /**
256 Allocate port buffers (only necessary for MIDI).
257 */
258 void
jalv_allocate_port_buffers(Jalv * jalv)259 jalv_allocate_port_buffers(Jalv* jalv)
260 {
261 for (uint32_t i = 0; i < jalv->num_ports; ++i) {
262 struct Port* const port = &jalv->ports[i];
263 switch (port->type) {
264 case TYPE_EVENT: {
265 lv2_evbuf_free(port->evbuf);
266 const size_t buf_size = (port->buf_size > 0)
267 ? port->buf_size
268 : jalv->midi_buf_size;
269 port->evbuf = lv2_evbuf_new(
270 buf_size,
271 jalv->map.map(jalv->map.handle,
272 lilv_node_as_string(jalv->nodes.atom_Chunk)),
273 jalv->map.map(jalv->map.handle,
274 lilv_node_as_string(jalv->nodes.atom_Sequence)));
275 lilv_instance_connect_port(
276 jalv->instance, i, lv2_evbuf_get_buffer(port->evbuf));
277 }
278 default: break;
279 }
280 }
281 }
282
283 /**
284 Get a port structure by symbol.
285
286 TODO: Build an index to make this faster, currently O(n) which may be
287 a problem when restoring the state of plugins with many ports.
288 */
289 struct Port*
jalv_port_by_symbol(Jalv * jalv,const char * sym)290 jalv_port_by_symbol(Jalv* jalv, const char* sym)
291 {
292 for (uint32_t i = 0; i < jalv->num_ports; ++i) {
293 struct Port* const port = &jalv->ports[i];
294 const LilvNode* port_sym = lilv_port_get_symbol(jalv->plugin,
295 port->lilv_port);
296
297 if (!strcmp(lilv_node_as_string(port_sym), sym)) {
298 return port;
299 }
300 }
301
302 return NULL;
303 }
304
305 ControlID*
jalv_control_by_symbol(Jalv * jalv,const char * sym)306 jalv_control_by_symbol(Jalv* jalv, const char* sym)
307 {
308 for (size_t i = 0; i < jalv->controls.n_controls; ++i) {
309 if (!strcmp(lilv_node_as_string(jalv->controls.controls[i]->symbol),
310 sym)) {
311 return jalv->controls.controls[i];
312 }
313 }
314 return NULL;
315 }
316
317 void
jalv_create_controls(Jalv * jalv,bool writable)318 jalv_create_controls(Jalv* jalv, bool writable)
319 {
320 const LilvPlugin* plugin = jalv->plugin;
321 LilvWorld* world = jalv->world;
322 LilvNode* patch_writable = lilv_new_uri(world, LV2_PATCH__writable);
323 LilvNode* patch_readable = lilv_new_uri(world, LV2_PATCH__readable);
324
325 LilvNodes* properties = lilv_world_find_nodes(
326 world,
327 lilv_plugin_get_uri(plugin),
328 writable ? patch_writable : patch_readable,
329 NULL);
330 LILV_FOREACH(nodes, p, properties) {
331 const LilvNode* property = lilv_nodes_get(properties, p);
332 ControlID* record = NULL;
333
334 if (!writable && lilv_world_ask(world,
335 lilv_plugin_get_uri(plugin),
336 patch_writable,
337 property)) {
338 // Find existing writable control
339 for (size_t i = 0; i < jalv->controls.n_controls; ++i) {
340 if (lilv_node_equals(jalv->controls.controls[i]->node, property)) {
341 record = jalv->controls.controls[i];
342 record->is_readable = true;
343 break;
344 }
345 }
346
347 if (record) {
348 continue;
349 }
350 }
351
352 record = new_property_control(jalv, property);
353 if (writable) {
354 record->is_writable = true;
355 } else {
356 record->is_readable = true;
357 }
358
359 if (record->value_type) {
360 add_control(&jalv->controls, record);
361 } else {
362 fprintf(stderr, "Parameter <%s> has unknown value type, ignored\n",
363 lilv_node_as_string(record->node));
364 free(record);
365 }
366 }
367 lilv_nodes_free(properties);
368
369 lilv_node_free(patch_readable);
370 lilv_node_free(patch_writable);
371 }
372
373 void
jalv_set_control(const ControlID * control,uint32_t size,LV2_URID type,const void * body)374 jalv_set_control(const ControlID* control,
375 uint32_t size,
376 LV2_URID type,
377 const void* body)
378 {
379 Jalv* jalv = control->jalv;
380 if (control->type == PORT && type == jalv->forge.Float) {
381 struct Port* port = &control->jalv->ports[control->index];
382 port->control = *(const float*)body;
383 } else if (control->type == PROPERTY) {
384 // Copy forge since it is used by process thread
385 LV2_Atom_Forge forge = jalv->forge;
386 LV2_Atom_Forge_Frame frame;
387 uint8_t buf[1024];
388 lv2_atom_forge_set_buffer(&forge, buf, sizeof(buf));
389
390 lv2_atom_forge_object(&forge, &frame, 0, jalv->urids.patch_Set);
391 lv2_atom_forge_key(&forge, jalv->urids.patch_property);
392 lv2_atom_forge_urid(&forge, control->property);
393 lv2_atom_forge_key(&forge, jalv->urids.patch_value);
394 lv2_atom_forge_atom(&forge, size, type);
395 lv2_atom_forge_write(&forge, body, size);
396
397 const LV2_Atom* atom = lv2_atom_forge_deref(&forge, frame.ref);
398 jalv_ui_write(jalv,
399 jalv->control_in,
400 lv2_atom_total_size(atom),
401 jalv->urids.atom_eventTransfer,
402 atom);
403 }
404 }
405
406 void
jalv_ui_instantiate(Jalv * jalv,const char * native_ui_type,void * parent)407 jalv_ui_instantiate(Jalv* jalv, const char* native_ui_type, void* parent)
408 {
409 #ifdef HAVE_SUIL
410 jalv->ui_host = suil_host_new(jalv_ui_write, jalv_ui_port_index, NULL, NULL);
411
412 const LV2_Feature parent_feature = {
413 LV2_UI__parent, parent
414 };
415 const LV2_Feature instance_feature = {
416 NS_EXT "instance-access", lilv_instance_get_handle(jalv->instance)
417 };
418 const LV2_Feature data_feature = {
419 LV2_DATA_ACCESS_URI, &jalv->features.ext_data
420 };
421 const LV2_Feature idle_feature = {
422 LV2_UI__idleInterface, NULL
423 };
424 const LV2_Feature* ui_features[] = {
425 &jalv->features.map_feature,
426 &jalv->features.unmap_feature,
427 &instance_feature,
428 &data_feature,
429 &jalv->features.log_feature,
430 &parent_feature,
431 &jalv->features.options_feature,
432 &idle_feature,
433 &jalv->features.request_value_feature,
434 NULL
435 };
436
437 const char* bundle_uri = lilv_node_as_uri(lilv_ui_get_bundle_uri(jalv->ui));
438 const char* binary_uri = lilv_node_as_uri(lilv_ui_get_binary_uri(jalv->ui));
439 char* bundle_path = lilv_file_uri_parse(bundle_uri, NULL);
440 char* binary_path = lilv_file_uri_parse(binary_uri, NULL);
441
442 jalv->ui_instance = suil_instance_new(
443 jalv->ui_host,
444 jalv,
445 native_ui_type,
446 lilv_node_as_uri(lilv_plugin_get_uri(jalv->plugin)),
447 lilv_node_as_uri(lilv_ui_get_uri(jalv->ui)),
448 lilv_node_as_uri(jalv->ui_type),
449 bundle_path,
450 binary_path,
451 ui_features);
452
453 lilv_free(binary_path);
454 lilv_free(bundle_path);
455 #endif
456 }
457
458 bool
jalv_ui_is_resizable(Jalv * jalv)459 jalv_ui_is_resizable(Jalv* jalv)
460 {
461 if (!jalv->ui) {
462 return false;
463 }
464
465 const LilvNode* s = lilv_ui_get_uri(jalv->ui);
466 LilvNode* p = lilv_new_uri(jalv->world, LV2_CORE__optionalFeature);
467 LilvNode* fs = lilv_new_uri(jalv->world, LV2_UI__fixedSize);
468 LilvNode* nrs = lilv_new_uri(jalv->world, LV2_UI__noUserResize);
469
470 LilvNodes* fs_matches = lilv_world_find_nodes(jalv->world, s, p, fs);
471 LilvNodes* nrs_matches = lilv_world_find_nodes(jalv->world, s, p, nrs);
472
473 lilv_nodes_free(nrs_matches);
474 lilv_nodes_free(fs_matches);
475 lilv_node_free(nrs);
476 lilv_node_free(fs);
477 lilv_node_free(p);
478
479 return !fs_matches && !nrs_matches;
480 }
481
482 void
jalv_ui_write(void * const jalv_handle,uint32_t port_index,uint32_t buffer_size,uint32_t protocol,const void * buffer)483 jalv_ui_write(void* const jalv_handle,
484 uint32_t port_index,
485 uint32_t buffer_size,
486 uint32_t protocol,
487 const void* buffer)
488 {
489 Jalv* const jalv = (Jalv*)jalv_handle;
490
491 if (protocol != 0 && protocol != jalv->urids.atom_eventTransfer) {
492 fprintf(stderr, "UI write with unsupported protocol %u (%s)\n",
493 protocol, unmap_uri(jalv, protocol));
494 return;
495 }
496
497 if (port_index >= jalv->num_ports) {
498 fprintf(stderr, "UI write to out of range port index %u\n",
499 port_index);
500 return;
501 }
502
503 if (jalv->opts.dump && protocol == jalv->urids.atom_eventTransfer) {
504 const LV2_Atom* atom = (const LV2_Atom*)buffer;
505 char* str = sratom_to_turtle(
506 jalv->sratom, &jalv->unmap, "jalv:", NULL, NULL,
507 atom->type, atom->size, LV2_ATOM_BODY_CONST(atom));
508 jalv_ansi_start(stdout, 36);
509 printf("\n## UI => Plugin (%u bytes) ##\n%s\n", atom->size, str);
510 jalv_ansi_reset(stdout);
511 free(str);
512 }
513
514 char buf[sizeof(ControlChange) + buffer_size];
515 ControlChange* ev = (ControlChange*)buf;
516 ev->index = port_index;
517 ev->protocol = protocol;
518 ev->size = buffer_size;
519 memcpy(ev->body, buffer, buffer_size);
520 zix_ring_write(jalv->ui_events, buf, sizeof(buf));
521 }
522
523 void
jalv_apply_ui_events(Jalv * jalv,uint32_t nframes)524 jalv_apply_ui_events(Jalv* jalv, uint32_t nframes)
525 {
526 if (!jalv->has_ui) {
527 return;
528 }
529
530 ControlChange ev;
531 const size_t space = zix_ring_read_space(jalv->ui_events);
532 for (size_t i = 0; i < space; i += sizeof(ev) + ev.size) {
533 zix_ring_read(jalv->ui_events, (char*)&ev, sizeof(ev));
534 char body[ev.size];
535 if (zix_ring_read(jalv->ui_events, body, ev.size) != ev.size) {
536 fprintf(stderr, "error: Error reading from UI ring buffer\n");
537 break;
538 }
539 assert(ev.index < jalv->num_ports);
540 struct Port* const port = &jalv->ports[ev.index];
541 if (ev.protocol == 0) {
542 assert(ev.size == sizeof(float));
543 port->control = *(float*)body;
544 } else if (ev.protocol == jalv->urids.atom_eventTransfer) {
545 LV2_Evbuf_Iterator e = lv2_evbuf_end(port->evbuf);
546 const LV2_Atom* const atom = (const LV2_Atom*)body;
547 lv2_evbuf_write(&e, nframes, 0, atom->type, atom->size,
548 (const uint8_t*)LV2_ATOM_BODY_CONST(atom));
549 } else {
550 fprintf(stderr, "error: Unknown control change protocol %u\n",
551 ev.protocol);
552 }
553 }
554 }
555
556 uint32_t
jalv_ui_port_index(void * const controller,const char * symbol)557 jalv_ui_port_index(void* const controller, const char* symbol)
558 {
559 Jalv* const jalv = (Jalv*)controller;
560 struct Port* port = jalv_port_by_symbol(jalv, symbol);
561
562 return port ? port->index : LV2UI_INVALID_PORT_INDEX;
563 }
564
565 void
jalv_init_ui(Jalv * jalv)566 jalv_init_ui(Jalv* jalv)
567 {
568 // Set initial control port values
569 for (uint32_t i = 0; i < jalv->num_ports; ++i) {
570 if (jalv->ports[i].type == TYPE_CONTROL) {
571 jalv_ui_port_event(jalv, i,
572 sizeof(float), 0,
573 &jalv->ports[i].control);
574 }
575 }
576
577 if (jalv->control_in != (uint32_t)-1) {
578 // Send patch:Get message for initial parameters/etc
579 LV2_Atom_Forge forge = jalv->forge;
580 LV2_Atom_Forge_Frame frame;
581 uint8_t buf[1024];
582 lv2_atom_forge_set_buffer(&forge, buf, sizeof(buf));
583 lv2_atom_forge_object(&forge, &frame, 0, jalv->urids.patch_Get);
584
585 const LV2_Atom* atom = lv2_atom_forge_deref(&forge, frame.ref);
586 jalv_ui_write(jalv,
587 jalv->control_in,
588 lv2_atom_total_size(atom),
589 jalv->urids.atom_eventTransfer,
590 atom);
591 lv2_atom_forge_pop(&forge, &frame);
592 }
593 }
594
595 bool
jalv_send_to_ui(Jalv * jalv,uint32_t port_index,uint32_t type,uint32_t size,const void * body)596 jalv_send_to_ui(Jalv* jalv,
597 uint32_t port_index,
598 uint32_t type,
599 uint32_t size,
600 const void* body)
601 {
602 /* TODO: Be more disciminate about what to send */
603 char evbuf[sizeof(ControlChange) + sizeof(LV2_Atom)];
604 ControlChange* ev = (ControlChange*)evbuf;
605 ev->index = port_index;
606 ev->protocol = jalv->urids.atom_eventTransfer;
607 ev->size = sizeof(LV2_Atom) + size;
608
609 LV2_Atom* atom = (LV2_Atom*)ev->body;
610 atom->type = type;
611 atom->size = size;
612
613 if (zix_ring_write_space(jalv->plugin_events) >= sizeof(evbuf) + size) {
614 zix_ring_write(jalv->plugin_events, evbuf, sizeof(evbuf));
615 zix_ring_write(jalv->plugin_events, (const char*)body, size);
616 return true;
617 } else {
618 fprintf(stderr, "Plugin => UI buffer overflow!\n");
619 return false;
620 }
621 }
622
623 bool
jalv_run(Jalv * jalv,uint32_t nframes)624 jalv_run(Jalv* jalv, uint32_t nframes)
625 {
626 /* Read and apply control change events from UI */
627 jalv_apply_ui_events(jalv, nframes);
628
629 /* Run plugin for this cycle */
630 lilv_instance_run(jalv->instance, nframes);
631
632 /* Process any worker replies. */
633 jalv_worker_emit_responses(&jalv->state_worker, jalv->instance);
634 jalv_worker_emit_responses(&jalv->worker, jalv->instance);
635
636 /* Notify the plugin the run() cycle is finished */
637 if (jalv->worker.iface && jalv->worker.iface->end_run) {
638 jalv->worker.iface->end_run(jalv->instance->lv2_handle);
639 }
640
641 /* Check if it's time to send updates to the UI */
642 jalv->event_delta_t += nframes;
643 bool send_ui_updates = false;
644 float update_frames = jalv->sample_rate / jalv->ui_update_hz;
645 if (jalv->has_ui && (jalv->event_delta_t > update_frames)) {
646 send_ui_updates = true;
647 jalv->event_delta_t = 0;
648 }
649
650 return send_ui_updates;
651 }
652
653 int
jalv_update(Jalv * jalv)654 jalv_update(Jalv* jalv)
655 {
656 /* Check quit flag and close if set. */
657 if (zix_sem_try_wait(&jalv->done)) {
658 jalv_close_ui(jalv);
659 return 0;
660 }
661
662 /* Emit UI events. */
663 ControlChange ev;
664 const size_t space = zix_ring_read_space(jalv->plugin_events);
665 for (size_t i = 0;
666 i + sizeof(ev) < space;
667 i += sizeof(ev) + ev.size) {
668 /* Read event header to get the size */
669 zix_ring_read(jalv->plugin_events, (char*)&ev, sizeof(ev));
670
671 /* Resize read buffer if necessary */
672 jalv->ui_event_buf = realloc(jalv->ui_event_buf, ev.size);
673 void* const buf = jalv->ui_event_buf;
674
675 /* Read event body */
676 zix_ring_read(jalv->plugin_events, (char*)buf, ev.size);
677
678 if (jalv->opts.dump && ev.protocol == jalv->urids.atom_eventTransfer) {
679 /* Dump event in Turtle to the console */
680 LV2_Atom* atom = (LV2_Atom*)buf;
681 char* str = sratom_to_turtle(
682 jalv->ui_sratom, &jalv->unmap, "jalv:", NULL, NULL,
683 atom->type, atom->size, LV2_ATOM_BODY(atom));
684 jalv_ansi_start(stdout, 35);
685 printf("\n## Plugin => UI (%u bytes) ##\n%s\n", atom->size, str);
686 jalv_ansi_reset(stdout);
687 free(str);
688 }
689
690 jalv_ui_port_event(jalv, ev.index, ev.size, ev.protocol, buf);
691
692 if (ev.protocol == 0 && jalv->opts.print_controls) {
693 jalv_print_control(jalv, &jalv->ports[ev.index], *(float*)buf);
694 }
695 }
696
697 return 1;
698 }
699
700 static bool
jalv_apply_control_arg(Jalv * jalv,const char * s)701 jalv_apply_control_arg(Jalv* jalv, const char* s)
702 {
703 char sym[256];
704 float val = 0.0f;
705 if (sscanf(s, "%[^=]=%f", sym, &val) != 2) {
706 fprintf(stderr, "warning: Ignoring invalid value `%s'\n", s);
707 return false;
708 }
709
710 ControlID* control = jalv_control_by_symbol(jalv, sym);
711 if (!control) {
712 fprintf(stderr, "warning: Ignoring value for unknown control `%s'\n", sym);
713 return false;
714 }
715
716 jalv_set_control(control, sizeof(float), jalv->urids.atom_Float, &val);
717 printf("%s = %f\n", sym, val);
718
719 return true;
720 }
721
722 static void
signal_handler(int ZIX_UNUSED (sig))723 signal_handler(int ZIX_UNUSED(sig))
724 {
725 zix_sem_post(exit_sem);
726 }
727
728 static void
init_feature(LV2_Feature * const dest,const char * const URI,void * data)729 init_feature(LV2_Feature* const dest, const char* const URI, void* data)
730 {
731 dest->URI = URI;
732 dest->data = data;
733 }
734
735 static void
setup_signals(Jalv * const jalv)736 setup_signals(Jalv* const jalv)
737 {
738 exit_sem = &jalv->done;
739
740 #ifdef HAVE_SIGACTION
741 struct sigaction action;
742 sigemptyset(&action.sa_mask);
743 action.sa_flags = 0;
744 action.sa_handler = signal_handler;
745 sigaction(SIGINT, &action, NULL);
746 sigaction(SIGTERM, &action, NULL);
747 #else
748 /* May not work in combination with fgets in the console interface */
749 signal(SIGINT, signal_handler);
750 signal(SIGTERM, signal_handler);
751 #endif
752 }
753
754 static const LilvUI*
jalv_select_custom_ui(const Jalv * const jalv)755 jalv_select_custom_ui(const Jalv* const jalv)
756 {
757 const char* const native_ui_type_uri = jalv_native_ui_type();
758
759 if (jalv->opts.ui_uri) {
760 // Specific UI explicitly requested by user
761 LilvNode* uri = lilv_new_uri(jalv->world, jalv->opts.ui_uri);
762 const LilvUI* ui = lilv_uis_get_by_uri(jalv->uis, uri);
763
764 lilv_node_free(uri);
765 return ui;
766 }
767
768 #ifdef HAVE_SUIL
769 if (native_ui_type_uri) {
770 // Try to find an embeddable UI
771 LilvNode* native_type = lilv_new_uri(jalv->world, native_ui_type_uri);
772
773 LILV_FOREACH (uis, u, jalv->uis) {
774 const LilvUI* ui = lilv_uis_get(jalv->uis, u);
775 const LilvNode* type = NULL;
776 const bool supported = lilv_ui_is_supported(
777 ui, suil_ui_supported, native_type, &type);
778
779 if (supported) {
780 lilv_node_free(native_type);
781 return ui;
782 }
783 }
784
785 lilv_node_free(native_type);
786 }
787 #endif
788
789 if (!native_ui_type_uri && jalv->opts.show_ui) {
790 // Try to find a UI with ui:showInterface
791 LILV_FOREACH (uis, u, jalv->uis) {
792 const LilvUI* ui = lilv_uis_get(jalv->uis, u);
793 const LilvNode* ui_node = lilv_ui_get_uri(ui);
794
795 lilv_world_load_resource(jalv->world, ui_node);
796
797 const bool supported = lilv_world_ask(jalv->world,
798 ui_node,
799 jalv->nodes.lv2_extensionData,
800 jalv->nodes.ui_showInterface);
801
802 lilv_world_unload_resource(jalv->world, ui_node);
803
804 if (supported) {
805 return ui;
806 }
807 }
808 }
809
810 return NULL;
811 }
812
813 int
jalv_open(Jalv * const jalv,int * argc,char *** argv)814 jalv_open(Jalv* const jalv, int* argc, char*** argv)
815 {
816 jalv->prog_name = (*argv)[0];
817 jalv->block_length = 4096; /* Should be set by backend */
818 jalv->midi_buf_size = 1024; /* Should be set by backend */
819 jalv->play_state = JALV_PAUSED;
820 jalv->bpm = 120.0f;
821 jalv->control_in = (uint32_t)-1;
822
823 #ifdef HAVE_SUIL
824 suil_init(argc, argv, SUIL_ARG_NONE);
825 #endif
826
827 if (jalv_init(argc, argv, &jalv->opts)) {
828 jalv_close(jalv);
829 return -1;
830 }
831
832 jalv->symap = symap_new();
833 zix_sem_init(&jalv->symap_lock, 1);
834 zix_sem_init(&jalv->work_lock, 1);
835
836 jalv->map.handle = jalv;
837 jalv->map.map = map_uri;
838 init_feature(&jalv->features.map_feature, LV2_URID__map, &jalv->map);
839
840 jalv->worker.jalv = jalv;
841 jalv->state_worker.jalv = jalv;
842
843 jalv->unmap.handle = jalv;
844 jalv->unmap.unmap = unmap_uri;
845 init_feature(&jalv->features.unmap_feature, LV2_URID__unmap, &jalv->unmap);
846
847 lv2_atom_forge_init(&jalv->forge, &jalv->map);
848
849 jalv->env = serd_env_new(NULL);
850 serd_env_set_prefix_from_strings(
851 jalv->env, (const uint8_t*)"patch", (const uint8_t*)LV2_PATCH_PREFIX);
852 serd_env_set_prefix_from_strings(
853 jalv->env, (const uint8_t*)"time", (const uint8_t*)LV2_TIME_PREFIX);
854 serd_env_set_prefix_from_strings(
855 jalv->env, (const uint8_t*)"xsd", (const uint8_t*)NS_XSD);
856
857 jalv->sratom = sratom_new(&jalv->map);
858 jalv->ui_sratom = sratom_new(&jalv->map);
859 sratom_set_env(jalv->sratom, jalv->env);
860 sratom_set_env(jalv->ui_sratom, jalv->env);
861
862 jalv->urids.atom_Float = symap_map(jalv->symap, LV2_ATOM__Float);
863 jalv->urids.atom_Int = symap_map(jalv->symap, LV2_ATOM__Int);
864 jalv->urids.atom_Object = symap_map(jalv->symap, LV2_ATOM__Object);
865 jalv->urids.atom_Path = symap_map(jalv->symap, LV2_ATOM__Path);
866 jalv->urids.atom_String = symap_map(jalv->symap, LV2_ATOM__String);
867 jalv->urids.atom_eventTransfer = symap_map(jalv->symap, LV2_ATOM__eventTransfer);
868 jalv->urids.bufsz_maxBlockLength = symap_map(jalv->symap, LV2_BUF_SIZE__maxBlockLength);
869 jalv->urids.bufsz_minBlockLength = symap_map(jalv->symap, LV2_BUF_SIZE__minBlockLength);
870 jalv->urids.bufsz_sequenceSize = symap_map(jalv->symap, LV2_BUF_SIZE__sequenceSize);
871 jalv->urids.log_Error = symap_map(jalv->symap, LV2_LOG__Error);
872 jalv->urids.log_Trace = symap_map(jalv->symap, LV2_LOG__Trace);
873 jalv->urids.log_Warning = symap_map(jalv->symap, LV2_LOG__Warning);
874 jalv->urids.midi_MidiEvent = symap_map(jalv->symap, LV2_MIDI__MidiEvent);
875 jalv->urids.param_sampleRate = symap_map(jalv->symap, LV2_PARAMETERS__sampleRate);
876 jalv->urids.patch_Get = symap_map(jalv->symap, LV2_PATCH__Get);
877 jalv->urids.patch_Put = symap_map(jalv->symap, LV2_PATCH__Put);
878 jalv->urids.patch_Set = symap_map(jalv->symap, LV2_PATCH__Set);
879 jalv->urids.patch_body = symap_map(jalv->symap, LV2_PATCH__body);
880 jalv->urids.patch_property = symap_map(jalv->symap, LV2_PATCH__property);
881 jalv->urids.patch_value = symap_map(jalv->symap, LV2_PATCH__value);
882 jalv->urids.time_Position = symap_map(jalv->symap, LV2_TIME__Position);
883 jalv->urids.time_bar = symap_map(jalv->symap, LV2_TIME__bar);
884 jalv->urids.time_barBeat = symap_map(jalv->symap, LV2_TIME__barBeat);
885 jalv->urids.time_beatUnit = symap_map(jalv->symap, LV2_TIME__beatUnit);
886 jalv->urids.time_beatsPerBar = symap_map(jalv->symap, LV2_TIME__beatsPerBar);
887 jalv->urids.time_beatsPerMinute = symap_map(jalv->symap, LV2_TIME__beatsPerMinute);
888 jalv->urids.time_frame = symap_map(jalv->symap, LV2_TIME__frame);
889 jalv->urids.time_speed = symap_map(jalv->symap, LV2_TIME__speed);
890 jalv->urids.ui_updateRate = symap_map(jalv->symap, LV2_UI__updateRate);
891
892 #ifdef _WIN32
893 jalv->temp_dir = jalv_strdup("jalvXXXXXX");
894 _mktemp(jalv->temp_dir);
895 #else
896 char* templ = jalv_strdup("/tmp/jalv-XXXXXX");
897 jalv->temp_dir = jalv_strjoin(mkdtemp(templ), "/");
898 free(templ);
899 #endif
900
901 jalv->features.make_path.handle = jalv;
902 jalv->features.make_path.path = jalv_make_path;
903 init_feature(&jalv->features.make_path_feature,
904 LV2_STATE__makePath, &jalv->features.make_path);
905
906 jalv->features.sched.handle = &jalv->worker;
907 jalv->features.sched.schedule_work = jalv_worker_schedule;
908 init_feature(&jalv->features.sched_feature,
909 LV2_WORKER__schedule, &jalv->features.sched);
910
911 jalv->features.ssched.handle = &jalv->state_worker;
912 jalv->features.ssched.schedule_work = jalv_worker_schedule;
913 init_feature(&jalv->features.state_sched_feature,
914 LV2_WORKER__schedule, &jalv->features.ssched);
915
916 jalv->features.llog.handle = jalv;
917 jalv->features.llog.printf = jalv_printf;
918 jalv->features.llog.vprintf = jalv_vprintf;
919 init_feature(&jalv->features.log_feature,
920 LV2_LOG__log, &jalv->features.llog);
921
922 jalv->features.request_value.handle = jalv;
923 init_feature(&jalv->features.request_value_feature,
924 LV2_UI__requestValue, &jalv->features.request_value);
925
926 zix_sem_init(&jalv->done, 0);
927
928 zix_sem_init(&jalv->paused, 0);
929 zix_sem_init(&jalv->worker.sem, 0);
930
931 /* Find all installed plugins */
932 LilvWorld* world = lilv_world_new();
933 lilv_world_load_all(world);
934 jalv->world = world;
935 const LilvPlugins* plugins = lilv_world_get_all_plugins(world);
936
937 /* Cache URIs for concepts we'll use */
938 jalv->nodes.atom_AtomPort = lilv_new_uri(world, LV2_ATOM__AtomPort);
939 jalv->nodes.atom_Chunk = lilv_new_uri(world, LV2_ATOM__Chunk);
940 jalv->nodes.atom_Float = lilv_new_uri(world, LV2_ATOM__Float);
941 jalv->nodes.atom_Path = lilv_new_uri(world, LV2_ATOM__Path);
942 jalv->nodes.atom_Sequence = lilv_new_uri(world, LV2_ATOM__Sequence);
943 jalv->nodes.lv2_AudioPort = lilv_new_uri(world, LV2_CORE__AudioPort);
944 jalv->nodes.lv2_CVPort = lilv_new_uri(world, LV2_CORE__CVPort);
945 jalv->nodes.lv2_ControlPort = lilv_new_uri(world, LV2_CORE__ControlPort);
946 jalv->nodes.lv2_InputPort = lilv_new_uri(world, LV2_CORE__InputPort);
947 jalv->nodes.lv2_OutputPort = lilv_new_uri(world, LV2_CORE__OutputPort);
948 jalv->nodes.lv2_connectionOptional = lilv_new_uri(world, LV2_CORE__connectionOptional);
949 jalv->nodes.lv2_control = lilv_new_uri(world, LV2_CORE__control);
950 jalv->nodes.lv2_default = lilv_new_uri(world, LV2_CORE__default);
951 jalv->nodes.lv2_enumeration = lilv_new_uri(world, LV2_CORE__enumeration);
952 jalv->nodes.lv2_extensionData = lilv_new_uri(world, LV2_CORE__extensionData);
953 jalv->nodes.lv2_integer = lilv_new_uri(world, LV2_CORE__integer);
954 jalv->nodes.lv2_maximum = lilv_new_uri(world, LV2_CORE__maximum);
955 jalv->nodes.lv2_minimum = lilv_new_uri(world, LV2_CORE__minimum);
956 jalv->nodes.lv2_name = lilv_new_uri(world, LV2_CORE__name);
957 jalv->nodes.lv2_reportsLatency = lilv_new_uri(world, LV2_CORE__reportsLatency);
958 jalv->nodes.lv2_sampleRate = lilv_new_uri(world, LV2_CORE__sampleRate);
959 jalv->nodes.lv2_symbol = lilv_new_uri(world, LV2_CORE__symbol);
960 jalv->nodes.lv2_toggled = lilv_new_uri(world, LV2_CORE__toggled);
961 jalv->nodes.midi_MidiEvent = lilv_new_uri(world, LV2_MIDI__MidiEvent);
962 jalv->nodes.pg_group = lilv_new_uri(world, LV2_PORT_GROUPS__group);
963 jalv->nodes.pprops_logarithmic = lilv_new_uri(world, LV2_PORT_PROPS__logarithmic);
964 jalv->nodes.pprops_notOnGUI = lilv_new_uri(world, LV2_PORT_PROPS__notOnGUI);
965 jalv->nodes.pprops_rangeSteps = lilv_new_uri(world, LV2_PORT_PROPS__rangeSteps);
966 jalv->nodes.pset_Preset = lilv_new_uri(world, LV2_PRESETS__Preset);
967 jalv->nodes.pset_bank = lilv_new_uri(world, LV2_PRESETS__bank);
968 jalv->nodes.rdfs_comment = lilv_new_uri(world, LILV_NS_RDFS "comment");
969 jalv->nodes.rdfs_label = lilv_new_uri(world, LILV_NS_RDFS "label");
970 jalv->nodes.rdfs_range = lilv_new_uri(world, LILV_NS_RDFS "range");
971 jalv->nodes.rsz_minimumSize = lilv_new_uri(world, LV2_RESIZE_PORT__minimumSize);
972 jalv->nodes.ui_showInterface = lilv_new_uri(world, LV2_UI__showInterface);
973 jalv->nodes.work_interface = lilv_new_uri(world, LV2_WORKER__interface);
974 jalv->nodes.work_schedule = lilv_new_uri(world, LV2_WORKER__schedule);
975 jalv->nodes.end = NULL;
976
977 /* Get plugin URI from loaded state or command line */
978 LilvState* state = NULL;
979 LilvNode* plugin_uri = NULL;
980 if (jalv->opts.load) {
981 struct stat info;
982 stat(jalv->opts.load, &info);
983 if (S_ISDIR(info.st_mode)) {
984 char* path = jalv_strjoin(jalv->opts.load, "/state.ttl");
985 state = lilv_state_new_from_file(jalv->world, &jalv->map, NULL, path);
986 free(path);
987 } else {
988 state = lilv_state_new_from_file(jalv->world, &jalv->map, NULL,
989 jalv->opts.load);
990 }
991 if (!state) {
992 fprintf(stderr, "Failed to load state from %s\n", jalv->opts.load);
993 jalv_close(jalv);
994 return -2;
995 }
996 plugin_uri = lilv_node_duplicate(lilv_state_get_plugin_uri(state));
997 } else if (*argc > 1) {
998 plugin_uri = lilv_new_uri(world, (*argv)[*argc - 1]);
999 }
1000
1001 if (!plugin_uri) {
1002 fprintf(stderr, "Missing plugin URI, try lv2ls to list plugins\n");
1003 jalv_close(jalv);
1004 return -3;
1005 }
1006
1007 /* Find plugin */
1008 printf("Plugin: %s\n", lilv_node_as_string(plugin_uri));
1009 jalv->plugin = lilv_plugins_get_by_uri(plugins, plugin_uri);
1010 lilv_node_free(plugin_uri);
1011 if (!jalv->plugin) {
1012 fprintf(stderr, "Failed to find plugin\n");
1013 jalv_close(jalv);
1014 return -4;
1015 }
1016
1017 /* Load preset, if specified */
1018 if (jalv->opts.preset) {
1019 LilvNode* preset = lilv_new_uri(jalv->world, jalv->opts.preset);
1020
1021 jalv_load_presets(jalv, NULL, NULL);
1022 state = lilv_state_new_from_world(jalv->world, &jalv->map, preset);
1023 jalv->preset = state;
1024 lilv_node_free(preset);
1025 if (!state) {
1026 fprintf(stderr, "Failed to find preset <%s>\n", jalv->opts.preset);
1027 jalv_close(jalv);
1028 return -5;
1029 }
1030 }
1031
1032 /* Check for thread-safe state restore() method. */
1033 LilvNode* state_threadSafeRestore = lilv_new_uri(
1034 jalv->world, LV2_STATE__threadSafeRestore);
1035 if (lilv_plugin_has_feature(jalv->plugin, state_threadSafeRestore)) {
1036 jalv->safe_restore = true;
1037 }
1038 lilv_node_free(state_threadSafeRestore);
1039
1040 if (!state) {
1041 /* Not restoring state, load the plugin as a preset to get default */
1042 state = lilv_state_new_from_world(
1043 jalv->world, &jalv->map, lilv_plugin_get_uri(jalv->plugin));
1044 }
1045
1046 /* Get a plugin UI */
1047 jalv->uis = lilv_plugin_get_uis(jalv->plugin);
1048 if (!jalv->opts.generic_ui) {
1049 if ((jalv->ui = jalv_select_custom_ui(jalv))) {
1050 const char* host_type_uri = jalv_native_ui_type();
1051 if (host_type_uri) {
1052 LilvNode* host_type = lilv_new_uri(jalv->world, host_type_uri);
1053
1054 if (!lilv_ui_is_supported(jalv->ui,
1055 suil_ui_supported,
1056 host_type,
1057 &jalv->ui_type)) {
1058 jalv->ui = NULL;
1059 }
1060
1061 lilv_node_free(host_type);
1062 }
1063 }
1064 }
1065
1066 /* Create ringbuffers for UI if necessary */
1067 if (jalv->ui) {
1068 fprintf(stderr, "UI: %s\n",
1069 lilv_node_as_uri(lilv_ui_get_uri(jalv->ui)));
1070 } else {
1071 fprintf(stderr, "UI: None\n");
1072 }
1073
1074 /* Create port and control structures */
1075 jalv_create_ports(jalv);
1076 jalv_create_controls(jalv, true);
1077 jalv_create_controls(jalv, false);
1078
1079 if (!(jalv->backend = jalv_backend_init(jalv))) {
1080 fprintf(stderr, "Failed to connect to audio system\n");
1081 jalv_close(jalv);
1082 return -6;
1083 }
1084
1085 printf("Sample rate: %u Hz\n", (uint32_t)jalv->sample_rate);
1086 printf("Block length: %u frames\n", jalv->block_length);
1087 printf("MIDI buffers: %zu bytes\n", jalv->midi_buf_size);
1088
1089 if (jalv->opts.buffer_size == 0) {
1090 /* The UI ring is fed by plugin output ports (usually one), and the UI
1091 updates roughly once per cycle. The ring size is a few times the
1092 size of the MIDI output to give the UI a chance to keep up. The UI
1093 should be able to keep up with 4 cycles, and tests show this works
1094 for me, but this value might need increasing to avoid overflows.
1095 */
1096 jalv->opts.buffer_size = jalv->midi_buf_size * N_BUFFER_CYCLES;
1097 }
1098
1099 if (jalv->opts.update_rate == 0.0) {
1100 /* Calculate a reasonable UI update frequency. */
1101 jalv->ui_update_hz = jalv_ui_refresh_rate(jalv);
1102 } else {
1103 /* Use user-specified UI update rate. */
1104 jalv->ui_update_hz = jalv->opts.update_rate;
1105 jalv->ui_update_hz = MAX(1.0f, jalv->ui_update_hz);
1106 }
1107
1108 /* The UI can only go so fast, clamp to reasonable limits */
1109 jalv->ui_update_hz = MIN(60, jalv->ui_update_hz);
1110 jalv->opts.buffer_size = MAX(4096, jalv->opts.buffer_size);
1111 fprintf(stderr, "Comm buffers: %u bytes\n", jalv->opts.buffer_size);
1112 fprintf(stderr, "Update rate: %.01f Hz\n", jalv->ui_update_hz);
1113
1114 /* Build options array to pass to plugin */
1115 const LV2_Options_Option options[ARRAY_SIZE(jalv->features.options)] = {
1116 { LV2_OPTIONS_INSTANCE, 0, jalv->urids.param_sampleRate,
1117 sizeof(float), jalv->urids.atom_Float, &jalv->sample_rate },
1118 { LV2_OPTIONS_INSTANCE, 0, jalv->urids.bufsz_minBlockLength,
1119 sizeof(int32_t), jalv->urids.atom_Int, &jalv->block_length },
1120 { LV2_OPTIONS_INSTANCE, 0, jalv->urids.bufsz_maxBlockLength,
1121 sizeof(int32_t), jalv->urids.atom_Int, &jalv->block_length },
1122 { LV2_OPTIONS_INSTANCE, 0, jalv->urids.bufsz_sequenceSize,
1123 sizeof(int32_t), jalv->urids.atom_Int, &jalv->midi_buf_size },
1124 { LV2_OPTIONS_INSTANCE, 0, jalv->urids.ui_updateRate,
1125 sizeof(float), jalv->urids.atom_Float, &jalv->ui_update_hz },
1126 { LV2_OPTIONS_INSTANCE, 0, 0, 0, 0, NULL }
1127 };
1128 memcpy(jalv->features.options, options, sizeof(jalv->features.options));
1129
1130 init_feature(&jalv->features.options_feature,
1131 LV2_OPTIONS__options,
1132 (void*)jalv->features.options);
1133
1134 init_feature(&jalv->features.safe_restore_feature,
1135 LV2_STATE__threadSafeRestore,
1136 NULL);
1137
1138 /* Create Plugin <=> UI communication buffers */
1139 jalv->ui_events = zix_ring_new(jalv->opts.buffer_size);
1140 jalv->plugin_events = zix_ring_new(jalv->opts.buffer_size);
1141 zix_ring_mlock(jalv->ui_events);
1142 zix_ring_mlock(jalv->plugin_events);
1143
1144 /* Build feature list for passing to plugins */
1145 const LV2_Feature* const features[] = {
1146 &jalv->features.map_feature,
1147 &jalv->features.unmap_feature,
1148 &jalv->features.sched_feature,
1149 &jalv->features.log_feature,
1150 &jalv->features.options_feature,
1151 &static_features[0],
1152 &static_features[1],
1153 &static_features[2],
1154 &static_features[3],
1155 NULL
1156 };
1157 jalv->feature_list = calloc(1, sizeof(features));
1158 if (!jalv->feature_list) {
1159 fprintf(stderr, "Failed to allocate feature list\n");
1160 jalv_close(jalv);
1161 return -7;
1162 }
1163 memcpy(jalv->feature_list, features, sizeof(features));
1164
1165 /* Check that any required features are supported */
1166 LilvNodes* req_feats = lilv_plugin_get_required_features(jalv->plugin);
1167 LILV_FOREACH(nodes, f, req_feats) {
1168 const char* uri = lilv_node_as_uri(lilv_nodes_get(req_feats, f));
1169 if (!feature_is_supported(jalv, uri)) {
1170 fprintf(stderr, "Feature %s is not supported\n", uri);
1171 jalv_close(jalv);
1172 return -8;
1173 }
1174 }
1175 lilv_nodes_free(req_feats);
1176
1177 /* Instantiate the plugin */
1178 jalv->instance = lilv_plugin_instantiate(
1179 jalv->plugin, jalv->sample_rate, jalv->feature_list);
1180 if (!jalv->instance) {
1181 fprintf(stderr, "Failed to instantiate plugin.\n");
1182 jalv_close(jalv);
1183 return -9;
1184 }
1185
1186 jalv->features.ext_data.data_access =
1187 lilv_instance_get_descriptor(jalv->instance)->extension_data;
1188
1189 fprintf(stderr, "\n");
1190 if (!jalv->buf_size_set) {
1191 jalv_allocate_port_buffers(jalv);
1192 }
1193
1194 /* Create workers if necessary */
1195 if (lilv_plugin_has_extension_data(jalv->plugin, jalv->nodes.work_interface)) {
1196 const LV2_Worker_Interface* iface = (const LV2_Worker_Interface*)
1197 lilv_instance_get_extension_data(jalv->instance, LV2_WORKER__interface);
1198
1199 jalv_worker_init(jalv, &jalv->worker, iface, true);
1200 if (jalv->safe_restore) {
1201 jalv_worker_init(jalv, &jalv->state_worker, iface, false);
1202 }
1203 }
1204
1205 /* Apply loaded state to plugin instance if necessary */
1206 if (state) {
1207 jalv_apply_state(jalv, state);
1208 }
1209
1210 if (jalv->opts.controls) {
1211 for (char** c = jalv->opts.controls; *c; ++c) {
1212 jalv_apply_control_arg(jalv, *c);
1213 }
1214 }
1215
1216 /* Create Jack ports and connect plugin ports to buffers */
1217 for (uint32_t i = 0; i < jalv->num_ports; ++i) {
1218 jalv_backend_activate_port(jalv, i);
1219 }
1220
1221 /* Print initial control values */
1222 for (size_t i = 0; i < jalv->controls.n_controls; ++i) {
1223 ControlID* control = jalv->controls.controls[i];
1224 if (control->type == PORT && control->is_writable) {
1225 struct Port* port = &jalv->ports[control->index];
1226 jalv_print_control(jalv, port, port->control);
1227 }
1228 }
1229
1230 /* Activate plugin */
1231 lilv_instance_activate(jalv->instance);
1232
1233 /* Discover UI */
1234 jalv->has_ui = jalv_discover_ui(jalv);
1235
1236 /* Activate Jack */
1237 jalv_backend_activate(jalv);
1238 jalv->play_state = JALV_RUNNING;
1239
1240 return 0;
1241 }
1242
1243 int
jalv_close(Jalv * const jalv)1244 jalv_close(Jalv* const jalv)
1245 {
1246 jalv->exit = true;
1247
1248 fprintf(stderr, "Exiting...\n");
1249
1250 /* Terminate the worker */
1251 jalv_worker_finish(&jalv->worker);
1252
1253 /* Deactivate audio */
1254 jalv_backend_deactivate(jalv);
1255 for (uint32_t i = 0; i < jalv->num_ports; ++i) {
1256 if (jalv->ports[i].evbuf) {
1257 lv2_evbuf_free(jalv->ports[i].evbuf);
1258 }
1259 }
1260 jalv_backend_close(jalv);
1261
1262 /* Destroy the worker */
1263 jalv_worker_destroy(&jalv->worker);
1264
1265 /* Deactivate plugin */
1266 #ifdef HAVE_SUIL
1267 suil_instance_free(jalv->ui_instance);
1268 #endif
1269 if (jalv->instance) {
1270 lilv_instance_deactivate(jalv->instance);
1271 lilv_instance_free(jalv->instance);
1272 }
1273
1274 /* Clean up */
1275 free(jalv->ports);
1276 zix_ring_free(jalv->ui_events);
1277 zix_ring_free(jalv->plugin_events);
1278 for (LilvNode** n = (LilvNode**)&jalv->nodes; *n; ++n) {
1279 lilv_node_free(*n);
1280 }
1281 symap_free(jalv->symap);
1282 zix_sem_destroy(&jalv->symap_lock);
1283 #ifdef HAVE_SUIL
1284 suil_host_free(jalv->ui_host);
1285 #endif
1286
1287 for (unsigned i = 0; i < jalv->controls.n_controls; ++i) {
1288 ControlID* const control = jalv->controls.controls[i];
1289 lilv_node_free(control->node);
1290 lilv_node_free(control->symbol);
1291 lilv_node_free(control->label);
1292 lilv_node_free(control->group);
1293 lilv_node_free(control->min);
1294 lilv_node_free(control->max);
1295 lilv_node_free(control->def);
1296 free(control);
1297 }
1298 free(jalv->controls.controls);
1299
1300 if (jalv->sratom) {
1301 sratom_free(jalv->sratom);
1302 }
1303 if (jalv->ui_sratom) {
1304 sratom_free(jalv->ui_sratom);
1305 }
1306 lilv_uis_free(jalv->uis);
1307 lilv_world_free(jalv->world);
1308
1309 zix_sem_destroy(&jalv->done);
1310
1311 remove(jalv->temp_dir);
1312 free(jalv->temp_dir);
1313 free(jalv->ui_event_buf);
1314 free(jalv->feature_list);
1315
1316 free(jalv->opts.name);
1317 free(jalv->opts.load);
1318 free(jalv->opts.controls);
1319
1320 return 0;
1321 }
1322
1323 int
main(int argc,char ** argv)1324 main(int argc, char** argv)
1325 {
1326 Jalv jalv;
1327 memset(&jalv, '\0', sizeof(Jalv));
1328
1329 if (jalv_open(&jalv, &argc, &argv)) {
1330 return EXIT_FAILURE;
1331 }
1332
1333 /* Set up signal handlers */
1334 setup_signals(&jalv);
1335
1336 /* Run UI (or prompt at console) */
1337 jalv_open_ui(&jalv);
1338
1339 /* Wait for finish signal from UI or signal handler */
1340 zix_sem_wait(&jalv.done);
1341
1342 return jalv_close(&jalv);
1343 }
1344