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 µ_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