1 /* GSequencer - Advanced GTK Sequencer
2 * Copyright (C) 2005-2020 Joël Krähemann
3 *
4 * This file is part of GSequencer.
5 *
6 * GSequencer is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * GSequencer is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GSequencer. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <ags/plugin/ags_lv2ui_plugin.h>
21
22 #include <ags/plugin/ags_lv2_plugin.h>
23 #include <ags/plugin/ags_lv2_event_manager.h>
24 #include <ags/plugin/ags_lv2_uri_map_manager.h>
25 #include <ags/plugin/ags_lv2_log_manager.h>
26 #include <ags/plugin/ags_lv2_urid_manager.h>
27
28 #if defined(AGS_W32API)
29 #include <windows.h>
30 #else
31 #include <dlfcn.h>
32 #endif
33
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <sys/types.h>
38 #include <unistd.h>
39
40 #include <math.h>
41
42 #include <lv2.h>
43 #include <lv2/lv2plug.in/ns/extensions/ui/ui.h>
44 #include <lv2/lv2plug.in/ns/ext/instance-access/instance-access.h>
45
46 #include <ags/i18n.h>
47
48 void ags_lv2ui_plugin_class_init(AgsLv2uiPluginClass *lv2ui_plugin);
49 void ags_lv2ui_plugin_init (AgsLv2uiPlugin *lv2ui_plugin);
50 void ags_lv2ui_plugin_set_property(GObject *gobject,
51 guint prop_id,
52 const GValue *value,
53 GParamSpec *param_spec);
54 void ags_lv2ui_plugin_get_property(GObject *gobject,
55 guint prop_id,
56 GValue *value,
57 GParamSpec *param_spec);
58 void ags_lv2ui_plugin_dispose(GObject *gobject);
59 void ags_lv2ui_plugin_finalize(GObject *gobject);
60
61 gpointer ags_lv2ui_plugin_instantiate_with_params(AgsBasePlugin *base_plugin,
62 guint *n_params,
63 gchar ***parameter_name,
64 GValue **value);
65
66 void ags_lv2ui_plugin_connect_port(AgsBasePlugin *base_plugin,
67 gpointer plugin_handle,
68 guint port_index,
69 gpointer data_location);
70 void ags_lv2ui_plugin_activate(AgsBasePlugin *base_plugin,
71 gpointer plugin_handle);
72 void ags_lv2ui_plugin_deactivate(AgsBasePlugin *base_plugin,
73 gpointer plugin_handle);
74 void ags_lv2ui_plugin_run(AgsBasePlugin *base_plugin,
75 gpointer plugin_handle,
76 snd_seq_event_t *seq_event,
77 guint frame_count);
78 void ags_lv2ui_plugin_load_plugin(AgsBasePlugin *base_plugin);
79
80 /**
81 * SECTION:ags_lv2ui_plugin
82 * @short_description: The lv2ui plugin class
83 * @title: AgsLv2uiPlugin
84 * @section_id:
85 * @include: ags/plugin/ags_lv2ui_plugin.h
86 *
87 * The #AgsLv2uiPlugin loads/unloads a Lv2ui plugin.
88 */
89
90 enum{
91 PROP_0,
92 PROP_GUI_FILENAME,
93 PROP_GUI_URI,
94 PROP_MANIFEST,
95 PROP_GUI_TURTLE,
96 PROP_LV2_PLUGIN,
97 };
98
99 static gpointer ags_lv2ui_plugin_parent_class = NULL;
100
101 GType
ags_lv2ui_plugin_get_type(void)102 ags_lv2ui_plugin_get_type (void)
103 {
104 static volatile gsize g_define_type_id__volatile = 0;
105
106 if(g_once_init_enter (&g_define_type_id__volatile)){
107 GType ags_type_lv2ui_plugin = 0;
108
109 static const GTypeInfo ags_lv2ui_plugin_info = {
110 sizeof (AgsLv2uiPluginClass),
111 NULL, /* lv2ui_init */
112 NULL, /* lv2ui_finalize */
113 (GClassInitFunc) ags_lv2ui_plugin_class_init,
114 NULL, /* class_finalize */
115 NULL, /* class_data */
116 sizeof (AgsLv2uiPlugin),
117 0, /* n_preallocs */
118 (GInstanceInitFunc) ags_lv2ui_plugin_init,
119 };
120
121 ags_type_lv2ui_plugin = g_type_register_static(AGS_TYPE_BASE_PLUGIN,
122 "AgsLv2uiPlugin",
123 &ags_lv2ui_plugin_info,
124 0);
125
126 g_once_init_leave(&g_define_type_id__volatile, ags_type_lv2ui_plugin);
127 }
128
129 return g_define_type_id__volatile;
130 }
131
132 GType
ags_lv2ui_plugin_flags_get_type()133 ags_lv2ui_plugin_flags_get_type()
134 {
135 static volatile gsize g_flags_type_id__volatile;
136
137 if(g_once_init_enter (&g_flags_type_id__volatile)){
138 static const GFlagsValue values[] = {
139 { AGS_LV2UI_PLUGIN_IS_SYNTHESIZER, "AGS_LV2UI_PLUGIN_IS_SYNTHESIZER", "lv2ui-plugin-is-synthesizer" },
140 { AGS_LV2UI_PLUGIN_GTK2, "AGS_LV2UI_PLUGIN_GTK2", "lv2ui-plugin-gtk2" },
141 { AGS_LV2UI_PLUGIN_GTK3, "AGS_LV2UI_PLUGIN_GTK3", "lv2ui-plugin-gtk3" },
142 { AGS_LV2UI_PLUGIN_QT4, "AGS_LV2UI_PLUGIN_QT4", "lv2ui-plugin-qt4" },
143 { AGS_LV2UI_PLUGIN_QT5, "AGS_LV2UI_PLUGIN_QT5", "lv2ui-plugin-qt5" },
144 { 0, NULL, NULL }
145 };
146
147 GType g_flags_type_id = g_flags_register_static(g_intern_static_string("AgsLv2uiPluginFlags"), values);
148
149 g_once_init_leave (&g_flags_type_id__volatile, g_flags_type_id);
150 }
151
152 return g_flags_type_id__volatile;
153 }
154
155 void
ags_lv2ui_plugin_class_init(AgsLv2uiPluginClass * lv2ui_plugin)156 ags_lv2ui_plugin_class_init(AgsLv2uiPluginClass *lv2ui_plugin)
157 {
158 AgsBasePluginClass *base_plugin;
159
160 GObjectClass *gobject;
161 GParamSpec *param_spec;
162
163 ags_lv2ui_plugin_parent_class = g_type_class_peek_parent(lv2ui_plugin);
164
165 /* GObjectClass */
166 gobject = (GObjectClass *) lv2ui_plugin;
167
168 gobject->set_property = ags_lv2ui_plugin_set_property;
169 gobject->get_property = ags_lv2ui_plugin_get_property;
170
171 gobject->dispose = ags_lv2ui_plugin_dispose;
172 gobject->finalize = ags_lv2ui_plugin_finalize;
173
174 /* properties */
175 /**
176 * AgsLv2uiPlugin:gui-uri:
177 *
178 * The assigned GUI URI.
179 *
180 * Since: 3.0.0
181 */
182 param_spec = g_param_spec_string("gui-uri",
183 i18n_pspec("GUI URI of the plugin"),
184 i18n_pspec("The GUI URI this plugin is located in"),
185 NULL,
186 G_PARAM_READABLE | G_PARAM_WRITABLE);
187 g_object_class_install_property(gobject,
188 PROP_GUI_URI,
189 param_spec);
190
191 /**
192 * AgsLv2uiPlugin:manifest:
193 *
194 * The assigned manifest.
195 *
196 * Since: 3.0.0
197 */
198 param_spec = g_param_spec_object("manifest",
199 i18n_pspec("manifest of the plugin"),
200 i18n_pspec("The manifest this plugin is located in"),
201 AGS_TYPE_TURTLE,
202 G_PARAM_READABLE | G_PARAM_WRITABLE);
203 g_object_class_install_property(gobject,
204 PROP_MANIFEST,
205 param_spec);
206
207 /**
208 * AgsLv2uiPlugin:gui-turtle:
209 *
210 * The assigned GUI turtle.
211 *
212 * Since: 3.0.0
213 */
214 param_spec = g_param_spec_object("gui-turtle",
215 i18n_pspec("GUI turtle of the plugin"),
216 i18n_pspec("The GUI turtle this plugin is located in"),
217 AGS_TYPE_TURTLE,
218 G_PARAM_READABLE | G_PARAM_WRITABLE);
219 g_object_class_install_property(gobject,
220 PROP_GUI_TURTLE,
221 param_spec);
222
223 /**
224 * AgsLv2uiPlugin:lv2-plugin:
225 *
226 * The assigned LV2 plugin.
227 *
228 * Since: 3.0.0
229 */
230 param_spec = g_param_spec_object("lv2-plugin",
231 i18n_pspec("LV2 plugin of the plugin"),
232 i18n_pspec("The LV2 plugin this plugin is located in"),
233 AGS_TYPE_LV2_PLUGIN,
234 G_PARAM_READABLE | G_PARAM_WRITABLE);
235 g_object_class_install_property(gobject,
236 PROP_LV2_PLUGIN,
237 param_spec);
238
239 /* AgsBasePluginClass */
240 base_plugin = (AgsBasePluginClass *) lv2ui_plugin;
241
242 base_plugin->instantiate_with_params = ags_lv2ui_plugin_instantiate_with_params;
243 base_plugin->load_plugin = ags_lv2ui_plugin_load_plugin;
244 }
245
246 void
ags_lv2ui_plugin_init(AgsLv2uiPlugin * lv2ui_plugin)247 ags_lv2ui_plugin_init(AgsLv2uiPlugin *lv2ui_plugin)
248 {
249 lv2ui_plugin->flags = 0;
250
251 lv2ui_plugin->gui_uri = NULL;
252
253 lv2ui_plugin->manifest = NULL;
254 lv2ui_plugin->gui_turtle = NULL;
255
256 lv2ui_plugin->lv2_plugin = NULL;
257
258 lv2ui_plugin->feature = NULL;
259 }
260
261 void
ags_lv2ui_plugin_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)262 ags_lv2ui_plugin_set_property(GObject *gobject,
263 guint prop_id,
264 const GValue *value,
265 GParamSpec *param_spec)
266 {
267 AgsLv2uiPlugin *lv2ui_plugin;
268
269 GRecMutex *base_plugin_mutex;
270
271 lv2ui_plugin = AGS_LV2UI_PLUGIN(gobject);
272
273 /* get base plugin mutex */
274 base_plugin_mutex = AGS_BASE_PLUGIN_GET_OBJ_MUTEX(lv2ui_plugin);
275
276 switch(prop_id){
277 case PROP_GUI_URI:
278 {
279 gchar *gui_uri;
280
281 gui_uri = (gchar *) g_value_get_string(value);
282
283 g_rec_mutex_lock(base_plugin_mutex);
284
285 if(lv2ui_plugin->gui_uri == gui_uri){
286 g_rec_mutex_unlock(base_plugin_mutex);
287
288 return;
289 }
290
291 if(lv2ui_plugin->gui_uri != NULL){
292 g_free(lv2ui_plugin->gui_uri);
293 }
294
295 lv2ui_plugin->gui_uri = g_strdup(gui_uri);
296
297 g_rec_mutex_unlock(base_plugin_mutex);
298 }
299 break;
300 case PROP_MANIFEST:
301 {
302 AgsTurtle *manifest;
303
304 manifest = (AgsTurtle *) g_value_get_object(value);
305
306 g_rec_mutex_lock(base_plugin_mutex);
307
308 if(lv2ui_plugin->manifest == manifest){
309 g_rec_mutex_unlock(base_plugin_mutex);
310
311 return;
312 }
313
314 if(lv2ui_plugin->manifest != NULL){
315 g_object_unref(lv2ui_plugin->manifest);
316 }
317
318 if(manifest != NULL){
319 g_object_ref(manifest);
320 }
321
322 lv2ui_plugin->manifest = manifest;
323
324 g_rec_mutex_unlock(base_plugin_mutex);
325 }
326 break;
327 case PROP_GUI_TURTLE:
328 {
329 AgsTurtle *gui_turtle;
330
331 gui_turtle = (AgsTurtle *) g_value_get_object(value);
332
333 g_rec_mutex_lock(base_plugin_mutex);
334
335 if(lv2ui_plugin->gui_turtle == gui_turtle){
336 g_rec_mutex_unlock(base_plugin_mutex);
337
338 return;
339 }
340
341 if(lv2ui_plugin->gui_turtle != NULL){
342 g_object_unref(lv2ui_plugin->gui_turtle);
343 }
344
345 if(gui_turtle != NULL){
346 g_object_ref(gui_turtle);
347 }
348
349 lv2ui_plugin->gui_turtle = gui_turtle;
350
351 g_rec_mutex_unlock(base_plugin_mutex);
352 }
353 break;
354 case PROP_LV2_PLUGIN:
355 {
356 GObject *lv2_plugin;
357
358 lv2_plugin = (GObject *) g_value_get_object(value);
359
360 g_rec_mutex_lock(base_plugin_mutex);
361
362 if(lv2ui_plugin->lv2_plugin == lv2_plugin){
363 g_rec_mutex_unlock(base_plugin_mutex);
364
365 return;
366 }
367
368 if(lv2ui_plugin->lv2_plugin != NULL){
369 g_object_unref(lv2ui_plugin->lv2_plugin);
370 }
371
372 if(lv2_plugin != NULL){
373 g_object_ref(lv2_plugin);
374 }
375
376 lv2ui_plugin->lv2_plugin = lv2_plugin;
377
378 g_rec_mutex_unlock(base_plugin_mutex);
379 }
380 break;
381 default:
382 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
383 break;
384 }
385 }
386
387 void
ags_lv2ui_plugin_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)388 ags_lv2ui_plugin_get_property(GObject *gobject,
389 guint prop_id,
390 GValue *value,
391 GParamSpec *param_spec)
392 {
393 AgsLv2uiPlugin *lv2ui_plugin;
394
395 GRecMutex *base_plugin_mutex;
396
397 lv2ui_plugin = AGS_LV2UI_PLUGIN(gobject);
398
399 /* get base plugin mutex */
400 base_plugin_mutex = AGS_BASE_PLUGIN_GET_OBJ_MUTEX(lv2ui_plugin);
401
402 switch(prop_id){
403 case PROP_GUI_URI:
404 {
405 g_rec_mutex_lock(base_plugin_mutex);
406
407 g_value_set_string(value, lv2ui_plugin->gui_uri);
408
409 g_rec_mutex_unlock(base_plugin_mutex);
410 }
411 break;
412 case PROP_MANIFEST:
413 {
414 g_rec_mutex_lock(base_plugin_mutex);
415
416 g_value_set_object(value, lv2ui_plugin->manifest);
417
418 g_rec_mutex_unlock(base_plugin_mutex);
419 }
420 break;
421 case PROP_GUI_TURTLE:
422 {
423 g_rec_mutex_lock(base_plugin_mutex);
424
425 g_value_set_object(value, lv2ui_plugin->gui_turtle);
426
427 g_rec_mutex_unlock(base_plugin_mutex);
428 }
429 break;
430 case PROP_LV2_PLUGIN:
431 {
432 g_rec_mutex_lock(base_plugin_mutex);
433
434 g_value_set_object(value, lv2ui_plugin->lv2_plugin);
435
436 g_rec_mutex_unlock(base_plugin_mutex);
437 }
438 break;
439 default:
440 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
441 break;
442 }
443 }
444
445 void
ags_lv2ui_plugin_dispose(GObject * gobject)446 ags_lv2ui_plugin_dispose(GObject *gobject)
447 {
448 AgsLv2uiPlugin *lv2ui_plugin;
449
450 lv2ui_plugin = AGS_LV2UI_PLUGIN(gobject);
451
452 if(lv2ui_plugin->manifest != NULL){
453 g_object_unref(lv2ui_plugin->manifest);
454
455 lv2ui_plugin->manifest = NULL;
456 }
457
458 if(lv2ui_plugin->gui_turtle != NULL){
459 g_object_unref(lv2ui_plugin->gui_turtle);
460
461 lv2ui_plugin->gui_turtle = NULL;
462 }
463
464 if(lv2ui_plugin->lv2_plugin != NULL){
465 g_object_unref(lv2ui_plugin->lv2_plugin);
466
467 lv2ui_plugin->lv2_plugin = NULL;
468 }
469
470 /* call parent */
471 G_OBJECT_CLASS(ags_lv2ui_plugin_parent_class)->dispose(gobject);
472 }
473
474 void
ags_lv2ui_plugin_finalize(GObject * gobject)475 ags_lv2ui_plugin_finalize(GObject *gobject)
476 {
477 AgsLv2uiPlugin *lv2ui_plugin;
478
479 lv2ui_plugin = AGS_LV2UI_PLUGIN(gobject);
480
481 g_free(lv2ui_plugin->gui_uri);
482
483 if(lv2ui_plugin->manifest != NULL){
484 g_object_unref(lv2ui_plugin->manifest);
485 }
486
487 if(lv2ui_plugin->gui_turtle != NULL){
488 g_object_unref(lv2ui_plugin->gui_turtle);
489 }
490
491 if(lv2ui_plugin->lv2_plugin != NULL){
492 g_object_unref(lv2ui_plugin->lv2_plugin);
493 }
494
495 /* call parent */
496 G_OBJECT_CLASS(ags_lv2ui_plugin_parent_class)->finalize(gobject);
497 }
498
499 void
ags_lv2ui_plugin_load_plugin(AgsBasePlugin * base_plugin)500 ags_lv2ui_plugin_load_plugin(AgsBasePlugin *base_plugin)
501 {
502 //NOTE:JK: deprecated
503 }
504
505 gpointer
ags_lv2ui_plugin_instantiate_with_params(AgsBasePlugin * base_plugin,guint * n_params,gchar *** parameter_name,GValue ** value)506 ags_lv2ui_plugin_instantiate_with_params(AgsBasePlugin *base_plugin,
507 guint *n_params,
508 gchar ***parameter_name,
509 GValue **value)
510 {
511 AgsLv2uiPlugin *lv2ui_plugin;
512
513 LV2UI_Controller controller;
514 LV2UI_Widget widget;
515
516 void *ui_plugin_so;
517 LV2UI_DescriptorFunction lv2ui_descriptor;
518 LV2UI_Descriptor *plugin_descriptor;
519
520 LV2_Handle *lv2_handle;
521 LV2UI_Handle *ui_handle;
522
523 LV2_URI_Map_Feature *uri_map_feature;
524
525 LV2_Log_Log *log_feature;
526
527 LV2_Event_Feature *event_feature;
528
529 LV2_URID_Map *urid_map;
530 LV2_URID_Unmap *urid_unmap;
531
532 LV2UI_Write_Function write_function;
533
534 LV2_Feature **feature;
535
536 gchar *uri;
537 gchar *filename;
538 char *path;
539 gchar *str;
540
541 float *ptr_samplerate;
542 float *ptr_buffer_size;
543
544 uint32_t ui_effect_index;
545 guint local_n_params;
546 guint total_feature;
547 guint nth;
548 guint i;
549 gboolean initial_call;
550
551 LV2UI_Handle (*instantiate)(const struct _LV2UI_Descriptor* descriptor,
552 const char *plugin_uri,
553 const char *bundle_path,
554 LV2UI_Write_Function write_function,
555 LV2UI_Controller controller,
556 LV2UI_Widget *widget,
557 const LV2_Feature *const *features);
558
559 GRecMutex *base_plugin_mutex;
560
561 lv2ui_plugin = AGS_LV2UI_PLUGIN(base_plugin);
562
563 /* get base plugin mutex */
564 base_plugin_mutex = AGS_BASE_PLUGIN_GET_OBJ_MUTEX(base_plugin);
565
566 local_n_params = 0;
567
568 if(n_params == NULL){
569 n_params = &local_n_params;
570 }
571
572 /* get some fields */
573 g_rec_mutex_lock(base_plugin_mutex);
574
575 ui_plugin_so = base_plugin->ui_plugin_so;
576 ui_effect_index = 0;
577
578 if(ui_plugin_so == NULL){
579 gboolean success;
580
581 g_message("open %s", base_plugin->ui_filename);
582
583 #ifdef AGS_W32API
584 ui_plugin_so = LoadLibrary(base_plugin->filename);
585 #else
586 ui_plugin_so = dlopen(base_plugin->filename,
587 RTLD_NOW);
588 #endif
589
590 g_object_set(lv2ui_plugin,
591 "ui-plugin-so", ui_plugin_so,
592 NULL);
593
594 success = FALSE;
595
596 #ifdef AGS_W32API
597 base_plugin->ui_plugin_handle =
598 lv2ui_descriptor = (LV2_Descriptor_Function) GetProcAddress(ui_plugin_so,
599 "lv2ui_descriptor");
600
601 success = (!lv2_descriptor) ? FALSE: TRUE;
602 #else
603 base_plugin->ui_plugin_handle =
604 lv2ui_descriptor = (LV2_Descriptor_Function) dlsym(ui_plugin_so,
605 "lv2ui_descriptor");
606
607 success = (dlerror() == NULL) ? TRUE: FALSE;
608 #endif
609
610 if(success && lv2_descriptor){
611 for(i = 0; (plugin_descriptor = lv2ui_descriptor((uint32_t) i)) != NULL; i++){
612 if(!g_ascii_strcasecmp(plugin_descriptor->URI,
613 lv2ui_plugin->gui_uri)){
614 base_plugin->ui_plugin_descriptor = plugin_descriptor;
615 ui_effect_index = i;
616
617 g_object_set(lv2ui_plugin,
618 "ui-effect-index", ui_effect_index,
619 NULL);
620
621 break;
622 }
623 }
624 }
625 }
626
627 lv2ui_descriptor = base_plugin->ui_plugin_handle;
628 plugin_descriptor = base_plugin->ui_plugin_descriptor;
629
630 feature = lv2ui_plugin->feature;
631
632 path = g_path_get_dirname(base_plugin->ui_filename);
633
634 ui_effect_index = base_plugin->ui_effect_index;
635
636 g_rec_mutex_unlock(base_plugin_mutex);
637
638 if(ui_plugin_so == NULL){
639 g_free(path);
640
641 return(NULL);
642 }
643
644 /* check args */
645 uri = NULL;
646
647 controller = NULL;
648 widget = NULL;
649
650 write_function = NULL;
651
652 lv2_handle = NULL;
653
654 if(n_params != NULL &&
655 parameter_name != NULL &&
656 parameter_name[0] != NULL &&
657 value != NULL &&
658 value[0] != NULL){
659 for(i = 0; i < n_params[0] && parameter_name[0][i] != NULL; i++){
660 if(!g_ascii_strncasecmp(parameter_name[0][i],
661 "uri",
662 4)){
663 uri = g_value_get_pointer(&(value[0][i]));
664 }else if(!g_ascii_strncasecmp(parameter_name[0][i],
665 "controller",
666 11)){
667 controller = g_value_get_pointer(&(value[0][i]));
668 }else if(!g_ascii_strncasecmp(parameter_name[0][i],
669 "write-function",
670 15)){
671 write_function = g_value_get_pointer(&(value[0][i]));
672 }else if(!g_ascii_strncasecmp(parameter_name[0][i],
673 "instance",
674 9)){
675 lv2_handle = g_value_get_pointer(&(value[0][i]));
676 }
677 }
678 }
679
680 /* features */
681 initial_call = FALSE;
682
683 if(feature == NULL){
684 initial_call = TRUE;
685
686 /**/
687 total_feature = 9;
688 nth = 0;
689
690 feature = (LV2_Feature **) malloc(total_feature * sizeof(LV2_Feature *));
691
692 /* idle interface */
693 feature[nth] = (LV2_Feature *) malloc(sizeof(LV2_Feature));
694 feature[nth]->URI = LV2_UI__idleInterface;
695 feature[nth]->data = NULL;
696
697 nth++;
698
699 /* show interface */
700 feature[nth] = (LV2_Feature *) malloc(sizeof(LV2_Feature));
701 feature[nth]->URI = LV2_UI__showInterface;
702 feature[nth]->data = NULL;
703
704 nth++;
705
706 /* instance access */
707 feature[nth] = (LV2_Feature *) malloc(sizeof(LV2_Feature));
708 feature[nth]->URI = LV2_INSTANCE_ACCESS_URI;
709 feature[nth]->data = NULL;
710
711 if(lv2_handle != NULL){
712 feature[nth]->data = lv2_handle[0];
713 }
714
715 nth++;
716
717 /* URI map feature */
718 uri_map_feature = (LV2_URI_Map_Feature *) malloc(sizeof(LV2_URI_Map_Feature));
719 uri_map_feature->callback_data = NULL;
720 uri_map_feature->uri_to_id = ags_lv2_uri_map_manager_uri_to_id;
721
722 feature[nth] = (LV2_Feature *) malloc(sizeof(LV2_Feature));
723 feature[nth]->URI = LV2_URI_MAP_URI;
724 feature[nth]->data = uri_map_feature;
725
726 nth++;
727
728 /* log feature */
729 #if 0
730 log_feature = (LV2_Log_Log *) malloc(sizeof(LV2_Log_Log));
731
732 log_feature->handle = NULL;
733 log_feature->printf = ags_lv2_log_manager_printf;
734 log_feature->vprintf = ags_lv2_log_manager_vprintf;
735
736 feature[nth] = (LV2_Feature *) malloc(sizeof(LV2_Feature));
737 feature[nth]->URI = LV2_LOG__log;
738 feature[nth]->data = log_feature;
739
740 nth++;
741 #endif
742
743 /* event feature */
744 event_feature = (LV2_Event_Feature *) malloc(sizeof(LV2_Event_Feature));
745
746 event_feature->callback_data = NULL;
747 event_feature->lv2_event_ref = ags_lv2_event_manager_lv2_event_ref;
748 event_feature->lv2_event_unref = ags_lv2_event_manager_lv2_event_unref;
749
750 feature[nth] = (LV2_Feature *) malloc(sizeof(LV2_Feature));
751 feature[nth]->URI = LV2_EVENT_URI;
752 feature[nth]->data = event_feature;
753
754 nth++;
755
756 /* URID map feature */
757 urid_map = (LV2_URID_Map *) malloc(sizeof(LV2_URID_Map));
758 urid_map->handle = NULL;
759 urid_map->map = ags_lv2_urid_manager_map;
760
761 feature[nth] = (LV2_Feature *) malloc(sizeof(LV2_Feature));
762 feature[nth]->URI = LV2_URID_MAP_URI;
763 feature[nth]->data = urid_map;
764
765 nth++;
766
767 /* URID unmap feature */
768 urid_unmap = (LV2_URID_Unmap *) malloc(sizeof(LV2_URID_Unmap));
769 urid_unmap->handle = NULL;
770 urid_unmap->unmap = ags_lv2_urid_manager_unmap;
771
772 feature[nth] = (LV2_Feature *) malloc(sizeof(LV2_Feature));
773 feature[nth]->URI = LV2_URID_UNMAP_URI;
774 feature[nth]->data = urid_unmap;
775
776 nth++;
777
778 /* terminate */
779 for(; nth < total_feature; nth++){
780 feature[nth] = NULL;
781 }
782
783 g_rec_mutex_lock(base_plugin_mutex);
784
785 lv2ui_plugin->feature = feature;
786
787 g_rec_mutex_unlock(base_plugin_mutex);
788 }
789
790 instantiate = NULL;
791
792 if(plugin_descriptor != NULL){
793 g_rec_mutex_lock(base_plugin_mutex);
794
795 instantiate = plugin_descriptor->instantiate;
796
797 g_rec_mutex_unlock(base_plugin_mutex);
798 }
799
800 /* instantiate */
801 ui_handle = (LV2UI_Handle *) malloc(sizeof(LV2UI_Handle));
802
803 ui_handle[0] = NULL;
804
805 if(instantiate != NULL){
806 ui_handle[0] = instantiate(plugin_descriptor,
807 uri,
808 path,
809 write_function,
810 controller,
811 &widget,
812 feature);
813 }
814
815 g_message("LV2UI handle = %p", ui_handle[0]);
816
817 if(parameter_name != NULL &&
818 value != NULL){
819 if(n_params[0] == 0){
820 parameter_name[0] = (gchar **) malloc(2 * sizeof(gchar *));
821 value[0] = g_new0(GValue,
822 1);
823 }else{
824 parameter_name[0] = (gchar **) realloc(parameter_name[0],
825 (n_params[0] + 2) * sizeof(gchar *));
826 value[0] = g_renew(GValue,
827 value[0],
828 n_params[0] + 1);
829 }
830
831 parameter_name[0][n_params[0]] = g_strdup("widget");
832 g_value_init(&(value[0][n_params[0]]),
833 G_TYPE_POINTER);
834 g_value_set_pointer(&(value[0][n_params[0]]), widget);
835
836 parameter_name[0][n_params[0] + 1] = NULL;
837
838 n_params[0] += 1;
839 }
840
841 return(ui_handle);
842 }
843
844 /**
845 * ags_lv2ui_plugin_test_flags:
846 * @lv2ui_plugin: the #AgsLv2uiPlugin
847 * @flags: the flags
848 *
849 * Test @flags to be set on @recall.
850 *
851 * Returns: %TRUE if flags are set, else %FALSE
852 *
853 * Since: 3.0.0
854 */
855 gboolean
ags_lv2ui_plugin_test_flags(AgsLv2uiPlugin * lv2ui_plugin,guint flags)856 ags_lv2ui_plugin_test_flags(AgsLv2uiPlugin *lv2ui_plugin, guint flags)
857 {
858 gboolean retval;
859
860 GRecMutex *base_plugin_mutex;
861
862 if(!AGS_IS_LV2UI_PLUGIN(lv2ui_plugin)){
863 return(FALSE);
864 }
865
866 /* get base plugin mutex */
867 base_plugin_mutex = AGS_BASE_PLUGIN_GET_OBJ_MUTEX(lv2ui_plugin);
868
869 /* test flags */
870 g_rec_mutex_lock(base_plugin_mutex);
871
872 retval = ((flags & (lv2ui_plugin->flags)) != 0) ? TRUE: FALSE;
873
874 g_rec_mutex_unlock(base_plugin_mutex);
875
876 return(retval);
877 }
878
879 /**
880 * ags_lv2ui_plugin_set_flags:
881 * @lv2ui_plugin: the #AgsLv2uiPlugin
882 * @flags: the flags
883 *
884 * Set flags.
885 *
886 * Since: 3.0.0
887 */
888 void
ags_lv2ui_plugin_set_flags(AgsLv2uiPlugin * lv2ui_plugin,guint flags)889 ags_lv2ui_plugin_set_flags(AgsLv2uiPlugin *lv2ui_plugin, guint flags)
890 {
891 GRecMutex *base_plugin_mutex;
892
893 if(!AGS_IS_LV2UI_PLUGIN(lv2ui_plugin)){
894 return;
895 }
896
897 /* get base plugin mutex */
898 base_plugin_mutex = AGS_BASE_PLUGIN_GET_OBJ_MUTEX(lv2ui_plugin);
899
900 /* set flags */
901 g_rec_mutex_lock(base_plugin_mutex);
902
903 lv2ui_plugin->flags |= flags;
904
905 g_rec_mutex_unlock(base_plugin_mutex);
906 }
907
908 /**
909 * ags_lv2ui_plugin_unset_flags:
910 * @lv2ui_plugin: the #AgsLv2uiPlugin
911 * @flags: the flags
912 *
913 * Unset flags.
914 *
915 * Since: 3.0.0
916 */
917 void
ags_lv2ui_plugin_unset_flags(AgsLv2uiPlugin * lv2ui_plugin,guint flags)918 ags_lv2ui_plugin_unset_flags(AgsLv2uiPlugin *lv2ui_plugin, guint flags)
919 {
920 GRecMutex *base_plugin_mutex;
921
922 if(!AGS_IS_LV2UI_PLUGIN(lv2ui_plugin)){
923 return;
924 }
925
926 /* get base plugin mutex */
927 base_plugin_mutex = AGS_BASE_PLUGIN_GET_OBJ_MUTEX(lv2ui_plugin);
928
929 /* unset flags */
930 g_rec_mutex_lock(base_plugin_mutex);
931
932 lv2ui_plugin->flags &= (~flags);
933
934 g_rec_mutex_unlock(base_plugin_mutex);
935 }
936
937 /**
938 * ags_lv2ui_plugin_find_gui_uri:
939 * @lv2ui_plugin: (element-type AgsAudio.Lv2uiPlugin) (transfer none): the #GList-struct containing #AgsLv2uiPlugin
940 * @gui_uri: the gui-uri as string
941 *
942 * Find next matching gui-uri in @lv2ui_plugin.
943 *
944 * Returns: (element-type AgsAudio.Lv2uiPlugin) (transfer none): the next matching #GList-struct
945 *
946 * Since: 3.0.0
947 */
948 GList*
ags_lv2ui_plugin_find_gui_uri(GList * lv2ui_plugin,gchar * gui_uri)949 ags_lv2ui_plugin_find_gui_uri(GList *lv2ui_plugin,
950 gchar *gui_uri)
951 {
952 if(gui_uri == NULL){
953 return(NULL);
954 }
955
956 while(lv2ui_plugin != NULL){
957 if(AGS_LV2UI_PLUGIN(lv2ui_plugin->data)->gui_uri != NULL &&
958 !g_ascii_strcasecmp(AGS_LV2UI_PLUGIN(lv2ui_plugin->data)->gui_uri,
959 gui_uri)){
960 return(lv2ui_plugin);
961 }
962
963 lv2ui_plugin = lv2ui_plugin->next;
964 }
965
966 return(NULL);
967 }
968
969 /**
970 * ags_lv2ui_plugin_new:
971 * @gui_turtle: the #AgsTurtle
972 * @filename: the plugin .so
973 * @effect: the effect's string representation
974 * @gui_uri: the effect's gui_uri
975 * @effect_index: the effect's index
976 *
977 * Creates an #AgsLv2uiPlugin
978 *
979 * Returns: a new #AgsLv2uiPlugin
980 *
981 * Since: 3.0.0
982 */
983 AgsLv2uiPlugin*
ags_lv2ui_plugin_new(AgsTurtle * gui_turtle,gchar * filename,gchar * effect,gchar * gui_uri,guint effect_index)984 ags_lv2ui_plugin_new(AgsTurtle *gui_turtle,
985 gchar *filename,
986 gchar *effect,
987 gchar *gui_uri,
988 guint effect_index)
989 {
990 AgsLv2uiPlugin *lv2ui_plugin;
991
992 lv2ui_plugin = (AgsLv2uiPlugin *) g_object_new(AGS_TYPE_LV2UI_PLUGIN,
993 "gui-turtle", gui_turtle,
994 "filename", filename,
995 "effect", effect,
996 "gui-uri", gui_uri,
997 "effect-index", effect_index,
998 NULL);
999
1000 return(lv2ui_plugin);
1001 }
1002