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 #include <limits.h> // INT_MAX
19 #include <math.h> // INFINITY
20 #include <inttypes.h>
21 #include <stdatomic.h>
22 
23 #include <osc.lv2/endian.h>
24 #include <xpress.lv2/xpress.h>
25 
26 #include <api_atom.h>
27 #include <api_forge.h>
28 #include <api_stash.h>
29 #include <api_midi.h>
30 #include <api_osc.h>
31 #include <api_time.h>
32 #include <api_state.h>
33 #include <api_parameter.h>
34 
35 #define RDF_PREFIX    "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
36 #define RDFS_PREFIX   "http://www.w3.org/2000/01/rdf-schema#"
37 
38 #define RDF__value    RDF_PREFIX"value"
39 #define RDF__type     RDF_PREFIX"type"
40 #define RDFS__label   RDFS_PREFIX"label"
41 #define RDFS__range   RDFS_PREFIX"range"
42 #define RDFS__comment RDFS_PREFIX"comment"
43 
44 #ifndef LV2_PATCH__Copy
45 #	define LV2_PATCH__Copy LV2_PATCH_PREFIX "Copy"
46 #endif
47 
48 #ifndef LV2_PATCH__Insert
49 #	define LV2_PATCH__Insert LV2_PATCH_PREFIX "Insert"
50 #endif
51 
52 #ifndef LV2_PATCH__accept
53 #	define LV2_PATCH__accept LV2_PATCH_PREFIX "accept"
54 #endif
55 
56 #ifndef LV2_PATCH__context
57 #	define LV2_PATCH__context LV2_PATCH_PREFIX "context"
58 #endif
59 
60 #ifndef LV2_UNITS__midiController
61 #	define LV2_UNITS__midiController LV2_UNITS_PREFIX "midiController"
62 #endif
63 
64 static const char *moony_ref [MOONY_UDATA_COUNT] = {
65 	[MOONY_UDATA_ATOM]	= "latom",
66 	[MOONY_UDATA_FORGE]	= "lforge",
67 	[MOONY_UDATA_STASH]	= "lstash"
68 };
69 
70 static const size_t moony_sz [MOONY_UDATA_COUNT] = {
71 	[MOONY_UDATA_ATOM]	= sizeof(latom_t),
72 	[MOONY_UDATA_FORGE]	= sizeof(lforge_t),
73 	[MOONY_UDATA_STASH]	= sizeof(lstash_t)
74 };
75 
76 __non_realtime static int
_hash_sort(const void * itm1,const void * itm2)77 _hash_sort(const void *itm1, const void *itm2)
78 {
79 	const latom_driver_hash_t *hash1 = itm1;
80 	const latom_driver_hash_t *hash2 = itm2;
81 
82 	if(hash1->type < hash2->type)
83 		return -1;
84 	else if(hash1->type > hash2->type)
85 		return 1;
86 	return 0;
87 }
88 
89 __realtime static int // map is not really realtime in most hosts
_lmap__index(lua_State * L)90 _lmap__index(lua_State *L)
91 {
92 	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
93 
94 	const char *uri = luaL_checkstring(L, 2);
95 	LV2_URID urid = moony->map->map(moony->map->handle, uri); // non-rt
96 	if(urid)
97 	{
98 		lua_pushinteger(L, urid);
99 
100 		// cache it
101 		lua_pushvalue(L, 2); // uri
102 		lua_pushvalue(L, -2); // urid
103 		lua_rawset(L, 1);  // self
104 	}
105 	else
106 		lua_pushnil(L);
107 
108 	return 1;
109 }
110 
111 static const luaL_Reg lmap_mt [] = {
112 	{"__index", _lmap__index},
113 	{"__call", _lmap__index},
114 	{NULL, NULL}
115 };
116 
117 __realtime static int // unmap is not really realtime in most hosts
_lunmap__index(lua_State * L)118 _lunmap__index(lua_State *L)
119 {
120 	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
121 
122 	LV2_URID urid = luaL_checkinteger(L, 2);
123 	const char *uri = moony->unmap->unmap(moony->unmap->handle, urid); // non-rt
124 	if(uri)
125 	{
126 		lua_pushstring(L, uri);
127 
128 		// cache it
129 		lua_pushvalue(L, 2); // urid
130 		lua_pushvalue(L, -2); // uri
131 		lua_rawset(L, 1);  // self
132 	}
133 	else
134 		lua_pushnil(L);
135 
136 	return 1;
137 }
138 
139 static const luaL_Reg lunmap_mt [] = {
140 	{"__index", _lunmap__index},
141 	{"__call", _lunmap__index},
142 	{NULL, NULL}
143 };
144 
145 __realtime static int // map is not really realtime in most hosts
_lmapper__index(lua_State * L)146 _lmapper__index(lua_State *L)
147 {
148 	//moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
149 
150 	if(lua_isstring(L, 2))
151 	{
152 		lua_getglobal(L, "Map");
153 		lua_pushvalue(L, lua_upvalueindex(2)); // uri.prefix
154 		lua_pushvalue(L, 2); // uri.postfix
155 		lua_concat(L, 2); // uri
156 		lua_gettable(L, -2); // Map[uri];
157 		if(lua_isinteger(L, -1))
158 		{
159 			// cache it
160 			lua_pushvalue(L, 2); // uri
161 			lua_pushvalue(L, -2); // urid
162 			lua_rawset(L, 1);  // self
163 		}
164 		else
165 			lua_pushnil(L);
166 	}
167 	else
168 		lua_pushnil(L);
169 
170 	return 1;
171 }
172 
173 static const luaL_Reg lhash_map_mt [] = {
174 	{"__index", _lmapper__index},
175 	{"__call", _lmapper__index},
176 	{NULL, NULL}
177 };
178 
179 __realtime static int // map is not really realtime in most hosts
_lmapper(lua_State * L)180 _lmapper(lua_State *L)
181 {
182 	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
183 
184 	if(lua_isstring(L, 1))
185 	{
186 		lua_newtable(L);
187 		lua_newtable(L);
188 		lua_pushlightuserdata(L, moony); // @ upvalueindex 1
189 		lua_pushvalue(L, 1); // uri.prefix @ upvalueindex 2
190 		luaL_setfuncs(L, lhash_map_mt, 2);
191 		//_protect_metatable(L, -1); //TODO
192 		lua_setmetatable(L, -2);
193 	}
194 	else
195 		lua_pushnil(L);
196 
197 	return 1;
198 }
199 
200 __realtime static int
_lvoice_map(lua_State * L)201 _lvoice_map(lua_State *L)
202 {
203 	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
204 
205 	lua_pushinteger(L, xpress_map(&moony->xpress));
206 	return 1;
207 }
208 
209 __realtime static int
_lmidi2cps(lua_State * L)210 _lmidi2cps(lua_State *L)
211 {
212 	const lua_Number note = luaL_checknumber(L, 1);
213 	const lua_Number base = luaL_optnumber(L, 2, 69.0);
214 	const lua_Number noct = luaL_optnumber(L, 3, 12.0);
215 	const lua_Number fref = luaL_optnumber(L, 4, 440.0);
216 
217 	const lua_Number cps = exp2( (note - base) / noct) * fref;
218 
219 	lua_pushnumber(L, cps);
220 	return 1;
221 }
222 
223 __realtime static int
_lcps2midi(lua_State * L)224 _lcps2midi(lua_State *L)
225 {
226 	const lua_Number cps = luaL_checknumber(L, 1);
227 	const lua_Number base = luaL_optnumber(L, 2, 69.0);
228 	const lua_Number noct = luaL_optnumber(L, 3, 12.0);
229 	const lua_Number fref = luaL_optnumber(L, 4, 440.0);
230 
231 	const lua_Number note = log2(cps / fref) * noct + base;
232 
233 	lua_pushnumber(L, note);
234 	return 1;
235 }
236 
237 static const char *note_keys [12] = {
238 	"C", "C#",
239 	"D", "D#",
240 	"E",
241 	"F", "F#",
242 	"G", "G#",
243 	"A", "A#",
244 	"B"
245 };
246 
247 __realtime static int
_lnote__index(lua_State * L)248 _lnote__index(lua_State *L)
249 {
250 	//moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
251 
252 	lua_settop(L, 2); // ignore superfluous arguments
253 
254 	const int type = lua_type(L, 2);
255 	if(type == LUA_TNUMBER)
256 	{
257 		const int note = lua_tointeger(L, 2);
258 
259 		if( (note >= 0) && (note < 0x80) )
260 		{
261 			char name [16];
262 			const int8_t octave = note / 12 - 1;
263 			const uint8_t key = note % 12;
264 			snprintf(name, 16, "%s%+"PRIi8, note_keys[key], octave);
265 
266 			lua_pushstring(L, name);
267 			return 1;
268 		}
269 	}
270 	else if(type == LUA_TSTRING)
271 	{
272 		size_t str_len;
273 		const char *str = lua_tolstring(L, 2, &str_len);
274 
275 		for(int i=0; i<12; i++)
276 		{
277 			const char *key = note_keys[i];
278 			const size_t key_len = strlen(key);
279 
280 			if( (str_len - 2 == key_len) && !strncmp(str, key, key_len) )
281 			{
282 				const int octave = atoi(str + key_len);
283 				const int note = (octave + 1)*12 + i;
284 				if( (note >= 0) && (note < 0x80) )
285 				{
286 					lua_pushinteger(L, note);
287 					return 1;
288 				}
289 			}
290 		}
291 	}
292 
293 	lua_pushnil(L);
294 	return 1;
295 }
296 
297 static const luaL_Reg lnote_mt [] = {
298 	{"__index", _lnote__index},
299 	{"__call", _lnote__index},
300 	{NULL, NULL}
301 };
302 
303 __realtime static int
_lopts__index(lua_State * L)304 _lopts__index(lua_State *L)
305 {
306 	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
307 
308 	const LV2_URID key = luaL_checkinteger(L, 2);
309 
310 	if(moony->opts)
311 	{
312 		for(LV2_Options_Option *opt = moony->opts;
313 			(opt->key != 0) && (opt->value != NULL);
314 			opt++)
315 		{
316 			if(opt->key == key)
317 			{
318 				const LV2_Atom *atom = (const LV2_Atom *)&opt->size;
319 				_latom_body_new(L, atom, opt->value, false);
320 				return 1;
321 			}
322 		}
323 	}
324 
325 	if(key == moony->uris.param_sampleRate)
326 	{
327 		_latom_body_new(L, &moony->sample_rate.atom, &moony->sample_rate.body, false);
328 		return 1;
329 	}
330 
331 	lua_pushnil(L); // not found
332 	return 1;
333 }
334 
335 __realtime static int
_lopts_itr(lua_State * L)336 _lopts_itr(lua_State *L)
337 {
338 	LV2_Options_Option **opt_ptr = lua_touserdata(L, lua_upvalueindex(1));
339 	LV2_Options_Option *opt = *opt_ptr;
340 
341 	if( (opt->key != 0) && (opt->value != NULL) )
342 	{
343 		const LV2_Atom *atom = (const LV2_Atom *)&opt->size;
344 		lua_pushinteger(L, opt->key);
345 		_latom_body_new(L, atom, opt->value, false);
346 
347 		*opt_ptr = opt + 1;
348 		return 2;
349 	}
350 
351 	//FIXME invalidate atom after use?
352 	lua_pushnil(L);
353 	return 1;
354 }
355 
356 __realtime static int
_lopts__pairs(lua_State * L)357 _lopts__pairs(lua_State *L)
358 {
359 	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
360 
361 	if(moony->opts)
362 	{
363 		LV2_Options_Option **opt_ptr = lua_newuserdata(L, sizeof(LV2_Options_Option **));
364 		*opt_ptr = moony->opts;
365 		lua_pushcclosure(L, _lopts_itr, 1);
366 		return 1;
367 	}
368 
369 	lua_pushnil(L);
370 	return 1;
371 }
372 
373 static const luaL_Reg lopts_mt [] = {
374 	{"__index", _lopts__index},
375 	{"__call", _lopts__index},
376 	{"__pairs", _lopts__pairs},
377 	{NULL, NULL}
378 };
379 
380 __realtime static int
_log(lua_State * L)381 _log(lua_State *L)
382 {
383 	int n = lua_gettop(L);
384 
385 	if(!n)
386 		return 0;
387 
388 	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
389 	moony_vm_t *vm = lua_touserdata(L, lua_upvalueindex(2));
390 
391 	luaL_Buffer buf;
392 	luaL_buffinit(L, &buf);
393 
394   lua_getglobal(L, "tostring"); //TODO cache this
395   for(int i=1; i<=n; i++)
396 	{
397     if(i>1)
398 			luaL_addchar(&buf, '\t');
399 
400 		if(lua_type(L, i) == LUA_TSTRING)
401 		{
402 			const size_t max_len = 512;
403 			size_t len;
404 			const char *s = lua_tolstring(L, i, &len);
405 			if(len > max_len) // truncate if string too long
406 			{
407 				luaL_addlstring(&buf, s, max_len);
408 				const size_t trunc_len = 32;
409 				char trunc [trunc_len];
410 				snprintf(trunc, trunc_len, " [+%zu chars]", len - max_len);
411 				luaL_addstring(&buf, trunc);
412 			}
413 			else // use whole string
414 			{
415 				luaL_addlstring(&buf, s, len);
416 			}
417 		}
418 		else // !LUA-TSTRING
419 		{
420 			lua_pushvalue(L, -1);  // function to be called
421 			lua_pushvalue(L, i);   // value to print
422 			lua_call(L, 1, 1);
423 
424 			size_t len;
425 			const char *s = lua_tolstring(L, -1, &len);
426 			luaL_addlstring(&buf, s, len);
427 			lua_pop(L, 1);  // pop result
428 		}
429   }
430 
431 	luaL_pushresult(&buf);
432 
433 	size_t len;
434 	const char *res = lua_tolstring(L, -1, &len);
435 
436 	if(moony->log)
437 	{
438 		if(vm->nrt) // we're running in worker thread
439 			lv2_log_note(&moony->logger, "%s\n", res);
440 		else // we're running in rt-thread
441 			lv2_log_trace(&moony->logger, "%s\n", res);
442 	}
443 
444 	// feedback to UI
445 	if(!vm->trace_overflow)
446 	{
447 		const size_t sz = strlen(vm->trace);
448 		if(sz + len + 2 < MOONY_MAX_TRACE_LEN)
449 		{
450 			char *end = vm->trace + sz; // end of string
451 			snprintf(end, len + 2, "%s\n", res);
452 			vm->trace_out = true; // set flag
453 		}
454 		else
455 			vm->trace_overflow = true;
456 	}
457 
458 	return 0;
459 }
460 
461 __realtime LV2_Atom_Forge_Ref
_sink_rt(LV2_Atom_Forge_Sink_Handle handle,const void * buf,uint32_t size)462 _sink_rt(LV2_Atom_Forge_Sink_Handle handle, const void *buf, uint32_t size)
463 {
464 	atom_ser_t *ser = handle;
465 
466 	const LV2_Atom_Forge_Ref ref = ser->offset + 1;
467 
468 	const uint32_t new_offset = ser->offset + size;
469 	if(new_offset > ser->size)
470 	{
471 		uint32_t new_size = ser->size << 1;
472 		while(new_offset > new_size)
473 			new_size <<= 1;
474 
475 		assert(ser->data);
476 		if(!(ser->buf = moony_rt_realloc(ser->data, ser->buf, ser->size, new_size)))
477 			return 0; // realloc failed
478 
479 		ser->size = new_size;
480 	}
481 
482 	memcpy(ser->buf + ser->offset, buf, size);
483 	ser->offset = new_offset;
484 
485 	return ref;
486 }
487 
488 __non_realtime LV2_Atom_Forge_Ref
_sink_non_rt(LV2_Atom_Forge_Sink_Handle handle,const void * buf,uint32_t size)489 _sink_non_rt(LV2_Atom_Forge_Sink_Handle handle, const void *buf, uint32_t size)
490 {
491 	atom_ser_t *ser = handle;
492 
493 	const LV2_Atom_Forge_Ref ref = ser->offset + 1;
494 
495 	const uint32_t new_offset = ser->offset + size;
496 	if(new_offset > ser->size)
497 	{
498 		uint32_t new_size = ser->size << 1;
499 		while(new_offset > new_size)
500 			new_size <<= 1;
501 
502 		if(!(ser->buf = realloc(ser->buf, new_size)))
503 			return 0; // realloc failed
504 
505 		ser->size = new_size;
506 	}
507 
508 	memcpy(ser->buf + ser->offset, buf, size);
509 	ser->offset = new_offset;
510 
511 	return ref;
512 }
513 
514 __realtime LV2_Atom *
_deref(LV2_Atom_Forge_Sink_Handle handle,LV2_Atom_Forge_Ref ref)515 _deref(LV2_Atom_Forge_Sink_Handle handle, LV2_Atom_Forge_Ref ref)
516 {
517 	atom_ser_t *ser = handle;
518 
519 	const uint32_t offset = ref - 1;
520 
521 	return (LV2_Atom *)(ser->buf + offset);
522 }
523 
524 __realtime static int
_stash(lua_State * L)525 _stash(lua_State *L)
526 {
527 	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
528 
529 	lua_getglobal(L, "stash");
530 	if(lua_isfunction(L, -1))
531 	{
532 		lforge_t *lframe = moony_newuserdata(L, moony, MOONY_UDATA_FORGE, true);
533 		lframe->depth = 0;
534 		lframe->last.frames = 0;
535 		lframe->forge = &moony->stash_forge;
536 
537 		atom_ser_t *ser = &moony->vm->ser;
538 		ser->data = moony->vm;
539 		ser->size = 1024;
540 		ser->offset = 0;
541 		ser->buf = moony_rt_alloc(moony->vm, ser->size);
542 
543 		if(ser->buf)
544 		{
545 			memset(ser->buf, 0x0, sizeof(LV2_Atom));
546 
547 			lv2_atom_forge_set_sink(lframe->forge, _sink_rt, _deref, ser);
548 			lua_call(L, 1, 0);
549 
550 			LV2_Atom *atom = (LV2_Atom *)ser->buf;
551 			moony->stash_atom = atom;
552 			moony->stash_size = ser->size;
553 
554 			// invalidate ser_atom
555 			ser->size = 0;
556 			ser->buf = NULL;
557 		}
558 	}
559 	else
560 		lua_pop(L, 1);
561 
562 	return 0;
563 }
564 
565 __realtime static int
_apply(lua_State * L)566 _apply(lua_State *L)
567 {
568 	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
569 
570 	lua_getglobal(L, "apply");
571 	if(lua_isfunction(L, -1))
572 	{
573 		_latom_new(L, moony->stash_atom, true);
574 		lua_call(L, 1, 0);
575 	}
576 	else
577 		lua_pop(L, 1);
578 
579 	return 0;
580 }
581 
582 __non_realtime static int
_save(lua_State * L)583 _save(lua_State *L)
584 {
585 	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
586 
587 	if(lua_getglobal(L, "save") == LUA_TFUNCTION)
588 	{
589 		lforge_t *lframe = moony_newuserdata(L, moony, MOONY_UDATA_FORGE, true);
590 		lframe->depth = 0;
591 		lframe->last.frames = 0;
592 		lframe->forge = &moony->state_forge;
593 
594 		lua_call(L, 1, 0);
595 	}
596 
597 	return 0;
598 }
599 
600 __non_realtime static int
_restore(lua_State * L)601 _restore(lua_State *L)
602 {
603 	moony_t *moony = lua_touserdata(L, lua_upvalueindex(1));
604 
605 	if(lua_getglobal(L, "restore") == LUA_TFUNCTION)
606 	{
607 		_latom_new(L, moony->state_atom, false);
608 		lua_call(L, 1, 0);
609 	}
610 
611 	return 0;
612 }
613 
614 __non_realtime static LV2_State_Status
_state_save(LV2_Handle instance,LV2_State_Store_Function store,LV2_State_Handle state,uint32_t flags,const LV2_Feature * const * features)615 _state_save(LV2_Handle instance,
616 	LV2_State_Store_Function store, LV2_State_Handle state,
617 	uint32_t flags, const LV2_Feature *const *features)
618 {
619 	moony_t *moony = (moony_t *)instance;
620 
621 	LV2_State_Status status = LV2_STATE_SUCCESS;
622 
623 	if(moony->chunk_nrt)
624 	{
625 		status = store(
626 			state,
627 			moony->uris.moony_code,
628 			moony->chunk_nrt,
629 			strlen(moony->chunk_nrt) + 1,
630 			moony->forge.String,
631 			LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
632 		(void)status; //TODO check status
633 	}
634 
635 	const int32_t minor_version = MOONY_MINOR_VERSION;
636 	status = store(
637 		state,
638 		moony->uris.lv2_minor_version,
639 		&minor_version,
640 		sizeof(int32_t),
641 		moony->forge.Int,
642 		LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
643 	(void)status; //TODO check status
644 
645 	const int32_t micro_version = MOONY_MICRO_VERSION;
646 	status = store(
647 		state,
648 		moony->uris.lv2_micro_version,
649 		&micro_version,
650 		sizeof(int32_t),
651 		moony->forge.Int,
652 		LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
653 	(void)status; //TODO check status
654 
655 	int32_t i32 = atomic_load_explicit(&moony->editor_hidden, memory_order_acquire);
656 	status = store(
657 		state,
658 		moony->uris.moony_editorHidden,
659 		&i32,
660 		sizeof(int32_t),
661 		moony->forge.Bool,
662 		LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
663 	(void)status; //TODO check status
664 
665 	i32 = atomic_load_explicit(&moony->graph_hidden, memory_order_acquire);
666 	status = store(
667 		state,
668 		moony->uris.moony_graphHidden,
669 		&i32,
670 		sizeof(int32_t),
671 		moony->forge.Bool,
672 		LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
673 	(void)status; //TODO check status
674 
675 	i32 = atomic_load_explicit(&moony->log_hidden, memory_order_acquire);
676 	status = store(
677 		state,
678 		moony->uris.moony_logHidden,
679 		&i32,
680 		sizeof(int32_t),
681 		moony->forge.Bool,
682 		LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
683 	(void)status; //TODO check status
684 
685 	i32 = atomic_load_explicit(&moony->log_follow, memory_order_acquire);
686 	status = store(
687 		state,
688 		moony->uris.moony_logFollow,
689 		&i32,
690 		sizeof(int32_t),
691 		moony->forge.Bool,
692 		LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
693 	(void)status; //TODO check status
694 
695 	i32 = atomic_load_explicit(&moony->log_reset, memory_order_acquire);
696 	status = store(
697 		state,
698 		moony->uris.moony_logReset,
699 		&i32,
700 		sizeof(int32_t),
701 		moony->forge.Bool,
702 		LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
703 	(void)status; //TODO check status
704 
705 	i32 = atomic_load_explicit(&moony->param_hidden, memory_order_acquire);
706 	status = store(
707 		state,
708 		moony->uris.moony_paramHidden,
709 		&i32,
710 		sizeof(int32_t),
711 		moony->forge.Bool,
712 		LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
713 	(void)status; //TODO check status
714 
715 	i32 = atomic_load_explicit(&moony->param_cols, memory_order_acquire);
716 	status = store(
717 		state,
718 		moony->uris.moony_paramCols,
719 		&i32,
720 		sizeof(int32_t),
721 		moony->forge.Int,
722 		LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
723 	(void)status; //TODO check status
724 
725 	i32 = atomic_load_explicit(&moony->param_rows, memory_order_acquire);
726 	status = store(
727 		state,
728 		moony->uris.moony_paramRows,
729 		&i32,
730 		sizeof(int32_t),
731 		moony->forge.Int,
732 		LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
733 	(void)status; //TODO check status
734 
735 	atom_ser_t ser = {
736 		.data = NULL,
737 		.size = 1024,
738 		.offset = 0
739 	};
740 	ser.buf = malloc(ser.size);
741 
742 	if(ser.buf)
743 	{
744 		memset(ser.buf, 0x0, sizeof(LV2_Atom));
745 
746 		lv2_atom_forge_set_sink(&moony->state_forge, _sink_non_rt, _deref, &ser);
747 
748 		// lock Lua state, so it cannot be accessed by realtime thread
749 		_spin_lock(&moony->state_lock);
750 		{
751 			// restore Lua defined properties
752 			lua_State *L = moony_current(moony);
753 			lua_rawgetp(L, LUA_REGISTRYINDEX, _save);
754 			if(lua_pcall(L, 0, 0, 0))
755 			{
756 				moony_err_async(moony, lua_tostring(L, -1));
757 				lua_pop(L, 1);
758 			}
759 #ifdef USE_MANUAL_GC
760 			lua_gc(L, LUA_GCSTEP, 0);
761 #endif
762 		}
763 		_unlock(&moony->state_lock);
764 
765 		LV2_Atom *state_atom_new = (LV2_Atom *)ser.buf;
766 		if( (state_atom_new->type) && (state_atom_new->size) )
767 		{
768 			status = store(
769 				state,
770 				moony->uris.moony_state,
771 				LV2_ATOM_BODY(state_atom_new),
772 				state_atom_new->size,
773 				state_atom_new->type,
774 				LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
775 		}
776 
777 		LV2_Atom *state_atom_old = (LV2_Atom *)atomic_exchange_explicit(&moony->state_atom_new, (uintptr_t)state_atom_new, memory_order_relaxed);
778 		if(state_atom_old)
779 			free(state_atom_old);
780 	}
781 
782 	return status;
783 }
784 
785 __non_realtime static moony_vm_t *
_compile(moony_t * moony,const char * chunk)786 _compile(moony_t *moony, const char *chunk)
787 {
788 	// save a copy for _state_save
789 	if(moony->chunk_nrt)
790 		free(moony->chunk_nrt);
791 	moony->chunk_nrt = strdup(chunk);
792 	if(!moony->chunk_nrt)
793 		return NULL;
794 
795 	char *chunk_new = strdup(chunk);
796 	if(!chunk_new)
797 		return NULL;
798 
799 	// chunk is always updated, even if compilation should fail
800 	char *chunk_old = (char *)atomic_exchange_explicit(&moony->chunk_new, (uintptr_t)chunk_new, memory_order_relaxed);
801 	if(chunk_old)
802 		free(chunk_old);
803 
804 	moony_vm_t *vm = moony_vm_new(moony->mem_size, moony->testing, moony);
805 	if(!vm)
806 	{
807 		moony_err_async(moony, "moony_vm_new failed");
808 		return NULL;
809 	}
810 
811 	moony_vm_nrt_enter(vm);
812 	moony_open(moony, vm, vm->L);
813 	if(luaL_dostring(vm->L, chunk))
814 	{
815 		moony_err_async(moony, lua_tostring(vm->L, -1));
816 		lua_pop(vm->L, 1);
817 
818 		moony_vm_free(vm);
819 		return NULL;
820 	}
821 	moony_vm_nrt_leave(vm);
822 
823 	return vm;
824 }
825 
826 __non_realtime static LV2_State_Status
_state_restore(LV2_Handle instance,LV2_State_Retrieve_Function retrieve,LV2_State_Handle state,uint32_t flags,const LV2_Feature * const * features)827 _state_restore(LV2_Handle instance,
828 	LV2_State_Retrieve_Function retrieve, LV2_State_Handle state,
829 	uint32_t flags, const LV2_Feature *const *features)
830 {
831 	moony_t *moony = (moony_t *)instance;
832 	const LV2_Worker_Schedule *work_sched = NULL;
833 
834 	for(unsigned i = 0; features[i]; i++)
835 	{
836 		if(!strcmp(features[i]->URI, LV2_WORKER__schedule))
837 			work_sched = features[i]->data;
838 	}
839 
840 	(void)work_sched; //FIXME
841 
842 	size_t size;
843 	uint32_t type;
844 	uint32_t flags2;
845 
846 	// get minor version
847 	const int32_t *minor_version = retrieve(
848 		state,
849 		moony->uris.lv2_minor_version,
850 		&size,
851 		&type,
852 		&flags2);
853 	if(!minor_version || (size != sizeof(int32_t)) || (type != moony->forge.Int) )
854 		minor_version = NULL;
855 
856 	// get micro version
857 	const int32_t *micro_version = retrieve(
858 		state,
859 		moony->uris.lv2_micro_version,
860 		&size,
861 		&type,
862 		&flags2);
863 	if(!micro_version || (size != sizeof(int32_t)) || (type != moony->forge.Int) )
864 		micro_version = NULL;
865 
866 	//TODO check preset version with current plugin version for API compatibility
867 
868 	// get moony:editorHidden
869 	const int32_t *i32 = retrieve(
870 		state,
871 		moony->uris.moony_editorHidden,
872 		&size,
873 		&type,
874 		&flags2);
875 	if(i32 && (size == sizeof(int32_t)) && (type == moony->forge.Bool) )
876 	{
877 		atomic_store_explicit(&moony->editor_hidden, *i32, memory_order_release);
878 	}
879 
880 	// get moony:graphHidden
881 	i32 = retrieve(
882 		state,
883 		moony->uris.moony_graphHidden,
884 		&size,
885 		&type,
886 		&flags2);
887 	if(i32 && (size == sizeof(int32_t)) && (type == moony->forge.Bool) )
888 	{
889 		atomic_store_explicit(&moony->graph_hidden, *i32, memory_order_release);
890 	}
891 
892 	// get moony:logHidden
893 	i32 = retrieve(
894 		state,
895 		moony->uris.moony_logHidden,
896 		&size,
897 		&type,
898 		&flags2);
899 	if(i32 && (size == sizeof(int32_t)) && (type == moony->forge.Bool) )
900 	{
901 		atomic_store_explicit(&moony->log_hidden, *i32, memory_order_release);
902 	}
903 
904 	// get moony:logFollow
905 	i32 = retrieve(
906 		state,
907 		moony->uris.moony_logFollow,
908 		&size,
909 		&type,
910 		&flags2);
911 	if(i32 && (size == sizeof(int32_t)) && (type == moony->forge.Bool) )
912 	{
913 		atomic_store_explicit(&moony->log_follow, *i32, memory_order_release);
914 	}
915 
916 	// get moony:logReset
917 	i32 = retrieve(
918 		state,
919 		moony->uris.moony_logReset,
920 		&size,
921 		&type,
922 		&flags2);
923 	if(i32 && (size == sizeof(int32_t)) && (type == moony->forge.Bool) )
924 	{
925 		atomic_store_explicit(&moony->log_reset, *i32, memory_order_release);
926 	}
927 
928 	// get moony:paramHidden
929 	i32 = retrieve(
930 		state,
931 		moony->uris.moony_paramHidden,
932 		&size,
933 		&type,
934 		&flags2);
935 	if(i32 && (size == sizeof(int32_t)) && (type == moony->forge.Bool) )
936 	{
937 		atomic_store_explicit(&moony->param_hidden, *i32, memory_order_release);
938 	}
939 
940 	// get moony:paramCols
941 	i32 = retrieve(
942 		state,
943 		moony->uris.moony_paramCols,
944 		&size,
945 		&type,
946 		&flags2);
947 	if(i32 && (size == sizeof(int32_t)) && (type == moony->forge.Int) )
948 	{
949 		atomic_store_explicit(&moony->param_cols, *i32, memory_order_release);
950 	}
951 
952 	// get moony:paramRows
953 	i32 = retrieve(
954 		state,
955 		moony->uris.moony_paramRows,
956 		&size,
957 		&type,
958 		&flags2);
959 	if(i32 && (size == sizeof(int32_t)) && (type == moony->forge.Int) )
960 	{
961 		atomic_store_explicit(&moony->param_rows, *i32, memory_order_release);
962 	}
963 
964 	// get state
965 	const uint8_t *body = retrieve(
966 		state,
967 		moony->uris.moony_state,
968 		&size,
969 		&type,
970 		&flags2
971 	);
972 
973 	if(body && size && type)
974 	{
975 		// allocate new state_atom
976 		LV2_Atom *state_atom_new = malloc(sizeof(LV2_Atom) + size);
977 		if(state_atom_new)
978 		{
979 			state_atom_new->size = size;
980 			state_atom_new->type = type;
981 			memcpy(LV2_ATOM_BODY(state_atom_new), body, size);
982 
983 			LV2_Atom *state_atom_old = (LV2_Atom *)atomic_exchange_explicit(&moony->state_atom_new, (uintptr_t)state_atom_new, memory_order_relaxed);
984 			if(state_atom_old)
985 				free(state_atom_old);
986 		}
987 	}
988 
989 	// get code chunk
990 	const char *chunk = retrieve(
991 		state,
992 		moony->uris.moony_code,
993 		&size,
994 		&type,
995 		&flags2);
996 
997 	if(chunk && size && (type == moony->forge.String) )
998 	{
999 		if(size <= MOONY_MAX_CHUNK_LEN)
1000 		{
1001 			moony_vm_t *vm_new = _compile(moony, chunk);
1002 			if(vm_new)
1003 			{
1004 				moony_vm_t *vm_old = (moony_vm_t *)atomic_exchange_explicit(&moony->vm_new, (uintptr_t)vm_new, memory_order_relaxed);
1005 				if(vm_old)
1006 					moony_vm_free(vm_old);
1007 			}
1008 		}
1009 		else
1010 		{
1011 			moony_err_async(moony, "restore: moony:code too long");
1012 		}
1013 	}
1014 	else
1015 	{
1016 		moony_err_async(moony, "restore: moony:code property not found");
1017 	}
1018 
1019 	return LV2_STATE_SUCCESS;
1020 }
1021 
1022 static const LV2_State_Interface state_iface = {
1023 	.save = _state_save,
1024 	.restore = _state_restore
1025 };
1026 
1027 __non_realtime static LV2_Worker_Status
_work_job(moony_t * moony,LV2_Worker_Respond_Function respond,LV2_Worker_Respond_Handle target,const moony_job_t * job)1028 _work_job(moony_t *moony,
1029 	LV2_Worker_Respond_Function respond,
1030 	LV2_Worker_Respond_Handle target,
1031 	const moony_job_t *job)
1032 {
1033 	//printf("_work: %i\n", job->type);
1034 
1035 	switch(job->type)
1036 	{
1037 		case MOONY_JOB_MEM_ALLOC:
1038 		{
1039 			const moony_job_t req = {
1040 				.type = MOONY_JOB_MEM_ALLOC,
1041 				.mem.size = job->mem.size,
1042 				.mem.ptr = moony_vm_mem_alloc(job->mem.size)
1043 			};
1044 
1045 			return respond(target, sizeof(moony_job_t), &req); // signal to _work_response
1046 		} break;
1047 		case MOONY_JOB_MEM_FREE:
1048 		{
1049 			moony_vm_mem_free(job->mem.ptr, job->mem.size);
1050 		} break;
1051 		case MOONY_JOB_VM_ALLOC:
1052 		{
1053 			moony_vm_t *vm_new = _compile(moony, job->chunk);
1054 			if(vm_new)
1055 			{
1056 				moony_vm_t *vm_old = (moony_vm_t *)atomic_exchange_explicit(&moony->vm_new, (uintptr_t)vm_new, memory_order_relaxed);
1057 				if(vm_old)
1058 					moony_vm_free(vm_old);
1059 			}
1060 			else
1061 			{
1062 				return LV2_WORKER_ERR_UNKNOWN;
1063 			}
1064 		} break;
1065 		case MOONY_JOB_VM_FREE:
1066 		{
1067 			moony_vm_free(job->vm);
1068 		} break;
1069 		case MOONY_JOB_PTR_FREE:
1070 		{
1071 			free(job->ptr);
1072 		} break;
1073 	}
1074 
1075 	return LV2_WORKER_SUCCESS;
1076 }
1077 
1078 __non_realtime static LV2_Worker_Status
_work(LV2_Handle instance,LV2_Worker_Respond_Function respond,LV2_Worker_Respond_Handle target,uint32_t size,const void * body)1079 _work(LV2_Handle instance,
1080 	LV2_Worker_Respond_Function respond,
1081 	LV2_Worker_Respond_Handle target,
1082 	uint32_t size,
1083 	const void *body)
1084 {
1085 	moony_t *moony = instance;
1086 
1087 	LV2_Worker_Status status = LV2_WORKER_SUCCESS;
1088 
1089 	size_t sz;
1090 	const moony_job_t *job;
1091 	while((job = varchunk_read_request(moony->from_dsp, &sz)))
1092 	{
1093 		status = _work_job(moony, respond, target, job);
1094 
1095 		varchunk_read_advance(moony->from_dsp);
1096 	}
1097 
1098 	return status;
1099 }
1100 
1101 __realtime static LV2_Worker_Status
_work_response(LV2_Handle instance,uint32_t size,const void * body)1102 _work_response(LV2_Handle instance, uint32_t size, const void *body)
1103 {
1104 	moony_t *moony = instance;
1105 	const moony_job_t *job = body;
1106 
1107 	//printf("_work_response: %i\n", job->type);
1108 	switch(job->type)
1109 	{
1110 		case MOONY_JOB_MEM_ALLOC:
1111 		{
1112 			moony->vm->allocating = false;
1113 
1114 			if(!job->mem.ptr) // allocation failed
1115 				return LV2_WORKER_ERR_UNKNOWN;
1116 
1117 			// search for next free pool
1118 			int i;
1119 			for(i=1; i<MOONY_POOL_NUM; i++)
1120 			{
1121 				if(!moony->vm->area[i])
1122 					break;
1123 			}
1124 
1125 			bool failed = true;
1126 			if(i != MOONY_POOL_NUM) // no overflow
1127 			{
1128 				// tlsf add pool
1129 				moony->vm->size[i] = job->mem.size;
1130 				moony->vm->area[i] = job->mem.ptr;
1131 				moony->vm->pool[i] = tlsf_add_pool(moony->vm->tlsf,
1132 					moony->vm->area[i], moony->vm->size[i]); //FIXME stoat complains about printf
1133 
1134 				if(moony->vm->pool[i])
1135 					failed = false;
1136 			}
1137 
1138 			if(failed) // pool addition failed
1139 			{
1140 				moony_job_t *req;
1141 				if((req = varchunk_write_request(moony->from_dsp, sizeof(moony_job_t))))
1142 				{
1143 					req->type = MOONY_JOB_MEM_FREE;
1144 					req->mem.size = job->mem.size;
1145 					req->mem.ptr = job->mem.ptr;
1146 
1147 					moony->vm->size[i] = 0;
1148 					moony->vm->area[i] = NULL;
1149 					moony->vm->pool[i] = NULL;
1150 
1151 					varchunk_write_advance(moony->from_dsp, sizeof(moony_job_t));
1152 					if(moony_wake_worker(moony->sched) != LV2_WORKER_SUCCESS)
1153 						moony_trace(moony, "waking worker failed");
1154 				}
1155 
1156 				return LV2_WORKER_ERR_UNKNOWN;
1157 			}
1158 
1159 			moony->vm->space += moony->vm->size[i];
1160 			//printf("mem extended to %zu KB\n", moony->vm->space / 1024);
1161 		} break;
1162 
1163 		case MOONY_JOB_VM_ALLOC:
1164 		case MOONY_JOB_MEM_FREE:
1165 		case MOONY_JOB_VM_FREE:
1166 		case MOONY_JOB_PTR_FREE:
1167 			break; // never reached
1168 	}
1169 
1170 	return LV2_WORKER_SUCCESS;
1171 }
1172 
1173 __realtime static LV2_Worker_Status
_end_run(LV2_Handle instance)1174 _end_run(LV2_Handle instance __attribute__((unused)))
1175 {
1176 	return LV2_WORKER_SUCCESS;
1177 }
1178 
1179 static const LV2_Worker_Interface work_iface = {
1180 	.work = _work,
1181 	.work_response = _work_response,
1182 	.end_run = _end_run
1183 };
1184 
1185 #if defined(BUILD_INLINE_DISP)
1186 __non_realtime static LV2_Inline_Display_Image_Surface *
_idisp_render(LV2_Handle instance,uint32_t w,uint32_t h)1187 _idisp_render(LV2_Handle instance, uint32_t w, uint32_t h)
1188 {
1189 	moony_t *moony = instance;
1190 
1191 	float aspect_ratio = 1.f; //FIXME
1192 
1193 	LV2_Inline_Display_Image_Surface *surf =
1194 		lv2_canvas_idisp_surf_configure(&moony->canvas_idisp, w, h, aspect_ratio);
1195 
1196 	const LV2_Atom *value = NULL;
1197 	size_t tot_size = 0;
1198 	while( (value = varchunk_read_request(moony->to_idisp, &tot_size)) )
1199 	{
1200 		moony->canvas_graph = realloc(moony->canvas_graph, tot_size);
1201 
1202 		memcpy(moony->canvas_graph, value, tot_size);
1203 
1204 		varchunk_read_advance(moony->to_idisp);
1205 	}
1206 
1207 	value = moony->canvas_graph;
1208 
1209 	const LV2_Atom fake = {
1210 		.size = 0,
1211 		.type = moony->forge.Tuple
1212 	};
1213 
1214 	if(!value)
1215 	{
1216 		value = &fake;
1217 	}
1218 
1219 	lv2_canvas_idisp_render_body(&moony->canvas_idisp, value->type, value->size,
1220 		LV2_ATOM_BODY_CONST(value));
1221 
1222 	return surf;
1223 }
1224 
1225 static const LV2_Inline_Display_Interface idisp_iface = {
1226 	.render = _idisp_render
1227 };
1228 #endif
1229 
1230 __non_realtime const void*
extension_data(const char * uri)1231 extension_data(const char* uri)
1232 {
1233 	if(!strcmp(uri, LV2_WORKER__interface))
1234 		return &work_iface;
1235 	else if(!strcmp(uri, LV2_STATE__interface))
1236 		return &state_iface;
1237 #if defined(BUILD_INLINE_DISP)
1238 	else if(!strcmp(uri, LV2_INLINEDISPLAY__interface))
1239 		return &idisp_iface;
1240 #endif
1241 	else
1242 		return NULL;
1243 }
1244 
1245 __non_realtime int
moony_init(moony_t * moony,const char * subject,double sample_rate,const LV2_Feature * const * features,size_t mem_size,bool testing)1246 moony_init(moony_t *moony, const char *subject, double sample_rate,
1247 	const LV2_Feature *const *features, size_t mem_size, bool testing)
1248 {
1249 	atomic_init(&moony->state_atom_new, 0);
1250 	atomic_init(&moony->vm_new, 0);
1251 	atomic_init(&moony->err_new, 0);
1252 	atomic_init(&moony->chunk_new, 0);
1253 	moony->state_lock = (atomic_flag)ATOMIC_FLAG_INIT;
1254 
1255 	moony->from_dsp = varchunk_new(MOONY_MAX_CHUNK_LEN * 2, true);
1256 	if(!moony->from_dsp)
1257 	{
1258 		fprintf(stderr, "varchunk_new failed\n");
1259 		return -1;
1260 	}
1261 
1262 	moony->mem_size = mem_size;
1263 	moony->testing = testing;
1264 	moony->vm = moony_vm_new(moony->mem_size, testing, moony);
1265 	if(!moony->vm)
1266 	{
1267 		fprintf(stderr, "Lua VM cannot be initialized\n");
1268 		return -1;
1269 	}
1270 
1271 	bool load_default_state = false;
1272 	xpress_map_t *voice_map = NULL;
1273 #if defined(BUILD_INLINE_DISP)
1274 	LV2_Inline_Display *queue_draw = NULL;
1275 	moony->to_idisp = varchunk_new(MOONY_MAX_CHUNK_LEN * 2, true);
1276 	if(!moony->to_idisp)
1277 	{
1278 		fprintf(stderr, "varchunk_new failed\n");
1279 		return -1;
1280 	}
1281 #endif
1282 
1283 	for(unsigned i=0; features[i]; i++)
1284 	{
1285 		if(!strcmp(features[i]->URI, LV2_URID__map))
1286 			moony->map = features[i]->data;
1287 		else if(!strcmp(features[i]->URI, LV2_URID__unmap))
1288 			moony->unmap = features[i]->data;
1289 		else if(!strcmp(features[i]->URI, LV2_WORKER__schedule))
1290 			moony->sched = features[i]->data;
1291 		else if(!strcmp(features[i]->URI, LV2_LOG__log))
1292 			moony->log = features[i]->data;
1293 		else if(!strcmp(features[i]->URI, LV2_OPTIONS__options))
1294 			moony->opts = features[i]->data;
1295 		else if(!strcmp(features[i]->URI, LV2_OSC__schedule))
1296 			moony->osc_sched = features[i]->data;
1297 		else if(!strcmp(features[i]->URI, LV2_STATE__loadDefaultState))
1298 			load_default_state = true;
1299 		else if(!strcmp(features[i]->URI, XPRESS__voiceMap))
1300 			voice_map = features[i]->data;
1301 #if defined(BUILD_INLINE_DISP)
1302 		else if(!strcmp(features[i]->URI, LV2_INLINEDISPLAY__queue_draw))
1303 			queue_draw = features[i]->data;
1304 #endif
1305 	}
1306 
1307 	if(!moony->map)
1308 	{
1309 		fprintf(stderr, "Host does not support urid:map\n");
1310 		return -1;
1311 	}
1312 	if(!moony->unmap)
1313 	{
1314 		fprintf(stderr, "Host does not support urid:unmap\n");
1315 		return -1;
1316 	}
1317 	if(!moony->sched)
1318 	{
1319 		fprintf(stderr, "Host does not support worker:schedule\n");
1320 		return -1;
1321 	}
1322 	if(!load_default_state)
1323 	{
1324 		strcpy(moony->chunk,
1325 			"-- host does not support state:loadDefaultState feature\n\n"
1326 			"function run(n, control, notify, ...)\n"
1327 			"end");
1328 		moony->chunk_nrt = strdup(moony->chunk);
1329 	}
1330 
1331 	xpress_init(&moony->xpress, 0, moony->map, voice_map, XPRESS_EVENT_NONE,
1332 		NULL, NULL, NULL);
1333 
1334 	moony->uris.moony_code = moony->map->map(moony->map->handle, MOONY_CODE_URI);
1335 	moony->uris.moony_error = moony->map->map(moony->map->handle, MOONY_ERROR_URI);
1336 	moony->uris.moony_trace = moony->map->map(moony->map->handle, MOONY_TRACE_URI);
1337 	moony->uris.moony_panic = moony->map->map(moony->map->handle, MOONY_PANIC_URI);
1338 	moony->uris.moony_state = moony->map->map(moony->map->handle, MOONY_STATE_URI);
1339 	moony->uris.moony_editorHidden = moony->map->map(moony->map->handle, MOONY_GRAPH_HIDDEN_URI);
1340 	moony->uris.moony_graphHidden = moony->map->map(moony->map->handle, MOONY_EDITOR_HIDDEN_URI);
1341 	moony->uris.moony_logHidden = moony->map->map(moony->map->handle, MOONY_LOG_HIDDEN_URI);
1342 	moony->uris.moony_logFollow = moony->map->map(moony->map->handle, MOONY_LOG_FOLLOW_URI);
1343 	moony->uris.moony_logReset = moony->map->map(moony->map->handle, MOONY_LOG_RESET_URI);
1344 	moony->uris.moony_paramHidden = moony->map->map(moony->map->handle, MOONY_PARAM_HIDDEN_URI);
1345 	moony->uris.moony_paramCols = moony->map->map(moony->map->handle, MOONY_PARAM_COLS_URI);
1346 	moony->uris.moony_paramRows = moony->map->map(moony->map->handle, MOONY_PARAM_ROWS_URI);
1347 	moony->uris.moony_color = moony->map->map(moony->map->handle, MOONY__color);
1348 	moony->uris.moony_syntax = moony->map->map(moony->map->handle, MOONY__syntax);
1349 
1350 	moony->uris.midi_event = moony->map->map(moony->map->handle, LV2_MIDI__MidiEvent);
1351 
1352 	moony->uris.patch.self = moony->map->map(moony->map->handle, subject);
1353 
1354 	moony->uris.patch.get = moony->map->map(moony->map->handle, LV2_PATCH__Get);
1355 	moony->uris.patch.set = moony->map->map(moony->map->handle, LV2_PATCH__Set);
1356 	moony->uris.patch.put = moony->map->map(moony->map->handle, LV2_PATCH__Put);
1357 	moony->uris.patch.patch = moony->map->map(moony->map->handle, LV2_PATCH__Patch);
1358 	moony->uris.patch.body = moony->map->map(moony->map->handle, LV2_PATCH__body);
1359 	moony->uris.patch.subject = moony->map->map(moony->map->handle, LV2_PATCH__subject);
1360 	moony->uris.patch.property = moony->map->map(moony->map->handle, LV2_PATCH__property);
1361 	moony->uris.patch.value = moony->map->map(moony->map->handle, LV2_PATCH__value);
1362 	moony->uris.patch.add = moony->map->map(moony->map->handle, LV2_PATCH__add);
1363 	moony->uris.patch.remove = moony->map->map(moony->map->handle, LV2_PATCH__remove);
1364 	moony->uris.patch.wildcard = moony->map->map(moony->map->handle, LV2_PATCH__wildcard);
1365 	moony->uris.patch.writable = moony->map->map(moony->map->handle, LV2_PATCH__writable);
1366 	moony->uris.patch.readable = moony->map->map(moony->map->handle, LV2_PATCH__readable);
1367 	moony->uris.patch.destination = moony->map->map(moony->map->handle, LV2_PATCH__destination);
1368 	moony->uris.patch.sequence = moony->map->map(moony->map->handle, LV2_PATCH__sequenceNumber);
1369 	moony->uris.patch.error = moony->map->map(moony->map->handle, LV2_PATCH__Error);
1370 	moony->uris.patch.ack = moony->map->map(moony->map->handle, LV2_PATCH__Ack);
1371 	moony->uris.patch.delete = moony->map->map(moony->map->handle, LV2_PATCH__Delete);
1372 	moony->uris.patch.copy = moony->map->map(moony->map->handle, LV2_PATCH__Copy);
1373 	moony->uris.patch.move = moony->map->map(moony->map->handle, LV2_PATCH__Move);
1374 	moony->uris.patch.insert = moony->map->map(moony->map->handle, LV2_PATCH__Insert);
1375 
1376 	moony->uris.rdfs_label = moony->map->map(moony->map->handle, RDFS__label);
1377 	moony->uris.rdfs_range = moony->map->map(moony->map->handle, RDFS__range);
1378 	moony->uris.rdfs_comment = moony->map->map(moony->map->handle, RDFS__comment);
1379 
1380 	moony->uris.rdf_value = moony->map->map(moony->map->handle, RDF__value);
1381 
1382 	moony->uris.lv2_minimum = moony->map->map(moony->map->handle, LV2_CORE__minimum);
1383 	moony->uris.lv2_maximum = moony->map->map(moony->map->handle, LV2_CORE__maximum);
1384 	moony->uris.lv2_scale_point = moony->map->map(moony->map->handle, LV2_CORE__scalePoint);
1385 	moony->uris.lv2_minor_version= moony->map->map(moony->map->handle, LV2_CORE__minorVersion);
1386 	moony->uris.lv2_micro_version= moony->map->map(moony->map->handle, LV2_CORE__microVersion);
1387 
1388 	moony->uris.units_unit = moony->map->map(moony->map->handle, LV2_UNITS__unit);
1389 	moony->uris.units_symbol = moony->map->map(moony->map->handle, LV2_UNITS__symbol);
1390 
1391 	moony->uris.atom_frame_time = moony->map->map(moony->map->handle, LV2_ATOM__frameTime);
1392 	moony->uris.atom_beat_time = moony->map->map(moony->map->handle, LV2_ATOM__beatTime);
1393 	moony->uris.atom_child_type = moony->map->map(moony->map->handle, LV2_ATOM__childType);
1394 
1395 	moony->uris.xpress_Token = moony->map->map(moony->map->handle, XPRESS__Token);
1396 	moony->uris.xpress_Alive = moony->map->map(moony->map->handle, XPRESS__Alive);
1397 	moony->uris.xpress_source = moony->map->map(moony->map->handle, XPRESS__source);
1398 	moony->uris.xpress_uuid = moony->map->map(moony->map->handle, XPRESS__uuid);
1399 	moony->uris.xpress_zone = moony->map->map(moony->map->handle, XPRESS__zone);
1400 	moony->uris.xpress_body = moony->map->map(moony->map->handle, XPRESS__body);
1401 	moony->uris.xpress_pitch = moony->map->map(moony->map->handle, XPRESS__pitch);
1402 	moony->uris.xpress_pressure = moony->map->map(moony->map->handle, XPRESS__pressure);
1403 	moony->uris.xpress_timbre = moony->map->map(moony->map->handle, XPRESS__timbre);
1404 	moony->uris.xpress_dPitch = moony->map->map(moony->map->handle, XPRESS__dPitch);
1405 	moony->uris.xpress_dPressure = moony->map->map(moony->map->handle, XPRESS__dPressure);
1406 	moony->uris.xpress_dTimbre = moony->map->map(moony->map->handle, XPRESS__dTimbre);
1407 
1408 	lv2_canvas_urid_init(&moony->canvas_urid, moony->map);
1409 
1410 	lv2_osc_urid_init(&moony->osc_urid, moony->map);
1411 	lv2_atom_forge_init(&moony->forge, moony->map);
1412 	lv2_atom_forge_init(&moony->state_forge, moony->map);
1413 	lv2_atom_forge_init(&moony->stash_forge, moony->map);
1414 	lv2_atom_forge_init(&moony->notify_forge, moony->map);
1415 	if(moony->log)
1416 		lv2_log_logger_init(&moony->logger, moony->map, moony->log);
1417 
1418 	moony->sample_rate.atom.size = sizeof(float);
1419 	moony->sample_rate.atom.type = moony->forge.Float;
1420 	moony->sample_rate.body = sample_rate;
1421 
1422 	latom_driver_hash_t *latom_driver_hash = moony->atom_driver_hash;
1423 	unsigned pos = 0;
1424 
1425 	latom_driver_hash[pos].type = 0;
1426 	latom_driver_hash[pos++].driver = &latom_nil_driver;
1427 
1428 	latom_driver_hash[pos].type = moony->forge.Int;
1429 	latom_driver_hash[pos++].driver = &latom_int_driver;
1430 
1431 	latom_driver_hash[pos].type = moony->forge.Long;
1432 	latom_driver_hash[pos++].driver = &latom_long_driver;
1433 
1434 	latom_driver_hash[pos].type = moony->forge.Float;
1435 	latom_driver_hash[pos++].driver = &latom_float_driver;
1436 
1437 	latom_driver_hash[pos].type = moony->forge.Double;
1438 	latom_driver_hash[pos++].driver = &latom_double_driver;
1439 
1440 	latom_driver_hash[pos].type = moony->forge.Bool;
1441 	latom_driver_hash[pos++].driver = &latom_bool_driver;
1442 
1443 	latom_driver_hash[pos].type = moony->forge.URID;
1444 	latom_driver_hash[pos++].driver = &latom_urid_driver;
1445 
1446 	latom_driver_hash[pos].type = moony->forge.String;
1447 	latom_driver_hash[pos++].driver = &latom_string_driver;
1448 
1449 	latom_driver_hash[pos].type = moony->forge.URI;
1450 	latom_driver_hash[pos++].driver = &latom_string_driver;
1451 
1452 	latom_driver_hash[pos].type = moony->forge.Path;
1453 	latom_driver_hash[pos++].driver = &latom_string_driver;
1454 
1455 	latom_driver_hash[pos].type = moony->forge.Literal;
1456 	latom_driver_hash[pos++].driver = &latom_literal_driver;
1457 
1458 	latom_driver_hash[pos].type = moony->forge.Tuple;
1459 	latom_driver_hash[pos++].driver = &latom_tuple_driver;
1460 
1461 	latom_driver_hash[pos].type = moony->forge.Object;
1462 	latom_driver_hash[pos++].driver = &latom_object_driver;
1463 
1464 	latom_driver_hash[pos].type = moony->forge.Vector;
1465 	latom_driver_hash[pos++].driver = &latom_vector_driver;
1466 
1467 	latom_driver_hash[pos].type = moony->forge.Sequence;
1468 	latom_driver_hash[pos++].driver = &latom_sequence_driver;
1469 
1470 	assert(pos == DRIVER_HASH_MAX);
1471 	qsort(latom_driver_hash, DRIVER_HASH_MAX, sizeof(latom_driver_hash_t), _hash_sort);
1472 
1473 	moony_freeuserdata(moony);
1474 
1475 	moony->editor_hidden = ATOMIC_VAR_INIT(0);
1476 	moony->graph_hidden = ATOMIC_VAR_INIT(1);
1477 	moony->log_hidden = ATOMIC_VAR_INIT(1);
1478 	moony->log_follow = ATOMIC_VAR_INIT(1);
1479 	moony->log_reset  = ATOMIC_VAR_INIT(0);
1480 	moony->param_hidden = ATOMIC_VAR_INIT(1);
1481 	moony->param_cols = ATOMIC_VAR_INIT(3);
1482 	moony->param_rows = ATOMIC_VAR_INIT(4);
1483 
1484 #if defined(BUILD_INLINE_DISP)
1485 	lv2_canvas_idisp_init(&moony->canvas_idisp, queue_draw, moony->map);
1486 #endif
1487 
1488 	return 0;
1489 }
1490 
1491 __non_realtime void
moony_deinit(moony_t * moony)1492 moony_deinit(moony_t *moony)
1493 {
1494 #if defined(BUILD_INLINE_DISP)
1495 	if(moony->to_idisp)
1496 		varchunk_free(moony->to_idisp);
1497 	free(moony->canvas_graph);
1498 	lv2_canvas_idisp_deinit(&moony->canvas_idisp);
1499 #endif
1500 
1501 	LV2_Atom *state_atom_old = (LV2_Atom *)atomic_load_explicit(&moony->state_atom_new, memory_order_relaxed);
1502 	if(state_atom_old)
1503 		free(state_atom_old);
1504 	if(moony->state_atom)
1505 		free(moony->state_atom);
1506 
1507 	xpress_deinit(&moony->xpress);
1508 
1509 	moony_vm_t *vm_old = (moony_vm_t *)atomic_load_explicit(&moony->vm_new, memory_order_relaxed);
1510 	if(vm_old)
1511 		moony_vm_free(vm_old);
1512 	if(moony->vm)
1513 		moony_vm_free(moony->vm);
1514 
1515 	char *err_old = (char *)atomic_load_explicit(&moony->err_new, memory_order_relaxed);
1516 	if(err_old)
1517 		free(err_old);
1518 
1519 	char *chunk_old = (char *)atomic_load_explicit(&moony->chunk_new, memory_order_relaxed);
1520 	if(chunk_old)
1521 		free(chunk_old);
1522 
1523 	if(moony->chunk_nrt)
1524 		free(moony->chunk_nrt);
1525 
1526 	if(moony->from_dsp)
1527 		varchunk_free(moony->from_dsp);
1528 }
1529 
1530 #define _protect_metatable(L, idx) \
1531 	lua_pushboolean(L, 0); \
1532 	lua_setfield(L, idx - 1, "__metatable");
1533 
1534 #define _index_metatable(L, idx) \
1535 	lua_pushvalue(L, idx); \
1536 	lua_setfield(L, idx - 1, "__index");
1537 
1538 __non_realtime void
moony_open(moony_t * moony,moony_vm_t * vm,lua_State * L)1539 moony_open(moony_t *moony, moony_vm_t *vm, lua_State *L)
1540 {
1541 	luaL_newmetatable(L, "latom");
1542 	lua_pushlightuserdata(L, moony); // @ upvalueindex 1
1543 	luaL_setfuncs (L, latom_mt, 1);
1544 	_protect_metatable(L, -1);
1545 	lua_pop(L, 1);
1546 
1547 	luaL_newmetatable(L, "lforge");
1548 	lua_pushlightuserdata(L, moony); // @ upvalueindex 1
1549 	luaL_setfuncs (L, lforge_mt, 1);
1550 	_protect_metatable(L, -1);
1551 	_index_metatable(L, -1);
1552 	lua_pop(L, 1);
1553 
1554 	luaL_newmetatable(L, "lstash");
1555 	lua_pushlightuserdata(L, moony); // @ upvalueindex 1
1556 	luaL_setfuncs (L, lstash_mt, 1);
1557 	_protect_metatable(L, -1);
1558 	_index_metatable(L, -1);
1559 	lua_pop(L, 1);
1560 
1561 	// lv2.map
1562 	lua_newtable(L);
1563 	lua_newtable(L);
1564 	lua_pushlightuserdata(L, moony); // @ upvalueindex 1
1565 	luaL_setfuncs(L, lmap_mt, 1);
1566 	_protect_metatable(L, -1);
1567 	lua_setmetatable(L, -2);
1568 	lua_setglobal(L, "Map");
1569 
1570 	// lv2.unmap
1571 	lua_newtable(L);
1572 	lua_newtable(L);
1573 	lua_pushlightuserdata(L, moony); // @ upvalueindex 1
1574 	luaL_setfuncs(L, lunmap_mt, 1);
1575 	_protect_metatable(L, -1);
1576 	lua_setmetatable(L, -2);
1577 	lua_setglobal(L, "Unmap");
1578 
1579 	// Note
1580 	lua_newtable(L);
1581 	lua_newtable(L);
1582 	lua_pushlightuserdata(L, moony); // @ upvalueindex 1
1583 	luaL_setfuncs(L, lnote_mt, 1);
1584 	_protect_metatable(L, -1);
1585 	lua_setmetatable(L, -2);
1586 	lua_setglobal(L, "Note");
1587 
1588 	// lv2.opts
1589 	lua_newtable(L);
1590 	lua_newtable(L);
1591 	lua_pushlightuserdata(L, moony); // @ upvalueindex 1
1592 	luaL_setfuncs(L, lopts_mt, 1);
1593 	_protect_metatable(L, -1);
1594 	lua_setmetatable(L, -2);
1595 	lua_setglobal(L, "Options");
1596 
1597 	// overwrite print function with LV2 log
1598 	lua_pushlightuserdata(L, moony); // @ upvalueindex 1
1599 	lua_pushlightuserdata(L, vm); // @ upvalueindex 2
1600 	lua_pushcclosure(L, _log, 2);
1601 	lua_setglobal(L, "print");
1602 
1603 	// lv2.hash
1604 	lua_pushlightuserdata(L, moony); // @ upvalueindex 1
1605 	lua_pushcclosure(L, _lmapper, 1);
1606 	lua_pushvalue(L, -1);
1607 	lua_setglobal(L, "HashMap"); // FIXME deprecated
1608 	lua_setglobal(L, "Mapper");
1609 
1610 	// lv2.voiceMap
1611 	lua_pushlightuserdata(L, moony); // @ upvalueindex 1
1612 	lua_pushcclosure(L, _lvoice_map, 1);
1613 	lua_setglobal(L, "Blank");
1614 
1615 	// lv2.midi2cps
1616 	lua_pushcclosure(L, _lmidi2cps, 0);
1617 	lua_setglobal(L, "midi2cps");
1618 
1619 	// lv2cps2midi.
1620 	lua_pushcclosure(L, _lcps2midi, 0);
1621 	lua_setglobal(L, "cps2midi");
1622 
1623 #define SET_MAP(L, PREFIX, PROPERTY) \
1624 ({ \
1625 	lua_getglobal(L, "Map"); \
1626 	lua_getfield(L, -1, PREFIX ## PROPERTY); \
1627 	LV2_URID urid = luaL_checkinteger(L, -1); \
1628 	lua_remove(L, -2); /* Map */ \
1629 	lua_setfield(L, -2, #PROPERTY); \
1630 	urid; \
1631 })
1632 
1633 	lua_newtable(L);
1634 	{
1635 		//SET_MAP(L, LV2_ATOM__, Blank); // is depracated
1636 		SET_MAP(L, LV2_ATOM__, Bool);
1637 		SET_MAP(L, LV2_ATOM__, Chunk);
1638 		SET_MAP(L, LV2_ATOM__, Double);
1639 		SET_MAP(L, LV2_ATOM__, Float);
1640 		SET_MAP(L, LV2_ATOM__, Int);
1641 		SET_MAP(L, LV2_ATOM__, Long);
1642 		SET_MAP(L, LV2_ATOM__, Literal);
1643 		SET_MAP(L, LV2_ATOM__, Object);
1644 		SET_MAP(L, LV2_ATOM__, Path);
1645 		SET_MAP(L, LV2_ATOM__, Property);
1646 		//SET_MAP(L, LV2_ATOM__, Resource); // is deprecated
1647 		SET_MAP(L, LV2_ATOM__, Sequence);
1648 		SET_MAP(L, LV2_ATOM__, String);
1649 		SET_MAP(L, LV2_ATOM__, Tuple);
1650 		SET_MAP(L, LV2_ATOM__, URI);
1651 		SET_MAP(L, LV2_ATOM__, URID);
1652 		SET_MAP(L, LV2_ATOM__, Vector);
1653 		SET_MAP(L, LV2_ATOM__, beatTime);
1654 		SET_MAP(L, LV2_ATOM__, frameTime);
1655 		SET_MAP(L, LV2_ATOM__, childType);
1656 	}
1657 	lua_setglobal(L, "Atom");
1658 
1659 	lua_newtable(L);
1660 	{
1661 		SET_MAP(L, LV2_MIDI__, MidiEvent);
1662 
1663 		for(const midi_msg_t *msg=midi_msgs; msg->key; msg++)
1664 		{
1665 			lua_pushinteger(L, msg->type);
1666 			lua_setfield(L, -2, msg->key);
1667 		}
1668 		for(const midi_msg_t *msg=controllers; msg->key; msg++)
1669 		{
1670 			lua_pushinteger(L, msg->type);
1671 			lua_setfield(L, -2, msg->key);
1672 		}
1673 	}
1674 	lua_setglobal(L, "MIDI");
1675 
1676 	lua_newtable(L);
1677 	{
1678 		SET_MAP(L, LV2_TIME__, Position);
1679 		SET_MAP(L, LV2_TIME__, barBeat);
1680 		SET_MAP(L, LV2_TIME__, bar);
1681 		SET_MAP(L, LV2_TIME__, beat);
1682 		SET_MAP(L, LV2_TIME__, beatUnit);
1683 		SET_MAP(L, LV2_TIME__, beatsPerBar);
1684 		SET_MAP(L, LV2_TIME__, beatsPerMinute);
1685 		SET_MAP(L, LV2_TIME__, frame);
1686 		SET_MAP(L, LV2_TIME__, framesPerSecond);
1687 		SET_MAP(L, LV2_TIME__, speed);
1688 	}
1689 	lua_setglobal(L, "Time");
1690 
1691 	lua_newtable(L);
1692 	{
1693 		SET_MAP(L, LV2_OSC__, Event);
1694 		SET_MAP(L, LV2_OSC__, Packet);
1695 		SET_MAP(L, LV2_OSC__, Bundle);
1696 		SET_MAP(L, LV2_OSC__, bundleTimetag);
1697 		SET_MAP(L, LV2_OSC__, bundleItems);
1698 		SET_MAP(L, LV2_OSC__, Message);
1699 		SET_MAP(L, LV2_OSC__, messagePath);
1700 		SET_MAP(L, LV2_OSC__, messageArguments);
1701 		SET_MAP(L, LV2_OSC__, Timetag);
1702 		SET_MAP(L, LV2_OSC__, timetagIntegral);
1703 		SET_MAP(L, LV2_OSC__, timetagFraction);
1704 		SET_MAP(L, LV2_OSC__, Nil);
1705 		SET_MAP(L, LV2_OSC__, Impulse);
1706 		SET_MAP(L, LV2_OSC__, Char);
1707 		SET_MAP(L, LV2_OSC__, RGBA);
1708 	}
1709 	lua_setglobal(L, "OSC");
1710 
1711 	lua_newtable(L);
1712 	{
1713 		SET_MAP(L, LV2_CORE__, minimum);
1714 		SET_MAP(L, LV2_CORE__, maximum);
1715 		SET_MAP(L, LV2_CORE__, scalePoint);
1716 	}
1717 	lua_setglobal(L, "LV2");
1718 
1719 	lua_newtable(L);
1720 	{
1721 		SET_MAP(L, LV2_BUF_SIZE__, minBlockLength);
1722 		SET_MAP(L, LV2_BUF_SIZE__, maxBlockLength);
1723 		SET_MAP(L, LV2_BUF_SIZE__, sequenceSize);
1724 	}
1725 	lua_setglobal(L, "Buf_Size");
1726 
1727 	lua_newtable(L);
1728 	{
1729 		SET_MAP(L, LV2_PATCH__, Ack);
1730 		SET_MAP(L, LV2_PATCH__, Delete);
1731 		SET_MAP(L, LV2_PATCH__, Copy);
1732 		SET_MAP(L, LV2_PATCH__, Error);
1733 		SET_MAP(L, LV2_PATCH__, Get);
1734 		SET_MAP(L, LV2_PATCH__, Message);
1735 		SET_MAP(L, LV2_PATCH__, Move);
1736 		SET_MAP(L, LV2_PATCH__, Insert);
1737 		SET_MAP(L, LV2_PATCH__, Patch);
1738 		SET_MAP(L, LV2_PATCH__, Post);
1739 		SET_MAP(L, LV2_PATCH__, Put);
1740 		SET_MAP(L, LV2_PATCH__, Request);
1741 		SET_MAP(L, LV2_PATCH__, Response);
1742 		SET_MAP(L, LV2_PATCH__, Set);
1743 		SET_MAP(L, LV2_PATCH__, accept);
1744 		SET_MAP(L, LV2_PATCH__, add);
1745 		SET_MAP(L, LV2_PATCH__, body);
1746 		SET_MAP(L, LV2_PATCH__, context);
1747 		SET_MAP(L, LV2_PATCH__, destination);
1748 		SET_MAP(L, LV2_PATCH__, property);
1749 		SET_MAP(L, LV2_PATCH__, readable);
1750 		SET_MAP(L, LV2_PATCH__, remove);
1751 		SET_MAP(L, LV2_PATCH__, request);
1752 		SET_MAP(L, LV2_PATCH__, subject);
1753 		SET_MAP(L, LV2_PATCH__, sequenceNumber);
1754 		SET_MAP(L, LV2_PATCH__, value);
1755 		SET_MAP(L, LV2_PATCH__, wildcard);
1756 		SET_MAP(L, LV2_PATCH__, writable);
1757 	}
1758 	lua_setglobal(L, "Patch");
1759 
1760 	lua_newtable(L);
1761 	{
1762 		SET_MAP(L, LV2_UI__, updateRate);
1763 		//TODO add more and document
1764 	}
1765 	lua_setglobal(L, "Ui");
1766 
1767 	lua_newtable(L);
1768 	{
1769 		SET_MAP(L, RDF__, value);
1770 		SET_MAP(L, RDF__, type);
1771 	}
1772 	lua_setglobal(L, "RDF");
1773 
1774 	lua_newtable(L);
1775 	{
1776 		SET_MAP(L, RDFS__, label);
1777 		SET_MAP(L, RDFS__, range);
1778 		SET_MAP(L, RDFS__, comment);
1779 	}
1780 	lua_setglobal(L, "RDFS");
1781 
1782 	lua_newtable(L);
1783 	{
1784 		SET_MAP(L, LV2_UNITS__, Conversion);
1785 		SET_MAP(L, LV2_UNITS__, Unit);
1786 		SET_MAP(L, LV2_UNITS__, bar);
1787 		SET_MAP(L, LV2_UNITS__, beat);
1788 		SET_MAP(L, LV2_UNITS__, bpm);
1789 		SET_MAP(L, LV2_UNITS__, cent);
1790 		SET_MAP(L, LV2_UNITS__, cm);
1791 		SET_MAP(L, LV2_UNITS__, coef);
1792 		SET_MAP(L, LV2_UNITS__, conversion);
1793 		SET_MAP(L, LV2_UNITS__, db);
1794 		SET_MAP(L, LV2_UNITS__, degree);
1795 		SET_MAP(L, LV2_UNITS__, frame);
1796 		SET_MAP(L, LV2_UNITS__, hz);
1797 		SET_MAP(L, LV2_UNITS__, inch);
1798 		SET_MAP(L, LV2_UNITS__, khz);
1799 		SET_MAP(L, LV2_UNITS__, km);
1800 		SET_MAP(L, LV2_UNITS__, m);
1801 		SET_MAP(L, LV2_UNITS__, mhz);
1802 		SET_MAP(L, LV2_UNITS__, midiNote);
1803 		SET_MAP(L, LV2_UNITS__, midiController);
1804 		SET_MAP(L, LV2_UNITS__, mile);
1805 		SET_MAP(L, LV2_UNITS__, min);
1806 		SET_MAP(L, LV2_UNITS__, mm);
1807 		SET_MAP(L, LV2_UNITS__, ms);
1808 		SET_MAP(L, LV2_UNITS__, name);
1809 		SET_MAP(L, LV2_UNITS__, oct);
1810 		SET_MAP(L, LV2_UNITS__, pc);
1811 		SET_MAP(L, LV2_UNITS__, prefixConversion);
1812 		SET_MAP(L, LV2_UNITS__, render);
1813 		SET_MAP(L, LV2_UNITS__, s);
1814 		SET_MAP(L, LV2_UNITS__, semitone12TET);
1815 		SET_MAP(L, LV2_UNITS__, symbol);
1816 		SET_MAP(L, LV2_UNITS__, unit);
1817 	}
1818 	lua_setglobal(L, "Units");
1819 
1820 	lua_newtable(L);
1821 	{
1822 		SET_MAP(L, CANVAS__, graph);
1823 		SET_MAP(L, CANVAS__, aspectRatio);
1824 		SET_MAP(L, CANVAS__, body);
1825 		SET_MAP(L, CANVAS__, BeginPath);
1826 		SET_MAP(L, CANVAS__, ClosePath);
1827 		SET_MAP(L, CANVAS__, Arc);
1828 		SET_MAP(L, CANVAS__, CurveTo);
1829 		SET_MAP(L, CANVAS__, LineTo);
1830 		SET_MAP(L, CANVAS__, MoveTo);
1831 		SET_MAP(L, CANVAS__, Rectangle);
1832 		SET_MAP(L, CANVAS__, PolyLine);
1833 		SET_MAP(L, CANVAS__, Style);
1834 		SET_MAP(L, CANVAS__, LineWidth);
1835 		SET_MAP(L, CANVAS__, LineDash);
1836 		SET_MAP(L, CANVAS__, LineCap);
1837 		SET_MAP(L, CANVAS__, LineJoin);
1838 		SET_MAP(L, CANVAS__, MiterLimit);
1839 		SET_MAP(L, CANVAS__, Stroke);
1840 		SET_MAP(L, CANVAS__, Fill);
1841 		SET_MAP(L, CANVAS__, Clip);
1842 		SET_MAP(L, CANVAS__, Save);
1843 		SET_MAP(L, CANVAS__, Restore);
1844 		SET_MAP(L, CANVAS__, Translate);
1845 		SET_MAP(L, CANVAS__, Scale);
1846 		SET_MAP(L, CANVAS__, Rotate);
1847 		SET_MAP(L, CANVAS__, Transform);
1848 		SET_MAP(L, CANVAS__, Reset);
1849 		SET_MAP(L, CANVAS__, FontSize);
1850 		SET_MAP(L, CANVAS__, FillText);
1851 		SET_MAP(L, CANVAS__, lineCapButt);
1852 		SET_MAP(L, CANVAS__, lineCapRound);
1853 		SET_MAP(L, CANVAS__, lineCapSquare);
1854 		SET_MAP(L, CANVAS__, lineJoinMiter);
1855 		SET_MAP(L, CANVAS__, lineJoinRound);
1856 		SET_MAP(L, CANVAS__, lineJoinBevel);
1857 		SET_MAP(L, CANVAS__, mouseButtonLeft);
1858 		SET_MAP(L, CANVAS__, mouseButtonMiddle);
1859 		SET_MAP(L, CANVAS__, mouseButtonRight);
1860 		SET_MAP(L, CANVAS__, mouseWheelX);
1861 		SET_MAP(L, CANVAS__, mouseWheelY);
1862 		SET_MAP(L, CANVAS__, mousePositionX);
1863 		SET_MAP(L, CANVAS__, mousePositionY);
1864 		SET_MAP(L, CANVAS__, mouseFocus);
1865 	}
1866 	lua_setglobal(L, "Canvas");
1867 
1868 	lua_newtable(L);
1869 	{
1870 		SET_MAP(L, XPRESS__, Token);
1871 		SET_MAP(L, XPRESS__, Alive);
1872 		SET_MAP(L, XPRESS__, source);
1873 		SET_MAP(L, XPRESS__, zone);
1874 		SET_MAP(L, XPRESS__, uuid);
1875 		SET_MAP(L, XPRESS__, body);
1876 		SET_MAP(L, XPRESS__, pitch);
1877 		SET_MAP(L, XPRESS__, pressure);
1878 		SET_MAP(L, XPRESS__, timbre);
1879 		SET_MAP(L, XPRESS__, dPitch);
1880 		SET_MAP(L, XPRESS__, dPressure);
1881 		SET_MAP(L, XPRESS__, dTimbre);
1882 	}
1883 	lua_setglobal(L, "Xpress");
1884 
1885 	lua_newtable(L);
1886 	{
1887 		SET_MAP(L, MOONY__, color);
1888 		SET_MAP(L, MOONY__, syntax);
1889 		//TODO more
1890 	}
1891 	lua_setglobal(L, "Moony");
1892 
1893 	lua_newtable(L);
1894 	{
1895 		moony->uris.param_sampleRate = SET_MAP(L, LV2_PARAMETERS__, sampleRate);
1896 		//TODO more
1897 	}
1898 	lua_setglobal(L, "Param");
1899 
1900 	lua_newtable(L);
1901 	{
1902 		SET_MAP(L, LUA__, lang);
1903 	}
1904 	lua_setglobal(L, "Lua");
1905 
1906 	// create userdata caches
1907 	lua_newtable(L);
1908 	lua_rawsetp(L, LUA_REGISTRYINDEX, &moony_ref[MOONY_UDATA_ATOM]);
1909 
1910 	lua_newtable(L);
1911 	lua_rawsetp(L, LUA_REGISTRYINDEX, &moony_ref[MOONY_UDATA_FORGE]);
1912 
1913 	lua_newtable(L);
1914 	lua_rawsetp(L, LUA_REGISTRYINDEX, &moony_ref[MOONY_UDATA_STASH]);
1915 
1916 	// MIDIResponder metatable
1917 	luaL_newmetatable(L, "lmidiresponder");
1918 	lua_pushlightuserdata(L, moony); // @ upvalueindex 1
1919 	luaL_setfuncs (L, lmidiresponder_mt, 1);
1920 	_protect_metatable(L, -1);
1921 	lua_pop(L, 1);
1922 
1923 	// MIDIResponder factory
1924 	lua_pushlightuserdata(L, moony); // @ upvalueindex 1
1925 	lua_pushcclosure(L, _lmidiresponder, 1);
1926 	lua_setglobal(L, "MIDIResponder");
1927 
1928 	// OSCResponder metatable
1929 	luaL_newmetatable(L, "loscresponder");
1930 	lua_pushlightuserdata(L, moony); // @ upvalueindex 1
1931 	luaL_setfuncs (L, loscresponder_mt, 1);
1932 	_protect_metatable(L, -1);
1933 	lua_pop(L, 1);
1934 
1935 	// OSCResponder factory
1936 	lua_pushlightuserdata(L, moony); // @ upvalueindex 1
1937 	lua_pushcclosure(L, _loscresponder, 1);
1938 	lua_setglobal(L, "OSCResponder");
1939 
1940 	// OSCResponder pattern matcher
1941 	(void)luaL_dostring(L, loscresponder_match); // cannot fail
1942 
1943 	// TimeResponder metatable
1944 	luaL_newmetatable(L, "ltimeresponder");
1945 	lua_pushlightuserdata(L, moony); // @ upvalueindex 1
1946 	luaL_setfuncs (L, ltimeresponder_mt, 1);
1947 	_protect_metatable(L, -1);
1948 	// we have a __index function, thus no __index table here
1949 	lua_pop(L, 1);
1950 
1951 	// TimeResponder factory
1952 	lua_pushlightuserdata(L, moony); // @ upvalueindex 1
1953 	lua_pushcclosure(L, _ltimeresponder, 1);
1954 	lua_setglobal(L, "TimeResponder");
1955 
1956 	// StateResponder metatable
1957 	luaL_newmetatable(L, "lstateresponder");
1958 	lua_pushlightuserdata(L, moony); // @ upvalueindex 1
1959 	luaL_setfuncs (L, lstateresponder_mt, 1);
1960 	_protect_metatable(L, -1);
1961 	_index_metatable(L, -1);
1962 	lua_pop(L, 1);
1963 
1964 	// StateResponder factory
1965 	lua_pushlightuserdata(L, moony); // @ upvalueindex 1
1966 	lua_pushcclosure(L, _lstateresponder, 1);
1967 	lua_setglobal(L, "StateResponder");
1968 
1969 	// Parameter metatable
1970 	luaL_newmetatable(L, "lparameter");
1971 	lua_pushlightuserdata(L, moony); // @ upvalueindex 1
1972 	luaL_setfuncs (L, lparameter_mt, 1);
1973 	_protect_metatable(L, -1);
1974 	//_index_metatable(L, -1);
1975 	lua_pop(L, 1);
1976 
1977 	// Parameter factory
1978 	lua_pushlightuserdata(L, moony); // @ upvalueindex 1
1979 	lua_pushcclosure(L, _lparameter, 1);
1980 	lua_setglobal(L, "Parameter");
1981 
1982 	// Stash factory
1983 	lua_pushlightuserdata(L, moony); // @ upvalueindex 1
1984 	lua_pushlightuserdata(L, vm); // @ upvalueindex 2
1985 	lua_pushcclosure(L, _lstash, 2);
1986 	lua_setglobal(L, "Stash");
1987 
1988 	// create cclosure caches
1989 	lua_pushlightuserdata(L, moony);
1990 	lua_pushcclosure(L, _save, 1);
1991 	lua_rawsetp(L, LUA_REGISTRYINDEX, _save);
1992 
1993 	lua_pushlightuserdata(L, moony);
1994 	lua_pushcclosure(L, _restore, 1);
1995 	lua_rawsetp(L, LUA_REGISTRYINDEX, _restore);
1996 
1997 	lua_pushlightuserdata(L, moony);
1998 	lua_pushcclosure(L, _stash, 1);
1999 	lua_rawsetp(L, LUA_REGISTRYINDEX, _stash);
2000 
2001 	lua_pushlightuserdata(L, moony);
2002 	lua_pushcclosure(L, _apply, 1);
2003 	lua_rawsetp(L, LUA_REGISTRYINDEX, _apply);
2004 
2005 	lua_pushlightuserdata(L, moony);
2006 	lua_pushcclosure(L, _ltimeresponder_stash, 1);
2007 	lua_rawsetp(L, LUA_REGISTRYINDEX, _ltimeresponder_stash);
2008 
2009 	lua_pushlightuserdata(L, moony);
2010 	lua_pushcclosure(L, _ltimeresponder_apply, 1);
2011 	lua_rawsetp(L, LUA_REGISTRYINDEX, _ltimeresponder_apply);
2012 
2013 	lua_pushlightuserdata(L, moony);
2014 	lua_pushcclosure(L, _latom_clone, 1);
2015 	lua_rawsetp(L, LUA_REGISTRYINDEX, _latom_clone);
2016 
2017 	lua_pushlightuserdata(L, moony);
2018 	lua_pushcclosure(L, _lstash_write, 1);
2019 	lua_rawsetp(L, LUA_REGISTRYINDEX, _lstash_write);
2020 
2021 	lua_pushlightuserdata(L, moony);
2022 	lua_pushcclosure(L, _lstash_read, 1);
2023 	lua_rawsetp(L, LUA_REGISTRYINDEX, _lstash_read);
2024 
2025 	lua_pushlightuserdata(L, moony);
2026 	lua_pushcclosure(L, _latom_literal_unpack, 1);
2027 	lua_rawsetp(L, LUA_REGISTRYINDEX, _latom_literal_unpack);
2028 
2029 	lua_pushlightuserdata(L, moony);
2030 	lua_pushcclosure(L, _latom_tuple_unpack, 1);
2031 	lua_rawsetp(L, LUA_REGISTRYINDEX, _latom_tuple_unpack);
2032 
2033 	lua_pushlightuserdata(L, moony);
2034 	lua_pushcclosure(L, _latom_vec_unpack, 1);
2035 	lua_rawsetp(L, LUA_REGISTRYINDEX, _latom_vec_unpack);
2036 
2037 	lua_pushlightuserdata(L, moony);
2038 	lua_pushcclosure(L, _latom_chunk_unpack, 1);
2039 	lua_rawsetp(L, LUA_REGISTRYINDEX, _latom_chunk_unpack);
2040 
2041 	lua_pushlightuserdata(L, moony);
2042 	lua_pushcclosure(L, _latom_tuple_foreach, 1);
2043 	lua_rawsetp(L, LUA_REGISTRYINDEX, _latom_tuple_foreach);
2044 
2045 	lua_pushlightuserdata(L, moony);
2046 	lua_pushcclosure(L, _latom_vec_foreach, 1);
2047 	lua_rawsetp(L, LUA_REGISTRYINDEX, _latom_vec_foreach);
2048 
2049 	lua_pushlightuserdata(L, moony);
2050 	lua_pushcclosure(L, _latom_obj_foreach, 1);
2051 	lua_rawsetp(L, LUA_REGISTRYINDEX, _latom_obj_foreach);
2052 
2053 	lua_pushlightuserdata(L, moony);
2054 	lua_pushcclosure(L, _latom_seq_foreach, 1);
2055 	lua_rawsetp(L, LUA_REGISTRYINDEX, _latom_seq_foreach);
2056 
2057 	lua_pushlightuserdata(L, moony);
2058 	lua_pushcclosure(L, _lforge_autopop_itr, 1);
2059 	lua_rawsetp(L, LUA_REGISTRYINDEX, _lforge_autopop_itr);
2060 
2061 	lua_newtable(L);
2062 	lua_rawsetp(L, LUA_REGISTRYINDEX, &upclosures[MOONY_UPCLOSURE_TUPLE_FOREACH]);
2063 
2064 	lua_newtable(L);
2065 	lua_rawsetp(L, LUA_REGISTRYINDEX, &upclosures[MOONY_UPCLOSURE_VECTOR_FOREACH]);
2066 
2067 	lua_newtable(L);
2068 	lua_rawsetp(L, LUA_REGISTRYINDEX, &upclosures[MOONY_UPCLOSURE_OBJECT_FOREACH]);
2069 
2070 	lua_newtable(L);
2071 	lua_rawsetp(L, LUA_REGISTRYINDEX, &upclosures[MOONY_UPCLOSURE_SEQUENCE_FOREACH]);
2072 
2073 	lua_newtable(L);
2074 	lua_rawsetp(L, LUA_REGISTRYINDEX, &upclosures[MOONY_UPCLOSURE_SEQUENCE_MULTIPLEX]);
2075 
2076 #undef SET_MAP
2077 }
2078 
2079 __realtime void *
moony_newuserdata(lua_State * L,moony_t * moony,moony_udata_t type,bool cache)2080 moony_newuserdata(lua_State *L, moony_t *moony, moony_udata_t type, bool cache)
2081 {
2082 	assert( (type >= MOONY_UDATA_ATOM) && (type < MOONY_UDATA_COUNT) );
2083 
2084 	int *itr = &moony->itr[type];
2085 	void *data = NULL;
2086 
2087 	if(cache) // do cash this!
2088 	{
2089 		lua_rawgetp(L, LUA_REGISTRYINDEX, &moony_ref[type]); // ref
2090 		if(lua_rawgeti(L, -1, *itr) == LUA_TNIL) // no cached udata, create one!
2091 		{
2092 #if 0
2093 			if(moony->log)
2094 				lv2_log_trace(&moony->logger, "moony_newuserdata: %s\n", moony_ref[type]);
2095 #endif
2096 			lua_pop(L, 1); // nil
2097 
2098 			data = lua_newuserdata(L, moony_sz[type]);
2099 			lheader_t *lheader = data;
2100 			lheader->type = type;
2101 			lheader->cache = cache;
2102 			luaL_getmetatable(L, moony_ref[type]);
2103 			lua_setmetatable(L, -2);
2104 			lua_pushvalue(L, -1);
2105 			lua_rawseti(L, -3, *itr); // store in cache
2106 		}
2107 		else // there is a cached udata, use it!
2108 		{
2109 			data = lua_touserdata(L, -1);
2110 			//printf("moony_newuserdata: %s %"PRIi32" %p\n", moony_ref[type], *itr, data);
2111 		}
2112 		lua_remove(L, -2); // ref
2113 		*itr += 1;
2114 	}
2115 	else // do not cash this!
2116 	{
2117 		data = lua_newuserdata(L, moony_sz[type]);
2118 		lheader_t *lheader = data;
2119 		lheader->type = type;
2120 		lheader->cache = cache;
2121 		luaL_getmetatable(L, moony_ref[type]);
2122 		lua_setmetatable(L, -2);
2123 	}
2124 
2125 	return data;
2126 }
2127 
2128 __realtime void
moony_pre(moony_t * moony,LV2_Atom_Sequence * notify)2129 moony_pre(moony_t *moony, LV2_Atom_Sequence *notify)
2130 {
2131 	// initialize notify forge
2132 	const uint32_t capacity = notify->atom.size;
2133 	lv2_atom_forge_set_buffer(&moony->notify_forge, (uint8_t *)notify, capacity);
2134 	moony->notify_ref = lv2_atom_forge_sequence_head(&moony->notify_forge, &moony->notify_frame, 0);
2135 }
2136 
2137 __realtime static LV2_Atom_Forge_Ref
_patch_set(patch_t * patch,LV2_Atom_Forge * forge,LV2_URID property,uint32_t size,LV2_URID type,const void * body)2138 _patch_set(patch_t *patch, LV2_Atom_Forge *forge, LV2_URID property, uint32_t size, LV2_URID type, const void *body)
2139 {
2140 	LV2_Atom_Forge_Frame frame;
2141 	LV2_Atom_Forge_Ref ref = lv2_atom_forge_object(forge, &frame, 0, patch->set);
2142 
2143 	if(ref)
2144 		ref = lv2_atom_forge_key(forge, patch->property);
2145 	if(ref)
2146 		ref = lv2_atom_forge_urid(forge, property);
2147 
2148 	if(ref)
2149 		ref = lv2_atom_forge_key(forge, patch->value);
2150 	if(ref)
2151 		ref = lv2_atom_forge_atom(forge, size, type);
2152 	if(ref)
2153 		ref = lv2_atom_forge_write(forge, body, size);
2154 
2155 	if(ref)
2156 		lv2_atom_forge_pop(forge, &frame);
2157 
2158 	return ref;
2159 }
2160 
2161 __realtime static inline LV2_Atom_Forge_Ref
_moony_chunk_out(moony_t * moony,uint32_t frames,LV2_Atom_Forge * forge)2162 _moony_chunk_out(moony_t *moony, uint32_t frames, LV2_Atom_Forge *forge)
2163 {
2164 	const uint32_t len = strlen(moony->chunk);
2165 
2166 	LV2_Atom_Forge_Ref ref = lv2_atom_forge_frame_time(forge, frames);
2167 	if(ref)
2168 		ref = _moony_patch(&moony->uris.patch, forge, moony->uris.moony_code, moony->chunk, len);
2169 
2170 	return ref;
2171 }
2172 
2173 __realtime static inline LV2_Atom_Forge_Ref
_moony_props_out(moony_t * moony,uint32_t frames,LV2_Atom_Forge * forge)2174 _moony_props_out(moony_t *moony, uint32_t frames, LV2_Atom_Forge *forge)
2175 {
2176 	// clear all properties in UI
2177 	LV2_Atom_Forge_Frame obj_frame, add_frame, rem_frame;
2178 	LV2_Atom_Forge_Ref ref = lv2_atom_forge_frame_time(forge, frames);
2179 	if(ref)
2180 		ref = lv2_atom_forge_object(forge, &obj_frame, 0, moony->uris.patch.patch);
2181 	if(ref)
2182 		ref = lv2_atom_forge_key(forge, moony->uris.patch.subject);
2183 	if(ref)
2184 		ref = lv2_atom_forge_urid(forge, moony->uris.patch.self);
2185 	if(ref)
2186 		ref = lv2_atom_forge_key(forge, moony->uris.patch.sequence);
2187 	if(ref)
2188 		ref = lv2_atom_forge_int(forge, 0); // we don't expect a reply
2189 	if(ref)
2190 		ref = lv2_atom_forge_key(forge, moony->uris.patch.remove);
2191 	if(ref)
2192 		ref = lv2_atom_forge_object(forge, &rem_frame, 0, 0);
2193 	if(ref)
2194 		ref = lv2_atom_forge_key(forge, moony->uris.patch.writable);
2195 	if(ref)
2196 		ref = lv2_atom_forge_urid(forge, moony->uris.patch.wildcard);
2197 	if(ref)
2198 		ref = lv2_atom_forge_key(forge, moony->uris.patch.readable);
2199 	if(ref)
2200 		ref = lv2_atom_forge_urid(forge, moony->uris.patch.wildcard);
2201 	if(ref)
2202 		lv2_atom_forge_pop(forge, &rem_frame);
2203 	if(ref)
2204 		ref = lv2_atom_forge_key(forge, moony->uris.patch.add);
2205 	if(ref)
2206 		lv2_atom_forge_object(forge, &add_frame, 0, 0);
2207 	if(ref)
2208 		lv2_atom_forge_pop(forge, &add_frame);
2209 	if(ref)
2210 		lv2_atom_forge_pop(forge, &obj_frame);
2211 
2212 	return ref;
2213 }
2214 
2215 __realtime LV2_Worker_Status
moony_wake_worker(const LV2_Worker_Schedule * work_sched)2216 moony_wake_worker(const LV2_Worker_Schedule *work_sched)
2217 {
2218 	int32_t dummy;
2219 	return work_sched->schedule_work(work_sched->handle, sizeof(int32_t), &dummy);
2220 }
2221 
2222 __realtime bool
moony_in(moony_t * moony,const LV2_Atom_Sequence * control,LV2_Atom_Sequence * notify)2223 moony_in(moony_t *moony, const LV2_Atom_Sequence *control, LV2_Atom_Sequence *notify)
2224 {
2225 	LV2_Atom_Forge *forge = &moony->notify_forge;
2226 	LV2_Atom_Forge_Ref ref = moony->notify_ref;
2227 
2228 	char *chunk_new = (char *)atomic_exchange_explicit(&moony->chunk_new, 0, memory_order_relaxed);
2229 	if(chunk_new)
2230 	{
2231 		snprintf(moony->chunk, MOONY_MAX_CHUNK_LEN, "%s", chunk_new);
2232 		if(ref)
2233 			ref = _moony_chunk_out(moony, 0, forge);
2234 
2235 		moony_job_t *req;
2236 		if((req = varchunk_write_request(moony->from_dsp, sizeof(moony_job_t))))
2237 		{
2238 			req->type = MOONY_JOB_PTR_FREE;
2239 			req->ptr = chunk_new;
2240 
2241 			varchunk_write_advance(moony->from_dsp, sizeof(moony_job_t));
2242 			if(moony_wake_worker(moony->sched) != LV2_WORKER_SUCCESS)
2243 				moony_trace(moony, "waking worker failed");
2244 		}
2245 	}
2246 
2247 	char *err_new = (char *)atomic_exchange_explicit(&moony->err_new, 0, memory_order_relaxed);
2248 	if(err_new)
2249 	{
2250 		//  always overwrite previous error message
2251 		snprintf(moony->error, MOONY_MAX_ERROR_LEN, "%s", err_new);
2252 		moony->error_out = true;
2253 
2254 		moony_job_t *req;
2255 		if((req = varchunk_write_request(moony->from_dsp, sizeof(moony_job_t))))
2256 		{
2257 			req->type = MOONY_JOB_PTR_FREE;
2258 			req->ptr = err_new;
2259 
2260 			varchunk_write_advance(moony->from_dsp, sizeof(moony_job_t));
2261 			if(moony_wake_worker(moony->sched) != LV2_WORKER_SUCCESS)
2262 				moony_trace(moony, "waking worker failed");
2263 		}
2264 	}
2265 
2266 	LV2_Atom *state_atom_new = (LV2_Atom *)atomic_exchange_explicit(&moony->state_atom_new, 0, memory_order_relaxed);
2267 	if(state_atom_new)
2268 	{
2269 		LV2_Atom *state_atom_old = moony->state_atom;
2270 		moony->state_atom = state_atom_new;
2271 
2272 		if(state_atom_old)
2273 		{
2274 			moony_job_t *req;
2275 			if((req = varchunk_write_request(moony->from_dsp, sizeof(moony_job_t))))
2276 			{
2277 				req->type = MOONY_JOB_PTR_FREE;
2278 				req->ptr = state_atom_old;
2279 
2280 				varchunk_write_advance(moony->from_dsp, sizeof(moony_job_t));
2281 				if(moony_wake_worker(moony->sched) != LV2_WORKER_SUCCESS)
2282 					moony_trace(moony, "waking worker failed");
2283 			}
2284 		}
2285 	}
2286 
2287 	moony_vm_t *vm_new = (moony_vm_t *)atomic_exchange_explicit(&moony->vm_new, 0, memory_order_relaxed);
2288 	if(vm_new)
2289 	{
2290 		lua_State *L = moony_current(moony);
2291 
2292 		moony->error[0] = 0x0; // clear error message
2293 		moony->error_out = true;
2294 
2295 		// stash
2296 		lua_rawgetp(L, LUA_REGISTRYINDEX, _stash);
2297 		if(lua_pcall(L, 0, 0, 0))
2298 			moony_error(moony);
2299 #ifdef USE_MANUAL_GC
2300 		lua_gc(L, LUA_GCSTEP, 0);
2301 #endif
2302 
2303 		// switch VM states
2304 		moony_vm_t *vm_old = moony->vm;
2305 		moony->vm = vm_new;
2306 		L = moony_current(moony);
2307 
2308 		if(moony->state_atom)
2309 		{
2310 			// restore Lua defined properties
2311 			lua_rawgetp(L, LUA_REGISTRYINDEX, _restore);
2312 			if(lua_pcall(L, 0, 0, 0))
2313 				moony_error(moony);
2314 #ifdef USE_MANUAL_GC
2315 			lua_gc(L, LUA_GCSTEP, 0);
2316 #endif
2317 		}
2318 
2319 		// apply stash
2320 		if(moony->stash_atom) // something has been stashed previously
2321 		{
2322 			lua_rawgetp(L, LUA_REGISTRYINDEX, _apply);
2323 			if(lua_pcall(L, 0, 0, 0))
2324 				moony_error(moony);
2325 #ifdef USE_MANUAL_GC
2326 			lua_gc(L, LUA_GCSTEP, 0);
2327 #endif
2328 
2329 			moony_rt_free(vm_old, moony->stash_atom, moony->stash_size);
2330 			moony->stash_atom = NULL;
2331 			moony->stash_size = 0;
2332 		}
2333 
2334 		{
2335 			moony_job_t *req;
2336 			if((req = varchunk_write_request(moony->from_dsp, sizeof(moony_job_t))))
2337 			{
2338 				req->type = MOONY_JOB_VM_FREE;
2339 				req->vm = vm_old;
2340 
2341 				varchunk_write_advance(moony->from_dsp, sizeof(moony_job_t));
2342 				if(moony_wake_worker(moony->sched) != LV2_WORKER_SUCCESS)
2343 					moony_trace(moony, "waking worker failed");
2344 			}
2345 		}
2346 
2347 		moony->once = true;
2348 
2349 		if(ref)
2350 			ref = _moony_props_out(moony, 0, forge);
2351 
2352 #if defined(BUILD_INLINE_DISP)
2353 		// invalidate inline display
2354 		const LV2_Atom fake = {
2355 			.size = 0,
2356 			.type = moony->forge.Tuple
2357 		};
2358 
2359 		const uint32_t tot_size = lv2_atom_total_size(&fake);
2360 		void *dst;
2361 		if( (dst = varchunk_write_request(moony->to_idisp, tot_size)) )
2362 		{
2363 			memcpy(dst, &fake, tot_size);
2364 			varchunk_write_advance(moony->to_idisp, tot_size);
2365 
2366 			lv2_canvas_idisp_queue_draw(&moony->canvas_idisp);
2367 		}
2368 #endif
2369 	}
2370 
2371 	// read control sequence
2372 	LV2_ATOM_SEQUENCE_FOREACH(control, ev)
2373 	{
2374 		const LV2_Atom_Object *obj = (const LV2_Atom_Object *)&ev->body;
2375 
2376 		if(!lv2_atom_forge_is_object_type(&moony->forge, obj->atom.type))
2377 			continue;
2378 
2379 		if(obj->body.otype == moony->uris.patch.get)
2380 		{
2381 			const LV2_Atom_URID *subject = NULL;
2382 			const LV2_Atom_URID *property = NULL;
2383 			const LV2_Atom_Int *sequence= NULL;
2384 
2385 			lv2_atom_object_get(obj,
2386 				moony->uris.patch.subject, &subject,
2387 				moony->uris.patch.property, &property,
2388 				moony->uris.patch.sequence, &sequence,
2389 				0);
2390 
2391 			int32_t sequence_num = 0;
2392 			if(sequence && (sequence->atom.type == moony->forge.Int))
2393 				sequence_num = sequence->body;
2394 			(void)sequence_num; //FIXME use
2395 
2396 			if(  subject
2397 				&& (subject->atom.type == moony->forge.URID)
2398 				&& (subject->body != moony->uris.patch.self) )
2399 				continue; // subject does not match
2400 
2401 			if(property && (property->atom.type == moony->forge.URID) )
2402 			{
2403 				if(property->body == moony->uris.moony_code)
2404 				{
2405 					if(ref)
2406 						ref = _moony_chunk_out(moony, 0, forge);
2407 				}
2408 				else if(property->body == moony->uris.moony_error)
2409 				{
2410 					if(moony->error[0] != 0x0)
2411 						moony->error_out = true;
2412 				}
2413 				else if(property->body == moony->uris.moony_editorHidden)
2414 				{
2415 					const int32_t i32 = atomic_load_explicit(&moony->editor_hidden, memory_order_acquire);
2416 					if(ref)
2417 						ref = lv2_atom_forge_frame_time(forge, 0); //FIXME
2418 					if(ref)
2419 						ref = _patch_set(&moony->uris.patch, forge, property->body, sizeof(int32_t), forge->Bool, &i32);
2420 				}
2421 				else if(property->body == moony->uris.moony_graphHidden)
2422 				{
2423 					const int32_t i32 = atomic_load_explicit(&moony->graph_hidden, memory_order_acquire);
2424 					if(ref)
2425 						ref = lv2_atom_forge_frame_time(forge, 0); //FIXME
2426 					if(ref)
2427 						ref = _patch_set(&moony->uris.patch, forge, property->body, sizeof(int32_t), forge->Bool, &i32);
2428 				}
2429 				else if(property->body == moony->uris.moony_logHidden)
2430 				{
2431 					const int32_t i32 = atomic_load_explicit(&moony->log_hidden, memory_order_acquire);
2432 					if(ref)
2433 						ref = lv2_atom_forge_frame_time(forge, 0); //FIXME
2434 					if(ref)
2435 						ref = _patch_set(&moony->uris.patch, forge, property->body, sizeof(int32_t), forge->Bool, &i32);
2436 				}
2437 				else if(property->body == moony->uris.moony_logFollow)
2438 				{
2439 					const int32_t i32 = atomic_load_explicit(&moony->log_follow, memory_order_acquire);
2440 					if(ref)
2441 						ref = lv2_atom_forge_frame_time(forge, 0); //FIXME
2442 					if(ref)
2443 						ref = _patch_set(&moony->uris.patch, forge, property->body, sizeof(int32_t), forge->Bool, &i32);
2444 				}
2445 				else if(property->body == moony->uris.moony_logReset)
2446 				{
2447 					const int32_t i32 = atomic_load_explicit(&moony->log_reset, memory_order_acquire);
2448 					if(ref)
2449 						ref = lv2_atom_forge_frame_time(forge, 0); //FIXME
2450 					if(ref)
2451 						ref = _patch_set(&moony->uris.patch, forge, property->body, sizeof(int32_t), forge->Bool, &i32);
2452 				}
2453 				else if(property->body == moony->uris.moony_paramHidden)
2454 				{
2455 					const int32_t i32 = atomic_load_explicit(&moony->param_hidden, memory_order_acquire);
2456 					if(ref)
2457 						ref = lv2_atom_forge_frame_time(forge, 0); //FIXME
2458 					if(ref)
2459 						ref = _patch_set(&moony->uris.patch, forge, property->body, sizeof(int32_t), forge->Bool, &i32);
2460 				}
2461 				else if(property->body == moony->uris.moony_paramCols)
2462 				{
2463 					const int32_t i32 = atomic_load_explicit(&moony->param_cols, memory_order_acquire);
2464 					if(ref)
2465 						ref = lv2_atom_forge_frame_time(forge, 0); //FIXME
2466 					if(ref)
2467 						ref = _patch_set(&moony->uris.patch, forge, property->body, sizeof(int32_t), forge->Int, &i32);
2468 				}
2469 				else if(property->body == moony->uris.moony_paramRows)
2470 				{
2471 					const int32_t i32 = atomic_load_explicit(&moony->param_rows, memory_order_acquire);
2472 					if(ref)
2473 						ref = lv2_atom_forge_frame_time(forge, 0); //FIXME
2474 					if(ref)
2475 						ref = _patch_set(&moony->uris.patch, forge, property->body, sizeof(int32_t), forge->Int, &i32);
2476 				}
2477 			}
2478 			else // !property
2479 			{
2480 				if(ref)
2481 					ref = _moony_props_out(moony, 0, forge);
2482 			}
2483 		}
2484 		else if(obj->body.otype == moony->uris.patch.set)
2485 		{
2486 			const LV2_Atom_URID *subject = NULL;
2487 			const LV2_Atom_URID *property = NULL;
2488 			const LV2_Atom_Int *sequence = NULL;
2489 			const LV2_Atom *value = NULL;
2490 
2491 			lv2_atom_object_get(obj,
2492 				moony->uris.patch.subject, &subject,
2493 				moony->uris.patch.property, &property,
2494 				moony->uris.patch.sequence, &sequence,
2495 				moony->uris.patch.value, &value,
2496 				0);
2497 
2498 			int32_t sequence_num = 0;
2499 			if(sequence && (sequence->atom.type == moony->forge.Int))
2500 				sequence_num = sequence->body;
2501 			(void)sequence_num; //FIXME use
2502 
2503 			if(  subject
2504 				&& (subject->atom.type == moony->forge.URID)
2505 				&& (subject->body != moony->uris.patch.self) )
2506 				continue; // subject does not match
2507 
2508 			if(  property && value
2509 				&& (property->atom.type == moony->forge.URID) )
2510 			{
2511 				if( (property->body == moony->uris.moony_code) && (value->type == forge->String) )
2512 				{
2513 					// send code to worker thread
2514 					const size_t sz = sizeof(moony_job_t) + value->size;
2515 					moony_job_t *req;
2516 					if((req = varchunk_write_request(moony->from_dsp, sz)))
2517 					{
2518 						req->type = MOONY_JOB_VM_ALLOC;
2519 						memcpy(req->chunk, LV2_ATOM_BODY_CONST(value), value->size);
2520 
2521 						varchunk_write_advance(moony->from_dsp, sz);
2522 						if(moony_wake_worker(moony->sched) != LV2_WORKER_SUCCESS)
2523 							moony_trace(moony, "waking worker failed");
2524 					}
2525 				}
2526 				else if( (property->body == moony->uris.moony_editorHidden) && (value->type == forge->Bool) )
2527 				{
2528 					atomic_store_explicit(&moony->editor_hidden, ((const LV2_Atom_Bool *)value)->body, memory_order_release);
2529 				}
2530 				else if( (property->body == moony->uris.moony_graphHidden) && (value->type == forge->Bool) )
2531 				{
2532 					atomic_store_explicit(&moony->graph_hidden, ((const LV2_Atom_Bool *)value)->body, memory_order_release);
2533 				}
2534 				else if( (property->body == moony->uris.moony_logHidden) && (value->type == forge->Bool) )
2535 				{
2536 					atomic_store_explicit(&moony->log_hidden, ((const LV2_Atom_Bool *)value)->body, memory_order_release);
2537 				}
2538 				else if( (property->body == moony->uris.moony_logFollow) && (value->type == forge->Bool) )
2539 				{
2540 					atomic_store_explicit(&moony->log_follow, ((const LV2_Atom_Bool *)value)->body, memory_order_release);
2541 				}
2542 				else if( (property->body == moony->uris.moony_logReset) && (value->type == forge->Bool) )
2543 				{
2544 					atomic_store_explicit(&moony->log_reset, ((const LV2_Atom_Bool *)value)->body, memory_order_release);
2545 				}
2546 				else if( (property->body == moony->uris.moony_paramHidden) && (value->type == forge->Bool) )
2547 				{
2548 					atomic_store_explicit(&moony->param_hidden, ((const LV2_Atom_Bool *)value)->body, memory_order_release);
2549 				}
2550 				else if( (property->body == moony->uris.moony_paramCols) && (value->type == forge->Int) )
2551 				{
2552 					atomic_store_explicit(&moony->param_cols, ((const LV2_Atom_Int *)value)->body, memory_order_release);
2553 				}
2554 				else if( (property->body == moony->uris.moony_paramRows) && (value->type == forge->Int) )
2555 				{
2556 					atomic_store_explicit(&moony->param_rows, ((const LV2_Atom_Int *)value)->body, memory_order_release);
2557 				}
2558 				else if( (property->body == moony->uris.moony_panic) && (value->type == forge->Bool) )
2559 				{
2560 					const LV2_Atom_Bool *i32 = (const LV2_Atom_Bool *)value;
2561 					if(i32->body)
2562 						moony_err(moony, "user called panic");
2563 				}
2564 			}
2565 		}
2566 	}
2567 
2568 	if(moony->error_out)
2569 	{
2570 		const uint32_t len = strlen(moony->error);
2571 		if(ref)
2572 			ref = lv2_atom_forge_frame_time(forge, 0);
2573 		if(ref)
2574 			ref = _moony_patch(&moony->uris.patch, forge, moony->uris.moony_error, moony->error, len);
2575 
2576 		moony->error_out = false; // reset flag
2577 	}
2578 
2579 	moony->notify_ref = ref;
2580 	moony->notify_snapshot = *forge; // make snapshot if script should error before moony_out
2581 
2582 	return moony->once;
2583 }
2584 
2585 __realtime void
moony_out(moony_t * moony,LV2_Atom_Sequence * notify,uint32_t frames)2586 moony_out(moony_t *moony, LV2_Atom_Sequence *notify, uint32_t frames)
2587 {
2588 	LV2_Atom_Forge *forge = &moony->notify_forge;
2589 	LV2_Atom_Forge_Ref ref = moony->notify_ref;
2590 	moony_vm_t *vm = moony->vm;
2591 
2592 	if(moony_bypass(moony)) // discard any written atoms on notify port since moony_in
2593 	{
2594 		*forge = moony->notify_snapshot;
2595 		notify->atom.size = forge->offset - sizeof(LV2_Atom);
2596 	}
2597 
2598 	if(vm->trace_out)
2599 	{
2600 		for(const char *from = vm->trace, *to = strchr(from, '\n');
2601 			from && to;
2602 			from = to + 1, to = strchr(from, '\n'))
2603 		{
2604 			if(ref)
2605 				ref = lv2_atom_forge_frame_time(forge, frames);
2606 			if(ref)
2607 				ref = _moony_patch(&moony->uris.patch, forge, moony->uris.moony_trace, from, to - from);
2608 		}
2609 
2610 		vm->trace[0] = '\0';
2611 		vm->trace_out = false; // reset flag
2612 	}
2613 
2614 	if(vm->trace_overflow)
2615 	{
2616 		if(moony->log)
2617 			lv2_log_trace(&moony->logger, "trace buffer overflow\n");
2618 		vm->trace_overflow = false; // reset flag
2619 	}
2620 
2621 	if(ref)
2622 		lv2_atom_forge_pop(forge, &moony->notify_frame);
2623 	else
2624 		lv2_atom_sequence_clear(notify);
2625 
2626 #if defined(BUILD_INLINE_DISP)
2627 	LV2_ATOM_SEQUENCE_FOREACH(notify, ev)
2628 	{
2629 		const LV2_Atom_Object *obj = (const LV2_Atom_Object *)&ev->body;
2630 
2631 		if(!lv2_atom_forge_is_object_type(forge, obj->atom.type))
2632 		{
2633 			continue;
2634 		}
2635 
2636 		if(obj->body.otype == moony->uris.patch.set)
2637 		{
2638 			const LV2_Atom_URID *subject = NULL;
2639 			const LV2_Atom_URID *property = NULL;
2640 			const LV2_Atom *value = NULL;
2641 
2642 			lv2_atom_object_get(obj,
2643 				moony->uris.patch.subject, &subject,
2644 				moony->uris.patch.property, &property,
2645 				moony->uris.patch.value, &value,
2646 				0);
2647 
2648 			const LV2_URID subj = subject && (subject->atom.type == forge->URID)
2649 				? subject->body : 0;
2650 			(void)subj;
2651 			//FIXME check subj
2652 
2653 			const LV2_URID prop = property && (property->atom.type == forge->URID)
2654 				? property->body : 0;
2655 
2656 			if(  (prop == moony->canvas_urid.Canvas_graph)
2657 				&& value
2658 				&& (value->type == forge->Tuple) )
2659 			{
2660 				const uint32_t tot_size = lv2_atom_total_size(value);
2661 				void *dst;
2662 				if( (dst = varchunk_write_request(moony->to_idisp, tot_size)) )
2663 				{
2664 					memcpy(dst, value, tot_size);
2665 					varchunk_write_advance(moony->to_idisp, tot_size);
2666 
2667 					lv2_canvas_idisp_queue_draw(&moony->canvas_idisp);
2668 				}
2669 			}
2670 		}
2671 		else if(obj->body.otype == moony->uris.patch.put)
2672 		{
2673 			const LV2_Atom_URID *subject = NULL;
2674 			const LV2_Atom_Object *body = NULL;
2675 
2676 			lv2_atom_object_get(obj,
2677 				moony->uris.patch.subject, &subject,
2678 				moony->uris.patch.body, &body,
2679 				0);
2680 
2681 			const LV2_URID subj = subject && (subject->atom.type == forge->URID)
2682 				? subject->body : 0;
2683 			(void)subj;
2684 			//FIXME check subj
2685 
2686 			if(  body
2687 				&& lv2_atom_forge_is_object_type(forge, body->atom.type) )
2688 			{
2689 				LV2_ATOM_OBJECT_FOREACH(body, prop)
2690 				{
2691 					const LV2_Atom *value = &prop->value;
2692 
2693 					if(  (prop->key != moony->canvas_urid.Canvas_graph)
2694 						|| (value->type != forge->Tuple))
2695 					{
2696 						continue;
2697 					}
2698 
2699 					const uint32_t tot_size = lv2_atom_total_size(value);
2700 					void *dst;
2701 					if( (dst = varchunk_write_request(moony->to_idisp, tot_size)) )
2702 					{
2703 						memcpy(dst, value, tot_size);
2704 						varchunk_write_advance(moony->to_idisp, tot_size);
2705 
2706 						lv2_canvas_idisp_queue_draw(&moony->canvas_idisp);
2707 					}
2708 				}
2709 			}
2710 		}
2711 	}
2712 #endif
2713 
2714 	moony->once = false;
2715 }
2716