1 /*
2  * Copyright (c) 2015-2021 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 _MOONY_H
19 #define _MOONY_H
20 
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stdint.h>
24 #include <stdatomic.h>
25 
26 #if !defined(_WIN32)
27 #	include <sys/mman.h>
28 #else
29 #	define mlock(...)
30 #	define munlock(...)
31 #endif
32 
33 #include <lv2/lv2plug.in/ns/ext/atom/atom.h>
34 #include <lv2/lv2plug.in/ns/ext/atom/util.h>
35 #include <lv2/lv2plug.in/ns/ext/atom/forge.h>
36 #include <lv2/lv2plug.in/ns/ext/midi/midi.h>
37 #include <lv2/lv2plug.in/ns/ext/time/time.h>
38 #include <lv2/lv2plug.in/ns/ext/urid/urid.h>
39 #include <lv2/lv2plug.in/ns/ext/worker/worker.h>
40 #include <lv2/lv2plug.in/ns/ext/log/log.h>
41 #include <lv2/lv2plug.in/ns/ext/log/logger.h>
42 #include <lv2/lv2plug.in/ns/ext/state/state.h>
43 #include <lv2/lv2plug.in/ns/ext/buf-size/buf-size.h>
44 #include <lv2/lv2plug.in/ns/ext/options/options.h>
45 #include <lv2/lv2plug.in/ns/ext/patch/patch.h>
46 #include <lv2/lv2plug.in/ns/ext/parameters/parameters.h>
47 #include <lv2/lv2plug.in/ns/lv2core/lv2.h>
48 #include <lv2/lv2plug.in/ns/extensions/ui/ui.h>
49 #include <lv2/lv2plug.in/ns/extensions/units/units.h>
50 
51 typedef struct _atom_ser_t atom_ser_t;
52 
53 struct _atom_ser_t {
54 	void *data; // e.g. use rt-memory pool?
55 	uint32_t size;
56 	union {
57 		uint8_t *buf;
58 		const LV2_Atom *atom;
59 	};
60 	uint32_t offset;
61 };
62 
63 #include <api_vm.h>
64 #include <osc.lv2/osc.h>
65 #include <xpress.lv2/xpress.h>
66 #include <varchunk.h>
67 
68 #include <lua.h>
69 #include <lauxlib.h>
70 
71 #include <canvas.lv2/forge.h>
72 #if defined(BUILD_INLINE_DISP)
73 #	include <canvas.lv2/idisp.h>
74 #endif
75 
76 #define __realtime __attribute__((annotate("realtime")))
77 #define __non_realtime __attribute__((annotate("non-realtime")))
78 
79 #ifdef LV2_ATOM_TUPLE_FOREACH
80 #	undef LV2_ATOM_TUPLE_FOREACH
81 #	define LV2_ATOM_TUPLE_FOREACH(tuple, iter) \
82 	for (LV2_Atom* (iter) = lv2_atom_tuple_begin(tuple); \
83 	     !lv2_atom_tuple_is_end(LV2_ATOM_BODY(tuple), (tuple)->atom.size, (iter)); \
84 	     (iter) = lv2_atom_tuple_next(iter))
85 #endif
86 
87 #define MOONY_MAX_CHUNK_LEN		0x20000 // 128KB
88 #define MOONY_MAX_ERROR_LEN		0x800 // 2KB
89 
90 #define MOONY_URI							"http://open-music-kontrollers.ch/lv2/moony"
91 #define MOONY_PREFIX					MOONY_URI"#"
92 
93 #define MOONY_CODE_URI				MOONY_URI"#code"
94 #define MOONY_ERROR_URI				MOONY_URI"#error"
95 #define MOONY_TRACE_URI				MOONY_URI"#trace"
96 #define MOONY_STATE_URI				MOONY_URI"#state"
97 #define MOONY_PANIC_URI				MOONY_URI"#panic"
98 
99 #define MOONY__color					MOONY_URI"#color"
100 #define MOONY__syntax					MOONY_URI"#syntax"
101 
102 #define MOONY_EDITOR_HIDDEN_URI	MOONY_URI"#editorHidden"
103 #define MOONY_GRAPH_HIDDEN_URI	MOONY_URI"#graphHidden"
104 #define MOONY_LOG_HIDDEN_URI	MOONY_URI"#logHidden"
105 #define MOONY_LOG_FOLLOW_URI	MOONY_URI"#logFollow"
106 #define MOONY_LOG_RESET_URI	MOONY_URI"#logReset"
107 #define MOONY_PARAM_HIDDEN_URI	MOONY_URI"#paramHidden"
108 #define MOONY_FONT_HEIGHT_URI	MOONY_URI"#fontHeight"
109 
110 #define MOONY_PARAM_COLS_URI	MOONY_URI"#paramCols"
111 #define MOONY_PARAM_ROWS_URI	MOONY_URI"#paramRows"
112 
113 #define MOONY_NK_URI					MOONY_URI"#moony_ui"
114 #define MOONY_D2TK_URI				MOONY_URI"#moony_d2tk"
115 
116 #define MOONY_C1XC1_URI				MOONY_URI"#c1xc1"
117 #define MOONY_C2XC2_URI				MOONY_URI"#c2xc2"
118 #define MOONY_C4XC4_URI				MOONY_URI"#c4xc4"
119 
120 #define MOONY_A1XA1_URI				MOONY_URI"#a1xa1"
121 #define MOONY_A2XA2_URI				MOONY_URI"#a2xa2"
122 #define MOONY_A4XA4_URI				MOONY_URI"#a4xa4"
123 
124 #define MOONY_C1A1XC1A1_URI		MOONY_URI"#c1a1xc1a1"
125 #define MOONY_C2A1XC2A1_URI		MOONY_URI"#c2a1xc2a1"
126 #define MOONY_C4A1XC4A1_URI		MOONY_URI"#c4a1xc4a1"
127 
128 #define LUA__lang							"http://lua.org#lang"
129 
130 extern const LV2_Descriptor c1xc1;
131 extern const LV2_Descriptor c2xc2;
132 extern const LV2_Descriptor c4xc4;
133 
134 extern const LV2_Descriptor a1xa1;
135 extern const LV2_Descriptor a2xa2;
136 extern const LV2_Descriptor a4xa4;
137 
138 extern const LV2_Descriptor c1a1xc1a1;
139 extern const LV2_Descriptor c2a1xc2a1;
140 extern const LV2_Descriptor c4a1xc4a1;
141 
142 extern const LV2UI_Descriptor nk_ui;
143 extern const LV2UI_Descriptor simple_ui;
144 extern const LV2UI_Descriptor simple_kx;
145 
146 typedef enum _moony_udata_t {
147 	MOONY_UDATA_ATOM,
148 	MOONY_UDATA_FORGE,
149 	MOONY_UDATA_STASH,
150 
151 	MOONY_UDATA_COUNT
152 } moony_udata_t;
153 
154 typedef enum _moony_upclosure_t {
155 	MOONY_UPCLOSURE_TUPLE_FOREACH,
156 	MOONY_UPCLOSURE_VECTOR_FOREACH,
157 	MOONY_UPCLOSURE_OBJECT_FOREACH,
158 	MOONY_UPCLOSURE_SEQUENCE_FOREACH,
159 	MOONY_UPCLOSURE_SEQUENCE_MULTIPLEX,
160 
161 	MOONY_UPCLOSURE_COUNT
162 } moony_upclosure_t;
163 
164 // from api_atom.c
165 typedef struct _lheader_t lheader_t;
166 typedef struct _latom_driver_t latom_driver_t;
167 typedef struct _latom_driver_hash_t latom_driver_hash_t;
168 
169 struct _lheader_t {
170 	moony_udata_t type;
171 	bool cache;
172 };
173 
174 struct _latom_driver_hash_t {
175 	LV2_URID type;
176 	const latom_driver_t *driver;
177 };
178 
179 #define DRIVER_HASH_MAX 15
180 
181 // from moony.c
182 typedef struct _patch_t patch_t;
183 typedef struct _moony_t moony_t;
184 
185 struct _patch_t {
186 	LV2_URID self;
187 
188 	LV2_URID get;
189 	LV2_URID set;
190 	LV2_URID put;
191 	LV2_URID patch;
192 	LV2_URID body;
193 	LV2_URID subject;
194 	LV2_URID property;
195 	LV2_URID value;
196 	LV2_URID add;
197 	LV2_URID remove;
198 	LV2_URID wildcard;
199 	LV2_URID writable;
200 	LV2_URID readable;
201 	LV2_URID destination;
202 	LV2_URID sequence;
203 	LV2_URID error;
204 	LV2_URID ack;
205 	LV2_URID delete;
206 	LV2_URID copy;
207 	LV2_URID move;
208 	LV2_URID insert;
209 };
210 
211 struct _moony_t {
212 	LV2_URID_Map *map;
213 	LV2_URID_Unmap *unmap;
214 	LV2_Options_Option *opts;
215 
216 	LV2_Atom_Forge forge;
217 	LV2_Atom_Forge state_forge;
218 	LV2_Atom_Forge stash_forge;
219 	LV2_Atom_Forge notify_forge;
220 
221 	LV2_Atom_Forge_Frame notify_frame;
222 	LV2_Atom_Forge_Ref notify_ref;
223 	LV2_Atom_Forge notify_snapshot;
224 
225 	LV2_Atom_Float sample_rate;
226 
227 	struct {
228 		LV2_URID moony_code;
229 		LV2_URID moony_error;
230 		LV2_URID moony_trace;
231 		LV2_URID moony_panic;
232 		LV2_URID moony_state;
233 		LV2_URID moony_editorHidden;
234 		LV2_URID moony_graphHidden;
235 		LV2_URID moony_logHidden;
236 		LV2_URID moony_logFollow;
237 		LV2_URID moony_logReset;
238 		LV2_URID moony_paramHidden;
239 		LV2_URID moony_paramCols;
240 		LV2_URID moony_paramRows;
241 		LV2_URID moony_color;
242 		LV2_URID moony_syntax;
243 
244 		LV2_URID midi_event;
245 
246 		patch_t patch;
247 
248 		LV2_URID rdfs_label;
249 		LV2_URID rdfs_range;
250 		LV2_URID rdfs_comment;
251 
252 		LV2_URID rdf_value;
253 
254 		LV2_URID lv2_minimum;
255 		LV2_URID lv2_maximum;
256 		LV2_URID lv2_scale_point;
257 		LV2_URID lv2_minor_version;
258 		LV2_URID lv2_micro_version;
259 
260 		LV2_URID units_unit;
261 		LV2_URID units_symbol;
262 
263 		LV2_URID atom_beat_time;
264 		LV2_URID atom_frame_time;
265 		LV2_URID atom_child_type;
266 
267 		LV2_URID xpress_Token;
268 		LV2_URID xpress_Alive;
269 		LV2_URID xpress_source;
270 		LV2_URID xpress_uuid;
271 		LV2_URID xpress_zone;
272 		LV2_URID xpress_body;
273 		LV2_URID xpress_pitch;
274 		LV2_URID xpress_pressure;
275 		LV2_URID xpress_timbre;
276 		LV2_URID xpress_dPitch;
277 		LV2_URID xpress_dPressure;
278 		LV2_URID xpress_dTimbre;
279 
280 		LV2_URID param_sampleRate;
281 	} uris;
282 
283 	LV2_OSC_URID osc_urid;
284 	LV2_OSC_Schedule *osc_sched;
285 
286 	LV2_Worker_Schedule *sched;
287 
288 	LV2_Log_Log *log;
289 	LV2_Log_Logger logger;
290 
291 	xpress_t xpress;
292 
293 	LV2_Canvas_URID canvas_urid;
294 #if defined(BUILD_INLINE_DISP)
295 	LV2_Canvas_Idisp canvas_idisp;
296 	varchunk_t *to_idisp;
297 	LV2_Atom *canvas_graph;
298 #endif
299 
300 	moony_vm_t *vm;
301 	atomic_uintptr_t vm_new;
302 
303 	bool once;
304 	bool error_out;
305 
306 	// udata cache
307 	int itr [MOONY_UDATA_COUNT];
308 	int upc [MOONY_UPCLOSURE_COUNT];
309 
310 	atomic_flag state_lock;
311 
312 	LV2_Atom *state_atom;
313 	atomic_uintptr_t state_atom_new;
314 
315 	LV2_Atom *stash_atom;
316 	uint32_t stash_size;
317 
318 	varchunk_t *from_dsp;
319 
320 	latom_driver_hash_t atom_driver_hash [DRIVER_HASH_MAX];
321 
322 	size_t mem_size;
323 	bool testing;
324 
325 	atomic_int editor_hidden;
326 	atomic_int graph_hidden;
327 	atomic_int log_hidden;
328 	atomic_int log_follow;
329 	atomic_int log_reset;
330 	atomic_int param_hidden;
331 	atomic_int param_cols;
332 	atomic_int param_rows;
333 
334 	char error [MOONY_MAX_ERROR_LEN];
335 	atomic_uintptr_t err_new;
336 
337 	char chunk [MOONY_MAX_CHUNK_LEN];
338 	atomic_uintptr_t chunk_new;
339 	char *chunk_nrt;
340 };
341 
342 // in api.c
343 int moony_init(moony_t *moony, const char *subject, double sample_rate,
344 	const LV2_Feature *const *features, size_t mem_size, bool testing);
345 void moony_deinit(moony_t *moony);
346 void moony_open(moony_t *moony, moony_vm_t *vm, lua_State *L);
347 void moony_pre(moony_t *moony, LV2_Atom_Sequence *notify);
348 bool moony_in(moony_t *moony, const LV2_Atom_Sequence *control, LV2_Atom_Sequence *notify);
349 void moony_out(moony_t *moony, LV2_Atom_Sequence *notify, uint32_t frames);
350 const void* extension_data(const char* uri);
351 void *moony_newuserdata(lua_State *L, moony_t *moony, moony_udata_t type, bool cache);
352 LV2_Worker_Status moony_wake_worker(const LV2_Worker_Schedule *work_sched);
353 
354 __realtime static inline void
moony_freeuserdata(moony_t * moony)355 moony_freeuserdata(moony_t *moony)
356 {
357 	for(unsigned i=0; i<MOONY_UDATA_COUNT; i++)
358 		moony->itr[i] = 1; // reset iterator
359 	for(unsigned i=0; i<MOONY_UPCLOSURE_COUNT; i++)
360 		moony->upc[i] = 1; // reset iterator
361 }
362 
363 __realtime static inline bool
moony_bypass(moony_t * moony)364 moony_bypass(moony_t *moony)
365 {
366 	return moony->error[0] != 0x0;
367 }
368 
369 __realtime static inline const char *
_err_skip(const char * msg)370 _err_skip(const char *msg)
371 {
372 	const char *err = strstr(msg, "\"]:"); // search end mark of header [string ""]:
373 	err = err
374 		? err + 3 // skip header end mark
375 		: msg; // use whole error string alternatively
376 
377 	return err;
378 }
379 
380 __non_realtime static inline void
moony_err_async(moony_t * moony,const char * msg)381 moony_err_async(moony_t *moony, const char *msg)
382 {
383 	const char *err = _err_skip(msg);
384 
385 	if(moony->log)
386 		lv2_log_error(&moony->logger, "%s\n", err);
387 
388 	char *err_new = strdup(err);
389 	if(err_new)
390 	{
391 		char *err_old = (char *)atomic_exchange_explicit(&moony->err_new, (uintptr_t)err_new, memory_order_relaxed);
392 
393 		if(err_old)
394 			free(err_old);
395 	}
396 }
397 
398 __realtime static inline void
moony_err(moony_t * moony,const char * msg)399 moony_err(moony_t *moony, const char *msg)
400 {
401 	const char *err = _err_skip(msg);
402 
403 	if(moony->log)
404 		lv2_log_trace(&moony->logger, "%s\n", err);
405 
406 	if(moony->error[0] == 0x0) // don't overwrite any previous error message
407 		snprintf(moony->error, MOONY_MAX_ERROR_LEN, "%s", err);
408 	moony->error_out = true;
409 }
410 
411 __realtime static inline void
moony_trace(moony_t * moony,const char * msg)412 moony_trace(moony_t *moony, const char *msg)
413 {
414 	const char *err = _err_skip(msg);
415 
416 	if(moony->log)
417 		lv2_log_trace(&moony->logger, "%s\n", err);
418 }
419 
420 __realtime static inline lua_State *
moony_current(moony_t * moony)421 moony_current(moony_t *moony)
422 {
423 	return moony->vm->L;
424 }
425 
426 __realtime static inline void
moony_error(moony_t * moony)427 moony_error(moony_t *moony)
428 {
429 	lua_State *L = moony_current(moony);
430 
431 	const char *msg = lua_tostring(L, -1);
432 	if(msg)
433 		moony_err(moony, msg);
434 	lua_pop(L, 1);
435 }
436 
437 #define _spin_lock(FLAG) while(atomic_flag_test_and_set_explicit((FLAG), memory_order_acquire)) {}
438 #define _try_lock(FLAG) !atomic_flag_test_and_set_explicit((FLAG), memory_order_acquire)
439 #define _unlock(FLAG) atomic_flag_clear_explicit((FLAG), memory_order_release)
440 
441 __realtime static inline LV2_Atom_Forge_Ref
_moony_patch(patch_t * patch,LV2_Atom_Forge * forge,LV2_URID key,const char * str,uint32_t size)442 _moony_patch(patch_t *patch, LV2_Atom_Forge *forge, LV2_URID key,
443 	const char *str, uint32_t size)
444 {
445 	LV2_Atom_Forge_Frame frame;
446 
447 	LV2_Atom_Forge_Ref ref = lv2_atom_forge_object(forge, &frame, 0, str ? patch->set : patch->get)
448 		&& lv2_atom_forge_key(forge, patch->subject)
449 		&& lv2_atom_forge_urid(forge, patch->self)
450 		&& lv2_atom_forge_key(forge, patch->property)
451 		&& lv2_atom_forge_urid(forge, key);
452 
453 	if(ref && str)
454 	{
455 		ref = lv2_atom_forge_key(forge, patch->value)
456 			&& lv2_atom_forge_string(forge, str, size);
457 	}
458 
459 	if(ref)
460 	{
461 		lv2_atom_forge_pop(forge, &frame);
462 		return 1; // success
463 	}
464 
465 	return 0; // overflow
466 }
467 
468 void *
469 moony_rt_alloc(moony_vm_t *vm, size_t nsize);
470 
471 void *
472 moony_rt_realloc(moony_vm_t *vm, void *buf, size_t osize, size_t nsize);
473 
474 void
475 moony_rt_free(moony_vm_t *vm, void *buf, size_t osize);
476 
477 LV2_Atom_Forge_Ref
478 _sink_rt(LV2_Atom_Forge_Sink_Handle handle, const void *buf, uint32_t size);
479 LV2_Atom_Forge_Ref
480 _sink_non_rt(LV2_Atom_Forge_Sink_Handle handle, const void *buf, uint32_t size);
481 
482 LV2_Atom *
483 _deref(LV2_Atom_Forge_Sink_Handle handle, LV2_Atom_Forge_Ref ref);
484 
485 #endif // _MOONY_H
486