1 /*
2  * Copyright (c) 2015-2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
3  *
4  * This is free software: you can redistribute it and/or modify
5  * it under the terms of the Artistic License 2.0 as published by
6  * The Perl Foundation.
7  *
8  * This source is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * Artistic License 2.0 for more details.
12  *
13  * You should have received a copy of the Artistic License 2.0
14  * along the source as a COPYING file. If not, obtain it from
15  * http://www.perlfoundation.org/artistic_license_2_0.
16  */
17 
18 #ifndef _SYNTHPOD_APP_PRIVATE_H
19 #define _SYNTHPOD_APP_PRIVATE_H
20 
21 #include <limits.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <stdatomic.h>
25 #include <ctype.h> // isspace
26 #include <math.h>
27 #include <semaphore.h>
28 #include <pthread.h>
29 
30 #include <synthpod_app.h>
31 #include <synthpod_private.h>
32 
33 #include <sratom/sratom.h>
34 #include <varchunk.h>
35 
36 #include <lv2_extensions.h> // ardour's inline display
37 
38 #define CROSS_CLOCK_IMPLEMENTATION
39 #include <cross_clock/cross_clock.h>
40 
41 #define XSD_PREFIX "http://www.w3.org/2001/XMLSchema#"
42 #define RDF_PREFIX "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
43 #define RDFS_PREFIX "http://www.w3.org/2000/01/rdf-schema#"
44 #define SPOD_PREFIX "http://open-music-kontrollers.ch/lv2/synthpod#"
45 
46 #define URN_UUID_LENGTH 46
47 
48 #define NUM_FEATURES 17
49 #define MAX_SOURCES 32 // TODO how many?
50 #define MAX_MODS 512 // TODO how many?
51 #define MAX_SLAVES 7 // e.g. 8-core machines
52 #define MAX_AUTOMATIONS 64
53 #define ALIAS_MAX 32
54 
55 typedef enum _job_type_request_t job_type_request_t;
56 typedef enum _job_type_reply_t job_type_reply_t;
57 typedef enum _blocking_state_t blocking_state_t;
58 typedef enum _silencing_state_t silencing_state_t;
59 typedef enum _ramp_state_t ramp_state_t;
60 typedef enum _auto_type_t auto_type_t;
61 
62 typedef char urn_uuid_t [URN_UUID_LENGTH];
63 typedef struct _dsp_slave_t dsp_slave_t;
64 typedef struct _dsp_client_t dsp_client_t;
65 typedef struct _dsp_master_t dsp_master_t;
66 
67 typedef struct _mod_worker_t mod_worker_t;
68 typedef struct _midi_auto_t midi_auto_t;
69 typedef struct _osc_auto_t osc_auto_t;
70 typedef struct _auto_t auto_t;
71 typedef struct _mod_t mod_t;
72 typedef struct _port_t port_t;
73 typedef struct _job_t job_t;
74 typedef struct _source_t source_t;
75 typedef struct _pool_t pool_t;
76 typedef struct _port_driver_t port_driver_t;
77 typedef struct _app_prof_t app_prof_t;
78 typedef struct _mod_prof_t mod_prof_t;
79 
80 typedef void (*port_multiplex_cb_t) (sp_app_t *app, port_t *port, uint32_t nsamples);
81 typedef void (*port_transfer_cb_t) (sp_app_t *app, port_t *port, uint32_t nsamples);
82 
83 enum _silencing_state_t {
84 	SILENCING_STATE_RUN = 0,
85 	SILENCING_STATE_BLOCK,
86 	SILENCING_STATE_WAIT
87 };
88 
89 enum _blocking_state_t {
90 	BLOCKING_STATE_RUN = 0,
91 	BLOCKING_STATE_DRAIN,
92 	BLOCKING_STATE_BLOCK,
93 	BLOCKING_STATE_WAIT,
94 };
95 
96 static const bool advance_ui [] = {
97 	[BLOCKING_STATE_RUN]		= true,
98 	[BLOCKING_STATE_DRAIN]	= false,
99 	[BLOCKING_STATE_BLOCK]	= true,
100 	[BLOCKING_STATE_WAIT]		= false
101 };
102 
103 static const bool advance_work [] = {
104 	[BLOCKING_STATE_RUN]		= true,
105 	[BLOCKING_STATE_DRAIN]	= true,
106 	[BLOCKING_STATE_BLOCK]	= true,
107 	[BLOCKING_STATE_WAIT]		= true
108 };
109 
110 enum _ramp_state_t {
111 	RAMP_STATE_NONE = 0,
112 	RAMP_STATE_UP,
113 	RAMP_STATE_DOWN,
114 	RAMP_STATE_DOWN_DEL,
115 	RAMP_STATE_DOWN_DRAIN,
116 	RAMP_STATE_DOWN_DISABLE,
117 };
118 
119 enum _job_type_request_t {
120 	JOB_TYPE_REQUEST_MODULE_SUPPORTED,
121 	JOB_TYPE_REQUEST_MODULE_ADD,
122 	JOB_TYPE_REQUEST_MODULE_DEL,
123 	JOB_TYPE_REQUEST_MODULE_REINSTANTIATE,
124 	JOB_TYPE_REQUEST_PRESET_LOAD,
125 	JOB_TYPE_REQUEST_PRESET_SAVE,
126 	JOB_TYPE_REQUEST_BUNDLE_LOAD,
127 	JOB_TYPE_REQUEST_BUNDLE_SAVE,
128 	JOB_TYPE_REQUEST_DRAIN
129 };
130 
131 enum _job_type_reply_t {
132 	JOB_TYPE_REPLY_MODULE_SUPPORTED,
133 	JOB_TYPE_REPLY_MODULE_ADD,
134 	JOB_TYPE_REPLY_MODULE_DEL,
135 	JOB_TYPE_REPLY_MODULE_REINSTANTIATE,
136 	JOB_TYPE_REPLY_PRESET_LOAD,
137 	JOB_TYPE_REPLY_PRESET_SAVE,
138 	JOB_TYPE_REPLY_BUNDLE_LOAD,
139 	JOB_TYPE_REPLY_BUNDLE_SAVE,
140 	JOB_TYPE_REPLY_DRAIN
141 };
142 
143 struct _dsp_slave_t {
144 	dsp_master_t *dsp_master;
145 	sem_t sem;
146 	pthread_t thread;
147 };
148 
149 struct _dsp_client_t {
150 	atomic_int ref_count;
151 	unsigned num_sinks;
152 	unsigned num_sources;
153 	dsp_client_t *sinks [64]; //FIXME
154 
155 #if defined(USE_DYNAMIC_PARALLELIZER)
156 	unsigned weight;
157 #else
158 	int count;
159 	unsigned mark;
160 #endif
161 };
162 
163 struct _dsp_master_t {
164 	dsp_slave_t dsp_slaves [MAX_SLAVES];
165 	atomic_bool kill;
166 	atomic_bool emergency_exit;
167 	sem_t sem;
168 	unsigned concurrent;
169 	unsigned num_slaves;
170 	uint32_t nsamples;
171 };
172 
173 struct _job_t {
174 	union {
175 		job_type_request_t request;
176 		job_type_reply_t reply;
177 	};
178 	union {
179 		mod_t *mod;
180 		int32_t status;
181 	};
182 	LV2_URID urn;
183 };
184 
185 struct _pool_t {
186 	size_t size;
187 	void *buf;
188 };
189 
190 struct _app_prof_t {
191 	struct timespec t0;
192 	struct timespec t1;
193 	unsigned sum;
194 	unsigned min;
195 	unsigned max;
196 	unsigned count;
197 };
198 
199 struct _mod_prof_t {
200 	unsigned sum;
201 	unsigned min;
202 	unsigned max;
203 };
204 
205 struct _mod_worker_t {
206 	sem_t sem;
207 	pthread_t thread;
208 	atomic_bool kill;
209 	varchunk_t *app_to_worker;
210 	varchunk_t *state_to_worker;
211 	varchunk_t *app_from_worker;
212 };
213 
214 enum _auto_type_t {
215 	AUTO_TYPE_NONE = 0,
216 	AUTO_TYPE_MIDI,
217 	AUTO_TYPE_OSC
218 };
219 
220 struct _midi_auto_t {
221 	int8_t channel;
222 	int8_t controller;
223 };
224 
225 struct _osc_auto_t {
226 	char path [128]; //TODO how big?
227 };
228 
229 struct _auto_t {
230 	auto_type_t type;
231 	uint32_t index;
232 	LV2_URID property;
233 	LV2_URID range;
234 
235 	int src_enabled;
236 	int snk_enabled;
237 
238 	double a;
239 	double b;
240 	double c;
241 	double d;
242 
243 	double mul;
244 	double add;
245 
246 	bool sync;
247 	bool learning;
248 
249 	union {
250 		midi_auto_t midi;
251 		osc_auto_t osc;
252 	};
253 };
254 
255 struct _mod_t {
256 	sp_app_t *app;
257 	int32_t uid;
258 	urn_uuid_t urn_uri;
259 	LV2_URID urn;
260 	LV2_URID visible;
261 	bool disabled;
262 
263 	bool delete_request;
264 	bool needs_bypassing;
265 	bool bypassed;
266 
267 	// worker
268 	struct {
269 		const LV2_Worker_Interface *iface;
270 		LV2_Worker_Schedule schedule;
271 	} worker;
272 
273 	mod_worker_t mod_worker;
274 
275 	LV2_Worker_Schedule state_worker;
276 	LV2_Feature state_feature_list [1];
277 	LV2_Feature *state_features [2];
278 
279 	// system_port
280 	bool system_ports;
281 
282 	// log
283 	LV2_Log_Log log;
284 
285 	// make_path
286 	LV2_State_Make_Path make_path;
287 
288 	struct {
289 		const LV2_Inline_Display_Interface *iface;
290 		const LV2_Inline_Display_Image_Surface *surf;
291 		LV2_Inline_Display queue_draw;
292 		atomic_bool draw_queued;
293 		atomic_flag lock;
294 		bool subscribed;
295 		uint32_t counter;
296 		uint32_t threshold;
297 	} idisp;
298 
299 	// opts
300 	struct {
301 		LV2_Options_Option options [7];
302 		const LV2_Options_Interface *iface;
303 	} opts;
304 
305 	// state
306 	struct {
307 		const LV2_State_Interface *iface;
308 	} state;
309 
310 	// features
311 	LV2_Feature feature_list [NUM_FEATURES];
312 	const LV2_Feature *features [NUM_FEATURES + 1];
313 
314 	// self
315 	const LilvPlugin *plug;
316 	LV2_URID plug_urid;
317 	LilvInstance *inst;
318 	LV2_Handle handle;
319 	LilvNodes *presets;
320 	char *uri_str;
321 
322 	// ports
323 	unsigned num_ports;
324 	port_t *ports;
325 
326 	pool_t pools [PORT_TYPE_NUM];
327 	mod_prof_t prof;
328 
329 	dsp_client_t dsp_client;
330 
331 	struct {
332 		float x;
333 		float y;
334 	} pos;
335 
336 	char alias [ALIAS_MAX];
337 	LV2_URID ui;
338 	auto_t automations [MAX_AUTOMATIONS];
339 };
340 
341 struct _port_driver_t {
342 	port_multiplex_cb_t multiplex;
343 	port_transfer_cb_t transfer;
344 	bool sparse_update;
345 };
346 
347 struct _source_t {
348 	port_t *port;
349 	float gain;
350 	struct {
351 		float x;
352 		float y;
353 	} pos;
354 
355 	// ramping
356 	struct {
357 		int can;
358 		int samples;
359 		ramp_state_t state;
360 		float value;
361 	} ramp;
362 };
363 
364 typedef struct _connectable_t connectable_t;
365 typedef struct _control_port_t control_port_t;
366 typedef struct _audio_port_t audio_port_t;
367 typedef struct _cv_port_t cv_port_t;
368 typedef struct _atom_port_t atom_port_t;
369 
370 struct _connectable_t {
371 	int num_sources;
372 	source_t sources [MAX_SOURCES];
373 };
374 
375 struct _control_port_t {
376 	bool is_integer;
377 	bool is_toggled;
378 
379 	float dflt;
380 	float min;
381 	float max;
382 	float range;
383 	float range_1;
384 	float last;
385 	int32_t i32;
386 	float f32;
387 	bool auto_dirty;
388 
389 	float stash;
390 	bool stashing;
391 	atomic_flag lock;
392 };
393 
394 struct _audio_port_t {
395 	connectable_t connectable;
396 	float last;
397 };
398 
399 struct _cv_port_t {
400 	connectable_t connectable;
401 	float last;
402 };
403 
404 struct _atom_port_t {
405 	connectable_t connectable;
406 	port_buffer_type_t buffer_type; // none, sequence
407 	bool patchable; // support patch:Message
408 };
409 
410 struct _port_t {
411 	mod_t *mod;
412 
413 	uint32_t index;
414 	const char *symbol;
415 
416 	size_t size;
417 	void *base;
418 
419 	port_type_t type; // audio, CV, control, atom
420 	port_direction_t direction; // input, output
421 	LV2_URID protocol; // floatProtocol, peakProtocol, atomTransfer, eventTransfer
422 	const port_driver_t *driver;
423 
424 	int subscriptions; // subsriptions reference counter
425 
426 	// system_port iface
427 	struct {
428 		system_port_t type;
429 		void *data;
430 	} sys;
431 
432 	union {
433 		control_port_t control;
434 		audio_port_t audio;
435 		cv_port_t cv;
436 		atom_port_t atom;
437 	};
438 };
439 
440 struct _sp_app_t {
441 	sp_app_driver_t *driver;
442 	void *data;
443 
444 	atomic_bool dirty;
445 
446 	blocking_state_t block_state;
447 	silencing_state_t silence_state;
448 	bool load_bundle;
449 
450 	struct {
451 		const char *home;
452 	} dir;
453 
454 	int embedded;
455 	LilvWorld *world;
456 	const LilvPlugins *plugs;
457 
458 	reg_t regs;
459 	LV2_Atom_Forge forge;
460 
461 	unsigned num_mods;
462 	mod_t *mods [MAX_MODS];
463 
464 	sp_app_system_source_t system_sources [64]; //FIXME, how many?
465 	sp_app_system_sink_t system_sinks [64]; //FIXME, how many?
466 
467 	LV2_State_Make_Path make_path;
468 	LV2_State_Map_Path map_path;
469 	LV2_Feature state_feature_list [2];
470 	LV2_Feature *state_features [3];
471 #pragma GCC diagnostic push
472 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
473 	LV2_URI_Map_Feature uri_to_id;
474 #pragma GCC diagnostic pop
475 
476 	char *bundle_path;
477 	char *bundle_filename;
478 	LV2_URID bundle_urn; //FIXME use this instead of bundle_path
479 
480 	struct {
481 		unsigned period_cnt;
482 		unsigned bound;
483 		unsigned counter;
484 	} fps;
485 
486 	int ramp_samples;
487 
488 	Sratom *sratom;
489 	app_prof_t prof;
490 
491 	int32_t ncols;
492 	int32_t nrows;
493 	float nleft;
494 
495 	dsp_master_t dsp_master;
496 
497 	LV2_OSC_URID osc_urid;
498 
499 	cross_clock_t clk_mono;
500 	cross_clock_t clk_real;
501 
502 	struct {
503 		float x;
504 		float y;
505 	} pos;
506 
507 	int32_t column_enabled;
508 	int32_t row_enabled;
509 };
510 
511 extern const port_driver_t control_port_driver;
512 extern const port_driver_t audio_port_driver;
513 extern const port_driver_t cv_port_driver;
514 extern const port_driver_t atom_port_driver;
515 extern const port_driver_t seq_port_driver;
516 
517 #define PORT_BASE_ALIGNED(PORT) ASSUME_ALIGNED((PORT)->base)
518 #define PORT_SIZE(PORT) ((PORT)->size)
519 
520 /*
521  * Debug
522  */
523 int __attribute__((format(printf, 2, 3)))
524 sp_app_log_error(sp_app_t *app, const char *fmt, ...);
525 
526 int __attribute__((format(printf, 2, 3)))
527 sp_app_log_note(sp_app_t *app, const char *fmt, ...);
528 
529 int __attribute__((format(printf, 2, 3)))
530 sp_app_log_warning(sp_app_t *app, const char *fmt, ...);
531 
532 int __attribute__((format(printf, 2, 3)))
533 sp_app_log_trace(sp_app_t *app, const char *fmt, ...);
534 
535 /*
536  * UI
537  */
538 static inline void *
__sp_app_to_ui_request(sp_app_t * app,size_t minimum,size_t * maximum)539 __sp_app_to_ui_request(sp_app_t *app, size_t minimum, size_t *maximum)
540 {
541 	if(app->driver->to_ui_request)
542 		return app->driver->to_ui_request(minimum, maximum, app->data);
543 
544 	sp_app_log_trace(app, "%s: failed to request buffer\n", __func__);
545 	return NULL;
546 }
547 #define _sp_app_to_ui_request(APP, MINIMUM) \
548 	ASSUME_ALIGNED(__sp_app_to_ui_request((APP), (MINIMUM), NULL))
549 #define _sp_app_to_ui_request_max(APP, MINIMUM, MAXIMUM) \
550 	ASSUME_ALIGNED(__sp_app_to_ui_request((APP), (MINIMUM), (MAXIMUM)))
551 
552 static inline void
_sp_app_to_ui_advance(sp_app_t * app,size_t written)553 _sp_app_to_ui_advance(sp_app_t *app, size_t written)
554 {
555 	if(app->driver->to_ui_advance)
556 		app->driver->to_ui_advance(written, app->data);
557 	else
558 		sp_app_log_trace(app, "%s: failed to advance buffer\n", __func__);
559 }
560 
561 static inline LV2_Atom *
_sp_app_to_ui_request_atom(sp_app_t * app)562 _sp_app_to_ui_request_atom(sp_app_t *app)
563 {
564 	size_t maximum;
565 	LV2_Atom *atom = _sp_app_to_ui_request_max(app, 4096, &maximum); //FIXME what should minimum be?
566 
567 	if(atom)
568 		lv2_atom_forge_set_buffer(&app->forge, (uint8_t *)atom, maximum);
569 	else
570 		sp_app_log_trace(app, "%s: failed to request atom\n", __func__);
571 
572 	return atom;
573 }
574 
575 static inline void
_sp_app_to_ui_advance_atom(sp_app_t * app,const LV2_Atom * atom)576 _sp_app_to_ui_advance_atom(sp_app_t *app, const LV2_Atom *atom)
577 {
578 	_sp_app_to_ui_advance(app, lv2_atom_total_size(atom));
579 }
580 
581 static inline void
_sp_app_to_ui_overflow(sp_app_t * app)582 _sp_app_to_ui_overflow(sp_app_t *app)
583 {
584 	sp_app_log_trace(app, "%s: buffer overflow\n", __func__);
585 }
586 
587 static inline LV2_Atom *
_sp_request_atom(sp_app_t * app,sp_to_request_t req,void * data)588 _sp_request_atom(sp_app_t *app, sp_to_request_t req, void *data)
589 {
590 	size_t maximum;
591 	LV2_Atom *atom = req(4096, &maximum, data); //FIXME what should minimum be?
592 
593 	if(atom)
594 		lv2_atom_forge_set_buffer(&app->forge, (uint8_t *)atom, maximum);
595 	else
596 		sp_app_log_trace(app, "%s: failed to request atom\n", __func__);
597 
598 	return atom;
599 }
600 
601 static inline void
_sp_advance_atom(sp_app_t * app,const LV2_Atom * atom,sp_to_advance_t adv,void * data)602 _sp_advance_atom(sp_app_t *app, const LV2_Atom *atom, sp_to_advance_t adv, void *data)
603 {
604 	adv(lv2_atom_total_size(atom), data);
605 }
606 
607 /*
608  * Worker
609  */
610 
611 static inline void *
__sp_app_to_worker_request(sp_app_t * app,size_t minimum,size_t * maximum)612 __sp_app_to_worker_request(sp_app_t *app, size_t minimum, size_t *maximum)
613 {
614 	if(app->driver->to_worker_request)
615 		return app->driver->to_worker_request(minimum, maximum, app->data);
616 
617 	sp_app_log_trace(app, "%s: failed to request buffer\n", __func__);
618 	return NULL;
619 }
620 #define _sp_app_to_worker_request(APP, MINIMUM) \
621 	ASSUME_ALIGNED(__sp_app_to_worker_request((APP), (MINIMUM), NULL))
622 #define _sp_app_to_worker_request_max(APP, MINIMUM, MAXIMUM) \
623 	ASSUME_ALIGNED(__sp_app_to_worker_request((APP), (MINIMUM), (MAXIMUM)))
624 
625 static inline void
_sp_app_to_worker_advance(sp_app_t * app,size_t written)626 _sp_app_to_worker_advance(sp_app_t *app, size_t written)
627 {
628 	if(app->driver->to_worker_advance)
629 		app->driver->to_worker_advance(written, app->data);
630 	else
631 		sp_app_log_trace(app, "%s: failed to advance buffer\n", __func__);
632 }
633 
634 void
635 _sp_app_order(sp_app_t *app);
636 
637 void
638 _sp_app_reset(sp_app_t *app);
639 
640 void
641 _sp_app_populate(sp_app_t *app);
642 
643 /*
644  * State
645  */
646 void
647 _sp_app_state_preset_restore(sp_app_t *app, mod_t *mod, LilvState *const state,
648 	bool async);
649 
650 int
651 _sp_app_state_preset_load(sp_app_t *app, mod_t *mod, const char *uri, bool async);
652 
653 LilvState *
654 _sp_app_state_preset_create(sp_app_t *app, mod_t *mod, const char *bndl);
655 
656 int
657 _sp_app_state_preset_save(sp_app_t *app, mod_t *mod, const char *target);
658 
659 int
660 _sp_app_state_bundle_save(sp_app_t *app, const char *bundle_path);
661 
662 int
663 _sp_app_state_bundle_load(sp_app_t *app, const char *bundle_path);
664 
665 /*
666  * Mod
667  */
668 mod_t *
669 _sp_app_mod_add(sp_app_t *app, const char *uri, LV2_URID urn);
670 
671 void
672 _sp_app_mod_eject(sp_app_t *app, mod_t *mod);
673 
674 int
675 _sp_app_mod_del(sp_app_t *app, mod_t *mod);
676 
677 mod_t *
678 _sp_app_mod_get_by_uid(sp_app_t *app, int32_t uid);
679 
680 void
681 _sp_app_mod_reinitialize(mod_t *mod);
682 
683 LV2_Worker_Status
684 _sp_app_mod_worker_work_sync(mod_t *mod, size_t size, const void *payload);
685 
686 void
687 _sp_app_mod_queue_draw(mod_t *mod);
688 
689 void
690 _sp_app_mod_reinstantiate(sp_app_t *app, mod_t *mod);
691 
692 /*
693  * Port
694  */
695 void
696 _dsp_master_reorder(sp_app_t *app);
697 
698 void
699 _sp_app_port_disconnect(sp_app_t *app, port_t *src_port, port_t *snk_port);
700 
701 int
702 _sp_app_port_disconnect_request(sp_app_t *app, port_t *src_port, port_t *snk_port,
703 	ramp_state_t ramp_state);
704 
705 bool
706 _sp_app_port_connected(port_t *src_port, port_t *snk_port, float gain);
707 
708 int
709 _sp_app_port_connect(sp_app_t *app, port_t *src_port, port_t *snk_port, float gain);
710 
711 int
712 _sp_app_port_silence_request(sp_app_t *app, port_t *src_port, port_t *snk_port,
713 	ramp_state_t ramp_state);
714 
715 void
716 _sp_app_port_control_stash(port_t *port);
717 
718 int
719 _sp_app_port_desilence(sp_app_t *app, port_t *src_port, port_t *snk_port);
720 
721 connectable_t *
722 _sp_app_port_connectable(port_t *src_port);
723 
724 static inline void
_sp_app_port_spin_lock(control_port_t * control)725 _sp_app_port_spin_lock(control_port_t *control)
726 {
727 	while(atomic_flag_test_and_set_explicit(&control->lock, memory_order_acquire))
728 	{
729 		// spin
730 	}
731 }
732 
733 static inline bool
_sp_app_port_try_lock(control_port_t * control)734 _sp_app_port_try_lock(control_port_t *control)
735 {
736 	return atomic_flag_test_and_set_explicit(&control->lock, memory_order_acquire) == false;
737 }
738 
739 static inline void
_sp_app_port_unlock(control_port_t * control)740 _sp_app_port_unlock(control_port_t *control)
741 {
742 	atomic_flag_clear_explicit(&control->lock, memory_order_release);
743 }
744 
745 /*
746  * Ui
747  */
748 void
749 _sp_app_ui_set_modlist(sp_app_t *app, LV2_URID subj, int32_t seqn);
750 
751 void
752 _connection_list_add(sp_app_t *app, const LV2_Atom_Object *obj);
753 
754 void
755 _node_list_add(sp_app_t *app, const LV2_Atom_Object *obj);
756 
757 void
758 _automation_refresh_mul_add(auto_t *automation);
759 
760 void
761 _automation_list_add(sp_app_t *app, const LV2_Atom_Object *obj);
762 
763 LV2_Atom_Forge_Ref
764 _sp_app_forge_midi_automation(sp_app_t *app, LV2_Atom_Forge_Frame *frame,
765 	mod_t *mod, port_t *port, const auto_t *automation);
766 
767 LV2_Atom_Forge_Ref
768 _sp_app_forge_osc_automation(sp_app_t *app, LV2_Atom_Forge_Frame *frame,
769 	mod_t *mod, port_t *port, const auto_t *automation);
770 
771 #endif
772