1 /*
2  * Copyright (c) 2015-2016 Hanspeter Portner (dev@open-music-kontrollers.ch)
3  *
4  * This is free software: you can redistribute it and/or modify
5  * it under the terms of the Artistic License 2.0 as published by
6  * The Perl Foundation.
7  *
8  * This source is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * Artistic License 2.0 for more details.
12  *
13  * You should have received a copy of the Artistic License 2.0
14  * along the source as a COPYING file. If not, obtain it from
15  * http://www.perlfoundation.org/artistic_license_2_0.
16  */
17 
18 #include <inttypes.h>
19 #include <unistd.h>
20 
21 #include <synthpod_app_private.h>
22 
23 #define ANSI_COLOR_BOLD    "\x1b[1m"
24 #define ANSI_COLOR_RESET   "\x1b[0m"
25 
26 //tools.ietf.org/html/rfc4122 version 4
27 static void
urn_uuid_unparse_random(urn_uuid_t urn_uuid)28 urn_uuid_unparse_random(urn_uuid_t urn_uuid)
29 {
30 	uint8_t bytes [0x10];
31 
32 	for(unsigned i=0x0; i<0x10; i++)
33 		bytes[i] = rand() & 0xff;
34 
35 	bytes[6] = (bytes[6] & 0b00001111) | 0b01000000; // set four most significant bits of 7th byte to 0b0100
36 	bytes[8] = (bytes[8] & 0b00111111) | 0b10000000; // set two most significant bits of 9th byte to 0b10
37 
38 	snprintf(urn_uuid, URN_UUID_LENGTH, "urn:uuid:%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
39 		bytes[0x0], bytes[0x1], bytes[0x2], bytes[0x3],
40 		bytes[0x4], bytes[0x5],
41 		bytes[0x6], bytes[0x7],
42 		bytes[0x8], bytes[0x9],
43 		bytes[0xa], bytes[0xb], bytes[0xc], bytes[0xd], bytes[0xe], bytes[0xf]);
44 }
45 
46 #if defined(_WIN32)
47 static inline char *
strsep(char ** sp,char * sep)48 strsep(char **sp, char *sep)
49 {
50 	char *p, *s;
51 	if(sp == NULL || *sp == NULL || **sp == '\0')
52 		return(NULL);
53 	s = *sp;
54 	p = s + strcspn(s, sep);
55 	if(*p != '\0')
56 		*p++ = '\0';
57 	*sp = p;
58 	return(s);
59 }
60 #endif
61 
62 //FIXME is actually __realtime
63 __non_realtime static int
_log_vprintf(LV2_Log_Handle handle,LV2_URID type,const char * fmt,va_list args)64 _log_vprintf(LV2_Log_Handle handle, LV2_URID type, const char *fmt, va_list args)
65 {
66 	mod_t *mod = handle;
67 	sp_app_t *app = mod->app;
68 
69 	char prefix [128]; //TODO how big?
70 	char buf [1024]; //TODO how big?
71 
72 	if(isatty(STDERR_FILENO))
73 		snprintf(prefix, sizeof(prefix), "{"ANSI_COLOR_BOLD"%s"ANSI_COLOR_RESET"} ", mod->urn_uri);
74 	else
75 		snprintf(prefix, sizeof(prefix), "{%s} ", mod->urn_uri);
76 	vsnprintf(buf, sizeof(buf), fmt, args);
77 
78 	const char *sep = "\n";
79 	for(char *bufp = buf, *pch = strsep(&bufp, sep);
80 		pch;
81 		pch = strsep(&bufp, sep) )
82 	{
83 		if(strlen(pch) && app->driver->log)
84 			app->driver->log->printf(app->driver->log->handle, type, "%s%s\n", prefix, pch);
85 	}
86 
87 	return 0;
88 }
89 
90 //FIXME is actually __realtime
91 __non_realtime static int __attribute__((format(printf, 3, 4)))
_log_printf(LV2_Log_Handle handle,LV2_URID type,const char * fmt,...)92 _log_printf(LV2_Log_Handle handle, LV2_URID type, const char *fmt, ...)
93 {
94   va_list args;
95 	int ret;
96 
97   va_start (args, fmt);
98 	ret = _log_vprintf(handle, type, fmt, args);
99   va_end(args);
100 
101 	return ret;
102 }
103 
104 __realtime static LV2_Worker_Status
_schedule_work(LV2_Worker_Schedule_Handle handle,uint32_t size,const void * data)105 _schedule_work(LV2_Worker_Schedule_Handle handle, uint32_t size, const void *data)
106 {
107 	mod_t *mod = handle;
108 	mod_worker_t *mod_worker = &mod->mod_worker;
109 
110 	void *target;
111 	if((target = varchunk_write_request(mod_worker->app_to_worker, size)))
112 	{
113 		memcpy(target, data, size);
114 		varchunk_write_advance(mod_worker->app_to_worker, size);
115 		sem_post(&mod_worker->sem);
116 
117 		return LV2_WORKER_SUCCESS;
118 	}
119 
120 	sp_app_log_trace(mod->app, "%s: failed to request buffer\n", __func__);
121 
122 	return LV2_WORKER_ERR_NO_SPACE;
123 }
124 
125 __non_realtime static char *
_mod_make_path(LV2_State_Make_Path_Handle instance,const char * abstract_path)126 _mod_make_path(LV2_State_Make_Path_Handle instance, const char *abstract_path)
127 {
128 	mod_t *mod = instance;
129 	sp_app_t *app = mod->app;
130 
131 	char *absolute_path = NULL;
132 	asprintf(&absolute_path, "%s/%s/%s", app->bundle_path, mod->urn_uri, abstract_path);
133 
134 	// create leading directory tree, e.g. up to last '/'
135 	if(absolute_path)
136 	{
137 		const char *end = strrchr(absolute_path, '/');
138 		if(end)
139 		{
140 			char *path = strndup(absolute_path, end - absolute_path);
141 			if(path)
142 			{
143 				mkpath(path);
144 
145 				free(path);
146 			}
147 		}
148 	}
149 
150 	return absolute_path;
151 }
152 
153 static inline int
_sp_app_mod_alloc_pool(pool_t * pool)154 _sp_app_mod_alloc_pool(pool_t *pool)
155 {
156 #if defined(_WIN32)
157 	pool->buf = _aligned_malloc(pool->size, 8);
158 #else
159 	posix_memalign(&pool->buf, 8, pool->size);
160 #endif
161 	if(pool->buf)
162 	{
163 		memset(pool->buf, 0x0, pool->size);
164 
165 		return 0;
166 	}
167 
168 	return -1;
169 }
170 
171 static inline void
_sp_app_mod_free_pool(pool_t * pool)172 _sp_app_mod_free_pool(pool_t *pool)
173 {
174 	if(pool->buf)
175 	{
176 		free(pool->buf);
177 		pool->buf = NULL;
178 	}
179 }
180 
181 static inline void
_sp_app_mod_slice_pool(mod_t * mod,port_type_t type)182 _sp_app_mod_slice_pool(mod_t *mod, port_type_t type)
183 {
184 	// set ptr to pool buffer
185 	void *ptr = mod->pools[type].buf;
186 
187 	for(port_direction_t dir=0; dir<PORT_DIRECTION_NUM; dir++)
188 	{
189 		for(unsigned i=0; i<mod->num_ports; i++)
190 		{
191 			port_t *tar = &mod->ports[i];
192 
193 			if( (tar->type != type) || (tar->direction != dir) )
194 				continue; //skip
195 
196 			// define buffer slice
197 			tar->base = ptr;
198 
199 			// initialize control buffers to default value
200 			if(tar->type == PORT_TYPE_CONTROL)
201 			{
202 				control_port_t *control = &tar->control;
203 
204 				float *buf_ptr = PORT_BASE_ALIGNED(tar);
205 				*buf_ptr = control->dflt;
206 				control->stash = control->dflt;
207 				control->last = control->dflt;
208 				control->auto_dirty = true;
209 			}
210 
211 			ptr += lv2_atom_pad_size(tar->size);
212 		}
213 	}
214 }
215 
216 void
_sp_app_mod_reinitialize(mod_t * mod)217 _sp_app_mod_reinitialize(mod_t *mod)
218 {
219 	sp_app_t *app = mod->app;
220 
221 	// reinitialize all modules,
222 	lilv_instance_deactivate(mod->inst);
223 	lilv_instance_free(mod->inst);
224 	mod->inst = NULL;
225 	mod->handle = NULL;
226 
227 	// mod->features should be up-to-date
228 	mod->inst = lilv_plugin_instantiate(mod->plug, app->driver->sample_rate, mod->features);
229 	mod->handle = lilv_instance_get_handle(mod->inst);
230 
231 	//TODO should we re-get extension_data?
232 
233 	// resize sample based buffers only (e.g. AUDIO and CV)
234 	_sp_app_mod_free_pool(&mod->pools[PORT_TYPE_AUDIO]);
235 	_sp_app_mod_free_pool(&mod->pools[PORT_TYPE_CV]);
236 
237 	mod->pools[PORT_TYPE_AUDIO].size = 0;
238 	mod->pools[PORT_TYPE_CV].size = 0;
239 
240 	for(unsigned i=0; i<mod->num_ports; i++)
241 	{
242 		port_t *tar = &mod->ports[i];
243 
244 		if(  (tar->type == PORT_TYPE_AUDIO)
245 			|| (tar->type == PORT_TYPE_CV) )
246 		{
247 			tar->size = app->driver->max_block_size * sizeof(float);
248 			mod->pools[tar->type].size += lv2_atom_pad_size(tar->size);
249 		}
250 	}
251 
252 	_sp_app_mod_alloc_pool(&mod->pools[PORT_TYPE_AUDIO]);
253 	_sp_app_mod_alloc_pool(&mod->pools[PORT_TYPE_CV]);
254 
255 	_sp_app_mod_slice_pool(mod, PORT_TYPE_AUDIO);
256 	_sp_app_mod_slice_pool(mod, PORT_TYPE_CV);
257 }
258 
259 static inline int
_sp_app_mod_features_populate(sp_app_t * app,mod_t * mod)260 _sp_app_mod_features_populate(sp_app_t *app, mod_t *mod)
261 {
262 	// populate feature list
263 	int nfeatures = 0;
264 	mod->feature_list[nfeatures].URI = LV2_URID__map;
265 	mod->feature_list[nfeatures++].data = app->driver->map;
266 
267 	mod->feature_list[nfeatures].URI = LV2_URID__unmap;
268 	mod->feature_list[nfeatures++].data = app->driver->unmap;
269 
270 	mod->feature_list[nfeatures].URI = XPRESS__voiceMap;
271 	mod->feature_list[nfeatures++].data = app->driver->xmap;
272 
273 	mod->feature_list[nfeatures].URI = LV2_WORKER__schedule;
274 	mod->feature_list[nfeatures++].data = &mod->worker.schedule;
275 
276 	mod->feature_list[nfeatures].URI = LV2_LOG__log;
277 	mod->feature_list[nfeatures++].data = &mod->log;
278 
279 	mod->feature_list[nfeatures].URI = LV2_STATE__makePath;
280 	mod->feature_list[nfeatures++].data = &mod->make_path;
281 
282 	mod->feature_list[nfeatures].URI = LV2_BUF_SIZE__boundedBlockLength;
283 	mod->feature_list[nfeatures++].data = NULL;
284 
285 	mod->feature_list[nfeatures].URI = LV2_OPTIONS__options;
286 	mod->feature_list[nfeatures++].data = mod->opts.options;
287 
288 	/* TODO support
289 	mod->feature_list[nfeatures].URI = LV2_PORT_PROPS__supportsStrictBounds;
290 	mod->feature_list[nfeatures++].data = NULL;
291 	*/
292 
293 	/* TODO support
294 	mod->feature_list[nfeatures].URI = LV2_RESIZE_PORT__resize;
295 	mod->feature_list[nfeatures++].data = NULL;
296 	*/
297 
298 	mod->feature_list[nfeatures].URI = LV2_STATE__loadDefaultState;
299 	mod->feature_list[nfeatures++].data = NULL;
300 
301 	if(app->driver->system_port_add && app->driver->system_port_del)
302 	{
303 		mod->feature_list[nfeatures].URI = SYNTHPOD_PREFIX"systemPorts";
304 		mod->feature_list[nfeatures++].data = NULL;
305 	}
306 
307 	if(app->driver->osc_sched)
308 	{
309 		mod->feature_list[nfeatures].URI = LV2_OSC__schedule;
310 		mod->feature_list[nfeatures++].data = app->driver->osc_sched;
311 	}
312 
313 	if(app->driver->features & SP_APP_FEATURE_FIXED_BLOCK_LENGTH)
314 	{
315 		mod->feature_list[nfeatures].URI = LV2_BUF_SIZE__fixedBlockLength;
316 		mod->feature_list[nfeatures++].data = NULL;
317 	}
318 
319 	if(app->driver->features & SP_APP_FEATURE_POWER_OF_2_BLOCK_LENGTH)
320 	{
321 		mod->feature_list[nfeatures].URI = LV2_BUF_SIZE__powerOf2BlockLength;
322 		mod->feature_list[nfeatures++].data = NULL;
323 	}
324 
325 	mod->feature_list[nfeatures].URI = LV2_URI_MAP_URI;
326 	mod->feature_list[nfeatures++].data = &app->uri_to_id;
327 
328 	mod->feature_list[nfeatures].URI = LV2_CORE__inPlaceBroken;
329 	mod->feature_list[nfeatures++].data = NULL;
330 
331 	mod->feature_list[nfeatures].URI = LV2_INLINEDISPLAY__queue_draw;
332 	mod->feature_list[nfeatures++].data = &mod->idisp.queue_draw;
333 
334 	mod->feature_list[nfeatures].URI = LV2_STATE__threadSafeRestore;
335 	mod->feature_list[nfeatures++].data = NULL;
336 
337 	assert(nfeatures <= NUM_FEATURES);
338 
339 	for(int i=0; i<nfeatures; i++)
340 		mod->features[i] = &mod->feature_list[i];
341 	mod->features[nfeatures] = NULL; // sentinel
342 
343 	return nfeatures;
344 }
345 
346 static const LilvPlugin *
_sp_app_mod_is_supported(sp_app_t * app,const char * uri)347 _sp_app_mod_is_supported(sp_app_t *app, const char *uri)
348 {
349 	LilvNode *uri_node = lilv_new_uri(app->world, uri);
350 	if(!uri_node)
351 	{
352 		sp_app_log_trace(app, "%s: failed to create URI\n", __func__);
353 		return NULL;
354 	}
355 
356 	const LilvPlugin *plug = lilv_plugins_get_by_uri(app->plugs, uri_node);
357 	lilv_node_free(uri_node);
358 
359 	if(!plug)
360 	{
361 		sp_app_log_trace(app, "%s: failed to get plugin\n", __func__);
362 		return NULL;
363 	}
364 
365 	const LilvNode *library_uri= lilv_plugin_get_library_uri(plug);
366 	if(!library_uri)
367 	{
368 		sp_app_log_trace(app, "%s: failed to get library URI\n", __func__);
369 		return NULL;
370 	}
371 
372 	if(!app->driver->bad_plugins)
373 	{
374 		// check whether DSP and UI code is mixed into same binary
375 		bool mixed_binary = false;
376 		LilvUIs *all_uis = lilv_plugin_get_uis(plug);
377 		if(all_uis)
378 		{
379 			LILV_FOREACH(uis, ptr, all_uis)
380 			{
381 				const LilvUI *ui = lilv_uis_get(all_uis, ptr);
382 				if(!ui)
383 					continue;
384 
385 				const LilvNode *ui_uri_node = lilv_ui_get_uri(ui);
386 				if(!ui_uri_node)
387 					continue;
388 
389 				// nedded if ui ttl referenced via rdfs#seeAlso
390 				lilv_world_load_resource(app->world, ui_uri_node);
391 
392 				const LilvNode *ui_library_uri= lilv_ui_get_binary_uri(ui);
393 				if(ui_library_uri && lilv_node_equals(library_uri, ui_library_uri))
394 					mixed_binary = true; // this is bad, we don't support that
395 
396 				lilv_world_unload_resource(app->world, ui_uri_node);
397 			}
398 
399 			lilv_uis_free(all_uis);
400 		}
401 
402 		if(mixed_binary)
403 		{
404 			sp_app_log_error(app, "%s: <%s> NOT supported: mixes DSP and UI code in same binary.\n", __func__, uri);
405 			return NULL;
406 		}
407 	}
408 
409 	// populate feature list in dummy mod structure
410 	mod_t mod;
411 	const int nfeatures = _sp_app_mod_features_populate(app, &mod);
412 
413 	// check for missing features
414 	int missing_required_feature = 0;
415 	LilvNodes *required_features = lilv_plugin_get_required_features(plug);
416 	if(required_features)
417 	{
418 		LILV_FOREACH(nodes, i, required_features)
419 		{
420 			const LilvNode* required_feature = lilv_nodes_get(required_features, i);
421 			const char *required_feature_uri = lilv_node_as_uri(required_feature);
422 			missing_required_feature = 1;
423 
424 			for(int f=0; f<nfeatures; f++)
425 			{
426 				if(!strcmp(mod.feature_list[f].URI, required_feature_uri))
427 				{
428 					missing_required_feature = 0;
429 					break;
430 				}
431 			}
432 
433 			if(missing_required_feature)
434 			{
435 				sp_app_log_error(app, "%s: <%s> NOT supported: requires feature <%s>\n",
436 					__func__, uri, required_feature_uri);
437 				break;
438 			}
439 		}
440 		lilv_nodes_free(required_features);
441 	}
442 
443 	if(missing_required_feature)
444 		return NULL;
445 
446 	return plug;
447 }
448 
449 __non_realtime static LV2_Worker_Status
_sp_worker_respond_async(LV2_Worker_Respond_Handle handle,uint32_t size,const void * data)450 _sp_worker_respond_async(LV2_Worker_Respond_Handle handle, uint32_t size, const void *data)
451 {
452 	mod_t *mod = handle;
453 	mod_worker_t *mod_worker = &mod->mod_worker;
454 
455 	void *payload;
456 	if((payload = varchunk_write_request(mod_worker->app_from_worker, size)))
457 	{
458 		memcpy(payload, data, size);
459 		varchunk_write_advance(mod_worker->app_from_worker, size);
460 		return LV2_WORKER_SUCCESS;
461 	}
462 
463 	sp_app_log_error(mod->app, "%s: failed to request buffer\n", __func__);
464 
465 	return LV2_WORKER_ERR_NO_SPACE;
466 }
467 
468 __non_realtime static LV2_Worker_Status
_sp_worker_respond_sync(LV2_Worker_Respond_Handle handle,uint32_t size,const void * data)469 _sp_worker_respond_sync(LV2_Worker_Respond_Handle handle, uint32_t size, const void *data)
470 {
471 	mod_t *mod = handle;
472 
473 	if(mod->worker.iface && mod->worker.iface->work_response)
474 		return mod->worker.iface->work_response(mod->handle, size, data);
475 
476 	sp_app_log_error(mod->app, "%s: failed to call work:response\n", __func__);
477 
478 	return LV2_WORKER_ERR_NO_SPACE;
479 }
480 
481 __non_realtime LV2_Worker_Status
_sp_app_mod_worker_work_sync(mod_t * mod,size_t size,const void * payload)482 _sp_app_mod_worker_work_sync(mod_t *mod, size_t size, const void *payload)
483 {
484 	if(mod->worker.iface && mod->worker.iface->work)
485 	{
486 		return mod->worker.iface->work(mod->handle, _sp_worker_respond_sync, mod,
487 			size, payload);
488 	}
489 
490 	sp_app_log_error(mod->app, "%s: failed to call work:work\n", __func__);
491 
492 	return LV2_WORKER_ERR_NO_SPACE;
493 }
494 
495 __non_realtime static void
_sp_app_mod_worker_work_async(mod_t * mod,size_t size,const void * payload)496 _sp_app_mod_worker_work_async(mod_t *mod, size_t size, const void *payload)
497 {
498 	//printf("_mod_worker_work: %s, %zu\n", mod->urn_uri, size);
499 
500 	if(mod->worker.iface && mod->worker.iface->work)
501 	{
502 		mod->worker.iface->work(mod->handle, _sp_worker_respond_async, mod,
503 			size, payload);
504 		//TODO check return status
505 	}
506 	else
507 	{
508 		sp_app_log_error(mod->app, "%s: failed to call work:work\n", __func__);
509 	}
510 }
511 
512 __non_realtime static void *
_mod_worker_thread(void * data)513 _mod_worker_thread(void *data)
514 {
515 	mod_t *mod = data;
516 	mod_worker_t *mod_worker = &mod->mod_worker;
517 
518 	// will inherit thread priority from main worker thread
519 
520 	while(!atomic_load_explicit(&mod_worker->kill, memory_order_acquire))
521 	{
522 		sem_wait(&mod_worker->sem);
523 
524 		const void *payload;
525 		size_t size;
526 		while((payload = varchunk_read_request(mod_worker->app_to_worker, &size)))
527 		{
528 			_sp_app_mod_worker_work_async(mod, size, payload);
529 
530 			varchunk_read_advance(mod_worker->app_to_worker);
531 		}
532 
533 		while((payload = varchunk_read_request(mod_worker->state_to_worker, &size)))
534 		{
535 			_sp_app_mod_worker_work_async(mod, size, payload);
536 
537 			varchunk_read_advance(mod_worker->state_to_worker);
538 		}
539 
540 		if(mod->idisp.iface && mod->idisp.iface->render)
541 		{
542 			if(atomic_exchange(&mod->idisp.draw_queued, false))
543 			{
544 				const uint32_t w = 256; //FIXME
545 				const uint32_t h = 256; //FIXME
546 
547 				// lock surface
548 				while(atomic_flag_test_and_set(&mod->idisp.lock))
549 				{
550 					// spin
551 				}
552 
553 				mod->idisp.surf = mod->idisp.iface->render(mod->handle, w, h);
554 
555 				// unlock surface
556 				atomic_flag_clear(&mod->idisp.lock);
557 			}
558 		}
559 	}
560 
561 	return NULL;
562 }
563 
564 __realtime void
_sp_app_mod_queue_draw(mod_t * mod)565 _sp_app_mod_queue_draw(mod_t *mod)
566 {
567 	mod_worker_t *mod_worker = &mod->mod_worker;
568 
569 	if(mod->idisp.iface && mod->idisp.subscribed)
570 	{
571 		if(mod->idisp.counter >= mod->idisp.threshold)
572 		{
573 			mod->idisp.counter = 0;
574 
575 			atomic_store(&mod->idisp.draw_queued, true);
576 			sem_post(&mod_worker->sem);
577 		}
578 	}
579 }
580 
581 __realtime static void
_mod_queue_draw(void * data)582 _mod_queue_draw(void *data)
583 {
584 	mod_t *mod = data;
585 
586 	_sp_app_mod_queue_draw(mod);
587 }
588 
589 mod_t *
_sp_app_mod_add(sp_app_t * app,const char * uri,LV2_URID urn)590 _sp_app_mod_add(sp_app_t *app, const char *uri, LV2_URID urn)
591 {
592 	const LilvPlugin *plug;
593 
594 	if(!(plug = _sp_app_mod_is_supported(app, uri)))
595 	{
596 		sp_app_log_error(app, "%s: plugin is not supported\n", __func__);
597 		return NULL;
598 	}
599 
600 	mod_t *mod = calloc(1, sizeof(mod_t));
601 	if(!mod)
602 	{
603 		sp_app_log_error(app, "%s: allocation failed\n", __func__);
604 		return NULL;
605 	}
606 
607 	mod->needs_bypassing = false; // plugins with control ports only need no bypassing upon preset load
608 	mod->bypassed = false;
609 	atomic_init(&mod->dsp_client.ref_count, 0);
610 
611 	// populate worker schedule
612 	mod->worker.schedule.handle = mod;
613 	mod->worker.schedule.schedule_work = _schedule_work;
614 
615 	// populate log
616 	mod->log.handle = mod;
617 	mod->log.printf = _log_printf;
618 	mod->log.vprintf = _log_vprintf;
619 
620 	mod->make_path.handle = mod;
621 	mod->make_path.path = _mod_make_path;
622 
623 	mod->idisp.queue_draw.handle = mod;
624 	mod->idisp.queue_draw.queue_draw = _mod_queue_draw;
625 	atomic_init(&mod->idisp.draw_queued, false);
626 	mod->idisp.lock = (atomic_flag)ATOMIC_FLAG_INIT;
627 	mod->idisp.threshold = app->driver->sample_rate / app->driver->update_rate;
628 
629 	// populate options
630 	mod->opts.options[0].context = LV2_OPTIONS_INSTANCE;
631 	mod->opts.options[0].subject = 0;
632 	mod->opts.options[0].key = app->regs.bufsz.max_block_length.urid;
633 	mod->opts.options[0].size = sizeof(int32_t);
634 	mod->opts.options[0].type = app->forge.Int;
635 	mod->opts.options[0].value = &app->driver->max_block_size;
636 
637 	mod->opts.options[1].context = LV2_OPTIONS_INSTANCE;
638 	mod->opts.options[1].subject = 0;
639 	mod->opts.options[1].key = app->regs.bufsz.min_block_length.urid;
640 	mod->opts.options[1].size = sizeof(int32_t);
641 	mod->opts.options[1].type = app->forge.Int;
642 	mod->opts.options[1].value = &app->driver->min_block_size;
643 
644 	mod->opts.options[2].context = LV2_OPTIONS_INSTANCE;
645 	mod->opts.options[2].subject = 0;
646 	mod->opts.options[2].key = app->regs.bufsz.sequence_size.urid;
647 	mod->opts.options[2].size = sizeof(int32_t);
648 	mod->opts.options[2].type = app->forge.Int;
649 	mod->opts.options[2].value = &app->driver->seq_size;
650 
651 	mod->opts.options[3].context = LV2_OPTIONS_INSTANCE;
652 	mod->opts.options[3].subject = 0;
653 	mod->opts.options[3].key = app->regs.bufsz.nominal_block_length.urid;
654 	mod->opts.options[3].size = sizeof(int32_t);
655 	mod->opts.options[3].type = app->forge.Int;
656 	mod->opts.options[3].value = &app->driver->max_block_size; // set to max by default
657 
658 	mod->opts.options[4].context = LV2_OPTIONS_INSTANCE;
659 	mod->opts.options[4].subject = 0;
660 	mod->opts.options[4].key = app->regs.param.sample_rate.urid;
661 	mod->opts.options[4].size = sizeof(float);
662 	mod->opts.options[4].type = app->forge.Float;
663 	mod->opts.options[4].value = &app->driver->sample_rate;
664 
665 	mod->opts.options[5].context = LV2_OPTIONS_INSTANCE;
666 	mod->opts.options[5].subject = 0;
667 	mod->opts.options[5].key = app->regs.ui.update_rate.urid;
668 	mod->opts.options[5].size = sizeof(float);
669 	mod->opts.options[5].type = app->forge.Float;
670 	mod->opts.options[5].value = &app->driver->update_rate;
671 
672 	mod->opts.options[6].key = 0; // sentinel
673 	mod->opts.options[6].value = NULL; // sentinel
674 
675 	_sp_app_mod_features_populate(app, mod);
676 
677 	mod->app = app;
678 	if(urn == 0)
679 	{
680 		urn_uuid_unparse_random(mod->urn_uri);
681 		urn = app->driver->map->map(app->driver->map->handle, mod->urn_uri);
682 	}
683 	else
684 	{
685 		const char *urn_uri = app->driver->unmap->unmap(app->driver->unmap->handle, urn);
686 		strcpy(mod->urn_uri, urn_uri);
687 	}
688 	//printf("urn: %s\n", mod->urn_uri);
689 	mod->urn = urn;
690 	mod->plug = plug;
691 	mod->plug_urid = app->driver->map->map(app->driver->map->handle, uri);
692 	mod->num_ports = lilv_plugin_get_num_ports(plug) + 2; // + automation ports
693 	mod->inst = lilv_plugin_instantiate(plug, app->driver->sample_rate, mod->features);
694 	if(!mod->inst)
695 	{
696 		sp_app_log_error(app, "%s: instantiation failed\n", __func__);
697 		free(mod);
698 		return NULL;
699 	}
700 	mod->uri_str = strdup(uri); //TODO check
701 	mod->handle = lilv_instance_get_handle(mod->inst);
702 	mod->worker.iface = lilv_instance_get_extension_data(mod->inst,
703 		LV2_WORKER__interface);
704 	mod->opts.iface = lilv_instance_get_extension_data(mod->inst,
705 		LV2_OPTIONS__interface);
706 	const bool has_ro_canvas_graph = lilv_world_ask(app->world,
707 		lilv_plugin_get_uri(mod->plug), app->regs.patch.readable.node,
708 		app->regs.canvas.graph.node);
709 	const bool has_rw_canvas_graph = lilv_world_ask(app->world,
710 		lilv_plugin_get_uri(mod->plug), app->regs.patch.writable.node,
711 		app->regs.canvas.graph.node);
712 	if(has_ro_canvas_graph || has_rw_canvas_graph)
713 	{
714 		//sp_app_log_note(app, "%s: detected canvas:graph parameter\n", __func__);
715 	}
716 	else
717 	{
718 		mod->idisp.iface = lilv_instance_get_extension_data(mod->inst,
719 			LV2_INLINEDISPLAY__interface);
720 	}
721 	mod->state.iface = lilv_instance_get_extension_data(mod->inst,
722 		LV2_STATE__interface);
723 	mod->system_ports = lilv_plugin_has_feature(plug, app->regs.synthpod.system_ports.node);
724 	const bool load_default_state = lilv_plugin_has_feature(plug, app->regs.state.load_default_state.node);
725 	const bool thread_safe_restore = lilv_plugin_has_feature(plug, app->regs.state.thread_safe_restore.node);
726 
727 	if(mod->state.iface) // plugins with state:interface need bypassing upon preset load
728 		mod->needs_bypassing = true;
729 
730 	if(thread_safe_restore) // plugins with state:threadSafeRestore need no bypassing upon preset load
731 		mod->needs_bypassing = false;
732 
733 	// clear pool sizes
734 	for(port_type_t pool=0; pool<PORT_TYPE_NUM; pool++)
735 		mod->pools[pool].size = 0;
736 
737 	mod->ports = calloc(mod->num_ports, sizeof(port_t));
738 	if(!mod->ports)
739 	{
740 		sp_app_log_error(app, "%s: pool allocation failed\n", __func__);
741 		free(mod);
742 		return NULL; // failed to alloc ports
743 	}
744 
745 	for(unsigned i=0; i<mod->num_ports - 2; i++) // - automation ports
746 	{
747 		port_t *tar = &mod->ports[i];
748 		const LilvPort *port = lilv_plugin_get_port_by_index(plug, i);
749 
750 		tar->size = 0;
751 		tar->mod = mod;
752 		tar->index = i;
753 		tar->symbol = lilv_node_as_string(lilv_port_get_symbol(plug, port));
754 		tar->direction = lilv_port_is_a(plug, port, app->regs.port.input.node)
755 			? PORT_DIRECTION_INPUT
756 			: PORT_DIRECTION_OUTPUT;
757 
758 		// register system ports
759 		if(mod->system_ports)
760 		{
761 			if(lilv_port_is_a(plug, port, app->regs.synthpod.control_port.node))
762 				tar->sys.type = SYSTEM_PORT_CONTROL;
763 			else if(lilv_port_is_a(plug, port, app->regs.synthpod.audio_port.node))
764 				tar->sys.type = SYSTEM_PORT_AUDIO;
765 			else if(lilv_port_is_a(plug, port, app->regs.synthpod.cv_port.node))
766 				tar->sys.type = SYSTEM_PORT_CV;
767 			else if(lilv_port_is_a(plug, port, app->regs.synthpod.midi_port.node))
768 				tar->sys.type = SYSTEM_PORT_MIDI;
769 			else if(lilv_port_is_a(plug, port, app->regs.synthpod.osc_port.node))
770 				tar->sys.type = SYSTEM_PORT_OSC;
771 			else if(lilv_port_is_a(plug, port, app->regs.synthpod.com_port.node))
772 				tar->sys.type = SYSTEM_PORT_COM;
773 			else
774 				tar->sys.type = SYSTEM_PORT_NONE;
775 
776 			if(app->driver->system_port_add)
777 			{
778 				//FIXME check lilv returns
779 				char *short_name = NULL;
780 				char *pretty_name = NULL;
781 				const char *designation = NULL;
782 				const LilvNode *port_symbol_node = lilv_port_get_symbol(plug, port);
783 				LilvNode *port_name_node = lilv_port_get_name(plug, port);
784 				LilvNode *port_designation= lilv_port_get(plug, port, app->regs.core.designation.node);
785 
786 				asprintf(&short_name, "#%"PRIu32"_%s",
787 					mod->urn, lilv_node_as_string(port_symbol_node));
788 				asprintf(&pretty_name, "#%"PRIu32" - %s",
789 					mod->urn, lilv_node_as_string(port_name_node));
790 				designation = port_designation ? lilv_node_as_string(port_designation) : NULL;
791 				const uint32_t order = (mod->urn << 16) | tar->index;
792 
793 				tar->sys.data = app->driver->system_port_add(app->data, tar->sys.type,
794 					short_name, pretty_name, designation,
795 					tar->direction == PORT_DIRECTION_OUTPUT, order);
796 
797 				lilv_node_free(port_designation);
798 				lilv_node_free(port_name_node);
799 				free(short_name);
800 				free(pretty_name);
801 			}
802 		}
803 		else
804 		{
805 			tar->sys.type = SYSTEM_PORT_NONE;
806 			tar->sys.data = NULL;
807 		}
808 
809 		if(lilv_port_is_a(plug, port, app->regs.port.audio.node))
810 		{
811 			tar->size = app->driver->max_block_size * sizeof(float);
812 			tar->type =  PORT_TYPE_AUDIO;
813 			tar->protocol = app->regs.port.peak_protocol.urid;
814 			tar->driver = &audio_port_driver;
815 		}
816 		else if(lilv_port_is_a(plug, port, app->regs.port.cv.node))
817 		{
818 			tar->size = app->driver->max_block_size * sizeof(float);
819 			tar->type = PORT_TYPE_CV;
820 			tar->protocol = app->regs.port.peak_protocol.urid;
821 			tar->driver = &cv_port_driver;
822 		}
823 		else if(lilv_port_is_a(plug, port, app->regs.port.control.node))
824 		{
825 			tar->size = sizeof(float);
826 			tar->type = PORT_TYPE_CONTROL;
827 			tar->protocol = app->regs.port.float_protocol.urid;
828 			tar->driver = &control_port_driver;
829 
830 			control_port_t *control = &tar->control;
831 			control->is_integer = lilv_port_has_property(plug, port, app->regs.port.integer.node);
832 			control->is_toggled = lilv_port_has_property(plug, port, app->regs.port.toggled.node);
833 			control->lock = (atomic_flag)ATOMIC_FLAG_INIT;
834 
835 			LilvNode *dflt_node;
836 			LilvNode *min_node;
837 			LilvNode *max_node;
838 			lilv_port_get_range(plug, port, &dflt_node, &min_node, &max_node);
839 			control->dflt = dflt_node ? lilv_node_as_float(dflt_node) : 0.f; //FIXME int, bool
840 			control->min = min_node ? lilv_node_as_float(min_node) : 0.f; //FIXME int, bool
841 			control->max = max_node ? lilv_node_as_float(max_node) : 1.f; //FIXME int, bool
842 			control->range = control->max - control->min;
843 			control->range_1 = 1.f / control->range;
844 			lilv_node_free(dflt_node);
845 			lilv_node_free(min_node);
846 			lilv_node_free(max_node);
847 		}
848 		else if(lilv_port_is_a(plug, port, app->regs.port.atom.node))
849 		{
850 			tar->size = app->driver->seq_size;
851 			tar->type = PORT_TYPE_ATOM;
852 			tar->protocol = app->regs.port.event_transfer.urid; //FIXME handle atom_transfer
853 			tar->driver = &seq_port_driver; // FIXME handle atom_port_driver
854 
855 			tar->atom.buffer_type = PORT_BUFFER_TYPE_SEQUENCE; //FIXME properly discover this
856 
857 			// does this port support patch:Message?
858 			tar->atom.patchable = lilv_port_supports_event(plug, port, app->regs.patch.message.node);
859 
860 			// check whether this is a control port
861 			const LilvPort *control_port = lilv_plugin_get_port_by_designation(plug,
862 				tar->direction == PORT_DIRECTION_INPUT
863 					? app->regs.port.input.node
864 					: app->regs.port.output.node
865 					, app->regs.core.control.node);
866 			(void)control_port; //TODO use this?
867 		}
868 		else
869 		{
870 			sp_app_log_warning(app, "%s: unknown port type\n", __func__); //FIXME plugin should fail to initialize here
871 
872 			free(mod->uri_str);
873 			free(mod->ports);
874 			free(mod);
875 
876 			return NULL;
877 		}
878 
879 		// get minimum port size if specified
880 		LilvNode *minsize = lilv_port_get(plug, port, app->regs.port.minimum_size.node);
881 		if(minsize)
882 		{
883 			tar->size = lilv_node_as_int(minsize);
884 			lilv_node_free(minsize);
885 		}
886 
887 		// increase pool sizes
888 		mod->pools[tar->type].size += lv2_atom_pad_size(tar->size);
889 	}
890 
891 	// automation input port //FIXME check
892 	{
893 		const unsigned i = mod->num_ports - 2;
894 		port_t *tar = &mod->ports[i];
895 
896 		tar->mod = mod;
897 		tar->index = i;
898 		tar->symbol = "__automation__in__";
899 		tar->direction = PORT_DIRECTION_INPUT;
900 
901 		tar->size = app->driver->seq_size;
902 		tar->type = PORT_TYPE_ATOM;
903 		tar->protocol = app->regs.port.event_transfer.urid;
904 		tar->driver = &seq_port_driver;
905 
906 		tar->atom.buffer_type = PORT_BUFFER_TYPE_SEQUENCE;
907 
908 		tar->sys.type = SYSTEM_PORT_NONE;
909 		tar->sys.data = NULL;
910 
911 		// increase pool sizes
912 		mod->pools[tar->type].size += lv2_atom_pad_size(tar->size);
913 	}
914 
915 	// automation output port //FIXME check
916 	{
917 		const unsigned i = mod->num_ports - 1;
918 		port_t *tar = &mod->ports[i];
919 
920 		tar->mod = mod;
921 		tar->index = i;
922 		tar->symbol = "__automation__out__";
923 		tar->direction = PORT_DIRECTION_OUTPUT;
924 
925 		tar->size = app->driver->seq_size;
926 		tar->type = PORT_TYPE_ATOM;
927 		tar->protocol = app->regs.port.event_transfer.urid;
928 		tar->driver = &seq_port_driver;
929 
930 		tar->atom.buffer_type = PORT_BUFFER_TYPE_SEQUENCE;
931 
932 		tar->sys.type = SYSTEM_PORT_NONE;
933 		tar->sys.data = NULL;
934 
935 		// increase pool sizes
936 		mod->pools[tar->type].size += lv2_atom_pad_size(tar->size);
937 	}
938 
939 	// allocate 8-byte aligned buffer per plugin and port type pool
940 	int alloc_failed = 0;
941 	for(port_type_t pool=0; pool<PORT_TYPE_NUM; pool++)
942 	{
943 		if(_sp_app_mod_alloc_pool(&mod->pools[pool]))
944 		{
945 			alloc_failed = 1;
946 			break;
947 		}
948 	}
949 
950 	if(alloc_failed)
951 	{
952 		sp_app_log_error(app, "%s: pool tiling failed\n", __func__);
953 
954 		for(port_type_t pool=0; pool<PORT_TYPE_NUM; pool++)
955 			_sp_app_mod_free_pool(&mod->pools[pool]);
956 
957 		free(mod->uri_str);
958 		free(mod->ports);
959 		free(mod);
960 
961 		return NULL;
962 	}
963 
964 	// slice plugin buffer into per-port-type-and-direction regions for
965 	// efficient dereference in plugin instance
966 	for(port_type_t pool=0; pool<PORT_TYPE_NUM; pool++)
967 		_sp_app_mod_slice_pool(mod, pool);
968 
969 	for(unsigned i=0; i<mod->num_ports - 2; i++)
970 	{
971 		port_t *tar = &mod->ports[i];
972 
973 		// set port buffer
974 		lilv_instance_connect_port(mod->inst, i, tar->base);
975 	}
976 
977 	// load presets
978 	mod->presets = lilv_plugin_get_related(plug, app->regs.pset.preset.node);
979 
980 	// spawn worker thread
981 	if(mod->worker.iface || mod->idisp.iface)
982 	{
983 		mod_worker_t *mod_worker = &mod->mod_worker;
984 
985 		sem_init(&mod_worker->sem, 0, 0);
986 		atomic_init(&mod_worker->kill, false);
987 		mod_worker->app_to_worker = varchunk_new(2048, true); //FIXME how big
988 		mod_worker->state_to_worker = varchunk_new(2048, true); //FIXME how big
989 		mod_worker->app_from_worker = varchunk_new(2048, true); //FIXME how big
990 		pthread_attr_t attr;
991 		pthread_attr_init(&attr);
992 		pthread_create(&mod_worker->thread, &attr, _mod_worker_thread, mod);
993 	}
994 
995 	// activate
996 	lilv_instance_activate(mod->inst);
997 
998 	// load default state
999 	if(load_default_state && _sp_app_state_preset_load(app, mod, uri, false))
1000 		sp_app_log_error(app, "%s: default state loading failed\n", __func__);
1001 
1002 	// initialize profiling reference time
1003 	mod->prof.sum = 0;
1004 
1005 	return mod;
1006 }
1007 
1008 int
_sp_app_mod_del(sp_app_t * app,mod_t * mod)1009 _sp_app_mod_del(sp_app_t *app, mod_t *mod)
1010 {
1011 	// deinit worker thread
1012 	if(mod->worker.iface || mod->idisp.iface)
1013 	{
1014 		mod_worker_t *mod_worker = &mod->mod_worker;
1015 
1016 		atomic_store_explicit(&mod_worker->kill, true, memory_order_release);
1017 		sem_post(&mod_worker->sem);
1018 		void *ret;
1019 		pthread_join(mod_worker->thread, &ret);
1020 		varchunk_free(mod_worker->app_to_worker);
1021 		varchunk_free(mod_worker->state_to_worker);
1022 		varchunk_free(mod_worker->app_from_worker);
1023 		sem_destroy(&mod_worker->sem);
1024 	}
1025 
1026 	// deinit instance
1027 	lilv_nodes_free(mod->presets);
1028 	lilv_instance_deactivate(mod->inst);
1029 	lilv_instance_free(mod->inst);
1030 
1031 	// free memory
1032 	for(port_type_t pool=0; pool<PORT_TYPE_NUM; pool++)
1033 		_sp_app_mod_free_pool(&mod->pools[pool]);
1034 
1035 	// unregister system ports
1036 	for(unsigned i=0; i<mod->num_ports; i++)
1037 	{
1038 		port_t *port = &mod->ports[i];
1039 
1040 		if(port->sys.data && app->driver->system_port_del)
1041 			app->driver->system_port_del(app->data, port->sys.data);
1042 	}
1043 
1044 	// free ports
1045 	if(mod->ports)
1046 	{
1047 		free(mod->ports);
1048 	}
1049 
1050 	if(mod->uri_str)
1051 		free(mod->uri_str);
1052 
1053 	free(mod);
1054 
1055 	return 0; //success
1056 }
1057 
1058 mod_t *
_sp_app_mod_get_by_uid(sp_app_t * app,int32_t uid)1059 _sp_app_mod_get_by_uid(sp_app_t *app, int32_t uid)
1060 {
1061 	for(unsigned m = 0; m < app->num_mods; m++)
1062 	{
1063 		mod_t *mod = app->mods[m];
1064 
1065 		if(mod->uid == uid)
1066 			return mod;
1067 	}
1068 
1069 	return NULL;
1070 }
1071 
1072 void
_sp_app_mod_eject(sp_app_t * app,mod_t * mod)1073 _sp_app_mod_eject(sp_app_t *app, mod_t *mod)
1074 {
1075 	// eject module from graph
1076 	app->num_mods -= 1;
1077 	// remove mod from ->mods
1078 	for(unsigned m=0, offset=0; m<app->num_mods; m++)
1079 	{
1080 		if(app->mods[m] == mod)
1081 			offset += 1;
1082 		app->mods[m] = app->mods[m+offset];
1083 	}
1084 
1085 	// disconnect all ports
1086 	for(unsigned p1=0; p1<mod->num_ports; p1++)
1087 	{
1088 		port_t *port = &mod->ports[p1];
1089 
1090 		connectable_t *conn = _sp_app_port_connectable(port);
1091 		if(conn)
1092 		{
1093 			// disconnect sources
1094 			for(int s=0; s<conn->num_sources; s++)
1095 				_sp_app_port_disconnect(app, conn->sources[s].port, port);
1096 		}
1097 
1098 		// disconnect sinks
1099 		for(unsigned m=0; m<app->num_mods; m++)
1100 		{
1101 			for(unsigned p2=0; p2<app->mods[m]->num_ports; p2++)
1102 				_sp_app_port_disconnect(app, port, &app->mods[m]->ports[p2]);
1103 		}
1104 	}
1105 
1106 	// send request to worker thread
1107 	size_t size = sizeof(job_t);
1108 	job_t *job = _sp_app_to_worker_request(app, size);
1109 	if(job)
1110 	{
1111 		job->request = JOB_TYPE_REQUEST_MODULE_DEL;
1112 		job->mod = mod;
1113 		_sp_app_to_worker_advance(app, size);
1114 	}
1115 	else
1116 	{
1117 		sp_app_log_error(app, "%s: failed requesting buffer\n", __func__);
1118 	}
1119 
1120 	_sp_app_order(app);
1121 
1122 #if 0
1123 	// signal to ui
1124 	size = sizeof(transmit_module_del_t);
1125 	transmit_module_del_t *trans = _sp_app_to_ui_request(app, size);
1126 	if(trans)
1127 	{
1128 		_sp_transmit_module_del_fill(&app->regs, &app->forge, trans, size, mod->uid);
1129 		_sp_app_to_ui_advance(app, size);
1130 	}
1131 #endif
1132 }
1133 
1134 static void
_sp_app_mod_reinitialize_soft(mod_t * mod)1135 _sp_app_mod_reinitialize_soft(mod_t *mod)
1136 {
1137 	sp_app_t *app = mod->app;
1138 
1139 	// reinitialize all modules,
1140 	lilv_instance_deactivate(mod->inst);
1141 	lilv_instance_free(mod->inst);
1142 
1143 	mod->inst = NULL;
1144 	mod->handle = NULL;
1145 
1146 	// mod->features should be up-to-date
1147 	mod->inst = lilv_plugin_instantiate(mod->plug, app->driver->sample_rate, mod->features);
1148 	mod->handle = lilv_instance_get_handle(mod->inst);
1149 
1150 	// refresh all connections
1151 	for(unsigned i=0; i<mod->num_ports - 2; i++)
1152 	{
1153 		port_t *tar = &mod->ports[i];
1154 
1155 		// set port buffer
1156 		lilv_instance_connect_port(mod->inst, i, tar->base);
1157 	}
1158 }
1159 
1160 void
_sp_app_mod_reinstantiate(sp_app_t * app,mod_t * mod)1161 _sp_app_mod_reinstantiate(sp_app_t *app, mod_t *mod)
1162 {
1163 	char *path;
1164 
1165 	if(asprintf(&path, "file:///tmp/%s.preset.lv2", mod->urn_uri) == -1)
1166 	{
1167 		sp_app_log_note(app, "%s: failed to create temporary path\n", __func__);
1168 		return;
1169 	}
1170 
1171 	LilvState *const state = _sp_app_state_preset_create(app, mod, path);
1172 	free(path);
1173 
1174 	if(state)
1175 	{
1176 		_sp_app_mod_reinitialize_soft(mod);
1177 
1178 		lilv_instance_activate(mod->inst);
1179 
1180 		_sp_app_state_preset_restore(app, mod, state, false);
1181 
1182 		lilv_state_free(state);
1183 	}
1184 }
1185