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/ags_effect_bulk.h>
21 #include <ags/X/ags_effect_bulk_callbacks.h>
22
23 #include <ags/X/ags_ui_provider.h>
24 #include <ags/X/ags_window.h>
25 #include <ags/X/ags_plugin_browser.h>
26 #include <ags/X/ags_bulk_member.h>
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/types.h>
32 #include <unistd.h>
33
34 #include <ladspa.h>
35 #include <dssi.h>
36 #include <lv2.h>
37
38 #include <ags/i18n.h>
39
40 void ags_effect_bulk_class_init(AgsEffectBulkClass *effect_bulk);
41 void ags_effect_bulk_connectable_interface_init(AgsConnectableInterface *connectable);
42 void ags_effect_bulk_init(AgsEffectBulk *effect_bulk);
43 void ags_effect_bulk_set_property(GObject *gobject,
44 guint prop_id,
45 const GValue *value,
46 GParamSpec *param_spec);
47 void ags_effect_bulk_get_property(GObject *gobject,
48 guint prop_id,
49 GValue *value,
50 GParamSpec *param_spec);
51 void ags_effect_bulk_dispose(GObject *gobject);
52 void ags_effect_bulk_finalize(GObject *gobject);
53
54 void ags_effect_bulk_connect(AgsConnectable *connectable);
55 void ags_effect_bulk_disconnect(AgsConnectable *connectable);
56
57 void ags_effect_bulk_show(GtkWidget *widget);
58
59 void ags_effect_bulk_add_ladspa_plugin(AgsEffectBulk *effect_bulk,
60 GList *control_type_name,
61 AgsRecallContainer *play_container, AgsRecallContainer *recall_container,
62 gchar *plugin_name,
63 gchar *filename,
64 gchar *effect,
65 guint start_audio_channel, guint stop_audio_channel,
66 guint start_pad, guint stop_pad,
67 gint position,
68 guint create_flags, guint recall_flags);
69 void ags_effect_bulk_add_dssi_plugin(AgsEffectBulk *effect_bulk,
70 GList *control_type_name,
71 AgsRecallContainer *play_container, AgsRecallContainer *recall_container,
72 gchar *plugin_name,
73 gchar *filename,
74 gchar *effect,
75 guint start_audio_channel, guint stop_audio_channel,
76 guint start_pad, guint stop_pad,
77 gint position,
78 guint create_flags, guint recall_flags);
79 void ags_effect_bulk_add_lv2_plugin(AgsEffectBulk *effect_bulk,
80 GList *control_type_name,
81 AgsRecallContainer *play_container, AgsRecallContainer *recall_container,
82 gchar *plugin_name,
83 gchar *filename,
84 gchar *effect,
85 guint start_audio_channel, guint stop_audio_channel,
86 guint start_pad, guint stop_pad,
87 gint position,
88 guint create_flags, guint recall_flags);
89 void ags_effect_bulk_real_add_plugin(AgsEffectBulk *effect_bulk,
90 GList *control_type_name,
91 AgsRecallContainer *play_container, AgsRecallContainer *recall_container,
92 gchar *plugin_name,
93 gchar *filename,
94 gchar *effect,
95 guint start_audio_channel, guint stop_audio_channel,
96 guint start_pad, guint stop_pad,
97 gint position,
98 guint create_flags, guint recall_flags);
99 void ags_effect_bulk_real_remove_plugin(AgsEffectBulk *effect_bulk,
100 guint nth);
101
102 void ags_effect_bulk_real_resize_audio_channels(AgsEffectBulk *effect_bulk,
103 guint new_size,
104 guint old_size);
105 void ags_effect_bulk_real_resize_pads(AgsEffectBulk *effect_bulk,
106 guint new_size,
107 guint old_size);
108 void ags_effect_bulk_real_map_recall(AgsEffectBulk *effect_bulk);
109 GList* ags_effect_bulk_real_find_port(AgsEffectBulk *effect_bulk);
110
111 /**
112 * SECTION:ags_effect_bulk
113 * @short_description: A composite widget to visualize a bunch of #AgsChannel
114 * @title: AgsEffectBulk
115 * @section_id:
116 * @include: ags/X/ags_effect_bulk.h
117 *
118 * #AgsEffectBulk is a composite widget to visualize one #AgsChannel. It should be
119 * packed by an #AgsEffectBulk.
120 */
121
122 enum{
123 ADD_PLUGIN,
124 REMOVE_PLUGIN,
125 RESIZE_AUDIO_CHANNELS,
126 RESIZE_PADS,
127 MAP_RECALL,
128 FIND_PORT,
129 LAST_SIGNAL,
130 };
131
132 enum{
133 PROP_0,
134 PROP_AUDIO,
135 PROP_CHANNEL_TYPE,
136 };
137
138 static gpointer ags_effect_bulk_parent_class = NULL;
139 static guint effect_bulk_signals[LAST_SIGNAL];
140
141 GHashTable *ags_effect_bulk_indicator_queue_draw = NULL;
142
143 GType
ags_effect_bulk_get_type(void)144 ags_effect_bulk_get_type(void)
145 {
146 static volatile gsize g_define_type_id__volatile = 0;
147
148 if(g_once_init_enter (&g_define_type_id__volatile)){
149 GType ags_type_effect_bulk = 0;
150
151 static const GTypeInfo ags_effect_bulk_info = {
152 sizeof(AgsEffectBulkClass),
153 NULL, /* base_init */
154 NULL, /* base_finalize */
155 (GClassInitFunc) ags_effect_bulk_class_init,
156 NULL, /* class_finalize */
157 NULL, /* class_data */
158 sizeof(AgsEffectBulk),
159 0, /* n_preallocs */
160 (GInstanceInitFunc) ags_effect_bulk_init,
161 };
162
163 static const GInterfaceInfo ags_connectable_interface_info = {
164 (GInterfaceInitFunc) ags_effect_bulk_connectable_interface_init,
165 NULL, /* interface_finalize */
166 NULL, /* interface_data */
167 };
168
169 ags_type_effect_bulk = g_type_register_static(GTK_TYPE_BOX,
170 "AgsEffectBulk", &ags_effect_bulk_info,
171 0);
172
173 g_type_add_interface_static(ags_type_effect_bulk,
174 AGS_TYPE_CONNECTABLE,
175 &ags_connectable_interface_info);
176
177 g_once_init_leave(&g_define_type_id__volatile, ags_type_effect_bulk);
178 }
179
180 return g_define_type_id__volatile;
181 }
182
183 void
ags_effect_bulk_class_init(AgsEffectBulkClass * effect_bulk)184 ags_effect_bulk_class_init(AgsEffectBulkClass *effect_bulk)
185 {
186 GObjectClass *gobject;
187 GtkWidgetClass *widget;
188 GParamSpec *param_spec;
189
190 ags_effect_bulk_parent_class = g_type_class_peek_parent(effect_bulk);
191
192 /* GObjectClass */
193 gobject = G_OBJECT_CLASS(effect_bulk);
194
195 gobject->set_property = ags_effect_bulk_set_property;
196 gobject->get_property = ags_effect_bulk_get_property;
197
198 gobject->dispose = ags_effect_bulk_dispose;
199 gobject->finalize = ags_effect_bulk_finalize;
200
201 /* properties */
202 /**
203 * AgsEffectBulk:audio:
204 *
205 * The #AgsAudio to visualize.
206 *
207 * Since: 3.0.0
208 */
209 param_spec = g_param_spec_object("audio",
210 i18n_pspec("assigned audio"),
211 i18n_pspec("The audio it is assigned with"),
212 AGS_TYPE_AUDIO,
213 G_PARAM_READABLE | G_PARAM_WRITABLE);
214 g_object_class_install_property(gobject,
215 PROP_AUDIO,
216 param_spec);
217
218 /**
219 * AgsEffectBulk:channel-type:
220 *
221 * The target channel.
222 *
223 * Since: 3.0.0
224 */
225 param_spec = g_param_spec_gtype("channel-type",
226 i18n_pspec("assigned channel type"),
227 i18n_pspec("The channel type it is assigned with"),
228 AGS_TYPE_CHANNEL,
229 G_PARAM_READABLE | G_PARAM_WRITABLE);
230 g_object_class_install_property(gobject,
231 PROP_CHANNEL_TYPE,
232 param_spec);
233
234 /* GtkWidgetClass */
235 widget = (GtkWidgetClass *) effect_bulk;
236
237 widget->show = ags_effect_bulk_show;
238
239 /* AgsEffectBulkClass */
240 effect_bulk->add_plugin = ags_effect_bulk_real_add_plugin;
241 effect_bulk->remove_plugin = ags_effect_bulk_real_remove_plugin;
242
243 effect_bulk->resize_audio_channels = ags_effect_bulk_real_resize_audio_channels;
244 effect_bulk->resize_pads = ags_effect_bulk_real_resize_pads;
245
246 effect_bulk->map_recall = ags_effect_bulk_real_map_recall;
247 effect_bulk->find_port = ags_effect_bulk_real_find_port;
248
249 /* signals */
250 /**
251 * AgsEffectBulk::add-plugin:
252 * @effect_bulk: the #AgsEffectBulk to modify
253 * @effect: the effect's name
254 *
255 * The ::add-plugin signal notifies about added effect.
256 *
257 * Since: 3.3.0
258 */
259 effect_bulk_signals[ADD_PLUGIN] =
260 g_signal_new("add-plugin",
261 G_TYPE_FROM_CLASS(effect_bulk),
262 G_SIGNAL_RUN_LAST,
263 G_STRUCT_OFFSET(AgsEffectBulkClass, add_plugin),
264 NULL, NULL,
265 ags_cclosure_marshal_VOID__POINTER_OBJECT_OBJECT_STRING_STRING_STRING_UINT_UINT_UINT_UINT_INT_UINT_UINT,
266 G_TYPE_NONE, 13,
267 G_TYPE_POINTER,
268 G_TYPE_OBJECT,
269 G_TYPE_OBJECT,
270 G_TYPE_STRING,
271 G_TYPE_STRING,
272 G_TYPE_STRING,
273 G_TYPE_UINT,
274 G_TYPE_UINT,
275 G_TYPE_UINT,
276 G_TYPE_UINT,
277 G_TYPE_INT,
278 G_TYPE_UINT,
279 G_TYPE_UINT);
280
281 /**
282 * AgsEffectBulk::remove-plugin:
283 * @effect_bulk: the #AgsEffectBulk to modify
284 * @nth: the nth effect
285 *
286 * The ::remove-plugin signal notifies about removed effect.
287 *
288 * Since: 3.3.0
289 */
290 effect_bulk_signals[REMOVE_PLUGIN] =
291 g_signal_new("remove-plugin",
292 G_TYPE_FROM_CLASS(effect_bulk),
293 G_SIGNAL_RUN_LAST,
294 G_STRUCT_OFFSET(AgsEffectBulkClass, remove_plugin),
295 NULL, NULL,
296 g_cclosure_marshal_VOID__UINT,
297 G_TYPE_NONE, 1,
298 G_TYPE_UINT);
299
300 /**
301 * AgsEffectBulk::resize-audio-channels:
302 * @effect_bulk: the object to adjust the channels.
303 * @new_size: new audio channel count
304 * @old_size: old audio channel count
305 *
306 * The ::resize-audio-channels signal notifies about changes in channel
307 * alignment.
308 *
309 * Since: 3.0.0
310 */
311 effect_bulk_signals[RESIZE_AUDIO_CHANNELS] =
312 g_signal_new("resize-audio-channels",
313 G_TYPE_FROM_CLASS(effect_bulk),
314 G_SIGNAL_RUN_LAST,
315 G_STRUCT_OFFSET(AgsEffectBulkClass, resize_audio_channels),
316 NULL, NULL,
317 ags_cclosure_marshal_VOID__UINT_UINT,
318 G_TYPE_NONE, 2,
319 G_TYPE_UINT, G_TYPE_UINT);
320
321 /**
322 * AgsEffectBulk::resize-pads:
323 * @effect_bulk: the object to adjust the channels.
324 * @new_size: new pad count
325 * @old_size: old pad count
326 *
327 * The ::resize-pads signal notifies about changes in channel
328 * alignment.
329 *
330 * Since: 3.0.0
331 */
332 effect_bulk_signals[RESIZE_PADS] =
333 g_signal_new("resize_pads",
334 G_TYPE_FROM_CLASS(effect_bulk),
335 G_SIGNAL_RUN_LAST,
336 G_STRUCT_OFFSET(AgsEffectBulkClass, resize_pads),
337 NULL, NULL,
338 ags_cclosure_marshal_VOID__UINT_UINT,
339 G_TYPE_NONE, 2,
340 G_TYPE_UINT, G_TYPE_UINT);
341
342 /**
343 * AgsEffectBulk::map-recall:
344 * @effect_bulk: the #AgsEffectBulk
345 *
346 * The ::map-recall should be used to add the effect_bulk's default recall.
347 *
348 * Since: 3.0.0
349 */
350 effect_bulk_signals[MAP_RECALL] =
351 g_signal_new("map-recall",
352 G_TYPE_FROM_CLASS (effect_bulk),
353 G_SIGNAL_RUN_LAST,
354 G_STRUCT_OFFSET (AgsEffectBulkClass, map_recall),
355 NULL, NULL,
356 g_cclosure_marshal_VOID__UINT,
357 G_TYPE_NONE, 0);
358
359 /**
360 * AgsEffectBulk::find-port:
361 * @effect_bulk: the #AgsEffectBulk to resize
362 *
363 * The ::find-port as recall should be mapped
364 *
365 * Returns: a #GList-struct with associated ports
366 *
367 * Since: 3.0.0
368 */
369 effect_bulk_signals[FIND_PORT] =
370 g_signal_new("find-port",
371 G_TYPE_FROM_CLASS(effect_bulk),
372 G_SIGNAL_RUN_LAST,
373 G_STRUCT_OFFSET(AgsEffectBulkClass, find_port),
374 NULL, NULL,
375 ags_cclosure_marshal_POINTER__VOID,
376 G_TYPE_POINTER, 0);
377 }
378
379 void
ags_effect_bulk_connectable_interface_init(AgsConnectableInterface * connectable)380 ags_effect_bulk_connectable_interface_init(AgsConnectableInterface *connectable)
381 {
382 connectable->is_ready = NULL;
383 connectable->is_connected = NULL;
384 connectable->connect = ags_effect_bulk_connect;
385 connectable->disconnect = ags_effect_bulk_disconnect;
386 }
387
388 void
ags_effect_bulk_init(AgsEffectBulk * effect_bulk)389 ags_effect_bulk_init(AgsEffectBulk *effect_bulk)
390 {
391 GtkBox *hbox;
392
393 gtk_orientable_set_orientation(GTK_ORIENTABLE(effect_bulk),
394 GTK_ORIENTATION_VERTICAL);
395
396 if(ags_effect_bulk_indicator_queue_draw == NULL){
397 ags_effect_bulk_indicator_queue_draw = g_hash_table_new_full(g_direct_hash, g_direct_equal,
398 NULL,
399 NULL);
400 }
401
402 effect_bulk->flags = 0;
403
404 effect_bulk->name = NULL;
405
406 effect_bulk->version = AGS_EFFECT_BULK_DEFAULT_VERSION;
407 effect_bulk->build_id = AGS_EFFECT_BULK_DEFAULT_BUILD_ID;
408
409 effect_bulk->channel_type = G_TYPE_NONE;
410 effect_bulk->audio = NULL;
411
412 effect_bulk->plugin = NULL;
413
414 hbox = (GtkBox *) gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
415 0);
416 gtk_widget_set_halign(hbox,
417 GTK_ALIGN_END);
418 gtk_widget_set_no_show_all((GtkWidget *) hbox,
419 TRUE);
420 gtk_box_pack_start((GtkBox *) effect_bulk,
421 (GtkWidget *) hbox,
422 FALSE, FALSE,
423 0);
424
425 effect_bulk->add = (GtkButton *) gtk_button_new_from_icon_name("list-add",
426 GTK_ICON_SIZE_BUTTON);
427 gtk_box_pack_start((GtkBox *) hbox,
428 (GtkWidget *) effect_bulk->add,
429 FALSE, FALSE,
430 0);
431 gtk_widget_show((GtkWidget *) effect_bulk->add);
432
433 effect_bulk->remove = (GtkButton *) gtk_button_new_from_icon_name("list-remove",
434 GTK_ICON_SIZE_BUTTON);
435 gtk_box_pack_start((GtkBox *) hbox,
436 (GtkWidget *) effect_bulk->remove,
437 FALSE, FALSE,
438 0);
439 gtk_widget_show((GtkWidget *) effect_bulk->remove);
440
441 hbox = (GtkBox *) gtk_box_new(GTK_ORIENTATION_HORIZONTAL,
442 0);
443 gtk_box_pack_start((GtkBox *) effect_bulk,
444 (GtkWidget *) hbox,
445 FALSE, FALSE,
446 0);
447
448 effect_bulk->bulk_member = (GtkVBox *) gtk_box_new(GTK_ORIENTATION_VERTICAL,
449 0);
450 gtk_widget_set_no_show_all((GtkWidget *) effect_bulk->bulk_member,
451 TRUE);
452 gtk_box_pack_start((GtkBox *) hbox,
453 (GtkWidget *) effect_bulk->bulk_member,
454 FALSE, FALSE,
455 0);
456
457 effect_bulk->grid = (GtkGrid *) gtk_grid_new();
458 gtk_box_pack_start((GtkBox *) hbox,
459 (GtkWidget *) effect_bulk->grid,
460 FALSE, FALSE,
461 0);
462
463 effect_bulk->plugin_browser = (GtkDialog *) ags_plugin_browser_new((GtkWidget *) effect_bulk);
464
465 effect_bulk->queued_drawing = NULL;
466 }
467
468 void
ags_effect_bulk_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)469 ags_effect_bulk_set_property(GObject *gobject,
470 guint prop_id,
471 const GValue *value,
472 GParamSpec *param_spec)
473 {
474 AgsEffectBulk *effect_bulk;
475
476 effect_bulk = AGS_EFFECT_BULK(gobject);
477
478 switch(prop_id){
479 case PROP_AUDIO:
480 {
481 AgsAudio *audio;
482
483 guint output_pads, input_pads;
484
485 audio = (AgsAudio *) g_value_get_object(value);
486
487 if(effect_bulk->audio == audio){
488 return;
489 }
490
491 if(effect_bulk->audio != NULL){
492 if((AGS_EFFECT_BULK_CONNECTED & (effect_bulk->flags)) != 0){
493 //TODO:JK: implement me
494 }
495
496 if(effect_bulk->channel_type == AGS_TYPE_OUTPUT){
497 g_object_get(effect_bulk->audio,
498 "output-pads", &output_pads,
499 NULL);
500
501 ags_effect_bulk_resize_pads(effect_bulk,
502 0,
503 output_pads);
504 }else{
505 g_object_get(effect_bulk->audio,
506 "input-pads", &input_pads,
507 NULL);
508
509 ags_effect_bulk_resize_pads(effect_bulk,
510 0,
511 input_pads);
512 }
513
514 g_object_unref(effect_bulk->audio);
515 }
516
517 if(audio != NULL){
518 g_object_ref(audio);
519 }
520
521 effect_bulk->audio = audio;
522
523 if((AGS_EFFECT_BULK_CONNECTED & (effect_bulk->flags)) != 0){
524 if(audio != NULL){
525 if(effect_bulk->channel_type == AGS_TYPE_OUTPUT){
526 g_object_get(audio,
527 "output-pads", &output_pads,
528 NULL);
529
530 ags_effect_bulk_resize_pads(effect_bulk,
531 output_pads,
532 0);
533 }else{
534 g_object_get(audio,
535 "input-pads", &input_pads,
536 NULL);
537
538 ags_effect_bulk_resize_pads(effect_bulk,
539 input_pads,
540 0);
541 }
542 }
543 }
544 }
545 break;
546 case PROP_CHANNEL_TYPE:
547 {
548 GType channel_type;
549
550 channel_type = (GType) g_value_get_gtype(value);
551
552 effect_bulk->channel_type = channel_type;
553 }
554 break;
555 default:
556 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
557 break;
558 }
559 }
560
561 void
ags_effect_bulk_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)562 ags_effect_bulk_get_property(GObject *gobject,
563 guint prop_id,
564 GValue *value,
565 GParamSpec *param_spec)
566 {
567 AgsEffectBulk *effect_bulk;
568
569 effect_bulk = AGS_EFFECT_BULK(gobject);
570
571 switch(prop_id){
572 case PROP_AUDIO:
573 {
574 g_value_set_object(value,
575 effect_bulk->audio);
576 }
577 break;
578 case PROP_CHANNEL_TYPE:
579 {
580 g_value_set_gtype(value,
581 effect_bulk->channel_type);
582 }
583 break;
584 default:
585 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
586 break;
587 }
588 }
589
590 void
ags_effect_bulk_dispose(GObject * gobject)591 ags_effect_bulk_dispose(GObject *gobject)
592 {
593 AgsEffectBulk *effect_bulk;
594
595 effect_bulk = (AgsEffectBulk *) gobject;
596
597 /* unref audio */
598 if(effect_bulk->audio != NULL){
599 g_object_unref(effect_bulk->audio);
600
601 effect_bulk->audio = NULL;
602 }
603
604 /* call parent */
605 G_OBJECT_CLASS(ags_effect_bulk_parent_class)->dispose(gobject);
606 }
607
608 void
ags_effect_bulk_finalize(GObject * gobject)609 ags_effect_bulk_finalize(GObject *gobject)
610 {
611 AgsEffectBulk *effect_bulk;
612
613 GList *list;
614
615 effect_bulk = (AgsEffectBulk *) gobject;
616
617 /* unref audio */
618 if(effect_bulk->audio != NULL){
619 g_object_unref(effect_bulk->audio);
620 }
621
622 /* free plugin list */
623 g_list_free_full(effect_bulk->plugin,
624 (GDestroyNotify) ags_effect_bulk_plugin_free);
625
626 /* destroy plugin browser */
627 gtk_widget_destroy(GTK_WIDGET(effect_bulk->plugin_browser));
628
629 /* remove of the queued drawing hash */
630 list = effect_bulk->queued_drawing;
631
632 while(list != NULL){
633 g_hash_table_remove(ags_effect_bulk_indicator_queue_draw,
634 (GDestroyNotify) list->data);
635
636 list = list->next;
637 }
638
639 /* call parent */
640 G_OBJECT_CLASS(ags_effect_bulk_parent_class)->finalize(gobject);
641 }
642
643 void
ags_effect_bulk_connect(AgsConnectable * connectable)644 ags_effect_bulk_connect(AgsConnectable *connectable)
645 {
646 AgsMachine *machine;
647 AgsEffectBulk *effect_bulk;
648
649 GList *list, *list_start;
650
651 effect_bulk = AGS_EFFECT_BULK(connectable);
652
653 if((AGS_EFFECT_BULK_CONNECTED & (effect_bulk->flags)) != 0){
654 return;
655 }
656
657 effect_bulk->flags |= AGS_EFFECT_BULK_CONNECTED;
658
659 machine = (AgsMachine *) gtk_widget_get_ancestor((GtkWidget *) effect_bulk,
660 AGS_TYPE_MACHINE);
661
662 g_signal_connect_after(machine, "resize-audio-channels",
663 G_CALLBACK(ags_effect_bulk_resize_audio_channels_callback), effect_bulk);
664
665 g_signal_connect_after(machine, "resize-pads",
666 G_CALLBACK(ags_effect_bulk_resize_pads_callback), effect_bulk);
667
668 /* */
669 g_signal_connect(G_OBJECT(effect_bulk->add), "clicked",
670 G_CALLBACK(ags_effect_bulk_add_callback), effect_bulk);
671
672 g_signal_connect(G_OBJECT(effect_bulk->remove), "clicked",
673 G_CALLBACK(ags_effect_bulk_remove_callback), effect_bulk);
674
675 ags_connectable_connect(AGS_CONNECTABLE(effect_bulk->plugin_browser));
676
677 g_signal_connect(G_OBJECT(effect_bulk->plugin_browser), "response",
678 G_CALLBACK(ags_effect_bulk_plugin_browser_response_callback), effect_bulk);
679
680 list =
681 list_start = gtk_container_get_children((GtkContainer *) effect_bulk->grid);
682
683 while(list != NULL){
684 if(AGS_IS_CONNECTABLE(list->data)){
685 ags_connectable_connect(AGS_CONNECTABLE(list->data));
686 }
687
688 list = list->next;
689 }
690
691 g_list_free(list_start);
692 }
693
694 void
ags_effect_bulk_disconnect(AgsConnectable * connectable)695 ags_effect_bulk_disconnect(AgsConnectable *connectable)
696 {
697 AgsMachine *machine;
698 AgsEffectBulk *effect_bulk;
699
700 GList *list, *list_start;
701
702 effect_bulk = AGS_EFFECT_BULK(connectable);
703
704 if((AGS_EFFECT_BULK_CONNECTED & (effect_bulk->flags)) == 0){
705 return;
706 }
707
708 effect_bulk->flags &= (~AGS_EFFECT_BULK_CONNECTED);
709
710 machine = (AgsMachine *) gtk_widget_get_ancestor((GtkWidget *) effect_bulk,
711 AGS_TYPE_MACHINE);
712
713 g_object_disconnect(G_OBJECT(machine),
714 "any_signal::resize-audio-channels",
715 G_CALLBACK(ags_effect_bulk_resize_audio_channels_callback),
716 effect_bulk,
717 "any_signal::resize-pads",
718 G_CALLBACK(ags_effect_bulk_resize_pads_callback),
719 effect_bulk,
720 NULL);
721
722 g_object_disconnect(G_OBJECT(effect_bulk->add),
723 "any_signal::clicked",
724 G_CALLBACK(ags_effect_bulk_add_callback),
725 effect_bulk,
726 NULL);
727
728 g_object_disconnect(G_OBJECT(effect_bulk->remove),
729 "any_signal::clicked",
730 G_CALLBACK(ags_effect_bulk_remove_callback),
731 effect_bulk,
732 NULL);
733
734 ags_connectable_disconnect(AGS_CONNECTABLE(effect_bulk->plugin_browser));
735
736 g_object_disconnect(G_OBJECT(effect_bulk->plugin_browser),
737 "any_signal::response",
738 G_CALLBACK(ags_effect_bulk_plugin_browser_response_callback),
739 effect_bulk,
740 NULL);
741
742 list =
743 list_start = gtk_container_get_children((GtkContainer *) effect_bulk->grid);
744
745 while(list != NULL){
746 if(AGS_IS_CONNECTABLE(list->data)){
747 ags_connectable_disconnect(AGS_CONNECTABLE(list->data));
748 }
749
750 list = list->next;
751 }
752
753 g_list_free(list_start);
754 }
755
756 void
ags_effect_bulk_show(GtkWidget * widget)757 ags_effect_bulk_show(GtkWidget *widget)
758 {
759 AgsEffectBulk *effect_bulk;
760
761 effect_bulk = AGS_EFFECT_BULK(widget);
762
763 GTK_WIDGET_CLASS(ags_effect_bulk_parent_class)->show(widget);
764
765 if((AGS_EFFECT_BULK_HIDE_BUTTONS & (effect_bulk->flags)) == 0){
766 gtk_widget_show(gtk_widget_get_parent(GTK_WIDGET(effect_bulk->add)));
767 }
768
769 if((AGS_EFFECT_BULK_HIDE_ENTRIES & (effect_bulk->flags)) == 0){
770 gtk_widget_show((GtkWidget *) effect_bulk->bulk_member);
771 }
772 }
773
774 /**
775 * ags_effect_bulk_plugin_alloc:
776 * @play_container: the #AgsRecallContainer
777 * @recall_container: the #AgsRecallContainer
778 * @plugin_name: the plugin name
779 * @filename: the filename as string
780 * @effect: the effect as string
781 *
782 * Allocate #AgsEffectBulkPlugin-struct.
783 *
784 * Returns: the newly allocated #AgsEffectBulkPlugin-struct
785 *
786 * Since: 3.3.0
787 */
788 AgsEffectBulkPlugin*
ags_effect_bulk_plugin_alloc(AgsRecallContainer * play_container,AgsRecallContainer * recall_container,gchar * plugin_name,gchar * filename,gchar * effect)789 ags_effect_bulk_plugin_alloc(AgsRecallContainer *play_container, AgsRecallContainer *recall_container,
790 gchar *plugin_name,
791 gchar *filename,
792 gchar *effect)
793 {
794 AgsEffectBulkPlugin *effect_bulk_plugin;
795
796 effect_bulk_plugin = (AgsEffectBulkPlugin *) g_malloc(sizeof(AgsEffectBulkPlugin));
797
798 if(play_container != NULL){
799 g_object_ref(play_container);
800 }
801
802 effect_bulk_plugin->play_container = play_container;
803
804 if(recall_container != NULL){
805 g_object_ref(recall_container);
806 }
807
808 effect_bulk_plugin->recall_container = recall_container;
809
810 effect_bulk_plugin->plugin_name = g_strdup(plugin_name);
811
812 effect_bulk_plugin->filename = g_strdup(filename);
813 effect_bulk_plugin->effect = g_strdup(effect);
814
815 effect_bulk_plugin->control_type_name = NULL;
816
817 effect_bulk_plugin->control_count = 0;
818
819 return(effect_bulk_plugin);
820 }
821
822 /**
823 * ags_effect_bulk_plugin_free:
824 * @effect_bulk_plugin: the #AgsEffectBulkPlugin-struct
825 *
826 * Free @effect_bulk_plugin.
827 *
828 * Since: 3.3.0
829 */
830 void
ags_effect_bulk_plugin_free(AgsEffectBulkPlugin * effect_bulk_plugin)831 ags_effect_bulk_plugin_free(AgsEffectBulkPlugin *effect_bulk_plugin)
832 {
833 if(effect_bulk_plugin == NULL){
834 return;
835 }
836
837 if(effect_bulk_plugin->play_container != NULL){
838 g_object_unref(effect_bulk_plugin->play_container);
839 }
840
841 if(effect_bulk_plugin->recall_container != NULL){
842 g_object_unref(effect_bulk_plugin->recall_container);
843 }
844
845 if(effect_bulk_plugin->filename != NULL){
846 g_free(effect_bulk_plugin->filename);
847 }
848
849 if(effect_bulk_plugin->effect != NULL){
850 g_free(effect_bulk_plugin->effect);
851 }
852
853 if(effect_bulk_plugin->control_type_name != NULL){
854 g_list_free(effect_bulk_plugin->control_type_name);
855 }
856
857 g_free(effect_bulk_plugin);
858 }
859
860 void
ags_effect_bulk_add_ladspa_plugin(AgsEffectBulk * effect_bulk,GList * control_type_name,AgsRecallContainer * play_container,AgsRecallContainer * recall_container,gchar * plugin_name,gchar * filename,gchar * effect,guint start_audio_channel,guint stop_audio_channel,guint start_pad,guint stop_pad,gint position,guint create_flags,guint recall_flags)861 ags_effect_bulk_add_ladspa_plugin(AgsEffectBulk *effect_bulk,
862 GList *control_type_name,
863 AgsRecallContainer *play_container, AgsRecallContainer *recall_container,
864 gchar *plugin_name,
865 gchar *filename,
866 gchar *effect,
867 guint start_audio_channel, guint stop_audio_channel,
868 guint start_pad, guint stop_pad,
869 gint position,
870 guint create_flags, guint recall_flags)
871 {
872 AgsBulkMember *bulk_member;
873
874 AgsEffectBulkPlugin *effect_bulk_plugin;
875
876 AgsLadspaPlugin *ladspa_plugin;
877
878 GList *start_recall, *recall;
879 GList *start_list, *list;
880 GList *start_plugin_port, *plugin_port;
881
882 guint pads, audio_channels;
883 gdouble page, step;
884 guint port_count;
885 guint control_count;
886
887 guint x, y;
888 guint k;
889
890 pads = 0;
891 audio_channels = 0;
892
893 /* alloc effect bulk plugin */
894 effect_bulk_plugin = ags_effect_bulk_plugin_alloc(play_container, recall_container,
895 plugin_name,
896 filename,
897 effect);
898 effect_bulk_plugin->control_type_name = control_type_name;
899
900 effect_bulk->plugin = g_list_append(effect_bulk->plugin,
901 effect_bulk_plugin);
902
903 /* get audio properties */
904 g_object_get(effect_bulk->audio,
905 "audio-channels", &audio_channels,
906 NULL);
907
908 if(g_type_is_a(effect_bulk->channel_type, AGS_TYPE_OUTPUT)){
909 g_object_get(effect_bulk->audio,
910 "output-pads", &pads,
911 NULL);
912 }else{
913 g_object_get(effect_bulk->audio,
914 "input-pads", &pads,
915 NULL);
916 }
917
918 /* load plugin */
919 ladspa_plugin = ags_ladspa_manager_find_ladspa_plugin(ags_ladspa_manager_get_instance(),
920 filename, effect);
921
922 /* ags-fx-ladspa */
923 start_recall = ags_fx_factory_create(effect_bulk->audio,
924 effect_bulk_plugin->play_container, effect_bulk_plugin->recall_container,
925 plugin_name,
926 filename,
927 effect,
928 0, audio_channels,
929 0, pads,
930 position,
931 create_flags | (g_type_is_a(effect_bulk->channel_type, AGS_TYPE_OUTPUT) ? AGS_FX_FACTORY_OUTPUT: AGS_FX_FACTORY_INPUT), recall_flags);
932
933 recall = start_recall;
934
935 while(recall != NULL){
936 ags_recall_set_behaviour_flags(recall->data, AGS_SOUND_BEHAVIOUR_BULK_MODE);
937
938 recall = recall->next;
939 }
940
941 g_list_free_full(start_recall,
942 (GDestroyNotify) g_object_unref);
943
944 /* retrieve position within table */
945 x = 0;
946 y = 0;
947
948 list =
949 start_list = gtk_container_get_children(GTK_CONTAINER(effect_bulk->grid));
950
951 while(list != NULL){
952 guint top_attach;
953
954 gtk_container_child_get(GTK_CONTAINER(effect_bulk->grid),
955 list->data,
956 "top-attach", &top_attach,
957 NULL);
958
959 if(y <= top_attach){
960 y = top_attach + 1;
961 }
962
963 list = list->next;
964 }
965
966 g_list_free(start_list);
967
968 /* load ports */
969 g_object_get(ladspa_plugin,
970 "plugin-port", &start_plugin_port,
971 NULL);
972
973 plugin_port = start_plugin_port;
974
975 port_count = g_list_length(plugin_port);
976
977 control_count = 0;
978
979 k = 0;
980
981 while(plugin_port != NULL){
982 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_CONTROL)){
983 GtkWidget *child_widget;
984
985 AgsLadspaConversion *ladspa_conversion;
986
987 LADSPA_Data default_value;
988
989 GType widget_type;
990
991 gchar *plugin_name;
992 gchar *control_port;
993 gchar *port_name;
994
995 guint unique_id;
996 guint scale_precision;
997 guint port_index;
998 gdouble step_count;
999 gboolean disable_seemless;
1000 gboolean do_step_conversion;
1001
1002 GRecMutex *plugin_port_mutex;
1003
1004 control_count++;
1005
1006 disable_seemless = FALSE;
1007 do_step_conversion = FALSE;
1008
1009 if(x == AGS_EFFECT_BULK_COLUMNS_COUNT){
1010 x = 0;
1011 y++;
1012 }
1013
1014 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_TOGGLED)){
1015 disable_seemless = TRUE;
1016
1017 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_OUTPUT)){
1018 widget_type = AGS_TYPE_LED;
1019 }else{
1020 widget_type = GTK_TYPE_TOGGLE_BUTTON;
1021 }
1022 }else{
1023 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_OUTPUT)){
1024 widget_type = AGS_TYPE_HINDICATOR;
1025 }else{
1026 widget_type = AGS_TYPE_DIAL;
1027 }
1028 }
1029
1030 scale_precision = AGS_DIAL_DEFAULT_PRECISION;
1031 step_count = AGS_LADSPA_CONVERSION_DEFAULT_STEP_COUNT;
1032
1033 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_INTEGER)){
1034 guint scale_steps;
1035
1036 g_object_get(plugin_port->data,
1037 "scale-steps", &scale_steps,
1038 NULL);
1039
1040 step_count =
1041 scale_precision = (gdouble) scale_steps;
1042
1043 disable_seemless = TRUE;
1044 }
1045
1046 /* get plugin port mutex */
1047 plugin_port_mutex = AGS_PLUGIN_PORT_GET_OBJ_MUTEX(plugin_port->data);
1048
1049 /* get port name */
1050 g_rec_mutex_lock(plugin_port_mutex);
1051
1052 port_name = g_strdup(AGS_PLUGIN_PORT(plugin_port->data)->port_name);
1053 port_index = AGS_PLUGIN_PORT(plugin_port->data)->port_index;
1054
1055 unique_id = ladspa_plugin->unique_id;
1056
1057 g_rec_mutex_unlock(plugin_port_mutex);
1058
1059 /* add bulk member */
1060 plugin_name = g_strdup_printf("ladspa-%u",
1061 unique_id);
1062 control_port = g_strdup_printf("%u/%u",
1063 k + 1,
1064 port_count);
1065 bulk_member = (AgsBulkMember *) g_object_new(AGS_TYPE_BULK_MEMBER,
1066 "widget-type", widget_type,
1067 "widget-label", port_name,
1068 "play-container", play_container,
1069 "recall-container", recall_container,
1070 "plugin-name", plugin_name,
1071 "filename", filename,
1072 "effect", effect,
1073 "port-index", port_index,
1074 "specifier", port_name,
1075 "control-port", control_port,
1076 "scale-precision", scale_precision,
1077 "step-count", step_count,
1078 NULL);
1079
1080 child_widget = ags_bulk_member_get_widget(bulk_member);
1081
1082 g_free(plugin_name);
1083 g_free(control_port);
1084 g_free(port_name);
1085
1086 /* ladspa conversion */
1087 ladspa_conversion = NULL;
1088
1089 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_BOUNDED_BELOW)){
1090 if(ladspa_conversion == NULL ||
1091 !AGS_IS_LADSPA_CONVERSION(ladspa_conversion)){
1092 ladspa_conversion = ags_ladspa_conversion_new();
1093 }
1094
1095 ladspa_conversion->flags |= AGS_LADSPA_CONVERSION_BOUNDED_BELOW;
1096 }
1097
1098 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_BOUNDED_ABOVE)){
1099 if(ladspa_conversion == NULL ||
1100 !AGS_IS_LADSPA_CONVERSION(ladspa_conversion)){
1101 ladspa_conversion = ags_ladspa_conversion_new();
1102 }
1103
1104 ladspa_conversion->flags |= AGS_LADSPA_CONVERSION_BOUNDED_ABOVE;
1105 }
1106 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_SAMPLERATE)){
1107 if(ladspa_conversion == NULL ||
1108 !AGS_IS_LADSPA_CONVERSION(ladspa_conversion)){
1109 ladspa_conversion = ags_ladspa_conversion_new();
1110 }
1111
1112 ladspa_conversion->flags |= AGS_LADSPA_CONVERSION_SAMPLERATE;
1113 }
1114
1115 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_LOGARITHMIC)){
1116 if(ladspa_conversion == NULL ||
1117 !AGS_IS_LADSPA_CONVERSION(ladspa_conversion)){
1118 ladspa_conversion = ags_ladspa_conversion_new();
1119 }
1120
1121 ladspa_conversion->flags |= AGS_LADSPA_CONVERSION_LOGARITHMIC;
1122
1123 do_step_conversion = TRUE;
1124 }
1125
1126 g_object_set(bulk_member,
1127 "conversion", ladspa_conversion,
1128 NULL);
1129
1130 /* child widget */
1131 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_TOGGLED)){
1132 bulk_member->port_flags = AGS_BULK_MEMBER_PORT_BOOLEAN;
1133 }
1134
1135 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_INTEGER)){
1136 bulk_member->port_flags = AGS_BULK_MEMBER_PORT_INTEGER;
1137 }
1138
1139 if(AGS_IS_DIAL(child_widget)){
1140 AgsDial *dial;
1141
1142 GtkAdjustment *adjustment;
1143
1144 LADSPA_Data lower_bound, upper_bound;
1145 gdouble lower, upper;
1146 gdouble control_value;
1147
1148 dial = (AgsDial *) child_widget;
1149
1150 if(disable_seemless){
1151 dial->flags &= (~AGS_DIAL_SEEMLESS_MODE);
1152 }
1153
1154 /* add controls of ports and apply range */
1155 g_rec_mutex_lock(plugin_port_mutex);
1156
1157 lower_bound = g_value_get_float(AGS_PLUGIN_PORT(plugin_port->data)->lower_value);
1158 upper_bound = g_value_get_float(AGS_PLUGIN_PORT(plugin_port->data)->upper_value);
1159
1160 g_rec_mutex_unlock(plugin_port_mutex);
1161
1162 if(do_step_conversion){
1163 g_object_set(ladspa_conversion,
1164 "lower", lower_bound,
1165 "upper", upper_bound,
1166 NULL);
1167
1168 lower = 0.0;
1169 upper = AGS_LADSPA_CONVERSION_DEFAULT_STEP_COUNT - 1.0;
1170
1171 #if 0
1172 if(!disable_seemless){
1173 g_object_get(ladspa_conversion,
1174 "step-count", &step_count,
1175 NULL);
1176 }
1177 #endif
1178 }else{
1179 lower = lower_bound;
1180 upper = upper_bound;
1181 }
1182
1183 adjustment = (GtkAdjustment *) gtk_adjustment_new(0.0, 0.0, 1.0, 0.1, 0.1, 0.0);
1184 g_object_set(dial,
1185 "adjustment", adjustment,
1186 NULL);
1187
1188 if(upper >= 0.0 && lower >= 0.0){
1189 step = (upper - lower) / step_count;
1190 }else if(upper < 0.0 && lower < 0.0){
1191 step = -1.0 * (lower - upper) / step_count;
1192 }else{
1193 step = (upper - lower) / step_count;
1194 }
1195
1196 if(step_count > 8){
1197 if(upper >= 0.0 && lower >= 0.0){
1198 page = (upper - lower) / AGS_DIAL_DEFAULT_PRECISION;
1199 }else if(upper < 0.0 && lower < 0.0){
1200 page = -1.0 * (lower - upper) / AGS_DIAL_DEFAULT_PRECISION;
1201 }else{
1202 page = (upper - lower) / AGS_DIAL_DEFAULT_PRECISION;
1203 }
1204 }else{
1205 page = step;
1206 }
1207
1208 gtk_adjustment_set_step_increment(adjustment,
1209 step);
1210 gtk_adjustment_set_page_increment(adjustment,
1211 page);
1212 gtk_adjustment_set_lower(adjustment,
1213 lower);
1214 gtk_adjustment_set_upper(adjustment,
1215 upper);
1216
1217 /* get/set default value */
1218 g_rec_mutex_lock(plugin_port_mutex);
1219
1220 default_value = g_value_get_float(AGS_PLUGIN_PORT(plugin_port->data)->default_value);
1221
1222 g_rec_mutex_unlock(plugin_port_mutex);
1223
1224 control_value = default_value;
1225
1226 if(ladspa_conversion != NULL){
1227 control_value = ags_conversion_convert((AgsConversion *) ladspa_conversion,
1228 default_value,
1229 TRUE);
1230 }
1231
1232 gtk_adjustment_set_value(adjustment,
1233 control_value);
1234 }else if(AGS_IS_INDICATOR(child_widget) ||
1235 AGS_IS_LED(child_widget)){
1236 g_hash_table_insert(ags_effect_bulk_indicator_queue_draw,
1237 child_widget, ags_effect_bulk_indicator_queue_draw_timeout);
1238
1239 effect_bulk->queued_drawing = g_list_prepend(effect_bulk->queued_drawing,
1240 child_widget);
1241
1242 g_timeout_add(AGS_UI_PROVIDER_DEFAULT_TIMEOUT * 1000.0,
1243 (GSourceFunc) ags_effect_bulk_indicator_queue_draw_timeout,
1244 (gpointer) child_widget);
1245 }
1246
1247 #ifdef AGS_DEBUG
1248 g_message("ladspa bounds: %f %f", lower, upper);
1249 #endif
1250
1251 gtk_widget_set_halign((GtkWidget *) bulk_member,
1252 GTK_ALIGN_FILL);
1253 gtk_widget_set_valign((GtkWidget *) bulk_member,
1254 GTK_ALIGN_FILL);
1255
1256 gtk_grid_attach(effect_bulk->grid,
1257 (GtkWidget *) bulk_member,
1258 x, y,
1259 1, 1);
1260 ags_connectable_connect(AGS_CONNECTABLE(bulk_member));
1261 gtk_widget_show_all((GtkWidget *) effect_bulk->grid);
1262
1263 /* iterate */
1264 x++;
1265 }
1266
1267 /* iterate */
1268 plugin_port = plugin_port->next;
1269 k++;
1270 }
1271
1272 effect_bulk_plugin->control_count = control_count;
1273
1274 g_list_free_full(start_plugin_port,
1275 g_object_unref);
1276 }
1277
1278 void
ags_effect_bulk_add_dssi_plugin(AgsEffectBulk * effect_bulk,GList * control_type_name,AgsRecallContainer * play_container,AgsRecallContainer * recall_container,gchar * plugin_name,gchar * filename,gchar * effect,guint start_audio_channel,guint stop_audio_channel,guint start_pad,guint stop_pad,gint position,guint create_flags,guint recall_flags)1279 ags_effect_bulk_add_dssi_plugin(AgsEffectBulk *effect_bulk,
1280 GList *control_type_name,
1281 AgsRecallContainer *play_container, AgsRecallContainer *recall_container,
1282 gchar *plugin_name,
1283 gchar *filename,
1284 gchar *effect,
1285 guint start_audio_channel, guint stop_audio_channel,
1286 guint start_pad, guint stop_pad,
1287 gint position,
1288 guint create_flags, guint recall_flags)
1289 {
1290 AgsBulkMember *bulk_member;
1291
1292 AgsEffectBulkPlugin *effect_bulk_plugin;
1293
1294 AgsDssiPlugin *dssi_plugin;
1295
1296 GList *start_recall, *recall;
1297 GList *start_list, *list;
1298 GList *start_plugin_port, *plugin_port;
1299
1300 guint unique_id;
1301 guint pads, audio_channels;
1302 gdouble page, step;
1303 guint port_count;
1304 guint control_count;
1305
1306 guint x, y;
1307 guint k;
1308
1309 pads = 0;
1310 audio_channels = 0;
1311
1312 /* alloc effect bulk plugin */
1313 effect_bulk_plugin = ags_effect_bulk_plugin_alloc(play_container, recall_container,
1314 plugin_name,
1315 filename,
1316 effect);
1317 effect_bulk_plugin->control_type_name = control_type_name;
1318
1319 effect_bulk->plugin = g_list_append(effect_bulk->plugin,
1320 effect_bulk_plugin);
1321
1322 /* get audio properties */
1323 g_object_get(effect_bulk->audio,
1324 "audio-channels", &audio_channels,
1325 NULL);
1326
1327 if(effect_bulk->channel_type == AGS_TYPE_OUTPUT){
1328 g_object_get(effect_bulk->audio,
1329 "output-pads", &pads,
1330 NULL);
1331 }else{
1332 g_object_get(effect_bulk->audio,
1333 "input-pads", &pads,
1334 NULL);
1335 }
1336
1337 /* load plugin */
1338 dssi_plugin = ags_dssi_manager_find_dssi_plugin(ags_dssi_manager_get_instance(),
1339 filename, effect);
1340
1341 g_object_get(dssi_plugin,
1342 "unique-id", &unique_id,
1343 NULL);
1344
1345 /* ags-fx-dssi */
1346 start_recall = ags_fx_factory_create(effect_bulk->audio,
1347 effect_bulk_plugin->play_container, effect_bulk_plugin->recall_container,
1348 "ags-fx-dssi",
1349 filename,
1350 effect,
1351 0, audio_channels,
1352 0, pads,
1353 position,
1354 create_flags | (g_type_is_a(effect_bulk->channel_type, AGS_TYPE_OUTPUT) ? AGS_FX_FACTORY_OUTPUT: AGS_FX_FACTORY_INPUT), recall_flags);
1355
1356 recall = start_recall;
1357
1358 while(recall != NULL){
1359 ags_recall_set_behaviour_flags(recall->data, AGS_SOUND_BEHAVIOUR_BULK_MODE);
1360
1361 recall = recall->next;
1362 }
1363
1364 g_list_free_full(start_recall,
1365 (GDestroyNotify) g_object_unref);
1366
1367 /* retrieve position within table */
1368 x = 0;
1369 y = 0;
1370
1371 list =
1372 start_list = gtk_container_get_children(GTK_CONTAINER(effect_bulk->grid));
1373
1374 while(list != NULL){
1375 guint top_attach;
1376
1377 gtk_container_child_get(GTK_CONTAINER(effect_bulk->grid),
1378 list->data,
1379 "top-attach", &top_attach,
1380 NULL);
1381
1382 if(y <= top_attach){
1383 y = top_attach + 1;
1384 }
1385
1386 list = list->next;
1387 }
1388
1389 g_list_free(start_list);
1390
1391 /* load ports */
1392 g_object_get(dssi_plugin,
1393 "plugin-port", &start_plugin_port,
1394 NULL);
1395
1396 plugin_port = start_plugin_port;
1397
1398 port_count = g_list_length(start_plugin_port);
1399
1400 control_count = 0;
1401
1402 k = 0;
1403
1404 while(plugin_port != NULL){
1405 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_CONTROL)){
1406 GtkWidget *child_widget;
1407
1408 AgsLadspaConversion *ladspa_conversion;
1409
1410 GType widget_type;
1411
1412 gchar *plugin_name;
1413 gchar *port_name;
1414 gchar *control_port;
1415
1416 guint scale_precision;
1417 guint port_index;
1418 gdouble step_count;
1419 gboolean disable_seemless;
1420 gboolean do_step_conversion;
1421
1422 GRecMutex *plugin_port_mutex;
1423
1424 control_count++;
1425
1426 disable_seemless = FALSE;
1427 do_step_conversion = FALSE;
1428
1429 if(x == AGS_EFFECT_BULK_COLUMNS_COUNT){
1430 x = 0;
1431 y++;
1432 }
1433
1434 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_TOGGLED)){
1435 disable_seemless = TRUE;
1436
1437 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_OUTPUT)){
1438 widget_type = AGS_TYPE_LED;
1439 }else{
1440 widget_type = GTK_TYPE_TOGGLE_BUTTON;
1441 }
1442 }else{
1443 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_OUTPUT)){
1444 widget_type = AGS_TYPE_HINDICATOR;
1445 }else{
1446 widget_type = AGS_TYPE_DIAL;
1447 }
1448 }
1449
1450 scale_precision = AGS_DIAL_DEFAULT_PRECISION;
1451 step_count = AGS_LADSPA_CONVERSION_DEFAULT_STEP_COUNT;
1452
1453 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_INTEGER)){
1454 guint scale_steps;
1455
1456 g_object_get(plugin_port->data,
1457 "scale-steps", &scale_steps,
1458 NULL);
1459
1460 step_count =
1461 scale_precision = (gdouble) scale_steps;
1462
1463 disable_seemless = TRUE;
1464 }
1465
1466 /* get plugin port mutex */
1467 plugin_port_mutex = AGS_PLUGIN_PORT_GET_OBJ_MUTEX(plugin_port->data);
1468
1469 /* get port name */
1470 g_rec_mutex_lock(plugin_port_mutex);
1471
1472 port_name = g_strdup(AGS_PLUGIN_PORT(plugin_port->data)->port_name);
1473 port_index = AGS_PLUGIN_PORT(plugin_port->data)->port_index;
1474
1475 g_rec_mutex_unlock(plugin_port_mutex);
1476
1477 /* add bulk member */
1478 plugin_name = g_strdup_printf("dssi-%u",
1479 unique_id);
1480 control_port = g_strdup_printf("%u/%u",
1481 k + 1,
1482 port_count);
1483 bulk_member = (AgsBulkMember *) g_object_new(AGS_TYPE_BULK_MEMBER,
1484 "widget-type", widget_type,
1485 "widget-label", port_name,
1486 "play-container", play_container,
1487 "recall-container", recall_container,
1488 "plugin-name", plugin_name,
1489 "filename", filename,
1490 "effect", effect,
1491 "port-index", port_index,
1492 "specifier", port_name,
1493 "control-port", control_port,
1494 "scale-precision", scale_precision,
1495 "step-count", step_count,
1496 NULL);
1497 child_widget = ags_bulk_member_get_widget(bulk_member);
1498
1499 g_free(plugin_name);
1500 g_free(control_port);
1501 g_free(port_name);
1502
1503 /* ladspa conversion */
1504 ladspa_conversion = NULL;
1505
1506 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_BOUNDED_BELOW)){
1507 if(ladspa_conversion == NULL ||
1508 !AGS_IS_LADSPA_CONVERSION(ladspa_conversion)){
1509 ladspa_conversion = ags_ladspa_conversion_new();
1510 }
1511
1512 ladspa_conversion->flags |= AGS_LADSPA_CONVERSION_BOUNDED_BELOW;
1513 }
1514
1515 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_BOUNDED_ABOVE)){
1516 if(ladspa_conversion == NULL ||
1517 !AGS_IS_LADSPA_CONVERSION(ladspa_conversion)){
1518 ladspa_conversion = ags_ladspa_conversion_new();
1519 }
1520
1521 ladspa_conversion->flags |= AGS_LADSPA_CONVERSION_BOUNDED_ABOVE;
1522 }
1523 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_SAMPLERATE)){
1524 if(ladspa_conversion == NULL ||
1525 !AGS_IS_LADSPA_CONVERSION(ladspa_conversion)){
1526 ladspa_conversion = ags_ladspa_conversion_new();
1527 }
1528
1529 ladspa_conversion->flags |= AGS_LADSPA_CONVERSION_SAMPLERATE;
1530 }
1531
1532 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_LOGARITHMIC)){
1533 if(ladspa_conversion == NULL ||
1534 !AGS_IS_LADSPA_CONVERSION(ladspa_conversion)){
1535 ladspa_conversion = ags_ladspa_conversion_new();
1536 }
1537
1538 ladspa_conversion->flags |= AGS_LADSPA_CONVERSION_LOGARITHMIC;
1539
1540 do_step_conversion = TRUE;
1541 }
1542
1543 g_object_set(bulk_member,
1544 "conversion", ladspa_conversion,
1545 NULL);
1546
1547 /* child widget */
1548 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_TOGGLED)){
1549 bulk_member->port_flags = AGS_BULK_MEMBER_PORT_BOOLEAN;
1550 }
1551
1552 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_INTEGER)){
1553 bulk_member->port_flags = AGS_BULK_MEMBER_PORT_INTEGER;
1554 }
1555
1556 if(AGS_IS_DIAL(child_widget)){
1557 AgsDial *dial;
1558 GtkAdjustment *adjustment;
1559
1560 LADSPA_Data lower_bound, upper_bound;
1561 gdouble lower, upper;
1562 LADSPA_Data default_value;
1563 gdouble control_value;
1564
1565 dial = (AgsDial *) child_widget;
1566
1567 if(disable_seemless){
1568 dial->flags &= (~AGS_DIAL_SEEMLESS_MODE);
1569 }
1570
1571 /* add controls of ports and apply range */
1572 g_rec_mutex_lock(plugin_port_mutex);
1573
1574 lower_bound = g_value_get_float(AGS_PLUGIN_PORT(plugin_port->data)->lower_value);
1575 upper_bound = g_value_get_float(AGS_PLUGIN_PORT(plugin_port->data)->upper_value);
1576
1577 g_rec_mutex_unlock(plugin_port_mutex);
1578
1579 if(do_step_conversion){
1580 g_object_set(ladspa_conversion,
1581 "lower", lower_bound,
1582 "upper", upper_bound,
1583 NULL);
1584
1585 lower = 0.0;
1586 upper = AGS_LADSPA_CONVERSION_DEFAULT_STEP_COUNT - 1.0;
1587
1588 #if 0
1589 if(!disable_seemless){
1590 g_object_get(ladspa_conversion,
1591 "step-count", &step_count,
1592 NULL);
1593 }
1594 #endif
1595 }else{
1596 lower = lower_bound;
1597 upper = upper_bound;
1598 }
1599
1600 adjustment = (GtkAdjustment *) gtk_adjustment_new(0.0, 0.0, 1.0, 0.1, 0.1, 0.0);
1601 g_object_set(dial,
1602 "adjustment", adjustment,
1603 NULL);
1604
1605 if(upper >= 0.0 && lower >= 0.0){
1606 step = (upper - lower) / step_count;
1607 }else if(upper < 0.0 && lower < 0.0){
1608 step = -1.0 * (lower - upper) / step_count;
1609 }else{
1610 step = (upper - lower) / step_count;
1611 }
1612
1613 if(step_count > 8){
1614 if(upper >= 0.0 && lower >= 0.0){
1615 page = (upper - lower) / AGS_DIAL_DEFAULT_PRECISION;
1616 }else if(upper < 0.0 && lower < 0.0){
1617 page = -1.0 * (lower - upper) / AGS_DIAL_DEFAULT_PRECISION;
1618 }else{
1619 page = (upper - lower) / AGS_DIAL_DEFAULT_PRECISION;
1620 }
1621 }else{
1622 page = step;
1623 }
1624
1625 gtk_adjustment_set_step_increment(adjustment,
1626 step);
1627 gtk_adjustment_set_page_increment(adjustment,
1628 page);
1629 gtk_adjustment_set_lower(adjustment,
1630 lower);
1631 gtk_adjustment_set_upper(adjustment,
1632 upper);
1633
1634 g_rec_mutex_lock(plugin_port_mutex);
1635
1636 default_value = (LADSPA_Data) g_value_get_float(AGS_PLUGIN_PORT(plugin_port->data)->default_value);
1637
1638 g_rec_mutex_unlock(plugin_port_mutex);
1639
1640 control_value = default_value;
1641
1642 if(ladspa_conversion != NULL){
1643 control_value = ags_conversion_convert((AgsConversion *) ladspa_conversion,
1644 default_value,
1645 TRUE);
1646 }
1647
1648 gtk_adjustment_set_value(adjustment,
1649 control_value);
1650
1651 #ifdef AGS_DEBUG
1652 g_message("dssi bounds: %f %f", lower, upper);
1653 #endif
1654 }else if(AGS_IS_INDICATOR(child_widget) ||
1655 AGS_IS_LED(child_widget)){
1656 g_hash_table_insert(ags_effect_bulk_indicator_queue_draw,
1657 child_widget, ags_effect_bulk_indicator_queue_draw_timeout);
1658 effect_bulk->queued_drawing = g_list_prepend(effect_bulk->queued_drawing,
1659 child_widget);
1660 g_timeout_add(AGS_UI_PROVIDER_DEFAULT_TIMEOUT * 1000.0, (GSourceFunc) ags_effect_bulk_indicator_queue_draw_timeout, (gpointer) child_widget);
1661 }
1662
1663 gtk_widget_set_halign(bulk_member,
1664 GTK_ALIGN_FILL);
1665 gtk_widget_set_valign(bulk_member,
1666 GTK_ALIGN_FILL);
1667
1668 gtk_grid_attach(effect_bulk->grid,
1669 (GtkWidget *) bulk_member,
1670 x, y,
1671 1, 1);
1672 ags_connectable_connect(AGS_CONNECTABLE(bulk_member));
1673 gtk_widget_show_all((GtkWidget *) effect_bulk->grid);
1674
1675 /* iterate */
1676 x++;
1677 }
1678
1679 /* iterate */
1680 plugin_port = plugin_port->next;
1681 k++;
1682 }
1683
1684 effect_bulk_plugin->control_count = control_count;
1685
1686 g_list_free_full(start_plugin_port,
1687 g_object_unref);
1688 }
1689
1690 void
ags_effect_bulk_add_lv2_plugin(AgsEffectBulk * effect_bulk,GList * control_type_name,AgsRecallContainer * play_container,AgsRecallContainer * recall_container,gchar * plugin_name,gchar * filename,gchar * effect,guint start_audio_channel,guint stop_audio_channel,guint start_pad,guint stop_pad,gint position,guint create_flags,guint recall_flags)1691 ags_effect_bulk_add_lv2_plugin(AgsEffectBulk *effect_bulk,
1692 GList *control_type_name,
1693 AgsRecallContainer *play_container, AgsRecallContainer *recall_container,
1694 gchar *plugin_name,
1695 gchar *filename,
1696 gchar *effect,
1697 guint start_audio_channel, guint stop_audio_channel,
1698 guint start_pad, guint stop_pad,
1699 gint position,
1700 guint create_flags, guint recall_flags)
1701 {
1702 AgsBulkMember *bulk_member;
1703
1704 AgsEffectBulkPlugin *effect_bulk_plugin;
1705
1706 AgsLv2Manager *lv2_manager;
1707 AgsLv2Plugin *lv2_plugin;
1708
1709 GList *start_recall, *recall;
1710 GList *start_list, *list;
1711 GList *start_plugin_port, *plugin_port;
1712
1713 gchar *uri;
1714 gchar *port_name;
1715
1716 gboolean is_lv2_plugin;
1717
1718 gdouble page, step;
1719 guint pads, audio_channels;
1720 guint port_count;
1721 guint control_count;
1722
1723 guint x, y;
1724 guint k;
1725
1726 GRecMutex *lv2_manager_mutex;
1727 GRecMutex *base_plugin_mutex;
1728
1729 lv2_manager = ags_lv2_manager_get_instance();
1730
1731 lv2_manager_mutex = AGS_LV2_MANAGER_GET_OBJ_MUTEX(lv2_manager);
1732
1733 pads = 0;
1734 audio_channels = 0;
1735
1736 /* make sure turtle is parsed */
1737 g_rec_mutex_lock(lv2_manager_mutex);
1738
1739 is_lv2_plugin = ((lv2_manager->quick_scan_plugin_filename != NULL &&
1740 g_strv_contains(lv2_manager->quick_scan_plugin_filename,
1741 filename)) ||
1742 (lv2_manager->quick_scan_instrument_filename != NULL &&
1743 g_strv_contains(lv2_manager->quick_scan_instrument_filename,
1744 filename))) ? TRUE: FALSE;
1745
1746 g_rec_mutex_unlock(lv2_manager_mutex);
1747
1748 if(filename != NULL &&
1749 effect != NULL &&
1750 is_lv2_plugin){
1751 AgsTurtle *manifest;
1752 AgsTurtleManager *turtle_manager;
1753
1754 gchar *path;
1755 gchar *manifest_filename;
1756
1757 turtle_manager = ags_turtle_manager_get_instance();
1758
1759 path = g_path_get_dirname(filename);
1760
1761 manifest_filename = g_strdup_printf("%s%c%s",
1762 path,
1763 G_DIR_SEPARATOR,
1764 "manifest.ttl");
1765
1766 manifest = (AgsTurtle *) ags_turtle_manager_find(turtle_manager,
1767 manifest_filename);
1768
1769 if(manifest == NULL){
1770 AgsLv2TurtleParser *lv2_turtle_parser;
1771
1772 AgsTurtle **turtle;
1773
1774 guint n_turtle;
1775
1776 g_message("new turtle [Manifest] - %s", manifest_filename);
1777
1778 manifest = ags_turtle_new(manifest_filename);
1779 ags_turtle_load(manifest,
1780 NULL);
1781 ags_turtle_manager_add(turtle_manager,
1782 (GObject *) manifest);
1783
1784 lv2_turtle_parser = ags_lv2_turtle_parser_new(manifest);
1785
1786 n_turtle = 1;
1787 turtle = (AgsTurtle **) malloc(2 * sizeof(AgsTurtle *));
1788
1789 turtle[0] = manifest;
1790 turtle[1] = NULL;
1791
1792 ags_lv2_turtle_parser_parse(lv2_turtle_parser,
1793 turtle, n_turtle);
1794
1795 g_object_run_dispose((GObject *) lv2_turtle_parser);
1796 g_object_unref(lv2_turtle_parser);
1797
1798 g_object_unref(manifest);
1799
1800 free(turtle);
1801 }
1802
1803 g_free(manifest_filename);
1804 }
1805
1806 /* alloc effect bulk plugin */
1807 effect_bulk_plugin = ags_effect_bulk_plugin_alloc(play_container, recall_container,
1808 plugin_name,
1809 filename,
1810 effect);
1811 effect_bulk_plugin->control_type_name = control_type_name;
1812
1813 effect_bulk->plugin = g_list_append(effect_bulk->plugin,
1814 effect_bulk_plugin);
1815
1816 /* get audio properties */
1817 g_object_get(effect_bulk->audio,
1818 "audio-channels", &audio_channels,
1819 NULL);
1820
1821 if(effect_bulk->channel_type == AGS_TYPE_OUTPUT){
1822 g_object_get(effect_bulk->audio,
1823 "output-pads", &pads,
1824 NULL);
1825 }else{
1826 g_object_get(effect_bulk->audio,
1827 "input-pads", &pads,
1828 NULL);
1829 }
1830
1831 /* load plugin */
1832 lv2_plugin = ags_lv2_manager_find_lv2_plugin(ags_lv2_manager_get_instance(),
1833 filename, effect);
1834
1835 /* get base plugin mutex */
1836 base_plugin_mutex = AGS_BASE_PLUGIN_GET_OBJ_MUTEX(lv2_plugin);
1837
1838 /* get uri */
1839 g_rec_mutex_lock(base_plugin_mutex);
1840
1841 uri = g_strdup(lv2_plugin->uri);
1842
1843 g_rec_mutex_unlock(base_plugin_mutex);
1844
1845 /* ags-fx-lv2 */
1846 start_recall = ags_fx_factory_create(effect_bulk->audio,
1847 effect_bulk_plugin->play_container, effect_bulk_plugin->recall_container,
1848 plugin_name,
1849 filename,
1850 effect,
1851 0, audio_channels,
1852 0, pads,
1853 position,
1854 create_flags | (g_type_is_a(effect_bulk->channel_type, AGS_TYPE_OUTPUT) ? AGS_FX_FACTORY_OUTPUT: AGS_FX_FACTORY_INPUT), recall_flags);
1855
1856 recall = start_recall;
1857
1858 while(recall != NULL){
1859 ags_recall_set_behaviour_flags(recall->data, AGS_SOUND_BEHAVIOUR_BULK_MODE);
1860
1861 recall = recall->next;
1862 }
1863
1864 g_list_free_full(start_recall,
1865 (GDestroyNotify) g_object_unref);
1866
1867 /* retrieve position within table */
1868 x = 0;
1869 y = 0;
1870
1871 list =
1872 start_list = gtk_container_get_children(GTK_CONTAINER(effect_bulk->grid));
1873
1874 while(list != NULL){
1875 guint top_attach;
1876
1877 gtk_container_child_get(GTK_CONTAINER(effect_bulk->grid),
1878 list->data,
1879 "top-attach", &top_attach,
1880 NULL);
1881
1882 if(y <= top_attach){
1883 y = top_attach + 1;
1884 }
1885
1886 list = list->next;
1887 }
1888
1889 g_list_free(start_list);
1890
1891 /* load ports */
1892 g_object_get(lv2_plugin,
1893 "plugin-port", &start_plugin_port,
1894 NULL);
1895
1896 plugin_port = start_plugin_port;
1897
1898 port_count = g_list_length(plugin_port);
1899
1900 control_count = 0;
1901
1902 k = 0;
1903
1904 while(plugin_port != NULL){
1905 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_CONTROL)){
1906 GtkWidget *child_widget;
1907
1908 AgsLv2Conversion *lv2_conversion;
1909
1910 GType widget_type;
1911
1912 gchar *plugin_name;
1913 gchar *control_port;
1914
1915 guint port_index;
1916 guint scale_precision;
1917 gdouble step_count;
1918 gboolean disable_seemless;
1919 gboolean do_step_conversion;
1920
1921 GRecMutex *plugin_port_mutex;
1922
1923 control_count++;
1924
1925 disable_seemless = FALSE;
1926 do_step_conversion = FALSE;
1927
1928 if(x == AGS_EFFECT_BULK_COLUMNS_COUNT){
1929 x = 0;
1930 y++;
1931 }
1932
1933 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_TOGGLED)){
1934 disable_seemless = TRUE;
1935
1936 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_OUTPUT)){
1937 widget_type = AGS_TYPE_LED;
1938 }else{
1939 widget_type = GTK_TYPE_TOGGLE_BUTTON;
1940 }
1941 }else{
1942 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_OUTPUT)){
1943 widget_type = AGS_TYPE_HINDICATOR;
1944 }else{
1945 widget_type = AGS_TYPE_DIAL;
1946 }
1947 }
1948
1949 scale_precision = AGS_DIAL_DEFAULT_PRECISION;
1950 step_count = AGS_LV2_CONVERSION_DEFAULT_STEP_COUNT;
1951
1952 if((AGS_PLUGIN_PORT_INTEGER & (AGS_PLUGIN_PORT(plugin_port->data)->flags)) != 0){
1953 guint scale_steps;
1954
1955 g_object_get(plugin_port->data,
1956 "scale-steps", &scale_steps,
1957 NULL);
1958
1959 step_count =
1960 scale_precision = (gdouble) scale_steps;
1961
1962 disable_seemless = TRUE;
1963 }
1964
1965 /* get plugin port mutex */
1966 plugin_port_mutex = AGS_PLUGIN_PORT_GET_OBJ_MUTEX(plugin_port->data);
1967
1968 /* get port name */
1969 g_rec_mutex_lock(plugin_port_mutex);
1970
1971 port_name = g_strdup(AGS_PLUGIN_PORT(plugin_port->data)->port_name);
1972 port_index = AGS_PLUGIN_PORT(plugin_port->data)->port_index;
1973
1974 g_rec_mutex_unlock(plugin_port_mutex);
1975
1976 /* add bulk member */
1977 plugin_name = g_strdup_printf("lv2-<%s>",
1978 uri);
1979
1980 control_port = g_strdup_printf("%u/%u",
1981 k + 1,
1982 port_count);
1983
1984 bulk_member = (AgsBulkMember *) g_object_new(AGS_TYPE_BULK_MEMBER,
1985 "widget-type", widget_type,
1986 "widget-label", port_name,
1987 "play-container", play_container,
1988 "recall-container", recall_container,
1989 "plugin-name", plugin_name,
1990 "filename", filename,
1991 "effect", effect,
1992 "specifier", port_name,
1993 "port-index", port_index,
1994 "control-port", control_port,
1995 "scale-precision", scale_precision,
1996 "step-count", step_count,
1997 NULL);
1998 child_widget = ags_bulk_member_get_widget(bulk_member);
1999
2000 g_free(plugin_name);
2001 g_free(control_port);
2002 g_free(port_name);
2003
2004 /* lv2 conversion */
2005 lv2_conversion = NULL;
2006
2007 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_LOGARITHMIC)){
2008 if(lv2_conversion == NULL ||
2009 !AGS_IS_LV2_CONVERSION(lv2_conversion)){
2010 lv2_conversion = ags_lv2_conversion_new();
2011 }
2012
2013 lv2_conversion->flags |= AGS_LV2_CONVERSION_LOGARITHMIC;
2014
2015 do_step_conversion = TRUE;
2016 }
2017
2018 g_object_set(bulk_member,
2019 "conversion", lv2_conversion,
2020 NULL);
2021
2022 /* child widget */
2023 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_TOGGLED)){
2024 bulk_member->port_flags = AGS_BULK_MEMBER_PORT_BOOLEAN;
2025 }
2026
2027 if(ags_plugin_port_test_flags(plugin_port->data, AGS_PLUGIN_PORT_INTEGER)){
2028 bulk_member->port_flags = AGS_BULK_MEMBER_PORT_INTEGER;
2029 }
2030
2031 if(AGS_IS_DIAL(child_widget)){
2032 AgsDial *dial;
2033 GtkAdjustment *adjustment;
2034
2035 float lower_bound, upper_bound;
2036 gdouble lower, upper;
2037 float default_value;
2038 gdouble control_value;
2039
2040 dial = (AgsDial *) child_widget;
2041
2042 if(disable_seemless){
2043 dial->flags &= (~AGS_DIAL_SEEMLESS_MODE);
2044 }
2045
2046 /* add controls of ports and apply range */
2047 g_rec_mutex_lock(plugin_port_mutex);
2048
2049 lower_bound = g_value_get_float(AGS_PLUGIN_PORT(plugin_port->data)->lower_value);
2050 upper_bound = g_value_get_float(AGS_PLUGIN_PORT(plugin_port->data)->upper_value);
2051
2052 g_rec_mutex_unlock(plugin_port_mutex);
2053
2054 if(do_step_conversion){
2055 g_object_set(lv2_conversion,
2056 "lower", lower_bound,
2057 "upper", upper_bound,
2058 NULL);
2059
2060 lower = 0.0;
2061 upper = AGS_LV2_CONVERSION_DEFAULT_STEP_COUNT - 1.0;
2062
2063 #if 0
2064 if(!disable_seemless){
2065 g_object_get(lv2_conversion,
2066 "step-count", &step_count,
2067 NULL);
2068 }
2069 #endif
2070 }else{
2071 lower = lower_bound;
2072 upper = upper_bound;
2073 }
2074
2075 adjustment = (GtkAdjustment *) gtk_adjustment_new(0.0, 0.0, 1.0, 0.1, 0.1, 0.0);
2076 g_object_set(dial,
2077 "adjustment", adjustment,
2078 NULL);
2079
2080 if(upper >= 0.0 && lower >= 0.0){
2081 step = (upper - lower) / step_count;
2082 }else if(upper < 0.0 && lower < 0.0){
2083 step = -1.0 * (lower - upper) / step_count;
2084 }else{
2085 step = (upper - lower) / step_count;
2086 }
2087
2088 if(step_count > 8){
2089 if(upper >= 0.0 && lower >= 0.0){
2090 page = (upper - lower) / AGS_DIAL_DEFAULT_PRECISION;
2091 }else if(upper < 0.0 && lower < 0.0){
2092 page = -1.0 * (lower - upper) / AGS_DIAL_DEFAULT_PRECISION;
2093 }else{
2094 page = (upper - lower) / AGS_DIAL_DEFAULT_PRECISION;
2095 }
2096 }else{
2097 page = step;
2098 }
2099
2100 gtk_adjustment_set_step_increment(adjustment,
2101 step);
2102 gtk_adjustment_set_page_increment(adjustment,
2103 page);
2104 gtk_adjustment_set_lower(adjustment,
2105 lower);
2106 gtk_adjustment_set_upper(adjustment,
2107 upper);
2108
2109 /* get/set default value */
2110 g_rec_mutex_lock(plugin_port_mutex);
2111
2112 default_value = (float) g_value_get_float(AGS_PLUGIN_PORT(plugin_port->data)->default_value);
2113
2114 g_rec_mutex_unlock(plugin_port_mutex);
2115
2116 control_value = default_value;
2117
2118 if(lv2_conversion != NULL){
2119 control_value = ags_conversion_convert((AgsConversion *) lv2_conversion,
2120 default_value,
2121 TRUE);
2122 }
2123
2124 gtk_adjustment_set_value(adjustment,
2125 control_value);
2126 }else if(AGS_IS_INDICATOR(child_widget) ||
2127 AGS_IS_LED(child_widget)){
2128 g_hash_table_insert(ags_effect_bulk_indicator_queue_draw,
2129 child_widget, ags_effect_bulk_indicator_queue_draw_timeout);
2130
2131 effect_bulk->queued_drawing = g_list_prepend(effect_bulk->queued_drawing,
2132 child_widget);
2133
2134 g_timeout_add(AGS_UI_PROVIDER_DEFAULT_TIMEOUT * 1000.0,
2135 (GSourceFunc) ags_effect_bulk_indicator_queue_draw_timeout,
2136 (gpointer) child_widget);
2137 }
2138
2139 #ifdef AGS_DEBUG
2140 g_message("lv2 bounds: %f %f", lower, upper);
2141 #endif
2142
2143 gtk_widget_set_halign(bulk_member,
2144 GTK_ALIGN_FILL);
2145 gtk_widget_set_valign(bulk_member,
2146 GTK_ALIGN_FILL);
2147
2148 gtk_grid_attach(effect_bulk->grid,
2149 (GtkWidget *) bulk_member,
2150 x, y,
2151 1, 1);
2152 ags_connectable_connect(AGS_CONNECTABLE(bulk_member));
2153 gtk_widget_show_all((GtkWidget *) effect_bulk->grid);
2154
2155 /* iterate */
2156 x++;
2157 }
2158
2159 /* iterate */
2160 plugin_port = plugin_port->next;
2161 k++;
2162 }
2163
2164 effect_bulk_plugin->control_count = control_count;
2165
2166 g_list_free_full(start_plugin_port,
2167 g_object_unref);
2168
2169 g_free(uri);
2170 }
2171
2172 void
ags_effect_bulk_real_add_plugin(AgsEffectBulk * effect_bulk,GList * control_type_name,AgsRecallContainer * play_container,AgsRecallContainer * recall_container,gchar * plugin_name,gchar * filename,gchar * effect,guint start_audio_channel,guint stop_audio_channel,guint start_pad,guint stop_pad,gint position,guint create_flags,guint recall_flags)2173 ags_effect_bulk_real_add_plugin(AgsEffectBulk *effect_bulk,
2174 GList *control_type_name,
2175 AgsRecallContainer *play_container, AgsRecallContainer *recall_container,
2176 gchar *plugin_name,
2177 gchar *filename,
2178 gchar *effect,
2179 guint start_audio_channel, guint stop_audio_channel,
2180 guint start_pad, guint stop_pad,
2181 gint position,
2182 guint create_flags, guint recall_flags)
2183 {
2184 AgsBasePlugin *base_plugin;
2185
2186 gchar *fallback_filename;
2187
2188 base_plugin = NULL;
2189
2190 fallback_filename = NULL;
2191
2192 if(!g_ascii_strncasecmp(plugin_name,
2193 "ags-fx-ladspa",
2194 14)){
2195 base_plugin = (AgsBasePlugin *) ags_ladspa_manager_find_ladspa_plugin_with_fallback(ags_ladspa_manager_get_instance(),
2196 filename, effect);
2197 }else if(!g_ascii_strncasecmp(plugin_name,
2198 "ags-fx-dssi",
2199 12)){
2200 base_plugin = (AgsBasePlugin *) ags_dssi_manager_find_dssi_plugin_with_fallback(ags_dssi_manager_get_instance(),
2201 filename, effect);
2202 }else if(!g_ascii_strncasecmp(plugin_name,
2203 "ags-fx-lv2",
2204 11)){
2205 base_plugin = (AgsBasePlugin *) ags_lv2_manager_find_lv2_plugin_with_fallback(ags_lv2_manager_get_instance(),
2206 filename, effect);
2207 }
2208
2209 if(base_plugin != NULL){
2210 g_object_get(base_plugin,
2211 "filename", &fallback_filename,
2212 NULL);
2213 }else{
2214 fallback_filename = g_strdup(filename);
2215 }
2216
2217 if((AGS_FX_FACTORY_ADD & (create_flags)) != 0){
2218 if(!g_ascii_strncasecmp(plugin_name,
2219 "ags-fx-ladspa",
2220 14)){
2221 ags_effect_bulk_add_ladspa_plugin(effect_bulk,
2222 control_type_name,
2223 play_container, recall_container,
2224 plugin_name,
2225 fallback_filename,
2226 effect,
2227 start_audio_channel, stop_audio_channel,
2228 start_pad, stop_pad,
2229 position,
2230 create_flags, recall_flags);
2231 }else if(!g_ascii_strncasecmp(plugin_name,
2232 "ags-fx-dssi",
2233 12)){
2234 ags_effect_bulk_add_dssi_plugin(effect_bulk,
2235 control_type_name,
2236 play_container, recall_container,
2237 plugin_name,
2238 fallback_filename,
2239 effect,
2240 start_audio_channel, stop_audio_channel,
2241 start_pad, stop_pad,
2242 position,
2243 create_flags, recall_flags);
2244 }else if(!g_ascii_strncasecmp(plugin_name,
2245 "ags-fx-lv2",
2246 11)){
2247 ags_effect_bulk_add_lv2_plugin(effect_bulk,
2248 control_type_name,
2249 play_container, recall_container,
2250 plugin_name,
2251 fallback_filename,
2252 effect,
2253 start_audio_channel, stop_audio_channel,
2254 start_pad, stop_pad,
2255 position,
2256 create_flags, recall_flags);
2257 }
2258 }else if((AGS_FX_FACTORY_REMAP & (create_flags)) != 0){
2259 GList *start_list, *list;
2260 GList *start_recall, *recall;
2261
2262 /* plugin_name */
2263 start_recall = ags_fx_factory_create(effect_bulk->audio,
2264 play_container, recall_container,
2265 plugin_name,
2266 fallback_filename,
2267 effect,
2268 start_audio_channel, stop_audio_channel,
2269 start_pad, stop_pad,
2270 position,
2271 create_flags | (g_type_is_a(effect_bulk->channel_type, AGS_TYPE_OUTPUT) ? AGS_FX_FACTORY_OUTPUT: AGS_FX_FACTORY_INPUT), recall_flags);
2272
2273 recall = start_recall;
2274
2275 while(recall != NULL){
2276 ags_recall_set_behaviour_flags(recall->data, AGS_SOUND_BEHAVIOUR_BULK_MODE);
2277
2278 recall = recall->next;
2279 }
2280
2281 /* unref */
2282 g_list_free_full(start_recall,
2283 (GDestroyNotify) g_object_unref);
2284
2285 /* */
2286 list =
2287 start_list = gtk_container_get_children((GtkContainer *) effect_bulk->grid);
2288
2289 while(list != NULL){
2290 if(AGS_IS_BULK_MEMBER(list->data) &&
2291 AGS_BULK_MEMBER(list->data)->play_container == play_container){
2292 ags_bulk_member_remap_bulk_port(list->data);
2293 }
2294
2295 list = list->next;
2296 }
2297
2298 g_list_free(start_list);
2299 }
2300
2301 g_free(fallback_filename);
2302 }
2303
2304 /**
2305 * ags_effect_bulk_add_plugin:
2306 * @effect_bulk: the #AgsEffectBulk to modify
2307 * @control_type_name: the #GList-struct containing string representation of a #GType
2308 * @play_container: an #AgsRecallContainer to indetify what recall to use
2309 * @recall_container: an #AgsRecallContainer to indetify what recall to use
2310 * @plugin_name: the plugin identifier
2311 * @filename: the effect's filename
2312 * @effect: the effect's name
2313 * @start_audio_channel: the first audio channel to apply
2314 * @stop_audio_channel: the last audio channel to apply
2315 * @start_pad: the first pad to apply
2316 * @stop_pad: the last pad to apply
2317 * @position: the position to insert the recall
2318 * @create_flags: modify the behaviour of this function
2319 * @recall_flags: flags to be set for #AgsRecall
2320 *
2321 * Add an effect by its filename and effect specifier.
2322 *
2323 * Since: 3.3.0
2324 */
2325 void
ags_effect_bulk_add_plugin(AgsEffectBulk * effect_bulk,GList * control_type_name,AgsRecallContainer * play_container,AgsRecallContainer * recall_container,gchar * plugin_name,gchar * filename,gchar * effect,guint start_audio_channel,guint stop_audio_channel,guint start_pad,guint stop_pad,gint position,guint create_flags,guint recall_flags)2326 ags_effect_bulk_add_plugin(AgsEffectBulk *effect_bulk,
2327 GList *control_type_name,
2328 AgsRecallContainer *play_container, AgsRecallContainer *recall_container,
2329 gchar *plugin_name,
2330 gchar *filename,
2331 gchar *effect,
2332 guint start_audio_channel, guint stop_audio_channel,
2333 guint start_pad, guint stop_pad,
2334 gint position,
2335 guint create_flags, guint recall_flags)
2336 {
2337 g_return_if_fail(AGS_IS_EFFECT_BULK(effect_bulk));
2338
2339 g_object_ref((GObject *) effect_bulk);
2340 g_signal_emit(G_OBJECT(effect_bulk),
2341 effect_bulk_signals[ADD_PLUGIN], 0,
2342 control_type_name,
2343 play_container, recall_container,
2344 plugin_name,
2345 filename,
2346 effect,
2347 start_audio_channel, stop_audio_channel,
2348 start_pad, stop_pad,
2349 position,
2350 create_flags, recall_flags);
2351 g_object_unref((GObject *) effect_bulk);
2352 }
2353
2354 void
ags_effect_bulk_real_remove_plugin(AgsEffectBulk * effect_bulk,guint nth)2355 ags_effect_bulk_real_remove_plugin(AgsEffectBulk *effect_bulk,
2356 guint nth)
2357 {
2358 AgsEffectBulkPlugin *effect_bulk_plugin;
2359
2360 AgsChannel *start_channel;
2361 AgsChannel *channel, *next_channel;
2362
2363 GList *start_list, *list;
2364 GList *start_recall, *recall;
2365
2366 if(!AGS_IS_EFFECT_BULK(effect_bulk)){
2367 return;
2368 }
2369
2370 start_channel = NULL;
2371
2372 list = g_list_nth(effect_bulk->plugin,
2373 nth);
2374
2375 if(list == NULL){
2376 return;
2377 }
2378
2379 effect_bulk_plugin = list->data;
2380
2381 /* */
2382 effect_bulk->plugin = g_list_remove(effect_bulk->plugin,
2383 effect_bulk_plugin);
2384
2385 /* AgsRecallAudio */
2386 ags_audio_remove_recall(effect_bulk->audio, (GObject *) ags_recall_container_get_recall_audio(effect_bulk_plugin->play_container),
2387 TRUE);
2388
2389 ags_audio_remove_recall(effect_bulk->audio, (GObject *) ags_recall_container_get_recall_audio(effect_bulk_plugin->recall_container),
2390 FALSE);
2391
2392 /* AgsRecallAudioRun - play context */
2393 g_object_get(effect_bulk_plugin->play_container,
2394 "recall-audio-run", &start_recall,
2395 NULL);
2396
2397 recall = start_recall;
2398
2399 while(recall != NULL){
2400 ags_audio_remove_recall(effect_bulk->audio, (GObject *) recall->data,
2401 TRUE);
2402
2403 recall = recall->next;
2404 }
2405
2406 g_list_free_full(start_recall,
2407 (GDestroyNotify) g_object_unref);
2408
2409 /* AgsRecallAudioRun - recall context */
2410 g_object_get(effect_bulk_plugin->recall_container,
2411 "recall-audio-run", &start_recall,
2412 NULL);
2413
2414 recall = start_recall;
2415
2416 while(recall != NULL){
2417 ags_audio_remove_recall(effect_bulk->audio, (GObject *) recall->data,
2418 FALSE);
2419
2420 recall = recall->next;
2421 }
2422
2423 g_list_free_full(start_recall,
2424 (GDestroyNotify) g_object_unref);
2425
2426 /* AgsRecallChannel - play context */
2427 g_object_get(effect_bulk_plugin->play_container,
2428 "recall-channel", &start_recall,
2429 NULL);
2430
2431 recall = start_recall;
2432
2433 while(recall != NULL){
2434 AgsChannel *channel;
2435
2436 g_object_get(recall->data,
2437 "source", &channel,
2438 NULL);
2439
2440 ags_channel_remove_recall(channel, (GObject *) recall->data,
2441 TRUE);
2442
2443 if(channel != NULL){
2444 g_object_unref(channel);
2445 }
2446
2447 recall = recall->next;
2448 }
2449
2450 g_list_free_full(start_recall,
2451 (GDestroyNotify) g_object_unref);
2452
2453 /* AgsRecallChannel - recall context */
2454 g_object_get(effect_bulk_plugin->recall_container,
2455 "recall-channel", &start_recall,
2456 NULL);
2457
2458 recall = start_recall;
2459
2460 while(recall != NULL){
2461 AgsChannel *channel;
2462
2463 g_object_get(recall->data,
2464 "source", &channel,
2465 NULL);
2466
2467 ags_channel_remove_recall(channel, (GObject *) recall->data,
2468 FALSE);
2469
2470
2471 if(channel != NULL){
2472 g_object_unref(channel);
2473 }
2474
2475 recall = recall->next;
2476 }
2477
2478 g_list_free_full(start_recall,
2479 (GDestroyNotify) g_object_unref);
2480
2481 /* AgsRecallChannelRun - play context */
2482 g_object_get(effect_bulk_plugin->play_container,
2483 "recall-channel-run", &start_recall,
2484 NULL);
2485
2486 recall = start_recall;
2487
2488 while(recall != NULL){
2489 AgsChannel *channel;
2490
2491 g_object_get(recall->data,
2492 "source", &channel,
2493 NULL);
2494
2495 ags_channel_remove_recall(channel, (GObject *) recall->data,
2496 TRUE);
2497
2498 if(channel != NULL){
2499 g_object_unref(channel);
2500 }
2501
2502 recall = recall->next;
2503 }
2504
2505 g_list_free_full(start_recall,
2506 (GDestroyNotify) g_object_unref);
2507
2508 /* AgsRecallChannelRun - recall context */
2509 g_object_get(effect_bulk_plugin->recall_container,
2510 "recall-channel-run", &start_recall,
2511 NULL);
2512
2513 recall = start_recall;
2514
2515 while(recall != NULL){
2516 AgsChannel *channel;
2517
2518 g_object_get(recall->data,
2519 "source", &channel,
2520 NULL);
2521
2522 ags_channel_remove_recall(channel, (GObject *) recall->data,
2523 FALSE);
2524
2525 if(channel != NULL){
2526 g_object_unref(channel);
2527 }
2528
2529 recall = recall->next;
2530 }
2531
2532 g_list_free_full(start_recall,
2533 (GDestroyNotify) g_object_unref);
2534
2535 /* recall container */
2536 ags_audio_remove_recall_container(effect_bulk->audio, (GObject *) effect_bulk_plugin->play_container);
2537 ags_audio_remove_recall_container(effect_bulk->audio, (GObject *) effect_bulk_plugin->recall_container);
2538
2539 g_object_get(effect_bulk->audio,
2540 "input", &start_channel,
2541 NULL);
2542
2543 if(start_channel != NULL){
2544 channel = start_channel;
2545
2546 g_object_ref(channel);
2547
2548 while(channel != NULL){
2549 ags_channel_remove_recall_container(channel, effect_bulk_plugin->play_container);
2550 ags_channel_remove_recall_container(channel, effect_bulk_plugin->recall_container);
2551
2552 /* iterate */
2553 next_channel = ags_channel_next(channel);
2554
2555 g_object_unref(channel);
2556
2557 channel = next_channel;
2558 }
2559 }
2560
2561 if(start_channel != NULL){
2562 g_object_unref(start_channel);
2563 }
2564
2565 /* destroy controls - bulk member */
2566 start_list = gtk_container_get_children((GtkContainer *) effect_bulk->bulk_member);
2567
2568 list = g_list_nth(start_list,
2569 nth);
2570
2571 if(list != NULL){
2572 gtk_widget_destroy(list->data);
2573 }
2574
2575 g_list_free(start_list);
2576
2577 /* destroy controls - table */
2578 start_list = gtk_container_get_children((GtkContainer *) effect_bulk->grid);
2579
2580 list = start_list;
2581
2582 while(list != NULL){
2583 if(AGS_IS_BULK_MEMBER(list->data) &&
2584 AGS_BULK_MEMBER(list->data)->play_container == effect_bulk_plugin->play_container){
2585 GtkWidget *child_widget;
2586
2587 child_widget = gtk_bin_get_child(list->data);
2588
2589 if(AGS_IS_INDICATOR(child_widget) ||
2590 AGS_IS_LED(child_widget)){
2591 g_hash_table_remove(ags_effect_bulk_indicator_queue_draw,
2592 child_widget);
2593 }
2594
2595 gtk_widget_destroy(list->data);
2596 }
2597
2598 list = list->next;
2599 }
2600
2601 g_list_free(start_list);
2602
2603 /* free AgsEffectBulkPlugin */
2604 ags_effect_bulk_plugin_free(effect_bulk_plugin);
2605 }
2606
2607 /**
2608 * ags_effect_bulk_remove_plugin:
2609 * @effect_bulk: the #AgsEffectBulk to modify
2610 * @nth: the nth effect to remove
2611 *
2612 * Remove an effect by its position.
2613 *
2614 * Since: 3.3.0
2615 */
2616 void
ags_effect_bulk_remove_plugin(AgsEffectBulk * effect_bulk,guint nth)2617 ags_effect_bulk_remove_plugin(AgsEffectBulk *effect_bulk,
2618 guint nth)
2619 {
2620 g_return_if_fail(AGS_IS_EFFECT_BULK(effect_bulk));
2621
2622 g_object_ref((GObject *) effect_bulk);
2623 g_signal_emit(G_OBJECT(effect_bulk),
2624 effect_bulk_signals[REMOVE_PLUGIN], 0,
2625 nth);
2626 g_object_unref((GObject *) effect_bulk);
2627 }
2628
2629 void
ags_effect_bulk_real_resize_audio_channels(AgsEffectBulk * effect_bulk,guint new_size,guint old_size)2630 ags_effect_bulk_real_resize_audio_channels(AgsEffectBulk *effect_bulk,
2631 guint new_size,
2632 guint old_size)
2633 {
2634 //TODO:JK: implement me
2635 }
2636
2637 void
ags_effect_bulk_resize_audio_channels(AgsEffectBulk * effect_bulk,guint new_size,guint old_size)2638 ags_effect_bulk_resize_audio_channels(AgsEffectBulk *effect_bulk,
2639 guint new_size,
2640 guint old_size)
2641 {
2642 g_return_if_fail(AGS_IS_EFFECT_BULK(effect_bulk));
2643
2644 g_object_ref((GObject *) effect_bulk);
2645 g_signal_emit(G_OBJECT(effect_bulk),
2646 effect_bulk_signals[RESIZE_AUDIO_CHANNELS], 0,
2647 new_size,
2648 old_size);
2649 g_object_unref((GObject *) effect_bulk);
2650 }
2651
2652 void
ags_effect_bulk_real_resize_pads(AgsEffectBulk * effect_bulk,guint new_size,guint old_size)2653 ags_effect_bulk_real_resize_pads(AgsEffectBulk *effect_bulk,
2654 guint new_size,
2655 guint old_size)
2656 {
2657 //TODO:JK: implement me
2658 }
2659
2660 void
ags_effect_bulk_resize_pads(AgsEffectBulk * effect_bulk,guint new_size,guint old_size)2661 ags_effect_bulk_resize_pads(AgsEffectBulk *effect_bulk,
2662 guint new_size,
2663 guint old_size)
2664 {
2665 g_return_if_fail(AGS_IS_EFFECT_BULK(effect_bulk));
2666
2667 g_object_ref((GObject *) effect_bulk);
2668 g_signal_emit(G_OBJECT(effect_bulk),
2669 effect_bulk_signals[RESIZE_PADS], 0,
2670 new_size,
2671 old_size);
2672 g_object_unref((GObject *) effect_bulk);
2673 }
2674
2675 void
ags_effect_bulk_real_map_recall(AgsEffectBulk * effect_bulk)2676 ags_effect_bulk_real_map_recall(AgsEffectBulk *effect_bulk)
2677 {
2678 if((AGS_MACHINE_PREMAPPED_RECALL & (effect_bulk->flags)) == 0 ||
2679 (AGS_EFFECT_BULK_MAPPED_RECALL & (effect_bulk->flags)) != 0){
2680 return;
2681 }
2682
2683 effect_bulk->flags |= AGS_EFFECT_BULK_MAPPED_RECALL;
2684
2685 ags_effect_bulk_find_port(effect_bulk);
2686 }
2687
2688 /**
2689 * ags_effect_bulk_map_recall:
2690 * @effect_bulk: the #AgsEffectBulk to add its default recall.
2691 *
2692 * You may want the @effect_bulk to add its default recall.
2693 *
2694 * Since: 3.0.0
2695 */
2696 void
ags_effect_bulk_map_recall(AgsEffectBulk * effect_bulk)2697 ags_effect_bulk_map_recall(AgsEffectBulk *effect_bulk)
2698 {
2699 g_return_if_fail(AGS_IS_EFFECT_BULK(effect_bulk));
2700
2701 g_object_ref((GObject *) effect_bulk);
2702 g_signal_emit((GObject *) effect_bulk,
2703 effect_bulk_signals[MAP_RECALL], 0);
2704 g_object_unref((GObject *) effect_bulk);
2705 }
2706
2707 GList*
ags_effect_bulk_real_find_port(AgsEffectBulk * effect_bulk)2708 ags_effect_bulk_real_find_port(AgsEffectBulk *effect_bulk)
2709 {
2710 GList *bulk_member, *bulk_member_start;
2711
2712 GList *port, *tmp_port;
2713
2714 port = NULL;
2715
2716 /* find output ports */
2717 bulk_member_start =
2718 bulk_member = gtk_container_get_children((GtkContainer *) effect_bulk->grid);
2719
2720 if(bulk_member != NULL){
2721 while(bulk_member != NULL){
2722 tmp_port = ags_bulk_member_find_port(AGS_BULK_MEMBER(bulk_member->data));
2723
2724 if(port != NULL){
2725 port = g_list_concat(port,
2726 tmp_port);
2727 }else{
2728 port = tmp_port;
2729 }
2730
2731 bulk_member = bulk_member->next;
2732 }
2733
2734 g_list_free(bulk_member_start);
2735 }
2736
2737 return(port);
2738 }
2739
2740 /**
2741 * ags_effect_bulk_find_port:
2742 * @effect_bulk: the #AgsEffectBulk
2743 * Returns: an #GList containing all related #AgsPort
2744 *
2745 * Lookup ports of associated recalls.
2746 *
2747 * Since: 3.0.0
2748 */
2749 GList*
ags_effect_bulk_find_port(AgsEffectBulk * effect_bulk)2750 ags_effect_bulk_find_port(AgsEffectBulk *effect_bulk)
2751 {
2752 GList *list;
2753
2754 list = NULL;
2755 g_return_val_if_fail(AGS_IS_EFFECT_BULK(effect_bulk),
2756 NULL);
2757
2758 g_object_ref((GObject *) effect_bulk);
2759 g_signal_emit((GObject *) effect_bulk,
2760 effect_bulk_signals[FIND_PORT], 0,
2761 &list);
2762 g_object_unref((GObject *) effect_bulk);
2763
2764 return(list);
2765 }
2766
2767 /**
2768 * ags_effect_bulk_indicator_queue_draw_timeout:
2769 * @widget: the indicator widgt
2770 *
2771 * Queue draw widget
2772 *
2773 * Returns: %TRUE if proceed with redraw, otherwise %FALSE
2774 *
2775 * Since: 3.0.0
2776 */
2777 gboolean
ags_effect_bulk_indicator_queue_draw_timeout(GtkWidget * widget)2778 ags_effect_bulk_indicator_queue_draw_timeout(GtkWidget *widget)
2779 {
2780 if(g_hash_table_lookup(ags_effect_bulk_indicator_queue_draw,
2781 widget) != NULL){
2782 AgsBulkMember *bulk_member;
2783
2784 GList *list;
2785
2786 gdouble val;
2787
2788 bulk_member = (AgsBulkMember *) gtk_widget_get_ancestor(widget,
2789 AGS_TYPE_BULK_MEMBER);
2790
2791 list = bulk_member->bulk_port;
2792
2793 val = 0.0;
2794
2795 while(list != NULL){
2796 GValue value = {0,};
2797
2798 g_value_init(&value,
2799 G_TYPE_FLOAT);
2800
2801 ags_port_safe_read(AGS_BULK_PORT(list->data)->port,
2802 &value);
2803
2804 val += g_value_get_float(&value);
2805
2806 list = list->next;
2807 }
2808
2809 if(AGS_IS_LED(widget)){
2810 if(val != 0.0){
2811 ags_led_set_active((AgsLed *) widget);
2812 }else{
2813 ags_led_unset_active((AgsLed *) widget);
2814 }
2815 }else if(AGS_IS_INDICATOR(widget)){
2816 gtk_adjustment_set_value(AGS_INDICATOR(widget)->adjustment,
2817 val);
2818 }
2819
2820 gtk_widget_queue_draw(widget);
2821
2822 return(TRUE);
2823 }else{
2824 return(FALSE);
2825 }
2826 }
2827
2828 /**
2829 * ags_effect_bulk_new:
2830 * @audio: the #AgsAudio to visualize
2831 * @channel_type: either %AGS_TYPE_INPUT or %AGS_TYPE_OUTPUT
2832 *
2833 * Creates an #AgsEffectBulk
2834 *
2835 * Returns: a new #AgsEffectBulk
2836 *
2837 * Since: 3.0.0
2838 */
2839 AgsEffectBulk*
ags_effect_bulk_new(AgsAudio * audio,GType channel_type)2840 ags_effect_bulk_new(AgsAudio *audio,
2841 GType channel_type)
2842 {
2843 AgsEffectBulk *effect_bulk;
2844
2845 effect_bulk = (AgsEffectBulk *) g_object_new(AGS_TYPE_EFFECT_BULK,
2846 "audio", audio,
2847 "channel-type", channel_type,
2848 NULL);
2849
2850 return(effect_bulk);
2851 }
2852