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 #ifndef JALV_INTERNAL_H
18 #define JALV_INTERNAL_H
19
20 #define _POSIX_C_SOURCE 200809L
21
22 #include "jalv_config.h"
23 #include "lv2_evbuf.h"
24 #include "symap.h"
25
26 #include "zix/ring.h"
27 #include "zix/sem.h"
28 #include "zix/thread.h"
29
30 #include "lilv/lilv.h"
31 #include "serd/serd.h"
32 #include "sratom/sratom.h"
33 #ifdef HAVE_SUIL
34 #include "suil/suil.h"
35 #endif
36
37 #include "lv2/atom/atom.h"
38 #include "lv2/atom/forge.h"
39 #include "lv2/core/lv2.h"
40 #include "lv2/data-access/data-access.h"
41 #include "lv2/log/log.h"
42 #include "lv2/options/options.h"
43 #include "lv2/state/state.h"
44 #include "lv2/ui/ui.h"
45 #include "lv2/urid/urid.h"
46 #include "lv2/worker/worker.h"
47
48 #ifdef HAVE_ISATTY
49 # include <unistd.h>
50 #endif
51
52 #include <stdarg.h>
53 #include <stdbool.h>
54 #include <stdint.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58
59 #ifdef __clang__
60 # define REALTIME __attribute__((annotate("realtime")))
61 #else
62 # define REALTIME
63 #endif
64
65 #ifdef __GNUC__
66 # define JALV_LOG_FUNC(fmt, arg1) __attribute__((format(printf, fmt, arg1)))
67 #else
68 # define JALV_LOG_FUNC(fmt, arg1)
69 #endif
70
71 #ifdef __cplusplus
72 extern "C" {
73 #endif
74
75 struct Jalv;
76
77 typedef struct JalvBackend JalvBackend;
78
79 typedef struct Jalv Jalv;
80
81 enum PortFlow {
82 FLOW_UNKNOWN,
83 FLOW_INPUT,
84 FLOW_OUTPUT
85 };
86
87 enum PortType {
88 TYPE_UNKNOWN,
89 TYPE_CONTROL,
90 TYPE_AUDIO,
91 TYPE_EVENT,
92 TYPE_CV
93 };
94
95 struct Port {
96 const LilvPort* lilv_port; ///< LV2 port
97 enum PortType type; ///< Data type
98 enum PortFlow flow; ///< Data flow direction
99 void* sys_port; ///< For audio/MIDI ports, otherwise NULL
100 LV2_Evbuf* evbuf; ///< For MIDI ports, otherwise NULL
101 void* widget; ///< Control widget, if applicable
102 size_t buf_size; ///< Custom buffer size, or 0
103 uint32_t index; ///< Port index
104 float control; ///< For control ports, otherwise 0.0f
105 };
106
107 /* Controls */
108
109 /** Type of plugin control. */
110 typedef enum {
111 PORT, ///< Control port
112 PROPERTY ///< Property (set via atom message)
113 } ControlType;
114
115 typedef struct {
116 float value;
117 char* label;
118 } ScalePoint;
119
120 /** Order scale points by value. */
121 int scale_point_cmp(const ScalePoint* a, const ScalePoint* b);
122
123 /** Plugin control. */
124 typedef struct {
125 Jalv* jalv;
126 ControlType type;
127 LilvNode* node;
128 LilvNode* symbol; ///< Symbol
129 LilvNode* label; ///< Human readable label
130 LV2_URID property; ///< Iff type == PROPERTY
131 uint32_t index; ///< Iff type == PORT
132 LilvNode* group; ///< Port/control group, or NULL
133 void* widget; ///< Control Widget
134 size_t n_points; ///< Number of scale points
135 ScalePoint* points; ///< Scale points
136 LV2_URID value_type; ///< Type of control value
137 LilvNode* min; ///< Minimum value
138 LilvNode* max; ///< Maximum value
139 LilvNode* def; ///< Default value
140 bool is_toggle; ///< Boolean (0 and 1 only)
141 bool is_integer; ///< Integer values only
142 bool is_enumeration; ///< Point values only
143 bool is_logarithmic; ///< Logarithmic scale
144 bool is_writable; ///< Writable (input)
145 bool is_readable; ///< Readable (output)
146 } ControlID;
147
148 ControlID*
149 new_port_control(Jalv* jalv, uint32_t index);
150
151 ControlID*
152 new_property_control(Jalv* jalv, const LilvNode* property);
153
154 typedef struct {
155 size_t n_controls;
156 ControlID** controls;
157 } Controls;
158
159 void
160 add_control(Controls* controls, ControlID* control);
161
162 ControlID*
163 get_property_control(const Controls* controls, LV2_URID property);
164
165 /**
166 Control change event, sent through ring buffers for UI updates.
167 */
168 typedef struct {
169 uint32_t index;
170 uint32_t protocol;
171 uint32_t size;
172 uint8_t body[];
173 } ControlChange;
174
175 typedef struct {
176 char* name; ///< Client name
177 int name_exact; ///< Exit if name is taken
178 char* load; ///< Path for state to load
179 char* preset; ///< URI of preset to load
180 char** controls; ///< Control values
181 uint32_t buffer_size; ///< Plugin <= >UI communication buffer size
182 double update_rate; ///< UI update rate in Hz
183 int dump; ///< Dump communication iff true
184 int trace; ///< Print trace log iff true
185 int generic_ui; ///< Use generic UI iff true
186 int show_hidden; ///< Show controls for notOnGUI ports
187 int no_menu; ///< Hide menu iff true
188 int show_ui; ///< Show non-embedded UI
189 int print_controls; ///< Print control changes to stdout
190 int non_interactive; ///< Do not listen for commands on stdin
191 char* ui_uri; ///< URI of UI to load
192 } JalvOptions;
193
194 typedef struct {
195 LV2_URID atom_Float;
196 LV2_URID atom_Int;
197 LV2_URID atom_Object;
198 LV2_URID atom_Path;
199 LV2_URID atom_String;
200 LV2_URID atom_eventTransfer;
201 LV2_URID bufsz_maxBlockLength;
202 LV2_URID bufsz_minBlockLength;
203 LV2_URID bufsz_sequenceSize;
204 LV2_URID log_Error;
205 LV2_URID log_Trace;
206 LV2_URID log_Warning;
207 LV2_URID midi_MidiEvent;
208 LV2_URID param_sampleRate;
209 LV2_URID patch_Get;
210 LV2_URID patch_Put;
211 LV2_URID patch_Set;
212 LV2_URID patch_body;
213 LV2_URID patch_property;
214 LV2_URID patch_value;
215 LV2_URID time_Position;
216 LV2_URID time_bar;
217 LV2_URID time_barBeat;
218 LV2_URID time_beatUnit;
219 LV2_URID time_beatsPerBar;
220 LV2_URID time_beatsPerMinute;
221 LV2_URID time_frame;
222 LV2_URID time_speed;
223 LV2_URID ui_updateRate;
224 } JalvURIDs;
225
226 typedef struct {
227 LilvNode* atom_AtomPort;
228 LilvNode* atom_Chunk;
229 LilvNode* atom_Float;
230 LilvNode* atom_Path;
231 LilvNode* atom_Sequence;
232 LilvNode* lv2_AudioPort;
233 LilvNode* lv2_CVPort;
234 LilvNode* lv2_ControlPort;
235 LilvNode* lv2_InputPort;
236 LilvNode* lv2_OutputPort;
237 LilvNode* lv2_connectionOptional;
238 LilvNode* lv2_control;
239 LilvNode* lv2_default;
240 LilvNode* lv2_enumeration;
241 LilvNode* lv2_extensionData;
242 LilvNode* lv2_integer;
243 LilvNode* lv2_maximum;
244 LilvNode* lv2_minimum;
245 LilvNode* lv2_name;
246 LilvNode* lv2_reportsLatency;
247 LilvNode* lv2_sampleRate;
248 LilvNode* lv2_symbol;
249 LilvNode* lv2_toggled;
250 LilvNode* midi_MidiEvent;
251 LilvNode* pg_group;
252 LilvNode* pprops_logarithmic;
253 LilvNode* pprops_notOnGUI;
254 LilvNode* pprops_rangeSteps;
255 LilvNode* pset_Preset;
256 LilvNode* pset_bank;
257 LilvNode* rdfs_comment;
258 LilvNode* rdfs_label;
259 LilvNode* rdfs_range;
260 LilvNode* rsz_minimumSize;
261 LilvNode* ui_showInterface;
262 LilvNode* work_interface;
263 LilvNode* work_schedule;
264 LilvNode* end; ///< NULL terminator for easy freeing of entire structure
265 } JalvNodes;
266
267 typedef enum {
268 JALV_RUNNING,
269 JALV_PAUSE_REQUESTED,
270 JALV_PAUSED
271 } JalvPlayState;
272
273 typedef struct {
274 Jalv* jalv; ///< Pointer back to Jalv
275 ZixRing* requests; ///< Requests to the worker
276 ZixRing* responses; ///< Responses from the worker
277 void* response; ///< Worker response buffer
278 ZixSem sem; ///< Worker semaphore
279 ZixThread thread; ///< Worker thread
280 const LV2_Worker_Interface* iface; ///< Plugin worker interface
281 bool threaded; ///< Run work in another thread
282 } JalvWorker;
283
284 typedef struct {
285 LV2_Feature map_feature;
286 LV2_Feature unmap_feature;
287 LV2_State_Make_Path make_path;
288 LV2_Feature make_path_feature;
289 LV2_Worker_Schedule sched;
290 LV2_Feature sched_feature;
291 LV2_Worker_Schedule ssched;
292 LV2_Feature state_sched_feature;
293 LV2_Log_Log llog;
294 LV2_Feature log_feature;
295 LV2_Options_Option options[6];
296 LV2_Feature options_feature;
297 LV2_Feature safe_restore_feature;
298 LV2UI_Request_Value request_value;
299 LV2_Feature request_value_feature;
300 LV2_Extension_Data_Feature ext_data;
301 } JalvFeatures;
302
303 struct Jalv {
304 JalvOptions opts; ///< Command-line options
305 JalvURIDs urids; ///< URIDs
306 JalvNodes nodes; ///< Nodes
307 LV2_Atom_Forge forge; ///< Atom forge
308 const char* prog_name; ///< Program name (argv[0])
309 LilvWorld* world; ///< Lilv World
310 LV2_URID_Map map; ///< URI => Int map
311 LV2_URID_Unmap unmap; ///< Int => URI map
312 SerdEnv* env; ///< Environment for RDF printing
313 Sratom* sratom; ///< Atom serialiser
314 Sratom* ui_sratom; ///< Atom serialiser for UI thread
315 Symap* symap; ///< URI map
316 ZixSem symap_lock; ///< Lock for URI map
317 JalvBackend* backend; ///< Audio system backend
318 ZixRing* ui_events; ///< Port events from UI
319 ZixRing* plugin_events; ///< Port events from plugin
320 void* ui_event_buf; ///< Buffer for reading UI port events
321 JalvWorker worker; ///< Worker thread implementation
322 JalvWorker state_worker; ///< Synchronous worker for state restore
323 ZixSem work_lock; ///< Lock for plugin work() method
324 ZixSem done; ///< Exit semaphore
325 ZixSem paused; ///< Paused signal from process thread
326 JalvPlayState play_state; ///< Current play state
327 char* temp_dir; ///< Temporary plugin state directory
328 char* save_dir; ///< Plugin save directory
329 const LilvPlugin* plugin; ///< Plugin class (RDF data)
330 LilvState* preset; ///< Current preset
331 LilvUIs* uis; ///< All plugin UIs (RDF data)
332 const LilvUI* ui; ///< Plugin UI (RDF data)
333 const LilvNode* ui_type; ///< Plugin UI type (unwrapped)
334 LilvInstance* instance; ///< Plugin instance (shared library)
335 #ifdef HAVE_SUIL
336 SuilHost* ui_host; ///< Plugin UI host support
337 SuilInstance* ui_instance; ///< Plugin UI instance (shared library)
338 #endif
339 void* window; ///< Window (if applicable)
340 struct Port* ports; ///< Port array of size num_ports
341 Controls controls; ///< Available plugin controls
342 uint32_t block_length; ///< Audio buffer size (block length)
343 size_t midi_buf_size; ///< Size of MIDI port buffers
344 uint32_t control_in; ///< Index of control input port
345 uint32_t num_ports; ///< Size of the two following arrays:
346 uint32_t plugin_latency; ///< Latency reported by plugin (if any)
347 float ui_update_hz; ///< Frequency of UI updates
348 float sample_rate; ///< Sample rate
349 uint32_t event_delta_t; ///< Frames since last update sent to UI
350 uint32_t position; ///< Transport position in frames
351 float bpm; ///< Transport tempo in beats per minute
352 bool rolling; ///< Transport speed (0=stop, 1=play)
353 bool buf_size_set; ///< True iff buffer size callback fired
354 bool exit; ///< True iff execution is finished
355 bool has_ui; ///< True iff a control UI is present
356 bool request_update; ///< True iff a plugin update is needed
357 bool safe_restore; ///< Plugin restore() is thread-safe
358 JalvFeatures features;
359 const LV2_Feature** feature_list;
360 };
361
362 int
363 jalv_open(Jalv* jalv, int* argc, char*** argv);
364
365 int
366 jalv_init(int* argc, char*** argv, JalvOptions* opts);
367
368 int
369 jalv_close(Jalv* jalv);
370
371 JalvBackend*
372 jalv_backend_init(Jalv* jalv);
373
374 void
375 jalv_backend_activate(Jalv* jalv);
376
377 void
378 jalv_backend_deactivate(Jalv* jalv);
379
380 void
381 jalv_backend_close(Jalv* jalv);
382
383 /** Expose a port to the system (if applicable) and connect it to its buffer. */
384 void
385 jalv_backend_activate_port(Jalv* jalv, uint32_t port_index);
386
387 void
388 jalv_create_ports(Jalv* jalv);
389
390 void
391 jalv_allocate_port_buffers(Jalv* jalv);
392
393 struct Port*
394 jalv_port_by_symbol(Jalv* jalv, const char* sym);
395
396 void
397 jalv_create_controls(Jalv* jalv, bool writable);
398
399 ControlID*
400 jalv_control_by_symbol(Jalv* jalv, const char* sym);
401
402 void
403 jalv_set_control(const ControlID* control,
404 uint32_t size,
405 LV2_URID type,
406 const void* body);
407
408 const char*
409 jalv_native_ui_type(void);
410
411 bool
412 jalv_discover_ui(Jalv* jalv);
413
414 float
415 jalv_ui_refresh_rate(Jalv* jalv);
416
417 int
418 jalv_open_ui(Jalv* jalv);
419
420 void
421 jalv_init_ui(Jalv* jalv);
422
423 int
424 jalv_close_ui(Jalv* jalv);
425
426 void
427 jalv_ui_instantiate(Jalv* jalv,
428 const char* native_ui_type,
429 void* parent);
430
431 bool
432 jalv_ui_is_resizable(Jalv* jalv);
433
434 void
435 jalv_ui_write(void* jalv_handle,
436 uint32_t port_index,
437 uint32_t buffer_size,
438 uint32_t protocol,
439 const void* buffer);
440
441 void
442 jalv_apply_ui_events(Jalv* jalv, uint32_t nframes);
443
444 uint32_t
445 jalv_ui_port_index(void* controller, const char* symbol);
446
447 void
448 jalv_ui_port_event(Jalv* jalv,
449 uint32_t port_index,
450 uint32_t buffer_size,
451 uint32_t protocol,
452 const void* buffer);
453
454 bool
455 jalv_send_to_ui(Jalv* jalv,
456 uint32_t port_index,
457 uint32_t type,
458 uint32_t size,
459 const void* body);
460 bool
461 jalv_run(Jalv* jalv, uint32_t nframes);
462
463 int
464 jalv_update(Jalv* jalv);
465
466 typedef int (*PresetSink)(Jalv* jalv,
467 const LilvNode* node,
468 const LilvNode* title,
469 void* data);
470
471 int
472 jalv_load_presets(Jalv* jalv, PresetSink sink, void* data);
473
474 int
475 jalv_unload_presets(Jalv* jalv);
476
477 int
478 jalv_apply_preset(Jalv* jalv, const LilvNode* preset);
479
480 int
481 jalv_delete_current_preset(Jalv* jalv);
482
483 int
484 jalv_save_preset(Jalv* jalv,
485 const char* dir,
486 const char* uri,
487 const char* label,
488 const char* filename);
489
490 void
491 jalv_save(Jalv* jalv, const char* dir);
492
493 void
494 jalv_save_port_values(Jalv* jalv,
495 SerdWriter* writer,
496 const SerdNode* subject);
497 char*
498 jalv_make_path(LV2_State_Make_Path_Handle handle,
499 const char* path);
500
501 void
502 jalv_apply_state(Jalv* jalv, LilvState* state);
503
504 char*
505 atom_to_turtle(LV2_URID_Unmap* unmap,
506 const SerdNode* subject,
507 const SerdNode* predicate,
508 const LV2_Atom* atom);
509
510 static inline void
jalv_print_control(Jalv * jalv,const struct Port * port,float value)511 jalv_print_control(Jalv* jalv, const struct Port* port, float value)
512 {
513 const LilvNode* sym = lilv_port_get_symbol(jalv->plugin, port->lilv_port);
514 printf("%s = %f\n", lilv_node_as_string(sym), value);
515 }
516
517 static inline char*
jalv_strdup(const char * str)518 jalv_strdup(const char* str)
519 {
520 const size_t len = strlen(str);
521 char* copy = (char*)malloc(len + 1);
522 memcpy(copy, str, len + 1);
523 return copy;
524 }
525
526 static inline char*
jalv_strjoin(const char * a,const char * b)527 jalv_strjoin(const char* a, const char* b)
528 {
529 const size_t a_len = strlen(a);
530 const size_t b_len = strlen(b);
531 char* const out = (char*)malloc(a_len + b_len + 1);
532
533 memcpy(out, a, a_len);
534 memcpy(out + a_len, b, b_len);
535 out[a_len + b_len] = '\0';
536
537 return out;
538 }
539
540 JALV_LOG_FUNC(3, 4)
541 int
542 jalv_printf(LV2_Log_Handle handle,
543 LV2_URID type,
544 const char* fmt, ...);
545
546 JALV_LOG_FUNC(3, 0)
547 int
548 jalv_vprintf(LV2_Log_Handle handle,
549 LV2_URID type,
550 const char* fmt,
551 va_list ap);
552
553 static inline bool
jalv_ansi_start(FILE * stream,int color)554 jalv_ansi_start(FILE* stream, int color)
555 {
556 #if defined(HAVE_ISATTY) && defined(HAVE_FILENO)
557 if (isatty(fileno(stream))) {
558 return fprintf(stream, "\033[0;%dm", color);
559 }
560 #endif
561 return 0;
562 }
563
564 static inline void
jalv_ansi_reset(FILE * stream)565 jalv_ansi_reset(FILE* stream)
566 {
567 #ifdef HAVE_ISATTY
568 if (isatty(fileno(stream))) {
569 fprintf(stream, "\033[0m");
570 fflush(stream);
571 }
572 #endif
573 }
574
575 #ifdef __cplusplus
576 } // extern "C"
577 #endif
578
579 #endif // JALV_INTERNAL_H
580