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