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