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_bridge.h>
21 #include <ags/X/ags_effect_bridge_callbacks.h>
22
23 #include <ags/X/ags_machine.h>
24 #include <ags/X/ags_effect_pad.h>
25 #include <ags/X/ags_effect_bulk.h>
26
27 #include <ags/i18n.h>
28
29 void ags_effect_bridge_class_init(AgsEffectBridgeClass *effect_bridge);
30 void ags_effect_bridge_connectable_interface_init(AgsConnectableInterface *connectable);
31 void ags_effect_bridge_init(AgsEffectBridge *effect_bridge);
32 void ags_effect_bridge_set_property(GObject *gobject,
33 guint prop_id,
34 const GValue *value,
35 GParamSpec *param_spec);
36 void ags_effect_bridge_get_property(GObject *gobject,
37 guint prop_id,
38 GValue *value,
39 GParamSpec *param_spec);
40 void ags_effect_bridge_connect(AgsConnectable *connectable);
41 void ags_effect_bridge_disconnect(AgsConnectable *connectable);
42
43 void ags_effect_bridge_real_resize_audio_channels(AgsEffectBridge *effect_bridge,
44 guint new_size, guint old_size);
45 void ags_effect_bridge_real_resize_pads(AgsEffectBridge *effect_bridge,
46 GType channel_type,
47 guint new_size, guint old_size);
48 void ags_effect_bridge_real_map_recall(AgsEffectBridge *effect_bridge);
49 GList* ags_effect_bridge_real_find_port(AgsEffectBridge *effect_bridge);
50
51 /**
52 * SECTION:ags_effect_bridge
53 * @short_description: A composite widget to visualize a bunch of #AgsChannel
54 * @title: AgsEffectBridge
55 * @section_id:
56 * @include: ags/X/ags_effect_bridge.h
57 *
58 * #AgsEffectBridge is a composite widget containing #AgsEffectBulk or #AgsEffectPad. It should be
59 * packed by an #AgsMachine.
60 */
61
62 enum{
63 SAMPLERATE_CHANGED,
64 BUFFER_SIZE_CHANGED,
65 FORMAT_CHANGED,
66 RESIZE_AUDIO_CHANNELS,
67 RESIZE_PADS,
68 MAP_RECALL,
69 FIND_PORT,
70 LAST_SIGNAL,
71 };
72
73 enum{
74 PROP_0,
75 PROP_SAMPLERATE,
76 PROP_BUFFER_SIZE,
77 PROP_FORMAT,
78 PROP_AUDIO,
79 };
80
81 static gpointer ags_effect_bridge_parent_class = NULL;
82 static guint effect_bridge_signals[LAST_SIGNAL];
83
84 GType
ags_effect_bridge_get_type(void)85 ags_effect_bridge_get_type(void)
86 {
87 static volatile gsize g_define_type_id__volatile = 0;
88
89 if(g_once_init_enter (&g_define_type_id__volatile)){
90 GType ags_type_effect_bridge = 0;
91
92 static const GTypeInfo ags_effect_bridge_info = {
93 sizeof(AgsEffectBridgeClass),
94 NULL, /* base_init */
95 NULL, /* base_finalize */
96 (GClassInitFunc) ags_effect_bridge_class_init,
97 NULL, /* class_finalize */
98 NULL, /* class_data */
99 sizeof(AgsEffectBridge),
100 0, /* n_preallocs */
101 (GInstanceInitFunc) ags_effect_bridge_init,
102 };
103
104 static const GInterfaceInfo ags_connectable_interface_info = {
105 (GInterfaceInitFunc) ags_effect_bridge_connectable_interface_init,
106 NULL, /* interface_finalize */
107 NULL, /* interface_data */
108 };
109
110 ags_type_effect_bridge = g_type_register_static(GTK_TYPE_BOX,
111 "AgsEffectBridge", &ags_effect_bridge_info,
112 0);
113
114 g_type_add_interface_static(ags_type_effect_bridge,
115 AGS_TYPE_CONNECTABLE,
116 &ags_connectable_interface_info);
117
118 g_once_init_leave(&g_define_type_id__volatile, ags_type_effect_bridge);
119 }
120
121 return g_define_type_id__volatile;
122 }
123
124 void
ags_effect_bridge_class_init(AgsEffectBridgeClass * effect_bridge)125 ags_effect_bridge_class_init(AgsEffectBridgeClass *effect_bridge)
126 {
127 GObjectClass *gobject;
128 GParamSpec *param_spec;
129
130 ags_effect_bridge_parent_class = g_type_class_peek_parent(effect_bridge);
131
132 /* GObjectClass */
133 gobject = (GObjectClass *) effect_bridge;
134
135 gobject->set_property = ags_effect_bridge_set_property;
136 gobject->get_property = ags_effect_bridge_get_property;
137
138 /* properties */
139 /**
140 * AgsEffectBridge:samplerate:
141 *
142 * The samplerate.
143 *
144 * Since: 3.0.0
145 */
146 param_spec = g_param_spec_uint("samplerate",
147 i18n_pspec("samplerate"),
148 i18n_pspec("The samplerate"),
149 0,
150 G_MAXUINT32,
151 AGS_SOUNDCARD_DEFAULT_SAMPLERATE,
152 G_PARAM_READABLE | G_PARAM_WRITABLE);
153 g_object_class_install_property(gobject,
154 PROP_SAMPLERATE,
155 param_spec);
156
157 /**
158 * AgsEffectBridge:buffer-size:
159 *
160 * The buffer length.
161 *
162 * Since: 3.0.0
163 */
164 param_spec = g_param_spec_uint("buffer-size",
165 i18n_pspec("buffer size"),
166 i18n_pspec("The buffer size"),
167 0,
168 G_MAXUINT32,
169 AGS_SOUNDCARD_DEFAULT_BUFFER_SIZE,
170 G_PARAM_READABLE | G_PARAM_WRITABLE);
171 g_object_class_install_property(gobject,
172 PROP_BUFFER_SIZE,
173 param_spec);
174
175 /**
176 * AgsEffectBridge:format:
177 *
178 * The format.
179 *
180 * Since: 3.0.0
181 */
182 param_spec = g_param_spec_uint("format",
183 i18n_pspec("format"),
184 i18n_pspec("The format"),
185 0,
186 G_MAXUINT32,
187 AGS_SOUNDCARD_DEFAULT_FORMAT,
188 G_PARAM_READABLE | G_PARAM_WRITABLE);
189 g_object_class_install_property(gobject,
190 PROP_FORMAT,
191 param_spec);
192
193 /**
194 * AgsEffectBridge:audio:
195 *
196 * The start of a bunch of #AgsAudio to visualize.
197 *
198 * Since: 3.0.0
199 */
200 param_spec = g_param_spec_object("audio",
201 i18n_pspec("assigned audio"),
202 i18n_pspec("The audio it is assigned with"),
203 AGS_TYPE_AUDIO,
204 G_PARAM_READABLE | G_PARAM_WRITABLE);
205 g_object_class_install_property(gobject,
206 PROP_AUDIO,
207 param_spec);
208
209 /* AgsEffectBridgeClass */
210 effect_bridge->samplerate_changed = NULL;
211 effect_bridge->buffer_size_changed = NULL;
212 effect_bridge->format_changed = NULL;
213
214 effect_bridge->resize_pads = ags_effect_bridge_real_resize_pads;
215 effect_bridge->resize_audio_channels = ags_effect_bridge_real_resize_audio_channels;
216
217 effect_bridge->map_recall = ags_effect_bridge_real_map_recall;
218 effect_bridge->find_port = ags_effect_bridge_real_find_port;
219
220 /* signals */
221 /**
222 * AgsEffectBridge::samplerate-changed:
223 * @effect_bridge: the #AgsEffectBridge
224 * @samplerate: the samplerate
225 * @old_samplerate: the old samplerate
226 *
227 * The ::samplerate-changed signal notifies about changed samplerate.
228 *
229 * Since: 3.0.0
230 */
231 effect_bridge_signals[SAMPLERATE_CHANGED] =
232 g_signal_new("samplerate-changed",
233 G_TYPE_FROM_CLASS(effect_bridge),
234 G_SIGNAL_RUN_LAST,
235 G_STRUCT_OFFSET(AgsEffectBridgeClass, samplerate_changed),
236 NULL, NULL,
237 ags_cclosure_marshal_VOID__UINT_UINT,
238 G_TYPE_NONE, 2,
239 G_TYPE_UINT,
240 G_TYPE_UINT);
241
242 /**
243 * AgsEffectBridge::buffer-size-changed:
244 * @effect_bridge: the #AgsEffectBridge
245 * @buffer_size: the buffer size
246 * @old_buffer_size: the old buffer size
247 *
248 * The ::buffer-size-changed signal notifies about changed buffer size.
249 *
250 * Since: 3.0.0
251 */
252 effect_bridge_signals[BUFFER_SIZE_CHANGED] =
253 g_signal_new("buffer-size-changed",
254 G_TYPE_FROM_CLASS(effect_bridge),
255 G_SIGNAL_RUN_LAST,
256 G_STRUCT_OFFSET(AgsEffectBridgeClass, buffer_size_changed),
257 NULL, NULL,
258 ags_cclosure_marshal_VOID__UINT_UINT,
259 G_TYPE_NONE, 2,
260 G_TYPE_UINT,
261 G_TYPE_UINT);
262
263 /**
264 * AgsEffectBridge::format-changed:
265 * @effect_bridge: the #AgsEffectBridge
266 * @format: the format
267 * @old_format: the old format
268 *
269 * The ::format-changed signal notifies about changed format.
270 *
271 * Since: 3.0.0
272 */
273 effect_bridge_signals[FORMAT_CHANGED] =
274 g_signal_new("format-changed",
275 G_TYPE_FROM_CLASS(effect_bridge),
276 G_SIGNAL_RUN_LAST,
277 G_STRUCT_OFFSET(AgsEffectBridgeClass, format_changed),
278 NULL, NULL,
279 ags_cclosure_marshal_VOID__UINT_UINT,
280 G_TYPE_NONE, 2,
281 G_TYPE_UINT,
282 G_TYPE_UINT);
283
284 /**
285 * AgsEffectBridge::resize-audio-channels:
286 * @effect_bridge: the #AgsEffectBridge to modify
287 * @channel: the #AgsChannel to set
288 * @new_size: the new size
289 * @old_size: the old size
290 *
291 * The ::resize-audio-channels signal notifies about changed channel allocation within
292 * audio.
293 *
294 * Since: 3.0.0
295 */
296 effect_bridge_signals[RESIZE_AUDIO_CHANNELS] =
297 g_signal_new("resize-audio-channels",
298 G_TYPE_FROM_CLASS(effect_bridge),
299 G_SIGNAL_RUN_LAST,
300 G_STRUCT_OFFSET(AgsEffectBridgeClass, resize_audio_channels),
301 NULL, NULL,
302 ags_cclosure_marshal_VOID__UINT_UINT,
303 G_TYPE_NONE, 2,
304 G_TYPE_UINT,
305 G_TYPE_UINT);
306
307 /**
308 * AgsEffectBridge::resize-pads:
309 * @effect_bridge: the #AgsEffectBridge to modify
310 * @channel: the #AgsChannel to set
311 * @channel_type: either %AGS_TYPE_INPUT or %AGS_TYPE_OUTPUT
312 * @new_size: the new size
313 * @old_size: the old size
314 *
315 * The ::resize-pads signal notifies about changed channel allocation within
316 * audio.
317 *
318 * Since: 3.0.0
319 */
320 effect_bridge_signals[RESIZE_PADS] =
321 g_signal_new("resize-pads",
322 G_TYPE_FROM_CLASS(effect_bridge),
323 G_SIGNAL_RUN_LAST,
324 G_STRUCT_OFFSET(AgsEffectBridgeClass, resize_pads),
325 NULL, NULL,
326 ags_cclosure_marshal_VOID__ULONG_UINT_UINT,
327 G_TYPE_NONE, 3,
328 G_TYPE_ULONG,
329 G_TYPE_UINT,
330 G_TYPE_UINT);
331
332 /**
333 * AgsEffectBridge::map-recall:
334 * @effect_bridge: the #AgsEffectBridge
335 *
336 * The ::map-recall should be used to add the effect_bridge's default recall.
337 *
338 * Since: 3.0.0
339 */
340 effect_bridge_signals[MAP_RECALL] =
341 g_signal_new("map-recall",
342 G_TYPE_FROM_CLASS (effect_bridge),
343 G_SIGNAL_RUN_LAST,
344 G_STRUCT_OFFSET (AgsEffectBridgeClass, map_recall),
345 NULL, NULL,
346 g_cclosure_marshal_VOID__UINT,
347 G_TYPE_NONE, 0);
348
349 /**
350 * AgsEffectBridge::find-port:
351 * @effect_bridge: the #AgsEffectBridge to resize
352 * Returns: a #GList with associated ports
353 *
354 * The ::find-port as recall should be mapped
355 *
356 * Since: 3.0.0
357 */
358 effect_bridge_signals[FIND_PORT] =
359 g_signal_new("find-port",
360 G_TYPE_FROM_CLASS(effect_bridge),
361 G_SIGNAL_RUN_LAST,
362 G_STRUCT_OFFSET(AgsEffectBridgeClass, find_port),
363 NULL, NULL,
364 ags_cclosure_marshal_POINTER__VOID,
365 G_TYPE_POINTER, 0);
366 }
367
368 void
ags_effect_bridge_connectable_interface_init(AgsConnectableInterface * connectable)369 ags_effect_bridge_connectable_interface_init(AgsConnectableInterface *connectable)
370 {
371 connectable->is_ready = NULL;
372 connectable->is_connected = NULL;
373 connectable->connect = ags_effect_bridge_connect;
374 connectable->disconnect = ags_effect_bridge_disconnect;
375 }
376
377 void
ags_effect_bridge_init(AgsEffectBridge * effect_bridge)378 ags_effect_bridge_init(AgsEffectBridge *effect_bridge)
379 {
380 gtk_orientable_set_orientation(GTK_ORIENTABLE(effect_bridge),
381 GTK_ORIENTATION_VERTICAL);
382
383 effect_bridge->flags = 0;
384
385 effect_bridge->name = NULL;
386
387 effect_bridge->version = AGS_EFFECT_BRIDGE_DEFAULT_VERSION;
388 effect_bridge->build_id = AGS_EFFECT_BRIDGE_DEFAULT_BUILD_ID;
389
390 effect_bridge->samplerate = AGS_SOUNDCARD_DEFAULT_SAMPLERATE;
391 effect_bridge->buffer_size = AGS_SOUNDCARD_DEFAULT_BUFFER_SIZE;
392 effect_bridge->format = AGS_SOUNDCARD_DEFAULT_FORMAT;
393
394 effect_bridge->audio_channels = 0;
395
396 effect_bridge->output_pads = 0;
397 effect_bridge->input_pads = 0;
398
399 effect_bridge->audio = NULL;
400
401 /* output */
402 effect_bridge->output_pad_type = G_TYPE_NONE;
403 effect_bridge->output_line_type = G_TYPE_NONE;
404
405 effect_bridge->bulk_output_type = G_TYPE_NONE;
406
407 effect_bridge->bulk_output = NULL;
408
409 effect_bridge->output = NULL;
410
411 /* input */
412 effect_bridge->input_pad_type = G_TYPE_NONE;
413 effect_bridge->input_line_type = G_TYPE_NONE;
414
415 effect_bridge->bulk_input_type = G_TYPE_NONE;
416
417 effect_bridge->bulk_input = NULL;
418
419 effect_bridge->input = NULL;
420 }
421
422 void
ags_effect_bridge_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)423 ags_effect_bridge_set_property(GObject *gobject,
424 guint prop_id,
425 const GValue *value,
426 GParamSpec *param_spec)
427 {
428 AgsEffectBridge *effect_bridge;
429
430 effect_bridge = AGS_EFFECT_BRIDGE(gobject);
431
432 switch(prop_id){
433 case PROP_SAMPLERATE:
434 {
435 GList *start_list, *list;
436
437 guint samplerate, old_samplerate;
438
439 samplerate = g_value_get_uint(value);
440 old_samplerate = effect_bridge->samplerate;
441
442 if(samplerate == old_samplerate){
443 return;
444 }
445
446 effect_bridge->samplerate = samplerate;
447
448 ags_effect_bridge_samplerate_changed(effect_bridge,
449 samplerate, old_samplerate);
450
451 if(effect_bridge->output != NULL){
452 list =
453 start_list = gtk_container_get_children(GTK_CONTAINER(effect_bridge->output));
454
455 while(list != NULL){
456 if(AGS_IS_EFFECT_PAD(list->data)){
457 g_object_set(list->data,
458 "samplerate", samplerate,
459 NULL);
460 }
461
462 list = list->next;
463 }
464
465 g_list_free(start_list);
466 }
467
468 if(effect_bridge->input != NULL){
469 list =
470 start_list = gtk_container_get_children(GTK_CONTAINER(effect_bridge->input));
471
472 while(list != NULL){
473 if(AGS_IS_EFFECT_PAD(list->data)){
474 g_object_set(list->data,
475 "samplerate", samplerate,
476 NULL);
477 }
478
479 list = list->next;
480 }
481
482 g_list_free(start_list);
483 }
484 }
485 break;
486 case PROP_BUFFER_SIZE:
487 {
488 GList *start_list, *list;
489
490 guint buffer_size, old_buffer_size;
491
492 buffer_size = g_value_get_uint(value);
493 old_buffer_size = effect_bridge->buffer_size;
494
495 if(buffer_size == old_buffer_size){
496 return;
497 }
498
499 effect_bridge->buffer_size = buffer_size;
500
501 ags_effect_bridge_buffer_size_changed(effect_bridge,
502 buffer_size, old_buffer_size);
503
504 if(effect_bridge->output != NULL){
505 list =
506 start_list = gtk_container_get_children(GTK_CONTAINER(effect_bridge->output));
507
508 while(list != NULL){
509 if(AGS_IS_EFFECT_PAD(list->data)){
510 g_object_set(list->data,
511 "buffer-size", buffer_size,
512 NULL);
513 }
514
515 list = list->next;
516 }
517
518 g_list_free(start_list);
519 }
520
521 if(effect_bridge->input != NULL){
522 list =
523 start_list = gtk_container_get_children(GTK_CONTAINER(effect_bridge->input));
524
525 while(list != NULL){
526 if(AGS_IS_EFFECT_PAD(list->data)){
527 g_object_set(list->data,
528 "buffer-size", buffer_size,
529 NULL);
530 }
531
532 list = list->next;
533 }
534
535 g_list_free(start_list);
536 }
537 }
538 break;
539 case PROP_FORMAT:
540 {
541 GList *start_list, *list;
542
543 guint format, old_format;
544
545 format = g_value_get_uint(value);
546 old_format = effect_bridge->format;
547
548 if(format == old_format){
549 return;
550 }
551
552 effect_bridge->format = format;
553
554 ags_effect_bridge_format_changed(effect_bridge,
555 format, old_format);
556
557 if(effect_bridge->output != NULL){
558 list =
559 start_list = gtk_container_get_children(GTK_CONTAINER(effect_bridge->output));
560
561 while(list != NULL){
562 if(AGS_IS_EFFECT_PAD(list->data)){
563 g_object_set(list->data,
564 "format", format,
565 NULL);
566 }
567
568 list = list->next;
569 }
570
571 g_list_free(start_list);
572 }
573
574 if(effect_bridge->input != NULL){
575 list =
576 start_list = gtk_container_get_children(GTK_CONTAINER(effect_bridge->input));
577
578 while(list != NULL){
579 if(AGS_IS_EFFECT_PAD(list->data)){
580 g_object_set(list->data,
581 "format", format,
582 NULL);
583 }
584
585 list = list->next;
586 }
587
588 g_list_free(start_list);
589 }
590 }
591 break;
592 case PROP_AUDIO:
593 {
594 AgsAudio *audio;
595
596 audio = (AgsAudio *) g_value_get_object(value);
597
598 if(effect_bridge->audio == audio){
599 return;
600 }
601
602 if(effect_bridge->audio != NULL){
603 GList *effect_pad;
604
605 g_object_unref(effect_bridge->audio);
606
607 if(audio == NULL){
608 /* destroy pad */
609 effect_pad = gtk_container_get_children((GtkContainer *) effect_bridge->output);
610
611 while(effect_pad != NULL){
612 gtk_widget_destroy(effect_pad->data);
613
614 effect_pad = effect_pad->next;
615 }
616
617 effect_pad = gtk_container_get_children((GtkContainer *) effect_bridge->input);
618
619 while(effect_pad != NULL){
620 gtk_widget_destroy(GTK_WIDGET(effect_pad->data));
621
622 effect_pad = effect_pad->next;
623 }
624 }
625 }
626
627 if(audio != NULL){
628 AgsChannel *input, *output;
629
630 GList *start_effect_pad, *effect_pad;
631 GList *start_effect_line, *effect_line;
632
633 guint audio_channels;
634 guint output_pads, input_pads;
635 guint i;
636
637 g_object_ref(audio);
638 g_object_get(audio,
639 "output", &output,
640 "input", &input,
641 "audio-channels", &audio_channels,
642 "output-pads", &output_pads,
643 "input-pads", &input_pads,
644 NULL);
645
646 effect_bridge->samplerate = audio->samplerate;
647 effect_bridge->buffer_size = audio->buffer_size;
648 effect_bridge->format = audio->format;
649
650 if(output != NULL){
651 g_object_unref(output);
652 }
653
654 if(input != NULL){
655 g_object_unref(input);
656 }
657
658 /* set channel and resize for AgsOutput */
659 if(effect_bridge->output_pad_type != G_TYPE_NONE){
660 effect_pad =
661 start_effect_pad = gtk_container_get_children((GtkContainer *) effect_bridge->output);
662
663 /* reset */
664 i = 0;
665
666 while(effect_pad != NULL && output != NULL){
667 effect_line =
668 start_effect_line = gtk_container_get_children((GtkContainer *) AGS_EFFECT_PAD(effect_pad->data)->grid);
669
670 g_object_set(G_OBJECT(effect_pad->data),
671 "channel", output,
672 NULL);
673
674 ags_effect_pad_resize_lines(AGS_EFFECT_PAD(effect_pad->data), effect_bridge->output_line_type,
675 audio_channels, g_list_length(effect_line));
676
677 g_list_free(start_effect_line);
678
679 /* iterate */
680 g_object_get(output,
681 "next-pad", &output,
682 NULL);
683
684 if(output != NULL){
685 g_object_unref(output);
686 }
687
688 effect_pad = effect_pad->next;
689 i++;
690 }
691
692 if(output != NULL){
693 AgsEffectPad *effect_pad;
694
695 /* add effect pad */
696 for(; i < output_pads; i++){
697 effect_pad = g_object_new(effect_bridge->output_pad_type,
698 "channel", output,
699 NULL);
700
701 gtk_container_add((GtkContainer *) effect_bridge->output,
702 GTK_WIDGET(effect_pad));
703
704 ags_effect_pad_resize_lines(effect_pad, effect_bridge->output_line_type,
705 audio_channels, 0);
706
707 /* iterate */
708 g_object_get(output,
709 "next-pad", &output,
710 NULL);
711
712 if(output != NULL){
713 g_object_unref(output);
714 }
715 }
716
717 g_list_free(start_effect_pad);
718 }else{
719 /* destroy effect pad */
720 effect_pad =
721 start_effect_pad = gtk_container_get_children((GtkContainer *) effect_bridge->output);
722 effect_pad = g_list_nth(effect_pad,
723 output_pads);
724
725 while(effect_pad != NULL){
726 gtk_widget_destroy(effect_pad->data);
727
728 effect_pad = effect_pad->next;
729 }
730
731 g_list_free(start_effect_pad);
732 }
733 }
734
735 /* set channel and resize for AgsInput */
736 if(effect_bridge->input_pad_type != G_TYPE_NONE){
737 effect_pad =
738 start_effect_pad = gtk_container_get_children((GtkContainer *) effect_bridge->input);
739
740 i = 0;
741
742 while(effect_pad != NULL && input != NULL){
743 effect_line =
744 start_effect_line = gtk_container_get_children((GtkContainer *) AGS_EFFECT_PAD(effect_pad->data)->grid);
745
746 g_object_set(G_OBJECT(effect_pad->data),
747 "channel", input,
748 NULL);
749
750 ags_effect_pad_resize_lines(AGS_EFFECT_PAD(effect_pad->data), effect_bridge->input_line_type,
751 audio_channels, g_list_length(effect_line));
752
753 g_list_free(start_effect_line);
754
755 /* iterate */
756 g_object_get(input,
757 "next-pad", &input,
758 NULL);
759
760 if(input != NULL){
761 g_object_unref(input);
762 }
763
764 effect_pad = effect_pad->next;
765 i++;
766 }
767
768 if(input != NULL){
769 AgsEffectPad *effect_pad;
770
771 /* add effect pad */
772 for(; i < input_pads; i++){
773 effect_pad = g_object_new(effect_bridge->input_pad_type,
774 "channel", input,
775 NULL);
776 gtk_container_add((GtkContainer *) effect_bridge->input,
777 GTK_WIDGET(effect_pad));
778
779 ags_effect_pad_resize_lines(effect_pad, effect_bridge->input_line_type,
780 audio_channels, 0);
781
782 /* iterate */
783 g_object_get(input,
784 "next-pad", &input,
785 NULL);
786
787 if(input != NULL){
788 g_object_unref(input);
789 }
790 }
791
792 g_list_free(start_effect_pad);
793 }else{
794 /* destroy effect pad */
795 effect_pad =
796 start_effect_pad = gtk_container_get_children((GtkContainer *) effect_bridge->input);
797 effect_pad = g_list_nth(effect_pad,
798 input_pads);
799
800 while(effect_pad != NULL){
801 gtk_widget_destroy(effect_pad->data);
802
803 effect_pad = effect_pad->next;
804 }
805
806 g_list_free(start_effect_pad);
807 }
808 }
809 }
810
811 effect_bridge->audio = audio;
812
813 if(effect_bridge->bulk_output != NULL){
814 g_object_set(effect_bridge->bulk_output,
815 "audio", audio,
816 NULL);
817 }
818
819 if(effect_bridge->bulk_input != NULL){
820 g_object_set(effect_bridge->bulk_input,
821 "audio", audio,
822 NULL);
823 }
824 }
825 break;
826 default:
827 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
828 break;
829 }
830 }
831
832 void
ags_effect_bridge_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)833 ags_effect_bridge_get_property(GObject *gobject,
834 guint prop_id,
835 GValue *value,
836 GParamSpec *param_spec)
837 {
838 AgsEffectBridge *effect_bridge;
839
840 effect_bridge = AGS_EFFECT_BRIDGE(gobject);
841
842 switch(prop_id){
843 case PROP_SAMPLERATE:
844 {
845 g_value_set_uint(value,
846 effect_bridge->samplerate);
847 }
848 break;
849 case PROP_BUFFER_SIZE:
850 {
851 g_value_set_uint(value,
852 effect_bridge->buffer_size);
853 }
854 break;
855 case PROP_FORMAT:
856 {
857 g_value_set_uint(value,
858 effect_bridge->format);
859 }
860 break;
861 case PROP_AUDIO:
862 {
863 g_value_set_object(value, effect_bridge->audio);
864 }
865 break;
866 default:
867 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
868 break;
869 }
870 }
871
872 void
ags_effect_bridge_connect(AgsConnectable * connectable)873 ags_effect_bridge_connect(AgsConnectable *connectable)
874 {
875 AgsMachine *machine;
876 AgsEffectBridge *effect_bridge;
877
878 GList *effect_pad_list, *effect_pad_list_start;
879
880 effect_bridge = AGS_EFFECT_BRIDGE(connectable);
881
882 if((AGS_EFFECT_BRIDGE_CONNECTED & (effect_bridge->flags)) != 0){
883 return;
884 }
885
886 effect_bridge->flags |= AGS_EFFECT_BRIDGE_CONNECTED;
887
888 machine = (AgsMachine *) gtk_widget_get_ancestor(GTK_WIDGET(effect_bridge),
889 AGS_TYPE_MACHINE);
890
891 g_signal_connect_after(machine, "resize-audio-channels",
892 G_CALLBACK(ags_effect_bridge_resize_audio_channels_callback), effect_bridge);
893
894 g_signal_connect_after(machine, "resize-pads",
895 G_CALLBACK(ags_effect_bridge_resize_pads_callback), effect_bridge);
896
897 /* AgsEffectBulk - input */
898 if(effect_bridge->bulk_input != NULL){
899 ags_connectable_connect(AGS_CONNECTABLE(effect_bridge->bulk_input));
900 }
901
902 /* AgsEffectBulk - output */
903 if(effect_bridge->bulk_output != NULL){
904 ags_connectable_connect(AGS_CONNECTABLE(effect_bridge->bulk_output));
905 }
906
907 /* AgsEffectPad - input */
908 if(effect_bridge->input != NULL){
909 effect_pad_list_start =
910 effect_pad_list = gtk_container_get_children((GtkContainer *) effect_bridge->input);
911
912 while(effect_pad_list != NULL){
913 ags_connectable_connect(AGS_CONNECTABLE(effect_pad_list->data));
914
915 effect_pad_list = effect_pad_list->next;
916 }
917
918 g_list_free(effect_pad_list_start);
919 }
920
921 /* AgsEffectPad - output */
922 if(effect_bridge->output != NULL){
923 effect_pad_list_start =
924 effect_pad_list = gtk_container_get_children((GtkContainer *) effect_bridge->output);
925
926 while(effect_pad_list != NULL){
927 ags_connectable_connect(AGS_CONNECTABLE(effect_pad_list->data));
928
929 effect_pad_list = effect_pad_list->next;
930 }
931
932 g_list_free(effect_pad_list_start);
933 }
934 }
935
936 void
ags_effect_bridge_disconnect(AgsConnectable * connectable)937 ags_effect_bridge_disconnect(AgsConnectable *connectable)
938 {
939 AgsMachine *machine;
940 AgsEffectBridge *effect_bridge;
941
942 GList *effect_pad_list, *effect_pad_list_start;
943
944 effect_bridge = AGS_EFFECT_BRIDGE(connectable);
945
946 if((AGS_EFFECT_BRIDGE_CONNECTED & (effect_bridge->flags)) == 0){
947 return;
948 }
949
950 effect_bridge->flags &= (~AGS_EFFECT_BRIDGE_CONNECTED);
951
952 machine = (AgsMachine *) gtk_widget_get_ancestor(GTK_WIDGET(effect_bridge),
953 AGS_TYPE_MACHINE);
954
955 g_object_disconnect(G_OBJECT(machine),
956 "any_signal::resize-audio-channels",
957 G_CALLBACK(ags_effect_bridge_resize_audio_channels_callback),
958 effect_bridge,
959 "any_signal::resize-pads",
960 G_CALLBACK(ags_effect_bridge_resize_pads_callback),
961 effect_bridge,
962 NULL);
963
964 /* AgsEffectBulk - input */
965 if(effect_bridge->bulk_input != NULL){
966 ags_connectable_disconnect(AGS_CONNECTABLE(effect_bridge->bulk_input));
967 }
968
969 /* AgsEffectBulk - output */
970 if(effect_bridge->bulk_output != NULL){
971 ags_connectable_disconnect(AGS_CONNECTABLE(effect_bridge->bulk_output));
972 }
973
974 /* AgsEffectPad - input */
975 if(effect_bridge->input != NULL){
976 effect_pad_list_start =
977 effect_pad_list = gtk_container_get_children((GtkContainer *) effect_bridge->input);
978
979 while(effect_pad_list != NULL){
980 ags_connectable_disconnect(AGS_CONNECTABLE(effect_pad_list->data));
981
982 effect_pad_list = effect_pad_list->next;
983 }
984
985 g_list_free(effect_pad_list_start);
986 }
987
988 /* AgsEffectPad - output */
989 if(effect_bridge->output != NULL){
990 effect_pad_list_start =
991 effect_pad_list = gtk_container_get_children((GtkContainer *) effect_bridge->output);
992
993 while(effect_pad_list != NULL){
994 ags_connectable_disconnect(AGS_CONNECTABLE(effect_pad_list->data));
995
996 effect_pad_list = effect_pad_list->next;
997 }
998
999 g_list_free(effect_pad_list_start);
1000 }
1001 }
1002
1003 /**
1004 * ags_effect_bridge_samplerate_changed:
1005 * @effect_bridge: the #AgsEffectBridge
1006 * @samplerate: the samplerate
1007 * @old_samplerate: the old samplerate
1008 *
1009 * Notify about samplerate changed.
1010 *
1011 * Since: 3.0.0
1012 */
1013 void
ags_effect_bridge_samplerate_changed(AgsEffectBridge * effect_bridge,guint samplerate,guint old_samplerate)1014 ags_effect_bridge_samplerate_changed(AgsEffectBridge *effect_bridge,
1015 guint samplerate, guint old_samplerate)
1016 {
1017 g_return_if_fail(AGS_IS_EFFECT_BRIDGE(effect_bridge));
1018
1019 g_object_ref((GObject *) effect_bridge);
1020 g_signal_emit(G_OBJECT(effect_bridge),
1021 effect_bridge_signals[SAMPLERATE_CHANGED], 0,
1022 samplerate,
1023 old_samplerate);
1024 g_object_unref((GObject *) effect_bridge);
1025 }
1026
1027 /**
1028 * ags_effect_bridge_buffer_size_changed:
1029 * @effect_bridge: the #AgsEffectBridge
1030 * @buffer_size: the buffer_size
1031 * @old_buffer_size: the old buffer_size
1032 *
1033 * Notify about buffer_size changed.
1034 *
1035 * Since: 3.0.0
1036 */
1037 void
ags_effect_bridge_buffer_size_changed(AgsEffectBridge * effect_bridge,guint buffer_size,guint old_buffer_size)1038 ags_effect_bridge_buffer_size_changed(AgsEffectBridge *effect_bridge,
1039 guint buffer_size, guint old_buffer_size)
1040 {
1041 g_return_if_fail(AGS_IS_EFFECT_BRIDGE(effect_bridge));
1042
1043 g_object_ref((GObject *) effect_bridge);
1044 g_signal_emit(G_OBJECT(effect_bridge),
1045 effect_bridge_signals[BUFFER_SIZE_CHANGED], 0,
1046 buffer_size,
1047 old_buffer_size);
1048 g_object_unref((GObject *) effect_bridge);
1049 }
1050
1051 /**
1052 * ags_effect_bridge_format_changed:
1053 * @effect_bridge: the #AgsEffectBridge
1054 * @format: the format
1055 * @old_format: the old format
1056 *
1057 * Notify about format changed.
1058 *
1059 * Since: 3.0.0
1060 */
1061 void
ags_effect_bridge_format_changed(AgsEffectBridge * effect_bridge,guint format,guint old_format)1062 ags_effect_bridge_format_changed(AgsEffectBridge *effect_bridge,
1063 guint format, guint old_format)
1064 {
1065 g_return_if_fail(AGS_IS_EFFECT_BRIDGE(effect_bridge));
1066
1067 g_object_ref((GObject *) effect_bridge);
1068 g_signal_emit(G_OBJECT(effect_bridge),
1069 effect_bridge_signals[FORMAT_CHANGED], 0,
1070 format,
1071 old_format);
1072 g_object_unref((GObject *) effect_bridge);
1073 }
1074
1075 void
ags_effect_bridge_real_resize_audio_channels(AgsEffectBridge * effect_bridge,guint new_size,guint old_size)1076 ags_effect_bridge_real_resize_audio_channels(AgsEffectBridge *effect_bridge,
1077 guint new_size,
1078 guint old_size)
1079 {
1080 AgsAudio *audio;
1081
1082 GList *start_list, *list;
1083
1084 audio = effect_bridge->audio;
1085
1086 if(audio == NULL ||
1087 new_size == old_size){
1088 return;
1089 }
1090
1091 /* output */
1092 if(effect_bridge->output != NULL){
1093 list =
1094 start_list = gtk_container_get_children((GtkContainer *) effect_bridge->output);
1095
1096 while(list != NULL){
1097 ags_effect_pad_resize_lines(AGS_EFFECT_PAD(list->data), effect_bridge->output_line_type,
1098 new_size, old_size);
1099
1100 list = list->next;
1101 }
1102
1103 g_list_free(start_list);
1104 }
1105
1106 /* input */
1107 if(effect_bridge->input != NULL){
1108 list =
1109 start_list = gtk_container_get_children((GtkContainer *) effect_bridge->input);
1110
1111 while(list != NULL){
1112 ags_effect_pad_resize_lines(AGS_EFFECT_PAD(list->data), effect_bridge->input_line_type,
1113 new_size, old_size);
1114
1115 list = list->next;
1116 }
1117
1118 g_list_free(start_list);
1119 }
1120
1121 effect_bridge->audio_channels = new_size;
1122 }
1123
1124 /**
1125 * ags_effect_bridge_resize_audio_channels:
1126 * @effect_bridge: the #AgsEffectBridge
1127 * @new_size: new allocation
1128 * @old_size: old allocation
1129 *
1130 * Resize audio channel allocation.
1131 *
1132 * Since: 3.0.0
1133 */
1134 void
ags_effect_bridge_resize_audio_channels(AgsEffectBridge * effect_bridge,guint new_size,guint old_size)1135 ags_effect_bridge_resize_audio_channels(AgsEffectBridge *effect_bridge,
1136 guint new_size,
1137 guint old_size)
1138 {
1139 g_return_if_fail(AGS_IS_EFFECT_BRIDGE(effect_bridge));
1140
1141 g_object_ref((GObject *) effect_bridge);
1142 g_signal_emit(G_OBJECT(effect_bridge),
1143 effect_bridge_signals[RESIZE_AUDIO_CHANNELS], 0,
1144 new_size,
1145 old_size);
1146 g_object_unref((GObject *) effect_bridge);
1147 }
1148
1149 void
ags_effect_bridge_real_resize_pads(AgsEffectBridge * effect_bridge,GType channel_type,guint new_size,guint old_size)1150 ags_effect_bridge_real_resize_pads(AgsEffectBridge *effect_bridge,
1151 GType channel_type,
1152 guint new_size,
1153 guint old_size)
1154 {
1155 AgsEffectPad *effect_pad;
1156
1157 AgsAudio *audio;
1158 AgsChannel *start_output, *start_input;
1159 AgsChannel *current;
1160
1161 guint audio_channels;
1162 guint audio_audio_channels;
1163 guint audio_input_pads, audio_output_pads;
1164 guint i;
1165
1166 audio = effect_bridge->audio;
1167
1168 if(audio == NULL){
1169 return;
1170 }
1171
1172 audio_channels = effect_bridge->audio_channels;
1173
1174 start_output = NULL;
1175 start_input = NULL;
1176
1177 audio_audio_channels = 0;
1178
1179 audio_input_pads = 0;
1180 audio_output_pads = 0;
1181
1182 if(audio != NULL){
1183 g_object_get(audio,
1184 "output", &start_output,
1185 "input", &start_input,
1186 "audio-channels", &audio_audio_channels,
1187 "input-pads", &audio_input_pads,
1188 "output-pads", &audio_output_pads,
1189 NULL);
1190 }
1191
1192 if(new_size > old_size){
1193 for(i = old_size; i < new_size; i++){
1194 if(g_type_is_a(channel_type, AGS_TYPE_OUTPUT)){
1195 if(audio_audio_channels > 0 &&
1196 i < new_size){
1197 current = ags_channel_nth(start_output, i * audio_audio_channels);
1198 }else{
1199 current = NULL;
1200 }
1201
1202 if(effect_bridge->output_pad_type != G_TYPE_NONE){
1203 effect_pad = g_object_new(effect_bridge->output_pad_type,
1204 "channel", current,
1205 NULL);
1206 ags_effect_pad_resize_lines(effect_pad, effect_bridge->output_line_type,
1207 audio_channels, 0);
1208 gtk_container_add((GtkContainer *) effect_bridge->output,
1209 GTK_WIDGET(effect_pad));
1210 }
1211 }else{
1212 if(audio_audio_channels > 0 &&
1213 i < audio_input_pads){
1214 current = ags_channel_nth(start_input, i * audio_audio_channels);
1215 }else{
1216 current = NULL;
1217 }
1218
1219 if(effect_bridge->input_pad_type != G_TYPE_NONE){
1220 effect_pad = g_object_new(effect_bridge->input_pad_type,
1221 "channel", current,
1222 NULL);
1223 ags_effect_pad_resize_lines(effect_pad, effect_bridge->input_line_type,
1224 audio_channels, 0);
1225 gtk_container_add((GtkContainer *) effect_bridge->input,
1226 GTK_WIDGET(effect_pad));
1227 }
1228 }
1229 }
1230
1231 if(start_output != NULL){
1232 g_object_unref(start_output);
1233 }
1234
1235 if(start_input != NULL){
1236 g_object_unref(start_input);
1237 }
1238
1239 /* connect and show */
1240 if((AGS_EFFECT_BRIDGE_CONNECTED & (effect_bridge->flags)) != 0){
1241 GtkContainer *container;
1242
1243 GList *start_list, *list;
1244
1245 container = (GtkContainer *) ((channel_type == AGS_TYPE_OUTPUT) ? effect_bridge->output: effect_bridge->input);
1246
1247 if(container != NULL){
1248 start_list = gtk_container_get_children(container);
1249 list = g_list_nth(start_list,
1250 old_size);
1251
1252 while(list != NULL){
1253 ags_connectable_connect(AGS_CONNECTABLE(list->data));
1254 gtk_widget_show_all(list->data);
1255
1256 list = list->next;
1257 }
1258
1259 g_list_free(start_list);
1260 }
1261 }
1262 }else{
1263 GList *start_list, *list;
1264
1265 list =
1266 start_list = NULL;
1267
1268 if(channel_type == AGS_TYPE_OUTPUT){
1269 if(effect_bridge->output != NULL){
1270 start_list = gtk_container_get_children((GtkContainer *) effect_bridge->output);
1271 list = g_list_nth(start_list,
1272 new_size);
1273 }
1274 }else{
1275 if(effect_bridge->input != NULL){
1276 start_list = gtk_container_get_children((GtkContainer *) effect_bridge->input);
1277 list = g_list_nth(start_list,
1278 new_size);
1279 }
1280 }
1281
1282 for(i = 0; list != NULL && i < new_size - old_size; i++){
1283 gtk_widget_destroy(list->data);
1284
1285 list = list->next;
1286 }
1287
1288 g_list_free(start_list);
1289 }
1290
1291 if(start_output != NULL){
1292 g_object_unref(start_output);
1293 }
1294
1295 if(start_input != NULL){
1296 g_object_unref(start_input);
1297 }
1298
1299 if(g_type_is_a(channel_type, AGS_TYPE_OUTPUT)){
1300 effect_bridge->output_pads = new_size;
1301 }else{
1302 effect_bridge->input_pads = new_size;
1303 }
1304 }
1305
1306 /**
1307 * ags_effect_bridge_resize_pads:
1308 * @effect_bridge: the #AgsEffectBridge
1309 * @channel_type: the channel #GType
1310 * @new_size: new allocation
1311 * @old_size: old allocation
1312 *
1313 * Resize pad allocation.
1314 *
1315 * Since: 3.0.0
1316 */
1317 void
ags_effect_bridge_resize_pads(AgsEffectBridge * effect_bridge,GType channel_type,guint new_size,guint old_size)1318 ags_effect_bridge_resize_pads(AgsEffectBridge *effect_bridge,
1319 GType channel_type,
1320 guint new_size,
1321 guint old_size)
1322 {
1323 g_return_if_fail(AGS_IS_EFFECT_BRIDGE(effect_bridge));
1324
1325 g_object_ref((GObject *) effect_bridge);
1326 g_signal_emit(G_OBJECT(effect_bridge),
1327 effect_bridge_signals[RESIZE_PADS], 0,
1328 channel_type,
1329 new_size,
1330 old_size);
1331 g_object_unref((GObject *) effect_bridge);
1332 }
1333
1334 void
ags_effect_bridge_real_map_recall(AgsEffectBridge * effect_bridge)1335 ags_effect_bridge_real_map_recall(AgsEffectBridge *effect_bridge)
1336 {
1337 if((AGS_EFFECT_BRIDGE_MAPPED_RECALL & (effect_bridge->flags)) != 0){
1338 return;
1339 }
1340
1341 effect_bridge->flags |= AGS_EFFECT_BRIDGE_MAPPED_RECALL;
1342
1343 ags_effect_bridge_find_port(effect_bridge);
1344 }
1345
1346 /**
1347 * ags_effect_bridge_map_recall:
1348 * @effect_bridge: the #AgsEffectBridge to add its default recall.
1349 *
1350 * You may want the @effect_bridge to add its default recall.
1351 *
1352 * Since: 3.0.0
1353 */
1354 void
ags_effect_bridge_map_recall(AgsEffectBridge * effect_bridge)1355 ags_effect_bridge_map_recall(AgsEffectBridge *effect_bridge)
1356 {
1357 g_return_if_fail(AGS_IS_EFFECT_BRIDGE(effect_bridge));
1358
1359 g_object_ref((GObject *) effect_bridge);
1360 g_signal_emit((GObject *) effect_bridge,
1361 effect_bridge_signals[MAP_RECALL], 0);
1362 g_object_unref((GObject *) effect_bridge);
1363 }
1364
1365 GList*
ags_effect_bridge_real_find_port(AgsEffectBridge * effect_bridge)1366 ags_effect_bridge_real_find_port(AgsEffectBridge *effect_bridge)
1367 {
1368 GList *effect_pad, *effect_pad_start;
1369
1370 GList *port, *tmp_port;
1371
1372 port = NULL;
1373
1374 /* find output ports */
1375 if(effect_bridge->output != NULL){
1376 effect_pad_start =
1377 effect_pad = gtk_container_get_children((GtkContainer *) effect_bridge->output);
1378
1379 while(effect_pad != NULL){
1380 tmp_port = ags_effect_pad_find_port(AGS_EFFECT_PAD(effect_pad->data));
1381
1382 if(port != NULL){
1383 port = g_list_concat(port,
1384 tmp_port);
1385 }else{
1386 port = tmp_port;
1387 }
1388
1389 effect_pad = effect_pad->next;
1390 }
1391
1392 g_list_free(effect_pad_start);
1393 }
1394
1395 /* find input ports */
1396 if(effect_bridge->input != NULL){
1397 effect_pad_start =
1398 effect_pad = gtk_container_get_children((GtkContainer *) effect_bridge->input);
1399
1400 while(effect_pad != NULL){
1401 tmp_port = ags_effect_pad_find_port(AGS_EFFECT_PAD(effect_pad->data));
1402
1403 if(port != NULL){
1404 port = g_list_concat(port,
1405 tmp_port);
1406 }else{
1407 port = tmp_port;
1408 }
1409
1410 effect_pad = effect_pad->next;
1411 }
1412
1413 g_list_free(effect_pad_start);
1414 }
1415
1416 /* find output bulk ports */
1417 if(effect_bridge->bulk_output != NULL){
1418 tmp_port = ags_effect_bulk_find_port((AgsEffectBulk *) effect_bridge->bulk_output);
1419
1420 if(port != NULL){
1421 port = g_list_concat(port,
1422 tmp_port);
1423 }else{
1424 port = tmp_port;
1425 }
1426 }
1427
1428 /* find input bulk ports */
1429 if(effect_bridge->bulk_output != NULL){
1430 tmp_port = ags_effect_bulk_find_port((AgsEffectBulk *) effect_bridge->bulk_output);
1431
1432 if(port != NULL){
1433 port = g_list_concat(port,
1434 tmp_port);
1435 }else{
1436 port = tmp_port;
1437 }
1438 }
1439
1440 return(port);
1441 }
1442
1443 /**
1444 * ags_effect_bridge_find_port:
1445 * @effect_bridge: the #AgsEffectBridge
1446 * Returns: an #GList containing all related #AgsPort
1447 *
1448 * Lookup ports of associated recalls.
1449 *
1450 * Since: 3.0.0
1451 */
1452 GList*
ags_effect_bridge_find_port(AgsEffectBridge * effect_bridge)1453 ags_effect_bridge_find_port(AgsEffectBridge *effect_bridge)
1454 {
1455 GList *list;
1456
1457 list = NULL;
1458 g_return_val_if_fail(AGS_IS_EFFECT_BRIDGE(effect_bridge),
1459 NULL);
1460
1461 g_object_ref((GObject *) effect_bridge);
1462 g_signal_emit((GObject *) effect_bridge,
1463 effect_bridge_signals[FIND_PORT], 0,
1464 &list);
1465 g_object_unref((GObject *) effect_bridge);
1466
1467 return(list);
1468 }
1469
1470 /**
1471 * ags_effect_bridge_new:
1472 * @audio: the #AgsAudio to visualize
1473 *
1474 * Creates an #AgsEffectBridge
1475 *
1476 * Returns: a new #AgsEffectBridge
1477 *
1478 * Since: 3.0.0
1479 */
1480 AgsEffectBridge*
ags_effect_bridge_new(AgsAudio * audio)1481 ags_effect_bridge_new(AgsAudio *audio)
1482 {
1483 AgsEffectBridge *effect_bridge;
1484
1485 effect_bridge = (AgsEffectBridge *) g_object_new(AGS_TYPE_EFFECT_BRIDGE,
1486 "audio", audio,
1487 NULL);
1488
1489 return(effect_bridge);
1490 }
1491