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