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