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/recall/ags_envelope_channel.h>
21 
22 #include <ags/i18n.h>
23 
24 void ags_envelope_channel_class_init(AgsEnvelopeChannelClass *envelope_channel);
25 void ags_envelope_channel_plugin_interface_init(AgsPluginInterface *plugin);
26 void ags_envelope_channel_init(AgsEnvelopeChannel *envelope_channel);
27 void ags_envelope_channel_set_property(GObject *gobject,
28 				       guint prop_id,
29 				       const GValue *value,
30 				       GParamSpec *param_spec);
31 void ags_envelope_channel_get_property(GObject *gobject,
32 				       guint prop_id,
33 				       GValue *value,
34 				       GParamSpec *param_spec);
35 void ags_envelope_channel_dispose(GObject *gobject);
36 void ags_envelope_channel_finalize(GObject *gobject);
37 
38 void ags_envelope_channel_set_ports(AgsPlugin *plugin, GList *port);
39 
40 /**
41  * SECTION:ags_envelope_channel
42  * @short_description: envelopes channel
43  * @title: AgsEnvelopeChannel
44  * @section_id:
45  * @include: ags/audio/recall/ags_envelope_channel.h
46  *
47  * The #AgsEnvelopeChannel class provides ports to the effect processor.
48  */
49 
50 enum{
51   PROP_0,
52   PROP_USE_NOTE_LENGTH,
53   PROP_USE_FIXED_LENGTH,
54   PROP_FIXED_LENGTH,
55   PROP_ATTACK,
56   PROP_DECAY,
57   PROP_SUSTAIN,
58   PROP_RELEASE,
59   PROP_RATIO,
60 };
61 
62 static gpointer ags_envelope_channel_parent_class = NULL;
63 
64 const gchar *ags_envelope_channel_plugin_name = "ags-envelope";
65 const gchar *ags_envelope_channel_specifier[] = {
66   "./use-note-length[0]",
67   "./use-fixed-length[0]",
68   "./fixed-length[0]",
69   "./attack[0]",
70   "./decay[0]",
71   "./sustain[0]",
72   "./release[0]",
73   "./ratio[0]"
74 };
75 
76 const gchar *ags_envelope_channel_control_port[] = {
77   "1/8",
78   "2/8",
79   "3/8",
80   "4/8",
81   "5/8",
82   "6/8",
83   "7/8",
84   "8/8",
85 };
86 
87 GType
ags_envelope_channel_get_type()88 ags_envelope_channel_get_type()
89 {
90   static volatile gsize g_define_type_id__volatile = 0;
91 
92   if(g_once_init_enter (&g_define_type_id__volatile)){
93     GType ags_type_envelope_channel = 0;
94 
95     static const GTypeInfo ags_envelope_channel_info = {
96       sizeof (AgsEnvelopeChannelClass),
97       NULL, /* base_init */
98       NULL, /* base_finalize */
99       (GClassInitFunc) ags_envelope_channel_class_init,
100       NULL, /* class_finalize */
101       NULL, /* class_data */
102       sizeof (AgsEnvelopeChannel),
103       0,    /* n_preallocs */
104       (GInstanceInitFunc) ags_envelope_channel_init,
105     };
106 
107     static const GInterfaceInfo ags_plugin_interface_info = {
108       (GInterfaceInitFunc) ags_envelope_channel_plugin_interface_init,
109       NULL, /* interface_finalize */
110       NULL, /* interface_data */
111     };
112 
113     ags_type_envelope_channel = g_type_register_static(AGS_TYPE_RECALL_CHANNEL,
114 						       "AgsEnvelopeChannel",
115 						       &ags_envelope_channel_info,
116 						       0);
117 
118     g_type_add_interface_static(ags_type_envelope_channel,
119 				AGS_TYPE_PLUGIN,
120 				&ags_plugin_interface_info);
121 
122     g_once_init_leave(&g_define_type_id__volatile, ags_type_envelope_channel);
123   }
124 
125   return g_define_type_id__volatile;
126 }
127 
128 void
ags_envelope_channel_plugin_interface_init(AgsPluginInterface * plugin)129 ags_envelope_channel_plugin_interface_init(AgsPluginInterface *plugin)
130 {
131   plugin->set_ports = ags_envelope_channel_set_ports;
132 }
133 
134 void
ags_envelope_channel_class_init(AgsEnvelopeChannelClass * envelope_channel)135 ags_envelope_channel_class_init(AgsEnvelopeChannelClass *envelope_channel)
136 {
137   GObjectClass *gobject;
138 
139   GParamSpec *param_spec;
140 
141   ags_envelope_channel_parent_class = g_type_class_peek_parent(envelope_channel);
142 
143   /* GObjectClass */
144   gobject = (GObjectClass *) envelope_channel;
145 
146   gobject->set_property = ags_envelope_channel_set_property;
147   gobject->get_property = ags_envelope_channel_get_property;
148 
149   gobject->dispose = ags_envelope_channel_dispose;
150   gobject->finalize = ags_envelope_channel_finalize;
151 
152   /* properties */
153   /**
154    * AgsEnvelopeChannel:use-note-length:
155    *
156    * Use note length to compute envelope.
157    *
158    * Since: 3.0.0
159    */
160   param_spec = g_param_spec_object("use-note-length",
161 				   i18n_pspec("use note length"),
162 				   i18n_pspec("Use note length to compute envelope"),
163 				   AGS_TYPE_PORT,
164 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
165   g_object_class_install_property(gobject,
166 				  PROP_USE_NOTE_LENGTH,
167 				  param_spec);
168 
169   /**
170    * AgsEnvelopeChannel:use-fixed-length:
171    *
172    * Use fixed length to compute envelope.
173    *
174    * Since: 3.0.0
175    */
176   param_spec = g_param_spec_object("use-fixed-length",
177 				   i18n_pspec("use fixed length"),
178 				   i18n_pspec("Use fixed length to compute envelope"),
179 				   AGS_TYPE_PORT,
180 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
181   g_object_class_install_property(gobject,
182 				  PROP_USE_FIXED_LENGTH,
183 				  param_spec);
184 
185   /**
186    * AgsEnvelopeChannel:fixed-length:
187    *
188    * The fixed length to compute envelope.
189    *
190    * Since: 3.0.0
191    */
192   param_spec = g_param_spec_object("fixed-length",
193 				   i18n_pspec("fixed length"),
194 				   i18n_pspec("The fixed length to compute envelope"),
195 				   AGS_TYPE_PORT,
196 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
197   g_object_class_install_property(gobject,
198 				  PROP_FIXED_LENGTH,
199 				  param_spec);
200 
201   /**
202    * AgsEnvelopeChannel:attack:
203    *
204    * The attack of envelope.
205    *
206    * Since: 3.0.0
207    */
208   param_spec = g_param_spec_object("attack",
209 				   i18n_pspec("attack channel"),
210 				   i18n_pspec("Attack of the channel"),
211 				   AGS_TYPE_PORT,
212 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
213   g_object_class_install_property(gobject,
214 				  PROP_ATTACK,
215 				  param_spec);
216 
217   /**
218    * AgsEnvelopeChannel:decay:
219    *
220    * The decay of envelope.
221    *
222    * Since: 3.0.0
223    */
224   param_spec = g_param_spec_object("decay",
225 				   i18n_pspec("decay channel"),
226 				   i18n_pspec("Decay of the channel"),
227 				   AGS_TYPE_PORT,
228 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
229   g_object_class_install_property(gobject,
230 				  PROP_DECAY,
231 				  param_spec);
232 
233   /**
234    * AgsEnvelopeChannel:sustain:
235    *
236    * The sustain of envelope.
237    *
238    * Since: 3.0.0
239    */
240   param_spec = g_param_spec_object("sustain",
241 				   i18n_pspec("sustain channel"),
242 				   i18n_pspec("Sustain of the channel"),
243 				   AGS_TYPE_PORT,
244 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
245   g_object_class_install_property(gobject,
246 				  PROP_SUSTAIN,
247 				  param_spec);
248 
249   /**
250    * AgsEnvelopeChannel:release:
251    *
252    * The release of envelope.
253    *
254    * Since: 3.0.0
255    */
256   param_spec = g_param_spec_object("release",
257 				   i18n_pspec("release channel"),
258 				   i18n_pspec("Release of the channel"),
259 				   AGS_TYPE_PORT,
260 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
261   g_object_class_install_property(gobject,
262 				  PROP_RELEASE,
263 				  param_spec);
264 
265   /**
266    * AgsEnvelopeChannel:ratio:
267    *
268    * The ratio of envelope.
269    *
270    * Since: 3.0.0
271    */
272   param_spec = g_param_spec_object("ratio",
273 				   i18n_pspec("envelope ratio"),
274 				   i18n_pspec("The ratio of the envelope"),
275 				   AGS_TYPE_PORT,
276 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
277   g_object_class_install_property(gobject,
278 				  PROP_RATIO,
279 				  param_spec);
280 }
281 
282 void
ags_envelope_channel_init(AgsEnvelopeChannel * envelope_channel)283 ags_envelope_channel_init(AgsEnvelopeChannel *envelope_channel)
284 {
285   GList *port;
286 
287   AGS_RECALL(envelope_channel)->name = "ags-envelope";
288   AGS_RECALL(envelope_channel)->version = AGS_RECALL_DEFAULT_VERSION;
289   AGS_RECALL(envelope_channel)->build_id = AGS_RECALL_DEFAULT_BUILD_ID;
290   AGS_RECALL(envelope_channel)->xml_type = "ags-envelope-channel";
291 
292   /* ports */
293   port = NULL;
294 
295   /* use note length */
296   envelope_channel->use_note_length = g_object_new(AGS_TYPE_PORT,
297 						   "plugin-name", ags_envelope_channel_plugin_name,
298 						   "specifier", ags_envelope_channel_specifier[0],
299 						   "control-port", ags_envelope_channel_control_port[0],
300 						   "port-value-is-pointer", FALSE,
301 						   "port-value-type", G_TYPE_BOOLEAN,
302 						   "port-value-size", sizeof(gboolean),
303 						   "port-value-length", 1,
304 						   NULL);
305   g_object_ref(envelope_channel->use_note_length);
306 
307   envelope_channel->use_note_length->port_value.ags_port_boolean = FALSE;
308 
309   /* use fixed length */
310   envelope_channel->use_fixed_length = g_object_new(AGS_TYPE_PORT,
311 						    "plugin-name", ags_envelope_channel_plugin_name,
312 						    "specifier", ags_envelope_channel_specifier[1],
313 						    "control-port", ags_envelope_channel_control_port[1],
314 						    "port-value-is-pointer", FALSE,
315 						    "port-value-type", G_TYPE_BOOLEAN,
316 						    "port-value-size", sizeof(gboolean),
317 						    "port-value-length", 1,
318 						    NULL);
319   g_object_ref(envelope_channel->use_fixed_length);
320 
321   envelope_channel->use_fixed_length->port_value.ags_port_boolean = FALSE;
322 
323   /* fixed length */
324   envelope_channel->fixed_length = g_object_new(AGS_TYPE_PORT,
325 						"plugin-name", ags_envelope_channel_plugin_name,
326 						"specifier", ags_envelope_channel_specifier[2],
327 						"control-port", ags_envelope_channel_control_port[2],
328 						"port-value-is-pointer", FALSE,
329 						"port-value-type", G_TYPE_DOUBLE,
330 						"port-value-size", sizeof(gdouble),
331 						"port-value-length", 1,
332 						NULL);
333   g_object_ref(envelope_channel->fixed_length);
334 
335   envelope_channel->fixed_length->port_value.ags_port_double = 0.0;
336 
337   /* attack */
338   envelope_channel->attack = g_object_new(AGS_TYPE_PORT,
339 					  "plugin-name", ags_envelope_channel_plugin_name,
340 					  "specifier", ags_envelope_channel_specifier[3],
341 					  "control-port", ags_envelope_channel_control_port[3],
342 					  "port-value-is-pointer", FALSE,
343 					  "port-value-type", G_TYPE_DOUBLE,
344 					  "port-value-size", sizeof(gdouble),
345 					  "port-value-length", 1,
346 					  NULL);
347   g_object_ref(envelope_channel->attack);
348 
349   envelope_channel->attack->port_value.ags_port_double = 1.0;
350 
351   /* add to port */
352   port = g_list_prepend(port, envelope_channel->attack);
353   g_object_ref(envelope_channel->attack);
354 
355   /* decay */
356   envelope_channel->decay = g_object_new(AGS_TYPE_PORT,
357 					 "plugin-name", ags_envelope_channel_plugin_name,
358 					 "specifier", ags_envelope_channel_specifier[4],
359 					 "control-port", ags_envelope_channel_control_port[4],
360 					 "port-value-is-pointer", FALSE,
361 					 "port-value-type", G_TYPE_DOUBLE,
362 					 "port-value-size", sizeof(gdouble),
363 					 "port-value-length", 1,
364 					 NULL);
365   g_object_ref(envelope_channel->decay);
366 
367   envelope_channel->decay->port_value.ags_port_double = 1.0;
368 
369   /* add to port */
370   port = g_list_prepend(port, envelope_channel->decay);
371   g_object_ref(envelope_channel->decay);
372 
373   /* sustain */
374   envelope_channel->sustain = g_object_new(AGS_TYPE_PORT,
375 					   "plugin-name", ags_envelope_channel_plugin_name,
376 					   "specifier", ags_envelope_channel_specifier[5],
377 					   "control-port", ags_envelope_channel_control_port[5],
378 					   "port-value-is-pointer", FALSE,
379 					   "port-value-type", G_TYPE_DOUBLE,
380 					   "port-value-size", sizeof(gdouble),
381 					   "port-value-length", 1,
382 					   NULL);
383   g_object_ref(envelope_channel->sustain);
384 
385   envelope_channel->sustain->port_value.ags_port_double = 1.0;
386 
387   /* add to port */
388   port = g_list_prepend(port, envelope_channel->sustain);
389   g_object_ref(envelope_channel->sustain);
390 
391   /* release */
392   envelope_channel->release = g_object_new(AGS_TYPE_PORT,
393 					   "plugin-name", ags_envelope_channel_plugin_name,
394 					   "specifier", ags_envelope_channel_specifier[6],
395 					   "control-port", ags_envelope_channel_control_port[6],
396 					   "port-value-is-pointer", FALSE,
397 					   "port-value-type", G_TYPE_DOUBLE,
398 					   "port-value-size", sizeof(gdouble),
399 					   "port-value-length", 1,
400 					   NULL);
401   g_object_ref(envelope_channel->release);
402 
403   envelope_channel->release->port_value.ags_port_double = 1.0;
404 
405   /* add to port */
406   port = g_list_prepend(port, envelope_channel->release);
407   g_object_ref(envelope_channel->release);
408 
409   /* ratio */
410   envelope_channel->ratio = g_object_new(AGS_TYPE_PORT,
411 					 "plugin-name", ags_envelope_channel_plugin_name,
412 					 "specifier", ags_envelope_channel_specifier[7],
413 					 "control-port", ags_envelope_channel_control_port[7],
414 					 "port-value-is-pointer", FALSE,
415 					 "port-value-type", G_TYPE_DOUBLE,
416 					 "port-value-size", sizeof(gdouble),
417 					 "port-value-length", 1,
418 					 NULL);
419   g_object_ref(envelope_channel->ratio);
420 
421   envelope_channel->ratio->port_value.ags_port_double = 1.0;
422 
423   /* add to port */
424   port = g_list_prepend(port, envelope_channel->ratio);
425   g_object_ref(envelope_channel->ratio);
426 
427   /* set ports */
428   AGS_RECALL(envelope_channel)->port = port;
429 }
430 
431 void
ags_envelope_channel_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)432 ags_envelope_channel_set_property(GObject *gobject,
433 				  guint prop_id,
434 				  const GValue *value,
435 				  GParamSpec *param_spec)
436 {
437   AgsEnvelopeChannel *envelope_channel;
438 
439   GRecMutex *recall_mutex;
440 
441   envelope_channel = AGS_ENVELOPE_CHANNEL(gobject);
442 
443   /* get recall mutex */
444   recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(envelope_channel);
445 
446   switch(prop_id){
447   case PROP_USE_NOTE_LENGTH:
448     {
449       AgsPort *port;
450 
451       port = (AgsPort *) g_value_get_object(value);
452 
453       g_rec_mutex_lock(recall_mutex);
454 
455       if(port == envelope_channel->use_note_length){
456 	g_rec_mutex_unlock(recall_mutex);
457 
458 	return;
459       }
460 
461       if(envelope_channel->use_note_length != NULL){
462 	g_object_unref(G_OBJECT(envelope_channel->use_note_length));
463       }
464 
465       if(port != NULL){
466 	g_object_ref(G_OBJECT(port));
467       }
468 
469       envelope_channel->use_note_length = port;
470 
471       g_rec_mutex_unlock(recall_mutex);
472     }
473     break;
474   case PROP_USE_FIXED_LENGTH:
475     {
476       AgsPort *port;
477 
478       port = (AgsPort *) g_value_get_object(value);
479 
480       g_rec_mutex_lock(recall_mutex);
481 
482       if(port == envelope_channel->use_fixed_length){
483 	g_rec_mutex_unlock(recall_mutex);
484 
485 	return;
486       }
487 
488       if(envelope_channel->use_fixed_length != NULL){
489 	g_object_unref(G_OBJECT(envelope_channel->use_fixed_length));
490       }
491 
492       if(port != NULL){
493 	g_object_ref(G_OBJECT(port));
494       }
495 
496       envelope_channel->use_fixed_length = port;
497 
498       g_rec_mutex_unlock(recall_mutex);
499     }
500     break;
501   case PROP_FIXED_LENGTH:
502     {
503       AgsPort *port;
504 
505       port = (AgsPort *) g_value_get_object(value);
506 
507       g_rec_mutex_lock(recall_mutex);
508 
509       if(port == envelope_channel->fixed_length){
510 	g_rec_mutex_unlock(recall_mutex);
511 
512 	return;
513       }
514 
515       if(envelope_channel->fixed_length != NULL){
516 	g_object_unref(G_OBJECT(envelope_channel->fixed_length));
517       }
518 
519       if(port != NULL){
520 	g_object_ref(G_OBJECT(port));
521       }
522 
523       envelope_channel->fixed_length = port;
524 
525       g_rec_mutex_unlock(recall_mutex);
526     }
527     break;
528   case PROP_ATTACK:
529     {
530       AgsPort *port;
531 
532       port = (AgsPort *) g_value_get_object(value);
533 
534       g_rec_mutex_lock(recall_mutex);
535 
536       if(port == envelope_channel->attack){
537 	g_rec_mutex_unlock(recall_mutex);
538 
539 	return;
540       }
541 
542       if(envelope_channel->attack != NULL){
543 	g_object_unref(G_OBJECT(envelope_channel->attack));
544       }
545 
546       if(port != NULL){
547 	g_object_ref(G_OBJECT(port));
548       }
549 
550       envelope_channel->attack = port;
551 
552       g_rec_mutex_unlock(recall_mutex);
553     }
554     break;
555   case PROP_DECAY:
556     {
557       AgsPort *port;
558 
559       port = (AgsPort *) g_value_get_object(value);
560 
561       g_rec_mutex_lock(recall_mutex);
562 
563       if(port == envelope_channel->decay){
564 	g_rec_mutex_unlock(recall_mutex);
565 
566 	return;
567       }
568 
569       if(envelope_channel->decay != NULL){
570 	g_object_unref(G_OBJECT(envelope_channel->decay));
571       }
572 
573       if(port != NULL){
574 	g_object_ref(G_OBJECT(port));
575       }
576 
577       envelope_channel->decay = port;
578 
579       g_rec_mutex_unlock(recall_mutex);
580     }
581     break;
582   case PROP_SUSTAIN:
583     {
584       AgsPort *port;
585 
586       port = (AgsPort *) g_value_get_object(value);
587 
588       g_rec_mutex_lock(recall_mutex);
589 
590       if(port == envelope_channel->sustain){
591 	g_rec_mutex_unlock(recall_mutex);
592 
593 	return;
594       }
595 
596       if(envelope_channel->sustain != NULL){
597 	g_object_unref(G_OBJECT(envelope_channel->sustain));
598       }
599 
600       if(port != NULL){
601 	g_object_ref(G_OBJECT(port));
602       }
603 
604       envelope_channel->sustain = port;
605 
606       g_rec_mutex_unlock(recall_mutex);
607     }
608     break;
609   case PROP_RELEASE:
610     {
611       AgsPort *port;
612 
613       port = (AgsPort *) g_value_get_object(value);
614 
615       g_rec_mutex_lock(recall_mutex);
616 
617       if(port == envelope_channel->release){
618 	g_rec_mutex_unlock(recall_mutex);
619 
620 	return;
621       }
622 
623       if(envelope_channel->release != NULL){
624 	g_object_unref(G_OBJECT(envelope_channel->release));
625       }
626 
627       if(port != NULL){
628 	g_object_ref(G_OBJECT(port));
629       }
630 
631       envelope_channel->release = port;
632 
633       g_rec_mutex_unlock(recall_mutex);
634     }
635     break;
636   case PROP_RATIO:
637     {
638       AgsPort *port;
639 
640       port = (AgsPort *) g_value_get_object(value);
641 
642       g_rec_mutex_lock(recall_mutex);
643 
644       if(port == envelope_channel->ratio){
645 	g_rec_mutex_unlock(recall_mutex);
646 
647 	return;
648       }
649 
650       if(envelope_channel->ratio != NULL){
651 	g_object_unref(G_OBJECT(envelope_channel->ratio));
652       }
653 
654       if(port != NULL){
655 	g_object_ref(G_OBJECT(port));
656       }
657 
658       envelope_channel->ratio = port;
659 
660       g_rec_mutex_unlock(recall_mutex);
661     }
662     break;
663   default:
664     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
665     break;
666   }
667 }
668 
669 void
ags_envelope_channel_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)670 ags_envelope_channel_get_property(GObject *gobject,
671 				  guint prop_id,
672 				  GValue *value,
673 				  GParamSpec *param_spec)
674 {
675   AgsEnvelopeChannel *envelope_channel;
676 
677   GRecMutex *recall_mutex;
678 
679   envelope_channel = AGS_ENVELOPE_CHANNEL(gobject);
680 
681   /* get recall mutex */
682   recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(envelope_channel);
683 
684   switch(prop_id){
685   case PROP_USE_NOTE_LENGTH:
686     {
687       g_rec_mutex_lock(recall_mutex);
688 
689       g_value_set_object(value, envelope_channel->use_note_length);
690 
691       g_rec_mutex_unlock(recall_mutex);
692     }
693     break;
694   case PROP_USE_FIXED_LENGTH:
695     {
696       g_rec_mutex_lock(recall_mutex);
697 
698       g_value_set_object(value, envelope_channel->use_fixed_length);
699 
700       g_rec_mutex_unlock(recall_mutex);
701     }
702     break;
703   case PROP_FIXED_LENGTH:
704     {
705       g_rec_mutex_lock(recall_mutex);
706 
707       g_value_set_object(value, envelope_channel->fixed_length);
708 
709       g_rec_mutex_unlock(recall_mutex);
710     }
711     break;
712   case PROP_ATTACK:
713     {
714       g_rec_mutex_lock(recall_mutex);
715 
716       g_value_set_object(value, envelope_channel->attack);
717 
718       g_rec_mutex_unlock(recall_mutex);
719     }
720     break;
721   case PROP_DECAY:
722     {
723       g_rec_mutex_lock(recall_mutex);
724 
725       g_value_set_object(value, envelope_channel->decay);
726 
727       g_rec_mutex_unlock(recall_mutex);
728     }
729     break;
730   case PROP_SUSTAIN:
731     {
732       g_rec_mutex_lock(recall_mutex);
733 
734       g_value_set_object(value, envelope_channel->sustain);
735 
736       g_rec_mutex_unlock(recall_mutex);
737     }
738     break;
739   case PROP_RELEASE:
740     {
741       g_rec_mutex_lock(recall_mutex);
742 
743       g_value_set_object(value, envelope_channel->release);
744 
745       g_rec_mutex_unlock(recall_mutex);
746     }
747     break;
748   case PROP_RATIO:
749     {
750       g_rec_mutex_lock(recall_mutex);
751 
752       g_value_set_object(value, envelope_channel->ratio);
753 
754       g_rec_mutex_unlock(recall_mutex);
755     }
756     break;
757   default:
758     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
759     break;
760   }
761 }
762 
763 void
ags_envelope_channel_dispose(GObject * gobject)764 ags_envelope_channel_dispose(GObject *gobject)
765 {
766   AgsEnvelopeChannel *envelope_channel;
767 
768   envelope_channel = AGS_ENVELOPE_CHANNEL(gobject);
769 
770   if(envelope_channel->use_note_length != NULL){
771     g_object_unref(G_OBJECT(envelope_channel->use_note_length));
772 
773     envelope_channel->use_note_length = NULL;
774   }
775 
776   if(envelope_channel->use_fixed_length != NULL){
777     g_object_unref(G_OBJECT(envelope_channel->use_fixed_length));
778 
779     envelope_channel->use_fixed_length = NULL;
780   }
781 
782   if(envelope_channel->fixed_length != NULL){
783     g_object_unref(G_OBJECT(envelope_channel->fixed_length));
784 
785     envelope_channel->fixed_length = NULL;
786   }
787 
788   if(envelope_channel->attack != NULL){
789     g_object_unref(G_OBJECT(envelope_channel->attack));
790 
791     envelope_channel->attack = NULL;
792   }
793 
794   if(envelope_channel->decay != NULL){
795     g_object_unref(G_OBJECT(envelope_channel->decay));
796 
797     envelope_channel->decay = NULL;
798   }
799 
800   if(envelope_channel->sustain != NULL){
801     g_object_unref(G_OBJECT(envelope_channel->sustain));
802 
803     envelope_channel->sustain = NULL;
804   }
805 
806   if(envelope_channel->release != NULL){
807     g_object_unref(G_OBJECT(envelope_channel->release));
808 
809     envelope_channel->release = NULL;
810   }
811 
812   if(envelope_channel->ratio != NULL){
813     g_object_unref(G_OBJECT(envelope_channel->ratio));
814 
815     envelope_channel->ratio = NULL;
816   }
817 
818   /* call parent */
819   G_OBJECT_CLASS(ags_envelope_channel_parent_class)->dispose(gobject);
820 }
821 
822 void
ags_envelope_channel_finalize(GObject * gobject)823 ags_envelope_channel_finalize(GObject *gobject)
824 {
825   AgsEnvelopeChannel *envelope_channel;
826 
827   envelope_channel = AGS_ENVELOPE_CHANNEL(gobject);
828 
829   if(envelope_channel->use_note_length != NULL){
830     g_object_unref(G_OBJECT(envelope_channel->use_note_length));
831   }
832 
833   if(envelope_channel->use_fixed_length != NULL){
834     g_object_unref(G_OBJECT(envelope_channel->use_fixed_length));
835   }
836 
837   if(envelope_channel->fixed_length != NULL){
838     g_object_unref(G_OBJECT(envelope_channel->fixed_length));
839   }
840 
841   if(envelope_channel->attack != NULL){
842     g_object_unref(G_OBJECT(envelope_channel->attack));
843   }
844 
845   if(envelope_channel->decay != NULL){
846     g_object_unref(G_OBJECT(envelope_channel->decay));
847   }
848 
849   if(envelope_channel->sustain != NULL){
850     g_object_unref(G_OBJECT(envelope_channel->sustain));
851   }
852 
853   if(envelope_channel->release != NULL){
854     g_object_unref(G_OBJECT(envelope_channel->release));
855   }
856 
857   if(envelope_channel->ratio != NULL){
858     g_object_unref(G_OBJECT(envelope_channel->ratio));
859   }
860 
861   /* call parent */
862   G_OBJECT_CLASS(ags_envelope_channel_parent_class)->finalize(gobject);
863 }
864 
865 
866 void
ags_envelope_channel_set_ports(AgsPlugin * plugin,GList * port)867 ags_envelope_channel_set_ports(AgsPlugin *plugin, GList *port)
868 {
869   while(port != NULL){
870     if(!strncmp(AGS_PORT(port->data)->specifier,
871 		"attack[0]",
872 		9)){
873       g_object_set(G_OBJECT(plugin),
874 		   "attack", AGS_PORT(port->data),
875 		   NULL);
876     }else if(!strncmp(AGS_PORT(port->data)->specifier,
877 		"decay[0]",
878 		8)){
879       g_object_set(G_OBJECT(plugin),
880 		   "decay", AGS_PORT(port->data),
881 		   NULL);
882     }else if(!strncmp(AGS_PORT(port->data)->specifier,
883 		"sustain[0]",
884 		10)){
885       g_object_set(G_OBJECT(plugin),
886 		   "sustain", AGS_PORT(port->data),
887 		   NULL);
888     }else if(!strncmp(AGS_PORT(port->data)->specifier,
889 		"release[0]",
890 		10)){
891       g_object_set(G_OBJECT(plugin),
892 		   "release", AGS_PORT(port->data),
893 		   NULL);
894     }else if(!strncmp(AGS_PORT(port->data)->specifier,
895 		"ratio[0]",
896 		8)){
897       g_object_set(G_OBJECT(plugin),
898 		   "ratio", AGS_PORT(port->data),
899 		   NULL);
900     }
901 
902 
903     port = port->next;
904   }
905 }
906 
907 /**
908  * ags_envelope_channel_new:
909  * @source: the #AgsChannel
910  *
911  * Create a new instance of #AgsEnvelopeChannel
912  *
913  * Returns: the new #AgsEnvelopeChannel
914  *
915  * Since: 3.0.0
916  */
917 AgsEnvelopeChannel*
ags_envelope_channel_new(AgsChannel * source)918 ags_envelope_channel_new(AgsChannel *source)
919 {
920   AgsEnvelopeChannel *envelope_channel;
921 
922   envelope_channel = (AgsEnvelopeChannel *) g_object_new(AGS_TYPE_ENVELOPE_CHANNEL,
923 							 "source", source,
924 							 NULL);
925 
926   return(envelope_channel);
927 }
928