1 /* GSequencer - Advanced GTK Sequencer
2 * Copyright (C) 2005-2021 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/X/machine/ags_lv2_bridge.h>
21 #include <ags/X/machine/ags_lv2_bridge_callbacks.h>
22
23 #include <lv2/lv2plug.in/ns/lv2ext/lv2_programs.h>
24
25 #include <ags/X/ags_ui_provider.h>
26 #include <ags/X/ags_window.h>
27 #include <ags/X/ags_navigation.h>
28 #include <ags/X/ags_effect_bridge.h>
29 #include <ags/X/ags_effect_bulk.h>
30 #include <ags/X/ags_bulk_member.h>
31
32 #include <ags/i18n.h>
33
34 void ags_lv2_bridge_class_init(AgsLv2BridgeClass *lv2_bridge);
35 void ags_lv2_bridge_connectable_interface_init(AgsConnectableInterface *connectable);
36 void ags_lv2_bridge_init(AgsLv2Bridge *lv2_bridge);
37 void ags_lv2_bridge_set_property(GObject *gobject,
38 guint prop_id,
39 const GValue *value,
40 GParamSpec *param_spec);
41 void ags_lv2_bridge_get_property(GObject *gobject,
42 guint prop_id,
43 GValue *value,
44 GParamSpec *param_spec);
45 void ags_lv2_bridge_finalize(GObject *gobject);
46
47 void ags_lv2_bridge_connect(AgsConnectable *connectable);
48 void ags_lv2_bridge_disconnect(AgsConnectable *connectable);
49
50 void ags_lv2_bridge_resize_audio_channels(AgsMachine *machine,
51 guint audio_channels, guint audio_channels_old,
52 gpointer data);
53 void ags_lv2_bridge_resize_pads(AgsMachine *machine, GType channel_type,
54 guint pads, guint pads_old,
55 gpointer data);
56
57 void ags_lv2_bridge_map_recall(AgsMachine *machine);
58
59 /**
60 * SECTION:ags_lv2_bridge
61 * @short_description: A composite widget to visualize a bunch of #AgsChannel
62 * @title: AgsLv2Bridge
63 * @section_id:
64 * @include: ags/X/ags_lv2_bridge.h
65 *
66 * #AgsLv2Bridge is a composite widget to visualize all #AgsChannel. It should be
67 * packed by an #AgsMachine.
68 */
69
70 enum{
71 PROP_0,
72 PROP_FILENAME,
73 PROP_EFFECT,
74 PROP_URI,
75 PROP_INDEX,
76 PROP_HAS_MIDI,
77 PROP_HAS_GUI,
78 PROP_GUI_FILENAME,
79 PROP_GUI_URI,
80 };
81
82 static gpointer ags_lv2_bridge_parent_class = NULL;
83 static AgsConnectableInterface* ags_lv2_bridge_parent_connectable_interface;
84
85 GHashTable *ags_lv2_bridge_lv2ui_handle = NULL;
86 GHashTable *ags_lv2_bridge_lv2ui_idle = NULL;
87
88 GType
ags_lv2_bridge_get_type(void)89 ags_lv2_bridge_get_type(void)
90 {
91 static volatile gsize g_define_type_id__volatile = 0;
92
93 if(g_once_init_enter (&g_define_type_id__volatile)){
94 GType ags_type_lv2_bridge = 0;
95
96 static const GTypeInfo ags_lv2_bridge_info = {
97 sizeof(AgsLv2BridgeClass),
98 NULL, /* base_init */
99 NULL, /* base_finalize */
100 (GClassInitFunc) ags_lv2_bridge_class_init,
101 NULL, /* class_finalize */
102 NULL, /* class_data */
103 sizeof(AgsLv2Bridge),
104 0, /* n_preallocs */
105 (GInstanceInitFunc) ags_lv2_bridge_init,
106 };
107
108 static const GInterfaceInfo ags_connectable_interface_info = {
109 (GInterfaceInitFunc) ags_lv2_bridge_connectable_interface_init,
110 NULL, /* interface_finalize */
111 NULL, /* interface_data */
112 };
113
114 ags_type_lv2_bridge = g_type_register_static(AGS_TYPE_MACHINE,
115 "AgsLv2Bridge", &ags_lv2_bridge_info,
116 0);
117
118 g_type_add_interface_static(ags_type_lv2_bridge,
119 AGS_TYPE_CONNECTABLE,
120 &ags_connectable_interface_info);
121
122 g_once_init_leave(&g_define_type_id__volatile, ags_type_lv2_bridge);
123 }
124
125 return g_define_type_id__volatile;
126 }
127
128 void
ags_lv2_bridge_class_init(AgsLv2BridgeClass * lv2_bridge)129 ags_lv2_bridge_class_init(AgsLv2BridgeClass *lv2_bridge)
130 {
131 AgsMachineClass *machine;
132 GObjectClass *gobject;
133
134 GParamSpec *param_spec;
135
136 ags_lv2_bridge_parent_class = g_type_class_peek_parent(lv2_bridge);
137
138 /* GObjectClass */
139 gobject = G_OBJECT_CLASS(lv2_bridge);
140
141 gobject->set_property = ags_lv2_bridge_set_property;
142 gobject->get_property = ags_lv2_bridge_get_property;
143
144 gobject->finalize = ags_lv2_bridge_finalize;
145
146 /* properties */
147 /**
148 * AgsRecallLv2:filename:
149 *
150 * The plugin's filename.
151 *
152 * Since: 3.0.0
153 */
154 param_spec = g_param_spec_string("filename",
155 i18n_pspec("the object file"),
156 i18n_pspec("The filename as string of object file"),
157 NULL,
158 G_PARAM_READABLE | G_PARAM_WRITABLE);
159 g_object_class_install_property(gobject,
160 PROP_FILENAME,
161 param_spec);
162
163 /**
164 * AgsRecallLv2:effect:
165 *
166 * The effect's name.
167 *
168 * Since: 3.0.0
169 */
170 param_spec = g_param_spec_string("effect",
171 i18n_pspec("the effect"),
172 i18n_pspec("The effect's string representation"),
173 NULL,
174 G_PARAM_READABLE | G_PARAM_WRITABLE);
175 g_object_class_install_property(gobject,
176 PROP_EFFECT,
177 param_spec);
178
179 /**
180 * AgsRecallLv2:uri:
181 *
182 * The uri's name.
183 *
184 * Since: 3.0.0
185 */
186 param_spec = g_param_spec_string("uri",
187 i18n_pspec("the uri"),
188 i18n_pspec("The uri's string representation"),
189 NULL,
190 G_PARAM_READABLE | G_PARAM_WRITABLE);
191 g_object_class_install_property(gobject,
192 PROP_URI,
193 param_spec);
194
195 /**
196 * AgsRecallLv2:index:
197 *
198 * The uri's index.
199 *
200 * Since: 3.0.0
201 */
202 param_spec = g_param_spec_ulong("index",
203 i18n_pspec("index of uri"),
204 i18n_pspec("The numerical index of uri"),
205 0,
206 65535,
207 0,
208 G_PARAM_READABLE | G_PARAM_WRITABLE);
209 g_object_class_install_property(gobject,
210 PROP_INDEX,
211 param_spec);
212
213 /**
214 * AgsRecallLv2:has-midi:
215 *
216 * If has-midi is set to %TRUE appropriate flag is set
217 * to audio in order to become a sequencer.
218 *
219 * Since: 3.0.0
220 */
221 param_spec = g_param_spec_boolean("has-midi",
222 i18n_pspec("has-midi"),
223 i18n_pspec("If effect has-midi"),
224 FALSE,
225 G_PARAM_READABLE | G_PARAM_WRITABLE);
226 g_object_class_install_property(gobject,
227 PROP_HAS_MIDI,
228 param_spec);
229
230 /**
231 * AgsRecallLv2:has-gui:
232 *
233 * If has-gui is set to %TRUE 128 inputs are allocated and appropriate flag is set
234 * to audio in order to become a sequencer.
235 *
236 * Since: 3.0.0
237 */
238 param_spec = g_param_spec_boolean("has-gui",
239 i18n_pspec("has-gui"),
240 i18n_pspec("If effect has-gui"),
241 FALSE,
242 G_PARAM_READABLE | G_PARAM_WRITABLE);
243 g_object_class_install_property(gobject,
244 PROP_HAS_GUI,
245 param_spec);
246
247 /**
248 * AgsRecallLv2:gui-filename:
249 *
250 * The plugin's GUI filename.
251 *
252 * Since: 3.0.0
253 */
254 param_spec = g_param_spec_string("gui-filename",
255 i18n_pspec("the GUI object file"),
256 i18n_pspec("The filename as string of GUI object file"),
257 NULL,
258 G_PARAM_READABLE | G_PARAM_WRITABLE);
259 g_object_class_install_property(gobject,
260 PROP_GUI_FILENAME,
261 param_spec);
262
263 /**
264 * AgsRecallLv2:gui-uri:
265 *
266 * The GUI's uri name.
267 *
268 * Since: 3.0.0
269 */
270 param_spec = g_param_spec_string("gui-uri",
271 i18n_pspec("the gui-uri"),
272 i18n_pspec("The gui-uri's string representation"),
273 NULL,
274 G_PARAM_READABLE | G_PARAM_WRITABLE);
275 g_object_class_install_property(gobject,
276 PROP_GUI_URI,
277 param_spec);
278
279 /* AgsMachine */
280 machine = (AgsMachineClass *) lv2_bridge;
281
282 machine->map_recall = ags_lv2_bridge_map_recall;
283 }
284
285 void
ags_lv2_bridge_connectable_interface_init(AgsConnectableInterface * connectable)286 ags_lv2_bridge_connectable_interface_init(AgsConnectableInterface *connectable)
287 {
288 ags_lv2_bridge_parent_connectable_interface = g_type_interface_peek_parent(connectable);
289
290 connectable->is_ready = NULL;
291 connectable->is_connected = NULL;
292 connectable->connect = ags_lv2_bridge_connect;
293 connectable->disconnect = ags_lv2_bridge_disconnect;
294 }
295
296 void
ags_lv2_bridge_init(AgsLv2Bridge * lv2_bridge)297 ags_lv2_bridge_init(AgsLv2Bridge *lv2_bridge)
298 {
299 GtkGrid *grid;
300 GtkMenuItem *item;
301
302 AgsAudio *audio;
303
304 g_signal_connect_after((GObject *) lv2_bridge, "parent-set",
305 G_CALLBACK(ags_lv2_bridge_parent_set_callback), (gpointer) lv2_bridge);
306
307 if(ags_lv2_bridge_lv2ui_handle == NULL){
308 ags_lv2_bridge_lv2ui_handle = g_hash_table_new_full(g_direct_hash, g_direct_equal,
309 NULL,
310 NULL);
311 }
312
313 if(ags_lv2_bridge_lv2ui_idle == NULL){
314 ags_lv2_bridge_lv2ui_idle = g_hash_table_new_full(g_direct_hash, g_direct_equal,
315 NULL,
316 NULL);
317 }
318
319 audio = AGS_MACHINE(lv2_bridge)->audio;
320 ags_audio_set_flags(audio, (AGS_AUDIO_SYNC));
321 g_object_set(audio,
322 "min-audio-channels", 1,
323 "min-output-pads", 1,
324 "min-input-pads", 1,
325 NULL);
326
327 g_signal_connect_after(G_OBJECT(lv2_bridge), "resize-audio-channels",
328 G_CALLBACK(ags_lv2_bridge_resize_audio_channels), NULL);
329
330 g_signal_connect_after(G_OBJECT(lv2_bridge), "resize-pads",
331 G_CALLBACK(ags_lv2_bridge_resize_pads), NULL);
332
333 lv2_bridge->flags = 0;
334
335 lv2_bridge->name = NULL;
336
337 lv2_bridge->version = AGS_LV2_BRIDGE_DEFAULT_VERSION;
338 lv2_bridge->build_id = AGS_LV2_BRIDGE_DEFAULT_BUILD_ID;
339
340 lv2_bridge->xml_type = "ags-lv2-bridge";
341
342 lv2_bridge->mapped_output_pad = 0;
343 lv2_bridge->mapped_input_pad = 0;
344
345 lv2_bridge->lv2_play_container = ags_recall_container_new();
346 lv2_bridge->lv2_recall_container = ags_recall_container_new();
347
348 lv2_bridge->envelope_play_container = ags_recall_container_new();
349 lv2_bridge->envelope_recall_container = ags_recall_container_new();
350
351 lv2_bridge->buffer_play_container = ags_recall_container_new();
352 lv2_bridge->buffer_recall_container = ags_recall_container_new();
353
354 lv2_bridge->filename = NULL;
355 lv2_bridge->effect = NULL;
356 lv2_bridge->uri = NULL;
357 lv2_bridge->uri_index = 0;
358
359 lv2_bridge->has_midi = FALSE;
360
361 lv2_bridge->lv2_plugin = NULL;
362
363 lv2_bridge->lv2_descriptor = NULL;
364 lv2_bridge->lv2_handle = NULL;
365 lv2_bridge->port_value = NULL;
366
367 lv2_bridge->has_gui = FALSE;
368 lv2_bridge->gui_filename = NULL;
369 lv2_bridge->gui_uri = NULL;
370
371 lv2_bridge->lv2ui_plugin = NULL;
372
373 lv2_bridge->ui_descriptor = NULL;
374
375 lv2_bridge->ui_feature = (LV2_Feature **) malloc(3 * sizeof(LV2_Feature *));
376
377 lv2_bridge->ui_feature[0] = (LV2_Feature *) malloc(sizeof(LV2_Feature));
378 lv2_bridge->ui_feature[0]->data = NULL;
379
380 lv2_bridge->ui_feature[1] = (LV2_Feature *) malloc(sizeof(LV2_Feature));
381 lv2_bridge->ui_feature[1]->data = NULL;
382
383 lv2_bridge->ui_feature[2] = NULL;
384
385 lv2_bridge->ui_handle = NULL;
386
387 /**/
388 lv2_bridge->vbox = (GtkBox *) gtk_box_new(GTK_ORIENTATION_VERTICAL,
389 0);
390 gtk_container_add((GtkContainer *) gtk_bin_get_child((GtkBin *) lv2_bridge),
391 (GtkWidget *) lv2_bridge->vbox);
392
393 lv2_bridge->program = NULL;
394 lv2_bridge->preset = NULL;
395
396 /* effect bridge */
397 AGS_MACHINE(lv2_bridge)->bridge = (GtkContainer *) ags_effect_bridge_new(audio);
398 gtk_box_pack_start(lv2_bridge->vbox,
399 (GtkWidget *) AGS_MACHINE(lv2_bridge)->bridge,
400 FALSE, FALSE,
401 0);
402
403 grid = (GtkGrid *) gtk_grid_new();
404 gtk_box_pack_start((GtkBox *) AGS_EFFECT_BRIDGE(AGS_MACHINE(lv2_bridge)->bridge),
405 (GtkWidget *) grid,
406 FALSE, FALSE,
407 0);
408
409 AGS_EFFECT_BRIDGE(AGS_MACHINE(lv2_bridge)->bridge)->bulk_input = (GtkWidget *) ags_effect_bulk_new(audio,
410 AGS_TYPE_INPUT);
411 AGS_EFFECT_BULK(AGS_EFFECT_BRIDGE(AGS_MACHINE(lv2_bridge)->bridge)->bulk_input)->flags |= (AGS_EFFECT_BULK_HIDE_BUTTONS |
412 AGS_EFFECT_BULK_HIDE_ENTRIES |
413 AGS_EFFECT_BULK_SHOW_LABELS);
414
415 gtk_widget_set_valign((GtkWidget *) AGS_EFFECT_BRIDGE(AGS_MACHINE(lv2_bridge)->bridge)->bulk_input,
416 GTK_ALIGN_FILL);
417 gtk_widget_set_halign((GtkWidget *) AGS_EFFECT_BRIDGE(AGS_MACHINE(lv2_bridge)->bridge)->bulk_input,
418 GTK_ALIGN_FILL);
419
420 gtk_grid_attach(grid,
421 (GtkWidget *) AGS_EFFECT_BRIDGE(AGS_MACHINE(lv2_bridge)->bridge)->bulk_input,
422 0, 0,
423 1, 1);
424
425 /* lv2 menu */
426 item = (GtkMenuItem *) gtk_menu_item_new_with_label("Lv2");
427 gtk_menu_shell_append((GtkMenuShell *) AGS_MACHINE(lv2_bridge)->popup,
428 (GtkWidget *) item);
429 gtk_widget_show((GtkWidget *) item);
430
431 lv2_bridge->lv2_menu = (GtkMenu *) gtk_menu_new();
432 gtk_menu_item_set_submenu((GtkMenuItem *) item,
433 (GtkWidget *) lv2_bridge->lv2_menu);
434
435 item = (GtkMenuItem *) gtk_menu_item_new_with_label(i18n("show GUI"));
436 gtk_menu_shell_append((GtkMenuShell *) lv2_bridge->lv2_menu,
437 (GtkWidget *) item);
438
439 gtk_widget_show_all((GtkWidget *) lv2_bridge->lv2_menu);
440
441 /* plugin widget */
442 lv2_bridge->lv2_gui = NULL;
443 lv2_bridge->ui_widget = NULL;
444
445 lv2_bridge->lv2_window = NULL;
446 }
447
448 void
ags_lv2_bridge_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)449 ags_lv2_bridge_set_property(GObject *gobject,
450 guint prop_id,
451 const GValue *value,
452 GParamSpec *param_spec)
453 {
454 AgsLv2Bridge *lv2_bridge;
455
456 lv2_bridge = AGS_LV2_BRIDGE(gobject);
457
458 switch(prop_id){
459 case PROP_FILENAME:
460 {
461 gchar *filename;
462
463 filename = g_value_get_string(value);
464
465 if(filename == lv2_bridge->filename){
466 return;
467 }
468
469 if(lv2_bridge->filename != NULL){
470 g_free(lv2_bridge->filename);
471 }
472
473 if(filename != NULL){
474 if(!g_file_test(filename,
475 G_FILE_TEST_EXISTS)){
476 AgsWindow *window;
477
478 window = (AgsWindow *) gtk_widget_get_toplevel((GtkWidget *) lv2_bridge);
479
480 ags_window_show_error(window,
481 g_strdup_printf("Plugin file not present %s",
482 filename));
483 }
484 }
485
486 lv2_bridge->filename = g_strdup(filename);
487 }
488 break;
489 case PROP_EFFECT:
490 {
491 gchar *effect;
492
493 effect = g_value_get_string(value);
494
495 if(effect == lv2_bridge->effect){
496 return;
497 }
498
499 if(lv2_bridge->effect != NULL){
500 g_free(lv2_bridge->effect);
501 }
502
503 lv2_bridge->effect = g_strdup(effect);
504 }
505 break;
506 case PROP_URI:
507 {
508 gchar *uri;
509
510 uri = g_value_get_string(value);
511
512 if(uri == lv2_bridge->uri){
513 return;
514 }
515
516 if(lv2_bridge->uri != NULL){
517 g_free(lv2_bridge->uri);
518 }
519
520 lv2_bridge->uri = g_strdup(uri);
521 }
522 break;
523 case PROP_INDEX:
524 {
525 unsigned long uri_index;
526
527 uri_index = g_value_get_ulong(value);
528
529 if(uri_index == lv2_bridge->uri_index){
530 return;
531 }
532
533 lv2_bridge->uri_index = uri_index;
534 }
535 break;
536 case PROP_HAS_MIDI:
537 {
538 gboolean has_midi;
539
540 has_midi = g_value_get_boolean(value);
541
542 if(lv2_bridge->has_midi == has_midi){
543 return;
544 }
545
546 lv2_bridge->has_midi = has_midi;
547 }
548 break;
549 case PROP_HAS_GUI:
550 {
551 gboolean has_gui;
552
553 has_gui = g_value_get_boolean(value);
554
555 if(lv2_bridge->has_gui == has_gui){
556 return;
557 }
558
559 lv2_bridge->has_gui = has_gui;
560 }
561 break;
562 case PROP_GUI_FILENAME:
563 {
564 gchar *gui_filename;
565
566 gui_filename = g_value_get_string(value);
567
568 if(lv2_bridge->gui_filename == gui_filename){
569 return;
570 }
571
572 lv2_bridge->gui_filename = g_strdup(gui_filename);
573 }
574 break;
575 case PROP_GUI_URI:
576 {
577 gchar *gui_uri;
578
579 gui_uri = g_value_get_string(value);
580
581 if(gui_uri == lv2_bridge->gui_uri){
582 return;
583 }
584
585 if(lv2_bridge->gui_uri != NULL){
586 g_free(lv2_bridge->gui_uri);
587 }
588
589 lv2_bridge->gui_uri = g_strdup(gui_uri);
590 }
591 break;
592 default:
593 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
594 break;
595 }
596 }
597
598 void
ags_lv2_bridge_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)599 ags_lv2_bridge_get_property(GObject *gobject,
600 guint prop_id,
601 GValue *value,
602 GParamSpec *param_spec)
603 {
604 AgsLv2Bridge *lv2_bridge;
605
606 lv2_bridge = AGS_LV2_BRIDGE(gobject);
607
608 switch(prop_id){
609 case PROP_FILENAME:
610 {
611 g_value_set_string(value, lv2_bridge->filename);
612 }
613 break;
614 case PROP_EFFECT:
615 {
616 g_value_set_string(value, lv2_bridge->effect);
617 }
618 break;
619 case PROP_URI:
620 {
621 g_value_set_string(value, lv2_bridge->uri);
622 }
623 break;
624 case PROP_INDEX:
625 {
626 g_value_set_ulong(value, lv2_bridge->uri_index);
627 }
628 break;
629 case PROP_HAS_MIDI:
630 {
631 g_value_set_boolean(value, lv2_bridge->has_midi);
632 }
633 break;
634 case PROP_HAS_GUI:
635 {
636 g_value_set_boolean(value, lv2_bridge->has_gui);
637 }
638 break;
639 case PROP_GUI_FILENAME:
640 {
641 g_value_set_string(value, lv2_bridge->gui_filename);
642 }
643 break;
644 case PROP_GUI_URI:
645 {
646 g_value_set_string(value, lv2_bridge->gui_uri);
647 }
648 break;
649 default:
650 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
651 break;
652 }
653 }
654
655 void
ags_lv2_bridge_finalize(GObject * gobject)656 ags_lv2_bridge_finalize(GObject *gobject)
657 {
658 AgsLv2Bridge *lv2_bridge;
659
660 lv2_bridge = AGS_LV2_BRIDGE(gobject);
661
662 g_object_disconnect(G_OBJECT(lv2_bridge),
663 "any_signal::resize-audio-channels",
664 G_CALLBACK(ags_lv2_bridge_resize_audio_channels),
665 NULL,
666 "any_signal::resize-pads",
667 G_CALLBACK(ags_lv2_bridge_resize_pads),
668 NULL,
669 NULL);
670
671 /* lv2 plugin */
672 if(lv2_bridge->lv2_plugin != NULL){
673 g_object_unref(lv2_bridge->lv2_plugin);
674 }
675
676 /* lv2ui plugin */
677 if(lv2_bridge->lv2ui_plugin != NULL){
678 g_object_unref(lv2_bridge->lv2ui_plugin);
679 }
680
681 /* plugin widget */
682 if(lv2_bridge->ui_handle != NULL){
683 lv2_bridge->ui_descriptor->cleanup(lv2_bridge->ui_handle[0]);
684
685 g_hash_table_remove(ags_lv2_bridge_lv2ui_handle,
686 lv2_bridge->ui_handle);
687
688 g_hash_table_remove(ags_lv2_bridge_lv2ui_idle,
689 lv2_bridge->ui_handle);
690 }
691
692 if(lv2_bridge->lv2_window != NULL){
693 gtk_widget_destroy(lv2_bridge->lv2_window);
694 }
695
696 /* call parent */
697 G_OBJECT_CLASS(ags_lv2_bridge_parent_class)->finalize(gobject);
698 }
699
700 void
ags_lv2_bridge_connect(AgsConnectable * connectable)701 ags_lv2_bridge_connect(AgsConnectable *connectable)
702 {
703 AgsLv2Bridge *lv2_bridge;
704 AgsEffectBridge *effect_bridge;
705 AgsBulkMember *bulk_member;
706 GtkWidget *control;
707
708 GList *list, *list_start;
709
710 if((AGS_MACHINE_CONNECTED & (AGS_MACHINE(connectable)->flags)) != 0){
711 return;
712 }
713
714 ags_lv2_bridge_parent_connectable_interface->connect(connectable);
715
716 lv2_bridge = AGS_LV2_BRIDGE(connectable);
717
718 /* menu */
719 list =
720 list_start = gtk_container_get_children((GtkContainer *) lv2_bridge->lv2_menu);
721
722 g_signal_connect(G_OBJECT(list->data), "activate",
723 G_CALLBACK(ags_lv2_bridge_show_gui_callback), lv2_bridge);
724
725 g_list_free(list_start);
726
727 /* program */
728 if(lv2_bridge->program != NULL){
729 g_signal_connect_after(G_OBJECT(lv2_bridge->program), "changed",
730 G_CALLBACK(ags_lv2_bridge_program_changed_callback), lv2_bridge);
731 }
732
733 /* bulk member */
734 effect_bridge = AGS_EFFECT_BRIDGE(AGS_MACHINE(lv2_bridge)->bridge);
735
736 list =
737 list_start = gtk_container_get_children((GtkContainer *) AGS_EFFECT_BULK(effect_bridge->bulk_input)->grid);
738
739 while(list != NULL){
740 bulk_member = list->data;
741
742 control = gtk_bin_get_child(GTK_BIN(bulk_member));
743
744 if(bulk_member->widget_type == AGS_TYPE_DIAL){
745 g_signal_connect_after(GTK_WIDGET(control), "value-changed",
746 G_CALLBACK(ags_lv2_bridge_dial_changed_callback), lv2_bridge);
747 }else if(bulk_member->widget_type == GTK_TYPE_SCALE){
748 g_signal_connect_after(GTK_WIDGET(control), "value-changed",
749 G_CALLBACK(ags_lv2_bridge_scale_changed_callback), lv2_bridge);
750 }else if(bulk_member->widget_type == GTK_TYPE_SPIN_BUTTON){
751 g_signal_connect_after(GTK_WIDGET(control), "value-changed",
752 G_CALLBACK(ags_lv2_bridge_spin_button_changed_callback), lv2_bridge);
753 }else if(bulk_member->widget_type == GTK_TYPE_CHECK_BUTTON){
754 g_signal_connect_after(GTK_WIDGET(control), "clicked",
755 G_CALLBACK(ags_lv2_bridge_check_button_clicked_callback), lv2_bridge);
756 }else if(bulk_member->widget_type == GTK_TYPE_TOGGLE_BUTTON){
757 g_signal_connect_after(GTK_WIDGET(control), "clicked",
758 G_CALLBACK(ags_lv2_bridge_toggle_button_clicked_callback), lv2_bridge);
759 }else if(bulk_member->widget_type == GTK_TYPE_BUTTON){
760 g_signal_connect_after(GTK_WIDGET(control), "clicked",
761 G_CALLBACK(ags_lv2_bridge_button_clicked_callback), lv2_bridge);
762 }
763
764 list = list->next;
765 }
766
767 g_list_free(list_start);
768 }
769
770 void
ags_lv2_bridge_disconnect(AgsConnectable * connectable)771 ags_lv2_bridge_disconnect(AgsConnectable *connectable)
772 {
773 AgsLv2Bridge *lv2_bridge;
774 AgsEffectBridge *effect_bridge;
775 AgsBulkMember *bulk_member;
776 GtkWidget *control;
777
778 GList *list, *list_start;
779
780 if((AGS_MACHINE_CONNECTED & (AGS_MACHINE(connectable)->flags)) == 0){
781 return;
782 }
783
784 ags_lv2_bridge_parent_connectable_interface->disconnect(connectable);
785
786 lv2_bridge = AGS_LV2_BRIDGE(connectable);
787
788 /* menu */
789 list =
790 list_start = gtk_container_get_children((GtkContainer *) lv2_bridge->lv2_menu);
791
792 g_object_disconnect(G_OBJECT(list->data),
793 "any_signal::activate",
794 G_CALLBACK(ags_lv2_bridge_show_gui_callback),
795 lv2_bridge,
796 NULL);
797
798 g_list_free(list_start);
799
800 /* program */
801 if(lv2_bridge->program != NULL){
802 g_object_disconnect(G_OBJECT(lv2_bridge->program),
803 "any_signal::changed",
804 G_CALLBACK(ags_lv2_bridge_program_changed_callback),
805 lv2_bridge,
806 NULL);
807 }
808
809 /* bulk member */
810 effect_bridge = AGS_EFFECT_BRIDGE(AGS_MACHINE(lv2_bridge)->bridge);
811
812 list =
813 list_start = gtk_container_get_children((GtkContainer *) AGS_EFFECT_BULK(effect_bridge->bulk_input)->grid);
814
815 while(list != NULL){
816 bulk_member = list->data;
817
818 control = gtk_bin_get_child(GTK_BIN(bulk_member));
819
820 if(bulk_member->widget_type == AGS_TYPE_DIAL){
821 g_object_disconnect(GTK_WIDGET(control),
822 "any_signal::value-changed",
823 G_CALLBACK(ags_lv2_bridge_dial_changed_callback),
824 lv2_bridge,
825 NULL);
826 }else if(bulk_member->widget_type == GTK_TYPE_VSCALE){
827 g_object_disconnect(GTK_WIDGET(control),
828 "any_signal::value-changed",
829 G_CALLBACK(ags_lv2_bridge_scale_changed_callback),
830 lv2_bridge,
831 NULL);
832 }else if(bulk_member->widget_type == GTK_TYPE_HSCALE){
833 g_object_disconnect(GTK_WIDGET(control),
834 "any_signal::value-changed",
835 G_CALLBACK(ags_lv2_bridge_scale_changed_callback),
836 lv2_bridge,
837 NULL);
838 }else if(bulk_member->widget_type == GTK_TYPE_SPIN_BUTTON){
839 g_object_disconnect(GTK_WIDGET(control),
840 "any_signal::value-changed",
841 G_CALLBACK(ags_lv2_bridge_spin_button_changed_callback),
842 lv2_bridge,
843 NULL);
844 }else if(bulk_member->widget_type == GTK_TYPE_CHECK_BUTTON){
845 g_object_disconnect(GTK_WIDGET(control),
846 "any_signal::clicked",
847 G_CALLBACK(ags_lv2_bridge_check_button_clicked_callback),
848 lv2_bridge,
849 NULL);
850 }else if(bulk_member->widget_type == GTK_TYPE_TOGGLE_BUTTON){
851 g_object_disconnect(GTK_WIDGET(control),
852 "any_signal::clicked",
853 G_CALLBACK(ags_lv2_bridge_toggle_button_clicked_callback),
854 lv2_bridge,
855 NULL);
856 }else if(bulk_member->widget_type == GTK_TYPE_BUTTON){
857 g_object_disconnect(GTK_WIDGET(control),
858 "any_signal::clicked",
859 G_CALLBACK(ags_lv2_bridge_button_clicked_callback),
860 lv2_bridge,
861 NULL);
862 }
863
864 list = list->next;
865 }
866
867 g_list_free(list_start);
868 }
869
870 void
ags_lv2_bridge_resize_audio_channels(AgsMachine * machine,guint audio_channels,guint audio_channels_old,gpointer data)871 ags_lv2_bridge_resize_audio_channels(AgsMachine *machine,
872 guint audio_channels, guint audio_channels_old,
873 gpointer data)
874 {
875 AgsLv2Bridge *lv2_bridge;
876
877 lv2_bridge = (AgsLv2Bridge *) machine;
878
879 if(audio_channels > audio_channels_old){
880 /* recall */
881 if((AGS_MACHINE_MAPPED_RECALL & (machine->flags)) != 0){
882 ags_lv2_bridge_input_map_recall(lv2_bridge,
883 audio_channels_old,
884 0);
885
886 ags_lv2_bridge_output_map_recall(lv2_bridge,
887 audio_channels_old,
888 0);
889 }
890 }
891 }
892
893 void
ags_lv2_bridge_resize_pads(AgsMachine * machine,GType channel_type,guint pads,guint pads_old,gpointer data)894 ags_lv2_bridge_resize_pads(AgsMachine *machine, GType channel_type,
895 guint pads, guint pads_old,
896 gpointer data)
897 {
898 AgsLv2Bridge *lv2_bridge;
899
900 gboolean grow;
901
902 lv2_bridge = (AgsLv2Bridge *) machine;
903
904 if(pads_old < pads){
905 grow = TRUE;
906 }else{
907 grow = FALSE;
908 }
909
910 if(g_type_is_a(channel_type, AGS_TYPE_INPUT)){
911 if(grow){
912 /* recall */
913 if((AGS_MACHINE_MAPPED_RECALL & (machine->flags)) != 0){
914 ags_lv2_bridge_input_map_recall(lv2_bridge,
915 0,
916 pads_old);
917 }
918 }else{
919 lv2_bridge->mapped_input_pad = pads;
920 }
921 }else{
922 if(grow){
923 /* recall */
924 if((AGS_MACHINE_MAPPED_RECALL & (machine->flags)) != 0){
925 ags_lv2_bridge_output_map_recall(lv2_bridge,
926 0,
927 pads_old);
928 }
929 }else{
930 lv2_bridge->mapped_output_pad = pads;
931 }
932 }
933 }
934
935 void
ags_lv2_bridge_map_recall(AgsMachine * machine)936 ags_lv2_bridge_map_recall(AgsMachine *machine)
937 {
938 AgsNavigation *navigation;
939 AgsLv2Bridge *lv2_bridge;
940
941 AgsAudio *audio;
942
943 AgsApplicationContext *application_context;
944
945 GList *start_play, *start_recall;
946 GList *start_list, *list;
947
948 gint position;
949
950 if((AGS_MACHINE_MAPPED_RECALL & (machine->flags)) != 0 ||
951 (AGS_MACHINE_PREMAPPED_RECALL & (machine->flags)) != 0){
952 return;
953 }
954
955 application_context = ags_application_context_get_instance();
956
957 navigation = (AgsNavigation *) ags_ui_provider_get_navigation(AGS_UI_PROVIDER(application_context));
958
959 lv2_bridge = (AgsLv2Bridge *) machine;
960
961 audio = machine->audio;
962
963 position = 0;
964
965 /* add new controls */
966 ags_effect_bulk_add_plugin(AGS_EFFECT_BULK(AGS_EFFECT_BRIDGE(machine->bridge)->bulk_input),
967 NULL,
968 lv2_bridge->lv2_play_container, lv2_bridge->lv2_recall_container,
969 "ags-fx-lv2",
970 lv2_bridge->filename,
971 lv2_bridge->effect,
972 0, 0,
973 0, 0,
974 position,
975 (AGS_FX_FACTORY_ADD | AGS_FX_FACTORY_INPUT), 0);
976
977
978
979 if((AGS_MACHINE_IS_SYNTHESIZER & (machine->flags)) != 0){
980 start_play = ags_audio_get_play(audio);
981 start_recall = ags_audio_get_recall(audio);
982
983 list =
984 start_list = NULL;
985
986 if(start_play != NULL &&
987 start_recall != NULL){
988 list =
989 start_list = g_list_concat(start_play,
990 start_recall);
991 }
992
993 while((list = ags_recall_template_find_type(list, AGS_TYPE_FX_NOTATION_AUDIO)) != NULL){
994 AgsPort *port;
995
996 GValue value = G_VALUE_INIT;
997
998 /* loop */
999 port = NULL;
1000
1001 g_object_get(list->data,
1002 "loop", &port,
1003 NULL);
1004
1005 g_value_init(&value,
1006 G_TYPE_BOOLEAN);
1007
1008 g_value_set_boolean(&value,
1009 gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(navigation->loop)));
1010
1011 ags_port_safe_write(port,
1012 &value);
1013
1014 if(port != NULL){
1015 g_object_unref(port);
1016 }
1017
1018 /* loop start */
1019 port = NULL;
1020
1021 g_object_get(list->data,
1022 "loop-start", &port,
1023 NULL);
1024
1025 g_value_unset(&value);
1026 g_value_init(&value,
1027 G_TYPE_UINT64);
1028
1029 g_value_set_uint64(&value,
1030 16 * gtk_spin_button_get_value_as_int(navigation->loop_left_tact));
1031
1032 ags_port_safe_write(port,
1033 &value);
1034
1035 if(port != NULL){
1036 g_object_unref(port);
1037 }
1038
1039 /* loop end */
1040 port = NULL;
1041
1042 g_object_get(list->data,
1043 "loop-end", &port,
1044 NULL);
1045
1046 g_value_unset(&value);
1047 g_value_init(&value,
1048 G_TYPE_UINT64);
1049
1050 g_value_set_uint64(&value,
1051 16 * gtk_spin_button_get_value_as_int(navigation->loop_right_tact));
1052
1053 ags_port_safe_write(port,
1054 &value);
1055
1056 if(port != NULL){
1057 g_object_unref(port);
1058 }
1059
1060 /* iterate */
1061 list = list->next;
1062 }
1063
1064 g_list_free_full(start_list,
1065 (GDestroyNotify) g_object_unref);
1066
1067 /* ags-fx-envelope */
1068 start_recall = ags_fx_factory_create(audio,
1069 lv2_bridge->envelope_play_container, lv2_bridge->envelope_recall_container,
1070 "ags-fx-envelope",
1071 NULL,
1072 NULL,
1073 0, 0,
1074 0, 0,
1075 position,
1076 (AGS_FX_FACTORY_ADD | AGS_FX_FACTORY_INPUT), 0);
1077
1078 g_list_free_full(start_recall,
1079 (GDestroyNotify) g_object_unref);
1080
1081 /* ags-fx-buffer */
1082 start_recall = ags_fx_factory_create(audio,
1083 lv2_bridge->buffer_play_container, lv2_bridge->buffer_recall_container,
1084 "ags-fx-buffer",
1085 NULL,
1086 NULL,
1087 0, 0,
1088 0, 0,
1089 position,
1090 (AGS_FX_FACTORY_ADD | AGS_FX_FACTORY_INPUT), 0);
1091
1092 g_list_free_full(start_recall,
1093 (GDestroyNotify) g_object_unref);
1094 }
1095
1096 /* depending on destination */
1097 ags_lv2_bridge_input_map_recall(lv2_bridge,
1098 0,
1099 0);
1100
1101 /* depending on destination */
1102 ags_lv2_bridge_output_map_recall(lv2_bridge,
1103 0,
1104 0);
1105
1106 /* call parent */
1107 AGS_MACHINE_CLASS(ags_lv2_bridge_parent_class)->map_recall(machine);
1108 }
1109
1110 void
ags_lv2_bridge_input_map_recall(AgsLv2Bridge * lv2_bridge,guint audio_channel_start,guint input_pad_start)1111 ags_lv2_bridge_input_map_recall(AgsLv2Bridge *lv2_bridge,
1112 guint audio_channel_start,
1113 guint input_pad_start)
1114 {
1115 AgsAudio *audio;
1116
1117 GList *start_recall;
1118
1119 gint position;
1120 guint input_pads;
1121 guint audio_channels;
1122
1123 if(lv2_bridge->mapped_input_pad > input_pad_start){
1124 return;
1125 }
1126
1127 audio = AGS_MACHINE(lv2_bridge)->audio;
1128
1129 position = 0;
1130
1131 input_pads = 0;
1132 audio_channels = 0;
1133
1134 /* get some fields */
1135 g_object_get(audio,
1136 "input-pads", &input_pads,
1137 "audio-channels", &audio_channels,
1138 NULL);
1139
1140 /* add to effect bridge */
1141 ags_effect_bulk_add_plugin((AgsEffectBulk *) AGS_EFFECT_BRIDGE(AGS_MACHINE(lv2_bridge)->bridge)->bulk_input,
1142 NULL,
1143 lv2_bridge->lv2_play_container, lv2_bridge->lv2_recall_container,
1144 "ags-fx-lv2",
1145 lv2_bridge->filename,
1146 lv2_bridge->effect,
1147 audio_channel_start, audio_channels,
1148 input_pad_start, input_pads,
1149 position,
1150 (AGS_FX_FACTORY_REMAP | AGS_FX_FACTORY_INPUT), 0);
1151
1152 /* source */
1153 if((AGS_MACHINE_IS_SYNTHESIZER & (AGS_MACHINE(lv2_bridge)->flags)) != 0){
1154 /* ags-fx-envelope */
1155 start_recall = ags_fx_factory_create(audio,
1156 lv2_bridge->envelope_play_container, lv2_bridge->envelope_recall_container,
1157 "ags-fx-envelope",
1158 NULL,
1159 NULL,
1160 audio_channel_start, audio_channels,
1161 input_pad_start, input_pads,
1162 position,
1163 (AGS_FX_FACTORY_REMAP | AGS_FX_FACTORY_INPUT), 0);
1164
1165 g_list_free_full(start_recall,
1166 (GDestroyNotify) g_object_unref);
1167
1168 /* ags-fx-buffer */
1169 start_recall = ags_fx_factory_create(audio,
1170 lv2_bridge->buffer_play_container, lv2_bridge->buffer_recall_container,
1171 "ags-fx-buffer",
1172 NULL,
1173 NULL,
1174 audio_channel_start, audio_channels,
1175 input_pad_start, input_pads,
1176 position,
1177 (AGS_FX_FACTORY_REMAP | AGS_FX_FACTORY_INPUT), 0);
1178
1179 g_list_free_full(start_recall,
1180 (GDestroyNotify) g_object_unref);
1181 }
1182
1183 lv2_bridge->mapped_input_pad = input_pads;
1184 }
1185
1186 void
ags_lv2_bridge_output_map_recall(AgsLv2Bridge * lv2_bridge,guint audio_channel_start,guint output_pad_start)1187 ags_lv2_bridge_output_map_recall(AgsLv2Bridge *lv2_bridge,
1188 guint audio_channel_start,
1189 guint output_pad_start)
1190 {
1191 AgsAudio *audio;
1192
1193 guint output_pads;
1194
1195 if(lv2_bridge->mapped_output_pad > output_pad_start){
1196 return;
1197 }
1198
1199 audio = AGS_MACHINE(lv2_bridge)->audio;
1200
1201 output_pads = 0;
1202
1203 /* get some fields */
1204 g_object_get(audio,
1205 "output-pads", &output_pads,
1206 NULL);
1207
1208 lv2_bridge->mapped_output_pad = output_pads;
1209 }
1210
1211 void
ags_lv2_bridge_load_program(AgsLv2Bridge * lv2_bridge)1212 ags_lv2_bridge_load_program(AgsLv2Bridge *lv2_bridge)
1213 {
1214 AgsLv2Plugin *lv2_plugin;
1215
1216 LV2_Descriptor *plugin_descriptor;
1217 LV2_Programs_Interface *program_interface;
1218
1219 /* retrieve lv2 plugin */
1220 lv2_plugin = lv2_bridge->lv2_plugin;
1221
1222 if(lv2_plugin == NULL){
1223 lv2_plugin =
1224 lv2_bridge->lv2_plugin = ags_lv2_manager_find_lv2_plugin(ags_lv2_manager_get_instance(),
1225 lv2_bridge->filename,
1226 lv2_bridge->effect);
1227 g_object_ref(lv2_plugin);
1228
1229 lv2_bridge->lv2_descriptor = AGS_BASE_PLUGIN(lv2_plugin)->plugin_descriptor;
1230 }
1231
1232 if(lv2_plugin == NULL){
1233 return;
1234 }
1235
1236 plugin_descriptor = lv2_bridge->lv2_descriptor;
1237
1238 if(plugin_descriptor != NULL &&
1239 plugin_descriptor->extension_data != NULL &&
1240 (program_interface = plugin_descriptor->extension_data(LV2_PROGRAMS__Interface)) != NULL){
1241 GtkListStore *model;
1242
1243 GtkTreeIter iter;
1244
1245 LV2_Program_Descriptor *program_descriptor;
1246
1247 uint32_t i;
1248
1249 if(lv2_bridge->lv2_handle == NULL){
1250 guint samplerate;
1251 guint buffer_size;
1252
1253 g_object_get(AGS_MACHINE(lv2_bridge)->audio,
1254 "samplerate", &samplerate,
1255 "buffer-size", &buffer_size,
1256 NULL);
1257
1258 lv2_bridge->lv2_handle = ags_base_plugin_instantiate((AgsBasePlugin *) lv2_plugin,
1259 samplerate, buffer_size);
1260 }
1261
1262 if(lv2_bridge->lv2_handle != NULL){
1263 if(lv2_bridge->port_value == NULL){
1264 GList *start_plugin_port, *plugin_port;
1265
1266 guint port_count;
1267
1268 g_object_get(lv2_plugin,
1269 "plugin-port", &start_plugin_port,
1270 NULL);
1271
1272 plugin_port = start_plugin_port;
1273 port_count = g_list_length(start_plugin_port);
1274
1275 if(port_count > 0){
1276 lv2_bridge->port_value = (float *) malloc(port_count * sizeof(float));
1277 }
1278
1279 while(plugin_port != NULL){
1280 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_CONTROL)){
1281 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_INPUT)){
1282 plugin_descriptor->connect_port(lv2_bridge->lv2_handle[0],
1283 AGS_PLUGIN_PORT(plugin_port->data)->port_index,
1284 &(lv2_bridge->port_value[AGS_PLUGIN_PORT(plugin_port->data)->port_index]));
1285 }
1286 }
1287
1288 /* iterate */
1289 plugin_port = plugin_port->next;
1290 }
1291
1292 g_list_free_full(start_plugin_port,
1293 g_object_unref);
1294 }
1295
1296 if(lv2_bridge->program == NULL){
1297 GtkBox *hbox;
1298 GtkLabel *label;
1299
1300 /* program */
1301 hbox = (GtkBox *) gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
1302 0);
1303 gtk_box_pack_start(lv2_bridge->vbox,
1304 (GtkWidget *) hbox,
1305 FALSE, FALSE,
1306 0);
1307 gtk_box_reorder_child(lv2_bridge->vbox,
1308 (GtkWidget *) hbox,
1309 0);
1310
1311 label = (GtkLabel *) gtk_label_new(i18n("program"));
1312 gtk_box_pack_start(hbox,
1313 (GtkWidget *) label,
1314 FALSE, FALSE,
1315 0);
1316
1317 lv2_bridge->program = (GtkComboBoxText *) gtk_combo_box_text_new();
1318 gtk_box_pack_start(hbox,
1319 (GtkWidget *) lv2_bridge->program,
1320 FALSE, FALSE,
1321 0);
1322
1323 if((AGS_MACHINE_CONNECTED & (AGS_MACHINE(lv2_bridge)->flags)) != 0){
1324 g_signal_connect_after(G_OBJECT(lv2_bridge->program), "changed",
1325 G_CALLBACK(ags_lv2_bridge_program_changed_callback), lv2_bridge);
1326 }
1327
1328 model = gtk_list_store_new(3,
1329 G_TYPE_STRING,
1330 G_TYPE_ULONG,
1331 G_TYPE_ULONG);
1332
1333 gtk_combo_box_set_model(GTK_COMBO_BOX(lv2_bridge->program),
1334 GTK_TREE_MODEL(model));
1335 }else{
1336 model = GTK_LIST_STORE(gtk_combo_box_get_model(GTK_COMBO_BOX(lv2_bridge->program)));
1337
1338 gtk_list_store_clear(GTK_LIST_STORE(model));
1339 }
1340
1341 for(i = 0; (program_descriptor = program_interface->get_program(lv2_bridge->lv2_handle[0], i)) != NULL; i++){
1342 gtk_list_store_append(model, &iter);
1343 gtk_list_store_set(model, &iter,
1344 0, program_descriptor->name,
1345 1, program_descriptor->bank,
1346 2, program_descriptor->program,
1347 -1);
1348 }
1349 }
1350 }
1351 }
1352
1353 void
ags_lv2_bridge_load_preset(AgsLv2Bridge * lv2_bridge)1354 ags_lv2_bridge_load_preset(AgsLv2Bridge *lv2_bridge)
1355 {
1356 GtkBox *hbox;
1357 GtkLabel *label;
1358
1359 AgsLv2Plugin *lv2_plugin;
1360
1361 GList *list;
1362
1363 /* retrieve lv2 plugin */
1364 lv2_plugin = lv2_bridge->lv2_plugin;
1365
1366 if(lv2_plugin == NULL){
1367 lv2_plugin =
1368 lv2_bridge->lv2_plugin = ags_lv2_manager_find_lv2_plugin(ags_lv2_manager_get_instance(),
1369 lv2_bridge->filename,
1370 lv2_bridge->effect);
1371 g_object_ref(lv2_plugin);
1372
1373 lv2_bridge->lv2_descriptor = AGS_BASE_PLUGIN(lv2_plugin)->plugin_descriptor;
1374 }
1375
1376 if(lv2_plugin == NULL){
1377 return;
1378 }
1379
1380 /* preset */
1381 hbox = (GtkBox *) gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
1382 0);
1383 gtk_box_pack_start(lv2_bridge->vbox,
1384 (GtkWidget *) hbox,
1385 FALSE, FALSE,
1386 0);
1387 gtk_box_reorder_child(lv2_bridge->vbox,
1388 (GtkWidget *) hbox,
1389 0);
1390
1391 label = (GtkLabel *) gtk_label_new(i18n("preset"));
1392 gtk_box_pack_start(hbox,
1393 (GtkWidget *) label,
1394 FALSE, FALSE,
1395 0);
1396
1397 lv2_bridge->preset = (GtkComboBoxText *) gtk_combo_box_text_new();
1398 gtk_box_pack_start(hbox,
1399 (GtkWidget *) lv2_bridge->preset,
1400 FALSE, FALSE,
1401 0);
1402
1403 /* preset */
1404 list = lv2_plugin->preset;
1405
1406 while(list != NULL){
1407 if(AGS_LV2_PRESET(list->data)->preset_label != NULL){
1408 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(lv2_bridge->preset),
1409 AGS_LV2_PRESET(list->data)->preset_label);
1410 }
1411
1412 list = list->next;
1413 }
1414
1415 gtk_widget_show_all((GtkWidget *) hbox);
1416
1417 /* connect preset */
1418 g_signal_connect_after(G_OBJECT(lv2_bridge->preset), "changed",
1419 G_CALLBACK(ags_lv2_bridge_preset_changed_callback), lv2_bridge);
1420 }
1421
1422 void
ags_lv2_bridge_load_midi(AgsLv2Bridge * lv2_bridge)1423 ags_lv2_bridge_load_midi(AgsLv2Bridge *lv2_bridge)
1424 {
1425 //TODO:JK: implement me
1426 }
1427
1428 void
ags_lv2_bridge_load_gui(AgsLv2Bridge * lv2_bridge)1429 ags_lv2_bridge_load_gui(AgsLv2Bridge *lv2_bridge)
1430 {
1431 AgsLv2Plugin *lv2_plugin;
1432 AgsLv2uiPlugin *lv2ui_plugin;
1433
1434 GList *list;
1435
1436 /* retrieve lv2 plugin */
1437 lv2_plugin = lv2_bridge->lv2_plugin;
1438
1439 if(lv2_plugin == NULL){
1440 lv2_plugin =
1441 lv2_bridge->lv2_plugin = ags_lv2_manager_find_lv2_plugin(ags_lv2_manager_get_instance(),
1442 lv2_bridge->filename,
1443 lv2_bridge->effect);
1444 g_object_ref(lv2_plugin);
1445
1446 lv2_bridge->lv2_descriptor = AGS_BASE_PLUGIN(lv2_plugin)->plugin_descriptor;
1447 }
1448
1449 if(lv2_plugin == NULL ||
1450 lv2_plugin->ui_uri == NULL){
1451 return;
1452 }
1453
1454 /* retrieve lv2ui plugin */
1455 lv2ui_plugin = lv2_bridge->lv2ui_plugin;
1456
1457 if(lv2ui_plugin == NULL){
1458 list = ags_lv2ui_plugin_find_gui_uri(ags_lv2ui_manager_get_instance()->lv2ui_plugin,
1459 lv2_plugin->ui_uri);
1460
1461 if(list == NULL){
1462 return;
1463 }
1464
1465 lv2ui_plugin =
1466 lv2_bridge->lv2ui_plugin = list->data;
1467 g_object_ref(lv2ui_plugin);
1468
1469 lv2_bridge->ui_descriptor = AGS_BASE_PLUGIN(lv2ui_plugin)->ui_plugin_descriptor;
1470 }
1471
1472 #ifdef AGS_DEBUG
1473 g_message("ui filename - %s, %s", AGS_BASE_PLUGIN(lv2ui_plugin)->ui_filename, lv2_plugin->ui_uri);
1474 #endif
1475
1476 /* apply ui */
1477 g_object_set(lv2_bridge,
1478 "has-gui", TRUE,
1479 "gui-uri", lv2_plugin->ui_uri,
1480 "gui-filename", AGS_BASE_PLUGIN(lv2ui_plugin)->ui_filename,
1481 NULL);
1482 }
1483
1484 void
ags_lv2_bridge_load(AgsLv2Bridge * lv2_bridge)1485 ags_lv2_bridge_load(AgsLv2Bridge *lv2_bridge)
1486 {
1487 AgsLv2Plugin *lv2_plugin;
1488
1489 guint samplerate;
1490 guint buffer_size;
1491
1492 /* retrieve lv2 plugin */
1493 lv2_plugin = lv2_bridge->lv2_plugin;
1494
1495 if(lv2_plugin == NULL){
1496 lv2_plugin =
1497 lv2_bridge->lv2_plugin = ags_lv2_manager_find_lv2_plugin(ags_lv2_manager_get_instance(),
1498 lv2_bridge->filename,
1499 lv2_bridge->effect);
1500 g_object_ref(lv2_plugin);
1501
1502 lv2_bridge->lv2_descriptor = AGS_BASE_PLUGIN(lv2_plugin)->plugin_descriptor;
1503 }
1504
1505 if(lv2_plugin == NULL){
1506 return;
1507 }
1508
1509 /* URI */
1510 g_object_set(lv2_bridge,
1511 "uri", lv2_plugin->uri,
1512 NULL);
1513
1514 /* samplerate and buffer size */
1515 samplerate = ags_soundcard_helper_config_get_samplerate(ags_config_get_instance());
1516 buffer_size = ags_soundcard_helper_config_get_buffer_size(ags_config_get_instance());
1517
1518 /* program */
1519 lv2_bridge->lv2_handle = ags_base_plugin_instantiate((AgsBasePlugin *) lv2_plugin,
1520 samplerate, buffer_size);
1521
1522 if((AGS_LV2_PLUGIN_HAS_PROGRAM_INTERFACE & (lv2_plugin->flags)) != 0){
1523 ags_lv2_bridge_load_program(lv2_bridge);
1524 }
1525
1526 /* preset */
1527 if(lv2_plugin->preset != NULL){
1528 ags_lv2_bridge_load_preset(lv2_bridge);
1529 }
1530
1531 /* load gui */
1532 ags_lv2_bridge_load_gui(lv2_bridge);
1533 }
1534
1535 /**
1536 * ags_lv2_bridge_lv2ui_idle_timeout:
1537 * @widget: LV2UI_Handle
1538 *
1539 * Idle lv2 ui.
1540 *
1541 * Returns: %TRUE if proceed with redraw, otherwise %FALSE
1542 *
1543 * Since: 3.0.0
1544 */
1545 gboolean
ags_lv2_bridge_lv2ui_idle_timeout(GtkWidget * widget)1546 ags_lv2_bridge_lv2ui_idle_timeout(GtkWidget *widget)
1547 {
1548 AgsLv2Bridge *lv2_bridge;
1549
1550 AgsLv2uiPlugin *lv2ui_plugin;
1551
1552 int retval;
1553
1554 /* retrieve lv2ui plugin */
1555 if((lv2_bridge = g_hash_table_lookup(ags_lv2_bridge_lv2ui_idle,
1556 widget)) != NULL){
1557 lv2ui_plugin = lv2_bridge->lv2ui_plugin;
1558
1559 if(lv2ui_plugin->feature != NULL &&
1560 lv2ui_plugin->feature[0]->data != NULL){
1561 retval = ((LV2UI_Idle_Interface *) lv2ui_plugin->feature[0]->data)->idle(lv2_bridge->ui_handle[0]);
1562
1563 if(retval != 0){
1564 g_hash_table_remove(ags_lv2_bridge_lv2ui_handle,
1565 lv2_bridge->ui_handle);
1566
1567 lv2_bridge->ui_handle = NULL;
1568
1569 return(FALSE);
1570 }
1571 }
1572
1573 return(TRUE);
1574 }else{
1575 return(FALSE);
1576 }
1577 }
1578
1579 /**
1580 * ags_lv2_bridge_new:
1581 * @soundcard: the assigned soundcard.
1582 * @filename: the plugin.so
1583 * @effect: the effect
1584 *
1585 * Create a new instance of #AgsLv2Bridge
1586 *
1587 * Returns: the new #AgsLv2Bridge
1588 *
1589 * Since: 3.0.0
1590 */
1591 AgsLv2Bridge*
ags_lv2_bridge_new(GObject * soundcard,gchar * filename,gchar * effect)1592 ags_lv2_bridge_new(GObject *soundcard,
1593 gchar *filename,
1594 gchar *effect)
1595 {
1596 AgsLv2Bridge *lv2_bridge;
1597
1598 lv2_bridge = (AgsLv2Bridge *) g_object_new(AGS_TYPE_LV2_BRIDGE,
1599 NULL);
1600
1601 g_object_set(AGS_MACHINE(lv2_bridge)->audio,
1602 "output-soundcard", soundcard,
1603 NULL);
1604
1605 g_object_set(lv2_bridge,
1606 "filename", filename,
1607 "effect", effect,
1608 NULL);
1609
1610 return(lv2_bridge);
1611 }
1612