1 /* GSequencer - Advanced GTK Sequencer
2 * Copyright (C) 2005-2019 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/audio/ags_port.h>
21
22 #include <ags/plugin/ags_plugin_port.h>
23
24 #include <ags/audio/ags_automation.h>
25
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include <ags/i18n.h>
30
31 void ags_port_class_init(AgsPortClass *port_class);
32 void ags_port_connectable_interface_init(AgsConnectableInterface *connectable);
33 void ags_port_init(AgsPort *port);
34 void ags_port_set_property(GObject *gobject,
35 guint prop_id,
36 const GValue *value,
37 GParamSpec *param_spec);
38 void ags_port_get_property(GObject *gobject,
39 guint prop_id,
40 GValue *value,
41 GParamSpec *param_spec);
42 void ags_port_dispose(GObject *gobject);
43 void ags_port_finalize(GObject *gobject);
44
45 AgsUUID* ags_port_get_uuid(AgsConnectable *connectable);
46 gboolean ags_port_has_resource(AgsConnectable *connectable);
47 gboolean ags_port_is_ready(AgsConnectable *connectable);
48 void ags_port_add_to_registry(AgsConnectable *connectable);
49 void ags_port_remove_from_registry(AgsConnectable *connectable);
50 xmlNode* ags_port_list_resource(AgsConnectable *connectable);
51 xmlNode* ags_port_xml_compose(AgsConnectable *connectable);
52 void ags_port_xml_parse(AgsConnectable *connectable,
53 xmlNode *node);
54 gboolean ags_port_is_connected(AgsConnectable *connectable);
55 void ags_port_connect(AgsConnectable *connectable);
56 void ags_port_disconnect(AgsConnectable *connectable);
57
58 void ags_port_real_safe_read(AgsPort *port, GValue *value);
59 void ags_port_real_safe_write(AgsPort *port, GValue *value);
60 void ags_port_real_safe_get_property(AgsPort *port, gchar *property_name, GValue *value);
61 void ags_port_real_safe_set_property(AgsPort *port, gchar *property_name, GValue *value);
62
63 /**
64 * SECTION:ags_port
65 * @short_description: Perform thread-safe operations
66 * @title: AgsPort
67 * @section_id:
68 * @include: ags/audio/ags_port.h
69 *
70 * #AgsPort provides a thread-safe way to access or change values or properties.
71 */
72
73 enum{
74 SAFE_READ,
75 SAFE_WRITE,
76 SAFE_GET_PROPERTY,
77 SAFE_SET_PROPERTY,
78 LAST_SIGNAL,
79 };
80
81 enum{
82 PROP_0,
83 PROP_PLUGIN_NAME,
84 PROP_SPECIFIER,
85 PROP_CONTROL_PORT,
86 PROP_PORT_VALUE_IS_POINTER,
87 PROP_PORT_VALUE_TYPE,
88 PROP_PORT_VALUE_SIZE,
89 PROP_PORT_VALUE_LENGTH,
90 PROP_PLUGIN_PORT,
91 PROP_CONVERSION,
92 PROP_AUTOMATION,
93 PROP_PORT_VALUE,
94 };
95
96 static gpointer ags_port_parent_class = NULL;
97 static guint port_signals[LAST_SIGNAL];
98
99 GType
ags_port_get_type(void)100 ags_port_get_type(void)
101 {
102 static volatile gsize g_define_type_id__volatile = 0;
103
104 if(g_once_init_enter (&g_define_type_id__volatile)){
105 GType ags_type_port = 0;
106
107 static const GTypeInfo ags_port_info = {
108 sizeof (AgsPortClass),
109 NULL, /* base_init */
110 NULL, /* base_finalize */
111 (GClassInitFunc) ags_port_class_init,
112 NULL, /* class_finalize */
113 NULL, /* class_data */
114 sizeof (AgsPort),
115 0, /* n_preallocs */
116 (GInstanceInitFunc) ags_port_init,
117 };
118
119 static const GInterfaceInfo ags_connectable_interface_info = {
120 (GInterfaceInitFunc) ags_port_connectable_interface_init,
121 NULL, /* interface_finalize */
122 NULL, /* interface_data */
123 };
124
125 ags_type_port = g_type_register_static(G_TYPE_OBJECT,
126 "AgsPort",
127 &ags_port_info,
128 0);
129
130 g_type_add_interface_static(ags_type_port,
131 AGS_TYPE_CONNECTABLE,
132 &ags_connectable_interface_info);
133
134 g_once_init_leave(&g_define_type_id__volatile, ags_type_port);
135 }
136
137 return g_define_type_id__volatile;
138 }
139
140 void
ags_port_class_init(AgsPortClass * port)141 ags_port_class_init(AgsPortClass *port)
142 {
143 GObjectClass *gobject;
144 GParamSpec *param_spec;
145
146 ags_port_parent_class = g_type_class_peek_parent(port);
147
148 /* GObjectClass */
149 gobject = (GObjectClass *) port;
150
151 gobject->set_property = ags_port_set_property;
152 gobject->get_property = ags_port_get_property;
153
154 gobject->dispose = ags_port_dispose;
155 gobject->finalize = ags_port_finalize;
156
157 /* properties */
158 /**
159 * AgsPort:plugin-name:
160 *
161 * The assigned plugin.
162 *
163 * Since: 3.0.0
164 */
165 param_spec = g_param_spec_string("plugin-name",
166 i18n_pspec("plugin-name of port"),
167 i18n_pspec("The plugin-name this port belongs to"),
168 NULL,
169 G_PARAM_READABLE | G_PARAM_WRITABLE);
170 g_object_class_install_property(gobject,
171 PROP_PLUGIN_NAME,
172 param_spec);
173
174 /**
175 * AgsPort:specifier:
176 *
177 * The assigned plugin identifier.
178 *
179 * Since: 3.0.0
180 */
181 param_spec = g_param_spec_string("specifier",
182 i18n_pspec("specifier of port"),
183 i18n_pspec("The specifier this port is identified by"),
184 NULL,
185 G_PARAM_READABLE | G_PARAM_WRITABLE);
186 g_object_class_install_property(gobject,
187 PROP_SPECIFIER,
188 param_spec);
189
190 /**
191 * AgsPort:control-port:
192 *
193 * The assigned plugin control port.
194 *
195 * Since: 3.0.0
196 */
197 param_spec = g_param_spec_string("control-port",
198 i18n_pspec("control-port of port"),
199 i18n_pspec("The control-port this port is numbered"),
200 NULL,
201 G_PARAM_READABLE | G_PARAM_WRITABLE);
202 g_object_class_install_property(gobject,
203 PROP_CONTROL_PORT,
204 param_spec);
205
206 /**
207 * AgsPort:port-value-is-pointer:
208 *
209 * Specify port data as pointer.
210 *
211 * Since: 3.0.0
212 */
213 param_spec = g_param_spec_boolean("port-value-is-pointer",
214 i18n_pspec("port-value-is-pointer indicates if value is a pointer"),
215 i18n_pspec("The port-value-is-pointer indicates if value is a pointer"),
216 FALSE,
217 G_PARAM_READABLE | G_PARAM_WRITABLE);
218 g_object_class_install_property(gobject,
219 PROP_PORT_VALUE_IS_POINTER,
220 param_spec);
221
222 /**
223 * AgsPort:port-value-type:
224 *
225 * The port's data type.
226 *
227 * Since: 3.0.0
228 */
229 param_spec = g_param_spec_gtype("port-value-type",
230 i18n_pspec("port-value-type tells you the type of the values"),
231 i18n_pspec("The port-value-type tells you the type of the values"),
232 G_TYPE_NONE,
233 G_PARAM_READABLE | G_PARAM_WRITABLE);
234 g_object_class_install_property(gobject,
235 PROP_PORT_VALUE_TYPE,
236 param_spec);
237
238 /**
239 * AgsPort:port-value-size:
240 *
241 * The port's data type size.
242 *
243 * Since: 3.0.0
244 */
245 param_spec = g_param_spec_uint("port-value-size",
246 i18n_pspec("port-value-size is the size of a single entry"),
247 i18n_pspec("The port-value-size is the size of a single entry"),
248 1,
249 16,
250 sizeof(gdouble),
251 G_PARAM_READABLE | G_PARAM_WRITABLE);
252 g_object_class_install_property(gobject,
253 PROP_PORT_VALUE_SIZE,
254 param_spec);
255
256 /**
257 * AgsPort:port-value-length:
258 *
259 * The port's data array length.
260 *
261 * Since: 3.0.0
262 */
263 param_spec = g_param_spec_uint("port-value-length",
264 i18n_pspec("port-value-length is the array size"),
265 i18n_pspec("The port-value-length is the array size"),
266 0,
267 G_MAXUINT32,
268 1,
269 G_PARAM_READABLE | G_PARAM_WRITABLE);
270 g_object_class_install_property(gobject,
271 PROP_PORT_VALUE_LENGTH,
272 param_spec);
273
274 /**
275 * AgsPort:plugin-port:
276 *
277 * The plugin-port.
278 *
279 * Since: 3.0.0
280 */
281 param_spec = g_param_spec_object("plugin-port",
282 i18n_pspec("plugin port"),
283 i18n_pspec("The plugin port"),
284 AGS_TYPE_PLUGIN_PORT,
285 G_PARAM_READABLE | G_PARAM_WRITABLE);
286 g_object_class_install_property(gobject,
287 PROP_PLUGIN_PORT,
288 param_spec);
289
290 /**
291 * AgsPort:conversion:
292 *
293 * The port's conversion object.
294 *
295 * Since: 3.0.0
296 */
297 param_spec = g_param_spec_object("conversion",
298 i18n_pspec("conversion converts values"),
299 i18n_pspec("The conversion is able to translate values"),
300 AGS_TYPE_CONVERSION,
301 G_PARAM_READABLE | G_PARAM_WRITABLE);
302 g_object_class_install_property(gobject,
303 PROP_CONVERSION,
304 param_spec);
305
306 /**
307 * AgsPort:automation: (type GList(AgsAutomation)) (transfer full)
308 *
309 * The port's automation.
310 *
311 * Since: 3.0.0
312 */
313 param_spec = g_param_spec_pointer("automation",
314 i18n_pspec("automation"),
315 i18n_pspec("The automation to apply"),
316 G_PARAM_READABLE | G_PARAM_WRITABLE);
317 g_object_class_install_property(gobject,
318 PROP_AUTOMATION,
319 param_spec);
320
321 /* AgsPortClass */
322 port->safe_read = ags_port_real_safe_read;
323 port->safe_write = ags_port_real_safe_write;
324
325 port->safe_get_property = ags_port_real_safe_get_property;
326 port->safe_set_property = ags_port_real_safe_set_property;
327
328 /* signals */
329 /**
330 * AgsPort::safe-read:
331 * @port: the object providing safe read
332 * @value: the #GValue-struct
333 *
334 * The ::safe-read signal is emited while doing safe read operation.
335 *
336 * Since: 3.0.0
337 */
338 port_signals[SAFE_READ] =
339 g_signal_new("safe-read",
340 G_TYPE_FROM_CLASS (port),
341 G_SIGNAL_RUN_LAST,
342 G_STRUCT_OFFSET (AgsPortClass, safe_read),
343 NULL, NULL,
344 g_cclosure_marshal_VOID__POINTER,
345 G_TYPE_NONE, 1,
346 G_TYPE_POINTER);
347
348 /**
349 * AgsPort::safe-write:
350 * @port: the object providing safe write
351 * @value: the #GValue-struct
352 *
353 * The ::safe-write signal is emited while doing safe write operation.
354 *
355 * Since: 3.0.0
356 */
357 port_signals[SAFE_WRITE] =
358 g_signal_new("safe-write",
359 G_TYPE_FROM_CLASS (port),
360 G_SIGNAL_RUN_LAST,
361 G_STRUCT_OFFSET (AgsPortClass, safe_write),
362 NULL, NULL,
363 g_cclosure_marshal_VOID__POINTER,
364 G_TYPE_NONE, 1,
365 G_TYPE_POINTER);
366
367 /**
368 * AgsPort::safe-get-property:
369 * @port: the object providing safe get property
370 * @property_name: the property name
371 * @value: the #GValue-struct
372 *
373 * The ::safe-get-property signal is emited while safe get property.
374 *
375 * Since: 3.0.0
376 */
377 port_signals[SAFE_GET_PROPERTY] =
378 g_signal_new("safe-get-property",
379 G_TYPE_FROM_CLASS (port),
380 G_SIGNAL_RUN_LAST,
381 G_STRUCT_OFFSET (AgsPortClass, safe_get_property),
382 NULL, NULL,
383 ags_cclosure_marshal_VOID__STRING_POINTER,
384 G_TYPE_NONE, 2,
385 G_TYPE_STRING, G_TYPE_POINTER);
386
387 /**
388 * AgsPort::safe-set-property:
389 * @port: the object providing safe set property
390 * @property_name: the property name
391 * @value: the #GValue-struct
392 *
393 * The ::safe-set-property signal is emited while safe set property.
394 *
395 * Since: 3.0.0
396 */
397 port_signals[SAFE_SET_PROPERTY] =
398 g_signal_new("safe-set-property",
399 G_TYPE_FROM_CLASS (port),
400 G_SIGNAL_RUN_LAST,
401 G_STRUCT_OFFSET (AgsPortClass, safe_set_property),
402 NULL, NULL,
403 ags_cclosure_marshal_VOID__STRING_POINTER,
404 G_TYPE_NONE, 2,
405 G_TYPE_STRING, G_TYPE_POINTER);
406 }
407
408 void
ags_port_connectable_interface_init(AgsConnectableInterface * connectable)409 ags_port_connectable_interface_init(AgsConnectableInterface *connectable)
410 {
411 connectable->get_uuid = ags_port_get_uuid;
412 connectable->has_resource = ags_port_has_resource;
413
414 connectable->is_ready = ags_port_is_ready;
415 connectable->add_to_registry = ags_port_add_to_registry;
416 connectable->remove_from_registry = ags_port_remove_from_registry;
417
418 connectable->list_resource = ags_port_list_resource;
419 connectable->xml_compose = ags_port_xml_compose;
420 connectable->xml_parse = ags_port_xml_parse;
421
422 connectable->is_connected = ags_port_is_connected;
423 connectable->connect = ags_port_connect;
424 connectable->disconnect = ags_port_disconnect;
425
426 connectable->connect_connection = NULL;
427 connectable->disconnect_connection = NULL;
428 }
429
430 void
ags_port_init(AgsPort * port)431 ags_port_init(AgsPort *port)
432 {
433 port->flags = 0; // AGS_PORT_CONVERT_ALWAYS;
434
435 /* port mutex */
436 g_rec_mutex_init(&(port->obj_mutex));
437
438 /* common fields */
439 port->plugin_name = NULL;
440 port->specifier = NULL;
441
442 port->control_port = NULL;
443
444 port->port_value_is_pointer = FALSE;
445 port->port_value_type = G_TYPE_DOUBLE;
446
447 port->port_value_size = sizeof(gdouble);
448 port->port_value_length = 1;
449
450 port->plugin_port = NULL;
451
452 port->conversion = ags_conversion_new();
453 g_object_ref(port->conversion);
454
455 port->automation = NULL;
456
457 port->port_value.ags_port_double = 0.0;
458 }
459
460 void
ags_port_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)461 ags_port_set_property(GObject *gobject,
462 guint prop_id,
463 const GValue *value,
464 GParamSpec *param_spec)
465 {
466 AgsPort *port;
467
468 GRecMutex *port_mutex;
469
470 port = AGS_PORT(gobject);
471
472 /* get port mutex */
473 port_mutex = AGS_PORT_GET_OBJ_MUTEX(port);
474
475 switch(prop_id){
476 case PROP_PLUGIN_NAME:
477 {
478 gchar *plugin_name;
479
480 plugin_name = (gchar *) g_value_get_string(value);
481
482 g_rec_mutex_lock(port_mutex);
483
484 if(port->plugin_name == plugin_name){
485 g_rec_mutex_unlock(port_mutex);
486
487 return;
488 }
489
490 if(port->plugin_name != NULL){
491 g_free(port->plugin_name);
492 }
493
494 port->plugin_name = g_strdup(plugin_name);
495
496 g_rec_mutex_unlock(port_mutex);
497 }
498 break;
499 case PROP_SPECIFIER:
500 {
501 gchar *specifier;
502
503 specifier = (gchar *) g_value_get_string(value);
504
505 g_rec_mutex_lock(port_mutex);
506
507 if(port->specifier == specifier){
508 g_rec_mutex_unlock(port_mutex);
509
510 return;
511 }
512
513 if(port->specifier != NULL){
514 g_free(port->specifier);
515 }
516
517 port->specifier = g_strdup(specifier);
518
519 g_rec_mutex_unlock(port_mutex);
520 }
521 break;
522 case PROP_CONTROL_PORT:
523 {
524 gchar *control_port;
525
526 control_port = (gchar *) g_value_get_string(value);
527
528 g_rec_mutex_lock(port_mutex);
529
530 if(port->control_port == control_port){
531 g_rec_mutex_unlock(port_mutex);
532
533 return;
534 }
535
536 if(port->control_port != NULL){
537 g_free(port->control_port);
538 }
539
540 port->control_port = g_strdup(control_port);
541
542 g_rec_mutex_unlock(port_mutex);
543 }
544 break;
545 case PROP_PORT_VALUE_IS_POINTER:
546 {
547 g_rec_mutex_lock(port_mutex);
548
549 port->port_value_is_pointer = g_value_get_boolean(value);
550
551 g_rec_mutex_unlock(port_mutex);
552 }
553 break;
554 case PROP_PORT_VALUE_TYPE:
555 {
556 g_rec_mutex_lock(port_mutex);
557
558 port->port_value_type = g_value_get_gtype(value);
559
560 g_rec_mutex_unlock(port_mutex);
561 }
562 break;
563 case PROP_PORT_VALUE_SIZE:
564 {
565 g_rec_mutex_lock(port_mutex);
566
567 port->port_value_size = g_value_get_uint(value);
568
569 g_rec_mutex_unlock(port_mutex);
570 }
571 break;
572 case PROP_PORT_VALUE_LENGTH:
573 {
574 g_rec_mutex_lock(port_mutex);
575
576 port->port_value_length = g_value_get_uint(value);
577
578 g_rec_mutex_unlock(port_mutex);
579 }
580 break;
581 case PROP_PLUGIN_PORT:
582 {
583 AgsPluginPort *plugin_port;
584
585 plugin_port = g_value_get_object(value);
586
587 g_rec_mutex_lock(port_mutex);
588
589 if(plugin_port == (AgsPluginPort *) port->plugin_port){
590 g_rec_mutex_unlock(port_mutex);
591
592 return;
593 }
594
595 if(port->plugin_port != NULL){
596 g_object_unref(port->plugin_port);
597 }
598
599 if(plugin_port != NULL){
600 g_object_ref(plugin_port);
601 }
602
603 port->plugin_port = (GObject *) plugin_port;
604
605 g_rec_mutex_unlock(port_mutex);
606 }
607 break;
608 case PROP_CONVERSION:
609 {
610 AgsConversion *conversion;
611
612 conversion = g_value_get_object(value);
613
614 g_rec_mutex_lock(port_mutex);
615
616 if(conversion == port->conversion){
617 g_rec_mutex_unlock(port_mutex);
618
619 return;
620 }
621
622 if(port->conversion != NULL){
623 g_object_unref(port->conversion);
624 }
625
626 if(conversion != NULL){
627 g_object_ref(conversion);
628 }
629
630 port->conversion = conversion;
631
632 g_rec_mutex_unlock(port_mutex);
633 }
634 break;
635 case PROP_AUTOMATION:
636 {
637 AgsAutomation *automation;
638
639 automation = g_value_get_pointer(value);
640
641 if(g_list_find(port->automation, automation) != NULL){
642 g_rec_mutex_unlock(port_mutex);
643
644 return;
645 }
646
647 if(automation != NULL){
648 g_object_ref(automation);
649 }
650
651 port->automation = ags_automation_add(port->automation,
652 automation);
653
654 g_rec_mutex_unlock(port_mutex);
655 }
656 break;
657 default:
658 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
659 break;
660 }
661 }
662
663 void
ags_port_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)664 ags_port_get_property(GObject *gobject,
665 guint prop_id,
666 GValue *value,
667 GParamSpec *param_spec)
668 {
669 AgsPort *port;
670
671 GRecMutex *port_mutex;
672
673 port = AGS_PORT(gobject);
674
675 /* get port mutex */
676 port_mutex = AGS_PORT_GET_OBJ_MUTEX(port);
677
678 switch(prop_id){
679 case PROP_PLUGIN_NAME:
680 {
681 g_rec_mutex_lock(port_mutex);
682
683 g_value_set_string(value, port->plugin_name);
684
685 g_rec_mutex_unlock(port_mutex);
686 }
687 break;
688 case PROP_SPECIFIER:
689 {
690 g_rec_mutex_lock(port_mutex);
691
692 g_value_set_string(value, port->specifier);
693
694 g_rec_mutex_unlock(port_mutex);
695 }
696 break;
697 case PROP_CONTROL_PORT:
698 {
699 g_rec_mutex_lock(port_mutex);
700
701 g_value_set_string(value, port->control_port);
702
703 g_rec_mutex_unlock(port_mutex);
704 }
705 break;
706 case PROP_PORT_VALUE_IS_POINTER:
707 {
708 g_rec_mutex_lock(port_mutex);
709
710 g_value_set_boolean(value, port->port_value_is_pointer);
711
712 g_rec_mutex_unlock(port_mutex);
713 }
714 break;
715 case PROP_PORT_VALUE_TYPE:
716 {
717 g_rec_mutex_lock(port_mutex);
718
719 g_value_set_gtype(value, port->port_value_type);
720
721 g_rec_mutex_unlock(port_mutex);
722 }
723 break;
724 case PROP_PORT_VALUE_SIZE:
725 {
726 g_rec_mutex_lock(port_mutex);
727
728 g_value_set_uint(value, port->port_value_size);
729
730 g_rec_mutex_unlock(port_mutex);
731 }
732 break;
733 case PROP_PORT_VALUE_LENGTH:
734 {
735 g_rec_mutex_lock(port_mutex);
736
737 g_value_set_uint(value, port->port_value_length);
738
739 g_rec_mutex_unlock(port_mutex);
740 }
741 break;
742 case PROP_PLUGIN_PORT:
743 {
744 g_rec_mutex_lock(port_mutex);
745
746 g_value_set_object(value, port->plugin_port);
747
748 g_rec_mutex_unlock(port_mutex);
749 }
750 break;
751 case PROP_CONVERSION:
752 {
753 g_rec_mutex_lock(port_mutex);
754
755 g_value_set_object(value, port->conversion);
756
757 g_rec_mutex_unlock(port_mutex);
758 }
759 break;
760 case PROP_AUTOMATION:
761 {
762 g_rec_mutex_lock(port_mutex);
763
764 g_value_set_pointer(value, g_list_copy_deep(port->automation,
765 (GCopyFunc) g_object_ref,
766 NULL));
767
768 g_rec_mutex_unlock(port_mutex);
769 }
770 break;
771 default:
772 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
773 break;
774 }
775 }
776
777 void
ags_port_dispose(GObject * gobject)778 ags_port_dispose(GObject *gobject)
779 {
780 AgsPort *port;
781
782 port = AGS_PORT(gobject);
783
784 if(port->plugin_port != NULL){
785 g_object_unref(port->plugin_port);
786
787 port->plugin_port = NULL;
788 }
789
790 if(port->conversion != NULL){
791 g_object_unref(port->conversion);
792
793 port->conversion = NULL;
794 }
795
796 if(port->automation != NULL){
797 g_list_free_full(port->automation,
798 g_object_unref);
799
800 port->automation = NULL;
801 }
802
803 /* call parent */
804 G_OBJECT_CLASS(ags_port_parent_class)->dispose(gobject);
805 }
806
807 void
ags_port_finalize(GObject * gobject)808 ags_port_finalize(GObject *gobject)
809 {
810 AgsPort *port;
811
812 port = AGS_PORT(gobject);
813
814 g_free(port->plugin_name);
815 g_free(port->specifier);
816
817 g_free(port->control_port);
818
819 if(port->plugin_port != NULL){
820 g_object_unref(port->plugin_port);
821 }
822
823 if(port->conversion != NULL){
824 g_object_unref(port->conversion);
825 }
826
827 if(port->automation != NULL){
828 g_list_free_full(port->automation,
829 g_object_unref);
830 }
831
832 /* call parent */
833 G_OBJECT_CLASS(ags_port_parent_class)->finalize(gobject);
834 }
835
836 AgsUUID*
ags_port_get_uuid(AgsConnectable * connectable)837 ags_port_get_uuid(AgsConnectable *connectable)
838 {
839 AgsPort *port;
840
841 AgsUUID *ptr;
842
843 GRecMutex *port_mutex;
844
845 port = AGS_PORT(connectable);
846
847 /* get port mutex */
848 port_mutex = AGS_PORT_GET_OBJ_MUTEX(port);
849
850 /* get UUID */
851 g_rec_mutex_lock(port_mutex);
852
853 ptr = port->uuid;
854
855 g_rec_mutex_unlock(port_mutex);
856
857 return(ptr);
858 }
859
860 gboolean
ags_port_has_resource(AgsConnectable * connectable)861 ags_port_has_resource(AgsConnectable *connectable)
862 {
863 return(TRUE);
864 }
865
866 gboolean
ags_port_is_ready(AgsConnectable * connectable)867 ags_port_is_ready(AgsConnectable *connectable)
868 {
869 AgsPort *port;
870
871 gboolean is_ready;
872
873 port = AGS_PORT(connectable);
874
875 /* check is added */
876 is_ready = ags_port_test_flags(port, AGS_PORT_ADDED_TO_REGISTRY);
877
878 return(is_ready);
879 }
880
881 void
ags_port_add_to_registry(AgsConnectable * connectable)882 ags_port_add_to_registry(AgsConnectable *connectable)
883 {
884 AgsPort *port;
885
886 AgsRegistry *registry;
887 AgsRegistryEntry *entry;
888
889 AgsApplicationContext *application_context;
890
891 GList *list;
892
893 if(ags_connectable_is_ready(connectable)){
894 return;
895 }
896
897 port = AGS_PORT(connectable);
898
899 ags_port_set_flags(port, AGS_PORT_ADDED_TO_REGISTRY);
900
901 application_context = ags_application_context_get_instance();
902
903 registry = ags_service_provider_get_registry(AGS_SERVICE_PROVIDER(application_context));
904
905 if(registry != NULL){
906 entry = ags_registry_entry_alloc(registry);
907 g_value_set_object(entry->entry,
908 (gpointer) port);
909 ags_registry_add_entry(registry,
910 entry);
911 }
912
913 //TODO:JK: implement me
914 }
915
916 void
ags_port_remove_from_registry(AgsConnectable * connectable)917 ags_port_remove_from_registry(AgsConnectable *connectable)
918 {
919 if(!ags_connectable_is_ready(connectable)){
920 return;
921 }
922
923 //TODO:JK: implement me
924 }
925
926 xmlNode*
ags_port_list_resource(AgsConnectable * connectable)927 ags_port_list_resource(AgsConnectable *connectable)
928 {
929 xmlNode *node;
930
931 node = NULL;
932
933 //TODO:JK: implement me
934
935 return(node);
936 }
937
938 xmlNode*
ags_port_xml_compose(AgsConnectable * connectable)939 ags_port_xml_compose(AgsConnectable *connectable)
940 {
941 xmlNode *node;
942
943 node = NULL;
944
945 //TODO:JK: implement me
946
947 return(node);
948 }
949
950 void
ags_port_xml_parse(AgsConnectable * connectable,xmlNode * node)951 ags_port_xml_parse(AgsConnectable *connectable,
952 xmlNode *node)
953 {
954 //TODO:JK: implement me
955 }
956
957 gboolean
ags_port_is_connected(AgsConnectable * connectable)958 ags_port_is_connected(AgsConnectable *connectable)
959 {
960 AgsPort *port;
961
962 gboolean is_connected;
963
964 port = AGS_PORT(connectable);
965
966 /* check is connected */
967 is_connected = ags_port_test_flags(port, AGS_PORT_CONNECTED);
968
969 return(is_connected);
970 }
971
972 void
ags_port_connect(AgsConnectable * connectable)973 ags_port_connect(AgsConnectable *connectable)
974 {
975 AgsPort *port;
976
977 GList *list_start, *list;
978
979 GRecMutex *port_mutex;
980
981 if(ags_connectable_is_connected(connectable)){
982 return;
983 }
984
985 port = AGS_PORT(connectable);
986
987 ags_port_set_flags(port, AGS_PORT_CONNECTED);
988 }
989
990 void
ags_port_disconnect(AgsConnectable * connectable)991 ags_port_disconnect(AgsConnectable *connectable)
992 {
993 AgsPort *port;
994
995 GList *list_start, *list;
996
997 GRecMutex *port_mutex;
998
999 if(!ags_connectable_is_connected(connectable)){
1000 return;
1001 }
1002
1003 port = AGS_PORT(connectable);
1004
1005 ags_port_unset_flags(port, AGS_PORT_CONNECTED);
1006 }
1007
1008 /**
1009 * ags_port_test_flags:
1010 * @port: the #AgsPort
1011 * @flags: the flags
1012 *
1013 * Test @flags to be set on @port.
1014 *
1015 * Returns: %TRUE if flags are set, else %FALSE
1016 *
1017 * Since: 3.0.0
1018 */
1019 gboolean
ags_port_test_flags(AgsPort * port,guint flags)1020 ags_port_test_flags(AgsPort *port, guint flags)
1021 {
1022 gboolean retval;
1023
1024 GRecMutex *port_mutex;
1025
1026 if(!AGS_IS_PORT(port)){
1027 return(FALSE);
1028 }
1029
1030 /* get port mutex */
1031 port_mutex = AGS_PORT_GET_OBJ_MUTEX(port);
1032
1033 /* test */
1034 g_rec_mutex_lock(port_mutex);
1035
1036 retval = (flags & (port->flags)) ? TRUE: FALSE;
1037
1038 g_rec_mutex_unlock(port_mutex);
1039
1040 return(retval);
1041 }
1042
1043 /**
1044 * ags_port_set_flags:
1045 * @port: the #AgsPort
1046 * @flags: the flags
1047 *
1048 * Set flags.
1049 *
1050 * Since: 3.0.0
1051 */
1052 void
ags_port_set_flags(AgsPort * port,guint flags)1053 ags_port_set_flags(AgsPort *port, guint flags)
1054 {
1055 GRecMutex *port_mutex;
1056
1057 if(!AGS_IS_PORT(port)){
1058 return;
1059 }
1060
1061 /* get port mutex */
1062 port_mutex = AGS_PORT_GET_OBJ_MUTEX(port);
1063
1064 /* set flags */
1065 g_rec_mutex_lock(port_mutex);
1066
1067 port->flags |= flags;
1068
1069 g_rec_mutex_unlock(port_mutex);
1070 }
1071
1072 /**
1073 * ags_port_unset_flags:
1074 * @port: the #AgsPort
1075 * @flags: the flags
1076 *
1077 * Unset flags.
1078 *
1079 * Since: 3.0.0
1080 */
1081 void
ags_port_unset_flags(AgsPort * port,guint flags)1082 ags_port_unset_flags(AgsPort *port, guint flags)
1083 {
1084 GRecMutex *port_mutex;
1085
1086 if(!AGS_IS_PORT(port)){
1087 return;
1088 }
1089
1090 /* get port mutex */
1091 port_mutex = AGS_PORT_GET_OBJ_MUTEX(port);
1092
1093 /* set flags */
1094 g_rec_mutex_lock(port_mutex);
1095
1096 port->flags &= (~flags);
1097
1098 g_rec_mutex_unlock(port_mutex);
1099 }
1100
1101 void
ags_port_real_safe_read(AgsPort * port,GValue * value)1102 ags_port_real_safe_read(AgsPort *port, GValue *value)
1103 {
1104 guint overall_size;
1105 gpointer data;
1106
1107 GRecMutex *port_mutex;
1108
1109 /* get port mutex */
1110 port_mutex = AGS_PORT_GET_OBJ_MUTEX(port);
1111
1112 /* safe read */
1113 g_rec_mutex_lock(port_mutex);
1114
1115 overall_size = port->port_value_length * port->port_value_size;
1116
1117 if(!port->port_value_is_pointer){
1118 if(port->port_value_type == G_TYPE_BOOLEAN){
1119 g_value_set_boolean(value, port->port_value.ags_port_boolean);
1120 }else if(port->port_value_type == G_TYPE_INT64){
1121 g_value_set_int64(value, port->port_value.ags_port_int);
1122 }else if(port->port_value_type == G_TYPE_UINT64){
1123 g_value_set_uint64(value, port->port_value.ags_port_uint);
1124 }else if(port->port_value_type == G_TYPE_FLOAT){
1125 gfloat new_value;
1126
1127 if((AGS_PORT_CONVERT_ALWAYS & (port->flags)) != 0){
1128 new_value = (gfloat) ags_conversion_convert(port->conversion,
1129 (double) port->port_value.ags_port_float,
1130 TRUE);
1131 }else{
1132 new_value = port->port_value.ags_port_float;
1133 }
1134
1135 g_value_set_float(value, new_value);
1136 }else if(port->port_value_type == G_TYPE_DOUBLE){
1137 gdouble new_value;
1138
1139 if((AGS_PORT_CONVERT_ALWAYS & (port->flags)) != 0){
1140 new_value = ags_conversion_convert(port->conversion,
1141 port->port_value.ags_port_double,
1142 TRUE);
1143 }else{
1144 new_value = port->port_value.ags_port_double;
1145 }
1146
1147 g_value_set_double(value, new_value);
1148 }else{
1149 data = NULL;
1150
1151 if(port->port_value_type == G_TYPE_POINTER){
1152 data = port->port_value.ags_port_pointer;
1153 }else if(port->port_value_type == G_TYPE_OBJECT){
1154 data = port->port_value.ags_port_object;
1155 }
1156
1157 g_value_set_pointer(value, data);
1158 }
1159 }else{
1160 data = NULL;
1161
1162 if(port->port_value_type == G_TYPE_STRING){
1163 data = g_strdup(port->port_value.ags_port_string);
1164 }else if(port->port_value_type == G_TYPE_POINTER){
1165 data = port->port_value.ags_port_pointer;
1166 }else if(port->port_value_type == G_TYPE_OBJECT){
1167 data = port->port_value.ags_port_object;
1168 }else{
1169 data = (gpointer) g_value_get_pointer(value);
1170
1171 if(port->port_value_type == G_TYPE_BOOLEAN){
1172 memcpy(data, port->port_value.ags_port_boolean_ptr, overall_size);
1173 }else if(port->port_value_type == G_TYPE_INT64){
1174 memcpy(data, port->port_value.ags_port_int_ptr, overall_size);
1175 }else if(port->port_value_type == G_TYPE_UINT64){
1176 memcpy(data, port->port_value.ags_port_uint_ptr, overall_size);
1177 }else if(port->port_value_type == G_TYPE_FLOAT){
1178 guint i;
1179
1180 for(i = 0; i < port->port_value_length; i++){
1181 // g_message("port[0x%x]: %f", port, port->port_value.ags_port_float_ptr[i]);
1182 ((gfloat *) data)[i] = port->port_value.ags_port_float_ptr[i];
1183 }
1184 }else if(port->port_value_type == G_TYPE_DOUBLE){
1185 guint i;
1186
1187 for(i = 0; i < port->port_value_length; i++){
1188 // g_message("port[0x%x]: %f", port, port->port_value.ags_port_double_ptr[i]);
1189 ((gdouble *) data)[i] = port->port_value.ags_port_double_ptr[i];
1190 }
1191 }
1192 }
1193
1194 g_value_set_pointer(value, data);
1195 }
1196
1197 g_rec_mutex_unlock(port_mutex);
1198 }
1199
1200 /**
1201 * ags_port_safe_read:
1202 * @port: an #AgsPort
1203 * @value: the #GValue to store result
1204 *
1205 * Perform safe read.
1206 *
1207 * Since: 3.0.0
1208 */
1209 void
ags_port_safe_read(AgsPort * port,GValue * value)1210 ags_port_safe_read(AgsPort *port, GValue *value)
1211 {
1212 g_return_if_fail(AGS_IS_PORT(port));
1213 g_object_ref(G_OBJECT(port));
1214 g_signal_emit(G_OBJECT(port),
1215 port_signals[SAFE_READ], 0,
1216 value);
1217 g_object_unref(G_OBJECT(port));
1218 }
1219
1220 /**
1221 * ags_port_safe_read_raw:
1222 * @port: an #AgsPort
1223 * @value: the #GValue to store result
1224 *
1225 * Perform safe read.
1226 *
1227 * Since: 3.0.0
1228 */
1229 void
ags_port_safe_read_raw(AgsPort * port,GValue * value)1230 ags_port_safe_read_raw(AgsPort *port, GValue *value)
1231 {
1232 guint overall_size;
1233 gpointer data;
1234
1235 GRecMutex *port_mutex;
1236
1237 /* get port mutex */
1238 port_mutex = AGS_PORT_GET_OBJ_MUTEX(port);
1239
1240 /* safe read */
1241 g_rec_mutex_lock(port_mutex);
1242
1243 overall_size = port->port_value_length * port->port_value_size;
1244
1245 if(!port->port_value_is_pointer){
1246 if(port->port_value_type == G_TYPE_BOOLEAN){
1247 g_value_set_boolean(value, port->port_value.ags_port_boolean);
1248 }else if(port->port_value_type == G_TYPE_INT64){
1249 g_value_set_int64(value, port->port_value.ags_port_int);
1250 }else if(port->port_value_type == G_TYPE_UINT64){
1251 g_value_set_uint64(value, port->port_value.ags_port_uint);
1252 }else if(port->port_value_type == G_TYPE_FLOAT){
1253 gfloat new_value;
1254
1255 new_value = port->port_value.ags_port_float;
1256
1257 g_value_set_float(value, new_value);
1258 }else if(port->port_value_type == G_TYPE_DOUBLE){
1259 gdouble new_value;
1260
1261 new_value = port->port_value.ags_port_double;
1262
1263 g_value_set_double(value, new_value);
1264 }else{
1265 data = NULL;
1266
1267 if(port->port_value_type == G_TYPE_POINTER){
1268 data = port->port_value.ags_port_pointer;
1269 }else if(port->port_value_type == G_TYPE_OBJECT){
1270 data = port->port_value.ags_port_object;
1271 }
1272
1273 g_value_set_pointer(value, data);
1274 }
1275 }else{
1276 data = NULL;
1277
1278 if(port->port_value_type == G_TYPE_POINTER){
1279 data = port->port_value.ags_port_pointer;
1280 }else if(port->port_value_type == G_TYPE_OBJECT){
1281 data = port->port_value.ags_port_object;
1282 }else{
1283 data = (gpointer) g_malloc(overall_size);
1284
1285 if(port->port_value_type == G_TYPE_BOOLEAN){
1286 memcpy(data, port->port_value.ags_port_boolean_ptr, overall_size);
1287 }else if(port->port_value_type == G_TYPE_INT64){
1288 memcpy(data, port->port_value.ags_port_int_ptr, overall_size);
1289 }else if(port->port_value_type == G_TYPE_UINT64){
1290 memcpy(data, port->port_value.ags_port_uint_ptr, overall_size);
1291 }else if(port->port_value_type == G_TYPE_FLOAT){
1292 guint i;
1293
1294 for(i = 0; i < port->port_value_length; i++){
1295 ((gfloat *) data)[i] = port->port_value.ags_port_float_ptr[i];
1296 }
1297 }else if(port->port_value_type == G_TYPE_DOUBLE){
1298 guint i;
1299
1300 for(i = 0; i < port->port_value_length; i++){
1301 ((gdouble *) data)[i] = port->port_value.ags_port_double_ptr[i];
1302 }
1303 }
1304 }
1305
1306 g_value_set_pointer(value, data);
1307 }
1308
1309 g_rec_mutex_unlock(port_mutex);
1310 }
1311
1312 void
ags_port_real_safe_write(AgsPort * port,GValue * value)1313 ags_port_real_safe_write(AgsPort *port, GValue *value)
1314 {
1315 guint overall_size;
1316 gpointer data;
1317
1318 GRecMutex *port_mutex;
1319
1320 /* get port mutex */
1321 port_mutex = AGS_PORT_GET_OBJ_MUTEX(port);
1322
1323 /* write */
1324 g_rec_mutex_lock(port_mutex);
1325
1326 overall_size = port->port_value_length * port->port_value_size;
1327
1328 if(!port->port_value_is_pointer){
1329 if(port->port_value_type == G_TYPE_BOOLEAN){
1330 port->port_value.ags_port_boolean = g_value_get_boolean(value);
1331 }else if(port->port_value_type == G_TYPE_INT64){
1332 port->port_value.ags_port_int = g_value_get_int64(value);
1333 }else if(port->port_value_type == G_TYPE_UINT64){
1334 port->port_value.ags_port_uint = g_value_get_uint64(value);
1335 }else if(port->port_value_type == G_TYPE_FLOAT){
1336 if((AGS_PORT_CONVERT_ALWAYS & (port->flags)) != 0 &&
1337 port->conversion != NULL){
1338 if((AGS_PORT_USE_LADSPA_FLOAT & (port->flags)) == 0){
1339 port->port_value.ags_port_float = (gfloat) ags_conversion_convert(port->conversion,
1340 (double) g_value_get_float(value),
1341 FALSE);
1342 }else{
1343 LADSPA_Data val;
1344
1345 val = g_value_get_float(value);
1346 port->port_value.ags_port_ladspa = (LADSPA_Data) ags_conversion_convert(port->conversion,
1347 (double) val,
1348 FALSE);
1349 }
1350 }else{
1351 if((AGS_PORT_USE_LADSPA_FLOAT & (port->flags)) == 0){
1352 port->port_value.ags_port_float = (gfloat) g_value_get_float(value);
1353 }else{
1354 port->port_value.ags_port_ladspa = (LADSPA_Data) g_value_get_float(value);
1355 }
1356 }
1357 }else if(port->port_value_type == G_TYPE_DOUBLE){
1358 if((AGS_PORT_CONVERT_ALWAYS & (port->flags)) != 0 &&
1359 port->conversion != NULL){
1360 port->port_value.ags_port_double = ags_conversion_convert(port->conversion,
1361 g_value_get_double(value),
1362 FALSE);
1363 }else{
1364 port->port_value.ags_port_double = g_value_get_double(value);
1365 }
1366 }else if(port->port_value_type == G_TYPE_POINTER){
1367 port->port_value.ags_port_pointer = g_value_get_pointer(value);
1368 }else if(port->port_value_type == G_TYPE_OBJECT){
1369 port->port_value.ags_port_object = g_value_get_object(value);
1370 }else{
1371 g_warning("ags_port.c: unknown type");
1372 }
1373 }else{
1374 data = g_value_get_pointer(value);
1375
1376 if(port->port_value_type == G_TYPE_BOOLEAN){
1377 memcpy(port->port_value.ags_port_boolean_ptr, data, overall_size);
1378 }else if(port->port_value_type == G_TYPE_INT64){
1379 memcpy(port->port_value.ags_port_int_ptr, data, overall_size);
1380 }else if(port->port_value_type == G_TYPE_UINT64){
1381 memcpy(port->port_value.ags_port_uint_ptr, data, overall_size);
1382 }else if(port->port_value_type == G_TYPE_DOUBLE){
1383 memcpy(port->port_value.ags_port_double_ptr, data, overall_size);
1384 }else if(port->port_value_type == G_TYPE_POINTER){
1385 port->port_value.ags_port_pointer = data;
1386 }else{
1387 data = g_value_get_object(value);
1388
1389 if(port->port_value_type == G_TYPE_OBJECT){
1390 port->port_value.ags_port_object = data;
1391 }else{
1392 g_warning("ags_port.c: unknown type");
1393 }
1394 }
1395 }
1396
1397 g_rec_mutex_unlock(port_mutex);
1398 }
1399
1400 /**
1401 * ags_port_safe_write:
1402 * @port: an #AgsPort
1403 * @value: the #GValue containing data
1404 *
1405 * Perform safe write.
1406 *
1407 * Since: 3.0.0
1408 */
1409 void
ags_port_safe_write(AgsPort * port,GValue * value)1410 ags_port_safe_write(AgsPort *port, GValue *value)
1411 {
1412 g_return_if_fail(AGS_IS_PORT(port));
1413 g_object_ref(G_OBJECT(port));
1414 g_signal_emit(G_OBJECT(port),
1415 port_signals[SAFE_WRITE], 0,
1416 value);
1417 g_object_unref(G_OBJECT(port));
1418 }
1419
1420 void
ags_port_safe_write_raw(AgsPort * port,GValue * value)1421 ags_port_safe_write_raw(AgsPort *port, GValue *value)
1422 {
1423 guint overall_size;
1424 gpointer data;
1425
1426 GRecMutex *port_mutex;
1427
1428 if(!AGS_IS_PORT(port)){
1429 return;
1430 }
1431
1432 /* get port mutex */
1433 port_mutex = AGS_PORT_GET_OBJ_MUTEX(port);
1434
1435 /* write raw */
1436 g_rec_mutex_lock(port_mutex);
1437
1438 overall_size = port->port_value_length * port->port_value_size;
1439
1440 if(!port->port_value_is_pointer){
1441 if(port->port_value_type == G_TYPE_BOOLEAN){
1442 port->port_value.ags_port_boolean = g_value_get_boolean(value);
1443 }else if(port->port_value_type == G_TYPE_INT64){
1444 port->port_value.ags_port_int = g_value_get_int64(value);
1445 }else if(port->port_value_type == G_TYPE_UINT64){
1446 port->port_value.ags_port_uint = g_value_get_uint64(value);
1447 }else if(port->port_value_type == G_TYPE_FLOAT){
1448 if((AGS_PORT_USE_LADSPA_FLOAT & (port->flags)) == 0){
1449 port->port_value.ags_port_float = (gfloat) g_value_get_float(value);
1450 }else{
1451 port->port_value.ags_port_ladspa = (LADSPA_Data) g_value_get_float(value);
1452 }
1453 }else if(port->port_value_type == G_TYPE_DOUBLE){
1454 port->port_value.ags_port_double = g_value_get_double(value);
1455 }else if(port->port_value_type == G_TYPE_POINTER){
1456 port->port_value.ags_port_pointer = g_value_get_pointer(value);
1457 }else if(port->port_value_type == G_TYPE_OBJECT){
1458 port->port_value.ags_port_object = g_value_get_object(value);
1459 }else{
1460 g_warning("ags_port.c: unknown type");
1461 }
1462 }else{
1463 data = g_value_get_pointer(value);
1464
1465 if(port->port_value_type == G_TYPE_BOOLEAN){
1466 memcpy(port->port_value.ags_port_boolean_ptr, data, overall_size);
1467 }else if(port->port_value_type == G_TYPE_INT64){
1468 memcpy(port->port_value.ags_port_int_ptr, data, overall_size);
1469 }else if(port->port_value_type == G_TYPE_UINT64){
1470 memcpy(port->port_value.ags_port_uint_ptr, data, overall_size);
1471 }else if(port->port_value_type == G_TYPE_DOUBLE){
1472 memcpy(port->port_value.ags_port_double_ptr, data, overall_size);
1473 }else if(port->port_value_type == G_TYPE_POINTER){
1474 port->port_value.ags_port_pointer = data;
1475 }else{
1476 data = g_value_get_object(value);
1477
1478 if(port->port_value_type == G_TYPE_OBJECT){
1479 port->port_value.ags_port_object = data;
1480 }else{
1481 g_warning("ags_port.c: unknown type");
1482 }
1483 }
1484 }
1485
1486 g_rec_mutex_unlock(port_mutex);
1487 }
1488
1489 void
ags_port_real_safe_get_property(AgsPort * port,gchar * property_name,GValue * value)1490 ags_port_real_safe_get_property(AgsPort *port, gchar *property_name, GValue *value)
1491 {
1492 GRecMutex *port_mutex;
1493
1494 /* get port mutex */
1495 port_mutex = AGS_PORT_GET_OBJ_MUTEX(port);
1496
1497 /* get property */
1498 g_rec_mutex_lock(port_mutex);
1499
1500 g_object_get_property(port->port_value.ags_port_object,
1501 property_name,
1502 value);
1503
1504 g_rec_mutex_unlock(port_mutex);
1505 }
1506
1507 /**
1508 * ags_port_safe_get_property:
1509 * @port: an #AgsPort
1510 * @property_name: the property's name
1511 * @value: the #GValue to store the result
1512 *
1513 * Perform safe get property.
1514 *
1515 * Since: 3.0.0
1516 */
1517 void
ags_port_safe_get_property(AgsPort * port,gchar * property_name,GValue * value)1518 ags_port_safe_get_property(AgsPort *port, gchar *property_name, GValue *value)
1519 {
1520 g_return_if_fail(AGS_IS_PORT(port));
1521 g_object_ref(G_OBJECT(port));
1522 g_signal_emit(G_OBJECT(port),
1523 port_signals[SAFE_GET_PROPERTY], 0,
1524 property_name, value);
1525 g_object_unref(G_OBJECT(port));
1526 }
1527
1528 void
ags_port_real_safe_set_property(AgsPort * port,gchar * property_name,GValue * value)1529 ags_port_real_safe_set_property(AgsPort *port, gchar *property_name, GValue *value)
1530 {
1531 GRecMutex *port_mutex;
1532
1533 /* get port mutex */
1534 port_mutex = AGS_PORT_GET_OBJ_MUTEX(port);
1535
1536 /* set property */
1537 g_rec_mutex_lock(port_mutex);
1538
1539 g_object_set_property(port->port_value.ags_port_object,
1540 property_name,
1541 value);
1542
1543 g_rec_mutex_unlock(port_mutex);
1544 }
1545
1546 /**
1547 * ags_port_safe_set_property:
1548 * @port: an #AgsPort
1549 * @property_name: the property's name
1550 * @value: the #GValue containing data
1551 *
1552 * Perform safe set property.
1553 *
1554 * Since: 3.0.0
1555 */
1556 void
ags_port_safe_set_property(AgsPort * port,gchar * property_name,GValue * value)1557 ags_port_safe_set_property(AgsPort *port, gchar *property_name, GValue *value)
1558 {
1559 g_return_if_fail(AGS_IS_PORT(port));
1560 g_object_ref(G_OBJECT(port));
1561 g_signal_emit(G_OBJECT(port),
1562 port_signals[SAFE_SET_PROPERTY], 0,
1563 property_name, value);
1564 g_object_unref(G_OBJECT(port));
1565 }
1566
1567 /**
1568 * ags_port_find_specifier:
1569 * @port: (element-type AgsAudio.Port) (transfer none): the #GList-struct containing #AgsPort
1570 * @specifier: the recall specifier to match
1571 *
1572 * Retrieve port by specifier.
1573 *
1574 * Returns: (element-type AgsAudio.Port) (transfer none): Next matching #GList-struct or %NULL
1575 *
1576 * Since: 3.0.0
1577 */
1578 GList*
ags_port_find_specifier(GList * port,gchar * specifier)1579 ags_port_find_specifier(GList *port, gchar *specifier)
1580 {
1581 AgsPort *current_port;
1582
1583 gboolean success;
1584
1585 GRecMutex *port_mutex;
1586
1587 while(port != NULL){
1588 current_port = port->data;
1589
1590 /* get port mutex */
1591 port_mutex = AGS_PORT_GET_OBJ_MUTEX(current_port);
1592
1593 /* check specifier */
1594 g_rec_mutex_lock(port_mutex);
1595
1596 success = (!g_strcmp0(current_port->specifier,
1597 specifier)) ? TRUE: FALSE;
1598
1599 g_rec_mutex_unlock(port_mutex);
1600
1601 if(success){
1602 return(port);
1603 }
1604
1605 port = port->next;
1606 }
1607
1608 return(NULL);
1609 }
1610
1611 /**
1612 * ags_port_add_automation:
1613 * @port: the #AgsPort
1614 * @automation: the #AgsAutomation
1615 *
1616 * Adds an automation.
1617 *
1618 * Since: 3.0.0
1619 */
1620 void
ags_port_add_automation(AgsPort * port,GObject * automation)1621 ags_port_add_automation(AgsPort *port, GObject *automation)
1622 {
1623 GRecMutex *port_mutex;
1624
1625 if(!AGS_IS_PORT(port) ||
1626 !AGS_IS_AUTOMATION(automation)){
1627 return;
1628 }
1629
1630 /* get port mutex */
1631 port_mutex = AGS_PORT_GET_OBJ_MUTEX(port);
1632
1633 /* add recall id */
1634 g_rec_mutex_lock(port_mutex);
1635
1636 if(g_list_find(port->automation,
1637 automation) == NULL){
1638 g_object_ref(automation);
1639 port->automation = ags_automation_add(port->automation,
1640 (AgsAutomation *) automation);
1641
1642 g_object_set(automation,
1643 "port", port,
1644 NULL);
1645 }
1646
1647 g_rec_mutex_unlock(port_mutex);
1648 }
1649
1650 /**
1651 * ags_port_remove_automation:
1652 * @port: the #AgsPort
1653 * @automation: the #AgsAutomation
1654 *
1655 * Removes an automation.
1656 *
1657 * Since: 3.0.0
1658 */
1659 void
ags_port_remove_automation(AgsPort * port,GObject * automation)1660 ags_port_remove_automation(AgsPort *port, GObject *automation)
1661 {
1662 GRecMutex *port_mutex;
1663
1664 if(!AGS_IS_PORT(port) ||
1665 !AGS_IS_AUTOMATION(automation)){
1666 return;
1667 }
1668
1669 /* get port mutex */
1670 port_mutex = AGS_PORT_GET_OBJ_MUTEX(port);
1671
1672 /* remove automation */
1673 g_rec_mutex_lock(port_mutex);
1674
1675 if(g_list_find(port->automation,
1676 automation) != NULL){
1677 port->automation = g_list_remove(port->automation,
1678 automation);
1679
1680 g_object_set(automation,
1681 "port", NULL,
1682 NULL);
1683
1684 g_object_unref(automation);
1685 }
1686
1687 g_rec_mutex_unlock(port_mutex);
1688 }
1689
1690 /**
1691 * ags_port_new:
1692 *
1693 * Creates an #AgsPort.
1694 *
1695 * Returns: a new #AgsPort.
1696 *
1697 * Since: 3.0.0
1698 */
1699 AgsPort*
ags_port_new()1700 ags_port_new()
1701 {
1702 AgsPort *port;
1703
1704 port = (AgsPort *) g_object_new(AGS_TYPE_PORT,
1705 NULL);
1706
1707 return(port);
1708 }
1709