1 /* GSequencer - Advanced GTK Sequencer
2  * Copyright (C) 2005-2021 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_audio.h>
21 
22 #include <ags/audio/ags_preset.h>
23 #include <ags/audio/ags_notation.h>
24 #include <ags/audio/ags_automation.h>
25 #include <ags/audio/ags_wave.h>
26 #include <ags/audio/ags_midi.h>
27 #include <ags/audio/ags_pattern.h>
28 #include <ags/audio/ags_synth_generator.h>
29 #include <ags/audio/ags_sf2_synth_generator.h>
30 #include <ags/audio/ags_sfz_synth_generator.h>
31 #include <ags/audio/ags_output.h>
32 #include <ags/audio/ags_input.h>
33 #include <ags/audio/ags_playback_domain.h>
34 #include <ags/audio/ags_playback.h>
35 #include <ags/audio/ags_recall_container.h>
36 #include <ags/audio/ags_recall.h>
37 #include <ags/audio/ags_recall_audio.h>
38 #include <ags/audio/ags_recall_audio_run.h>
39 #include <ags/audio/ags_recall_id.h>
40 
41 #include <ags/audio/thread/ags_audio_loop.h>
42 #include <ags/audio/thread/ags_audio_thread.h>
43 #include <ags/audio/thread/ags_channel_thread.h>
44 
45 #include <ags/audio/task/ags_cancel_audio.h>
46 
47 #include <ags/audio/file/ags_audio_file_link.h>
48 #include <ags/audio/file/ags_audio_file.h>
49 
50 #include <ags/audio/midi/ags_midi_file.h>
51 
52 #include <ags/audio/recall/ags_count_beats_audio_run.h>
53 
54 #include <ags/audio/fx/ags_fx_playback_audio_processor.h>
55 #include <ags/audio/fx/ags_fx_pattern_audio_processor.h>
56 #include <ags/audio/fx/ags_fx_notation_audio_processor.h>
57 
58 #include <libxml/tree.h>
59 
60 #include <stdlib.h>
61 #include <string.h>
62 
63 #include <math.h>
64 
65 #include <ags/i18n.h>
66 
67 /**
68  * SECTION:ags_audio
69  * @short_description: A container of channels organizing them as input or output
70  * @title: AgsAudio
71  * @section_id:
72  * @include: ags/audio/ags_audio.h
73  *
74  * #AgsAudio organizes #AgsChannel objects either as input or output and
75  * is responsible of their alignment. The class can contain #AgsRecall objects
76  * in order to perform computation on all channels or in audio context.
77  * Therefor exists #AgsRecyclingContext acting as tree context.
78  *
79  * At least one #AgsRecallID is assigned to it and has one more if
80  * %AGS_AUDIO_OUTPUT_HAS_RECYCLING is set as flag.
81  *
82  * If %AGS_AUDIO_HAS_NOTATION is set as flag one #AgsNotation is allocated per audio
83  * channel.
84  */
85 
86 void ags_audio_class_init(AgsAudioClass *audio_class);
87 void ags_audio_connectable_interface_init(AgsConnectableInterface *connectable);
88 void ags_audio_init(AgsAudio *audio);
89 void ags_audio_set_property(GObject *gobject,
90 			    guint prop_id,
91 			    const GValue *value,
92 			    GParamSpec *param_spec);
93 void ags_audio_get_property(GObject *gobject,
94 			    guint prop_id,
95 			    GValue *value,
96 			    GParamSpec *param_spec);
97 void ags_audio_dispose(GObject *gobject);
98 void ags_audio_finalize(GObject *gobject);
99 
100 AgsUUID* ags_audio_get_uuid(AgsConnectable *connectable);
101 gboolean ags_audio_has_resource(AgsConnectable *connectable);
102 gboolean ags_audio_is_ready(AgsConnectable *connectable);
103 void ags_audio_add_to_registry(AgsConnectable *connectable);
104 void ags_audio_remove_from_registry(AgsConnectable *connectable);
105 xmlNode* ags_audio_list_resource(AgsConnectable *connectable);
106 xmlNode* ags_audio_xml_compose(AgsConnectable *connectable);
107 void ags_audio_xml_parse(AgsConnectable *connectable,
108 			 xmlNode *node);
109 gboolean ags_audio_is_connected(AgsConnectable *connectable);
110 void ags_audio_connect(AgsConnectable *connectable);
111 void ags_audio_disconnect(AgsConnectable *connectable);
112 
113 void ags_audio_set_ability_flags_channel(AgsChannel *start_channel, guint ability_flags);
114 void ags_audio_unset_ability_flags_channel(AgsChannel *start_channel, guint ability_flags);
115 
116 void ags_audio_set_audio_channels_grow(AgsAudio *audio,
117 				       GType channel_type,
118 				       guint audio_channels, guint audio_channels_old,
119 				       guint bank_dim_0, guint bank_dim_1, guint bank_dim_2,
120 				       gboolean add_recycling, gboolean add_pattern, gboolean add_synth_generator,
121 				       gboolean link_recycling,
122 				       gboolean set_sync_link, gboolean set_async_link);
123 
124 void ags_audio_set_audio_channels_shrink_zero(AgsAudio *audio);
125 void ags_audio_set_audio_channels_shrink(AgsAudio *audio,
126 					 guint audio_channels, guint audio_channels_old);
127 void ags_audio_set_audio_channels_shrink_notation(AgsAudio *audio,
128 						  guint audio_channels, guint audio_channels_old);
129 void ags_audio_set_audio_channels_shrink_automation(AgsAudio *audio,
130 						    guint audio_channels, guint audio_channels_old);
131 void ags_audio_set_audio_channels_shrink_wave(AgsAudio *audio,
132 					      guint audio_channels, guint audio_channels_old);
133 void ags_audio_set_audio_channels_shrink_midi(AgsAudio *audio,
134 					      guint audio_channels, guint audio_channels_old);
135 
136 void ags_audio_real_set_audio_channels(AgsAudio *audio,
137 				       guint audio_channels, guint audio_channels_old);
138 
139 void ags_audio_set_pads_grow(AgsAudio *audio,
140 			     GType channel_type,
141 			     guint pads, guint pads_old,
142 			     guint bank_dim_0, guint bank_dim_1, guint bank_dim_2,
143 			     gboolean add_recycling, gboolean add_pattern, gboolean add_synth_generator,
144 			     gboolean link_recycling,
145 			     gboolean set_sync_link, gboolean set_async_link);
146 void ags_audio_set_pads_unlink(AgsAudio *audio,
147 			       GType channel_type,
148 			       guint pads);
149 void ags_audio_set_pads_shrink_zero(AgsAudio *audio,
150 				    GType channel_type,
151 				    guint pads);
152 void ags_audio_set_pads_shrink(AgsAudio *audio,
153 			       GType channel_type,
154 			       guint pads);
155 void ags_audio_set_pads_remove_notes(AgsAudio *audio,
156 				     GType channel_type,
157 				     guint pads);
158 void ags_audio_set_pads_shrink_automation(AgsAudio *audio,
159 					  GType channel_type,
160 					  guint pads);
161 void ags_audio_set_pads_shrink_wave(AgsAudio *audio,
162 				    GType channel_type,
163 				    guint pads);
164 void ags_audio_set_pads_shrink_midi(AgsAudio *audio,
165 				    GType channel_type,
166 				    guint pads);
167 
168 void ags_audio_real_set_pads(AgsAudio *audio,
169 			     GType channel_type,
170 			     guint channels, guint channels_old);
171 
172 void ags_audio_real_set_output_soundcard(AgsAudio *audio, GObject *output_soundcard);
173 
174 void ags_audio_real_set_input_soundcard(AgsAudio *audio, GObject *input_soundcard);
175 
176 void ags_audio_real_set_output_sequencer(AgsAudio *audio, GObject *output_sequencer);
177 
178 void ags_audio_real_set_input_sequencer(AgsAudio *audio, GObject *input_sequencer);
179 
180 void ags_audio_set_samplerate_channel(AgsChannel *start_channel, guint samplerate);
181 void ags_audio_real_set_samplerate(AgsAudio *audio, guint samplerate);
182 
183 void ags_audio_set_buffer_size_channel(AgsChannel *start_channel, guint buffer_size);
184 void ags_audio_real_set_buffer_size(AgsAudio *audio, guint buffer_size);
185 
186 void ags_audio_set_format_channel(AgsChannel *start_channel, guint format);
187 void ags_audio_real_set_format(AgsAudio *audio, guint format);
188 
189 void ags_audio_real_duplicate_recall(AgsAudio *audio,
190 				     AgsRecallID *recall_id,
191 				     guint pad, guint audio_channel,
192 				     guint line);
193 void ags_audio_real_resolve_recall(AgsAudio *audio,
194 				   AgsRecallID *recall_id);
195 
196 void ags_audio_real_init_recall(AgsAudio *audio,
197 				AgsRecallID *recall_id, guint staging_flags);
198 void ags_audio_real_play_recall(AgsAudio *audio,
199 				AgsRecallID *recall_id, guint staging_flags);
200 
201 void ags_audio_real_done_recall(AgsAudio *audio,
202 				AgsRecallID *recall_id);
203 void ags_audio_real_cancel_recall(AgsAudio *audio,
204 				  AgsRecallID *recall_id);
205 
206 void ags_audio_real_cleanup_recall(AgsAudio *audio,
207 				   AgsRecallID *recall_id);
208 
209 void ags_audio_recall_done_callback(AgsRecall *recall,
210 				    AgsAudio *audio);
211 
212 GList* ags_audio_real_start(AgsAudio *audio,
213 			    gint sound_scope);
214 void ags_audio_real_stop(AgsAudio *audio,
215 			 GList *recall_id, gint sound_scope);
216 
217 GList* ags_audio_real_check_scope(AgsAudio *audio, gint sound_scope);
218 
219 void ags_audio_set_property_all(AgsAudio *audio,
220 				gint n_params,
221 				const gchar *parameter_name[], const GValue value[]);
222 void ags_audio_recursive_set_property_down(AgsChannel *channel,
223 					   gint n_params,
224 					   const gchar *parameter_name[], const GValue value[]);
225 void ags_audio_recursive_set_property_down_input(AgsChannel *channel,
226 						 gint n_params,
227 						 const gchar *parameter_name[], const GValue value[]);
228 
229 void ags_audio_real_recursive_run_stage(AgsAudio *audio,
230 					gint sound_scope, guint stage);
231 
232 enum{
233   SET_AUDIO_CHANNELS,
234   SET_PADS,
235   DUPLICATE_RECALL,
236   RESOLVE_RECALL,
237   INIT_RECALL,
238   PLAY_RECALL,
239   DONE_RECALL,
240   CANCEL_RECALL,
241   CLEANUP_RECALL,
242   START,
243   STOP,
244   CHECK_SCOPE,
245   RECURSIVE_RUN_STAGE,
246   LAST_SIGNAL,
247 };
248 
249 enum{
250   PROP_0,
251   PROP_AUDIO_NAME,
252   PROP_OUTPUT_SOUNDCARD,
253   PROP_INPUT_SOUNDCARD,
254   PROP_OUTPUT_SEQUENCER,
255   PROP_INPUT_SEQUENCER,
256   PROP_SAMPLERATE,
257   PROP_BUFFER_SIZE,
258   PROP_FORMAT,
259   PROP_BPM,
260   PROP_MIN_AUDIO_CHANNELS,
261   PROP_MAX_AUDIO_CHANNELS,
262   PROP_MIN_OUTPUT_PADS,
263   PROP_MAX_OUTPUT_PADS,
264   PROP_MIN_INPUT_PADS,
265   PROP_MAX_INPUT_PADS,
266   PROP_AUDIO_CHANNELS,
267   PROP_OUTPUT_PADS,
268   PROP_OUTPUT_LINES,
269   PROP_INPUT_PADS,
270   PROP_INPUT_LINES,
271   PROP_AUDIO_START_MAPPING,
272   PROP_AUDIO_END_MAPPING,
273   PROP_MIDI_START_MAPPING,
274   PROP_MIDI_END_MAPPING,
275   PROP_MIDI_CHANNEL,
276   PROP_NUMERATOR,
277   PROP_DENOMINATOR,
278   PROP_TIME_SIGNATURE,
279   PROP_IS_MINOR,
280   PROP_SHARP_FLATS,
281   PROP_OCTAVE,
282   PROP_KEY,
283   PROP_ABSOLUTE_KEY,
284   PROP_LOOP_START,
285   PROP_LOOP_END,
286   PROP_OFFSET,
287   PROP_OUTPUT,
288   PROP_INPUT,
289   PROP_PRESET,
290   PROP_SYNTH_GENERATOR,
291   PROP_SF2_SYNTH_GENERATOR,
292   PROP_SFZ_SYNTH_GENERATOR,
293   PROP_PLAYBACK_DOMAIN,
294   PROP_CURSOR,
295   PROP_NOTATION,
296   PROP_AUTOMATION,
297   PROP_WAVE,
298   PROP_OUTPUT_AUDIO_FILE,
299   PROP_INPUT_AUDIO_FILE,
300   PROP_MIDI,
301   PROP_OUTPUT_MIDI_FILE,
302   PROP_INPUT_MIDI_FILE,
303   PROP_RECALL_ID,
304   PROP_RECYCLING_CONTEXT,
305   PROP_RECALL_CONTAINER,
306   PROP_PLAY,
307   PROP_RECALL,
308 };
309 
310 static gpointer ags_audio_parent_class = NULL;
311 static guint audio_signals[LAST_SIGNAL];
312 
313 GType
ags_audio_get_type(void)314 ags_audio_get_type (void)
315 {
316   static volatile gsize g_define_type_id__volatile = 0;
317 
318   if(g_once_init_enter (&g_define_type_id__volatile)){
319     GType ags_type_audio = 0;
320 
321     static const GTypeInfo ags_audio_info = {
322       sizeof(AgsAudioClass),
323       NULL, /* base_init */
324       NULL, /* base_finalize */
325       (GClassInitFunc) ags_audio_class_init,
326       NULL, /* class_finalize */
327       NULL, /* class_data */
328       sizeof(AgsAudio),
329       0,    /* n_preallocs */
330       (GInstanceInitFunc) ags_audio_init,
331     };
332 
333     static const GInterfaceInfo ags_connectable_interface_info = {
334       (GInterfaceInitFunc) ags_audio_connectable_interface_init,
335       NULL, /* interface_finalize */
336       NULL, /* interface_data */
337     };
338 
339     ags_type_audio = g_type_register_static(G_TYPE_OBJECT,
340 					    "AgsAudio", &ags_audio_info,
341 					    0);
342 
343     g_type_add_interface_static(ags_type_audio,
344 				AGS_TYPE_CONNECTABLE,
345 				&ags_connectable_interface_info);
346 
347     g_once_init_leave(&g_define_type_id__volatile, ags_type_audio);
348   }
349 
350   return g_define_type_id__volatile;
351 }
352 
353 GType
ags_audio_flags_get_type()354 ags_audio_flags_get_type()
355 {
356   static volatile gsize g_flags_type_id__volatile;
357 
358   if(g_once_init_enter (&g_flags_type_id__volatile)){
359     static const GFlagsValue values[] = {
360       { AGS_AUDIO_ADDED_TO_REGISTRY, "AGS_AUDIO_ADDED_TO_REGISTRY", "audio-added-to-registry" },
361       { AGS_AUDIO_CONNECTED, "AGS_AUDIO_CONNECTED", "audio-connected" },
362       { AGS_AUDIO_NO_OUTPUT, "AGS_AUDIO_NO_OUTPUT", "audio-no-output" },
363       { AGS_AUDIO_NO_INPUT, "AGS_AUDIO_NO_INPUT", "audio-no-input" },
364       { AGS_AUDIO_SYNC, "AGS_AUDIO_SYNC", "audio-sync" },
365       { AGS_AUDIO_ASYNC, "AGS_AUDIO_ASYNC", "audio-async" },
366       { AGS_AUDIO_OUTPUT_HAS_RECYCLING, "AGS_AUDIO_OUTPUT_HAS_RECYCLING", "audio-output-has-recycling" },
367       { AGS_AUDIO_OUTPUT_HAS_SYNTH, "AGS_AUDIO_OUTPUT_HAS_SYNTH", "audio-output-has-synth" },
368       { AGS_AUDIO_INPUT_HAS_RECYCLING, "AGS_AUDIO_INPUT_HAS_RECYCLING", "audio-input-has-recycling" },
369       { AGS_AUDIO_INPUT_HAS_SYNTH, "AGS_AUDIO_INPUT_HAS_SYNTH", "audio-input-has-synth" },
370       { AGS_AUDIO_INPUT_HAS_FILE, "AGS_AUDIO_INPUT_HAS_FILE", "audio-input-has-file" },
371       { AGS_AUDIO_CAN_NEXT_ACTIVE, "AGS_AUDIO_CAN_NEXT_ACTIVE", "audio-can-next-active" },
372       { AGS_AUDIO_SKIP_OUTPUT, "AGS_AUDIO_SKIP_OUTPUT", "audio-skip-output" },
373       { AGS_AUDIO_SKIP_INPUT, "AGS_AUDIO_SKIP_INPUT", "audio-skip-input" },
374       { AGS_AUDIO_BYPASS, "AGS_AUDIO_BYPASS", "audio-bypass" },
375       { 0, NULL, NULL }
376     };
377 
378     GType g_flags_type_id = g_flags_register_static(g_intern_static_string("AgsAudioFlags"), values);
379 
380     g_once_init_leave (&g_flags_type_id__volatile, g_flags_type_id);
381   }
382 
383   return g_flags_type_id__volatile;
384 }
385 
386 void
ags_audio_class_init(AgsAudioClass * audio)387 ags_audio_class_init(AgsAudioClass *audio)
388 {
389   GObjectClass *gobject;
390   GParamSpec *param_spec;
391 
392   ags_audio_parent_class = g_type_class_peek_parent(audio);
393 
394   /* GObjectClass */
395   gobject = (GObjectClass *) audio;
396 
397   gobject->set_property = ags_audio_set_property;
398   gobject->get_property = ags_audio_get_property;
399 
400   gobject->dispose = ags_audio_dispose;
401   gobject->finalize = ags_audio_finalize;
402 
403   /* properties */
404   /**
405    * AgsAudio:audio-name:
406    *
407    * The name of audio object.
408    *
409    * Since: 3.0.0
410    */
411   param_spec = g_param_spec_string("audio-name",
412 				   i18n_pspec("assigned name"),
413 				   i18n_pspec("The name of audio"),
414 				   NULL,
415 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
416   g_object_class_install_property(gobject,
417 				  PROP_AUDIO_NAME,
418 				  param_spec);
419 
420   /**
421    * AgsAudio:output-soundcard:
422    *
423    * The assigned #AgsSoundcard acting as default sink.
424    *
425    * Since: 3.0.0
426    */
427   param_spec = g_param_spec_object("output-soundcard",
428 				   i18n_pspec("assigned output soundcard"),
429 				   i18n_pspec("The output soundcard it is assigned with"),
430 				   G_TYPE_OBJECT,
431 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
432   g_object_class_install_property(gobject,
433 				  PROP_OUTPUT_SOUNDCARD,
434 				  param_spec);
435 
436   /**
437    * AgsAudio:input-soundcard:
438    *
439    * The assigned #AgsSoundcard acting as default source.
440    *
441    * Since: 3.0.0
442    */
443   param_spec = g_param_spec_object("input-soundcard",
444 				   i18n_pspec("assigned input soundcard"),
445 				   i18n_pspec("The input soundcard it is assigned with"),
446 				   G_TYPE_OBJECT,
447 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
448   g_object_class_install_property(gobject,
449 				  PROP_INPUT_SOUNDCARD,
450 				  param_spec);
451 
452   /**
453    * AgsAudio:output-sequencer:
454    *
455    * The assigned #AgsSequencer acting as default source.
456    *
457    * Since: 3.0.0
458    */
459   param_spec = g_param_spec_object("output-sequencer",
460 				   i18n_pspec("assigned output sequencer"),
461 				   i18n_pspec("The output sequencer it is assigned with"),
462 				   G_TYPE_OBJECT,
463 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
464   g_object_class_install_property(gobject,
465 				  PROP_OUTPUT_SEQUENCER,
466 				  param_spec);
467 
468   /**
469    * AgsAudio:input-sequencer:
470    *
471    * The assigned #AgsSequencer acting as default source.
472    *
473    * Since: 3.0.0
474    */
475   param_spec = g_param_spec_object("input-sequencer",
476 				   i18n_pspec("assigned input sequencer"),
477 				   i18n_pspec("The input sequencer it is assigned with"),
478 				   G_TYPE_OBJECT,
479 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
480   g_object_class_install_property(gobject,
481 				  PROP_INPUT_SEQUENCER,
482 				  param_spec);
483 
484   /**
485    * AgsAudio:samplerate:
486    *
487    * The samplerate.
488    *
489    * Since: 3.0.0
490    */
491   param_spec = g_param_spec_uint("samplerate",
492 				 i18n_pspec("samplerate"),
493 				 i18n_pspec("The samplerate"),
494 				 0,
495 				 G_MAXUINT32,
496 				 AGS_SOUNDCARD_DEFAULT_SAMPLERATE,
497 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
498   g_object_class_install_property(gobject,
499 				  PROP_SAMPLERATE,
500 				  param_spec);
501 
502   /**
503    * AgsAudio:buffer-size:
504    *
505    * The buffer length.
506    *
507    * Since: 3.0.0
508    */
509   param_spec = g_param_spec_uint("buffer-size",
510 				 i18n_pspec("buffer size"),
511 				 i18n_pspec("The buffer size"),
512 				 0,
513 				 G_MAXUINT32,
514 				 AGS_SOUNDCARD_DEFAULT_BUFFER_SIZE,
515 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
516   g_object_class_install_property(gobject,
517 				  PROP_BUFFER_SIZE,
518 				  param_spec);
519 
520   /**
521    * AgsAudio:format:
522    *
523    * The format.
524    *
525    * Since: 3.0.0
526    */
527   param_spec = g_param_spec_uint("format",
528 				 i18n_pspec("format"),
529 				 i18n_pspec("The format"),
530 				 0,
531 				 G_MAXUINT32,
532 				 AGS_SOUNDCARD_DEFAULT_FORMAT,
533 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
534   g_object_class_install_property(gobject,
535 				  PROP_FORMAT,
536 				  param_spec);
537 
538   /**
539    * AgsAudio:bpm:
540    *
541    * The bpm.
542    *
543    * Since: 3.0.0
544    */
545   param_spec = g_param_spec_double("bpm",
546 				   i18n_pspec("bpm"),
547 				   i18n_pspec("The bpm"),
548 				   0.0,
549 				   G_MAXDOUBLE,
550 				   AGS_SOUNDCARD_DEFAULT_BPM,
551 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
552   g_object_class_install_property(gobject,
553 				  PROP_BPM,
554 				  param_spec);
555 
556   /**
557    * AgsAudio:min-audio-channels:
558    *
559    * The minimum audio channels count.
560    *
561    * Since: 3.0.0
562    */
563   param_spec = g_param_spec_uint("min-audio-channels",
564 				 i18n_pspec("minimum audio channels count"),
565 				 i18n_pspec("The minimum count of audio channels of audio"),
566 				 0,
567 				 G_MAXUINT32,
568 				 0,
569 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
570   g_object_class_install_property(gobject,
571 				  PROP_MIN_AUDIO_CHANNELS,
572 				  param_spec);
573 
574   /**
575    * AgsAudio:max-audio-channels:
576    *
577    * The maximum audio channels count.
578    *
579    * Since: 3.0.0
580    */
581   param_spec = g_param_spec_uint("max-audio-channels",
582 				 i18n_pspec("maximum audio channels count"),
583 				 i18n_pspec("The maximum count of audio channels of audio"),
584 				 0,
585 				 G_MAXUINT32,
586 				 0,
587 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
588   g_object_class_install_property(gobject,
589 				  PROP_MAX_AUDIO_CHANNELS,
590 				  param_spec);
591 
592   /**
593    * AgsAudio:min-output-pads:
594    *
595    * The minimum output pads count.
596    *
597    * Since: 3.0.0
598    */
599   param_spec = g_param_spec_uint("min-output-pads",
600 				 i18n_pspec("minimum output pads count"),
601 				 i18n_pspec("The minimum count of output pads of audio"),
602 				 0,
603 				 G_MAXUINT32,
604 				 0,
605 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
606   g_object_class_install_property(gobject,
607 				  PROP_MIN_OUTPUT_PADS,
608 				  param_spec);
609 
610   /**
611    * AgsAudio:max-output-pads:
612    *
613    * The maximum output pads count.
614    *
615    * Since: 3.0.0
616    */
617   param_spec = g_param_spec_uint("max-output-pads",
618 				 i18n_pspec("maximum output pads count"),
619 				 i18n_pspec("The maximum count of output pads of audio"),
620 				 0,
621 				 G_MAXUINT32,
622 				 0,
623 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
624   g_object_class_install_property(gobject,
625 				  PROP_MAX_OUTPUT_PADS,
626 				  param_spec);
627 
628   /**
629    * AgsAudio:min-input-pads:
630    *
631    * The minimum input pads count.
632    *
633    * Since: 3.0.0
634    */
635   param_spec = g_param_spec_uint("min-input-pads",
636 				 i18n_pspec("minimum input pads count"),
637 				 i18n_pspec("The minimum count of input pads of audio"),
638 				 0,
639 				 G_MAXUINT32,
640 				 0,
641 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
642   g_object_class_install_property(gobject,
643 				  PROP_MIN_INPUT_PADS,
644 				  param_spec);
645 
646   /**
647    * AgsAudio:max-input-pads:
648    *
649    * The maximum input pads count.
650    *
651    * Since: 3.0.0
652    */
653   param_spec = g_param_spec_uint("max-input-pads",
654 				 i18n_pspec("maximum input pads count"),
655 				 i18n_pspec("The maximum count of input pads of audio"),
656 				 0,
657 				 G_MAXUINT32,
658 				 0,
659 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
660   g_object_class_install_property(gobject,
661 				  PROP_MAX_INPUT_PADS,
662 				  param_spec);
663 
664   /**
665    * AgsAudio:audio-channels:
666    *
667    * The audio channels count.
668    *
669    * Since: 3.0.0
670    */
671   param_spec = g_param_spec_uint("audio-channels",
672 				 i18n_pspec("audio channels count"),
673 				 i18n_pspec("The count of audio channels of audio"),
674 				 0,
675 				 G_MAXUINT32,
676 				 0,
677 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
678   g_object_class_install_property(gobject,
679 				  PROP_AUDIO_CHANNELS,
680 				  param_spec);
681 
682   /**
683    * AgsAudio:output-pads:
684    *
685    * The output pads count.
686    *
687    * Since: 3.0.0
688    */
689   param_spec = g_param_spec_uint("output-pads",
690 				 i18n_pspec("output pads count"),
691 				 i18n_pspec("The count of output pads of audio"),
692 				 0,
693 				 G_MAXUINT32,
694 				 0,
695 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
696   g_object_class_install_property(gobject,
697 				  PROP_OUTPUT_PADS,
698 				  param_spec);
699 
700   /**
701    * AgsAudio:output-lines:
702    *
703    * The output lines count.
704    *
705    * Since: 3.0.0
706    */
707   param_spec = g_param_spec_uint("output-lines",
708 				 i18n_pspec("output lines count"),
709 				 i18n_pspec("The count of output lines of audio"),
710 				 0,
711 				 G_MAXUINT32,
712 				 0,
713 				 G_PARAM_READABLE);
714   g_object_class_install_property(gobject,
715 				  PROP_OUTPUT_LINES,
716 				  param_spec);
717 
718   /**
719    * AgsAudio:input-pads:
720    *
721    * The input pads count.
722    *
723    * Since: 3.0.0
724    */
725   param_spec = g_param_spec_uint("input-pads",
726 				 i18n_pspec("input pads count"),
727 				 i18n_pspec("The count of input pads of audio"),
728 				 0,
729 				 G_MAXUINT32,
730 				 0,
731 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
732   g_object_class_install_property(gobject,
733 				  PROP_INPUT_PADS,
734 				  param_spec);
735 
736   /**
737    * AgsAudio:input-lines:
738    *
739    * The input lines count.
740    *
741    * Since: 3.0.0
742    */
743   param_spec = g_param_spec_uint("input-lines",
744 				 i18n_pspec("input lines count"),
745 				 i18n_pspec("The count of input lines of audio"),
746 				 0,
747 				 G_MAXUINT32,
748 				 0,
749 				 G_PARAM_READABLE);
750   g_object_class_install_property(gobject,
751 				  PROP_INPUT_LINES,
752 				  param_spec);
753 
754   /**
755    * AgsAudio:audio-start-mapping:
756    *
757    * The audio start mapping.
758    *
759    * Since: 3.0.0
760    */
761   param_spec = g_param_spec_uint("audio-start-mapping",
762 				 i18n_pspec("audio start mapping"),
763 				 i18n_pspec("The audio start mapping"),
764 				 0,
765 				 G_MAXUINT32,
766 				 0,
767 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
768   g_object_class_install_property(gobject,
769 				  PROP_AUDIO_START_MAPPING,
770 				  param_spec);
771 
772   /**
773    * AgsAudio:audio-end-mapping:
774    *
775    * The audio end mapping.
776    *
777    * Since: 3.0.0
778    */
779   param_spec = g_param_spec_uint("audio-end-mapping",
780 				 i18n_pspec("audio end mapping"),
781 				 i18n_pspec("The audio end mapping"),
782 				 0,
783 				 G_MAXUINT32,
784 				 0,
785 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
786   g_object_class_install_property(gobject,
787 				  PROP_AUDIO_END_MAPPING,
788 				  param_spec);
789 
790   /**
791    * AgsAudio:midi-start-mapping:
792    *
793    * The midi start mapping.
794    *
795    * Since: 3.0.0
796    */
797   param_spec =  g_param_spec_uint("midi-start-mapping",
798 				  i18n_pspec("midi start mapping range"),
799 				  i18n_pspec("The midi mapping range's start"),
800 				  0,
801 				  G_MAXUINT32,
802 				  0,
803 				  G_PARAM_READABLE | G_PARAM_WRITABLE);
804   g_object_class_install_property(gobject,
805 				  PROP_MIDI_START_MAPPING,
806 				  param_spec);
807 
808   /**
809    * AgsAudio:midi-end-mapping:
810    *
811    * The midi end mapping.
812    *
813    * Since: 3.0.0
814    */
815   param_spec = g_param_spec_uint("midi-end-mapping",
816 				 i18n_pspec("midi end mapping range"),
817 				 i18n_pspec("The midi mapping range's start"),
818 				 0,
819 				 G_MAXUINT32,
820 				 0,
821 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
822   g_object_class_install_property(gobject,
823 				  PROP_MIDI_END_MAPPING,
824 				  param_spec);
825 
826   /**
827    * AgsAudio:midi-channel:
828    *
829    * The midi channel.
830    *
831    * Since: 3.0.0
832    */
833   param_spec = g_param_spec_uint("midi-channel",
834 				 i18n_pspec("midi channel"),
835 				 i18n_pspec("The midi channel"),
836 				 0,
837 				 16,
838 				 0,
839 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
840   g_object_class_install_property(gobject,
841 				  PROP_MIDI_CHANNEL,
842 				  param_spec);
843 
844   /**
845    * AgsAudio:numerator:
846    *
847    * The numerator of time signature.
848    *
849    * Since: 3.0.0
850    */
851   param_spec = g_param_spec_uint("numerator",
852 				 i18n_pspec("numerator"),
853 				 i18n_pspec("The numerator"),
854 				 0,
855 				 32,
856 				 4,
857 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
858   g_object_class_install_property(gobject,
859 				  PROP_NUMERATOR,
860 				  param_spec);
861 
862   /**
863    * AgsAudio:denominator:
864    *
865    * The denominator of time signature.
866    *
867    * Since: 3.0.0
868    */
869   param_spec = g_param_spec_uint("denominator",
870 				 i18n_pspec("denominator"),
871 				 i18n_pspec("The denominator"),
872 				 0,
873 				 32,
874 				 4,
875 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
876   g_object_class_install_property(gobject,
877 				  PROP_DENOMINATOR,
878 				  param_spec);
879 
880   /**
881    * AgsAudio:time-signature:
882    *
883    * The time signature.
884    *
885    * Since: 3.0.0
886    */
887   param_spec = g_param_spec_string("time-signature",
888 				   i18n_pspec("time signature"),
889 				   i18n_pspec("The time signature"),
890 				   "4/4",
891 				   G_PARAM_READABLE);
892   g_object_class_install_property(gobject,
893 				  PROP_TIME_SIGNATURE,
894 				  param_spec);
895 
896   /**
897    * AgsAudio:is-minor:
898    *
899    * Is minor.
900    *
901    * Since: 3.0.0
902    */
903   param_spec = g_param_spec_boolean("is-minor",
904 				    i18n_pspec("is minor"),
905 				    i18n_pspec("Is minor"),
906 				    FALSE,
907 				    G_PARAM_READABLE | G_PARAM_WRITABLE);
908   g_object_class_install_property(gobject,
909 				  PROP_IS_MINOR,
910 				  param_spec);
911 
912   /**
913    * AgsAudio:sharp-flats:
914    *
915    * The sharp/flats count.
916    *
917    * Since: 3.0.0
918    */
919   param_spec = g_param_spec_uint("sharp-flats",
920 				 i18n_pspec("sharp/flats"),
921 				 i18n_pspec("The sharp/flats count"),
922 				 0,
923 				 12,
924 				 0,
925 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
926   g_object_class_install_property(gobject,
927 				  PROP_SHARP_FLATS,
928 				  param_spec);
929 
930   /**
931    * AgsAudio:octave:
932    *
933    * The octave lower.
934    *
935    * Since: 3.0.0
936    */
937   param_spec = g_param_spec_int("octave",
938 				i18n_pspec("octave"),
939 				i18n_pspec("The octave lower"),
940 				0,
941 				10,
942 				0,
943 				G_PARAM_READABLE | G_PARAM_WRITABLE);
944   g_object_class_install_property(gobject,
945 				  PROP_OCTAVE,
946 				  param_spec);
947 
948   /**
949    * AgsAudio:key:
950    *
951    * The key relative to octave.
952    *
953    * Since: 3.0.0
954    */
955   param_spec = g_param_spec_uint("key",
956 				 i18n_pspec("relative key"),
957 				 i18n_pspec("The key relative to octave"),
958 				 0,
959 				 12,
960 				 0,
961 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
962   g_object_class_install_property(gobject,
963 				  PROP_KEY,
964 				  param_spec);
965 
966   /**
967    * AgsAudio:absolute-key:
968    *
969    * The absolute key lower.
970    *
971    * Since: 3.0.0
972    */
973   param_spec = g_param_spec_int("absolute-key",
974 				i18n_pspec("absolute key"),
975 				i18n_pspec("The absolute key lower"),
976 				0,
977 				128,
978 				0,
979 				G_PARAM_READABLE | G_PARAM_WRITABLE);
980   g_object_class_install_property(gobject,
981 				  PROP_ABSOLUTE_KEY,
982 				  param_spec);
983 
984 
985   /**
986    * AgsAudio:loop-start:
987    *
988    * The audio's loop start.
989    *
990    * Since: 3.0.0
991    */
992   param_spec =  g_param_spec_uint64("loop-start",
993 				    i18n_pspec("loop start of audio"),
994 				    i18n_pspec("The loop start of audio"),
995 				    0.0,
996 				    G_MAXUINT64,
997 				    0.0,
998 				    G_PARAM_READABLE | G_PARAM_WRITABLE);
999   g_object_class_install_property(gobject,
1000 				  PROP_LOOP_START,
1001 				  param_spec);
1002 
1003   /**
1004    * AgsAudio:loop-end:
1005    *
1006    * The audio's loop end.
1007    *
1008    * Since: 3.0.0
1009    */
1010   param_spec =  g_param_spec_uint64("loop-end",
1011 				    i18n_pspec("loop end of audio"),
1012 				    i18n_pspec("The loop end of audio"),
1013 				    0.0,
1014 				    G_MAXUINT64,
1015 				    0.0,
1016 				    G_PARAM_READABLE | G_PARAM_WRITABLE);
1017   g_object_class_install_property(gobject,
1018 				  PROP_LOOP_END,
1019 				  param_spec);
1020 
1021   /**
1022    * AgsAudio:offset:
1023    *
1024    * The audio's offset.
1025    *
1026    * Since: 3.0.0
1027    */
1028   param_spec =  g_param_spec_uint64("offset",
1029 				    i18n_pspec("offset of audio"),
1030 				    i18n_pspec("The offset of audio"),
1031 				    0.0,
1032 				    G_MAXUINT64,
1033 				    0.0,
1034 				    G_PARAM_READABLE | G_PARAM_WRITABLE);
1035   g_object_class_install_property(gobject,
1036 				  PROP_OFFSET,
1037 				  param_spec);
1038 
1039   /**
1040    * AgsAudio:output:
1041    *
1042    * The #AgsOutput it contains.
1043    *
1044    * Since: 3.0.0
1045    */
1046   param_spec = g_param_spec_object("output",
1047 				   i18n_pspec("containing output"),
1048 				   i18n_pspec("The output it contains"),
1049 				   AGS_TYPE_OUTPUT,
1050 				   G_PARAM_READABLE);
1051   g_object_class_install_property(gobject,
1052 				  PROP_OUTPUT,
1053 				  param_spec);
1054 
1055   /**
1056    * AgsAudio:input:
1057    *
1058    * The #AgsInput it contains.
1059    *
1060    * Since: 3.0.0
1061    */
1062   param_spec = g_param_spec_object("input",
1063 				   i18n_pspec("containing input"),
1064 				   i18n_pspec("The input it contains"),
1065 				   AGS_TYPE_INPUT,
1066 				   G_PARAM_READABLE);
1067   g_object_class_install_property(gobject,
1068 				  PROP_INPUT,
1069 				  param_spec);
1070 
1071   /**
1072    * AgsAudio:preset: (type GList(AgsPreset)) (transfer full)
1073    *
1074    * The assigned #GList-struct containing #AgsPreset information.
1075    *
1076    * Since: 3.0.0
1077    */
1078   param_spec = g_param_spec_pointer("preset",
1079 				    i18n_pspec("preset"),
1080 				    i18n_pspec("The preset"),
1081 				    G_PARAM_READABLE | G_PARAM_WRITABLE);
1082   g_object_class_install_property(gobject,
1083 				  PROP_PRESET,
1084 				  param_spec);
1085 
1086   /**
1087    * AgsAudio:synth-generator: (type GList(AgsSynthGenerator)) (transfer full)
1088    *
1089    * The assigned #GList-struct containing #AgsSynthGenerator information.
1090    *
1091    * Since: 3.0.0
1092    */
1093   param_spec = g_param_spec_pointer("synth-generator",
1094 				    i18n_pspec("synth generator"),
1095 				    i18n_pspec("The synth generator"),
1096 				    G_PARAM_READABLE | G_PARAM_WRITABLE);
1097   g_object_class_install_property(gobject,
1098 				  PROP_SYNTH_GENERATOR,
1099 				  param_spec);
1100 
1101   /**
1102    * AgsAudio:sf2-synth-generator: (type GList(AgsSF2SynthGenerator)) (transfer full)
1103    *
1104    * The assigned #GList-struct containing #AgsSF2SynthGenerator information.
1105    *
1106    * Since: 3.4.0
1107    */
1108   param_spec = g_param_spec_pointer("sf2-synth-generator",
1109 				    i18n_pspec("SF2 synth generator"),
1110 				    i18n_pspec("The SF2 synth generator"),
1111 				    G_PARAM_READABLE | G_PARAM_WRITABLE);
1112   g_object_class_install_property(gobject,
1113 				  PROP_SF2_SYNTH_GENERATOR,
1114 				  param_spec);
1115 
1116   /**
1117    * AgsAudio:sfz-synth-generator: (type GList(AgsSFZSynthGenerator)) (transfer full)
1118    *
1119    * The assigned #GList-struct containing #AgsSFZSynthGenerator information.
1120    *
1121    * Since: 3.4.0
1122    */
1123   param_spec = g_param_spec_pointer("sfz-synth-generator",
1124 				    i18n_pspec("SFZ synth generator"),
1125 				    i18n_pspec("The SFZ synth generator"),
1126 				    G_PARAM_READABLE | G_PARAM_WRITABLE);
1127   g_object_class_install_property(gobject,
1128 				  PROP_SFZ_SYNTH_GENERATOR,
1129 				  param_spec);
1130 
1131   /**
1132    * AgsAudio:playback-domain:
1133    *
1134    * The assigned #AgsPlaybackDomain.
1135    *
1136    * Since: 3.0.0
1137    */
1138   param_spec = g_param_spec_object("playback-domain",
1139 				   i18n_pspec("assigned playback domain"),
1140 				   i18n_pspec("The assigned playback domain"),
1141 				   AGS_TYPE_PLAYBACK_DOMAIN,
1142 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
1143   g_object_class_install_property(gobject,
1144 				  PROP_PLAYBACK_DOMAIN,
1145 				  param_spec);
1146 
1147   /**
1148    * AgsAudio:cursor: (type GList(GObject)) (transfer full)
1149    *
1150    * The #GObject implementing #AgsCursor interface.
1151    *
1152    * Since: 3.0.0
1153    */
1154   param_spec = g_param_spec_pointer("cursor",
1155 				    i18n_pspec("cursor"),
1156 				    i18n_pspec("The cursor object"),
1157 				    G_PARAM_READABLE | G_PARAM_WRITABLE);
1158   g_object_class_install_property(gobject,
1159 				  PROP_CURSOR,
1160 				  param_spec);
1161 
1162   /**
1163    * AgsAudio:notation: (type GList(AgsNotation)) (transfer full)
1164    *
1165    * The #AgsNotation it contains.
1166    *
1167    * Since: 3.0.0
1168    */
1169   param_spec = g_param_spec_pointer("notation",
1170 				    i18n_pspec("containing notation"),
1171 				    i18n_pspec("The notation it contains"),
1172 				    G_PARAM_READABLE | G_PARAM_WRITABLE);
1173   g_object_class_install_property(gobject,
1174 				  PROP_NOTATION,
1175 				  param_spec);
1176 
1177   /**
1178    * AgsAudio:automation: (type GList(AgsAutomation)) (transfer full)
1179    *
1180    * The #AgsAutomation it contains.
1181    *
1182    * Since: 3.0.0
1183    */
1184   param_spec = g_param_spec_pointer("automation",
1185 				    i18n_pspec("containing automation"),
1186 				    i18n_pspec("The automation it contains"),
1187 				    G_PARAM_READABLE | G_PARAM_WRITABLE);
1188   g_object_class_install_property(gobject,
1189 				  PROP_AUTOMATION,
1190 				  param_spec);
1191 
1192   /**
1193    * AgsAudio:wave: (type GList(AgsWave)) (transfer full)
1194    *
1195    * The #AgsWave it contains.
1196    *
1197    * Since: 3.0.0
1198    */
1199   param_spec = g_param_spec_pointer("wave",
1200 				    i18n_pspec("containing wave"),
1201 				    i18n_pspec("The wave it contains"),
1202 				    G_PARAM_READABLE | G_PARAM_WRITABLE);
1203   g_object_class_install_property(gobject,
1204 				  PROP_WAVE,
1205 				  param_spec);
1206 
1207   /**
1208    * AgsAudio:output-audio-file:
1209    *
1210    * The assigned #AgsAudioFile acting as default sink.
1211    *
1212    * Since: 3.0.0
1213    */
1214   param_spec = g_param_spec_object("output-audio-file",
1215 				   i18n_pspec("assigned output audio file"),
1216 				   i18n_pspec("The output audio file it is assigned with"),
1217 				   G_TYPE_OBJECT,
1218 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
1219   g_object_class_install_property(gobject,
1220 				  PROP_OUTPUT_AUDIO_FILE,
1221 				  param_spec);
1222 
1223   /**
1224    * AgsAudio:input-audio-file:
1225    *
1226    * The assigned #AgsAudioFile acting as default sink.
1227    *
1228    * Since: 3.0.0
1229    */
1230   param_spec = g_param_spec_object("input-audio-file",
1231 				   i18n_pspec("assigned input audio file"),
1232 				   i18n_pspec("The input audio file it is assigned with"),
1233 				   G_TYPE_OBJECT,
1234 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
1235   g_object_class_install_property(gobject,
1236 				  PROP_INPUT_AUDIO_FILE,
1237 				  param_spec);
1238 
1239   /**
1240    * AgsAudio:midi: (type GList(AgsMidi)) (transfer full)
1241    *
1242    * The #AgsMidi it contains.
1243    *
1244    * Since: 3.0.0
1245    */
1246   param_spec = g_param_spec_pointer("midi",
1247 				    i18n_pspec("containing midi"),
1248 				    i18n_pspec("The midi it contains"),
1249 				    G_PARAM_READABLE | G_PARAM_WRITABLE);
1250   g_object_class_install_property(gobject,
1251 				  PROP_MIDI,
1252 				  param_spec);
1253 
1254   /**
1255    * AgsAudio:output-midi-file:
1256    *
1257    * The assigned #AgsMidiFile acting as default sink.
1258    *
1259    * Since: 3.0.0
1260    */
1261   param_spec = g_param_spec_object("output-midi-file",
1262 				   i18n_pspec("assigned output midi file"),
1263 				   i18n_pspec("The output midi file it is assigned with"),
1264 				   G_TYPE_OBJECT,
1265 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
1266   g_object_class_install_property(gobject,
1267 				  PROP_OUTPUT_MIDI_FILE,
1268 				  param_spec);
1269 
1270   /**
1271    * AgsAudio:input-midi-file:
1272    *
1273    * The assigned #AgsMidiFile acting as default sink.
1274    *
1275    * Since: 3.0.0
1276    */
1277   param_spec = g_param_spec_object("input-midi-file",
1278 				   i18n_pspec("assigned input midi file"),
1279 				   i18n_pspec("The input midi file it is assigned with"),
1280 				   G_TYPE_OBJECT,
1281 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
1282   g_object_class_install_property(gobject,
1283 				  PROP_INPUT_MIDI_FILE,
1284 				  param_spec);
1285 
1286   /**
1287    * AgsAudio:recall-id: (type GList(AgsRecallID)) (transfer full)
1288    *
1289    * The assigned #AgsRecallID.
1290    *
1291    * Since: 3.0.0
1292    */
1293   param_spec = g_param_spec_pointer("recall-id",
1294 				    i18n_pspec("assigned recall id"),
1295 				    i18n_pspec("The assigned recall id"),
1296 				    G_PARAM_READABLE | G_PARAM_WRITABLE);
1297   g_object_class_install_property(gobject,
1298 				  PROP_RECALL_ID,
1299 				  param_spec);
1300 
1301   /**
1302    * AgsAudio:recycling-context: (type GList(AgsRecyclingContext)) (transfer full)
1303    *
1304    * The assigned #AgsRecyclingContext.
1305    *
1306    * Since: 3.0.0
1307    */
1308   param_spec = g_param_spec_pointer("recycling-context",
1309 				    i18n_pspec("assigned recycling context"),
1310 				    i18n_pspec("The assigned recall id"),
1311 				    G_PARAM_READABLE | G_PARAM_WRITABLE);
1312   g_object_class_install_property(gobject,
1313 				  PROP_RECYCLING_CONTEXT,
1314 				  param_spec);
1315 
1316   /**
1317    * AgsAudio:recall-container: (type GList(AgsRecallContainer)) (transfer full)
1318    *
1319    * The #AgsRecallContainer it contains in container-context.
1320    *
1321    * Since: 3.0.0
1322    */
1323   param_spec = g_param_spec_pointer("recall-container",
1324 				    i18n_pspec("containing recall container"),
1325 				    i18n_pspec("The recall container it contains"),
1326 				    G_PARAM_READABLE | G_PARAM_WRITABLE);
1327   g_object_class_install_property(gobject,
1328 				  PROP_RECALL_CONTAINER,
1329 				  param_spec);
1330 
1331   /**
1332    * AgsAudio:play: (type GList(AgsRecall)) (transfer full)
1333    *
1334    * The #AgsRecall it contains in play-context.
1335    *
1336    * Since: 3.0.0
1337    */
1338   param_spec = g_param_spec_pointer("play",
1339 				    i18n_pspec("containing play"),
1340 				    i18n_pspec("The play it contains"),
1341 				    G_PARAM_READABLE | G_PARAM_WRITABLE);
1342   g_object_class_install_property(gobject,
1343 				  PROP_PLAY,
1344 				  param_spec);
1345 
1346   /**
1347    * AgsAudio:recall: (type GList(AgsRecall)) (transfer full)
1348    *
1349    * The #AgsRecall it contains in recall-context.
1350    *
1351    * Since: 3.0.0
1352    */
1353   param_spec = g_param_spec_pointer("recall",
1354 				    i18n_pspec("containing recall"),
1355 				    i18n_pspec("The recall it contains"),
1356 				    G_PARAM_READABLE | G_PARAM_WRITABLE);
1357   g_object_class_install_property(gobject,
1358 				  PROP_RECALL,
1359 				  param_spec);
1360 
1361 
1362   /* AgsAudioClass */
1363   audio->set_audio_channels = ags_audio_real_set_audio_channels;
1364   audio->set_pads = ags_audio_real_set_pads;
1365 
1366   audio->duplicate_recall = ags_audio_real_duplicate_recall;
1367   audio->resolve_recall = ags_audio_real_resolve_recall;
1368 
1369   audio->init_recall = ags_audio_real_init_recall;
1370   audio->play_recall = ags_audio_real_play_recall;
1371 
1372   audio->done_recall = ags_audio_real_done_recall;
1373   audio->cancel_recall = ags_audio_real_cancel_recall;
1374 
1375   audio->cleanup_recall = ags_audio_real_cleanup_recall;
1376 
1377   audio->start = ags_audio_real_start;
1378   audio->stop = ags_audio_real_stop;
1379 
1380   audio->check_scope = ags_audio_real_check_scope;
1381   audio->recursive_run_stage = ags_audio_real_recursive_run_stage;
1382 
1383   /* signals */
1384   /**
1385    * AgsAudio::set-audio-channels:
1386    * @audio: the object to adjust the channels.
1387    * @audio_channels_new: new audio channel count
1388    * @audio_channels_old: old audio channel count
1389    *
1390    * The ::set-audio-channels signal notifies about changes in channel
1391    * alignment.
1392    *
1393    * Since: 3.0.0
1394    */
1395   audio_signals[SET_AUDIO_CHANNELS] =
1396     g_signal_new("set-audio-channels",
1397 		 G_TYPE_FROM_CLASS(audio),
1398 		 G_SIGNAL_RUN_LAST,
1399 		 G_STRUCT_OFFSET(AgsAudioClass, set_audio_channels),
1400 		 NULL, NULL,
1401 		 ags_cclosure_marshal_VOID__UINT_UINT,
1402 		 G_TYPE_NONE, 2,
1403 		 G_TYPE_UINT, G_TYPE_UINT);
1404 
1405   /**
1406    * AgsAudio::set-pads:
1407    * @audio: the object to adjust pads.
1408    * @channel_type: either #AGS_TYPE_INPUT or #AGS_TYPE_OUTPUT
1409    * @pads_new: new pad count
1410    * @pads_old: old pad count
1411    *
1412    * The ::set-pads signal notifies about changes in channel
1413    * alignment.
1414    *
1415    * Since: 3.0.0
1416    */
1417   audio_signals[SET_PADS] =
1418     g_signal_new("set-pads",
1419 		 G_TYPE_FROM_CLASS(audio),
1420 		 G_SIGNAL_RUN_LAST,
1421 		 G_STRUCT_OFFSET(AgsAudioClass, set_pads),
1422 		 NULL, NULL,
1423 		 ags_cclosure_marshal_VOID__ULONG_UINT_UINT,
1424 		 G_TYPE_NONE, 3,
1425 		 G_TYPE_ULONG,
1426 		 G_TYPE_UINT, G_TYPE_UINT);
1427 
1428   /**
1429    * AgsAudio::duplicate-recall:
1430    * @audio: the #AgsAudio
1431    * @recall_id: the #AgsRecallID
1432    * @pad: the pad
1433    * @audio_channel: the audio channel
1434    * @line: the line
1435    *
1436    * The ::duplicate-recall signal notifies about duplicated recalls.
1437    *
1438    * Since: 3.0.0
1439    */
1440   audio_signals[DUPLICATE_RECALL] =
1441     g_signal_new("duplicate-recall",
1442 		 G_TYPE_FROM_CLASS(audio),
1443 		 G_SIGNAL_RUN_LAST,
1444 		 G_STRUCT_OFFSET(AgsAudioClass, duplicate_recall),
1445 		 NULL, NULL,
1446 		 ags_cclosure_marshal_VOID__OBJECT_UINT_UINT_UINT,
1447 		 G_TYPE_NONE, 4,
1448 		 G_TYPE_OBJECT,
1449 		 G_TYPE_UINT, G_TYPE_UINT,
1450 		 G_TYPE_UINT);
1451 
1452   /**
1453    * AgsAudio::resolve-recall:
1454    * @audio: the #AgsAudio
1455    * @recall_id: the #AgsRecallID
1456    *
1457    * The ::resolve-recall signal notifies about resolved recalls.
1458    *
1459    * Since: 3.0.0
1460    */
1461   audio_signals[RESOLVE_RECALL] =
1462     g_signal_new("resolve-recall",
1463 		 G_TYPE_FROM_CLASS(audio),
1464 		 G_SIGNAL_RUN_LAST,
1465 		 G_STRUCT_OFFSET(AgsAudioClass, resolve_recall),
1466 		 NULL, NULL,
1467 		 g_cclosure_marshal_VOID__OBJECT,
1468 		 G_TYPE_NONE, 1,
1469 		 G_TYPE_OBJECT);
1470 
1471   /**
1472    * AgsAudio::init-recall:
1473    * @audio: the #AgsAudio
1474    * @recall_id: the #AgsRecallID
1475    * @staging_flags: the staging flags
1476    *
1477    * The ::init-recall signal notifies about initd recalls.
1478    *
1479    * Since: 3.0.0
1480    */
1481   audio_signals[INIT_RECALL] =
1482     g_signal_new("init-recall",
1483 		 G_TYPE_FROM_CLASS(audio),
1484 		 G_SIGNAL_RUN_LAST,
1485 		 G_STRUCT_OFFSET(AgsAudioClass, init_recall),
1486 		 NULL, NULL,
1487 		 ags_cclosure_marshal_VOID__OBJECT_UINT,
1488 		 G_TYPE_NONE, 2,
1489 		 G_TYPE_OBJECT,
1490 		 G_TYPE_UINT);
1491 
1492   /**
1493    * AgsAudio::play-recall:
1494    * @audio: the #AgsAudio
1495    * @recall_id: the #AgsRecallID
1496    * @staging_flags: the staging flags
1497    *
1498    * The ::play-recall signal notifies about playd recalls.
1499    *
1500    * Since: 3.0.0
1501    */
1502   audio_signals[PLAY_RECALL] =
1503     g_signal_new("play-recall",
1504 		 G_TYPE_FROM_CLASS(audio),
1505 		 G_SIGNAL_RUN_LAST,
1506 		 G_STRUCT_OFFSET(AgsAudioClass, play_recall),
1507 		 NULL, NULL,
1508 		 ags_cclosure_marshal_VOID__OBJECT_UINT,
1509 		 G_TYPE_NONE, 2,
1510 		 G_TYPE_OBJECT,
1511 		 G_TYPE_UINT);
1512 
1513   /**
1514    * AgsAudio::done-recall:
1515    * @audio: the #AgsAudio
1516    * @recall_id: the #AgsRecallID
1517    *
1518    * The ::done-recall signal notifies about doned recalls.
1519    *
1520    * Since: 3.0.0
1521    */
1522   audio_signals[DONE_RECALL] =
1523     g_signal_new("done-recall",
1524 		 G_TYPE_FROM_CLASS(audio),
1525 		 G_SIGNAL_RUN_LAST,
1526 		 G_STRUCT_OFFSET(AgsAudioClass, done_recall),
1527 		 NULL, NULL,
1528 		 g_cclosure_marshal_VOID__OBJECT,
1529 		 G_TYPE_NONE, 1,
1530 		 G_TYPE_OBJECT);
1531 
1532   /**
1533    * AgsAudio::cancel-recall:
1534    * @audio: the #AgsAudio
1535    * @recall_id: the #AgsRecallID
1536    *
1537    * The ::cancel-recall signal notifies about canceld recalls.
1538    *
1539    * Since: 3.0.0
1540    */
1541   audio_signals[CANCEL_RECALL] =
1542     g_signal_new("cancel-recall",
1543 		 G_TYPE_FROM_CLASS(audio),
1544 		 G_SIGNAL_RUN_LAST,
1545 		 G_STRUCT_OFFSET(AgsAudioClass, cancel_recall),
1546 		 NULL, NULL,
1547 		 g_cclosure_marshal_VOID__OBJECT,
1548 		 G_TYPE_NONE, 1,
1549 		 G_TYPE_OBJECT);
1550 
1551   /**
1552    * AgsAudio::cleanup-recall:
1553    * @audio: the #AgsAudio
1554    * @recall_id: the #AgsRecallID
1555    *
1556    * The ::cleanup-recall signal notifies about cleanup recalls.
1557    *
1558    * Since: 3.0.0
1559    */
1560   audio_signals[CLEANUP_RECALL] =
1561     g_signal_new("cleanup-recall",
1562 		 G_TYPE_FROM_CLASS(audio),
1563 		 G_SIGNAL_RUN_LAST,
1564 		 G_STRUCT_OFFSET(AgsAudioClass, cleanup_recall),
1565 		 NULL, NULL,
1566 		 g_cclosure_marshal_VOID__OBJECT,
1567 		 G_TYPE_NONE, 1,
1568 		 G_TYPE_OBJECT);
1569 
1570   /**
1571    * AgsAudio::start:
1572    * @audio: the #AgsAudio starts playing
1573    * @sound_scope: the affected scope
1574    *
1575    * The ::start signal is invoked while starting playback
1576    * of @audio.
1577    *
1578    * Returns: the #GList-struct containing #AgsRecallID
1579    *
1580    * Since: 3.0.0
1581    */
1582   audio_signals[START] =
1583     g_signal_new("start",
1584 		 G_TYPE_FROM_CLASS(audio),
1585 		 G_SIGNAL_RUN_LAST,
1586 		 G_STRUCT_OFFSET(AgsAudioClass, start),
1587 		 NULL, NULL,
1588 		 ags_cclosure_marshal_POINTER__INT,
1589 		 G_TYPE_POINTER, 1,
1590 		 G_TYPE_INT);
1591 
1592   /**
1593    * AgsAudio::stop:
1594    * @audio: the #AgsAudio stops playing
1595    * @recall_id: a #GList-struct containing #AgsRecallID
1596    * @sound_scope: the affected scope
1597    *
1598    * The ::stop signal is invoked while stoping playback
1599    * of @audio.
1600    *
1601    * Since: 3.0.0
1602    */
1603   audio_signals[STOP] =
1604     g_signal_new("stop",
1605 		 G_TYPE_FROM_CLASS(audio),
1606 		 G_SIGNAL_RUN_LAST,
1607 		 G_STRUCT_OFFSET(AgsAudioClass, stop),
1608 		 NULL, NULL,
1609 		 ags_cclosure_marshal_VOID__POINTER_INT,
1610 		 G_TYPE_NONE, 2,
1611 		 G_TYPE_POINTER,
1612 		 G_TYPE_INT);
1613 
1614   /**
1615    * AgsAudio::check-scope:
1616    * @audio: the #AgsAudio to check the scopes
1617    * @sound_scope: the affected scope
1618    *
1619    * The ::check-scope method returns the appropriate recall id of @sound_scope.
1620    *
1621    * Returns: the #GList-struct containing #AgsRecallID
1622    *
1623    * Since: 3.0.0
1624    */
1625   audio_signals[CHECK_SCOPE] =
1626     g_signal_new("check-scope",
1627 		 G_TYPE_FROM_CLASS(audio),
1628 		 G_SIGNAL_RUN_LAST,
1629 		 G_STRUCT_OFFSET(AgsAudioClass, check_scope),
1630 		 NULL, NULL,
1631 		 ags_cclosure_marshal_POINTER__INT,
1632 		 G_TYPE_POINTER, 1,
1633 		 G_TYPE_INT);
1634 
1635   /**
1636    * AgsAudio::recursive-run-stage:
1637    * @audio: the #AgsAudio to run
1638    * @sound_scope: the affected scope
1639    * @staging_flags: the flags to set
1640    *
1641    * The ::recursive-run-stage signal is invoked while run staging
1642    * of @audio for @sound_scope.
1643    *
1644    * Since: 3.0.0
1645    */
1646   audio_signals[RECURSIVE_RUN_STAGE] =
1647     g_signal_new("recursive-run-stage",
1648 		 G_TYPE_FROM_CLASS(audio),
1649 		 G_SIGNAL_RUN_LAST,
1650 		 G_STRUCT_OFFSET(AgsAudioClass, recursive_run_stage),
1651 		 NULL, NULL,
1652 		 ags_cclosure_marshal_VOID__INT_UINT,
1653 		 G_TYPE_NONE, 2,
1654 		 G_TYPE_INT,
1655 		 G_TYPE_UINT);
1656 }
1657 
1658 void
ags_audio_connectable_interface_init(AgsConnectableInterface * connectable)1659 ags_audio_connectable_interface_init(AgsConnectableInterface *connectable)
1660 {
1661   connectable->get_uuid = ags_audio_get_uuid;
1662   connectable->has_resource = ags_audio_has_resource;
1663 
1664   connectable->is_ready = ags_audio_is_ready;
1665   connectable->add_to_registry = ags_audio_add_to_registry;
1666   connectable->remove_from_registry = ags_audio_remove_from_registry;
1667 
1668   connectable->list_resource = ags_audio_list_resource;
1669   connectable->xml_compose = ags_audio_xml_compose;
1670   connectable->xml_parse = ags_audio_xml_parse;
1671 
1672   connectable->is_connected = ags_audio_is_connected;
1673   connectable->connect = ags_audio_connect;
1674   connectable->disconnect = ags_audio_disconnect;
1675 
1676   connectable->connect_connection = NULL;
1677   connectable->disconnect_connection = NULL;
1678 }
1679 
1680 void
ags_audio_init(AgsAudio * audio)1681 ags_audio_init(AgsAudio *audio)
1682 {
1683   AgsConfig *config;
1684 
1685   gchar *str;
1686   gchar *str0, *str1;
1687 
1688   audio->flags = 0;
1689   audio->ability_flags = 0;
1690   audio->behaviour_flags = 0;
1691   memset(audio->staging_flags, 0, AGS_SOUND_SCOPE_LAST * sizeof(guint));
1692 
1693   memset(audio->staging_completed, FALSE, AGS_SOUND_SCOPE_LAST * sizeof(gboolean));
1694 
1695   /* audio mutex */
1696   g_rec_mutex_init(&(audio->obj_mutex));
1697 
1698   /* uuid */
1699   audio->uuid = ags_uuid_alloc();
1700   ags_uuid_generate(audio->uuid);
1701 
1702   audio->audio_name = NULL;
1703 
1704   /* config */
1705   config = ags_config_get_instance();
1706 
1707   /* base init */
1708   audio->output_soundcard = NULL;
1709   audio->output_soundcard_channel_map = NULL;
1710 
1711   audio->input_soundcard = NULL;
1712   audio->input_soundcard_channel_map = NULL;
1713 
1714   audio->output_sequencer = NULL;
1715   audio->input_sequencer = NULL;
1716 
1717   audio->samplerate = ags_soundcard_helper_config_get_samplerate(config);
1718   audio->buffer_size = ags_soundcard_helper_config_get_buffer_size(config);
1719   audio->format = ags_soundcard_helper_config_get_format(config);
1720 
1721   audio->bpm = AGS_SOUNDCARD_DEFAULT_BPM;
1722 
1723   /* bank */
1724   audio->bank_dim[0] = 0;
1725   audio->bank_dim[1] = 0;
1726   audio->bank_dim[2] = 0;
1727 
1728   /* channel allocation */
1729   audio->max_audio_channels = G_MAXUINT32;
1730   audio->min_audio_channels = 0;
1731 
1732   audio->max_output_pads = G_MAXUINT32;
1733   audio->min_output_pads = 0;
1734 
1735   audio->max_input_pads = G_MAXUINT32;
1736   audio->min_input_pads = 0;
1737 
1738   audio->audio_channels = 0;
1739 
1740   audio->output_pads = 0;
1741   audio->output_lines = 0;
1742 
1743   audio->input_pads = 0;
1744   audio->input_lines = 0;
1745 
1746   /* midi mapping */
1747   audio->audio_start_mapping = 0;
1748   audio->audio_end_mapping = 0;
1749 
1750   audio->midi_start_mapping = 0;
1751   audio->midi_end_mapping = 0;
1752 
1753   audio->midi_channel = 0;
1754 
1755   /* time-signature */
1756   audio->numerator = 4;
1757   audio->denominator = 4;
1758 
1759   audio->time_signature = g_strdup("4/4");
1760 
1761   /* sharp/flats */
1762   audio->is_minor = FALSE;
1763 
1764   audio->sharp_flats = 0;
1765 
1766   /* octave */
1767   audio->octave = 0;
1768   audio->key = 0;
1769 
1770   audio->absolute_key = 0;
1771 
1772   /* loop */
1773   audio->loop_start = 0;
1774   audio->loop_end = 0;
1775   audio->offset = 0;
1776 
1777   /* channels */
1778   audio->output = NULL;
1779   audio->input = NULL;
1780 
1781   /* preset */
1782   audio->preset = NULL;
1783 
1784   /* playback domain */
1785   audio->playback_domain = (GObject *) ags_playback_domain_new((GObject *) audio);
1786   g_object_ref(audio->playback_domain);
1787 
1788   /* synth generator */
1789   audio->synth_generator = NULL;
1790   audio->sf2_synth_generator = NULL;
1791   audio->sfz_synth_generator = NULL;
1792 
1793   /*
1794    * Storage objects
1795    */
1796   /* cursor */
1797   audio->cursor = NULL;
1798 
1799   /* notation */
1800   audio->notation = NULL;
1801 
1802   /* automation */
1803   audio->automation_port = NULL;
1804 
1805   audio->automation = NULL;
1806 
1807   /* wave */
1808   audio->wave = NULL;
1809 
1810   audio->output_audio_file = NULL;
1811   audio->input_audio_file = NULL;
1812 
1813   /* midi */
1814   audio->midi = NULL;
1815 
1816   audio->output_midi_file = NULL;
1817   audio->input_midi_file = NULL;
1818 
1819   /* recycling context */
1820   audio->recall_id = NULL;
1821   audio->recycling_context = NULL;
1822 
1823   audio->recall_container = NULL;
1824 
1825   /* play context */
1826   g_rec_mutex_init(&(audio->play_mutex));
1827 
1828   audio->play = NULL;
1829 
1830   /* recall context */
1831   g_rec_mutex_init(&(audio->recall_mutex));
1832 
1833   audio->recall = NULL;
1834 
1835   /* data */
1836   audio->machine_widget = NULL;
1837 }
1838 
1839 void
ags_audio_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)1840 ags_audio_set_property(GObject *gobject,
1841 		       guint prop_id,
1842 		       const GValue *value,
1843 		       GParamSpec *param_spec)
1844 {
1845   AgsAudio *audio;
1846 
1847   GRecMutex *audio_mutex;
1848 
1849   audio = AGS_AUDIO(gobject);
1850 
1851   /* get audio mutex */
1852   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
1853 
1854   switch(prop_id){
1855   case PROP_AUDIO_NAME:
1856   {
1857     gchar *audio_name;
1858 
1859     audio_name = g_value_get_string(value);
1860 
1861     g_rec_mutex_lock(audio_mutex);
1862 
1863     audio->audio_name = g_strdup(audio_name);
1864 
1865     g_rec_mutex_unlock(audio_mutex);
1866   }
1867   break;
1868   case PROP_OUTPUT_SOUNDCARD:
1869   {
1870     GObject *soundcard;
1871 
1872     soundcard = g_value_get_object(value);
1873 
1874     ags_audio_real_set_output_soundcard(audio,
1875 					(GObject *) soundcard);
1876   }
1877   break;
1878   case PROP_INPUT_SOUNDCARD:
1879   {
1880     GObject *soundcard;
1881 
1882     soundcard = g_value_get_object(value);
1883 
1884     ags_audio_real_set_input_soundcard(audio,
1885 				       (GObject *) soundcard);
1886   }
1887   break;
1888   case PROP_OUTPUT_SEQUENCER:
1889   {
1890     GObject *sequencer;
1891 
1892     sequencer = g_value_get_object(value);
1893 
1894     ags_audio_real_set_output_sequencer(audio,
1895 					(GObject *) sequencer);
1896   }
1897   break;
1898   case PROP_INPUT_SEQUENCER:
1899   {
1900     GObject *sequencer;
1901 
1902     sequencer = g_value_get_object(value);
1903 
1904     ags_audio_real_set_input_sequencer(audio,
1905 				       (GObject *) sequencer);
1906   }
1907   break;
1908   case PROP_SAMPLERATE:
1909   {
1910     guint samplerate;
1911 
1912     samplerate = g_value_get_uint(value);
1913 
1914     ags_audio_real_set_samplerate(audio,
1915 				  samplerate);
1916   }
1917   break;
1918   case PROP_BUFFER_SIZE:
1919   {
1920     guint buffer_size;
1921 
1922     buffer_size = g_value_get_uint(value);
1923 
1924     ags_audio_real_set_buffer_size(audio,
1925 				   buffer_size);
1926   }
1927   break;
1928   case PROP_FORMAT:
1929   {
1930     guint format;
1931 
1932     format = g_value_get_uint(value);
1933 
1934     ags_audio_real_set_format(audio,
1935 			      format);
1936   }
1937   break;
1938   case PROP_BPM:
1939   {
1940     gdouble bpm;
1941 
1942     bpm = g_value_get_double(value);
1943 
1944     g_rec_mutex_lock(audio_mutex);
1945 
1946     audio->bpm = bpm;
1947 
1948     g_rec_mutex_unlock(audio_mutex);
1949   }
1950   break;
1951   case PROP_MIN_AUDIO_CHANNELS:
1952   {
1953     guint min_audio_channels;
1954 
1955     min_audio_channels = g_value_get_uint(value);
1956 
1957     g_rec_mutex_lock(audio_mutex);
1958 
1959     audio->min_audio_channels = min_audio_channels;
1960 
1961     g_rec_mutex_unlock(audio_mutex);
1962   }
1963   break;
1964   case PROP_MAX_AUDIO_CHANNELS:
1965   {
1966     guint max_audio_channels;
1967 
1968     max_audio_channels = g_value_get_uint(value);
1969 
1970     ags_audio_set_max_audio_channels(audio,
1971 				     max_audio_channels);
1972   }
1973   break;
1974   case PROP_MIN_OUTPUT_PADS:
1975   {
1976     guint min_output_pads;
1977 
1978     min_output_pads = g_value_get_uint(value);
1979 
1980     g_rec_mutex_lock(audio_mutex);
1981 
1982     audio->min_output_pads = min_output_pads;
1983 
1984     g_rec_mutex_unlock(audio_mutex);
1985   }
1986   break;
1987   case PROP_MAX_OUTPUT_PADS:
1988   {
1989     guint max_output_pads;
1990 
1991     max_output_pads = g_value_get_uint(value);
1992 
1993     ags_audio_set_max_pads(audio,
1994 			   AGS_TYPE_OUTPUT,
1995 			   max_output_pads);
1996   }
1997   break;
1998   case PROP_MIN_INPUT_PADS:
1999   {
2000     guint min_input_pads;
2001 
2002     min_input_pads = g_value_get_uint(value);
2003 
2004     g_rec_mutex_lock(audio_mutex);
2005 
2006     audio->min_input_pads = min_input_pads;
2007 
2008     g_rec_mutex_unlock(audio_mutex);
2009   }
2010   break;
2011   case PROP_MAX_INPUT_PADS:
2012   {
2013     guint max_input_pads;
2014 
2015     max_input_pads = g_value_get_uint(value);
2016 
2017     ags_audio_set_max_pads(audio,
2018 			   AGS_TYPE_INPUT,
2019 			   max_input_pads);
2020   }
2021   break;
2022   case PROP_AUDIO_CHANNELS:
2023   {
2024     guint audio_channels;
2025 
2026     audio_channels = g_value_get_uint(value);
2027 
2028     ags_audio_set_audio_channels(audio,
2029 				 audio_channels, 0);
2030   }
2031   break;
2032   case PROP_OUTPUT_PADS:
2033   {
2034     guint output_pads;
2035 
2036     output_pads = g_value_get_uint(value);
2037 
2038     ags_audio_set_pads(audio,
2039 		       AGS_TYPE_OUTPUT,
2040 		       output_pads, 0);
2041   }
2042   break;
2043   case PROP_INPUT_PADS:
2044   {
2045     guint input_pads;
2046 
2047     input_pads = g_value_get_uint(value);
2048 
2049     ags_audio_set_pads(audio,
2050 		       AGS_TYPE_INPUT,
2051 		       input_pads, 0);
2052   }
2053   break;
2054   case PROP_AUDIO_START_MAPPING:
2055   {
2056     guint audio_start_mapping;
2057 
2058     audio_start_mapping = g_value_get_uint(value);
2059 
2060     g_rec_mutex_lock(audio_mutex);
2061 
2062     audio->audio_start_mapping = audio_start_mapping;
2063 
2064     g_rec_mutex_unlock(audio_mutex);
2065   }
2066   break;
2067   case PROP_AUDIO_END_MAPPING:
2068   {
2069     guint audio_end_mapping;
2070 
2071     audio_end_mapping = g_value_get_uint(value);
2072 
2073     g_rec_mutex_lock(audio_mutex);
2074 
2075     audio->audio_end_mapping = audio_end_mapping;
2076 
2077     g_rec_mutex_unlock(audio_mutex);
2078   }
2079   break;
2080   case PROP_MIDI_START_MAPPING:
2081   {
2082     guint midi_start_mapping;
2083 
2084     midi_start_mapping = g_value_get_uint(value);
2085 
2086     g_rec_mutex_lock(audio_mutex);
2087 
2088     audio->midi_start_mapping = midi_start_mapping;
2089 
2090     g_rec_mutex_unlock(audio_mutex);
2091   }
2092   break;
2093   case PROP_MIDI_END_MAPPING:
2094   {
2095     guint midi_end_mapping;
2096 
2097     midi_end_mapping = g_value_get_uint(value);
2098 
2099     g_rec_mutex_lock(audio_mutex);
2100 
2101     audio->midi_end_mapping = midi_end_mapping;
2102 
2103     g_rec_mutex_unlock(audio_mutex);
2104   }
2105   break;
2106   case PROP_MIDI_CHANNEL:
2107   {
2108     guint midi_channel;
2109 
2110     midi_channel = g_value_get_uint(value);
2111 
2112     g_rec_mutex_lock(audio_mutex);
2113 
2114     audio->midi_channel = midi_channel;
2115 
2116     g_rec_mutex_unlock(audio_mutex);
2117   }
2118   break;
2119   case PROP_NUMERATOR:
2120   {
2121     guint numerator;
2122 
2123     numerator = g_value_get_uint(value);
2124 
2125     /* numerator and time signature */
2126     g_rec_mutex_lock(audio_mutex);
2127 
2128     audio->numerator = numerator;
2129 
2130     g_free(audio->time_signature);
2131     audio->time_signature = g_strdup_printf("%u/%u",
2132 					    audio->numerator,
2133 					    audio->denominator);
2134 
2135     g_rec_mutex_unlock(audio_mutex);
2136   }
2137   break;
2138   case PROP_DENOMINATOR:
2139   {
2140     guint denominator;
2141 
2142     denominator = g_value_get_uint(value);
2143 
2144     /* denominator and time signature */
2145     g_rec_mutex_lock(audio_mutex);
2146 
2147     audio->denominator = denominator;
2148 
2149     g_free(audio->time_signature);
2150     audio->time_signature = g_strdup_printf("%u/%u",
2151 					    audio->numerator,
2152 					    audio->denominator);
2153 
2154     g_rec_mutex_unlock(audio_mutex);
2155   }
2156   break;
2157   case PROP_IS_MINOR:
2158   {
2159     gboolean is_minor;
2160 
2161     is_minor = g_value_get_boolean(value);
2162 
2163     g_rec_mutex_lock(audio_mutex);
2164 
2165     audio->is_minor = is_minor;
2166 
2167     g_rec_mutex_unlock(audio_mutex);
2168   }
2169   break;
2170   case PROP_SHARP_FLATS:
2171   {
2172     guint sharp_flats;
2173 
2174     sharp_flats = g_value_get_uint(value);
2175 
2176     g_rec_mutex_lock(audio_mutex);
2177 
2178     audio->sharp_flats = sharp_flats;
2179 
2180     g_rec_mutex_unlock(audio_mutex);
2181   }
2182   break;
2183   case PROP_OCTAVE:
2184   {
2185     gint octave;
2186 
2187     octave = g_value_get_int(value);
2188 
2189     g_rec_mutex_lock(audio_mutex);
2190 
2191     audio->octave = octave;
2192 
2193     g_rec_mutex_unlock(audio_mutex);
2194   }
2195   break;
2196   case PROP_KEY:
2197   {
2198     guint key;
2199 
2200     key = g_value_get_uint(value);
2201 
2202     g_rec_mutex_lock(audio_mutex);
2203 
2204     audio->key = key;
2205 
2206     g_rec_mutex_unlock(audio_mutex);
2207   }
2208   break;
2209   case PROP_ABSOLUTE_KEY:
2210   {
2211     gint absolute_key;
2212 
2213     absolute_key = g_value_get_int(value);
2214 
2215     g_rec_mutex_lock(audio_mutex);
2216 
2217     audio->absolute_key = absolute_key;
2218 
2219     g_rec_mutex_unlock(audio_mutex);
2220   }
2221   break;
2222   case PROP_LOOP_START:
2223   {
2224     guint64 loop_start;
2225 
2226     loop_start = g_value_get_uint64(value);
2227 
2228     g_rec_mutex_lock(audio_mutex);
2229 
2230     audio->loop_start = loop_start;
2231 
2232     g_rec_mutex_unlock(audio_mutex);
2233   }
2234   break;
2235   case PROP_LOOP_END:
2236   {
2237     guint64 loop_end;
2238 
2239     loop_end = g_value_get_uint64(value);
2240 
2241     g_rec_mutex_lock(audio_mutex);
2242 
2243     audio->loop_end = loop_end;
2244 
2245     g_rec_mutex_unlock(audio_mutex);
2246   }
2247   break;
2248   case PROP_OFFSET:
2249   {
2250     guint64 offset;
2251 
2252     offset = g_value_get_uint64(value);
2253 
2254     g_rec_mutex_lock(audio_mutex);
2255 
2256     audio->offset = offset;
2257 
2258     g_rec_mutex_unlock(audio_mutex);
2259   }
2260   break;
2261   case PROP_PRESET:
2262   {
2263     AgsPreset *preset;
2264 
2265     preset = (AgsPreset *) g_value_get_pointer(value);
2266 
2267     ags_audio_add_preset(audio,
2268 			 (GObject *) preset);
2269   }
2270   break;
2271   case PROP_SYNTH_GENERATOR:
2272   {
2273     AgsSynthGenerator *synth_generator;
2274 
2275     synth_generator = (AgsSynthGenerator *) g_value_get_pointer(value);
2276 
2277     ags_audio_add_synth_generator(audio,
2278 				  (GObject *) synth_generator);
2279   }
2280   break;
2281   case PROP_SF2_SYNTH_GENERATOR:
2282   {
2283     AgsSF2SynthGenerator *sf2_synth_generator;
2284 
2285     sf2_synth_generator = (AgsSF2SynthGenerator *) g_value_get_pointer(value);
2286 
2287     ags_audio_add_sf2_synth_generator(audio,
2288 				      (GObject *) sf2_synth_generator);
2289   }
2290   break;
2291   case PROP_SFZ_SYNTH_GENERATOR:
2292   {
2293     AgsSFZSynthGenerator *sfz_synth_generator;
2294 
2295     sfz_synth_generator = (AgsSFZSynthGenerator *) g_value_get_pointer(value);
2296 
2297     ags_audio_add_sfz_synth_generator(audio,
2298 				      (GObject *) sfz_synth_generator);
2299   }
2300   break;
2301   case PROP_PLAYBACK_DOMAIN:
2302   {
2303     AgsPlaybackDomain *playback_domain;
2304 
2305     playback_domain = (AgsPlaybackDomain *) g_value_get_object(value);
2306 
2307     g_rec_mutex_lock(audio_mutex);
2308 
2309     if(audio->playback_domain == (GObject *) playback_domain){
2310       g_rec_mutex_unlock(audio_mutex);
2311 
2312       return;
2313     }
2314 
2315     if(audio->playback_domain != NULL){
2316       g_object_unref(audio->playback_domain);
2317     }
2318 
2319     if(playback_domain != NULL){
2320       g_object_ref(playback_domain);
2321     }
2322 
2323     audio->playback_domain = (GObject *) playback_domain;
2324 
2325     g_rec_mutex_unlock(audio_mutex);
2326   }
2327   break;
2328   case PROP_CURSOR:
2329   {
2330     GObject *cursor;
2331 
2332     cursor = (GObject *) g_value_get_pointer(value);
2333 
2334     ags_audio_add_cursor(audio,
2335 			 (GObject *) cursor);
2336   }
2337   break;
2338   case PROP_NOTATION:
2339   {
2340     AgsNotation *notation;
2341 
2342     notation = (AgsNotation *) g_value_get_pointer(value);
2343 
2344     ags_audio_add_notation(audio,
2345 			   (GObject *) notation);
2346   }
2347   break;
2348   case PROP_AUTOMATION:
2349   {
2350     AgsAutomation *automation;
2351 
2352     automation = (AgsAutomation *) g_value_get_pointer(value);
2353 
2354     ags_audio_add_automation(audio,
2355 			     (GObject *) automation);
2356   }
2357   break;
2358   case PROP_WAVE:
2359   {
2360     AgsWave *wave;
2361 
2362     wave = (AgsWave *) g_value_get_pointer(value);
2363 
2364     ags_audio_add_wave(audio,
2365 		       (GObject *) wave);
2366   }
2367   break;
2368   case PROP_OUTPUT_AUDIO_FILE:
2369   {
2370     AgsAudioFile *output_audio_file;
2371 
2372     output_audio_file = (AgsAudioFile *) g_value_get_object(value);
2373 
2374     g_rec_mutex_lock(audio_mutex);
2375 
2376     if(audio->output_audio_file == (GObject *) output_audio_file){
2377       g_rec_mutex_unlock(audio_mutex);
2378 
2379       return;
2380     }
2381 
2382     if(audio->output_audio_file != NULL){
2383       g_object_unref(audio->output_audio_file);
2384     }
2385 
2386     if(output_audio_file != NULL){
2387       g_object_ref(output_audio_file);
2388     }
2389 
2390     audio->output_audio_file = (GObject *) output_audio_file;
2391 
2392     g_rec_mutex_unlock(audio_mutex);
2393   }
2394   break;
2395   case PROP_INPUT_AUDIO_FILE:
2396   {
2397     AgsAudioFile *input_audio_file;
2398 
2399     input_audio_file = (AgsAudioFile *) g_value_get_object(value);
2400 
2401     g_rec_mutex_lock(audio_mutex);
2402 
2403     if(audio->input_audio_file == (GObject *) input_audio_file){
2404       g_rec_mutex_unlock(audio_mutex);
2405 
2406       return;
2407     }
2408 
2409     if(audio->input_audio_file != NULL){
2410       g_object_unref(audio->input_audio_file);
2411     }
2412 
2413     if(input_audio_file != NULL){
2414       g_object_ref(input_audio_file);
2415     }
2416 
2417     audio->input_audio_file = (GObject *) input_audio_file;
2418 
2419     g_rec_mutex_unlock(audio_mutex);
2420   }
2421   break;
2422   case PROP_MIDI:
2423   {
2424     AgsMidi *midi;
2425 
2426     midi = (AgsMidi *) g_value_get_pointer(value);
2427 
2428     ags_audio_add_midi(audio,
2429 		       (GObject *) midi);
2430   }
2431   break;
2432   case PROP_OUTPUT_MIDI_FILE:
2433   {
2434     AgsMidiFile *output_midi_file;
2435 
2436     output_midi_file = g_value_get_object(value);
2437 
2438     g_rec_mutex_lock(audio_mutex);
2439 
2440     if((AgsMidiFile *) audio->output_midi_file == output_midi_file){
2441       g_rec_mutex_unlock(audio_mutex);
2442 
2443       return;
2444     }
2445 
2446     if(audio->output_midi_file != NULL){
2447       g_object_unref(audio->output_midi_file);
2448     }
2449 
2450     if(output_midi_file != NULL) {
2451       g_object_ref(output_midi_file);
2452     }
2453 
2454     audio->output_midi_file = (GObject *) output_midi_file;
2455 
2456     g_rec_mutex_unlock(audio_mutex);
2457   }
2458   break;
2459   case PROP_INPUT_MIDI_FILE:
2460   {
2461     AgsMidiFile *input_midi_file;
2462 
2463     input_midi_file = g_value_get_object(value);
2464 
2465     g_rec_mutex_lock(audio_mutex);
2466 
2467     if((AgsMidiFile *) audio->input_midi_file == input_midi_file){
2468       g_rec_mutex_unlock(audio_mutex);
2469 
2470       return;
2471     }
2472 
2473     if(audio->input_midi_file != NULL){
2474       g_object_unref(audio->input_midi_file);
2475     }
2476 
2477     if(input_midi_file != NULL) {
2478       g_object_ref(input_midi_file);
2479     }
2480 
2481     audio->input_midi_file = (GObject *) input_midi_file;
2482 
2483     g_rec_mutex_unlock(audio_mutex);
2484   }
2485   break;
2486   case PROP_RECALL_ID:
2487   {
2488     AgsRecallID *recall_id;
2489 
2490     recall_id = (AgsRecallID *) g_value_get_pointer(value);
2491 
2492     ags_audio_add_recall_id(audio,
2493 			    (GObject *) recall_id);
2494   }
2495   break;
2496   case PROP_RECYCLING_CONTEXT:
2497   {
2498     AgsRecyclingContext *recycling_context;
2499 
2500     recycling_context = (AgsRecyclingContext *) g_value_get_pointer(value);
2501 
2502     ags_audio_add_recycling_context(audio,
2503 				    (GObject *) recycling_context);
2504   }
2505   break;
2506   case PROP_RECALL_CONTAINER:
2507   {
2508     AgsRecallContainer *recall_container;
2509 
2510     recall_container = (AgsRecallContainer *) g_value_get_pointer(value);
2511 
2512     ags_audio_add_recall_container(audio,
2513 				   (GObject *) recall_container);
2514   }
2515   break;
2516   case PROP_PLAY:
2517   {
2518     AgsRecall *recall;
2519 
2520     /*  */
2521     recall = (AgsRecall *) g_value_get_pointer(value);
2522 
2523     ags_audio_add_recall(audio,
2524 			 (GObject *) recall,
2525 			 TRUE);
2526   }
2527   break;
2528   case PROP_RECALL:
2529   {
2530     AgsRecall *recall;
2531 
2532     /*  */
2533     recall = (AgsRecall *) g_value_get_pointer(value);
2534 
2535     ags_audio_add_recall(audio,
2536 			 (GObject *) recall,
2537 			 FALSE);
2538   }
2539   break;
2540   default:
2541     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
2542   }
2543 }
2544 
2545 void
ags_audio_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)2546 ags_audio_get_property(GObject *gobject,
2547 		       guint prop_id,
2548 		       GValue *value,
2549 		       GParamSpec *param_spec)
2550 {
2551   AgsAudio *audio;
2552 
2553   GRecMutex *audio_mutex;
2554 
2555   audio = AGS_AUDIO(gobject);
2556 
2557   /* get audio mutex */
2558   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
2559 
2560   switch(prop_id){
2561   case PROP_AUDIO_NAME:
2562   {
2563     g_rec_mutex_lock(audio_mutex);
2564 
2565     g_value_set_string(value,
2566 		       audio->audio_name);
2567 
2568     g_rec_mutex_unlock(audio_mutex);
2569   }
2570   break;
2571   case PROP_OUTPUT_SOUNDCARD:
2572   {
2573     g_rec_mutex_lock(audio_mutex);
2574 
2575     g_value_set_object(value,
2576 		       audio->output_soundcard);
2577 
2578     g_rec_mutex_unlock(audio_mutex);
2579   }
2580   break;
2581   case PROP_INPUT_SOUNDCARD:
2582   {
2583     g_rec_mutex_lock(audio_mutex);
2584 
2585     g_value_set_object(value,
2586 		       audio->input_soundcard);
2587 
2588     g_rec_mutex_unlock(audio_mutex);
2589   }
2590   break;
2591   case PROP_OUTPUT_SEQUENCER:
2592   {
2593     g_rec_mutex_lock(audio_mutex);
2594 
2595     g_value_set_object(value,
2596 		       audio->output_sequencer);
2597 
2598     g_rec_mutex_unlock(audio_mutex);
2599   }
2600   break;
2601   case PROP_INPUT_SEQUENCER:
2602   {
2603     g_rec_mutex_lock(audio_mutex);
2604 
2605     g_value_set_object(value,
2606 		       audio->input_sequencer);
2607 
2608     g_rec_mutex_unlock(audio_mutex);
2609   }
2610   break;
2611   case PROP_SAMPLERATE:
2612   {
2613     g_rec_mutex_lock(audio_mutex);
2614 
2615     g_value_set_uint(value,
2616 		     audio->samplerate);
2617 
2618     g_rec_mutex_unlock(audio_mutex);
2619   }
2620   break;
2621   case PROP_BUFFER_SIZE:
2622   {
2623     g_rec_mutex_lock(audio_mutex);
2624 
2625     g_value_set_uint(value,
2626 		     audio->buffer_size);
2627 
2628     g_rec_mutex_unlock(audio_mutex);
2629   }
2630   break;
2631   case PROP_FORMAT:
2632   {
2633     g_rec_mutex_lock(audio_mutex);
2634 
2635     g_value_set_uint(value,
2636 		     audio->format);
2637 
2638     g_rec_mutex_unlock(audio_mutex);
2639   }
2640   break;
2641   case PROP_BPM:
2642   {
2643     g_rec_mutex_lock(audio_mutex);
2644 
2645     g_value_set_double(value,
2646 		       audio->bpm);
2647 
2648     g_rec_mutex_unlock(audio_mutex);
2649   }
2650   break;
2651   case PROP_MIN_AUDIO_CHANNELS:
2652   {
2653     g_rec_mutex_lock(audio_mutex);
2654 
2655     g_value_set_uint(value,
2656 		     audio->min_audio_channels);
2657 
2658     g_rec_mutex_unlock(audio_mutex);
2659   }
2660   break;
2661   case PROP_MAX_AUDIO_CHANNELS:
2662   {
2663     g_rec_mutex_lock(audio_mutex);
2664 
2665     g_value_set_uint(value,
2666 		     audio->max_audio_channels);
2667 
2668     g_rec_mutex_unlock(audio_mutex);
2669   }
2670   break;
2671   case PROP_MIN_OUTPUT_PADS:
2672   {
2673     g_rec_mutex_lock(audio_mutex);
2674 
2675     g_value_set_uint(value,
2676 		     audio->min_output_pads);
2677 
2678     g_rec_mutex_unlock(audio_mutex);
2679   }
2680   break;
2681   case PROP_MAX_OUTPUT_PADS:
2682   {
2683     g_rec_mutex_lock(audio_mutex);
2684 
2685     g_value_set_uint(value,
2686 		     audio->max_output_pads);
2687 
2688     g_rec_mutex_unlock(audio_mutex);
2689   }
2690   break;
2691   case PROP_MIN_INPUT_PADS:
2692   {
2693     g_rec_mutex_lock(audio_mutex);
2694 
2695     g_value_set_uint(value,
2696 		     audio->min_input_pads);
2697 
2698     g_rec_mutex_unlock(audio_mutex);
2699   }
2700   break;
2701   case PROP_MAX_INPUT_PADS:
2702   {
2703     g_rec_mutex_lock(audio_mutex);
2704 
2705     g_value_set_uint(value,
2706 		     audio->max_input_pads);
2707 
2708     g_rec_mutex_unlock(audio_mutex);
2709   }
2710   break;
2711   case PROP_AUDIO_CHANNELS:
2712   {
2713     g_rec_mutex_lock(audio_mutex);
2714 
2715     g_value_set_uint(value,
2716 		     audio->audio_channels);
2717 
2718     g_rec_mutex_unlock(audio_mutex);
2719   }
2720   break;
2721   case PROP_OUTPUT_PADS:
2722   {
2723     g_rec_mutex_lock(audio_mutex);
2724 
2725     g_value_set_uint(value,
2726 		     audio->output_pads);
2727 
2728     g_rec_mutex_unlock(audio_mutex);
2729   }
2730   break;
2731   case PROP_OUTPUT_LINES:
2732   {
2733     g_rec_mutex_lock(audio_mutex);
2734 
2735     g_value_set_uint(value,
2736 		     audio->output_lines);
2737 
2738     g_rec_mutex_unlock(audio_mutex);
2739   }
2740   break;
2741   case PROP_INPUT_PADS:
2742   {
2743     g_rec_mutex_lock(audio_mutex);
2744 
2745     g_value_set_uint(value,
2746 		     audio->input_pads);
2747 
2748     g_rec_mutex_unlock(audio_mutex);
2749   }
2750   break;
2751   case PROP_INPUT_LINES:
2752   {
2753     g_rec_mutex_lock(audio_mutex);
2754 
2755     g_value_set_uint(value,
2756 		     audio->input_lines);
2757 
2758     g_rec_mutex_unlock(audio_mutex);
2759   }
2760   break;
2761   case PROP_AUDIO_START_MAPPING:
2762   {
2763     g_rec_mutex_lock(audio_mutex);
2764 
2765     g_value_set_uint(value,
2766 		     audio->audio_start_mapping);
2767 
2768     g_rec_mutex_unlock(audio_mutex);
2769   }
2770   break;
2771   case PROP_AUDIO_END_MAPPING:
2772   {
2773     g_rec_mutex_lock(audio_mutex);
2774 
2775     g_value_set_uint(value,
2776 		     audio->audio_end_mapping);
2777 
2778     g_rec_mutex_unlock(audio_mutex);
2779   }
2780   break;
2781   case PROP_MIDI_START_MAPPING:
2782   {
2783     g_rec_mutex_lock(audio_mutex);
2784 
2785     g_value_set_uint(value,
2786 		     audio->midi_start_mapping);
2787 
2788     g_rec_mutex_unlock(audio_mutex);
2789   }
2790   break;
2791   case PROP_MIDI_END_MAPPING:
2792   {
2793     g_rec_mutex_lock(audio_mutex);
2794 
2795     g_value_set_uint(value,
2796 		     audio->midi_end_mapping);
2797 
2798     g_rec_mutex_unlock(audio_mutex);
2799   }
2800   break;
2801   case PROP_MIDI_CHANNEL:
2802   {
2803     g_rec_mutex_lock(audio_mutex);
2804 
2805     g_value_set_uint(value,
2806 		     audio->midi_channel);
2807 
2808     g_rec_mutex_unlock(audio_mutex);
2809   }
2810   break;
2811   case PROP_NUMERATOR:
2812   {
2813     g_rec_mutex_lock(audio_mutex);
2814 
2815     g_value_set_uint(value,
2816 		     audio->numerator);
2817 
2818     g_rec_mutex_unlock(audio_mutex);
2819   }
2820   break;
2821   case PROP_DENOMINATOR:
2822   {
2823     g_rec_mutex_lock(audio_mutex);
2824 
2825     g_value_set_uint(value,
2826 		     audio->denominator);
2827 
2828     g_rec_mutex_unlock(audio_mutex);
2829   }
2830   break;
2831   case PROP_TIME_SIGNATURE:
2832   {
2833     g_rec_mutex_lock(audio_mutex);
2834 
2835     g_value_set_string(value,
2836 		       audio->time_signature);
2837 
2838     g_rec_mutex_unlock(audio_mutex);
2839   }
2840   break;
2841   case PROP_IS_MINOR:
2842   {
2843     g_rec_mutex_lock(audio_mutex);
2844 
2845     g_value_set_boolean(value,
2846 			audio->is_minor);
2847 
2848     g_rec_mutex_unlock(audio_mutex);
2849   }
2850   break;
2851   case PROP_SHARP_FLATS:
2852   {
2853     g_rec_mutex_lock(audio_mutex);
2854 
2855     g_value_set_uint(value,
2856 		     audio->sharp_flats);
2857 
2858     g_rec_mutex_unlock(audio_mutex);
2859   }
2860   break;
2861   case PROP_OCTAVE:
2862   {
2863     g_rec_mutex_lock(audio_mutex);
2864 
2865     g_value_set_int(value,
2866 		    audio->octave);
2867 
2868     g_rec_mutex_unlock(audio_mutex);
2869   }
2870   break;
2871   case PROP_KEY:
2872   {
2873     g_rec_mutex_lock(audio_mutex);
2874 
2875     g_value_set_uint(value,
2876 		     audio->key);
2877 
2878     g_rec_mutex_unlock(audio_mutex);
2879   }
2880   break;
2881   case PROP_ABSOLUTE_KEY:
2882   {
2883     g_rec_mutex_lock(audio_mutex);
2884 
2885     g_value_set_int(value,
2886 		    audio->absolute_key);
2887 
2888     g_rec_mutex_unlock(audio_mutex);
2889   }
2890   break;
2891   case PROP_LOOP_START:
2892   {
2893     g_rec_mutex_lock(audio_mutex);
2894 
2895     g_value_set_uint64(value,
2896 		       audio->loop_start);
2897 
2898     g_rec_mutex_unlock(audio_mutex);
2899   }
2900   break;
2901   case PROP_LOOP_END:
2902   {
2903     g_rec_mutex_lock(audio_mutex);
2904 
2905     g_value_set_uint64(value,
2906 		       audio->loop_end);
2907 
2908     g_rec_mutex_unlock(audio_mutex);
2909   }
2910   break;
2911   case PROP_OFFSET:
2912   {
2913     g_rec_mutex_lock(audio_mutex);
2914 
2915     g_value_set_uint64(value,
2916 		       audio->offset);
2917 
2918     g_rec_mutex_unlock(audio_mutex);
2919   }
2920   break;
2921   case PROP_OUTPUT:
2922   {
2923     g_rec_mutex_lock(audio_mutex);
2924 
2925     g_value_set_object(value,
2926 		       audio->output);
2927 
2928     g_rec_mutex_unlock(audio_mutex);
2929   }
2930   break;
2931   case PROP_INPUT:
2932   {
2933     g_rec_mutex_lock(audio_mutex);
2934 
2935     g_value_set_object(value,
2936 		       audio->input);
2937 
2938     g_rec_mutex_unlock(audio_mutex);
2939   }
2940   break;
2941   case PROP_PRESET:
2942   {
2943     g_rec_mutex_lock(audio_mutex);
2944 
2945     g_value_set_pointer(value,
2946 			g_list_copy_deep(audio->preset,
2947 					 (GCopyFunc) g_object_ref,
2948 					 NULL));
2949 
2950     g_rec_mutex_unlock(audio_mutex);
2951   }
2952   break;
2953   case PROP_SYNTH_GENERATOR:
2954   {
2955     g_rec_mutex_lock(audio_mutex);
2956 
2957     g_value_set_pointer(value,
2958 			g_list_copy_deep(audio->synth_generator,
2959 					 (GCopyFunc) g_object_ref,
2960 					 NULL));
2961 
2962     g_rec_mutex_unlock(audio_mutex);
2963   }
2964   break;
2965   case PROP_SF2_SYNTH_GENERATOR:
2966   {
2967     g_rec_mutex_lock(audio_mutex);
2968 
2969     g_value_set_pointer(value,
2970 			g_list_copy_deep(audio->sf2_synth_generator,
2971 					 (GCopyFunc) g_object_ref,
2972 					 NULL));
2973 
2974     g_rec_mutex_unlock(audio_mutex);
2975   }
2976   break;
2977   case PROP_SFZ_SYNTH_GENERATOR:
2978   {
2979     g_rec_mutex_lock(audio_mutex);
2980 
2981     g_value_set_pointer(value,
2982 			g_list_copy_deep(audio->sfz_synth_generator,
2983 					 (GCopyFunc) g_object_ref,
2984 					 NULL));
2985 
2986     g_rec_mutex_unlock(audio_mutex);
2987   }
2988   break;
2989   case PROP_PLAYBACK_DOMAIN:
2990   {
2991     g_rec_mutex_lock(audio_mutex);
2992 
2993     g_value_set_object(value,
2994 		       audio->playback_domain);
2995 
2996     g_rec_mutex_unlock(audio_mutex);
2997   }
2998   break;
2999   case PROP_CURSOR:
3000   {
3001     g_rec_mutex_lock(audio_mutex);
3002 
3003     g_value_set_pointer(value,
3004 			g_list_copy_deep(audio->cursor,
3005 					 (GCopyFunc) g_object_ref,
3006 					 NULL));
3007 
3008     g_rec_mutex_unlock(audio_mutex);
3009   }
3010   break;
3011   case PROP_NOTATION:
3012   {
3013     g_rec_mutex_lock(audio_mutex);
3014 
3015     g_value_set_pointer(value,
3016 			g_list_copy_deep(audio->notation,
3017 					 (GCopyFunc) g_object_ref,
3018 					 NULL));
3019 
3020     g_rec_mutex_unlock(audio_mutex);
3021   }
3022   break;
3023   case PROP_AUTOMATION:
3024   {
3025     g_rec_mutex_lock(audio_mutex);
3026 
3027     g_value_set_pointer(value,
3028 			g_list_copy_deep(audio->automation,
3029 					 (GCopyFunc) g_object_ref,
3030 					 NULL));
3031 
3032     g_rec_mutex_unlock(audio_mutex);
3033   }
3034   break;
3035   case PROP_WAVE:
3036   {
3037     g_rec_mutex_lock(audio_mutex);
3038 
3039     g_value_set_pointer(value,
3040 			g_list_copy_deep(audio->wave,
3041 					 (GCopyFunc) g_object_ref,
3042 					 NULL));
3043 
3044     g_rec_mutex_unlock(audio_mutex);
3045   }
3046   break;
3047   case PROP_OUTPUT_AUDIO_FILE:
3048   {
3049     g_rec_mutex_lock(audio_mutex);
3050 
3051     g_value_set_object(value,
3052 		       audio->output_audio_file);
3053 
3054     g_rec_mutex_unlock(audio_mutex);
3055   }
3056   break;
3057   case PROP_INPUT_AUDIO_FILE:
3058   {
3059     g_rec_mutex_lock(audio_mutex);
3060 
3061     g_value_set_object(value,
3062 		       audio->input_audio_file);
3063 
3064     g_rec_mutex_unlock(audio_mutex);
3065   }
3066   break;
3067   case PROP_OUTPUT_MIDI_FILE:
3068   {
3069     g_rec_mutex_lock(audio_mutex);
3070 
3071     g_value_set_object(value,
3072 		       audio->output_midi_file);
3073 
3074     g_rec_mutex_unlock(audio_mutex);
3075   }
3076   break;
3077   case PROP_INPUT_MIDI_FILE:
3078   {
3079     g_rec_mutex_lock(audio_mutex);
3080 
3081     g_value_set_object(value,
3082 		       audio->input_midi_file);
3083 
3084     g_rec_mutex_unlock(audio_mutex);
3085   }
3086   break;
3087   case PROP_RECALL_ID:
3088   {
3089     g_rec_mutex_lock(audio_mutex);
3090 
3091     g_value_set_pointer(value,
3092 			g_list_copy_deep(audio->recall_id,
3093 					 (GCopyFunc) g_object_ref,
3094 					 NULL));
3095 
3096     g_rec_mutex_unlock(audio_mutex);
3097   }
3098   break;
3099   case PROP_RECYCLING_CONTEXT:
3100   {
3101     g_rec_mutex_lock(audio_mutex);
3102 
3103     g_value_set_pointer(value,
3104 			g_list_copy_deep(audio->recycling_context,
3105 					 (GCopyFunc) g_object_ref,
3106 					 NULL));
3107 
3108     g_rec_mutex_unlock(audio_mutex);
3109   }
3110   break;
3111   case PROP_RECALL_CONTAINER:
3112   {
3113     g_rec_mutex_lock(audio_mutex);
3114 
3115     g_value_set_pointer(value,
3116 			g_list_copy_deep(audio->recall_container,
3117 					 (GCopyFunc) g_object_ref,
3118 					 NULL));
3119 
3120     g_rec_mutex_unlock(audio_mutex);
3121   }
3122   break;
3123   case PROP_PLAY:
3124   {
3125     GRecMutex *play_mutex;
3126 
3127     /* get play mutex */
3128     play_mutex = AGS_AUDIO_GET_PLAY_MUTEX(audio);
3129 
3130     /*  */
3131     g_rec_mutex_lock(play_mutex);
3132 
3133     g_value_set_pointer(value,
3134 			g_list_copy_deep(audio->play,
3135 					 (GCopyFunc) g_object_ref,
3136 					 NULL));
3137 
3138     g_rec_mutex_unlock(play_mutex);
3139   }
3140   break;
3141   case PROP_RECALL:
3142   {
3143     GRecMutex *recall_mutex;
3144 
3145     /* get recall mutex */
3146     recall_mutex = AGS_AUDIO_GET_RECALL_MUTEX(audio);
3147 
3148     /*  */
3149     g_rec_mutex_lock(recall_mutex);
3150 
3151     g_value_set_pointer(value,
3152 			g_list_copy_deep(audio->recall,
3153 					 (GCopyFunc) g_object_ref,
3154 					 NULL));
3155 
3156     g_rec_mutex_unlock(recall_mutex);
3157   }
3158   break;
3159   default:
3160     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
3161   }
3162 }
3163 
3164 void
ags_audio_dispose(GObject * gobject)3165 ags_audio_dispose(GObject *gobject)
3166 {
3167   AgsAudio *audio;
3168 
3169   GList *start_list, *list, *list_next;
3170 
3171   GRecMutex *play_mutex;
3172   GRecMutex *recall_mutex;
3173 
3174   audio = AGS_AUDIO(gobject);
3175 
3176   ags_connectable_disconnect(AGS_CONNECTABLE(audio));
3177 
3178   /* soundcard */
3179   if(audio->output_soundcard != NULL){
3180     gpointer tmp;
3181 
3182     tmp = audio->output_soundcard;
3183 
3184     audio->output_soundcard = NULL;
3185 
3186     g_object_unref(tmp);
3187   }
3188 
3189   if(audio->input_soundcard != NULL){
3190     gpointer tmp;
3191 
3192     tmp = audio->input_soundcard;
3193 
3194     audio->input_soundcard = NULL;
3195 
3196     g_object_unref(tmp);
3197   }
3198 
3199   /* sequencer */
3200   if(audio->output_sequencer != NULL){
3201     gpointer tmp;
3202 
3203     tmp = audio->output_sequencer;
3204 
3205     audio->output_sequencer = NULL;
3206 
3207     g_object_unref(tmp);
3208   }
3209 
3210   if(audio->input_sequencer != NULL){
3211     gpointer tmp;
3212 
3213     tmp = audio->input_sequencer;
3214 
3215     audio->input_sequencer = NULL;
3216 
3217     g_object_unref(tmp);
3218   }
3219 
3220   /* channels */
3221   ags_audio_set_audio_channels(audio,
3222 			       0, 0);
3223 
3224   ags_audio_set_pads(audio,
3225 		     AGS_TYPE_INPUT,
3226 		     0, 0);
3227   ags_audio_set_pads(audio,
3228 		     AGS_TYPE_OUTPUT,
3229 		     0, 0);
3230 
3231   /* preset */
3232   if(audio->preset != NULL){
3233     list =
3234       start_list = audio->preset;
3235 
3236     audio->preset = NULL;
3237 
3238     while(list != NULL){
3239       list_next = list->next;
3240 
3241       g_object_run_dispose(list->data);
3242 
3243       list = list_next;
3244     }
3245 
3246     g_list_free_full(start_list,
3247 		     g_object_unref);
3248   }
3249 
3250   /* synth generator */
3251   if(audio->synth_generator != NULL){
3252     list =
3253       start_list = audio->synth_generator;
3254 
3255     audio->synth_generator = NULL;
3256 
3257     while(list != NULL){
3258       list_next = list->next;
3259 
3260       g_object_run_dispose(list->data);
3261 
3262       list = list_next;
3263     }
3264 
3265     g_list_free_full(start_list,
3266 		     g_object_unref);
3267   }
3268 
3269   /* sf2 synth generator */
3270   if(audio->sf2_synth_generator != NULL){
3271     list =
3272       start_list = audio->sf2_synth_generator;
3273 
3274     audio->sf2_synth_generator = NULL;
3275 
3276     while(list != NULL){
3277       list_next = list->next;
3278 
3279       g_object_run_dispose(list->data);
3280 
3281       list = list_next;
3282     }
3283 
3284     g_list_free_full(start_list,
3285 		     g_object_unref);
3286   }
3287 
3288   /* sfz synth generator */
3289   if(audio->sfz_synth_generator != NULL){
3290     list =
3291       start_list = audio->sfz_synth_generator;
3292 
3293     audio->sfz_synth_generator = NULL;
3294 
3295     while(list != NULL){
3296       list_next = list->next;
3297 
3298       g_object_run_dispose(list->data);
3299 
3300       list = list_next;
3301     }
3302 
3303     g_list_free_full(start_list,
3304 		     g_object_unref);
3305   }
3306 
3307   /* playback domain */
3308   if(audio->playback_domain != NULL){
3309     AgsPlaybackDomain *playback_domain;
3310 
3311     playback_domain = audio->playback_domain;
3312 
3313     audio->playback_domain = NULL;
3314 
3315     g_object_run_dispose(playback_domain);
3316   }
3317 
3318   /* notation */
3319   if(audio->notation != NULL){
3320     list =
3321       start_list = audio->notation;
3322 
3323     audio->notation = NULL;
3324 
3325     while(list != NULL){
3326       list_next = list->next;
3327 
3328       g_object_run_dispose(list->data);
3329 
3330       list = list_next;
3331     }
3332 
3333     g_list_free_full(start_list,
3334 		     g_object_unref);
3335   }
3336 
3337   /* automation */
3338   if(audio->automation != NULL){
3339     list =
3340       start_list = audio->automation;
3341 
3342     audio->automation = NULL;
3343 
3344     while(list != NULL){
3345       list_next = list->next;
3346 
3347       g_object_run_dispose(list->data);
3348 
3349       list = list_next;
3350     }
3351 
3352     g_list_free_full(start_list,
3353 		     g_object_unref);
3354   }
3355 
3356   /* wave */
3357   if(audio->wave != NULL){
3358     list =
3359       start_list = audio->wave;
3360 
3361     audio->wave = NULL;
3362 
3363     while(list != NULL){
3364       list_next = list->next;
3365 
3366       g_object_run_dispose(list->data);
3367 
3368       list = list_next;
3369     }
3370 
3371     g_list_free_full(start_list,
3372 		     g_object_unref);
3373   }
3374 
3375   /* output audio file */
3376   if(audio->output_audio_file != NULL){
3377     gpointer tmp;
3378 
3379     tmp = audio->output_audio_file;
3380 
3381     audio->output_audio_file = NULL;
3382 
3383     g_object_unref(tmp);
3384   }
3385 
3386   /* input audio file */
3387   if(audio->input_audio_file != NULL){
3388     gpointer tmp;
3389 
3390     tmp = audio->input_audio_file;
3391 
3392     audio->input_audio_file = NULL;
3393 
3394     g_object_unref(tmp);
3395   }
3396 
3397   /* midi */
3398   if(audio->midi != NULL){
3399     list =
3400       start_list = audio->midi;
3401 
3402     audio->midi = NULL;
3403 
3404     while(list != NULL){
3405       list_next = list->next;
3406 
3407       g_object_run_dispose(list->data);
3408 
3409       list = list_next;
3410     }
3411 
3412     g_list_free_full(start_list,
3413 		     g_object_unref);
3414   }
3415 
3416   /* output midi file */
3417   if(audio->output_midi_file != NULL){
3418     gpointer tmp;
3419 
3420     tmp = audio->output_midi_file;
3421 
3422     audio->output_midi_file = NULL;
3423 
3424     g_object_unref(tmp);
3425   }
3426 
3427   /* input midi file */
3428   if(audio->input_midi_file != NULL){
3429     gpointer tmp;
3430 
3431     tmp = audio->input_midi_file;
3432 
3433     audio->input_midi_file = NULL;
3434 
3435     g_object_unref(tmp);
3436   }
3437 
3438   /* recall id */
3439   if(audio->recall_id != NULL){
3440     list =
3441       start_list = audio->recall_id;
3442 
3443     audio->recall_id = NULL;
3444 
3445     while(list != NULL){
3446       list_next = list->next;
3447 
3448       g_object_run_dispose(list->data);
3449 
3450       list = list_next;
3451     }
3452 
3453     g_list_free_full(start_list,
3454 		     g_object_unref);
3455   }
3456 
3457   /* recycling context */
3458   if(audio->recycling_context != NULL){
3459     list =
3460       start_list = audio->recycling_context;
3461 
3462     audio->recycling_context = NULL;
3463 
3464     while(list != NULL){
3465       list_next = list->next;
3466 
3467       g_object_run_dispose(list->data);
3468 
3469       list = list_next;
3470     }
3471 
3472     g_list_free_full(start_list,
3473 		     g_object_unref);
3474   }
3475 
3476   /* recall container */
3477   if(audio->recall_container != NULL){
3478     list =
3479       start_list = audio->recall_container;
3480 
3481     audio->recall_container = NULL;
3482 
3483     while(list != NULL){
3484       list_next = list->next;
3485 
3486       g_object_run_dispose(list->data);
3487 
3488       list = list_next;
3489     }
3490 
3491     g_list_free_full(start_list,
3492 		     g_object_unref);
3493   }
3494 
3495   /* play */
3496   if(audio->play != NULL){
3497     play_mutex = AGS_AUDIO_GET_PLAY_MUTEX(audio);
3498 
3499     /* run dispose and unref */
3500     g_rec_mutex_lock(play_mutex);
3501 
3502     list =
3503       start_list = audio->play;
3504 
3505     audio->play = NULL;
3506 
3507     g_rec_mutex_unlock(play_mutex);
3508 
3509     while(list != NULL){
3510       list_next = list->next;
3511 
3512       g_object_run_dispose(list->data);
3513 
3514       list = list_next;
3515     }
3516 
3517     g_list_free_full(start_list,
3518 		     g_object_unref);
3519   }
3520 
3521   /* recall */
3522   if(audio->recall != NULL){
3523     recall_mutex = AGS_AUDIO_GET_RECALL_MUTEX(audio);
3524 
3525     /* run dispose and unref */
3526     g_rec_mutex_lock(recall_mutex);
3527 
3528     list =
3529       start_list = audio->recall;
3530 
3531     audio->recall = NULL;
3532 
3533     while(list != NULL){
3534       list_next = list->next;
3535 
3536       g_object_run_dispose(list->data);
3537 
3538       list = list_next;
3539     }
3540 
3541     g_list_free_full(start_list,
3542 		     g_object_unref);
3543 
3544     g_rec_mutex_unlock(recall_mutex);
3545   }
3546 
3547   /* call parent */
3548   G_OBJECT_CLASS(ags_audio_parent_class)->dispose(gobject);
3549 }
3550 
3551 void
ags_audio_finalize(GObject * gobject)3552 ags_audio_finalize(GObject *gobject)
3553 {
3554   AgsAudio *audio;
3555   AgsChannel *channel;
3556 
3557   GList *start_list, *list, *list_next;
3558 
3559   GRecMutex *play_mutex;
3560   GRecMutex *recall_mutex;
3561 
3562   audio = AGS_AUDIO(gobject);
3563 
3564   ags_uuid_free(audio->uuid);
3565 
3566   g_free(audio->audio_name);
3567 
3568   /* soundcard */
3569   if(audio->output_soundcard != NULL){
3570     gpointer tmp;
3571 
3572     tmp = audio->output_soundcard;
3573 
3574     audio->output_soundcard = NULL;
3575 
3576     g_object_unref(tmp);
3577   }
3578 
3579   if(audio->input_soundcard != NULL){
3580     gpointer tmp;
3581 
3582     tmp = audio->input_soundcard;
3583 
3584     audio->input_soundcard = NULL;
3585 
3586     g_object_unref(tmp);
3587   }
3588 
3589   /* sequencer */
3590   if(audio->output_sequencer != NULL){
3591     gpointer tmp;
3592 
3593     tmp = audio->output_sequencer;
3594 
3595     audio->output_sequencer = NULL;
3596 
3597     g_object_unref(tmp);
3598   }
3599 
3600   if(audio->input_sequencer != NULL){
3601     gpointer tmp;
3602 
3603     tmp = audio->input_sequencer;
3604 
3605     audio->input_sequencer = NULL;
3606 
3607     g_object_unref(tmp);
3608   }
3609 
3610   /* channels */
3611   ags_audio_set_audio_channels(audio,
3612 			       0, 0);
3613 
3614   ags_audio_set_pads(audio,
3615 		     AGS_TYPE_INPUT,
3616 		     0, 0);
3617   ags_audio_set_pads(audio,
3618 		     AGS_TYPE_OUTPUT,
3619 		     0, 0);
3620 
3621   /* preset */
3622   if(audio->preset != NULL){
3623     list =
3624       start_list = audio->preset;
3625 
3626     audio->preset = NULL;
3627 
3628     while(list != NULL){
3629       list_next = list->next;
3630 
3631       g_object_run_dispose(list->data);
3632 
3633       list = list_next;
3634     }
3635 
3636     g_list_free_full(start_list,
3637 		     g_object_unref);
3638   }
3639 
3640   /* synth generator */
3641   if(audio->synth_generator != NULL){
3642     list =
3643       start_list = audio->synth_generator;
3644 
3645     audio->synth_generator = NULL;
3646 
3647     while(list != NULL){
3648       list_next = list->next;
3649 
3650       g_object_run_dispose(list->data);
3651 
3652       list = list_next;
3653     }
3654 
3655     g_list_free_full(start_list,
3656 		     g_object_unref);
3657   }
3658 
3659   /* sf2 synth generator */
3660   if(audio->sf2_synth_generator != NULL){
3661     list =
3662       start_list = audio->sf2_synth_generator;
3663 
3664     audio->sf2_synth_generator = NULL;
3665 
3666     while(list != NULL){
3667       list_next = list->next;
3668 
3669       g_object_run_dispose(list->data);
3670 
3671       list = list_next;
3672     }
3673 
3674     g_list_free_full(start_list,
3675 		     g_object_unref);
3676   }
3677 
3678   /* sfz synth generator */
3679   if(audio->sfz_synth_generator != NULL){
3680     list =
3681       start_list = audio->sfz_synth_generator;
3682 
3683     audio->sfz_synth_generator = NULL;
3684 
3685     while(list != NULL){
3686       list_next = list->next;
3687 
3688       g_object_run_dispose(list->data);
3689 
3690       list = list_next;
3691     }
3692 
3693     g_list_free_full(start_list,
3694 		     g_object_unref);
3695   }
3696 
3697   /* playback domain */
3698   if(audio->playback_domain != NULL){
3699     AgsPlaybackDomain *playback_domain;
3700 
3701     playback_domain = audio->playback_domain;
3702 
3703     audio->playback_domain = NULL;
3704 
3705     g_object_run_dispose(playback_domain);
3706   }
3707 
3708   /* notation */
3709   if(audio->notation != NULL){
3710     list =
3711       start_list = audio->notation;
3712 
3713     audio->notation = NULL;
3714 
3715     while(list != NULL){
3716       list_next = list->next;
3717 
3718       g_object_run_dispose(list->data);
3719 
3720       list = list_next;
3721     }
3722 
3723     g_list_free_full(start_list,
3724 		     g_object_unref);
3725   }
3726 
3727   /* automation */
3728   if(audio->automation != NULL){
3729     list =
3730       start_list = audio->automation;
3731 
3732     audio->automation = NULL;
3733 
3734     while(list != NULL){
3735       list_next = list->next;
3736 
3737       g_object_run_dispose(list->data);
3738 
3739       list = list_next;
3740     }
3741 
3742     g_list_free_full(start_list,
3743 		     g_object_unref);
3744   }
3745 
3746   /* wave */
3747   if(audio->wave != NULL){
3748     list =
3749       start_list = audio->wave;
3750 
3751     audio->wave = NULL;
3752 
3753     while(list != NULL){
3754       list_next = list->next;
3755 
3756       g_object_run_dispose(list->data);
3757 
3758       list = list_next;
3759     }
3760 
3761     g_list_free_full(start_list,
3762 		     g_object_unref);
3763   }
3764 
3765   /* output audio file */
3766   if(audio->output_audio_file != NULL){
3767     gpointer tmp;
3768 
3769     tmp = audio->output_audio_file;
3770 
3771     audio->output_audio_file = NULL;
3772 
3773     g_object_unref(tmp);
3774   }
3775 
3776   /* input audio file */
3777   if(audio->input_audio_file != NULL){
3778     gpointer tmp;
3779 
3780     tmp = audio->input_audio_file;
3781 
3782     audio->input_audio_file = NULL;
3783 
3784     g_object_unref(tmp);
3785   }
3786 
3787   /* midi */
3788   if(audio->midi != NULL){
3789     list =
3790       start_list = audio->midi;
3791 
3792     audio->midi = NULL;
3793 
3794     while(list != NULL){
3795       list_next = list->next;
3796 
3797       g_object_run_dispose(list->data);
3798 
3799       list = list_next;
3800     }
3801 
3802     g_list_free_full(start_list,
3803 		     g_object_unref);
3804   }
3805 
3806   /* output midi file */
3807   if(audio->output_midi_file != NULL){
3808     gpointer tmp;
3809 
3810     tmp = audio->output_midi_file;
3811 
3812     audio->output_midi_file = NULL;
3813 
3814     g_object_unref(tmp);
3815   }
3816 
3817   /* input midi file */
3818   if(audio->input_midi_file != NULL){
3819     gpointer tmp;
3820 
3821     tmp = audio->input_midi_file;
3822 
3823     audio->input_midi_file = NULL;
3824 
3825     g_object_unref(tmp);
3826   }
3827 
3828   /* recall id */
3829   if(audio->recall_id != NULL){
3830     list =
3831       start_list = audio->recall_id;
3832 
3833     audio->recall_id = NULL;
3834 
3835     while(list != NULL){
3836       list_next = list->next;
3837 
3838       g_object_run_dispose(list->data);
3839 
3840       list = list_next;
3841     }
3842 
3843     g_list_free_full(start_list,
3844 		     g_object_unref);
3845   }
3846 
3847   /* recycling context */
3848   if(audio->recycling_context != NULL){
3849     list =
3850       start_list = audio->recycling_context;
3851 
3852     audio->recycling_context = NULL;
3853 
3854     while(list != NULL){
3855       list_next = list->next;
3856 
3857       g_object_run_dispose(list->data);
3858 
3859       list = list_next;
3860     }
3861 
3862     g_list_free_full(start_list,
3863 		     g_object_unref);
3864   }
3865 
3866   /* recall container */
3867   if(audio->recall_container != NULL){
3868     list =
3869       start_list = audio->recall_container;
3870 
3871     audio->recall_container = NULL;
3872 
3873     while(list != NULL){
3874       list_next = list->next;
3875 
3876       g_object_run_dispose(list->data);
3877 
3878       list = list_next;
3879     }
3880 
3881     g_list_free_full(start_list,
3882 		     g_object_unref);
3883   }
3884 
3885   /* play */
3886   if(audio->play != NULL){
3887     play_mutex = AGS_AUDIO_GET_PLAY_MUTEX(audio);
3888 
3889     /* run dispose and unref */
3890     g_rec_mutex_lock(play_mutex);
3891 
3892     list =
3893       start_list = audio->play;
3894 
3895     audio->play = NULL;
3896 
3897     g_rec_mutex_unlock(play_mutex);
3898 
3899     while(list != NULL){
3900       list_next = list->next;
3901 
3902       g_object_run_dispose(list->data);
3903 
3904       list = list_next;
3905     }
3906 
3907     g_list_free_full(start_list,
3908 		     g_object_unref);
3909   }
3910 
3911   /* recall */
3912   if(audio->recall != NULL){
3913     recall_mutex = AGS_AUDIO_GET_RECALL_MUTEX(audio);
3914 
3915     /* run dispose and unref */
3916     g_rec_mutex_lock(recall_mutex);
3917 
3918     list =
3919       start_list = audio->recall;
3920 
3921     audio->recall = NULL;
3922 
3923     while(list != NULL){
3924       list_next = list->next;
3925 
3926       g_object_run_dispose(list->data);
3927 
3928       list = list_next;
3929     }
3930 
3931     g_list_free_full(start_list,
3932 		     g_object_unref);
3933 
3934     g_rec_mutex_unlock(recall_mutex);
3935   }
3936 
3937   /* call parent */
3938   G_OBJECT_CLASS(ags_audio_parent_class)->finalize(gobject);
3939 }
3940 
3941 AgsUUID*
ags_audio_get_uuid(AgsConnectable * connectable)3942 ags_audio_get_uuid(AgsConnectable *connectable)
3943 {
3944   AgsAudio *audio;
3945 
3946   AgsUUID *ptr;
3947 
3948   GRecMutex *audio_mutex;
3949 
3950   audio = AGS_AUDIO(connectable);
3951 
3952   /* get audio mutex */
3953   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
3954 
3955   /* get UUID */
3956   g_rec_mutex_lock(audio_mutex);
3957 
3958   ptr = audio->uuid;
3959 
3960   g_rec_mutex_unlock(audio_mutex);
3961 
3962   return(ptr);
3963 }
3964 
3965 gboolean
ags_audio_has_resource(AgsConnectable * connectable)3966 ags_audio_has_resource(AgsConnectable *connectable)
3967 {
3968   return(TRUE);
3969 }
3970 
3971 gboolean
ags_audio_is_ready(AgsConnectable * connectable)3972 ags_audio_is_ready(AgsConnectable *connectable)
3973 {
3974   AgsAudio *audio;
3975 
3976   gboolean is_ready;
3977 
3978   audio = AGS_AUDIO(connectable);
3979 
3980   /* check is added */
3981   is_ready = ags_audio_test_flags(audio, AGS_AUDIO_ADDED_TO_REGISTRY);
3982 
3983   return(is_ready);
3984 }
3985 
3986 void
ags_audio_add_to_registry(AgsConnectable * connectable)3987 ags_audio_add_to_registry(AgsConnectable *connectable)
3988 {
3989   AgsAudio *audio;
3990   AgsChannel *channel;
3991 
3992   AgsRegistry *registry;
3993   AgsRegistryEntry *entry;
3994 
3995   AgsApplicationContext *application_context;
3996 
3997   GList *list;
3998 
3999   if(ags_connectable_is_ready(connectable)){
4000     return;
4001   }
4002 
4003   audio = AGS_AUDIO(connectable);
4004 
4005   ags_audio_set_flags(audio, AGS_AUDIO_ADDED_TO_REGISTRY);
4006 
4007   application_context = ags_application_context_get_instance();
4008 
4009   registry = (AgsRegistry *) ags_service_provider_get_registry(AGS_SERVICE_PROVIDER(application_context));
4010 
4011   if(registry != NULL){
4012     entry = ags_registry_entry_alloc(registry);
4013 
4014     entry->id = audio->uuid;
4015     g_value_set_object(entry->entry,
4016 		       (gpointer) audio);
4017 
4018     ags_registry_add_entry(registry,
4019 			   entry);
4020   }
4021 
4022   /* add play */
4023   list = audio->play;
4024 
4025   while(list != NULL){
4026     ags_connectable_add_to_registry(AGS_CONNECTABLE(list->data));
4027 
4028     list = list->next;
4029   }
4030 
4031   /* add recall */
4032   list = audio->recall;
4033 
4034   while(list != NULL){
4035     ags_connectable_add_to_registry(AGS_CONNECTABLE(list->data));
4036 
4037     list = list->next;
4038   }
4039 
4040   /* add output */
4041   channel = audio->output;
4042 
4043   while(channel != NULL){
4044     ags_connectable_add_to_registry(AGS_CONNECTABLE(channel));
4045 
4046     channel = channel->next;
4047   }
4048 
4049   /* add input */
4050   channel = audio->input;
4051 
4052   while(channel != NULL){
4053     ags_connectable_add_to_registry(AGS_CONNECTABLE(channel));
4054 
4055     channel = channel->next;
4056   }
4057 }
4058 
4059 void
ags_audio_remove_from_registry(AgsConnectable * connectable)4060 ags_audio_remove_from_registry(AgsConnectable *connectable)
4061 {
4062   if(!ags_connectable_is_ready(connectable)){
4063     return;
4064   }
4065 
4066   //TODO:JK: implement me
4067 }
4068 
4069 xmlNode*
ags_audio_list_resource(AgsConnectable * connectable)4070 ags_audio_list_resource(AgsConnectable *connectable)
4071 {
4072   xmlNode *node;
4073 
4074   node = NULL;
4075 
4076   //TODO:JK: implement me
4077 
4078   return(node);
4079 }
4080 
4081 xmlNode*
ags_audio_xml_compose(AgsConnectable * connectable)4082 ags_audio_xml_compose(AgsConnectable *connectable)
4083 {
4084   xmlNode *node;
4085 
4086   node = NULL;
4087 
4088   //TODO:JK: implement me
4089 
4090   return(node);
4091 }
4092 
4093 void
ags_audio_xml_parse(AgsConnectable * connectable,xmlNode * node)4094 ags_audio_xml_parse(AgsConnectable *connectable,
4095 		    xmlNode *node)
4096 {
4097   //TODO:JK: implement me
4098 }
4099 
4100 gboolean
ags_audio_is_connected(AgsConnectable * connectable)4101 ags_audio_is_connected(AgsConnectable *connectable)
4102 {
4103   AgsAudio *audio;
4104 
4105   gboolean is_connected;
4106 
4107   audio = AGS_AUDIO(connectable);
4108 
4109   /* check is connected */
4110   is_connected = ags_audio_test_flags(audio, AGS_AUDIO_CONNECTED);
4111 
4112   return(is_connected);
4113 }
4114 
4115 void
ags_audio_connect(AgsConnectable * connectable)4116 ags_audio_connect(AgsConnectable *connectable)
4117 {
4118   AgsAudio *audio;
4119   AgsChannel *start_channel, *channel, *next_channel;
4120 
4121   GList *start_list, *list;
4122 
4123   if(ags_connectable_is_connected(connectable)){
4124     return;
4125   }
4126 
4127   audio = AGS_AUDIO(connectable);
4128 
4129   ags_audio_set_flags(audio, AGS_AUDIO_CONNECTED);
4130 
4131 #ifdef AGS_DEBUG
4132   g_message("connecting audio");
4133 #endif
4134 
4135   /* connect channels - output */
4136   g_object_get(audio,
4137 	       "output", &start_channel,
4138 	       NULL);
4139 
4140   if(start_channel != NULL){
4141     channel = start_channel;
4142     g_object_ref(channel);
4143 
4144     while(channel != NULL){
4145       /* connect */
4146       ags_connectable_connect(AGS_CONNECTABLE(channel));
4147 
4148       /* iterate */
4149       next_channel = ags_channel_next(channel);
4150 
4151       g_object_unref(channel);
4152 
4153       channel = next_channel;
4154     }
4155 
4156     g_object_unref(start_channel);
4157   }
4158 
4159   /* connect channels - input */
4160   g_object_get(audio,
4161 	       "input", &start_channel,
4162 	       NULL);
4163 
4164   if(start_channel != NULL){
4165     channel = start_channel;
4166     g_object_ref(channel);
4167 
4168     while(channel != NULL){
4169       /* connect */
4170       ags_connectable_connect(AGS_CONNECTABLE(channel));
4171 
4172       /* iterate */
4173       next_channel = ags_channel_next(channel);
4174 
4175       g_object_unref(channel);
4176 
4177       channel = next_channel;
4178     }
4179 
4180     g_object_unref(start_channel);
4181   }
4182 
4183   /* connect recall container */
4184   g_object_get(audio,
4185 	       "recall-container", &start_list,
4186 	       NULL);
4187 
4188   list = start_list;
4189 
4190   while(list != NULL){
4191     ags_connectable_connect(AGS_CONNECTABLE(list->data));
4192 
4193     list = list->next;
4194   }
4195 
4196   g_list_free_full(start_list,
4197 		   g_object_unref);
4198 
4199   /* connect recall - play context */
4200   g_object_get(audio,
4201 	       "play", &start_list,
4202 	       NULL);
4203 
4204   list = start_list;
4205 
4206   while(list != NULL){
4207     ags_connectable_connect(AGS_CONNECTABLE(list->data));
4208 
4209     list = list->next;
4210   }
4211 
4212   g_list_free_full(start_list,
4213 		   g_object_unref);
4214 
4215   /* connect recall - recall context */
4216   g_object_get(audio,
4217 	       "recall", &start_list,
4218 	       NULL);
4219 
4220   list = start_list;
4221 
4222   while(list != NULL){
4223     ags_connectable_connect(AGS_CONNECTABLE(list->data));
4224 
4225     list = list->next;
4226   }
4227 
4228   g_list_free_full(start_list,
4229 		   g_object_unref);
4230 }
4231 
4232 void
ags_audio_disconnect(AgsConnectable * connectable)4233 ags_audio_disconnect(AgsConnectable *connectable)
4234 {
4235   AgsAudio *audio;
4236   AgsChannel *start_channel, *channel, *next_channel;
4237 
4238   GList *start_list, *list;
4239 
4240   if(!ags_connectable_is_connected(connectable)){
4241     return;
4242   }
4243 
4244   audio = AGS_AUDIO(connectable);
4245 
4246   ags_audio_unset_flags(audio, AGS_AUDIO_CONNECTED);
4247 
4248 #ifdef AGS_DEBUG
4249   g_message("disconnecting audio");
4250 #endif
4251 
4252   /* disconnect channels - output */
4253   g_object_get(audio,
4254 	       "output", &start_channel,
4255 	       NULL);
4256 
4257   if(start_channel != NULL){
4258     channel = start_channel;
4259     g_object_ref(channel);
4260 
4261     while(channel != NULL){
4262       /* disconnect */
4263       ags_connectable_disconnect(AGS_CONNECTABLE(channel));
4264 
4265       /* iterate */
4266       next_channel = ags_channel_next(channel);
4267 
4268       g_object_unref(channel);
4269 
4270       channel = next_channel;
4271     }
4272 
4273     g_object_unref(start_channel);
4274   }
4275 
4276   /* disconnect channels - input */
4277   g_object_get(audio,
4278 	       "input", &start_channel,
4279 	       NULL);
4280 
4281   if(start_channel != NULL){
4282     channel = start_channel;
4283     g_object_ref(channel);
4284 
4285     while(channel != NULL){
4286       /* disconnect */
4287       ags_connectable_disconnect(AGS_CONNECTABLE(channel));
4288 
4289       /* iterate */
4290       next_channel = ags_channel_next(channel);
4291 
4292       g_object_unref(channel);
4293 
4294       channel = next_channel;
4295     }
4296 
4297     g_object_unref(start_channel);
4298   }
4299 
4300   /* disconnect recall container */
4301   g_object_get(audio,
4302 	       "recall-container", &start_list,
4303 	       NULL);
4304 
4305   list = start_list;
4306 
4307   while(list != NULL){
4308     ags_connectable_disconnect(AGS_CONNECTABLE(list->data));
4309 
4310     list = list->next;
4311   }
4312 
4313   g_list_free_full(start_list,
4314 		   g_object_unref);
4315 
4316   /* disconnect recall - play context */
4317   g_object_get(audio,
4318 	       "play", &start_list,
4319 	       NULL);
4320 
4321   list = start_list;
4322 
4323   while(list != NULL){
4324     ags_connectable_disconnect(AGS_CONNECTABLE(list->data));
4325 
4326     list = list->next;
4327   }
4328 
4329   g_list_free_full(start_list,
4330 		   g_object_unref);
4331 
4332   /* disconnect recall - recall context */
4333   g_object_get(audio,
4334 	       "recall", &start_list,
4335 	       NULL);
4336 
4337   list = start_list;
4338 
4339   while(list != NULL){
4340     ags_connectable_disconnect(AGS_CONNECTABLE(list->data));
4341 
4342     list = list->next;
4343   }
4344 
4345   g_list_free_full(start_list,
4346 		   g_object_unref);
4347 }
4348 
4349 /**
4350  * ags_audio_get_obj_mutex:
4351  * @audio: the #AgsAudio
4352  *
4353  * Get object mutex.
4354  *
4355  * Returns: the #GRecMutex to lock @audio
4356  *
4357  * Since: 3.1.0
4358  */
4359 GRecMutex*
ags_audio_get_obj_mutex(AgsAudio * audio)4360 ags_audio_get_obj_mutex(AgsAudio *audio)
4361 {
4362   if(!AGS_IS_AUDIO(audio)){
4363     return(NULL);
4364   }
4365 
4366   return(AGS_AUDIO_GET_OBJ_MUTEX(audio));
4367 }
4368 
4369 /**
4370  * ags_audio_get_play_mutex:
4371  * @audio: the #AgsAudio
4372  *
4373  * Get play mutex.
4374  *
4375  * Returns: the #GRecMutex to lock @audio's play property
4376  *
4377  * Since: 3.1.0
4378  */
4379 GRecMutex*
ags_audio_get_play_mutex(AgsAudio * audio)4380 ags_audio_get_play_mutex(AgsAudio *audio)
4381 {
4382   if(!AGS_IS_AUDIO(audio)){
4383     return(NULL);
4384   }
4385 
4386   return(AGS_AUDIO_GET_PLAY_MUTEX(audio));
4387 }
4388 
4389 /**
4390  * ags_audio_get_recall_mutex:
4391  * @audio: the #AgsAudio
4392  *
4393  * Get recall mutex.
4394  *
4395  * Returns: the #GRecMutex to lock @audio's recall property
4396  *
4397  * Since: 3.1.0
4398  */
4399 GRecMutex*
ags_audio_get_recall_mutex(AgsAudio * audio)4400 ags_audio_get_recall_mutex(AgsAudio *audio)
4401 {
4402   if(!AGS_IS_AUDIO(audio)){
4403     return(NULL);
4404   }
4405 
4406   return(AGS_AUDIO_GET_RECALL_MUTEX(audio));
4407 }
4408 
4409 /**
4410  * ags_audio_test_flags:
4411  * @audio: the #AgsAudio
4412  * @flags: the flags
4413  *
4414  * Test @flags to be set on @audio.
4415  *
4416  * Returns: %TRUE if flags are set, else %FALSE
4417  *
4418  * Since: 3.0.0
4419  */
4420 gboolean
ags_audio_test_flags(AgsAudio * audio,guint flags)4421 ags_audio_test_flags(AgsAudio *audio, guint flags)
4422 {
4423   gboolean retval;
4424 
4425   GRecMutex *audio_mutex;
4426 
4427   if(!AGS_IS_AUDIO(audio)){
4428     return(FALSE);
4429   }
4430 
4431   /* get audio mutex */
4432   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
4433 
4434   /* test */
4435   g_rec_mutex_lock(audio_mutex);
4436 
4437   retval = (flags & (audio->flags)) ? TRUE: FALSE;
4438 
4439   g_rec_mutex_unlock(audio_mutex);
4440 
4441   return(retval);
4442 }
4443 
4444 /**
4445  * ags_audio_set_flags:
4446  * @audio: the #AgsAudio
4447  * @flags: see enum AgsAudioFlags
4448  *
4449  * Enable a feature of #AgsAudio.
4450  *
4451  * Since: 3.0.0
4452  */
4453 void
ags_audio_set_flags(AgsAudio * audio,guint flags)4454 ags_audio_set_flags(AgsAudio *audio, guint flags)
4455 {
4456   guint audio_flags;
4457 
4458   GRecMutex *audio_mutex;
4459 
4460   if(!AGS_IS_AUDIO(audio)){
4461     return;
4462   }
4463 
4464   /* get audio mutex */
4465   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
4466 
4467   /* check flags */
4468   g_rec_mutex_lock(audio_mutex);
4469 
4470   audio_flags = audio->flags;
4471 
4472   g_rec_mutex_unlock(audio_mutex);
4473 
4474   if((AGS_AUDIO_NO_OUTPUT & flags) != 0 &&
4475      (AGS_AUDIO_NO_OUTPUT & audio_flags) == 0){
4476     ags_audio_set_pads(audio,
4477 		       AGS_TYPE_OUTPUT,
4478 		       0, 0);
4479   }
4480 
4481   if((AGS_AUDIO_NO_INPUT & flags) != 0 &&
4482      (AGS_AUDIO_NO_INPUT & audio_flags) == 0){
4483     ags_audio_set_pads(audio,
4484 		       AGS_TYPE_INPUT,
4485 		       0, 0);
4486   }
4487 
4488   if((AGS_AUDIO_OUTPUT_HAS_RECYCLING & (flags)) != 0 &&
4489      (AGS_AUDIO_OUTPUT_HAS_RECYCLING & (audio_flags)) == 0){
4490     AgsChannel *start_channel, *channel, *next_channel;
4491 
4492     g_object_get(audio,
4493 		 "output", &start_channel,
4494 		 NULL);
4495 
4496     if(start_channel != NULL){
4497       channel = start_channel;
4498       g_object_ref(channel);
4499 
4500       while(channel != NULL){
4501 	GObject *output_soundcard;
4502 
4503 	AgsRecycling *first_recycling, *last_recycling;
4504 
4505 	/* get some fields */
4506 	g_object_get(channel,
4507 		     "output-soundcard", &output_soundcard,
4508 		     NULL);
4509 
4510 	/* add recycling */
4511 	first_recycling =
4512 	  last_recycling = ags_recycling_new(output_soundcard);
4513 	g_object_ref(first_recycling);
4514 	g_object_set(first_recycling,
4515 		     "channel", channel,
4516 		     NULL);
4517 
4518 	ags_channel_reset_recycling(channel,
4519 				    first_recycling, last_recycling);
4520 
4521 	g_object_unref(output_soundcard);
4522 
4523 	/* iterate */
4524 	next_channel = ags_channel_next(channel);
4525 
4526 	g_object_unref(channel);
4527 
4528 	channel = next_channel;
4529       }
4530 
4531       g_object_unref(start_channel);
4532     }
4533   }
4534 
4535   if((AGS_AUDIO_INPUT_HAS_RECYCLING & (flags)) != 0 &&
4536      (AGS_AUDIO_INPUT_HAS_RECYCLING & (audio_flags)) == 0){
4537     AgsChannel *start_channel, *channel, *next_channel;
4538 
4539     g_object_get(audio,
4540 		 "input", &start_channel,
4541 		 NULL);
4542 
4543     if(start_channel != NULL){
4544       channel = start_channel;
4545       g_object_ref(channel);
4546 
4547       while(channel != NULL){
4548 	AgsRecycling *recycling;
4549 	AgsRecycling *first_recycling, *last_recycling;
4550 
4551 	GObject *output_soundcard;
4552 
4553 	/* get some fields */
4554 	g_object_get(channel,
4555 		     "output-soundcard", &output_soundcard,
4556 		     "first-recycling", &recycling,
4557 		     NULL);
4558 
4559 	/* add recycling */
4560 	if(recycling == NULL){
4561 	  first_recycling =
4562 	    last_recycling = ags_recycling_new(output_soundcard);
4563 	  g_object_ref(first_recycling);
4564 	  g_object_set(first_recycling,
4565 		       "channel", channel,
4566 		       NULL);
4567 
4568 	  ags_channel_reset_recycling(channel,
4569 				      first_recycling, last_recycling);
4570 	}else{
4571 	  g_object_unref(recycling);
4572 	}
4573 
4574 	g_object_unref(output_soundcard);
4575 
4576 	/* iterate */
4577 	next_channel = ags_channel_next(channel);
4578 
4579 	g_object_unref(channel);
4580 
4581 	channel = next_channel;
4582       }
4583 
4584       g_object_unref(start_channel);
4585     }
4586   }
4587 
4588   //TODO:JK: add more?
4589 
4590   /* set flags */
4591   g_rec_mutex_lock(audio_mutex);
4592 
4593   audio->flags |= flags;
4594 
4595   g_rec_mutex_unlock(audio_mutex);
4596 }
4597 
4598 /**
4599  * ags_audio_unset_flags:
4600  * @audio: the #AgsAudio
4601  * @flags: see enum AgsAudioFlags
4602  *
4603  * Disable a feature of AgsAudio.
4604  *
4605  * Since: 3.0.0
4606  */
4607 void
ags_audio_unset_flags(AgsAudio * audio,guint flags)4608 ags_audio_unset_flags(AgsAudio *audio, guint flags)
4609 {
4610   guint audio_flags;
4611 
4612   GRecMutex *audio_mutex;
4613 
4614   if(!AGS_IS_AUDIO(audio)){
4615     return;
4616   }
4617 
4618   /* get audio mutex */
4619   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
4620 
4621   /* check flags */
4622   g_rec_mutex_lock(audio_mutex);
4623 
4624   audio_flags = audio->flags;
4625 
4626   g_rec_mutex_unlock(audio_mutex);
4627 
4628   if((AGS_AUDIO_OUTPUT_HAS_RECYCLING & (audio_flags)) != 0 &&
4629      (AGS_AUDIO_OUTPUT_HAS_RECYCLING & (flags)) == 0){
4630     AgsChannel *start_channel, *channel, *next_channel;
4631 
4632     GRecMutex *channel_mutex;
4633 
4634     g_object_get(audio,
4635 		 "output", &start_channel,
4636 		 NULL);
4637 
4638     if(start_channel != NULL){
4639       channel = start_channel;
4640       g_object_ref(channel);
4641 
4642       while(channel != NULL){
4643 	AgsRecycling *first_recycling;
4644 
4645 	/* get channel mutex */
4646 	channel_mutex = AGS_CHANNEL_GET_OBJ_MUTEX(channel);
4647 
4648 	/* unset recycling */
4649 	g_rec_mutex_lock(channel_mutex);
4650 
4651 	first_recycling = channel->first_recycling;
4652 
4653 	channel->first_recycling =
4654 	  channel->last_recycling = NULL;
4655 
4656 	g_rec_mutex_unlock(channel_mutex);
4657 
4658 	/* remove recycling */
4659 	if(first_recycling != NULL){
4660 	  g_object_run_dispose((GObject *) first_recycling);
4661 	  g_object_unref(first_recycling);
4662 	}
4663 
4664 	ags_channel_reset_recycling(channel,
4665 				    NULL, NULL);
4666 
4667 	/* iterate */
4668 	next_channel = ags_channel_next(channel);
4669 
4670 	g_object_unref(channel);
4671 
4672 	channel = next_channel;
4673       }
4674 
4675       g_object_unref(start_channel);
4676     }
4677   }
4678 
4679   if((AGS_AUDIO_INPUT_HAS_RECYCLING & (audio_flags)) != 0 &&
4680      (AGS_AUDIO_INPUT_HAS_RECYCLING & (flags)) == 0){
4681     AgsChannel *start_channel, *channel, *next_channel;
4682     AgsChannel *link;
4683 
4684     GRecMutex *channel_mutex;
4685 
4686     g_object_get(audio,
4687 		 "input", &start_channel,
4688 		 NULL);
4689 
4690     if(start_channel != NULL){
4691       channel = start_channel;
4692       g_object_ref(channel);
4693 
4694       while(channel != NULL){
4695 	AgsRecycling *first_recycling;
4696 
4697 	/* get channel mutex */
4698 	channel_mutex = AGS_CHANNEL_GET_OBJ_MUTEX(channel);
4699 
4700 	/* get some fields */
4701 	g_rec_mutex_lock(channel_mutex);
4702 
4703 	link = channel->link;
4704 
4705 	g_rec_mutex_unlock(channel_mutex);
4706 
4707 	/* unset recycling */
4708 	if(link == NULL){
4709 	  g_rec_mutex_lock(channel_mutex);
4710 
4711 	  first_recycling = channel->first_recycling;
4712 
4713 	  channel->first_recycling =
4714 	    channel->last_recycling = NULL;
4715 
4716 	  g_rec_mutex_unlock(channel_mutex);
4717 
4718 	  /* remove recycling */
4719 	  if(first_recycling != NULL){
4720 	    g_object_run_dispose((GObject *) first_recycling);
4721 	    g_object_unref(first_recycling);
4722 	  }
4723 
4724 	  ags_channel_reset_recycling(channel,
4725 				      NULL, NULL);
4726 	}
4727 
4728 	/* iterate */
4729 	next_channel = ags_channel_next(channel);
4730 
4731 	g_object_unref(channel);
4732 
4733 	channel = next_channel;
4734       }
4735 
4736       g_object_unref(start_channel);
4737     }
4738   }
4739 
4740   //TODO:JK: add more?
4741 
4742   /* unset flags */
4743   g_rec_mutex_lock(audio_mutex);
4744 
4745   audio->flags &= (~flags);
4746 
4747   g_rec_mutex_unlock(audio_mutex);
4748 }
4749 
4750 /**
4751  * ags_audio_test_ability_flags:
4752  * @audio: the #AgsAudio
4753  * @ability_flags: the ability flags
4754  *
4755  * Test @ability_flags to be set on @audio.
4756  *
4757  * Returns: %TRUE if flags are set, else %FALSE
4758  *
4759  * Since: 3.0.0
4760  */
4761 gboolean
ags_audio_test_ability_flags(AgsAudio * audio,guint ability_flags)4762 ags_audio_test_ability_flags(AgsAudio *audio, guint ability_flags)
4763 {
4764   gboolean retval;
4765 
4766   GRecMutex *audio_mutex;
4767 
4768   if(!AGS_IS_AUDIO(audio)){
4769     return(FALSE);
4770   }
4771 
4772   /* get audio mutex */
4773   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
4774 
4775   /* test */
4776   g_rec_mutex_lock(audio_mutex);
4777 
4778   retval = (ability_flags & (audio->ability_flags)) ? TRUE: FALSE;
4779 
4780   g_rec_mutex_unlock(audio_mutex);
4781 
4782   return(retval);
4783 }
4784 
4785 void
ags_audio_set_ability_flags_channel(AgsChannel * start_channel,guint ability_flags)4786 ags_audio_set_ability_flags_channel(AgsChannel *start_channel, guint ability_flags)
4787 {
4788   AgsChannel *channel, *next_channel;
4789 
4790   if(!AGS_IS_CHANNEL(start_channel)){
4791     return;
4792   }
4793 
4794   channel = start_channel;
4795   g_object_ref(channel);
4796 
4797   while(channel != NULL){
4798     /* set ability flags */
4799     ags_channel_set_ability_flags(channel, ability_flags);
4800 
4801     /* iterate */
4802     next_channel = ags_channel_next(channel);
4803 
4804     g_object_unref(channel);
4805 
4806     channel = next_channel;
4807   }
4808 }
4809 
4810 /**
4811  * ags_audio_set_ability_flags:
4812  * @audio: the #AgsAudio
4813  * @ability_flags: see enum AgsSoundAbilityFlags
4814  *
4815  * Enable an ability of AgsAudio.
4816  *
4817  * Since: 3.0.0
4818  */
4819 void
ags_audio_set_ability_flags(AgsAudio * audio,guint ability_flags)4820 ags_audio_set_ability_flags(AgsAudio *audio, guint ability_flags)
4821 {
4822   AgsChannel *start_output, *start_input;
4823   AgsPlaybackDomain *playback_domain;
4824 
4825   AgsThread *main_loop;
4826   AgsAudioLoop *audio_loop;
4827 
4828   AgsApplicationContext *application_context;
4829 
4830   GObject *output_soundcard;
4831 
4832   guint samplerate, buffer_size;
4833   guint audio_ability_flags;
4834   gboolean super_threaded_audio;
4835 
4836   GRecMutex *audio_mutex;
4837 
4838   if(!AGS_IS_AUDIO(audio)){
4839     return;
4840   }
4841 
4842   application_context = ags_application_context_get_instance();
4843 
4844   /* get main loop */
4845   main_loop = ags_concurrency_provider_get_main_loop(AGS_CONCURRENCY_PROVIDER(application_context));
4846 
4847   /* get audio mutex */
4848   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
4849 
4850   /* check flags */
4851   g_rec_mutex_lock(audio_mutex);
4852 
4853   audio_ability_flags = audio->ability_flags;
4854 
4855   samplerate = audio->samplerate;
4856   buffer_size = audio->buffer_size;
4857 
4858   g_rec_mutex_unlock(audio_mutex);
4859 
4860   g_object_get(audio,
4861 	       "output-soundcard", &output_soundcard,
4862 	       "output", &start_output,
4863 	       "input", &start_input,
4864 	       "playback-domain", &playback_domain,
4865 	       NULL);
4866 
4867   /* get super-threaded flags */
4868   super_threaded_audio = ags_playback_domain_test_flags(playback_domain, AGS_PLAYBACK_DOMAIN_SUPER_THREADED_AUDIO);
4869 
4870   /* notation ability */
4871   if(super_threaded_audio){
4872     /* find audio loop */
4873     audio_loop = (AgsAudioLoop *) ags_thread_find_type(main_loop,
4874 						       AGS_TYPE_AUDIO_LOOP);
4875 
4876     /* playback ability */
4877     if((AGS_SOUND_ABILITY_PLAYBACK & (ability_flags)) != 0 &&
4878        (AGS_SOUND_ABILITY_PLAYBACK & (audio_ability_flags)) == 0){
4879       AgsAudioThread *audio_thread;
4880 
4881       audio_thread = ags_audio_thread_new(output_soundcard,
4882 					  (GObject *) audio);
4883       ags_audio_thread_set_sound_scope(audio_thread,
4884 				       AGS_SOUND_SCOPE_PLAYBACK);
4885 
4886       g_object_set(audio_thread,
4887 		   "frequency", ceil((gdouble) samplerate / (gdouble) buffer_size) + AGS_SOUNDCARD_DEFAULT_OVERCLOCK,
4888 		   NULL);
4889 
4890       ags_playback_domain_set_audio_thread(playback_domain,
4891 					   (AgsThread *) audio_thread,
4892 					   AGS_SOUND_SCOPE_PLAYBACK);
4893 
4894       /* set thread child */
4895       ags_thread_add_child_extended((AgsThread *) audio_loop,
4896 				    (AgsThread *) audio_thread,
4897 				    TRUE, TRUE);
4898     }
4899 
4900     /* sequencer ability */
4901     if((AGS_SOUND_ABILITY_SEQUENCER & (ability_flags)) != 0 &&
4902        (AGS_SOUND_ABILITY_SEQUENCER & (audio_ability_flags)) == 0){
4903       AgsAudioThread *audio_thread;
4904 
4905       audio_thread = ags_audio_thread_new(output_soundcard,
4906 					  (GObject *) audio);
4907       ags_audio_thread_set_sound_scope(audio_thread,
4908 				       AGS_SOUND_SCOPE_SEQUENCER);
4909 
4910       g_object_set(audio_thread,
4911 		   "frequency", ceil((gdouble) samplerate / (gdouble) buffer_size) + AGS_SOUNDCARD_DEFAULT_OVERCLOCK,
4912 		   NULL);
4913 
4914       ags_playback_domain_set_audio_thread(playback_domain,
4915 					   (AgsThread *) audio_thread,
4916 					   AGS_SOUND_SCOPE_SEQUENCER);
4917 
4918       /* set thread child */
4919       ags_thread_add_child_extended((AgsThread *) audio_loop,
4920 				    (AgsThread *) audio_thread,
4921 				    TRUE, TRUE);
4922     }
4923 
4924     /* notation ability */
4925     if((AGS_SOUND_ABILITY_NOTATION & (ability_flags)) != 0 &&
4926        (AGS_SOUND_ABILITY_NOTATION & (audio_ability_flags)) == 0){
4927       AgsAudioThread *audio_thread;
4928 
4929       audio_thread = ags_audio_thread_new(output_soundcard,
4930 					  (GObject *) audio);
4931       ags_audio_thread_set_sound_scope(audio_thread,
4932 				       AGS_SOUND_SCOPE_NOTATION);
4933 
4934       g_object_set(audio_thread,
4935 		   "frequency", ceil((gdouble) samplerate / (gdouble) buffer_size) + AGS_SOUNDCARD_DEFAULT_OVERCLOCK,
4936 		   NULL);
4937 
4938       ags_playback_domain_set_audio_thread(playback_domain,
4939 					   (AgsThread *) audio_thread,
4940 					   AGS_SOUND_SCOPE_NOTATION);
4941 
4942       /* set thread child */
4943       ags_thread_add_child_extended((AgsThread *) audio_loop,
4944 				    (AgsThread *) audio_thread,
4945 				    TRUE, TRUE);
4946     }
4947 
4948     /* wave ability */
4949     if((AGS_SOUND_ABILITY_WAVE & (ability_flags)) != 0 &&
4950        (AGS_SOUND_ABILITY_WAVE & (audio_ability_flags)) == 0){
4951       AgsAudioThread *audio_thread;
4952 
4953       audio_thread = ags_audio_thread_new(output_soundcard,
4954 					  (GObject *) audio);
4955       ags_audio_thread_set_sound_scope(audio_thread,
4956 				       AGS_SOUND_SCOPE_WAVE);
4957 
4958       g_object_set(audio_thread,
4959 		   "frequency", ceil((gdouble) samplerate / (gdouble) buffer_size) + AGS_SOUNDCARD_DEFAULT_OVERCLOCK,
4960 		   NULL);
4961 
4962       ags_playback_domain_set_audio_thread(playback_domain,
4963 					   (AgsThread *) audio_thread,
4964 					   AGS_SOUND_SCOPE_WAVE);
4965 
4966       /* set thread child */
4967       ags_thread_add_child_extended((AgsThread *) audio_loop,
4968 				    (AgsThread *) audio_thread,
4969 				    TRUE, TRUE);
4970     }
4971 
4972     /* midi ability */
4973     if((AGS_SOUND_ABILITY_MIDI & (ability_flags)) != 0 &&
4974        (AGS_SOUND_ABILITY_MIDI & (audio_ability_flags)) == 0){
4975       AgsAudioThread *audio_thread;
4976 
4977       audio_thread = ags_audio_thread_new(output_soundcard,
4978 					  (GObject *) audio);
4979       ags_audio_thread_set_sound_scope(audio_thread,
4980 				       AGS_SOUND_SCOPE_MIDI);
4981 
4982       g_object_set(audio_thread,
4983 		   "frequency", ceil((gdouble) samplerate / (gdouble) buffer_size) + AGS_SOUNDCARD_DEFAULT_OVERCLOCK,
4984 		   NULL);
4985 
4986       ags_playback_domain_set_audio_thread(playback_domain,
4987 					   (AgsThread *) audio_thread,
4988 					   AGS_SOUND_SCOPE_MIDI);
4989 
4990       /* set thread child */
4991       ags_thread_add_child_extended((AgsThread *) audio_loop,
4992 				    (AgsThread *) audio_thread,
4993 				    TRUE, TRUE);
4994     }
4995   }
4996 
4997   /* channel */
4998   ags_audio_set_ability_flags_channel(start_output, ability_flags);
4999   ags_audio_set_ability_flags_channel(start_input, ability_flags);
5000 
5001   /* set flags */
5002   g_rec_mutex_lock(audio_mutex);
5003 
5004   audio->ability_flags |= ability_flags;
5005 
5006   g_rec_mutex_unlock(audio_mutex);
5007 
5008   /* unref */
5009   if(main_loop != NULL){
5010     g_object_unref(main_loop);
5011   }
5012 
5013   if(output_soundcard != NULL) {
5014     g_object_unref(output_soundcard);
5015   }
5016 
5017   g_object_unref(playback_domain);
5018 
5019   if(start_output != NULL){
5020     g_object_unref(start_output);
5021   }
5022 
5023   if(start_input != NULL){
5024     g_object_unref(start_input);
5025   }
5026 }
5027 
5028 void
ags_audio_unset_ability_flags_channel(AgsChannel * start_channel,guint ability_flags)5029 ags_audio_unset_ability_flags_channel(AgsChannel *start_channel, guint ability_flags)
5030 {
5031   AgsChannel *channel, *next_channel;
5032 
5033   if(!AGS_IS_CHANNEL(start_channel)){
5034     return;
5035   }
5036 
5037   channel = start_channel;
5038   g_object_ref(channel);
5039 
5040   while(channel != NULL){
5041     /* set ability flags */
5042     ags_channel_unset_ability_flags(channel, ability_flags);
5043 
5044     /* iterate */
5045     next_channel = ags_channel_next(channel);
5046 
5047     g_object_unref(channel);
5048 
5049     channel = next_channel;
5050   }
5051 }
5052 
5053 /**
5054  * ags_audio_unset_ability_flags:
5055  * @audio: the #AgsAudio
5056  * @ability_flags: see enum AgsSoundAbilityFlags
5057  *
5058  * Disable an ability of AgsAudio.
5059  *
5060  * Since: 3.0.0
5061  */
5062 void
ags_audio_unset_ability_flags(AgsAudio * audio,guint ability_flags)5063 ags_audio_unset_ability_flags(AgsAudio *audio, guint ability_flags)
5064 {
5065   AgsChannel *start_output, *start_input;
5066   AgsPlaybackDomain *playback_domain;
5067 
5068   AgsThread *main_loop;
5069   AgsThread *audio_loop;
5070 
5071   AgsApplicationContext *application_context;
5072 
5073   guint audio_ability_flags;
5074 
5075   GRecMutex *audio_mutex;
5076 
5077   if(!AGS_IS_AUDIO(audio)){
5078     return;
5079   }
5080 
5081   application_context = ags_application_context_get_instance();
5082 
5083   /* get main loop */
5084   main_loop = ags_concurrency_provider_get_main_loop(AGS_CONCURRENCY_PROVIDER(application_context));
5085 
5086   /* get audio mutex */
5087   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
5088 
5089   /* check flags */
5090   g_rec_mutex_lock(audio_mutex);
5091 
5092   audio_ability_flags = audio->ability_flags;
5093 
5094   g_rec_mutex_unlock(audio_mutex);
5095 
5096   g_object_get(audio,
5097 	       "output", &start_output,
5098 	       "input", &start_input,
5099 	       "playback-domain", &playback_domain,
5100 	       NULL);
5101 
5102   /* find audio loop */
5103   audio_loop = ags_thread_find_type(main_loop,
5104 				    AGS_TYPE_AUDIO_LOOP);
5105 
5106   /* playback ability */
5107   if((AGS_SOUND_ABILITY_PLAYBACK & (ability_flags)) == 0 &&
5108      (AGS_SOUND_ABILITY_PLAYBACK & (audio_ability_flags)) != 0){
5109     AgsAudioThread *audio_thread;
5110 
5111     audio_thread = (AgsAudioThread *) ags_playback_domain_get_audio_thread(playback_domain,
5112 									   AGS_SOUND_SCOPE_PLAYBACK);
5113     ags_thread_remove_child(audio_loop,
5114 			    (AgsThread *) audio_thread);
5115 
5116     ags_playback_domain_set_audio_thread(playback_domain,
5117 					 NULL,
5118 					 AGS_SOUND_SCOPE_PLAYBACK);
5119   }
5120 
5121   /* notation ability */
5122   if((AGS_SOUND_ABILITY_NOTATION & (ability_flags)) == 0 &&
5123      (AGS_SOUND_ABILITY_NOTATION & (audio_ability_flags)) != 0){
5124     AgsAudioThread *audio_thread;
5125 
5126     audio_thread = (AgsAudioThread *) ags_playback_domain_get_audio_thread(playback_domain,
5127 									   AGS_SOUND_SCOPE_NOTATION);
5128     ags_thread_remove_child(audio_loop,
5129 			    (AgsThread *) audio_thread);
5130 
5131     ags_playback_domain_set_audio_thread(playback_domain,
5132 					 NULL,
5133 					 AGS_SOUND_SCOPE_NOTATION);
5134   }
5135 
5136   /* sequencer ability */
5137   if((AGS_SOUND_ABILITY_SEQUENCER & (ability_flags)) == 0 &&
5138      (AGS_SOUND_ABILITY_SEQUENCER & (audio_ability_flags)) != 0){
5139     AgsAudioThread *audio_thread;
5140 
5141     audio_thread = (AgsAudioThread *) ags_playback_domain_get_audio_thread(playback_domain,
5142 									   AGS_SOUND_SCOPE_SEQUENCER);
5143     ags_thread_remove_child(audio_loop,
5144 			    (AgsThread *) audio_thread);
5145 
5146     ags_playback_domain_set_audio_thread(playback_domain,
5147 					 NULL,
5148 					 AGS_SOUND_SCOPE_SEQUENCER);
5149   }
5150 
5151   /* wave ability */
5152   if((AGS_SOUND_ABILITY_WAVE & (ability_flags)) == 0 &&
5153      (AGS_SOUND_ABILITY_WAVE & (audio_ability_flags)) != 0){
5154     AgsAudioThread *audio_thread;
5155 
5156     audio_thread = (AgsAudioThread *) ags_playback_domain_get_audio_thread(playback_domain,
5157 									   AGS_SOUND_SCOPE_WAVE);
5158     ags_thread_remove_child(audio_loop,
5159 			    (AgsThread *) audio_thread);
5160 
5161     ags_playback_domain_set_audio_thread(playback_domain,
5162 					 NULL,
5163 					 AGS_SOUND_SCOPE_WAVE);
5164   }
5165 
5166   /* midi ability */
5167   if((AGS_SOUND_ABILITY_MIDI & (ability_flags)) == 0 &&
5168      (AGS_SOUND_ABILITY_MIDI & (audio_ability_flags)) != 0){
5169     AgsAudioThread *audio_thread;
5170 
5171     audio_thread = (AgsAudioThread *) ags_playback_domain_get_audio_thread(playback_domain,
5172 									   AGS_SOUND_SCOPE_MIDI);
5173     ags_thread_remove_child(audio_loop,
5174 			    (AgsThread *) audio_thread);
5175 
5176     ags_playback_domain_set_audio_thread(playback_domain,
5177 					 NULL,
5178 					 AGS_SOUND_SCOPE_MIDI);
5179   }
5180 
5181   /* channel */
5182   ags_audio_unset_ability_flags_channel(start_output, ability_flags);
5183   ags_audio_unset_ability_flags_channel(start_input, ability_flags);
5184 
5185   /* unset flags */
5186   g_rec_mutex_lock(audio_mutex);
5187 
5188   audio->ability_flags &= (~ability_flags);
5189 
5190   g_rec_mutex_unlock(audio_mutex);
5191 
5192   /* unref */
5193   g_object_unref(main_loop);
5194 
5195   g_object_unref(playback_domain);
5196 
5197   g_object_unref(start_output);
5198   g_object_unref(start_input);
5199 }
5200 
5201 /**
5202  * ags_audio_test_behaviour_flags:
5203  * @audio: the #AgsAudio
5204  * @behaviour_flags: the behaviour flags
5205  *
5206  * Test @behaviour_flags to be set on @audio.
5207  *
5208  * Returns: %TRUE if flags are set, else %FALSE
5209  *
5210  * Since: 3.0.0
5211  */
5212 gboolean
ags_audio_test_behaviour_flags(AgsAudio * audio,guint behaviour_flags)5213 ags_audio_test_behaviour_flags(AgsAudio *audio, guint behaviour_flags)
5214 {
5215   gboolean retval;
5216 
5217   GRecMutex *audio_mutex;
5218 
5219   if(!AGS_IS_AUDIO(audio)){
5220     return(FALSE);
5221   }
5222 
5223   /* get audio mutex */
5224   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
5225 
5226   /* test */
5227   g_rec_mutex_lock(audio_mutex);
5228 
5229   retval = (behaviour_flags & (audio->behaviour_flags)) ? TRUE: FALSE;
5230 
5231   g_rec_mutex_unlock(audio_mutex);
5232 
5233   return(retval);
5234 }
5235 
5236 /**
5237  * ags_audio_set_behaviour_flags:
5238  * @audio: the #AgsAudio
5239  * @behaviour_flags: the behaviour flags
5240  *
5241  * Set behaviour flags.
5242  *
5243  * Since: 3.0.0
5244  */
5245 void
ags_audio_set_behaviour_flags(AgsAudio * audio,guint behaviour_flags)5246 ags_audio_set_behaviour_flags(AgsAudio *audio, guint behaviour_flags)
5247 {
5248   GRecMutex *audio_mutex;
5249 
5250   if(!AGS_IS_AUDIO(audio)){
5251     return;
5252   }
5253 
5254   /* get audio mutex */
5255   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
5256 
5257   /* set flags */
5258   g_rec_mutex_lock(audio_mutex);
5259 
5260   audio->behaviour_flags |= behaviour_flags;
5261 
5262   g_rec_mutex_unlock(audio_mutex);
5263 }
5264 
5265 /**
5266  * ags_audio_unset_behaviour_flags:
5267  * @audio: the #AgsAudio
5268  * @behaviour_flags: the behaviour flags
5269  *
5270  * Unset behaviour flags.
5271  *
5272  * Since: 3.0.0
5273  */
5274 void
ags_audio_unset_behaviour_flags(AgsAudio * audio,guint behaviour_flags)5275 ags_audio_unset_behaviour_flags(AgsAudio *audio, guint behaviour_flags)
5276 {
5277   GRecMutex *audio_mutex;
5278 
5279   if(!AGS_IS_AUDIO(audio)){
5280     return;
5281   }
5282 
5283   /* get audio mutex */
5284   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
5285 
5286   /* unset flags */
5287   g_rec_mutex_lock(audio_mutex);
5288 
5289   audio->behaviour_flags &= (~behaviour_flags);
5290 
5291   g_rec_mutex_unlock(audio_mutex);
5292 }
5293 
5294 /**
5295  * ags_audio_test_staging_flags:
5296  * @audio: the #AgsAudio
5297  * @sound_scope: the #AgsSoundScope to test
5298  * @staging_flags: the staging flags
5299  *
5300  * Test @staging_flags to be set on @audio.
5301  *
5302  * Returns: %TRUE if flags are set, else %FALSE
5303  *
5304  * Since: 3.0.0
5305  */
5306 gboolean
ags_audio_test_staging_flags(AgsAudio * audio,gint sound_scope,guint staging_flags)5307 ags_audio_test_staging_flags(AgsAudio *audio, gint sound_scope,
5308 			     guint staging_flags)
5309 {
5310   gboolean retval;
5311 
5312   GRecMutex *audio_mutex;
5313 
5314   if(!AGS_IS_AUDIO(audio)){
5315     return(FALSE);
5316   }
5317 
5318   /* get audio mutex */
5319   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
5320 
5321   /* test */
5322   g_rec_mutex_lock(audio_mutex);
5323 
5324   retval = (staging_flags & (audio->staging_flags[sound_scope])) ? TRUE: FALSE;
5325 
5326   g_rec_mutex_unlock(audio_mutex);
5327 
5328   return(retval);
5329 }
5330 
5331 /**
5332  * ags_audio_set_staging_flags:
5333  * @audio: the #AgsAudio
5334  * @sound_scope: the #AgsSoundScope to apply, or -1 to apply to all
5335  * @staging_flags: the staging flags
5336  *
5337  * Set staging flags.
5338  *
5339  * Since: 3.0.0
5340  */
5341 void
ags_audio_set_staging_flags(AgsAudio * audio,gint sound_scope,guint staging_flags)5342 ags_audio_set_staging_flags(AgsAudio *audio, gint sound_scope,
5343 			    guint staging_flags)
5344 {
5345   guint i;
5346 
5347   GRecMutex *audio_mutex;
5348 
5349   if(!AGS_IS_AUDIO(audio)){
5350     return;
5351   }
5352 
5353   /* get audio mutex */
5354   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
5355 
5356   /* set flags */
5357   g_rec_mutex_lock(audio_mutex);
5358 
5359   if(sound_scope < 0){
5360     for(i = 0; i < AGS_SOUND_SCOPE_LAST; i++){
5361       audio->staging_flags[i] |= staging_flags;
5362     }
5363   }else if(sound_scope < AGS_SOUND_SCOPE_LAST){
5364     audio->staging_flags[sound_scope] |= staging_flags;
5365   }
5366 
5367   g_rec_mutex_unlock(audio_mutex);
5368 }
5369 
5370 /**
5371  * ags_audio_unset_staging_flags:
5372  * @audio: the #AgsAudio
5373  * @sound_scope: the #AgsSoundScope to apply, or -1 to apply to all
5374  * @staging_flags: the staging flags
5375  *
5376  * Unset staging flags.
5377  *
5378  * Since: 3.0.0
5379  */
5380 void
ags_audio_unset_staging_flags(AgsAudio * audio,gint sound_scope,guint staging_flags)5381 ags_audio_unset_staging_flags(AgsAudio *audio, gint sound_scope,
5382 			      guint staging_flags)
5383 {
5384   guint i;
5385 
5386   GRecMutex *audio_mutex;
5387 
5388   if(!AGS_IS_AUDIO(audio)){
5389     return;
5390   }
5391 
5392   /* get audio mutex */
5393   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
5394 
5395   /* unset flags */
5396   g_rec_mutex_lock(audio_mutex);
5397 
5398   if(sound_scope < 0){
5399     for(i = 0; i < AGS_SOUND_SCOPE_LAST; i++){
5400       audio->staging_flags[i] &= (~staging_flags);
5401     }
5402   }else if(sound_scope < AGS_SOUND_SCOPE_LAST){
5403     audio->staging_flags[sound_scope] &= (~staging_flags);
5404   }
5405 
5406   g_rec_mutex_unlock(audio_mutex);
5407 }
5408 
5409 /**
5410  * ags_audio_test_staging_completed:
5411  * @audio: the #AgsAudio
5412  * @sound_scope: the #AgsSoundScope to test
5413  *
5414  * Test @sound_scope to be completed on @audio.
5415  *
5416  * Returns: %TRUE if completed, otherwise %FALSE
5417  *
5418  * Since: 3.3.0
5419  */
5420 gboolean
ags_audio_test_staging_completed(AgsAudio * audio,gint sound_scope)5421 ags_audio_test_staging_completed(AgsAudio *audio, gint sound_scope)
5422 {
5423   guint i;
5424   gboolean success;
5425 
5426   GRecMutex *audio_mutex;
5427 
5428   if(!AGS_IS_AUDIO(audio)){
5429     return(FALSE);
5430   }
5431 
5432   /* get audio mutex */
5433   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
5434 
5435   /* test staging completed */
5436   success = FALSE;
5437 
5438   g_rec_mutex_lock(audio_mutex);
5439 
5440   if(sound_scope < 0){
5441     for(i = 0; i < AGS_SOUND_SCOPE_LAST; i++){
5442       if(!audio->staging_completed[i]){
5443 	break;
5444       }
5445     }
5446 
5447     if(i == AGS_SOUND_SCOPE_LAST){
5448       success = TRUE;
5449     }
5450   }else if(sound_scope < AGS_SOUND_SCOPE_LAST){
5451     success = audio->staging_completed[sound_scope];
5452   }
5453 
5454   g_rec_mutex_unlock(audio_mutex);
5455 
5456   return(success);
5457 }
5458 
5459 /**
5460  * ags_audio_set_staging_completed:
5461  * @audio: the #AgsAudio
5462  * @sound_scope: the #AgsSoundScope to apply, or -1 to apply to all
5463  *
5464  * Set @sound_scope to be completed.
5465  *
5466  * Since: 3.3.0
5467  */
5468 void
ags_audio_set_staging_completed(AgsAudio * audio,gint sound_scope)5469 ags_audio_set_staging_completed(AgsAudio *audio, gint sound_scope)
5470 {
5471   guint i;
5472 
5473   GRecMutex *audio_mutex;
5474 
5475   if(!AGS_IS_AUDIO(audio)){
5476     return;
5477   }
5478 
5479   /* get audio mutex */
5480   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
5481 
5482   /* test staging completed */
5483   g_rec_mutex_lock(audio_mutex);
5484 
5485   if(sound_scope < 0){
5486     for(i = 0; i < AGS_SOUND_SCOPE_LAST; i++){
5487       audio->staging_completed[i] = TRUE;
5488     }
5489   }else if(sound_scope < AGS_SOUND_SCOPE_LAST){
5490     audio->staging_completed[sound_scope] = TRUE;
5491   }
5492 
5493   g_rec_mutex_unlock(audio_mutex);
5494 }
5495 
5496 /**
5497  * ags_audio_unset_staging_completed:
5498  * @audio: the #AgsAudio
5499  * @sound_scope: the #AgsSoundScope to apply, or -1 to apply to all
5500  *
5501  * Unset @sound_scope to be completed.
5502  *
5503  * Since: 3.3.0
5504  */
5505 void
ags_audio_unset_staging_completed(AgsAudio * audio,gint sound_scope)5506 ags_audio_unset_staging_completed(AgsAudio *audio, gint sound_scope)
5507 {
5508   guint i;
5509 
5510   GRecMutex *audio_mutex;
5511 
5512   if(!AGS_IS_AUDIO(audio)){
5513     return;
5514   }
5515 
5516   /* get audio mutex */
5517   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
5518 
5519   /* test staging completed */
5520   g_rec_mutex_lock(audio_mutex);
5521 
5522   if(sound_scope < 0){
5523     for(i = 0; i < AGS_SOUND_SCOPE_LAST; i++){
5524       audio->staging_completed[i] = FALSE;
5525     }
5526   }else if(sound_scope < AGS_SOUND_SCOPE_LAST){
5527     audio->staging_completed[sound_scope] = FALSE;
5528   }
5529 
5530   g_rec_mutex_unlock(audio_mutex);
5531 }
5532 
5533 /**
5534  * ags_audio_get_audio_name:
5535  * @audio: the #AgsAudio
5536  *
5537  * Get audio name of @audio.
5538  *
5539  * Returns: the audio name
5540  *
5541  * Since: 3.1.0
5542  */
5543 gchar*
ags_audio_get_audio_name(AgsAudio * audio)5544 ags_audio_get_audio_name(AgsAudio *audio)
5545 {
5546   gchar *audio_name;
5547 
5548   if(!AGS_IS_AUDIO(audio)){
5549     return(NULL);
5550   }
5551 
5552   g_object_get(audio,
5553 	       "audio-name", &audio_name,
5554 	       NULL);
5555 
5556   return(audio_name);
5557 }
5558 
5559 /**
5560  * ags_audio_set_audio_name:
5561  * @audio: the #AgsAudio
5562  * @audio_name: the audio name
5563  *
5564  * Set audio name of @audio.
5565  *
5566  * Since: 3.1.0
5567  */
5568 void
ags_audio_set_audio_name(AgsAudio * audio,gchar * audio_name)5569 ags_audio_set_audio_name(AgsAudio *audio, gchar *audio_name)
5570 {
5571   if(!AGS_IS_AUDIO(audio)){
5572     return;
5573   }
5574 
5575   g_object_set(audio,
5576 	       "audio-name", audio_name,
5577 	       NULL);
5578 }
5579 
5580 /**
5581  * ags_audio_find_name:
5582  * @audio: (element-type AgsAudio.Audio) (transfer none): the #GList-struct containing #AgsAudio
5583  * @audio_name: the audio name to find
5584  *
5585  * Find @audio_name in @audio.
5586  *
5587  * Returns: (element-type AgsAudio.Audio) (transfer none): the next matching #GList-struct containing #AgsAudio
5588  *
5589  * Since: 3.0.0
5590  */
5591 GList*
ags_audio_find_name(GList * audio,gchar * audio_name)5592 ags_audio_find_name(GList *audio,
5593 		    gchar *audio_name)
5594 {
5595   if(audio == NULL ||
5596      audio_name == NULL){
5597     return(NULL);
5598   }
5599 
5600   while(audio != NULL){
5601     gboolean success;
5602 
5603     GRecMutex *audio_mutex;
5604 
5605     /* get audio mutex */
5606     audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio->data);
5607 
5608     /* match */
5609     g_rec_mutex_lock(audio_mutex);
5610 
5611     success = (AGS_AUDIO(audio->data)->audio_name != NULL &&
5612 	       !g_strcmp0(AGS_AUDIO(audio->data)->audio_name,
5613 			  audio_name)) ? TRUE: FALSE;
5614 
5615     g_rec_mutex_unlock(audio_mutex);
5616 
5617     if(success){
5618       return(audio);
5619     }
5620 
5621     audio = audio->next;
5622   }
5623 
5624   return(NULL);
5625 }
5626 
5627 /**
5628  * ags_audio_get_max_audio_channels:
5629  * @audio: the #AgsAudio
5630  *
5631  * Get maximum audio channels.
5632  *
5633  * Returns: the maximum audio channels
5634  *
5635  * Since: 3.1.0
5636  */
5637 guint
ags_audio_get_max_audio_channels(AgsAudio * audio)5638 ags_audio_get_max_audio_channels(AgsAudio *audio)
5639 {
5640   guint max_audio_channels;
5641 
5642   if(!AGS_IS_AUDIO(audio)){
5643     return(0);
5644   }
5645 
5646   g_object_get(audio,
5647 	       "max-audio-channels", &max_audio_channels,
5648 	       NULL);
5649 
5650   return(max_audio_channels);
5651 }
5652 
5653 /**
5654  * ags_audio_set_max_audio_channels:
5655  * @audio: the #AgsAudio
5656  * @max_audio_channels: maximum of audio channels
5657  *
5658  * Set maximum audio channels.
5659  *
5660  * Since: 3.0.0
5661  */
5662 void
ags_audio_set_max_audio_channels(AgsAudio * audio,guint max_audio_channels)5663 ags_audio_set_max_audio_channels(AgsAudio *audio,
5664 				 guint max_audio_channels)
5665 {
5666   GRecMutex *audio_mutex;
5667 
5668   if(!AGS_IS_AUDIO(audio)){
5669     return;
5670   }
5671 
5672   /* get audio mutex */
5673   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
5674 
5675   /* set max audio channels */
5676   g_rec_mutex_lock(audio_mutex);
5677 
5678   audio->max_audio_channels = max_audio_channels;
5679 
5680   g_rec_mutex_unlock(audio_mutex);
5681 }
5682 
5683 /**
5684  * ags_audio_get_max_output_pads:
5685  * @audio: the #AgsAudio
5686  *
5687  * Get maximum output pads.
5688  *
5689  * Returns: the maximum output pads
5690  *
5691  * Since: 3.1.0
5692  */
5693 guint
ags_audio_get_max_output_pads(AgsAudio * audio)5694 ags_audio_get_max_output_pads(AgsAudio *audio)
5695 {
5696   guint max_output_pads;
5697 
5698   if(!AGS_IS_AUDIO(audio)){
5699     return(0);
5700   }
5701 
5702   g_object_get(audio,
5703 	       "max-output-pads", &max_output_pads,
5704 	       NULL);
5705 
5706   return(max_output_pads);
5707 }
5708 
5709 /**
5710  * ags_audio_set_max_output_pads:
5711  * @audio: the #AgsAudio
5712  * @max_output_pads: maximum of output pads
5713  *
5714  * Set maximum output pads.
5715  *
5716  * Since: 3.1.0
5717  */
5718 void
ags_audio_set_max_output_pads(AgsAudio * audio,guint max_output_pads)5719 ags_audio_set_max_output_pads(AgsAudio *audio,
5720 			      guint max_output_pads)
5721 {
5722   ags_audio_set_max_pads(audio,
5723 			 AGS_TYPE_OUTPUT,
5724 			 max_output_pads);
5725 }
5726 
5727 /**
5728  * ags_audio_get_max_input_pads:
5729  * @audio: the #AgsAudio
5730  *
5731  * Get maximum input pads.
5732  *
5733  * Returns: the maximum input pads
5734  *
5735  * Since: 3.1.0
5736  */
5737 guint
ags_audio_get_max_input_pads(AgsAudio * audio)5738 ags_audio_get_max_input_pads(AgsAudio *audio)
5739 {
5740   guint max_input_pads;
5741 
5742   if(!AGS_IS_AUDIO(audio)){
5743     return(0);
5744   }
5745 
5746   g_object_get(audio,
5747 	       "max-input-pads", &max_input_pads,
5748 	       NULL);
5749 
5750   return(max_input_pads);
5751 }
5752 
5753 /**
5754  * ags_audio_set_max_input_pads:
5755  * @audio: the #AgsAudio
5756  * @max_input_pads: maximum of input pads
5757  *
5758  * Set maximum input pads.
5759  *
5760  * Since: 3.1.0
5761  */
5762 void
ags_audio_set_max_input_pads(AgsAudio * audio,guint max_input_pads)5763 ags_audio_set_max_input_pads(AgsAudio *audio,
5764 			     guint max_input_pads)
5765 {
5766   ags_audio_set_max_pads(audio,
5767 			 AGS_TYPE_INPUT,
5768 			 max_input_pads);
5769 }
5770 
5771 /**
5772  * ags_audio_set_max_pads:
5773  * @audio: the #AgsAudio
5774  * @channel_type: the #GType of channel, either AGS_TYPE_OUTPUT or AGS_TYPE_INPUT
5775  * @max_pads: maximum of pads
5776  *
5777  * Set maximum pads of @channel_type.
5778  *
5779  * Since: 3.0.0
5780  */
5781 void
ags_audio_set_max_pads(AgsAudio * audio,GType channel_type,guint max_pads)5782 ags_audio_set_max_pads(AgsAudio *audio,
5783 		       GType channel_type,
5784 		       guint max_pads)
5785 {
5786   GRecMutex *audio_mutex;
5787 
5788   if(!AGS_IS_AUDIO(audio)){
5789     return;
5790   }
5791 
5792   /* get audio mutex */
5793   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
5794 
5795   /* set max pads */
5796   g_rec_mutex_lock(audio_mutex);
5797 
5798   if(g_type_is_a(channel_type,
5799 		 AGS_TYPE_OUTPUT)){
5800     audio->max_output_pads = max_pads;
5801   }else if(g_type_is_a(channel_type,
5802 		       AGS_TYPE_INPUT)){
5803     audio->max_input_pads = max_pads;
5804   }
5805 
5806   g_rec_mutex_unlock(audio_mutex);
5807 }
5808 
5809 /**
5810  * ags_audio_get_audio_channels:
5811  * @audio: the #AgsAudio
5812  *
5813  * Get audio channels.
5814  *
5815  * Returns: the audio channels
5816  *
5817  * Since: 3.1.0
5818  */
5819 guint
ags_audio_get_audio_channels(AgsAudio * audio)5820 ags_audio_get_audio_channels(AgsAudio *audio)
5821 {
5822   guint audio_channels;
5823 
5824   if(!AGS_IS_AUDIO(audio)){
5825     return(0);
5826   }
5827 
5828   g_object_get(audio,
5829 	       "audio-channels", &audio_channels,
5830 	       NULL);
5831 
5832   return(audio_channels);
5833 }
5834 
5835 void
ags_audio_set_audio_channels_grow(AgsAudio * audio,GType channel_type,guint audio_channels,guint audio_channels_old,guint bank_dim_0,guint bank_dim_1,guint bank_dim_2,gboolean add_recycling,gboolean add_pattern,gboolean add_synth_generator,gboolean link_recycling,gboolean set_sync_link,gboolean set_async_link)5836 ags_audio_set_audio_channels_grow(AgsAudio *audio,
5837 				  GType channel_type,
5838 				  guint audio_channels, guint audio_channels_old,
5839 				  guint bank_dim_0, guint bank_dim_1, guint bank_dim_2,
5840 				  gboolean add_recycling, gboolean add_pattern, gboolean add_synth_generator,
5841 				  gboolean link_recycling,
5842 				  gboolean set_sync_link, gboolean set_async_link)
5843 {
5844   AgsChannel *start;
5845   AgsChannel *channel, *current, *pad_next, *nth_channel;
5846   AgsRecycling *first_recycling, *last_recycling;
5847   AgsPlaybackDomain *playback_domain;
5848 
5849   GObject *output_soundcard, *input_soundcard;
5850 
5851   guint samplerate;
5852   guint buffer_size;
5853   guint format;
5854   guint pads;
5855   guint i, j;
5856 
5857   GRecMutex *audio_mutex;
5858   GRecMutex *prev_mutex, *prev_pad_mutex;
5859   GRecMutex *next_pad_mutex;
5860 
5861   if(!AGS_IS_AUDIO(audio)){
5862     return;
5863   }
5864 
5865   /* get audio mutex */
5866   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
5867 
5868   /* get some fields */
5869   g_object_get(audio,
5870 	       "samplerate", &samplerate,
5871 	       "buffer-size", &buffer_size,
5872 	       "format", &format,
5873 	       "playback-domain", &playback_domain,
5874 	       "output-soundcard", &output_soundcard,
5875 	       "input-soundcard", &input_soundcard,
5876 	       NULL);
5877 
5878   if(g_type_is_a(channel_type, AGS_TYPE_OUTPUT)){
5879     g_object_get(audio,
5880 		 "output", &start,
5881 		 "output-pads", &pads,
5882 		 NULL);
5883   }else{
5884     g_object_get(audio,
5885 		 "input", &start,
5886 		 "input-pads", &pads,
5887 		 NULL);
5888   }
5889 
5890   /* grow */
5891   for(j = 0; j < pads; j++){
5892     for(i = audio_channels_old; i < audio_channels; i++){
5893       AgsPlayback *playback;
5894 
5895       channel = (AgsChannel *) g_object_new(channel_type,
5896 					    "audio", (GObject *) audio,
5897 					    "output-soundcard", output_soundcard,
5898 					    "output-soundcard-channel", i,
5899 					    "input-soundcard", input_soundcard,
5900 					    "input-soundcard-channel", i,
5901 					    "samplerate", samplerate,
5902 					    "buffer-size", buffer_size,
5903 					    "format", format,
5904 					    NULL);
5905       g_object_ref(channel);
5906 
5907       /* set indices */
5908       channel->pad = j;
5909       channel->audio_channel = i;
5910       channel->line = j * audio_channels + i;
5911 
5912       playback = (AgsPlayback *) channel->playback;
5913       ags_playback_domain_insert_playback(playback_domain,
5914 					  (GObject *) playback, channel_type,
5915 					  channel->line);
5916 
5917       if(add_pattern){
5918 	AgsPattern *pattern;
5919 
5920 	pattern = ags_pattern_new();
5921 	g_object_set(pattern,
5922 		     "channel", channel,
5923 		     NULL);
5924 
5925 	g_object_set(channel,
5926 		     "pattern", pattern,
5927 		     NULL);
5928 
5929 	ags_pattern_set_dim(pattern,
5930 			    bank_dim_0, bank_dim_1, bank_dim_2);
5931       }
5932 
5933       if(add_synth_generator){
5934 	AgsSynthGenerator *synth_generator;
5935 
5936 	synth_generator = ags_synth_generator_new();
5937 	ags_input_add_synth_generator((AgsInput *) channel,
5938 				      (GObject *) synth_generator);
5939       }
5940 
5941       if(start == NULL){
5942 	g_rec_mutex_lock(audio_mutex);
5943 
5944 	start = channel;
5945 
5946 	if(channel_type == AGS_TYPE_OUTPUT){
5947 	  audio->output = channel;
5948 	}else{
5949 	  audio->input = channel;
5950 	}
5951 
5952 	g_rec_mutex_unlock(audio_mutex);
5953       }
5954 
5955       if(j * audio_channels + i != 0){
5956 	AgsChannel *prev;
5957 
5958 	prev = ags_channel_nth(start, j * audio_channels + i - 1);
5959 
5960 	/* set prev next */
5961 	if(prev != NULL){
5962 	  prev_mutex = AGS_CHANNEL_GET_OBJ_MUTEX(prev);
5963 
5964 	  g_rec_mutex_lock(prev_mutex);
5965 
5966 	  prev->next = channel;
5967 
5968 	  g_rec_mutex_unlock(prev_mutex);
5969 	}
5970 
5971 	/* set prev */
5972 	channel->prev = prev;
5973 
5974 	if(prev != NULL){
5975 	  g_object_unref(prev);
5976 	}
5977 
5978 	/* set next */
5979 	if(audio_channels_old != 0 &&
5980 	   i == audio_channels - 1){
5981 	  AgsChannel *next_pad;
5982 
5983 	  pad_next = ags_channel_pad_nth(start, j + 1);
5984 
5985 	  channel->next = pad_next;
5986 
5987 	  if(pad_next != NULL){
5988 	    next_pad_mutex = AGS_CHANNEL_GET_OBJ_MUTEX(pad_next);
5989 
5990 	    g_rec_mutex_lock(next_pad_mutex);
5991 
5992 	    pad_next->prev = channel;
5993 
5994 	    g_rec_mutex_unlock(next_pad_mutex);
5995 
5996 	    g_object_unref(pad_next);
5997 	  }
5998 	}
5999       }
6000 
6001       if(j != 0){
6002 	AgsChannel *prev_pad;
6003 
6004 	nth_channel = ags_channel_nth(start, i);
6005 
6006 	/* get prev pad */
6007 	prev_pad = ags_channel_pad_nth(nth_channel, j - 1);
6008 
6009 	prev_pad_mutex = AGS_CHANNEL_GET_OBJ_MUTEX(prev_pad);
6010 
6011 	/* set prev pad next pad */
6012 	g_rec_mutex_lock(prev_pad_mutex);
6013 
6014 	prev_pad->next_pad = channel;
6015 
6016 	g_rec_mutex_unlock(prev_pad_mutex);
6017 
6018 	/* set prev pad */
6019 	channel->prev_pad = prev_pad;
6020 
6021 	g_object_unref(nth_channel);
6022 	g_object_unref(prev_pad);
6023       }
6024 
6025       /* reset nested AgsRecycling tree */
6026       if(add_recycling){
6027 	first_recycling =
6028 	  last_recycling = ags_recycling_new(output_soundcard);
6029 	g_object_ref(first_recycling);
6030 	g_object_set(first_recycling,
6031 		     "channel", channel,
6032 		     NULL);
6033 
6034 	ags_channel_reset_recycling(channel,
6035 				    first_recycling, last_recycling);
6036       }else if(set_sync_link){
6037 	AgsChannel *input;
6038 
6039 	g_rec_mutex_lock(audio_mutex);
6040 
6041 	input = audio->input;
6042 
6043 	g_rec_mutex_unlock(audio_mutex);
6044 
6045 	input = ags_channel_nth(input,
6046 				channel->line);
6047 	g_object_unref(input);
6048 
6049 	/* set sync link */
6050 	if(input != NULL){
6051 	  first_recycling = input->first_recycling;
6052 	  last_recycling = input->last_recycling;
6053 
6054 	  ags_channel_reset_recycling(channel,
6055 				      first_recycling, last_recycling);
6056 	}
6057       }else if(set_async_link){
6058 	AgsChannel *start_input;
6059 	AgsChannel *input, *input_pad_last, *nth_input;
6060 
6061 	g_rec_mutex_lock(audio_mutex);
6062 
6063 	start_input = audio->input;
6064 
6065 	if(start_input != NULL){
6066 	  g_object_ref(start_input);
6067 	}
6068 
6069 	g_rec_mutex_unlock(audio_mutex);
6070 
6071 	nth_input = ags_channel_nth(start_input,
6072 				    i);
6073 	g_object_unref(nth_input);
6074 
6075 	input = nth_input;
6076 
6077 	/* set async link */
6078 	if(input != NULL){
6079 	  input_pad_last = ags_channel_pad_last(input);
6080 
6081 	  first_recycling = input->first_recycling;
6082 	  last_recycling = input_pad_last->last_recycling;
6083 
6084 	  ags_channel_reset_recycling(channel,
6085 				      first_recycling, last_recycling);
6086 
6087 	  g_object_unref(input_pad_last);
6088 	  g_object_unref(input);
6089 	}
6090 
6091 	/* unref */
6092 	if(start_input != NULL){
6093 	  g_object_unref(start_input);
6094 	}
6095       }
6096     }
6097   }
6098 
6099   /* unref */
6100   if(output_soundcard != NULL){
6101     g_object_unref(output_soundcard);
6102   }
6103 
6104   if(input_soundcard != NULL){
6105     g_object_unref(input_soundcard);
6106   }
6107 
6108   if(start != NULL){
6109     g_object_unref(start);
6110   }
6111 
6112   g_object_unref(playback_domain);
6113 }
6114 
6115 void
ags_audio_set_audio_channels_shrink_zero(AgsAudio * audio)6116 ags_audio_set_audio_channels_shrink_zero(AgsAudio *audio)
6117 {
6118   AgsChannel *channel, *start, *channel_next;
6119 
6120   gboolean first_run;
6121 
6122   GError *error;
6123 
6124   GRecMutex *audio_mutex;
6125 
6126   if(!AGS_IS_AUDIO(audio)){
6127     return;
6128   }
6129 
6130   /* get audio mutex */
6131   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
6132 
6133   g_rec_mutex_lock(audio_mutex);
6134 
6135   start =
6136     channel = audio->output;
6137   first_run = TRUE;
6138 
6139   error = NULL;
6140 
6141 ags_audio_set_audio_channel_shrink_zero0:
6142 
6143   while(channel != NULL){
6144     error =  NULL;
6145     ags_channel_set_link(channel, NULL,
6146 			 &error);
6147 
6148     if(error != NULL){
6149       g_error("%s", error->message);
6150 
6151       g_error_free(error);
6152     }
6153 
6154     channel = channel->next;
6155   }
6156 
6157   channel = start;
6158 
6159   while(channel != NULL){
6160     channel_next = channel->next;
6161 
6162     g_object_run_dispose((GObject *) channel);
6163 
6164     channel = channel_next;
6165   }
6166 
6167   if(first_run){
6168     start =
6169       channel = audio->input;
6170     first_run = FALSE;
6171     goto ags_audio_set_audio_channel_shrink_zero0;
6172   }
6173 
6174   audio->output = NULL;
6175   audio->input = NULL;
6176 
6177   g_rec_mutex_unlock(audio_mutex);
6178 }
6179 
6180 void
ags_audio_set_audio_channels_shrink(AgsAudio * audio,guint audio_channels,guint audio_channels_old)6181 ags_audio_set_audio_channels_shrink(AgsAudio *audio,
6182 				    guint audio_channels, guint audio_channels_old)
6183 {
6184   AgsChannel *start;
6185   AgsChannel *channel, *nth_channel;
6186   AgsChannel *channel0, *channel1;
6187   AgsRecycling *recycling;
6188 
6189   guint pads, i, j;
6190   gboolean first_run;
6191 
6192   GError *error;
6193 
6194   GRecMutex *audio_mutex;
6195 
6196   if(!AGS_IS_AUDIO(audio) ||
6197      audio_channels == audio_channels_old){
6198     return;
6199   }
6200 
6201   /* get audio mutex */
6202   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
6203 
6204   g_rec_mutex_lock(audio_mutex);
6205 
6206   start =
6207     channel = audio->output;
6208   pads = audio->output_pads;
6209 
6210   g_rec_mutex_unlock(audio_mutex);
6211 
6212   first_run = TRUE;
6213 
6214 ags_audio_set_audio_channel_shrink0:
6215 
6216   for(i = 0; i < pads; i++){
6217     channel = ags_channel_nth(channel, audio_channels);
6218     g_object_unref(channel);
6219 
6220     for(j = audio_channels; j < audio_channels_old; j++){
6221       error = NULL;
6222       ags_channel_set_link(channel, NULL,
6223 			   &error);
6224 
6225       if(error != NULL){
6226 	g_error("%s", error->message);
6227 
6228 	g_error_free(error);
6229       }
6230 
6231       channel = channel->next;
6232     }
6233   }
6234 
6235   channel = start;
6236 
6237   for(i = 0; ; i++){
6238     for(j = 0; j < audio_channels -1; j++){
6239       channel->pad = i;
6240       channel->audio_channel = j;
6241       channel->line = i * audio_channels + j;
6242 
6243       channel = channel->next;
6244     }
6245 
6246     channel->pad = i;
6247     channel->audio_channel = j;
6248     channel->line = i * audio_channels + j;
6249 
6250     channel0 = channel->next;
6251 
6252     j++;
6253 
6254     for(; j < audio_channels_old; j++){
6255       channel1 = channel0->next;
6256 
6257       g_object_run_dispose((GObject *) channel0);
6258 
6259       channel0 = channel1;
6260     }
6261 
6262     channel->next = channel1;
6263 
6264     if(channel1 != NULL){
6265       channel1->prev = channel;
6266     }else{
6267       break;
6268     }
6269 
6270     channel = channel1;
6271   }
6272 
6273   if(first_run){
6274     first_run = FALSE;
6275 
6276     g_rec_mutex_lock(audio_mutex);
6277 
6278     start =
6279       channel = audio->input;
6280     pads = audio->input_pads;
6281 
6282     g_rec_mutex_unlock(audio_mutex);
6283 
6284     goto ags_audio_set_audio_channel_shrink0;
6285   }
6286 }
6287 
6288 void
ags_audio_set_audio_channels_shrink_notation(AgsAudio * audio,guint audio_channels,guint audio_channels_old)6289 ags_audio_set_audio_channels_shrink_notation(AgsAudio *audio,
6290 					     guint audio_channels, guint audio_channels_old)
6291 {
6292   GList *list_start, *list;
6293 
6294   GRecMutex *audio_mutex;
6295 
6296   if(!AGS_IS_AUDIO(audio)){
6297     return;
6298   }
6299 
6300   /* get audio mutex */
6301   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
6302 
6303   g_rec_mutex_lock(audio_mutex);
6304 
6305   list =
6306     list_start = g_list_copy(audio->notation);
6307 
6308   while(list != NULL){
6309     if(AGS_NOTATION(list->data)->audio_channel >= audio_channels){
6310       ags_audio_remove_notation(audio,
6311 				list->data);
6312 
6313       g_object_run_dispose((GObject *) list->data);
6314       g_object_unref((GObject *) list->data);
6315     }
6316 
6317     list = list->next;
6318   }
6319 
6320   g_list_free(list_start);
6321 
6322   g_rec_mutex_unlock(audio_mutex);
6323 }
6324 
6325 void
ags_audio_set_audio_channels_shrink_automation(AgsAudio * audio,guint audio_channels,guint audio_channels_old)6326 ags_audio_set_audio_channels_shrink_automation(AgsAudio *audio,
6327 					       guint audio_channels, guint audio_channels_old)
6328 {
6329   GList *list_start, *list;
6330 
6331   GRecMutex *audio_mutex;
6332 
6333   if(!AGS_IS_AUDIO(audio)){
6334     return;
6335   }
6336 
6337   /* get audio mutex */
6338   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
6339 
6340   g_rec_mutex_lock(audio_mutex);
6341 
6342   list =
6343     list_start = g_list_copy(audio->automation);
6344 
6345   while(list != NULL){
6346     if(AGS_AUTOMATION(list->data)->line % audio_channels_old >= audio_channels){
6347       ags_audio_remove_automation(audio,
6348 				  list->data);
6349 
6350       g_object_run_dispose((GObject *) list->data);
6351       g_object_unref((GObject *) list->data);
6352     }
6353 
6354     list = list->next;
6355   }
6356 
6357   g_list_free(list_start);
6358 
6359   if(audio_channels == 0){
6360     audio->automation = NULL;
6361   }
6362 
6363   g_rec_mutex_unlock(audio_mutex);
6364 }
6365 
6366 void
ags_audio_set_audio_channels_shrink_wave(AgsAudio * audio,guint audio_channels,guint audio_channels_old)6367 ags_audio_set_audio_channels_shrink_wave(AgsAudio *audio,
6368 					 guint audio_channels, guint audio_channels_old)
6369 {
6370   GList *list_start, *list;
6371 
6372   GRecMutex *audio_mutex;
6373 
6374   if(!AGS_IS_AUDIO(audio)){
6375     return;
6376   }
6377 
6378   /* get audio mutex */
6379   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
6380 
6381   g_rec_mutex_lock(audio_mutex);
6382 
6383   list =
6384     list_start = g_list_copy(audio->wave);
6385 
6386   while(list != NULL){
6387     if(AGS_WAVE(list->data)->line % audio_channels_old >= audio_channels){
6388       ags_audio_remove_wave(audio,
6389 			    list->data);
6390 
6391       g_object_run_dispose((GObject *) list->data);
6392       g_object_unref((GObject *) list->data);
6393     }
6394 
6395     list = list->next;
6396   }
6397 
6398   g_list_free(list_start);
6399 
6400   g_rec_mutex_unlock(audio_mutex);
6401 }
6402 
6403 void
ags_audio_set_audio_channels_shrink_midi(AgsAudio * audio,guint audio_channels,guint audio_channels_old)6404 ags_audio_set_audio_channels_shrink_midi(AgsAudio *audio,
6405 					 guint audio_channels, guint audio_channels_old)
6406 {
6407   GList *list_start, *list;
6408 
6409   GRecMutex *audio_mutex;
6410 
6411   if(!AGS_IS_AUDIO(audio)){
6412     return;
6413   }
6414 
6415   /* get audio mutex */
6416   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
6417 
6418   g_rec_mutex_lock(audio_mutex);
6419 
6420   list =
6421     list_start = g_list_copy(audio->midi);
6422 
6423   while(list != NULL){
6424     if(AGS_MIDI(list->data)->audio_channel >= audio_channels){
6425       ags_audio_remove_midi(audio,
6426 			    list->data);
6427 
6428       g_object_run_dispose((GObject *) list->data);
6429       g_object_unref((GObject *) list->data);
6430     }
6431 
6432     list = list->next;
6433   }
6434 
6435   g_list_free(list_start);
6436 
6437   g_rec_mutex_unlock(audio_mutex);
6438 }
6439 
6440 void
ags_audio_real_set_audio_channels(AgsAudio * audio,guint audio_channels,guint audio_channels_old)6441 ags_audio_real_set_audio_channels(AgsAudio *audio,
6442 				  guint audio_channels, guint audio_channels_old)
6443 {
6444   AgsPlaybackDomain *playback_domain;
6445   AgsPlayback *playback;
6446   AgsChannel *start_channel, *channel, *nth_channel, *next_channel;
6447 
6448   AgsMessageDelivery *message_delivery;
6449 
6450   GList *start_message_queue;
6451 
6452   guint bank_dim[3];
6453 
6454   guint audio_flags;
6455   guint ability_flags;
6456   guint output_pads, input_pads;
6457   gboolean add_recycling;
6458   gboolean add_pattern;
6459   gboolean add_synth_generator;
6460   gboolean link_recycling; // affects AgsInput
6461   gboolean set_sync_link, set_async_link; // affects AgsOutput
6462 
6463   GRecMutex *audio_mutex;
6464 
6465   if(audio_channels == audio_channels_old){
6466     return;
6467   }
6468 
6469   /* get audio mutex */
6470   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
6471 
6472   /* grow / shrink */
6473   g_rec_mutex_lock(audio_mutex);
6474 
6475   audio_flags = audio->flags;
6476   ability_flags = audio->ability_flags;
6477 
6478   output_pads = audio->output_pads;
6479   input_pads = audio->input_pads;
6480 
6481   g_rec_mutex_unlock(audio_mutex);
6482 
6483   /* get some fields */
6484   g_object_get(audio,
6485 	       "playback-domain", &playback_domain,
6486 	       NULL);
6487 
6488   if(audio_channels > audio_channels_old){
6489     guint i, j;
6490 
6491     /* grow input channels */
6492     if(input_pads > 0 &&
6493        (AGS_AUDIO_NO_INPUT & (audio_flags)) == 0){
6494       add_recycling = FALSE;
6495       add_pattern = FALSE;
6496       add_synth_generator = FALSE;
6497 
6498       link_recycling = FALSE;
6499 
6500       set_sync_link = FALSE;
6501       set_async_link = FALSE;
6502 
6503       if((AGS_AUDIO_INPUT_HAS_RECYCLING & (audio_flags)) != 0){
6504 	add_recycling = TRUE;
6505       }
6506 
6507       bank_dim[0] = 0;
6508       bank_dim[1] = 0;
6509       bank_dim[2] = 0;
6510 
6511       if((AGS_SOUND_ABILITY_SEQUENCER & (ability_flags)) != 0){
6512 	add_pattern = TRUE;
6513 
6514 	g_rec_mutex_lock(audio_mutex);
6515 
6516 	bank_dim[0] = audio->bank_dim[0];
6517 	bank_dim[1] = audio->bank_dim[1];
6518 	bank_dim[2] = audio->bank_dim[2];
6519 
6520 	g_rec_mutex_unlock(audio_mutex);
6521 
6522       }
6523 
6524       if((AGS_AUDIO_INPUT_HAS_SYNTH & (audio_flags)) != 0){
6525 	add_synth_generator = TRUE;
6526       }
6527 
6528       if((AGS_AUDIO_ASYNC & (audio_flags)) != 0 && add_recycling){
6529 	link_recycling = TRUE;
6530       }
6531 
6532       ags_audio_set_audio_channels_grow(audio,
6533 					AGS_TYPE_INPUT,
6534 					audio_channels, audio_channels_old,
6535 					bank_dim[0], bank_dim[1], bank_dim[2],
6536 					add_recycling, add_pattern, add_synth_generator,
6537 					link_recycling,
6538 					set_sync_link, set_async_link);
6539     }
6540 
6541     /* apply new sizes */
6542     g_rec_mutex_lock(audio_mutex);
6543 
6544     audio->input_lines = audio_channels * audio->input_pads;
6545 
6546     g_rec_mutex_unlock(audio_mutex);
6547 
6548     /* grow output channels */
6549     if(audio->output_pads > 0 &&
6550        (AGS_AUDIO_NO_OUTPUT & (audio_flags)) == 0){
6551       add_recycling = FALSE;
6552       add_pattern = FALSE;
6553       add_synth_generator = FALSE;
6554 
6555       link_recycling = FALSE;
6556 
6557       set_sync_link = FALSE;
6558       set_async_link = FALSE;
6559 
6560       if((AGS_AUDIO_OUTPUT_HAS_RECYCLING & (audio_flags)) != 0){
6561 	add_recycling = TRUE;
6562       }else{
6563 	if((AGS_AUDIO_INPUT_HAS_RECYCLING & (audio_flags)) != 0){
6564 	  if((AGS_AUDIO_SYNC & (audio_flags)) != 0 && (AGS_AUDIO_ASYNC & (audio_flags)) == 0){
6565 	    set_sync_link = FALSE;
6566 	    set_async_link = TRUE;
6567 	  }else if((AGS_AUDIO_ASYNC & (audio_flags)) != 0){
6568 	    set_async_link = TRUE;
6569 	    set_sync_link = FALSE;
6570 	  }else{
6571 #ifdef AGS_DEBUG
6572 	    g_message("ags_audio_set_audio_channels - warning: AGS_AUDIO_SYNC nor AGS_AUDIO_ASYNC aren't defined");
6573 #endif
6574 	    set_sync_link = FALSE;
6575 	    set_async_link = FALSE;
6576 	  }
6577 	}
6578       }
6579 
6580       ags_audio_set_audio_channels_grow(audio,
6581 					AGS_TYPE_OUTPUT,
6582 					audio_channels, audio_channels_old,
6583 					0, 0, 0,
6584 					add_recycling, add_pattern, add_synth_generator,
6585 					link_recycling,
6586 					set_sync_link, set_async_link);
6587     }
6588 
6589     /* apply new sizes */
6590     g_rec_mutex_lock(audio_mutex);
6591 
6592     audio->output_lines = audio_channels * audio->output_pads;
6593 
6594     audio->audio_channels = audio_channels;
6595 
6596     g_rec_mutex_unlock(audio_mutex);
6597 
6598     /* set ability flags */
6599     g_object_get(audio,
6600 		 "output", &start_channel,
6601 		 NULL);
6602 
6603     if(start_channel != NULL){
6604       for(i = 0; i < output_pads; i++){
6605 	nth_channel = ags_channel_nth(start_channel,
6606 				      (i * audio_channels) + audio_channels_old);
6607 
6608 	channel = nth_channel;
6609 
6610 	if(channel != NULL){
6611 	  g_object_ref(channel);
6612 	}
6613 
6614 	next_channel = NULL;
6615 
6616 	for(j = 0; j < audio_channels - audio_channels_old; j++){
6617 	  ags_channel_set_ability_flags(channel, ability_flags);
6618 
6619 	  /* iterate */
6620 	  next_channel = ags_channel_next(channel);
6621 
6622 	  if(channel != NULL){
6623 	    g_object_unref(channel);
6624 	  }
6625 
6626 	  channel = next_channel;
6627 	}
6628 
6629 	if(next_channel != NULL){
6630 	  g_object_unref(next_channel);
6631 	}
6632 
6633 	if(nth_channel != NULL){
6634 	  g_object_unref(nth_channel);
6635 	}
6636       }
6637 
6638       g_object_unref(start_channel);
6639     }
6640 
6641     /* set ability flags */
6642     g_object_get(audio,
6643 		 "input", &start_channel,
6644 		 NULL);
6645 
6646     if(start_channel != NULL){
6647       for(i = 0; i < input_pads; i++){
6648 	nth_channel = ags_channel_nth(start_channel,
6649 				      (i * audio_channels) + audio_channels_old);
6650 
6651 	channel = nth_channel;
6652 
6653 	if(channel != NULL){
6654 	  g_object_ref(channel);
6655 	}
6656 
6657 	next_channel = NULL;
6658 
6659 	for(j = 0; j < audio_channels - audio_channels_old; j++){
6660 	  ags_channel_set_ability_flags(channel, ability_flags);
6661 
6662 	  /* iterate */
6663 	  next_channel = ags_channel_next(channel);
6664 
6665 	  if(channel != NULL){
6666 	    g_object_unref(channel);
6667 	  }
6668 
6669 	  channel = next_channel;
6670 	}
6671 
6672 	if(next_channel != NULL){
6673 	  g_object_unref(next_channel);
6674 	}
6675 
6676 	if(nth_channel != NULL){
6677 	  g_object_unref(nth_channel);
6678 	}
6679       }
6680 
6681       g_object_unref(start_channel);
6682     }
6683   }else if(audio_channels < audio_channels_old){
6684     GList *start_list, *list;
6685 
6686     guint i, j;
6687 
6688     GRecMutex *playback_domain_mutex;
6689 
6690     /* shrink audio channels */
6691     ags_audio_set_audio_channels_shrink_automation(audio,
6692 						   audio_channels, audio_channels_old);
6693 
6694     if((AGS_SOUND_ABILITY_NOTATION & (ability_flags)) != 0){
6695       ags_audio_set_audio_channels_shrink_notation(audio,
6696 						   audio_channels, audio_channels_old);
6697     }
6698 
6699     if((AGS_SOUND_ABILITY_WAVE & (ability_flags)) != 0){
6700       ags_audio_set_audio_channels_shrink_wave(audio,
6701 					       audio_channels, audio_channels_old);
6702     }
6703 
6704     if((AGS_SOUND_ABILITY_MIDI & (ability_flags)) != 0){
6705       ags_audio_set_audio_channels_shrink_midi(audio,
6706 					       audio_channels, audio_channels_old);
6707     }
6708 
6709     if(audio_channels == 0){
6710       ags_audio_set_audio_channels_shrink_zero(audio);
6711     }else{
6712       ags_audio_set_audio_channels_shrink(audio,
6713 					  audio_channels, audio_channels_old);
6714     }
6715 
6716     /* apply new sizes */
6717     g_rec_mutex_lock(audio_mutex);
6718 
6719     audio->audio_channels = audio_channels;
6720 
6721     audio->input_lines = audio_channels * audio->input_pads;
6722     audio->output_lines = audio_channels * audio->output_pads;
6723 
6724     g_rec_mutex_unlock(audio_mutex);
6725   }
6726 
6727   /* unref */
6728   g_object_unref(playback_domain);
6729 
6730   /* emit message */
6731   message_delivery = ags_message_delivery_get_instance();
6732 
6733   start_message_queue = ags_message_delivery_find_sender_namespace(message_delivery,
6734 								   "libags-audio");
6735 
6736   if(start_message_queue != NULL){
6737     AgsMessageEnvelope *message;
6738 
6739     xmlDoc *doc;
6740     xmlNode *root_node;
6741 
6742     /* specify message body */
6743     doc = xmlNewDoc("1.0");
6744 
6745     root_node = xmlNewNode(NULL,
6746 			   "ags-command");
6747     xmlDocSetRootElement(doc, root_node);
6748 
6749     xmlNewProp(root_node,
6750 	       "method",
6751 	       "AgsAudio::set-audio-channels");
6752 
6753     /* add message */
6754     message = ags_message_envelope_new((GObject *) audio,
6755 				       NULL,
6756 				       doc);
6757 
6758     /* set parameter */
6759     message->n_params = 2;
6760 
6761     message->parameter_name = (gchar **) malloc(3 * sizeof(gchar *));
6762     message->value = g_new0(GValue,
6763 			    2);
6764 
6765     /* audio channels */
6766     message->parameter_name[0] = "audio-channels";
6767 
6768     g_value_init(&(message->value[0]),
6769 		 G_TYPE_UINT);
6770     g_value_set_uint(&(message->value[0]),
6771 		     audio_channels);
6772 
6773     /* audio channels old */
6774     message->parameter_name[1] = "audio-channels-old";
6775 
6776     g_value_init(&(message->value[1]),
6777 		 G_TYPE_UINT);
6778     g_value_set_uint(&(message->value[1]),
6779 		     audio_channels_old);
6780 
6781     /* terminate string vector */
6782     message->parameter_name[2] = NULL;
6783 
6784     /* add message */
6785     ags_message_delivery_add_message_envelope(message_delivery,
6786 					      "libags-audio",
6787 					      message);
6788 
6789     g_list_free_full(start_message_queue,
6790 		     (GDestroyNotify) g_object_unref);
6791   }
6792 }
6793 
6794 /**
6795  * ags_audio_set_audio_channels:
6796  * @audio: the #AgsAudio
6797  * @audio_channels: new audio channels
6798  * @audio_channels_old: old audio channels
6799  *
6800  * Resize audio channels AgsInput will be allocated first.
6801  *
6802  * Since: 3.0.0
6803  */
6804 void
ags_audio_set_audio_channels(AgsAudio * audio,guint audio_channels,guint audio_channels_old)6805 ags_audio_set_audio_channels(AgsAudio *audio,
6806 			     guint audio_channels, guint audio_channels_old)
6807 {
6808   GRecMutex *audio_mutex;
6809 
6810   g_return_if_fail(AGS_IS_AUDIO(audio));
6811 
6812   /* get audio mutex */
6813   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
6814 
6815   /* get audio channels old */
6816   g_rec_mutex_lock(audio_mutex);
6817 
6818   audio_channels_old = audio->audio_channels;
6819 
6820   g_rec_mutex_unlock(audio_mutex);
6821 
6822   /* emit */
6823   g_object_ref((GObject *) audio);
6824   g_signal_emit(G_OBJECT(audio),
6825 		audio_signals[SET_AUDIO_CHANNELS], 0,
6826 		audio_channels, audio_channels_old);
6827   g_object_unref((GObject *) audio);
6828 }
6829 
6830 /**
6831  * ags_audio_get_output_pads:
6832  * @audio: the #AgsAudio
6833  *
6834  * Get output pads.
6835  *
6836  * Returns: the output pads
6837  *
6838  * Since: 3.1.0
6839  */
6840 guint
ags_audio_get_output_pads(AgsAudio * audio)6841 ags_audio_get_output_pads(AgsAudio *audio)
6842 {
6843   guint output_pads;
6844 
6845   if(!AGS_IS_AUDIO(audio)){
6846     return(0);
6847   }
6848 
6849   g_object_get(audio,
6850 	       "output-pads", &output_pads,
6851 	       NULL);
6852 
6853   return(output_pads);
6854 }
6855 
6856 /**
6857  * ags_audio_set_output_pads:
6858  * @audio: the #AgsAudio
6859  * @output_pads: output pads
6860  *
6861  * Set output pads.
6862  *
6863  * Since: 3.1.0
6864  */
6865 void
ags_audio_set_output_pads(AgsAudio * audio,guint output_pads)6866 ags_audio_set_output_pads(AgsAudio *audio,
6867 			  guint output_pads)
6868 {
6869   ags_audio_set_pads(audio,
6870 		     AGS_TYPE_OUTPUT,
6871 		     output_pads, 0);
6872 }
6873 
6874 /**
6875  * ags_audio_get_input_pads:
6876  * @audio: the #AgsAudio
6877  *
6878  * Get input pads.
6879  *
6880  * Returns: the input pads
6881  *
6882  * Since: 3.1.0
6883  */
6884 guint
ags_audio_get_input_pads(AgsAudio * audio)6885 ags_audio_get_input_pads(AgsAudio *audio)
6886 {
6887   guint input_pads;
6888 
6889   if(!AGS_IS_AUDIO(audio)){
6890     return(0);
6891   }
6892 
6893   g_object_get(audio,
6894 	       "input-pads", &input_pads,
6895 	       NULL);
6896 
6897   return(input_pads);
6898 }
6899 
6900 /**
6901  * ags_audio_set_input_pads:
6902  * @audio: the #AgsAudio
6903  * @input_pads: input pads
6904  *
6905  * Set input pads.
6906  *
6907  * Since: 3.1.0
6908  */
6909 void
ags_audio_set_input_pads(AgsAudio * audio,guint input_pads)6910 ags_audio_set_input_pads(AgsAudio *audio,
6911 			  guint input_pads)
6912 {
6913   ags_audio_set_pads(audio,
6914 		     AGS_TYPE_INPUT,
6915 		     input_pads, 0);
6916 }
6917 
6918 void
ags_audio_set_pads_grow(AgsAudio * audio,GType channel_type,guint pads,guint pads_old,guint bank_dim_0,guint bank_dim_1,guint bank_dim_2,gboolean add_recycling,gboolean add_pattern,gboolean add_synth_generator,gboolean link_recycling,gboolean set_sync_link,gboolean set_async_link)6919 ags_audio_set_pads_grow(AgsAudio *audio,
6920 			GType channel_type,
6921 			guint pads, guint pads_old,
6922 			guint bank_dim_0, guint bank_dim_1, guint bank_dim_2,
6923 			gboolean add_recycling, gboolean add_pattern, gboolean add_synth_generator,
6924 			gboolean link_recycling,
6925 			gboolean set_sync_link, gboolean set_async_link)
6926 {
6927   AgsChannel *start;
6928   AgsChannel *channel, *nth_channel;
6929   AgsRecycling *first_recycling, *last_recycling;
6930   AgsPlaybackDomain *playback_domain;
6931 
6932   GObject *output_soundcard;
6933   GObject *input_soundcard;
6934 
6935   guint samplerate;
6936   guint buffer_size;
6937   guint format;
6938   guint audio_channels;
6939   guint i, j;
6940 
6941   GRecMutex *audio_mutex;
6942   GRecMutex *prev_mutex, *prev_pad_mutex;
6943 
6944   if(!AGS_IS_AUDIO(audio)){
6945     return;
6946   }
6947 
6948   /* get audio mutex */
6949   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
6950 
6951   /* get some fields */
6952   g_object_get(audio,
6953 	       "samplerate", &samplerate,
6954 	       "buffer-size", &buffer_size,
6955 	       "format", &format,
6956 	       "audio-channels", &audio_channels,
6957 	       "output-soundcard", &output_soundcard,
6958 	       "input-soundcard", &input_soundcard,
6959 	       "playback-domain", &playback_domain,
6960 	       NULL);
6961 
6962   if(g_type_is_a(channel_type, AGS_TYPE_OUTPUT)){
6963     g_object_get(audio,
6964 		 "output", &start,
6965 		 NULL);
6966   }else{
6967     g_object_get(audio,
6968 		 "input", &start,
6969 		 NULL);
6970   }
6971 
6972   for(j = pads_old; j < pads; j++){
6973     AgsPlayback *playback;
6974 
6975     for(i = 0; i < audio_channels; i++){
6976       channel = (AgsChannel *) g_object_new(channel_type,
6977 					    "audio", (GObject *) audio,
6978 					    "output-soundcard", output_soundcard,
6979 					    "output-soundcard-channel", i,
6980 					    "input-soundcard", input_soundcard,
6981 					    "input-soundcard-channel", i,
6982 					    "samplerate", samplerate,
6983 					    "buffer-size", buffer_size,
6984 					    "format", format,
6985 					    NULL);
6986       g_object_ref(channel);
6987 
6988       /* set indices */
6989       channel->pad = j;
6990       channel->audio_channel = i;
6991       channel->line = j * audio_channels + i;
6992 
6993       playback = (AgsPlayback *) channel->playback;
6994       ags_playback_domain_insert_playback(playback_domain,
6995 					  (GObject *) playback, channel_type,
6996 					  channel->line);
6997 
6998       if(add_pattern){
6999 	AgsPattern *pattern;
7000 
7001 	pattern = ags_pattern_new();
7002 	g_object_set(pattern,
7003 		     "channel", channel,
7004 		     NULL);
7005 
7006 	g_object_set(channel,
7007 		     "pattern", pattern,
7008 		     NULL);
7009 
7010 	ags_pattern_set_dim(pattern,
7011 			    bank_dim_0, bank_dim_1, bank_dim_2);
7012       }
7013 
7014       if(add_synth_generator){
7015 	AgsSynthGenerator *synth_generator;
7016 
7017 	synth_generator = ags_synth_generator_new();
7018 	ags_input_add_synth_generator((AgsInput *) channel,
7019 				      (GObject *) synth_generator);
7020       }
7021 
7022       if(start == NULL){
7023 	/* set first channel in AgsAudio */
7024 	g_rec_mutex_lock(audio_mutex);
7025 
7026 	if(channel_type == AGS_TYPE_OUTPUT){
7027 	  start =
7028 	    audio->output = channel;
7029 	}else{
7030 	  start =
7031 	    audio->input = channel;
7032 	}
7033 
7034 	g_rec_mutex_unlock(audio_mutex);
7035       }
7036 
7037       if(j * audio_channels + i != 0){
7038 	/* set prev */
7039 	channel->prev = ags_channel_nth(start, j * audio_channels + i - 1);
7040 	g_object_unref(channel->prev);
7041 
7042 	/* get prev mutex */
7043 	prev_mutex = AGS_CHANNEL_GET_OBJ_MUTEX(channel->prev);
7044 
7045 	/* set prev->next */
7046 	g_rec_mutex_lock(prev_mutex);
7047 
7048 	channel->prev->next = channel;
7049 
7050 	g_rec_mutex_unlock(prev_mutex);
7051       }
7052 
7053       if(j != 0){
7054 	/* set prev pad */
7055 	nth_channel = ags_channel_nth(start, i);
7056 
7057 	channel->prev_pad = ags_channel_pad_nth(nth_channel, j - 1);
7058 
7059 	g_object_unref(nth_channel);
7060 	g_object_unref(channel->prev_pad);
7061 
7062 	/* get prev pad mutex */
7063 	prev_pad_mutex = AGS_CHANNEL_GET_OBJ_MUTEX(channel->prev_pad);
7064 
7065 	/* set prev_pad->next_pad */
7066 	g_rec_mutex_lock(prev_pad_mutex);
7067 
7068 	channel->prev_pad->next_pad = channel;
7069 
7070 	g_rec_mutex_unlock(prev_pad_mutex);
7071       }
7072 
7073       /* reset nested AgsRecycling tree */
7074       if(add_recycling){
7075 	first_recycling =
7076 	  last_recycling = ags_recycling_new(output_soundcard);
7077 	g_object_ref(first_recycling);
7078 	g_object_set(first_recycling,
7079 		     "channel", channel,
7080 		     NULL);
7081 
7082 	ags_channel_reset_recycling(channel,
7083 				    first_recycling, last_recycling);
7084       }else if(set_sync_link){
7085 	AgsChannel *input;
7086 
7087 	g_rec_mutex_lock(audio_mutex);
7088 
7089 	input = audio->input;
7090 
7091 	g_rec_mutex_unlock(audio_mutex);
7092 
7093 	input = ags_channel_nth(input,
7094 				channel->line);
7095 	g_object_unref(input);
7096 
7097 	/* set sync link */
7098 	if(input != NULL){
7099 	  first_recycling = input->first_recycling;
7100 	  last_recycling = input->last_recycling;
7101 
7102 	  ags_channel_reset_recycling(channel,
7103 				      first_recycling, last_recycling);
7104 	}
7105       }else if(set_async_link){
7106 	AgsChannel *start_input;
7107 	AgsChannel *input, *input_pad_last, *nth_input;
7108 
7109 	g_rec_mutex_lock(audio_mutex);
7110 
7111 	start_input = audio->input;
7112 
7113 	if(start_input != NULL){
7114 	  g_object_ref(start_input);
7115 	}
7116 
7117 	g_rec_mutex_unlock(audio_mutex);
7118 
7119 	nth_input = ags_channel_nth(start_input,
7120 				    i);
7121 	g_object_unref(nth_input);
7122 
7123 	input = nth_input;
7124 
7125 	/* set async link */
7126 	if(input != NULL){
7127 	  input_pad_last = ags_channel_pad_last(input);
7128 
7129 	  first_recycling = input->first_recycling;
7130 	  last_recycling = input_pad_last->last_recycling;
7131 
7132 	  ags_channel_reset_recycling(channel,
7133 				      first_recycling, last_recycling);
7134 
7135 	  g_object_unref(input_pad_last);
7136 	  g_object_unref(input);
7137 	}
7138 
7139 	/* unref */
7140 	if(start_input != NULL){
7141 	  g_object_unref(start_input);
7142 	}
7143       }
7144     }
7145   }
7146 
7147   /* unref */
7148   if(output_soundcard != NULL){
7149     g_object_unref(output_soundcard);
7150   }
7151 
7152   if(input_soundcard != NULL){
7153     g_object_unref(input_soundcard);
7154   }
7155 
7156 
7157   if(start != NULL){
7158     g_object_unref(start);
7159   }
7160 
7161   g_object_unref(playback_domain);
7162 }
7163 
7164 void
ags_audio_set_pads_unlink(AgsAudio * audio,GType channel_type,guint pads)7165 ags_audio_set_pads_unlink(AgsAudio *audio,
7166 			  GType channel_type,
7167 			  guint pads)
7168 {
7169   AgsChannel *channel, *next_channel;
7170 
7171   GError *error;
7172 
7173   if(!AGS_IS_AUDIO(audio)){
7174     return;
7175   }
7176 
7177   if(channel_type == AGS_TYPE_OUTPUT){
7178     channel = ags_channel_pad_nth(audio->output,
7179 				  pads);
7180   }else{
7181     channel = ags_channel_pad_nth(audio->input,
7182 				  pads);
7183   }
7184 
7185   while(channel != NULL){
7186     error = NULL;
7187     ags_channel_set_link(channel, NULL,
7188 			 &error);
7189 
7190     if(error != NULL){
7191       g_error("%s", error->message);
7192 
7193       g_error_free(error);
7194     }
7195 
7196     /* iterate */
7197     next_channel = ags_channel_next(channel);
7198 
7199     g_object_unref(channel);
7200 
7201     channel = next_channel;
7202   }
7203 }
7204 
7205 void
ags_audio_set_pads_shrink_zero(AgsAudio * audio,GType channel_type,guint pads)7206 ags_audio_set_pads_shrink_zero(AgsAudio *audio,
7207 			       GType channel_type,
7208 			       guint pads)
7209 {
7210   AgsChannel *channel, *channel_next;
7211 
7212   GError *error;
7213 
7214   if(!AGS_IS_AUDIO(audio)){
7215     return;
7216   }
7217 
7218   if(channel_type == AGS_TYPE_OUTPUT){
7219     channel = ags_channel_pad_nth(audio->output,
7220 				  pads);
7221   }else{
7222     channel = ags_channel_pad_nth(audio->input,
7223 				  pads);
7224   }
7225 
7226   while(channel != NULL){
7227     channel_next = channel->next;
7228 
7229 #if 0
7230     error = NULL;
7231     ags_channel_set_link(channel, NULL,
7232 			 &error);
7233 
7234     if(error != NULL){
7235       g_error("%s", error->message);
7236 
7237       g_error_free(error);
7238     }
7239 #endif
7240 
7241     g_object_run_dispose((GObject *) channel);
7242 
7243     channel = channel_next;
7244   }
7245 }
7246 
7247 void
ags_audio_set_pads_shrink(AgsAudio * audio,GType channel_type,guint pads)7248 ags_audio_set_pads_shrink(AgsAudio *audio,
7249 			  GType channel_type,
7250 			  guint pads)
7251 {
7252   AgsChannel *channel, *current;
7253 
7254   guint audio_channels;
7255 
7256   guint i;
7257 
7258   if(!AGS_IS_AUDIO(audio)){
7259     return;
7260   }
7261 
7262   g_object_get(audio,
7263 	       "audio-channels", &audio_channels,
7264 	       NULL);
7265 
7266   if(channel_type == AGS_TYPE_OUTPUT){
7267     channel = ags_channel_pad_nth(audio->output,
7268 				  pads);
7269   }else{
7270     channel = ags_channel_pad_nth(audio->input,
7271 				  pads);
7272   }
7273 
7274   g_object_unref(channel);
7275   current = channel;
7276 
7277   if(channel != NULL &&
7278      channel->prev_pad != NULL){
7279     channel = channel->prev_pad;
7280   }else{
7281     channel = NULL;
7282   }
7283 
7284   ags_audio_set_pads_shrink_zero(audio,
7285 				 channel_type,
7286 				 pads);
7287 
7288   /* remove pads */
7289   if(channel != NULL){
7290     current = channel;
7291 
7292     for(i = 0; i < audio_channels; i++){
7293       current->next_pad = NULL;
7294 
7295       /* iterate */
7296       current = current->next;
7297     }
7298 
7299     /* remove channel */
7300     current = ags_channel_nth(channel,
7301 			      audio_channels - 1);
7302 
7303     if(current != NULL){
7304       g_object_unref(current);
7305 
7306       current->next = NULL;
7307     }
7308   }
7309 }
7310 
7311 void
ags_audio_set_pads_remove_notes(AgsAudio * audio,GType channel_type,guint pads)7312 ags_audio_set_pads_remove_notes(AgsAudio *audio,
7313 				GType channel_type,
7314 				guint pads)
7315 {
7316   GList *notation;
7317   GList *note_start, *note;
7318 
7319   GRecMutex *audio_mutex;
7320 
7321   if(!AGS_IS_AUDIO(audio)){
7322     return;
7323   }
7324 
7325   /* get audio mutex */
7326   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
7327 
7328   g_rec_mutex_lock(audio_mutex);
7329 
7330   notation = audio->notation;
7331 
7332   while(notation != NULL){
7333     note =
7334       note_start = g_list_copy(AGS_NOTATION(notation->data)->note);
7335 
7336     while(note != NULL){
7337       if(AGS_NOTE(note->data)->y >= pads){
7338 	AGS_NOTATION(notation->data)->note = g_list_remove(AGS_NOTATION(notation->data)->note,
7339 							   note->data);
7340 
7341 	g_object_unref(note->data);
7342       }
7343 
7344       note = note->next;
7345     }
7346 
7347     g_list_free(note_start);
7348 
7349     notation = notation->next;
7350   }
7351 
7352   g_rec_mutex_unlock(audio_mutex);
7353 }
7354 
7355 void
ags_audio_set_pads_shrink_automation(AgsAudio * audio,GType channel_type,guint pads)7356 ags_audio_set_pads_shrink_automation(AgsAudio *audio,
7357 				     GType channel_type,
7358 				     guint pads)
7359 {
7360   GList *list_start, *list;
7361 
7362   guint audio_channels;
7363 
7364   GRecMutex *audio_mutex;
7365 
7366   if(!AGS_IS_AUDIO(audio)){
7367     return;
7368   }
7369 
7370   /* get audio mutex */
7371   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
7372 
7373   g_rec_mutex_lock(audio_mutex);
7374 
7375   audio_channels = audio->audio_channels;
7376 
7377   list =
7378     list_start = g_list_copy(audio->automation);
7379 
7380   while(list != NULL){
7381     if(AGS_AUTOMATION(list->data)->channel_type == channel_type &&
7382        AGS_AUTOMATION(list->data)->line >= pads * audio_channels){
7383       ags_audio_remove_automation(audio,
7384 				  list->data);
7385 
7386       g_object_run_dispose((GObject *) list->data);
7387       g_object_unref((GObject *) list->data);
7388     }
7389 
7390     list = list->next;
7391   }
7392 
7393   g_list_free(list_start);
7394 
7395   g_rec_mutex_unlock(audio_mutex);
7396 }
7397 
7398 void
ags_audio_set_pads_shrink_wave(AgsAudio * audio,GType channel_type,guint pads)7399 ags_audio_set_pads_shrink_wave(AgsAudio *audio,
7400 			       GType channel_type,
7401 			       guint pads)
7402 {
7403   GList *list_start, *list;
7404 
7405   GRecMutex *audio_mutex;
7406 
7407   if(!AGS_IS_AUDIO(audio)){
7408     return;
7409   }
7410 
7411   /* get audio mutex */
7412   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
7413 
7414   g_rec_mutex_lock(audio_mutex);
7415 
7416   list =
7417     list_start = g_list_copy(audio->wave);
7418 
7419   while(list != NULL){
7420     ags_audio_remove_wave(audio,
7421 			  list->data);
7422 
7423     g_object_run_dispose((GObject *) list->data);
7424     g_object_unref((GObject *) list->data);
7425 
7426     list = list->next;
7427   }
7428 
7429   g_list_free(audio->wave);
7430   g_list_free(list_start);
7431 
7432   audio->wave = NULL;
7433 
7434   g_rec_mutex_unlock(audio_mutex);
7435 }
7436 
7437 void
ags_audio_set_pads_shrink_midi(AgsAudio * audio,GType channel_type,guint pads)7438 ags_audio_set_pads_shrink_midi(AgsAudio *audio,
7439 			       GType channel_type,
7440 			       guint pads)
7441 {
7442   GList *list_start, *list;
7443 
7444   GRecMutex *audio_mutex;
7445 
7446   if(!AGS_IS_AUDIO(audio)){
7447     return;
7448   }
7449 
7450   /* get audio mutex */
7451   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
7452 
7453   g_rec_mutex_lock(audio_mutex);
7454 
7455   list =
7456     list_start = g_list_copy(audio->midi);
7457 
7458   while(list != NULL){
7459     ags_audio_remove_midi(audio,
7460 			  list->data);
7461 
7462     g_object_run_dispose((GObject *) list->data);
7463     g_object_unref((GObject *) list->data);
7464 
7465     list = list->next;
7466   }
7467 
7468   g_list_free(audio->midi);
7469   g_list_free(list_start);
7470 
7471   audio->midi = NULL;
7472 
7473   g_rec_mutex_unlock(audio_mutex);
7474 }
7475 
7476 /*
7477  * resize
7478  * AgsInput has to be allocated first
7479  */
7480 void
ags_audio_real_set_pads(AgsAudio * audio,GType channel_type,guint pads,guint pads_old)7481 ags_audio_real_set_pads(AgsAudio *audio,
7482 			GType channel_type,
7483 			guint pads, guint pads_old)
7484 {
7485   AgsChannel *start_channel, *channel, *next_channel;
7486   AgsPlaybackDomain *playback_domain;
7487 
7488   AgsMessageDelivery *message_delivery;
7489 
7490   GList *start_message_queue;
7491 
7492   guint bank_dim[3];
7493 
7494   guint audio_flags;
7495   guint ability_flags;
7496   guint behaviour_flags;
7497   guint audio_channels;
7498   guint output_pads, input_pads;
7499   gboolean add_recycling;
7500   gboolean add_pattern;
7501   gboolean add_synth_generator;
7502   gboolean link_recycling;
7503   gboolean set_sync_link, set_async_link;
7504 
7505   GRecMutex *audio_mutex;
7506 
7507   if(!(g_type_is_a(channel_type,
7508 		   AGS_TYPE_OUTPUT) ||
7509        g_type_is_a(channel_type,
7510 		   AGS_TYPE_INPUT))){
7511     g_warning("unknown channel type");
7512 
7513     return;
7514   }
7515 
7516   if(pads_old == pads){
7517     return;
7518   }
7519 
7520   /* get audio mutex */
7521   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
7522 
7523   /* get some fields */
7524   g_rec_mutex_lock(audio_mutex);
7525 
7526   audio_flags = audio->flags;
7527   ability_flags = audio->ability_flags;
7528   behaviour_flags = audio->behaviour_flags;
7529 
7530   audio_channels = audio->audio_channels;
7531 
7532   output_pads = audio->output_pads;
7533   input_pads = audio->input_pads;
7534 
7535   g_rec_mutex_unlock(audio_mutex);
7536 
7537   /* get some fields */
7538   g_object_get(audio,
7539 	       "playback-domain", &playback_domain,
7540 	       NULL);
7541 
7542   add_recycling = FALSE;
7543   add_pattern = FALSE;
7544   add_synth_generator = FALSE;
7545 
7546   link_recycling = FALSE;
7547   set_sync_link = FALSE;
7548   set_async_link = FALSE;
7549 
7550   if(g_type_is_a(channel_type,
7551 		 AGS_TYPE_OUTPUT) &&
7552      (AGS_AUDIO_NO_OUTPUT & (audio_flags)) == 0){
7553     if((AGS_AUDIO_OUTPUT_HAS_RECYCLING & (audio_flags)) != 0){
7554       add_recycling = TRUE;
7555     }else{
7556       if((AGS_AUDIO_INPUT_HAS_RECYCLING & (audio_flags)) != 0){
7557 	if((AGS_AUDIO_SYNC & (audio_flags)) != 0 && (AGS_AUDIO_ASYNC & (audio_flags)) == 0){
7558 	  set_async_link = TRUE;
7559 	}else if((AGS_AUDIO_ASYNC & (audio_flags)) != 0){
7560 	  set_async_link = TRUE;
7561 	}else{
7562 #ifdef AGS_DEBUG
7563 	  g_message("ags_audio_set_pads - warning: AGS_AUDIO_SYNC nor AGS_AUDIO_ASYNC aren't defined");
7564 #endif
7565 	}
7566       }
7567     }
7568 
7569     /* output */
7570     if(audio_channels != 0){
7571       /* grow or shrink */
7572       if(pads > output_pads){
7573 	guint i, j;
7574 
7575 	/* grow channels */
7576 	ags_audio_set_pads_grow(audio,
7577 				AGS_TYPE_OUTPUT,
7578 				pads, pads_old,
7579 				0, 0, 0,
7580 				add_recycling, add_pattern, add_synth_generator,
7581 				link_recycling,
7582 				set_sync_link, set_async_link);
7583 
7584 	/* get some fields */
7585 	g_object_get(audio,
7586 		     "output", &start_channel,
7587 		     NULL);
7588 
7589 	/* set ability flags */
7590 	channel = ags_channel_pad_nth(start_channel,
7591 				      pads_old);
7592 
7593 	for(j = pads_old; j < pads; j++){
7594 	  for(i = 0; i < audio_channels; i++){
7595 	    ags_channel_set_ability_flags(channel, ability_flags);
7596 
7597 	    /* iterate */
7598 	    next_channel = ags_channel_next(channel);
7599 
7600 	    if(channel != NULL){
7601 	      g_object_unref(channel);
7602 	    }
7603 
7604 	    channel = next_channel;
7605 	  }
7606 	}
7607 
7608 	if(start_channel != NULL){
7609 	  g_object_unref(start_channel);
7610 	}
7611       }else if(pads == 0){
7612 	GList *start_list, *list;
7613 
7614 	ags_audio_set_pads_shrink_automation(audio,
7615 					     AGS_TYPE_OUTPUT,
7616 					     pads);
7617 
7618 	if((AGS_SOUND_BEHAVIOUR_DEFAULTS_TO_OUTPUT & (behaviour_flags)) != 0){
7619 	  if((AGS_SOUND_ABILITY_NOTATION & (ability_flags)) != 0){
7620 	    ags_audio_set_pads_remove_notes(audio,
7621 					    AGS_TYPE_OUTPUT,
7622 					    pads);
7623 	  }
7624 
7625 	  if((AGS_SOUND_ABILITY_WAVE & (ability_flags)) != 0){
7626 	    ags_audio_set_pads_shrink_wave(audio,
7627 					   AGS_TYPE_OUTPUT,
7628 					   pads);
7629 	  }
7630 
7631 	  if((AGS_SOUND_ABILITY_MIDI & (ability_flags)) != 0){
7632 	    ags_audio_set_pads_shrink_midi(audio,
7633 					   AGS_TYPE_OUTPUT,
7634 					   pads);
7635 	  }
7636 	}
7637 
7638 	/* unlink and remove */
7639 	ags_audio_set_pads_unlink(audio,
7640 				  AGS_TYPE_OUTPUT,
7641 				  0);
7642 	ags_audio_set_pads_shrink_zero(audio,
7643 				       AGS_TYPE_OUTPUT,
7644 				       0);
7645 
7646 	g_rec_mutex_lock(audio_mutex);
7647 
7648 	audio->output = NULL;
7649 
7650 	g_rec_mutex_unlock(audio_mutex);
7651       }else if(pads < output_pads){
7652 	GList *start_list, *list;
7653 
7654 	/* get some fields */
7655 	ags_audio_set_pads_shrink_automation(audio,
7656 					     AGS_TYPE_OUTPUT,
7657 					     pads);
7658 	ags_audio_set_pads_remove_notes(audio,
7659 					AGS_TYPE_OUTPUT,
7660 					pads);
7661 
7662 	ags_audio_set_pads_unlink(audio,
7663 				  AGS_TYPE_OUTPUT,
7664 				  pads);
7665 	ags_audio_set_pads_shrink(audio,
7666 				  AGS_TYPE_OUTPUT,
7667 				  pads);
7668       }
7669     }
7670 
7671     /* apply new size */
7672     g_rec_mutex_lock(audio_mutex);
7673 
7674     audio->output_pads = pads;
7675     audio->output_lines = pads * audio_channels;
7676 
7677     g_rec_mutex_unlock(audio_mutex);
7678 
7679     //    if((AGS_AUDIO_SYNC & audio_flags) != 0 && (AGS_AUDIO_ASYNC & audio_flags) == 0){
7680     //TODO:JK: fix me
7681     //      input_pads = pads;
7682     //      audio->input_lines = pads * audio_channels;
7683     //    }
7684   }else if(g_type_is_a(channel_type,
7685 		       AGS_TYPE_INPUT) &&
7686 	   (AGS_AUDIO_NO_INPUT & (audio_flags)) == 0){
7687     if((AGS_AUDIO_INPUT_HAS_SYNTH & (audio_flags)) != 0){
7688       add_synth_generator = TRUE;
7689     }
7690 
7691     if((AGS_AUDIO_INPUT_HAS_RECYCLING & (audio_flags)) != 0){
7692       add_recycling = TRUE;
7693     }
7694 
7695     if((AGS_AUDIO_ASYNC & (audio_flags)) != 0 && add_recycling){
7696       link_recycling = TRUE;
7697     }
7698 
7699     bank_dim[0] = 0;
7700     bank_dim[1] = 0;
7701     bank_dim[2] = 0;
7702 
7703     g_rec_mutex_lock(audio_mutex);
7704 
7705     if((AGS_SOUND_ABILITY_SEQUENCER & (ability_flags)) != 0){
7706       add_pattern = TRUE;
7707 
7708       bank_dim[0] = audio->bank_dim[0];
7709       bank_dim[1] = audio->bank_dim[1];
7710       bank_dim[2] = audio->bank_dim[2];
7711     }
7712 
7713     g_rec_mutex_unlock(audio_mutex);
7714 
7715     /* input */
7716     if(audio_channels != 0){
7717       /* grow or shrink */
7718       if(pads > pads_old){
7719 	AgsChannel *current;
7720 
7721 	guint i, j;
7722 
7723 	/* grow channels */
7724 	ags_audio_set_pads_grow(audio,
7725 				AGS_TYPE_INPUT,
7726 				pads, pads_old,
7727 				bank_dim[0], bank_dim[1], bank_dim[2],
7728 				add_recycling, add_pattern, add_synth_generator,
7729 				link_recycling,
7730 				set_sync_link, set_async_link);
7731 
7732 	/* get some fields */
7733 	g_object_get(audio,
7734 		     "input", &start_channel,
7735 		     NULL);
7736 
7737 	/* set ability flags */
7738 	channel = ags_channel_pad_nth(start_channel,
7739 				      pads_old);
7740 
7741 	for(j = pads_old; j < pads; j++){
7742 	  for(i = 0; i < audio_channels; i++){
7743 	    ags_channel_set_ability_flags(channel, ability_flags);
7744 
7745 	    /* iterate */
7746 	    next_channel = ags_channel_next(channel);
7747 
7748 	    if(channel != NULL){
7749 	      g_object_unref(channel);
7750 	    }
7751 
7752 	    channel = next_channel;
7753 	  }
7754 	}
7755 
7756 	if(start_channel != NULL){
7757 	  g_object_unref(start_channel);
7758 	}
7759       }else if(pads == 0){
7760 	GList *start_list, *list;
7761 
7762 	ags_audio_set_pads_shrink_automation(audio,
7763 					     AGS_TYPE_INPUT,
7764 					     pads);
7765 
7766 	if((AGS_SOUND_BEHAVIOUR_DEFAULTS_TO_INPUT & (behaviour_flags)) != 0){
7767 	  if((AGS_SOUND_ABILITY_NOTATION & (ability_flags)) != 0){
7768 	    ags_audio_set_pads_remove_notes(audio,
7769 					    AGS_TYPE_INPUT,
7770 					    pads);
7771 	  }
7772 
7773 	  if((AGS_SOUND_ABILITY_WAVE & (ability_flags)) != 0){
7774 	    ags_audio_set_pads_shrink_wave(audio,
7775 					   AGS_TYPE_INPUT,
7776 					   pads);
7777 	  }
7778 
7779 	  if((AGS_SOUND_ABILITY_MIDI & (ability_flags)) != 0){
7780 	    ags_audio_set_pads_shrink_midi(audio,
7781 					   AGS_TYPE_INPUT,
7782 					   pads);
7783 	  }
7784 	}
7785 
7786 	/* shrink channels */
7787 	ags_audio_set_pads_unlink(audio,
7788 				  AGS_TYPE_INPUT,
7789 				  pads);
7790 	ags_audio_set_pads_shrink_zero(audio,
7791 				       AGS_TYPE_INPUT,
7792 				       pads);
7793 
7794 	g_rec_mutex_lock(audio_mutex);
7795 
7796 	audio->input = NULL;
7797 
7798 	g_rec_mutex_unlock(audio_mutex);
7799       }else if(pads < pads_old){
7800 	GList *start_list, *list;
7801 
7802 	/* get some fields */
7803 	ags_audio_set_pads_shrink_automation(audio,
7804 					     AGS_TYPE_INPUT,
7805 					     pads);
7806 
7807 	ags_audio_set_pads_unlink(audio,
7808 				  AGS_TYPE_INPUT,
7809 				  pads);
7810 	ags_audio_set_pads_shrink(audio,
7811 				  AGS_TYPE_INPUT,
7812 				  pads);
7813       }
7814     }
7815 
7816     /* apply new allocation */
7817     g_rec_mutex_lock(audio_mutex);
7818 
7819     audio->input_pads = pads;
7820     audio->input_lines = pads * audio_channels;
7821 
7822     g_rec_mutex_unlock(audio_mutex);
7823   }
7824 
7825   /* unref */
7826   g_object_unref(playback_domain);
7827 
7828   /* emit message */
7829   message_delivery = ags_message_delivery_get_instance();
7830 
7831   start_message_queue = ags_message_delivery_find_sender_namespace(message_delivery,
7832 								   "libags-audio");
7833 
7834   if(start_message_queue != NULL){
7835     AgsMessageEnvelope *message;
7836 
7837     xmlDoc *doc;
7838     xmlNode *root_node;
7839 
7840     /* specify message body */
7841     doc = xmlNewDoc("1.0");
7842 
7843     root_node = xmlNewNode(NULL,
7844 			   "ags-command");
7845     xmlDocSetRootElement(doc, root_node);
7846 
7847     xmlNewProp(root_node,
7848 	       "method",
7849 	       "AgsAudio::set-pads");
7850 
7851     /* add message */
7852     message = ags_message_envelope_new((GObject *) audio,
7853 				       NULL,
7854 				       doc);
7855     /* set parameter */
7856     message->n_params = 3;
7857 
7858     message->parameter_name = (gchar *) malloc(4 * sizeof(gchar *));
7859     message->value = g_new0(GValue,
7860 			    3);
7861 
7862     /* channel type */
7863     message->parameter_name[0] = "channel-type";
7864 
7865     g_value_init(&(message->value[0]),
7866 		 G_TYPE_ULONG);
7867     g_value_set_ulong(&(message->value[0]),
7868 		      channel_type);
7869 
7870     /* pads */
7871     message->parameter_name[1] = "pads";
7872 
7873     g_value_init(&(message->value[1]),
7874 		 G_TYPE_UINT);
7875     g_value_set_uint(&(message->value[1]),
7876 		     pads);
7877 
7878     /* pads old */
7879     message->parameter_name[2] = "pads-old";
7880 
7881     g_value_init(&(message->value[2]),
7882 		 G_TYPE_UINT);
7883     g_value_set_uint(&(message->value[2]),
7884 		     pads_old);
7885 
7886     /* terminate string vector */
7887     message->parameter_name[3] = NULL;
7888 
7889     /* add message */
7890     ags_message_delivery_add_message_envelope(message_delivery,
7891 					      "libags-audio",
7892 					      message);
7893 
7894     g_list_free_full(start_message_queue,
7895 		     (GDestroyNotify) g_object_unref);
7896   }
7897 }
7898 
7899 /**
7900  * ags_audio_set_pads:
7901  * @audio: the #AgsAudio
7902  * @channel_type: AGS_TYPE_INPUT or AGS_TYPE_OUTPUT
7903  * @pads: new pad count
7904  * @pads_old: old pad count
7905  *
7906  * Set pad count for the apropriate @channel_type
7907  *
7908  * Since: 3.0.0
7909  */
7910 void
ags_audio_set_pads(AgsAudio * audio,GType channel_type,guint pads,guint pads_old)7911 ags_audio_set_pads(AgsAudio *audio,
7912 		   GType channel_type,
7913 		   guint pads, guint pads_old)
7914 {
7915   GRecMutex *audio_mutex;
7916 
7917   g_return_if_fail(AGS_IS_AUDIO(audio));
7918 
7919   /* get audio mutex */
7920   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
7921 
7922   /* get output/input pads old */
7923   g_rec_mutex_lock(audio_mutex);
7924 
7925   pads_old = ((g_type_is_a(channel_type, AGS_TYPE_OUTPUT)) ? audio->output_pads: audio->input_pads);
7926 
7927   g_rec_mutex_unlock(audio_mutex);
7928 
7929   /* emit */
7930   g_object_ref((GObject *) audio);
7931   g_signal_emit(G_OBJECT(audio),
7932 		audio_signals[SET_PADS], 0,
7933 		channel_type,
7934 		pads, pads_old);
7935   g_object_unref((GObject *) audio);
7936 }
7937 
7938 /**
7939  * ags_audio_get_output_lines:
7940  * @audio: the #AgsAudio
7941  *
7942  * Get output lines.
7943  *
7944  * Returns: the output lines
7945  *
7946  * Since: 3.1.0
7947  */
7948 guint
ags_audio_get_output_lines(AgsAudio * audio)7949 ags_audio_get_output_lines(AgsAudio *audio)
7950 {
7951   guint output_lines;
7952 
7953   if(!AGS_IS_AUDIO(audio)){
7954     return(0);
7955   }
7956 
7957   g_object_get(audio,
7958 	       "output-lines", &output_lines,
7959 	       NULL);
7960 
7961   return(output_lines);
7962 }
7963 
7964 /**
7965  * ags_audio_get_input_lines:
7966  * @audio: the #AgsAudio
7967  *
7968  * Get input lines.
7969  *
7970  * Returns: the input lines
7971  *
7972  * Since: 3.1.0
7973  */
7974 guint
ags_audio_get_input_lines(AgsAudio * audio)7975 ags_audio_get_input_lines(AgsAudio *audio)
7976 {
7977   guint input_lines;
7978 
7979   if(!AGS_IS_AUDIO(audio)){
7980     return(0);
7981   }
7982 
7983   g_object_get(audio,
7984 	       "input-lines", &input_lines,
7985 	       NULL);
7986 
7987   return(input_lines);
7988 }
7989 
7990 /**
7991  * ags_audio_get_output:
7992  * @audio: the #AgsAudio
7993  *
7994  * Get the output object of @audio.
7995  *
7996  * Returns: (transfer full): the output
7997  *
7998  * Since: 3.1.0
7999  */
8000 AgsChannel*
ags_audio_get_output(AgsAudio * audio)8001 ags_audio_get_output(AgsAudio *audio)
8002 {
8003   AgsChannel *output;
8004 
8005   if(!AGS_IS_AUDIO(audio)){
8006     return(NULL);
8007   }
8008 
8009   g_object_get(audio,
8010 	       "output", &output,
8011 	       NULL);
8012 
8013   return(output);
8014 }
8015 
8016 /**
8017  * ags_audio_get_input:
8018  * @audio: the #AgsAudio
8019  *
8020  * Get the input object of @audio.
8021  *
8022  * Returns: (transfer full): the input
8023  *
8024  * Since: 3.1.0
8025  */
8026 AgsChannel*
ags_audio_get_input(AgsAudio * audio)8027 ags_audio_get_input(AgsAudio *audio)
8028 {
8029   AgsChannel *input;
8030 
8031   if(!AGS_IS_AUDIO(audio)){
8032     return(NULL);
8033   }
8034 
8035   g_object_get(audio,
8036 	       "input", &input,
8037 	       NULL);
8038 
8039   return(input);
8040 }
8041 
8042 /**
8043  * ags_audio_get_output_soundcard:
8044  * @audio: the #AgsAudio
8045  *
8046  * Get the output soundcard object of @audio.
8047  *
8048  * Returns: (transfer full): the output soundcard
8049  *
8050  * Since: 3.1.0
8051  */
8052 GObject*
ags_audio_get_output_soundcard(AgsAudio * audio)8053 ags_audio_get_output_soundcard(AgsAudio *audio)
8054 {
8055   GObject *output_soundcard;
8056 
8057   if(!AGS_IS_AUDIO(audio)){
8058     return(NULL);
8059   }
8060 
8061   g_object_get(audio,
8062 	       "output-soundcard", &output_soundcard,
8063 	       NULL);
8064 
8065   return(output_soundcard);
8066 }
8067 
8068 void
ags_audio_real_set_output_soundcard(AgsAudio * audio,GObject * output_soundcard)8069 ags_audio_real_set_output_soundcard(AgsAudio *audio,
8070 				    GObject *output_soundcard)
8071 {
8072   AgsChannel *start_channel, *channel, *next_channel;
8073   AgsPlaybackDomain *playback_domain;
8074 
8075   AgsThread *audio_thread;
8076 
8077   GObject *old_soundcard;
8078 
8079   GList *list;
8080 
8081   guint samplerate;
8082   guint buffer_size;
8083   guint format;
8084   guint i;
8085 
8086   GRecMutex *audio_mutex;
8087   GRecMutex *play_mutex, *recall_mutex;
8088 
8089   if(!AGS_IS_AUDIO(audio)){
8090     return;
8091   }
8092 
8093   /* get audio mutex */
8094   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
8095 
8096   /* old soundcard */
8097   g_rec_mutex_lock(audio_mutex);
8098 
8099   old_soundcard = audio->output_soundcard;
8100 
8101   g_rec_mutex_unlock(audio_mutex);
8102 
8103   if(old_soundcard == output_soundcard){
8104     return;
8105   }
8106 
8107   /* ref and set new soundcard */
8108   if(output_soundcard != NULL){
8109     g_object_ref(output_soundcard);
8110   }
8111 
8112   g_rec_mutex_lock(audio_mutex);
8113 
8114   audio->output_soundcard = (GObject *) output_soundcard;
8115 
8116   g_rec_mutex_unlock(audio_mutex);
8117 
8118   if(output_soundcard != NULL){
8119     /* get presets */
8120     ags_soundcard_get_presets(AGS_SOUNDCARD(output_soundcard),
8121 			      NULL,
8122 			      &samplerate,
8123 			      &buffer_size,
8124 			      &format);
8125 
8126     /* apply presets */
8127     g_object_set(audio,
8128 		 "samplerate", samplerate,
8129 		 "buffer-size", buffer_size,
8130 		 "format", format,
8131 		 NULL);
8132   }
8133 
8134   /* output */
8135   g_object_get(audio,
8136 	       "output", &start_channel,
8137 	       NULL);
8138 
8139   if(start_channel != NULL){
8140     channel = start_channel;
8141     g_object_ref(start_channel);
8142 
8143     while(channel != NULL){
8144       /* reset */
8145       g_object_set(G_OBJECT(channel),
8146 		   "output-soundcard", output_soundcard,
8147 		   NULL);
8148 
8149       /* iterate */
8150       next_channel = ags_channel_next(channel);
8151 
8152       g_object_unref(channel);
8153 
8154       channel = next_channel;
8155     }
8156 
8157     g_object_unref(start_channel);
8158   }
8159 
8160   /* input */
8161   g_object_get(audio,
8162 	       "input", &start_channel,
8163 	       NULL);
8164 
8165   if(start_channel != NULL){
8166     channel = start_channel;
8167     g_object_ref(start_channel);
8168 
8169     while(channel != NULL){
8170       /* reset */
8171       g_object_set(G_OBJECT(channel),
8172 		   "output-soundcard", output_soundcard,
8173 		   NULL);
8174 
8175       /* iterate */
8176       next_channel = ags_channel_next(channel);
8177 
8178       g_object_unref(channel);
8179 
8180       channel = next_channel;
8181     }
8182 
8183     g_object_unref(start_channel);
8184   }
8185 
8186   /* playback domain - audio thread */
8187   g_object_get(audio,
8188 	       "playback-domain", &playback_domain,
8189 	       NULL);
8190 
8191   /* audio thread - output soundcard */
8192   for(i = 0; i < AGS_SOUND_SCOPE_LAST; i++){
8193     audio_thread = ags_playback_domain_get_audio_thread(playback_domain,
8194 							i);
8195 
8196     if(audio_thread != NULL){
8197       /* set output soundcard */
8198       g_object_set(audio_thread,
8199 		   "default-output-soundcard", output_soundcard,
8200 		   NULL);
8201 
8202       g_object_unref(audio_thread);
8203     }
8204   }
8205 
8206   g_object_unref(playback_domain);
8207 
8208   /* get play mutex */
8209   play_mutex = AGS_AUDIO_GET_PLAY_MUTEX(audio);
8210 
8211   /* play context */
8212   g_rec_mutex_lock(play_mutex);
8213 
8214   list = audio->play;
8215 
8216   while(list != NULL){
8217     g_object_set(G_OBJECT(list->data),
8218 		 "output-soundcard", output_soundcard,
8219 		 NULL);
8220 
8221     list = list->next;
8222   }
8223 
8224   g_rec_mutex_unlock(play_mutex);
8225 
8226   /* get recall mutex */
8227   recall_mutex = AGS_AUDIO_GET_RECALL_MUTEX(audio);
8228 
8229   /* recall context */
8230   g_rec_mutex_lock(recall_mutex);
8231 
8232   list = audio->recall;
8233 
8234   while(list != NULL){
8235     g_object_set(G_OBJECT(list->data),
8236 		 "output-soundcard", output_soundcard,
8237 		 NULL);
8238 
8239     list = list->next;
8240   }
8241 
8242   g_rec_mutex_unlock(recall_mutex);
8243 
8244   /* unref old soundcard */
8245   if(old_soundcard != NULL){
8246     g_object_unref(old_soundcard);
8247   }
8248 }
8249 
8250 /**
8251  * ags_audio_set_output_soundcard:
8252  * @audio: the #AgsAudio
8253  * @output_soundcard: the #GObject implementing #AgsSoundcard
8254  *
8255  * Set the output soundcard object of @audio.
8256  *
8257  * Since: 3.0.0
8258  */
8259 void
ags_audio_set_output_soundcard(AgsAudio * audio,GObject * output_soundcard)8260 ags_audio_set_output_soundcard(AgsAudio *audio, GObject *output_soundcard)
8261 {
8262   if(!AGS_IS_AUDIO(audio)){
8263     return;
8264   }
8265 
8266   g_object_set(audio,
8267 	       "output-soundcard", output_soundcard,
8268 	       NULL);
8269 }
8270 
8271 /**
8272  * ags_audio_get_input_soundcard:
8273  * @audio: the #AgsAudio
8274  *
8275  * Get the input soundcard object of @audio.
8276  *
8277  * Returns: (transfer full): the input soundcard
8278  *
8279  * Since: 3.1.0
8280  */
8281 GObject*
ags_audio_get_input_soundcard(AgsAudio * audio)8282 ags_audio_get_input_soundcard(AgsAudio *audio)
8283 {
8284   GObject *input_soundcard;
8285 
8286   if(!AGS_IS_AUDIO(audio)){
8287     return(NULL);
8288   }
8289 
8290   g_object_get(audio,
8291 	       "input-soundcard", &input_soundcard,
8292 	       NULL);
8293 
8294   return(input_soundcard);
8295 }
8296 
8297 void
ags_audio_real_set_input_soundcard(AgsAudio * audio,GObject * input_soundcard)8298 ags_audio_real_set_input_soundcard(AgsAudio *audio,
8299 				   GObject *input_soundcard)
8300 {
8301   AgsChannel *start_channel, *channel, *next_channel;
8302 
8303   GObject *old_soundcard;
8304 
8305   GList *list;
8306 
8307   GRecMutex *audio_mutex;
8308   GRecMutex *play_mutex, *recall_mutex;
8309 
8310   if(!AGS_IS_AUDIO(audio)){
8311     return;
8312   }
8313 
8314   /* get audio mutex */
8315   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
8316 
8317   /* old soundcard */
8318   g_rec_mutex_lock(audio_mutex);
8319 
8320   old_soundcard = audio->input_soundcard;
8321 
8322   g_rec_mutex_unlock(audio_mutex);
8323 
8324   if(old_soundcard == input_soundcard){
8325     return;
8326   }
8327 
8328   /* ref and set new soundcard */
8329   if(input_soundcard != NULL){
8330     g_object_ref(input_soundcard);
8331   }
8332 
8333   g_rec_mutex_lock(audio_mutex);
8334 
8335   audio->input_soundcard = (GObject *) input_soundcard;
8336 
8337   g_rec_mutex_unlock(audio_mutex);
8338 
8339   /* output */
8340   g_object_get(audio,
8341 	       "output", &start_channel,
8342 	       NULL);
8343 
8344   if(start_channel != NULL){
8345     channel = start_channel;
8346     g_object_ref(start_channel);
8347 
8348     while(channel != NULL){
8349       /* reset */
8350       g_object_set(G_OBJECT(channel),
8351 		   "input-soundcard", input_soundcard,
8352 		   NULL);
8353 
8354       /* iterate */
8355       next_channel = ags_channel_next(channel);
8356 
8357       g_object_unref(channel);
8358 
8359       channel = next_channel;
8360     }
8361 
8362     g_object_unref(start_channel);
8363   }
8364 
8365   /* input */
8366   g_object_get(audio,
8367 	       "input", &start_channel,
8368 	       NULL);
8369 
8370   if(start_channel != NULL){
8371     channel = start_channel;
8372     g_object_ref(start_channel);
8373 
8374     while(channel != NULL){
8375       /* reset */
8376       g_object_set(G_OBJECT(channel),
8377 		   "input-soundcard", input_soundcard,
8378 		   NULL);
8379 
8380       /* iterate */
8381       next_channel = ags_channel_next(channel);
8382 
8383       g_object_unref(channel);
8384 
8385       channel = next_channel;
8386     }
8387 
8388     g_object_unref(start_channel);
8389   }
8390 
8391   /* get play mutex */
8392   play_mutex = AGS_AUDIO_GET_PLAY_MUTEX(audio);
8393 
8394   /* play context */
8395   g_rec_mutex_lock(play_mutex);
8396 
8397   list = audio->play;
8398 
8399   while(list != NULL){
8400     g_object_set(G_OBJECT(list->data),
8401 		 "input-soundcard", input_soundcard,
8402 		 NULL);
8403 
8404     list = list->next;
8405   }
8406 
8407   g_rec_mutex_unlock(play_mutex);
8408 
8409   /* get recall mutex */
8410   recall_mutex = AGS_AUDIO_GET_RECALL_MUTEX(audio);
8411 
8412   /* recall context */
8413   g_rec_mutex_lock(recall_mutex);
8414 
8415   list = audio->recall;
8416 
8417   while(list != NULL){
8418     g_object_set(G_OBJECT(list->data),
8419 		 "input-soundcard", input_soundcard,
8420 		 NULL);
8421 
8422     list = list->next;
8423   }
8424 
8425   g_rec_mutex_unlock(recall_mutex);
8426 
8427   /* unref old soundcard */
8428   if(old_soundcard != NULL){
8429     g_object_unref(old_soundcard);
8430   }
8431 }
8432 
8433 /**
8434  * ags_audio_set_input_soundcard:
8435  * @audio: an #AgsAudio
8436  * @input_soundcard: the #GObject implementing #AgsSoundcard
8437  *
8438  * Set the input soundcard object of @audio.
8439  *
8440  * Since: 3.0.0
8441  */
8442 void
ags_audio_set_input_soundcard(AgsAudio * audio,GObject * input_soundcard)8443 ags_audio_set_input_soundcard(AgsAudio *audio, GObject *input_soundcard)
8444 {
8445   if(!AGS_IS_AUDIO(audio)){
8446     return;
8447   }
8448 
8449   g_object_set(audio,
8450 	       "input-soundcard", input_soundcard,
8451 	       NULL);
8452 }
8453 
8454 /**
8455  * ags_audio_get_output_sequencer:
8456  * @audio: the #AgsAudio
8457  *
8458  * Get the output sequencer object of @audio.
8459  *
8460  * Returns: (transfer full): the output sequencer
8461  *
8462  * Since: 3.1.0
8463  */
8464 GObject*
ags_audio_get_output_sequencer(AgsAudio * audio)8465 ags_audio_get_output_sequencer(AgsAudio *audio)
8466 {
8467   GObject *output_sequencer;
8468 
8469   if(!AGS_IS_AUDIO(audio)){
8470     return(NULL);
8471   }
8472 
8473   g_object_get(audio,
8474 	       "output-sequencer", &output_sequencer,
8475 	       NULL);
8476 
8477   return(output_sequencer);
8478 }
8479 
8480 void
ags_audio_real_set_output_sequencer(AgsAudio * audio,GObject * sequencer)8481 ags_audio_real_set_output_sequencer(AgsAudio *audio,
8482 				    GObject *sequencer)
8483 {
8484   GObject *old_sequencer;
8485 
8486   GRecMutex *audio_mutex;
8487 
8488   if(!AGS_IS_AUDIO(audio)){
8489     return;
8490   }
8491 
8492   /* get audio mutex */
8493   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
8494 
8495   /* old sequencer */
8496   g_rec_mutex_lock(audio_mutex);
8497 
8498   old_sequencer = audio->output_sequencer;
8499 
8500   g_rec_mutex_unlock(audio_mutex);
8501 
8502   if(old_sequencer == sequencer){
8503     return;
8504   }
8505 
8506   /* ref and set new sequencer */
8507   if(sequencer != NULL){
8508     g_object_ref(sequencer);
8509   }
8510 
8511   g_rec_mutex_lock(audio_mutex);
8512 
8513   audio->output_sequencer = (GObject *) sequencer;
8514 
8515   g_rec_mutex_unlock(audio_mutex);
8516 
8517   /* unref old sequencer */
8518   if(old_sequencer != NULL){
8519     g_object_unref(old_sequencer);
8520   }
8521 }
8522 
8523 /**
8524  * ags_audio_set_output_sequencer:
8525  * @audio: an #AgsAudio
8526  * @output_sequencer: the #GObject implementing #AgsSequencer
8527  *
8528  * Set the output sequencer object of @audio.
8529  *
8530  * Since: 3.0.0
8531  */
8532 void
ags_audio_set_output_sequencer(AgsAudio * audio,GObject * output_sequencer)8533 ags_audio_set_output_sequencer(AgsAudio *audio, GObject *output_sequencer)
8534 {
8535   if(!AGS_IS_AUDIO(audio)){
8536     return;
8537   }
8538 
8539   g_object_set(audio,
8540 	       "output-sequencer", output_sequencer,
8541 	       NULL);
8542 }
8543 
8544 /**
8545  * ags_audio_get_input_sequencer:
8546  * @audio: the #AgsAudio
8547  *
8548  * Get the input sequencer object of @audio.
8549  *
8550  * Returns: (transfer full): the input sequencer
8551  *
8552  * Since: 3.1.0
8553  */
8554 GObject*
ags_audio_get_input_sequencer(AgsAudio * audio)8555 ags_audio_get_input_sequencer(AgsAudio *audio)
8556 {
8557   GObject *input_sequencer;
8558 
8559   if(!AGS_IS_AUDIO(audio)){
8560     return(NULL);
8561   }
8562 
8563   g_object_get(audio,
8564 	       "input-sequencer", &input_sequencer,
8565 	       NULL);
8566 
8567   return(input_sequencer);
8568 }
8569 
8570 void
ags_audio_real_set_input_sequencer(AgsAudio * audio,GObject * sequencer)8571 ags_audio_real_set_input_sequencer(AgsAudio *audio,
8572 				   GObject *sequencer)
8573 {
8574   GObject *old_sequencer;
8575 
8576   GRecMutex *audio_mutex;
8577 
8578   if(!AGS_IS_AUDIO(audio)){
8579     return;
8580   }
8581 
8582   /* get audio mutex */
8583   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
8584 
8585   /* old sequencer */
8586   g_rec_mutex_lock(audio_mutex);
8587 
8588   old_sequencer = audio->input_sequencer;
8589 
8590   g_rec_mutex_unlock(audio_mutex);
8591 
8592   if(old_sequencer == sequencer){
8593     return;
8594   }
8595 
8596   /* ref and set new sequencer */
8597   if(sequencer != NULL){
8598     g_object_ref(sequencer);
8599   }
8600 
8601   g_rec_mutex_lock(audio_mutex);
8602 
8603   audio->input_sequencer = (GObject *) sequencer;
8604 
8605   g_rec_mutex_unlock(audio_mutex);
8606 
8607   /* unref old sequencer */
8608   if(old_sequencer != NULL){
8609     g_object_unref(old_sequencer);
8610   }
8611 }
8612 
8613 /**
8614  * ags_audio_set_input_sequencer:
8615  * @audio: an #AgsAudio
8616  * @input_sequencer: the #GObject implementing #AgsSequencer
8617  *
8618  * Set the input sequencer object of @audio.
8619  *
8620  * Since: 3.0.0
8621  */
8622 void
ags_audio_set_input_sequencer(AgsAudio * audio,GObject * input_sequencer)8623 ags_audio_set_input_sequencer(AgsAudio *audio, GObject *input_sequencer)
8624 {
8625   if(!AGS_IS_AUDIO(audio)){
8626     return;
8627   }
8628 
8629   g_object_set(audio,
8630 	       "input-sequencer", input_sequencer,
8631 	       NULL);
8632 }
8633 
8634 /**
8635  * ags_audio_get_samplerate:
8636  * @audio: the #AgsAudio
8637  *
8638  * Gets samplerate.
8639  *
8640  * Returns: the samplerate
8641  *
8642  * Since: 3.1.0
8643  */
8644 guint
ags_audio_get_samplerate(AgsAudio * audio)8645 ags_audio_get_samplerate(AgsAudio *audio)
8646 {
8647   guint samplerate;
8648 
8649   if(!AGS_IS_AUDIO(audio)){
8650     return(0);
8651   }
8652 
8653   g_object_get(audio,
8654 	       "samplerate", &samplerate,
8655 	       NULL);
8656 
8657   return(samplerate);
8658 }
8659 
8660 void
ags_audio_set_samplerate_channel(AgsChannel * start_channel,guint samplerate)8661 ags_audio_set_samplerate_channel(AgsChannel *start_channel, guint samplerate)
8662 {
8663   AgsChannel *channel, *next_channel;
8664 
8665   if(!AGS_IS_CHANNEL(start_channel)){
8666     return;
8667   }
8668 
8669   channel = start_channel;
8670   g_object_ref(channel);
8671 
8672   while(channel != NULL){
8673     /* set samplerate */
8674     g_object_set(channel,
8675 		 "samplerate", samplerate,
8676 		 NULL);
8677 
8678     /* iterate */
8679     next_channel = ags_channel_next(channel);
8680 
8681     g_object_unref(channel);
8682 
8683     channel = next_channel;
8684   }
8685 }
8686 
8687 void
ags_audio_real_set_samplerate(AgsAudio * audio,guint samplerate)8688 ags_audio_real_set_samplerate(AgsAudio *audio, guint samplerate)
8689 {
8690   AgsChannel *start_output, *start_input;
8691   AgsPlaybackDomain *playback_domain;
8692 
8693   AgsThread *audio_thread;
8694   AgsMessageDelivery *message_delivery;
8695 
8696   GList *start_message_queue;
8697   GList *start_list, *list;
8698 
8699   gdouble frequency;
8700   guint old_samplerate;
8701   guint i;
8702 
8703   GRecMutex *audio_mutex;
8704 
8705   if(!AGS_IS_AUDIO(audio)){
8706     return;
8707   }
8708 
8709   /* get audio mutex */
8710   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
8711 
8712   /* set samplerate */
8713   g_rec_mutex_lock(audio_mutex);
8714 
8715   old_samplerate = audio->samplerate;
8716 
8717   audio->samplerate = samplerate;
8718 
8719   frequency = ceil((gdouble) audio->samplerate / (gdouble) audio->buffer_size) + AGS_SOUNDCARD_DEFAULT_OVERCLOCK;
8720 
8721   g_rec_mutex_unlock(audio_mutex);
8722 
8723   g_object_get(audio,
8724 	       "output", &start_output,
8725 	       "input", &start_input,
8726 	       "playback-domain", &playback_domain,
8727 	       "synth-generator", &start_list,
8728 	       NULL);
8729 
8730   /* audio thread - frequency */
8731   if(playback_domain != NULL){
8732     for(i = 0; i < AGS_SOUND_SCOPE_LAST; i++){
8733       audio_thread = ags_playback_domain_get_audio_thread(playback_domain,
8734 							  i);
8735 
8736       if(audio_thread != NULL){
8737 	/* apply new frequency */
8738 	g_object_set(audio_thread,
8739 		     "frequency", frequency,
8740 		     NULL);
8741 
8742 	g_object_unref(audio_thread);
8743       }
8744     }
8745   }
8746 
8747   /* set samplerate output/input */
8748   ags_audio_set_samplerate_channel(start_output, samplerate);
8749   ags_audio_set_samplerate_channel(start_input, samplerate);
8750 
8751   /* set samplerate synth generator */
8752   list = start_list;
8753 
8754   while(list != NULL){
8755     g_object_set(list->data,
8756 		 "samplerate", samplerate,
8757 		 NULL);
8758 
8759     list = list->next;
8760   }
8761 
8762   g_list_free_full(start_list,
8763 		   g_object_unref);
8764 
8765   /* unref */
8766   if(start_output != NULL){
8767     g_object_unref(start_output);
8768   }
8769 
8770   if(start_input != NULL){
8771     g_object_unref(start_input);
8772   }
8773 
8774   /* emit message */
8775   message_delivery = ags_message_delivery_get_instance();
8776 
8777   start_message_queue = ags_message_delivery_find_sender_namespace(message_delivery,
8778 								   "libags-audio");
8779 
8780   if(start_message_queue != NULL){
8781     AgsMessageEnvelope *message;
8782 
8783     xmlDoc *doc;
8784     xmlNode *root_node;
8785 
8786     /* specify message body */
8787     doc = xmlNewDoc("1.0");
8788 
8789     root_node = xmlNewNode(NULL,
8790 			   "ags-command");
8791     xmlDocSetRootElement(doc, root_node);
8792 
8793     xmlNewProp(root_node,
8794 	       "method",
8795 	       "AgsAudio::set-samplerate");
8796 
8797     /* add message */
8798     message = ags_message_envelope_new((GObject *) audio,
8799 				       NULL,
8800 				       doc);
8801 
8802     /* set parameter */
8803     message->n_params = 2;
8804 
8805     message->parameter_name = (gchar **) malloc(3 * sizeof(gchar *));
8806     message->value = g_new0(GValue,
8807 			    2);
8808 
8809     /* samplerate */
8810     message->parameter_name[0] = "samplerate";
8811 
8812     g_value_init(&(message->value[0]),
8813 		 G_TYPE_UINT);
8814     g_value_set_uint(&(message->value[0]),
8815 		     samplerate);
8816 
8817     /* old samplerate */
8818     message->parameter_name[1] = "old-samplerate";
8819 
8820     g_value_init(&(message->value[1]),
8821 		 G_TYPE_UINT);
8822     g_value_set_uint(&(message->value[1]),
8823 		     old_samplerate);
8824 
8825     /* terminate string vector */
8826     message->parameter_name[2] = NULL;
8827 
8828     /* add message */
8829     ags_message_delivery_add_message_envelope(message_delivery,
8830 					      "libags-audio",
8831 					      message);
8832 
8833     g_list_free_full(start_message_queue,
8834 		     (GDestroyNotify) g_object_unref);
8835   }
8836 }
8837 
8838 /**
8839  * ags_audio_set_samplerate:
8840  * @audio: the #AgsAudio
8841  * @samplerate: the samplerate
8842  *
8843  * Sets samplerate.
8844  *
8845  * Since: 3.0.0
8846  */
8847 void
ags_audio_set_samplerate(AgsAudio * audio,guint samplerate)8848 ags_audio_set_samplerate(AgsAudio *audio, guint samplerate)
8849 {
8850   if(!AGS_IS_AUDIO(audio)){
8851     return;
8852   }
8853 
8854   g_object_set(audio,
8855 	       "samplerate", samplerate,
8856 	       NULL);
8857 }
8858 
8859 /**
8860  * ags_audio_get_buffer_size:
8861  * @audio: the #AgsAudio
8862  *
8863  * Gets buffer size.
8864  *
8865  * Returns: the buffer size
8866  *
8867  * Since: 3.1.0
8868  */
8869 guint
ags_audio_get_buffer_size(AgsAudio * audio)8870 ags_audio_get_buffer_size(AgsAudio *audio)
8871 {
8872   guint buffer_size;
8873 
8874   if(!AGS_IS_AUDIO(audio)){
8875     return(0);
8876   }
8877 
8878   g_object_get(audio,
8879 	       "buffer-size", &buffer_size,
8880 	       NULL);
8881 
8882   return(buffer_size);
8883 }
8884 
8885 void
ags_audio_set_buffer_size_channel(AgsChannel * start_channel,guint buffer_size)8886 ags_audio_set_buffer_size_channel(AgsChannel *start_channel, guint buffer_size)
8887 {
8888   AgsChannel *channel, *next_channel;
8889 
8890   if(!AGS_IS_CHANNEL(start_channel)){
8891     return;
8892   }
8893 
8894   channel = start_channel;
8895   g_object_ref(channel);
8896 
8897   while(channel != NULL){
8898     /* set buffer size */
8899     g_object_set(channel,
8900 		 "buffer-size", buffer_size,
8901 		 NULL);
8902 
8903     /* iterate */
8904     next_channel = ags_channel_next(channel);
8905 
8906     g_object_unref(channel);
8907 
8908     channel = next_channel;
8909   }
8910 }
8911 
8912 void
ags_audio_real_set_buffer_size(AgsAudio * audio,guint buffer_size)8913 ags_audio_real_set_buffer_size(AgsAudio *audio, guint buffer_size)
8914 {
8915   AgsChannel *start_output, *start_input;
8916   AgsPlaybackDomain *playback_domain;
8917 
8918   AgsThread *audio_thread;
8919   AgsMessageDelivery *message_delivery;
8920 
8921   GList *start_message_queue;
8922   GList *start_list, *list;
8923 
8924   gdouble frequency;
8925   guint old_buffer_size;
8926   guint i;
8927 
8928   GRecMutex *audio_mutex;
8929 
8930   if(!AGS_IS_AUDIO(audio)){
8931     return;
8932   }
8933 
8934   /* get audio mutex */
8935   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
8936 
8937   /* set buffer size */
8938   g_rec_mutex_lock(audio_mutex);
8939 
8940   old_buffer_size = audio->buffer_size;
8941 
8942   audio->buffer_size = buffer_size;
8943 
8944   frequency = ceil((gdouble) audio->samplerate / (gdouble) audio->buffer_size) + AGS_SOUNDCARD_DEFAULT_OVERCLOCK;
8945 
8946   g_rec_mutex_unlock(audio_mutex);
8947 
8948   g_object_get(audio,
8949 	       "output", &start_output,
8950 	       "input", &start_input,
8951 	       "playback-domain", &playback_domain,
8952 	       "synth-generator", &start_list,
8953 	       NULL);
8954 
8955   /* audio thread - frequency */
8956   if(playback_domain != NULL){
8957     for(i = 0; i < AGS_SOUND_SCOPE_LAST; i++){
8958       audio_thread = ags_playback_domain_get_audio_thread(playback_domain,
8959 							  i);
8960 
8961       if(audio_thread != NULL){
8962 	/* apply new frequency */
8963 	g_object_set(playback_domain->audio_thread[i],
8964 		     "frequency", frequency,
8965 		     NULL);
8966 
8967 	g_object_unref(audio_thread);
8968       }
8969     }
8970   }
8971 
8972   /* set buffer size output/input */
8973   ags_audio_set_buffer_size_channel(start_output, buffer_size);
8974   ags_audio_set_buffer_size_channel(start_input, buffer_size);
8975 
8976   /* set buffer size synth generator */
8977   list = start_list;
8978 
8979   while(list != NULL){
8980     g_object_set(list->data,
8981 		 "buffer-size", buffer_size,
8982 		 NULL);
8983 
8984     list = list->next;
8985   }
8986 
8987   g_list_free_full(start_list,
8988 		   g_object_unref);
8989 
8990   /* unref */
8991   if(start_output != NULL){
8992     g_object_unref(start_output);
8993   }
8994 
8995   if(start_input != NULL){
8996     g_object_unref(start_input);
8997   }
8998 
8999   /* emit message */
9000   message_delivery = ags_message_delivery_get_instance();
9001 
9002   start_message_queue = ags_message_delivery_find_sender_namespace(message_delivery,
9003 								   "libags-audio");
9004 
9005   if(start_message_queue != NULL){
9006     AgsMessageEnvelope *message;
9007 
9008     xmlDoc *doc;
9009     xmlNode *root_node;
9010 
9011     /* specify message body */
9012     doc = xmlNewDoc("1.0");
9013 
9014     root_node = xmlNewNode(NULL,
9015 			   "ags-command");
9016     xmlDocSetRootElement(doc, root_node);
9017 
9018     xmlNewProp(root_node,
9019 	       "method",
9020 	       "AgsAudio::set-buffer-size");
9021 
9022     /* add message */
9023     message = ags_message_envelope_new((GObject *) audio,
9024 				       NULL,
9025 				       doc);
9026 
9027     /* set parameter */
9028     message->n_params = 2;
9029 
9030     message->parameter_name = (gchar **) malloc(3 * sizeof(gchar *));
9031     message->value = g_new0(GValue,
9032 			    2);
9033 
9034     /* buffer_size */
9035     message->parameter_name[0] = "buffer-size";
9036 
9037     g_value_init(&(message->value[0]),
9038 		 G_TYPE_UINT);
9039     g_value_set_uint(&(message->value[0]),
9040 		     buffer_size);
9041 
9042     /* old buffer_size */
9043     message->parameter_name[1] = "old-buffer-size";
9044 
9045     g_value_init(&(message->value[1]),
9046 		 G_TYPE_UINT);
9047     g_value_set_uint(&(message->value[1]),
9048 		     old_buffer_size);
9049 
9050     /* terminate string vector */
9051     message->parameter_name[2] = NULL;
9052 
9053     /* add message */
9054     ags_message_delivery_add_message_envelope(message_delivery,
9055 					      "libags-audio",
9056 					      message);
9057 
9058     g_list_free_full(start_message_queue,
9059 		     (GDestroyNotify) g_object_unref);
9060   }
9061 }
9062 
9063 /**
9064  * ags_audio_set_buffer_size:
9065  * @audio: the #AgsAudio
9066  * @buffer_size: the buffer length
9067  *
9068  * Sets buffer length.
9069  *
9070  * Since: 3.0.0
9071  */
9072 void
ags_audio_set_buffer_size(AgsAudio * audio,guint buffer_size)9073 ags_audio_set_buffer_size(AgsAudio *audio, guint buffer_size)
9074 {
9075   if(!AGS_IS_AUDIO(audio)){
9076     return;
9077   }
9078 
9079   g_object_set(audio,
9080 	       "buffer-size", buffer_size,
9081 	       NULL);
9082 }
9083 
9084 /**
9085  * ags_audio_get_format:
9086  * @audio: the #AgsAudio
9087  *
9088  * Gets format.
9089  *
9090  * Returns: the format
9091  *
9092  * Since: 3.1.0
9093  */
9094 guint
ags_audio_get_format(AgsAudio * audio)9095 ags_audio_get_format(AgsAudio *audio)
9096 {
9097   guint format;
9098 
9099   if(!AGS_IS_AUDIO(audio)){
9100     return(0);
9101   }
9102 
9103   g_object_get(audio,
9104 	       "format", &format,
9105 	       NULL);
9106 
9107   return(format);
9108 }
9109 
9110 void
ags_audio_set_format_channel(AgsChannel * start_channel,guint format)9111 ags_audio_set_format_channel(AgsChannel *start_channel, guint format)
9112 {
9113   AgsChannel *channel, *next_channel;
9114 
9115   if(!AGS_IS_CHANNEL(start_channel)){
9116     return;
9117   }
9118 
9119   channel = start_channel;
9120   g_object_ref(channel);
9121 
9122   while(channel != NULL){
9123     /* set format */
9124     g_object_set(channel,
9125 		 "format", format,
9126 		 NULL);
9127 
9128     /* iterate */
9129     next_channel = ags_channel_next(channel);
9130 
9131     g_object_unref(channel);
9132 
9133     channel = next_channel;
9134   }
9135 }
9136 
9137 void
ags_audio_real_set_format(AgsAudio * audio,guint format)9138 ags_audio_real_set_format(AgsAudio *audio, guint format)
9139 {
9140   AgsChannel *start_output, *start_input;
9141 
9142   AgsMessageDelivery *message_delivery;
9143 
9144   GList *start_message_queue;
9145   GList *start_list, *list;
9146 
9147   guint old_format;
9148 
9149   GRecMutex *audio_mutex;
9150 
9151   if(!AGS_IS_AUDIO(audio)){
9152     return;
9153   }
9154 
9155   /* get audio mutex */
9156   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
9157 
9158   /* set format */
9159   g_rec_mutex_lock(audio_mutex);
9160 
9161   old_format = audio->format;
9162 
9163   audio->format = format;
9164 
9165   g_rec_mutex_unlock(audio_mutex);
9166 
9167   g_object_get(audio,
9168 	       "output", &start_output,
9169 	       "input", &start_input,
9170 	       "synth-generator", &start_list,
9171 	       NULL);
9172 
9173   /* set format output/input */
9174   ags_audio_set_format_channel(start_output, format);
9175   ags_audio_set_format_channel(start_input, format);
9176 
9177   /* set format synth generator */
9178   list = start_list;
9179 
9180   while(list != NULL){
9181     g_object_set(list->data,
9182 		 "format", format,
9183 		 NULL);
9184 
9185     list = list->next;
9186   }
9187 
9188   g_list_free_full(start_list,
9189 		   g_object_unref);
9190 
9191   /* unref */
9192   if(start_output != NULL){
9193     g_object_unref(start_output);
9194   }
9195 
9196   if(start_input != NULL){
9197     g_object_unref(start_input);
9198   }
9199 
9200   /* emit message */
9201   message_delivery = ags_message_delivery_get_instance();
9202 
9203   start_message_queue = ags_message_delivery_find_sender_namespace(message_delivery,
9204 								   "libags-audio");
9205 
9206   if(start_message_queue != NULL){
9207     AgsMessageEnvelope *message;
9208 
9209     xmlDoc *doc;
9210     xmlNode *root_node;
9211 
9212     /* specify message body */
9213     doc = xmlNewDoc("1.0");
9214 
9215     root_node = xmlNewNode(NULL,
9216 			   "ags-command");
9217     xmlDocSetRootElement(doc, root_node);
9218 
9219     xmlNewProp(root_node,
9220 	       "method",
9221 	       "AgsAudio::set-format");
9222 
9223     /* add message */
9224     message = ags_message_envelope_new((GObject *) audio,
9225 				       NULL,
9226 				       doc);
9227 
9228     /* set parameter */
9229     message->n_params = 2;
9230 
9231     message->parameter_name = (gchar **) malloc(3 * sizeof(gchar *));
9232     message->value = g_new0(GValue,
9233 			    2);
9234 
9235     /* format */
9236     message->parameter_name[0] = "format";
9237 
9238     g_value_init(&(message->value[0]),
9239 		 G_TYPE_UINT);
9240     g_value_set_uint(&(message->value[0]),
9241 		     format);
9242 
9243     /* old format */
9244     message->parameter_name[1] = "old-format";
9245 
9246     g_value_init(&(message->value[1]),
9247 		 G_TYPE_UINT);
9248     g_value_set_uint(&(message->value[1]),
9249 		     old_format);
9250 
9251     /* terminate string vector */
9252     message->parameter_name[2] = NULL;
9253 
9254     /* add message */
9255     ags_message_delivery_add_message_envelope(message_delivery,
9256 					      "libags-audio",
9257 					      message);
9258 
9259     g_list_free_full(start_message_queue,
9260 		     (GDestroyNotify) g_object_unref);
9261   }
9262 }
9263 
9264 /**
9265  * ags_audio_set_format:
9266  * @audio: the #AgsAudio
9267  * @format: the format
9268  *
9269  * Sets buffer length.
9270  *
9271  * Since: 3.0.0
9272  */
9273 void
ags_audio_set_format(AgsAudio * audio,guint format)9274 ags_audio_set_format(AgsAudio *audio, guint format)
9275 {
9276   if(!AGS_IS_AUDIO(audio)){
9277     return;
9278   }
9279 
9280   g_object_set(audio,
9281 	       "format", format,
9282 	       NULL);
9283 }
9284 
9285 /**
9286  * ags_audio_get_bpm:
9287  * @audio: the #AgsAudio
9288  *
9289  * Gets bpm.
9290  *
9291  * Returns: the bpm
9292  *
9293  * Since: 3.1.0
9294  */
9295 gdouble
ags_audio_get_bpm(AgsAudio * audio)9296 ags_audio_get_bpm(AgsAudio *audio)
9297 {
9298   gdouble bpm;
9299 
9300   if(!AGS_IS_AUDIO(audio)){
9301     return(0.0);
9302   }
9303 
9304   g_object_get(audio,
9305 	       "bpm", &bpm,
9306 	       NULL);
9307 
9308   return(bpm);
9309 }
9310 
9311 /**
9312  * ags_audio_set_bpm:
9313  * @audio: the #AgsAudio
9314  * @bpm: the bpm
9315  *
9316  * Sets bpm.
9317  *
9318  * Since: 3.1.0
9319  */
9320 void
ags_audio_set_bpm(AgsAudio * audio,gdouble bpm)9321 ags_audio_set_bpm(AgsAudio *audio, gdouble bpm)
9322 {
9323   if(!AGS_IS_AUDIO(audio)){
9324     return;
9325   }
9326 
9327   g_object_set(audio,
9328 	       "bpm", bpm,
9329 	       NULL);
9330 }
9331 
9332 /**
9333  * ags_audio_get_audio_start_mapping:
9334  * @audio: the #AgsAudio
9335  *
9336  * Gets audio start mapping.
9337  *
9338  * Returns: the audio start mapping
9339  *
9340  * Since: 3.1.0
9341  */
9342 guint
ags_audio_get_audio_start_mapping(AgsAudio * audio)9343 ags_audio_get_audio_start_mapping(AgsAudio *audio)
9344 {
9345   guint audio_start_mapping;
9346 
9347   if(!AGS_IS_AUDIO(audio)){
9348     return(0);
9349   }
9350 
9351   g_object_get(audio,
9352 	       "audio-start-mapping", &audio_start_mapping,
9353 	       NULL);
9354 
9355   return(audio_start_mapping);
9356 }
9357 
9358 /**
9359  * ags_audio_set_audio_start_mapping:
9360  * @audio: the #AgsAudio
9361  * @audio_start_mapping: the audio start mapping
9362  *
9363  * Sets audio start mapping.
9364  *
9365  * Since: 3.1.0
9366  */
9367 void
ags_audio_set_audio_start_mapping(AgsAudio * audio,guint audio_start_mapping)9368 ags_audio_set_audio_start_mapping(AgsAudio *audio, guint audio_start_mapping)
9369 {
9370   if(!AGS_IS_AUDIO(audio)){
9371     return;
9372   }
9373 
9374   g_object_set(audio,
9375 	       "audio-start-mapping", audio_start_mapping,
9376 	       NULL);
9377 }
9378 
9379 /**
9380  * ags_audio_get_midi_start_mapping:
9381  * @audio: the #AgsAudio
9382  *
9383  * Gets midi start mapping.
9384  *
9385  * Returns: the midi start mapping
9386  *
9387  * Since: 3.1.0
9388  */
9389 guint
ags_audio_get_midi_start_mapping(AgsAudio * audio)9390 ags_audio_get_midi_start_mapping(AgsAudio *audio)
9391 {
9392   guint midi_start_mapping;
9393 
9394   if(!AGS_IS_AUDIO(audio)){
9395     return(0);
9396   }
9397 
9398   g_object_get(audio,
9399 	       "midi-start-mapping", &midi_start_mapping,
9400 	       NULL);
9401 
9402   return(midi_start_mapping);
9403 }
9404 
9405 /**
9406  * ags_audio_set_midi_start_mapping:
9407  * @audio: the #AgsAudio
9408  * @midi_start_mapping: the midi start mapping
9409  *
9410  * Sets midi start mapping.
9411  *
9412  * Since: 3.1.0
9413  */
9414 void
ags_audio_set_midi_start_mapping(AgsAudio * audio,guint midi_start_mapping)9415 ags_audio_set_midi_start_mapping(AgsAudio *audio, guint midi_start_mapping)
9416 {
9417   if(!AGS_IS_AUDIO(audio)){
9418     return;
9419   }
9420 
9421   g_object_set(audio,
9422 	       "midi-start-mapping", midi_start_mapping,
9423 	       NULL);
9424 }
9425 
9426 /**
9427  * ags_audio_get_midi_channel:
9428  * @audio: the #AgsAudio
9429  *
9430  * Gets midi channel.
9431  *
9432  * Returns: the midi channel
9433  *
9434  * Since: 3.1.0
9435  */
9436 guint
ags_audio_get_midi_channel(AgsAudio * audio)9437 ags_audio_get_midi_channel(AgsAudio *audio)
9438 {
9439   guint midi_channel;
9440 
9441   if(!AGS_IS_AUDIO(audio)){
9442     return(0);
9443   }
9444 
9445   g_object_get(audio,
9446 	       "midi-channel", &midi_channel,
9447 	       NULL);
9448 
9449   return(midi_channel);
9450 }
9451 
9452 /**
9453  * ags_audio_set_midi_channel:
9454  * @audio: the #AgsAudio
9455  * @midi_channel: the midi channel
9456  *
9457  * Sets midi channel.
9458  *
9459  * Since: 3.1.0
9460  */
9461 void
ags_audio_set_midi_channel(AgsAudio * audio,guint midi_channel)9462 ags_audio_set_midi_channel(AgsAudio *audio, guint midi_channel)
9463 {
9464   if(!AGS_IS_AUDIO(audio)){
9465     return;
9466   }
9467 
9468   g_object_set(audio,
9469 	       "midi-channel", midi_channel,
9470 	       NULL);
9471 }
9472 
9473 /**
9474  * ags_audio_get_numerator:
9475  * @audio: the #AgsAudio
9476  *
9477  * Gets numerator.
9478  *
9479  * Returns: the numerator
9480  *
9481  * Since: 3.1.0
9482  */
9483 guint
ags_audio_get_numerator(AgsAudio * audio)9484 ags_audio_get_numerator(AgsAudio *audio)
9485 {
9486   guint numerator;
9487 
9488   if(!AGS_IS_AUDIO(audio)){
9489     return(0);
9490   }
9491 
9492   g_object_get(audio,
9493 	       "numerator", &numerator,
9494 	       NULL);
9495 
9496   return(numerator);
9497 }
9498 
9499 /**
9500  * ags_audio_set_numerator:
9501  * @audio: the #AgsAudio
9502  * @numerator: the numerator
9503  *
9504  * Sets numerator.
9505  *
9506  * Since: 3.1.0
9507  */
9508 void
ags_audio_set_numerator(AgsAudio * audio,guint numerator)9509 ags_audio_set_numerator(AgsAudio *audio, guint numerator)
9510 {
9511   if(!AGS_IS_AUDIO(audio)){
9512     return;
9513   }
9514 
9515   g_object_set(audio,
9516 	       "numerator", numerator,
9517 	       NULL);
9518 }
9519 
9520 /**
9521  * ags_audio_get_denominator:
9522  * @audio: the #AgsAudio
9523  *
9524  * Gets denominator.
9525  *
9526  * Returns: the denominator
9527  *
9528  * Since: 3.1.0
9529  */
9530 guint
ags_audio_get_denominator(AgsAudio * audio)9531 ags_audio_get_denominator(AgsAudio *audio)
9532 {
9533   guint denominator;
9534 
9535   if(!AGS_IS_AUDIO(audio)){
9536     return(0);
9537   }
9538 
9539   g_object_get(audio,
9540 	       "denominator", &denominator,
9541 	       NULL);
9542 
9543   return(denominator);
9544 }
9545 
9546 /**
9547  * ags_audio_set_denominator:
9548  * @audio: the #AgsAudio
9549  * @denominator: the denominator
9550  *
9551  * Sets denominator.
9552  *
9553  * Since: 3.1.0
9554  */
9555 void
ags_audio_set_denominator(AgsAudio * audio,guint denominator)9556 ags_audio_set_denominator(AgsAudio *audio, guint denominator)
9557 {
9558   if(!AGS_IS_AUDIO(audio)){
9559     return;
9560   }
9561 
9562   g_object_set(audio,
9563 	       "denominator", denominator,
9564 	       NULL);
9565 }
9566 
9567 /**
9568  * ags_audio_get_time_signature:
9569  * @audio: the #AgsAudio
9570  *
9571  * Gets time signature.
9572  *
9573  * Returns: the time signature
9574  *
9575  * Since: 3.1.0
9576  */
9577 gchar*
ags_audio_get_time_signature(AgsAudio * audio)9578 ags_audio_get_time_signature(AgsAudio *audio)
9579 {
9580   gchar *time_signature;
9581 
9582   if(!AGS_IS_AUDIO(audio)){
9583     return(NULL);
9584   }
9585 
9586   g_object_get(audio,
9587 	       "time-signature", &time_signature,
9588 	       NULL);
9589 
9590   return(time_signature);
9591 }
9592 
9593 /**
9594  * ags_audio_set_time_signature:
9595  * @audio: the #AgsAudio
9596  * @time_signature: the time signature
9597  *
9598  * Sets time signature.
9599  *
9600  * Since: 3.1.0
9601  */
9602 void
ags_audio_set_time_signature(AgsAudio * audio,gchar * time_signature)9603 ags_audio_set_time_signature(AgsAudio *audio, gchar *time_signature)
9604 {
9605   if(!AGS_IS_AUDIO(audio)){
9606     return;
9607   }
9608 
9609   g_object_set(audio,
9610 	       "time-signature", time_signature,
9611 	       NULL);
9612 }
9613 
9614 /**
9615  * ags_audio_get_is_minor:
9616  * @audio: the #AgsAudio
9617  *
9618  * Gets is minor.
9619  *
9620  * Returns: is minor
9621  *
9622  * Since: 3.1.0
9623  */
9624 gboolean
ags_audio_get_is_minor(AgsAudio * audio)9625 ags_audio_get_is_minor(AgsAudio *audio)
9626 {
9627   gboolean is_minor;
9628 
9629   if(!AGS_IS_AUDIO(audio)){
9630     return(FALSE);
9631   }
9632 
9633   g_object_get(audio,
9634 	       "is-minor", &is_minor,
9635 	       NULL);
9636 
9637   return(is_minor);
9638 }
9639 
9640 /**
9641  * ags_audio_set_is_minor:
9642  * @audio: the #AgsAudio
9643  * @is_minor: is minor
9644  *
9645  * Sets is minor.
9646  *
9647  * Since: 3.1.0
9648  */
9649 void
ags_audio_set_is_minor(AgsAudio * audio,gboolean is_minor)9650 ags_audio_set_is_minor(AgsAudio *audio, gboolean is_minor)
9651 {
9652   if(!AGS_IS_AUDIO(audio)){
9653     return;
9654   }
9655 
9656   g_object_set(audio,
9657 	       "is-minor", is_minor,
9658 	       NULL);
9659 }
9660 
9661 /**
9662  * ags_audio_get_sharp_flats:
9663  * @audio: the #AgsAudio
9664  *
9665  * Gets sharp flats.
9666  *
9667  * Returns: the sharp flats
9668  *
9669  * Since: 3.1.0
9670  */
9671 guint
ags_audio_get_sharp_flats(AgsAudio * audio)9672 ags_audio_get_sharp_flats(AgsAudio *audio)
9673 {
9674   guint sharp_flats;
9675 
9676   if(!AGS_IS_AUDIO(audio)){
9677     return(0);
9678   }
9679 
9680   g_object_get(audio,
9681 	       "sharp-flats", &sharp_flats,
9682 	       NULL);
9683 
9684   return(sharp_flats);
9685 }
9686 
9687 /**
9688  * ags_audio_set_sharp_flats:
9689  * @audio: the #AgsAudio
9690  * @sharp_flats: the sharp flats
9691  *
9692  * Sets sharp flats.
9693  *
9694  * Since: 3.1.0
9695  */
9696 void
ags_audio_set_sharp_flats(AgsAudio * audio,guint sharp_flats)9697 ags_audio_set_sharp_flats(AgsAudio *audio, guint sharp_flats)
9698 {
9699   if(!AGS_IS_AUDIO(audio)){
9700     return;
9701   }
9702 
9703   g_object_set(audio,
9704 	       "sharp-flats", sharp_flats,
9705 	       NULL);
9706 }
9707 
9708 /**
9709  * ags_audio_get_octave:
9710  * @audio: the #AgsAudio
9711  *
9712  * Gets octave.
9713  *
9714  * Returns: the octave
9715  *
9716  * Since: 3.1.0
9717  */
9718 gint
ags_audio_get_octave(AgsAudio * audio)9719 ags_audio_get_octave(AgsAudio *audio)
9720 {
9721   gint octave;
9722 
9723   if(!AGS_IS_AUDIO(audio)){
9724     return(0);
9725   }
9726 
9727   g_object_get(audio,
9728 	       "octave", &octave,
9729 	       NULL);
9730 
9731   return(octave);
9732 }
9733 
9734 /**
9735  * ags_audio_set_octave:
9736  * @audio: the #AgsAudio
9737  * @octave: the octave
9738  *
9739  * Sets octave.
9740  *
9741  * Since: 3.1.0
9742  */
9743 void
ags_audio_set_octave(AgsAudio * audio,gint octave)9744 ags_audio_set_octave(AgsAudio *audio, gint octave)
9745 {
9746   if(!AGS_IS_AUDIO(audio)){
9747     return;
9748   }
9749 
9750   g_object_set(audio,
9751 	       "octave", octave,
9752 	       NULL);
9753 }
9754 
9755 /**
9756  * ags_audio_get_key:
9757  * @audio: the #AgsAudio
9758  *
9759  * Gets key.
9760  *
9761  * Returns: the key
9762  *
9763  * Since: 3.1.0
9764  */
9765 guint
ags_audio_get_key(AgsAudio * audio)9766 ags_audio_get_key(AgsAudio *audio)
9767 {
9768   guint key;
9769 
9770   if(!AGS_IS_AUDIO(audio)){
9771     return(0);
9772   }
9773 
9774   g_object_get(audio,
9775 	       "key", &key,
9776 	       NULL);
9777 
9778   return(key);
9779 }
9780 
9781 /**
9782  * ags_audio_set_key:
9783  * @audio: the #AgsAudio
9784  * @key: the key
9785  *
9786  * Sets key.
9787  *
9788  * Since: 3.1.0
9789  */
9790 void
ags_audio_set_key(AgsAudio * audio,guint key)9791 ags_audio_set_key(AgsAudio *audio, guint key)
9792 {
9793   if(!AGS_IS_AUDIO(audio)){
9794     return;
9795   }
9796 
9797   g_object_set(audio,
9798 	       "key", key,
9799 	       NULL);
9800 }
9801 
9802 /**
9803  * ags_audio_get_absolute_key:
9804  * @audio: the #AgsAudio
9805  *
9806  * Gets absolute key.
9807  *
9808  * Returns: the absolute key
9809  *
9810  * Since: 3.1.0
9811  */
9812 gint
ags_audio_get_absolute_key(AgsAudio * audio)9813 ags_audio_get_absolute_key(AgsAudio *audio)
9814 {
9815   gint absolute_key;
9816 
9817   if(!AGS_IS_AUDIO(audio)){
9818     return(0);
9819   }
9820 
9821   g_object_get(audio,
9822 	       "absolute-key", &absolute_key,
9823 	       NULL);
9824 
9825   return(absolute_key);
9826 }
9827 
9828 /**
9829  * ags_audio_set_absolute_key:
9830  * @audio: the #AgsAudio
9831  * @absolute_key: the absolute key
9832  *
9833  * Sets absolute key.
9834  *
9835  * Since: 3.1.0
9836  */
9837 void
ags_audio_set_absolute_key(AgsAudio * audio,gint absolute_key)9838 ags_audio_set_absolute_key(AgsAudio *audio, gint absolute_key)
9839 {
9840   if(!AGS_IS_AUDIO(audio)){
9841     return;
9842   }
9843 
9844   g_object_set(audio,
9845 	       "absolute-key", absolute_key,
9846 	       NULL);
9847 }
9848 
9849 /**
9850  * ags_audio_get_preset:
9851  * @audio: the #AgsAudio
9852  *
9853  * Get preset.
9854  *
9855  * Returns: (element-type AgsAudio.Preset) (transfer full): the #GList-struct containig #AgsPreset
9856  *
9857  * Since: 3.1.0
9858  */
9859 GList*
ags_audio_get_preset(AgsAudio * audio)9860 ags_audio_get_preset(AgsAudio *audio)
9861 {
9862   GList *preset;
9863 
9864   if(!AGS_IS_AUDIO(audio)){
9865     return(NULL);
9866   }
9867 
9868   g_object_get(audio,
9869 	       "preset", &preset,
9870 	       NULL);
9871 
9872   return(preset);
9873 }
9874 
9875 /**
9876  * ags_audio_set_preset:
9877  * @audio: the #AgsAudio
9878  * @preset: (element-type AgsAudio.Preset) (transfer full): the #GList-struct containing #AgsPreset
9879  *
9880  * Set preset by replacing existing.
9881  *
9882  * Since: 3.1.0
9883  */
9884 void
ags_audio_set_preset(AgsAudio * audio,GList * preset)9885 ags_audio_set_preset(AgsAudio *audio, GList *preset)
9886 {
9887   GList *start_preset;
9888 
9889   GRecMutex *audio_mutex;
9890 
9891   if(!AGS_IS_AUDIO(audio)){
9892     return;
9893   }
9894 
9895   /* get audio mutex */
9896   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
9897 
9898   g_rec_mutex_lock(audio_mutex);
9899 
9900   start_preset = audio->preset;
9901   audio->preset = preset;
9902 
9903   g_rec_mutex_unlock(audio_mutex);
9904 
9905   g_list_free_full(start_preset,
9906 		   (GDestroyNotify) g_object_unref);
9907 }
9908 
9909 /**
9910  * ags_audio_add_preset:
9911  * @audio: the #AgsAudio
9912  * @preset: an #AgsPreset
9913  *
9914  * Adds a preset.
9915  *
9916  * Since: 3.0.0
9917  */
9918 void
ags_audio_add_preset(AgsAudio * audio,GObject * preset)9919 ags_audio_add_preset(AgsAudio *audio,
9920 		     GObject *preset)
9921 {
9922   gboolean success;
9923 
9924   GRecMutex *audio_mutex;
9925 
9926   if(!AGS_IS_AUDIO(audio) ||
9927      !AGS_IS_PRESET(preset)){
9928     return;
9929   }
9930 
9931   /* get audio mutex */
9932   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
9933 
9934   /* add preset */
9935   success = FALSE;
9936 
9937   g_rec_mutex_lock(audio_mutex);
9938 
9939   if(g_list_find(audio->preset,
9940 		 preset) == NULL){
9941     success = TRUE;
9942 
9943     g_object_ref(preset);
9944     audio->preset = g_list_prepend(audio->preset,
9945 				   preset);
9946   }
9947 
9948   g_rec_mutex_unlock(audio_mutex);
9949 
9950   if(success){
9951     g_object_set(preset,
9952 		 "audio", audio,
9953 		 NULL);
9954   }
9955 }
9956 
9957 /**
9958  * ags_audio_remove_preset:
9959  * @audio: the #AgsAudio
9960  * @preset: an #AgsPreset
9961  *
9962  * Removes a preset.
9963  *
9964  * Since: 3.0.0
9965  */
9966 void
ags_audio_remove_preset(AgsAudio * audio,GObject * preset)9967 ags_audio_remove_preset(AgsAudio *audio,
9968 			GObject *preset)
9969 {
9970   gboolean success;
9971 
9972   GRecMutex *audio_mutex;
9973 
9974   if(!AGS_IS_AUDIO(audio) ||
9975      !AGS_IS_PRESET(preset)){
9976     return;
9977   }
9978 
9979   /* get audio mutex */
9980   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
9981 
9982   /* remove preset */
9983   success = FALSE;
9984 
9985   g_rec_mutex_lock(audio_mutex);
9986 
9987   if(g_list_find(audio->preset,
9988 		 preset) != NULL){
9989     success = TRUE;
9990 
9991     audio->preset = g_list_remove(audio->preset,
9992 				  preset);
9993   }
9994 
9995   g_rec_mutex_unlock(audio_mutex);
9996 
9997   if(success){
9998     g_object_set(preset,
9999 		 "audio", NULL,
10000 		 NULL);
10001 
10002     g_object_unref(preset);
10003   }
10004 }
10005 
10006 /**
10007  * ags_audio_get_playback_domain:
10008  * @audio: the #AgsAudio
10009  *
10010  * Get playback domain.
10011  *
10012  * Returns: (transfer full): the #AgsPlaybackDomain
10013  *
10014  * Since: 3.1.0
10015  */
10016 GObject*
ags_audio_get_playback_domain(AgsAudio * audio)10017 ags_audio_get_playback_domain(AgsAudio *audio)
10018 {
10019   GObject *playback_domain;
10020 
10021   if(!AGS_IS_AUDIO(audio)){
10022     return(NULL);
10023   }
10024 
10025   g_object_get(audio,
10026 	       "playback-domain", &playback_domain,
10027 	       NULL);
10028 
10029   return(playback_domain);
10030 }
10031 
10032 /**
10033  * ags_audio_set_playback_domain:
10034  * @audio: the #AgsAudio
10035  * @playback_domain: the #AgsPlaybackDomain
10036  *
10037  * Set playback domain.
10038  *
10039  * Since: 3.1.0
10040  */
10041 void
ags_audio_set_playback_domain(AgsAudio * audio,GObject * playback_domain)10042 ags_audio_set_playback_domain(AgsAudio *audio, GObject *playback_domain)
10043 {
10044   if(!AGS_IS_AUDIO(audio)){
10045     return;
10046   }
10047 
10048   g_object_set(audio,
10049 	       "playback-domain", playback_domain,
10050 	       NULL);
10051 }
10052 
10053 /**
10054  * ags_audio_get_synth_generator:
10055  * @audio: the #AgsAudio
10056  *
10057  * Get synth generator.
10058  *
10059  * Returns: (element-type AgsAudio.SynthGenerator) (transfer full): the #GList-struct containing #AgsSynthGenerator
10060  *
10061  * Since: 3.1.0
10062  */
10063 GList*
ags_audio_get_synth_generator(AgsAudio * audio)10064 ags_audio_get_synth_generator(AgsAudio *audio)
10065 {
10066   GList *synth_generator;
10067 
10068   if(!AGS_IS_AUDIO(audio)){
10069     return(NULL);
10070   }
10071 
10072   g_object_get(audio,
10073 	       "synth-generator", &synth_generator,
10074 	       NULL);
10075 
10076   return(synth_generator);
10077 }
10078 
10079 /**
10080  * ags_audio_set_synth_generator:
10081  * @audio: the #AgsAudio
10082  * @synth_generator: (element-type AgsAudio.SynthGenerator) (transfer full): the #GList-struct containing #AgsSynthGenerator
10083  *
10084  * Set synth generator by replacing existing.
10085  *
10086  * Since: 3.1.0
10087  */
10088 void
ags_audio_set_synth_generator(AgsAudio * audio,GList * synth_generator)10089 ags_audio_set_synth_generator(AgsAudio *audio, GList *synth_generator)
10090 {
10091   GList *start_synth_generator;
10092 
10093   GRecMutex *audio_mutex;
10094 
10095   if(!AGS_IS_AUDIO(audio)){
10096     return;
10097   }
10098 
10099   /* get audio mutex */
10100   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
10101 
10102   g_rec_mutex_lock(audio_mutex);
10103 
10104   start_synth_generator = audio->synth_generator;
10105   audio->synth_generator = synth_generator;
10106 
10107   g_rec_mutex_unlock(audio_mutex);
10108 
10109   g_list_free_full(start_synth_generator,
10110 		   (GDestroyNotify) g_object_unref);
10111 }
10112 
10113 /**
10114  * ags_audio_add_synth_generator:
10115  * @audio: the #AgsAudio
10116  * @synth_generator: an #AgsSynthGenerator
10117  *
10118  * Adds a synth generator.
10119  *
10120  * Since: 3.0.0
10121  */
10122 void
ags_audio_add_synth_generator(AgsAudio * audio,GObject * synth_generator)10123 ags_audio_add_synth_generator(AgsAudio *audio,
10124 			      GObject *synth_generator)
10125 {
10126   GRecMutex *audio_mutex;
10127 
10128   if(!AGS_IS_AUDIO(audio) ||
10129      !AGS_IS_SYNTH_GENERATOR(synth_generator)){
10130     return;
10131   }
10132 
10133   /* get audio mutex */
10134   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
10135 
10136   /* add synth_generator */
10137   g_rec_mutex_lock(audio_mutex);
10138 
10139   if(g_list_find(audio->synth_generator,
10140 		 synth_generator) == NULL){
10141     g_object_ref(synth_generator);
10142     audio->synth_generator = g_list_prepend(audio->synth_generator,
10143 					    synth_generator);
10144   }
10145 
10146   g_rec_mutex_unlock(audio_mutex);
10147 }
10148 
10149 /**
10150  * ags_audio_remove_synth_generator:
10151  * @audio: the #AgsAudio
10152  * @synth_generator: an #AgsSynthGenerator
10153  *
10154  * Removes a synth generator.
10155  *
10156  * Since: 3.0.0
10157  */
10158 void
ags_audio_remove_synth_generator(AgsAudio * audio,GObject * synth_generator)10159 ags_audio_remove_synth_generator(AgsAudio *audio,
10160 				 GObject *synth_generator)
10161 {
10162   GRecMutex *audio_mutex;
10163 
10164   if(!AGS_IS_AUDIO(audio) ||
10165      !AGS_IS_SYNTH_GENERATOR(synth_generator)){
10166     return;
10167   }
10168 
10169   /* get audio mutex */
10170   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
10171 
10172   /* remove synth_generator */
10173   g_rec_mutex_lock(audio_mutex);
10174 
10175   if(g_list_find(audio->synth_generator,
10176 		 synth_generator) != NULL){
10177     audio->synth_generator = g_list_remove(audio->synth_generator,
10178 					   synth_generator);
10179     g_object_unref(synth_generator);
10180   }
10181 
10182   g_rec_mutex_unlock(audio_mutex);
10183 }
10184 
10185 /**
10186  * ags_audio_get_sf2_synth_generator:
10187  * @audio: the #AgsAudio
10188  *
10189  * Get SF2 synth generator.
10190  *
10191  * Returns: (element-type AgsAudio.SF2SynthGenerator) (transfer full): the #GList-struct containing #AgsSF2SynthGenerator
10192  *
10193  * Since: 3.4.0
10194  */
10195 GList*
ags_audio_get_sf2_synth_generator(AgsAudio * audio)10196 ags_audio_get_sf2_synth_generator(AgsAudio *audio)
10197 {
10198   GList *sf2_synth_generator;
10199 
10200   if(!AGS_IS_AUDIO(audio)){
10201     return(NULL);
10202   }
10203 
10204   g_object_get(audio,
10205 	       "sf2-synth-generator", &sf2_synth_generator,
10206 	       NULL);
10207 
10208   return(sf2_synth_generator);
10209 }
10210 
10211 /**
10212  * ags_audio_set_sf2_synth_generator:
10213  * @audio: the #AgsAudio
10214  * @sf2_synth_generator: (element-type AgsAudio.SF2SynthGenerator) (transfer full): the #GList-struct containing #AgsSF2SynthGenerator
10215  *
10216  * Set SF2 synth generator by replacing existing.
10217  *
10218  * Since: 3.4.0
10219  */
10220 void
ags_audio_set_sf2_synth_generator(AgsAudio * audio,GList * sf2_synth_generator)10221 ags_audio_set_sf2_synth_generator(AgsAudio *audio, GList *sf2_synth_generator)
10222 {
10223   GList *start_sf2_synth_generator;
10224 
10225   GRecMutex *audio_mutex;
10226 
10227   if(!AGS_IS_AUDIO(audio)){
10228     return;
10229   }
10230 
10231   /* get audio mutex */
10232   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
10233 
10234   g_rec_mutex_lock(audio_mutex);
10235 
10236   start_sf2_synth_generator = audio->sf2_synth_generator;
10237   audio->sf2_synth_generator = sf2_synth_generator;
10238 
10239   g_rec_mutex_unlock(audio_mutex);
10240 
10241   g_list_free_full(start_sf2_synth_generator,
10242 		   (GDestroyNotify) g_object_unref);
10243 }
10244 
10245 /**
10246  * ags_audio_add_sf2_synth_generator:
10247  * @audio: the #AgsAudio
10248  * @sf2_synth_generator: an #AgsSF2SynthGenerator
10249  *
10250  * Adds a SF2 synth generator.
10251  *
10252  * Since: 3.4.0
10253  */
10254 void
ags_audio_add_sf2_synth_generator(AgsAudio * audio,GObject * sf2_synth_generator)10255 ags_audio_add_sf2_synth_generator(AgsAudio *audio,
10256 				  GObject *sf2_synth_generator)
10257 {
10258   GRecMutex *audio_mutex;
10259 
10260   if(!AGS_IS_AUDIO(audio) ||
10261      !AGS_IS_SF2_SYNTH_GENERATOR(sf2_synth_generator)){
10262     return;
10263   }
10264 
10265   /* get audio mutex */
10266   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
10267 
10268   /* add sf2_synth_generator */
10269   g_rec_mutex_lock(audio_mutex);
10270 
10271   if(g_list_find(audio->sf2_synth_generator,
10272 		 sf2_synth_generator) == NULL){
10273     g_object_ref(sf2_synth_generator);
10274     audio->sf2_synth_generator = g_list_prepend(audio->sf2_synth_generator,
10275 						sf2_synth_generator);
10276   }
10277 
10278   g_rec_mutex_unlock(audio_mutex);
10279 }
10280 
10281 /**
10282  * ags_audio_remove_sf2_synth_generator:
10283  * @audio: the #AgsAudio
10284  * @sf2_synth_generator: an #AgsSF2SynthGenerator
10285  *
10286  * Removes a SF2 synth generator.
10287  *
10288  * Since: 3.4.0
10289  */
10290 void
ags_audio_remove_sf2_synth_generator(AgsAudio * audio,GObject * sf2_synth_generator)10291 ags_audio_remove_sf2_synth_generator(AgsAudio *audio,
10292 				     GObject *sf2_synth_generator)
10293 {
10294   GRecMutex *audio_mutex;
10295 
10296   if(!AGS_IS_AUDIO(audio) ||
10297      !AGS_IS_SF2_SYNTH_GENERATOR(sf2_synth_generator)){
10298     return;
10299   }
10300 
10301   /* get audio mutex */
10302   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
10303 
10304   /* remove sf2_synth_generator */
10305   g_rec_mutex_lock(audio_mutex);
10306 
10307   if(g_list_find(audio->sf2_synth_generator,
10308 		 sf2_synth_generator) != NULL){
10309     audio->sf2_synth_generator = g_list_remove(audio->sf2_synth_generator,
10310 					       sf2_synth_generator);
10311     g_object_unref(sf2_synth_generator);
10312   }
10313 
10314   g_rec_mutex_unlock(audio_mutex);
10315 }
10316 
10317 /**
10318  * ags_audio_get_sfz_synth_generator:
10319  * @audio: the #AgsAudio
10320  *
10321  * Get SFZ synth generator.
10322  *
10323  * Returns: (element-type AgsAudio.SFZSynthGenerator) (transfer full): the #GList-struct containing #AgsSFZSynthGenerator
10324  *
10325  * Since: 3.4.0
10326  */
10327 GList*
ags_audio_get_sfz_synth_generator(AgsAudio * audio)10328 ags_audio_get_sfz_synth_generator(AgsAudio *audio)
10329 {
10330   GList *sfz_synth_generator;
10331 
10332   if(!AGS_IS_AUDIO(audio)){
10333     return(NULL);
10334   }
10335 
10336   g_object_get(audio,
10337 	       "sfz-synth-generator", &sfz_synth_generator,
10338 	       NULL);
10339 
10340   return(sfz_synth_generator);
10341 }
10342 
10343 /**
10344  * ags_audio_set_sfz_synth_generator:
10345  * @audio: the #AgsAudio
10346  * @sfz_synth_generator: (element-type AgsAudio.SFZSynthGenerator) (transfer full): the #GList-struct containing #AgsSFZSynthGenerator
10347  *
10348  * Set SFZ synth generator by replacing existing.
10349  *
10350  * Since: 3.4.0
10351  */
10352 void
ags_audio_set_sfz_synth_generator(AgsAudio * audio,GList * sfz_synth_generator)10353 ags_audio_set_sfz_synth_generator(AgsAudio *audio, GList *sfz_synth_generator)
10354 {
10355   GList *start_sfz_synth_generator;
10356 
10357   GRecMutex *audio_mutex;
10358 
10359   if(!AGS_IS_AUDIO(audio)){
10360     return;
10361   }
10362 
10363   /* get audio mutex */
10364   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
10365 
10366   g_rec_mutex_lock(audio_mutex);
10367 
10368   start_sfz_synth_generator = audio->sfz_synth_generator;
10369   audio->sfz_synth_generator = sfz_synth_generator;
10370 
10371   g_rec_mutex_unlock(audio_mutex);
10372 
10373   g_list_free_full(start_sfz_synth_generator,
10374 		   (GDestroyNotify) g_object_unref);
10375 }
10376 
10377 /**
10378  * ags_audio_add_sfz_synth_generator:
10379  * @audio: the #AgsAudio
10380  * @sfz_synth_generator: an #AgsSFZSynthGenerator
10381  *
10382  * Adds a SFZ synth generator.
10383  *
10384  * Since: 3.4.0
10385  */
10386 void
ags_audio_add_sfz_synth_generator(AgsAudio * audio,GObject * sfz_synth_generator)10387 ags_audio_add_sfz_synth_generator(AgsAudio *audio,
10388 				  GObject *sfz_synth_generator)
10389 {
10390   GRecMutex *audio_mutex;
10391 
10392   if(!AGS_IS_AUDIO(audio) ||
10393      !AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
10394     return;
10395   }
10396 
10397   /* get audio mutex */
10398   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
10399 
10400   /* add sfz_synth_generator */
10401   g_rec_mutex_lock(audio_mutex);
10402 
10403   if(g_list_find(audio->sfz_synth_generator,
10404 		 sfz_synth_generator) == NULL){
10405     g_object_ref(sfz_synth_generator);
10406     audio->sfz_synth_generator = g_list_prepend(audio->sfz_synth_generator,
10407 						sfz_synth_generator);
10408   }
10409 
10410   g_rec_mutex_unlock(audio_mutex);
10411 }
10412 
10413 /**
10414  * ags_audio_remove_sfz_synth_generator:
10415  * @audio: the #AgsAudio
10416  * @sfz_synth_generator: an #AgsSFZSynthGenerator
10417  *
10418  * Removes a SFZ synth generator.
10419  *
10420  * Since: 3.4.0
10421  */
10422 void
ags_audio_remove_sfz_synth_generator(AgsAudio * audio,GObject * sfz_synth_generator)10423 ags_audio_remove_sfz_synth_generator(AgsAudio *audio,
10424 				     GObject *sfz_synth_generator)
10425 {
10426   GRecMutex *audio_mutex;
10427 
10428   if(!AGS_IS_AUDIO(audio) ||
10429      !AGS_IS_SFZ_SYNTH_GENERATOR(sfz_synth_generator)){
10430     return;
10431   }
10432 
10433   /* get audio mutex */
10434   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
10435 
10436   /* remove sfz_synth_generator */
10437   g_rec_mutex_lock(audio_mutex);
10438 
10439   if(g_list_find(audio->sfz_synth_generator,
10440 		 sfz_synth_generator) != NULL){
10441     audio->sfz_synth_generator = g_list_remove(audio->sfz_synth_generator,
10442 					       sfz_synth_generator);
10443     g_object_unref(sfz_synth_generator);
10444   }
10445 
10446   g_rec_mutex_unlock(audio_mutex);
10447 }
10448 
10449 /**
10450  * ags_audio_get_cursor:
10451  * @audio: the #AgsAudio
10452  *
10453  * Get cursor.
10454  *
10455  * Returns: (element-type GObject) (transfer full): the #GList-struct containig #GObject implementing #AgsCursor
10456  *
10457  * Since: 3.1.0
10458  */
10459 GList*
ags_audio_get_cursor(AgsAudio * audio)10460 ags_audio_get_cursor(AgsAudio *audio)
10461 {
10462   GList *cursor;
10463 
10464   if(!AGS_IS_AUDIO(audio)){
10465     return(NULL);
10466   }
10467 
10468   g_object_get(audio,
10469 	       "cursor", &cursor,
10470 	       NULL);
10471 
10472   return(cursor);
10473 }
10474 
10475 /**
10476  * ags_audio_set_cursor:
10477  * @audio: the #AgsAudio
10478  * @cursor: (element-type GObject) (transfer full): the #GList-struct containing #AgsCursor
10479  *
10480  * Set cursor by replacing existing.
10481  *
10482  * Since: 3.1.0
10483  */
10484 void
ags_audio_set_cursor(AgsAudio * audio,GList * cursor)10485 ags_audio_set_cursor(AgsAudio *audio, GList *cursor)
10486 {
10487   GList *start_cursor;
10488 
10489   GRecMutex *audio_mutex;
10490 
10491   if(!AGS_IS_AUDIO(audio)){
10492     return;
10493   }
10494 
10495   /* get audio mutex */
10496   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
10497 
10498   g_rec_mutex_lock(audio_mutex);
10499 
10500   start_cursor = audio->cursor;
10501   audio->cursor = cursor;
10502 
10503   g_rec_mutex_unlock(audio_mutex);
10504 
10505   g_list_free_full(start_cursor,
10506 		   (GDestroyNotify) g_object_unref);
10507 }
10508 
10509 /**
10510  * ags_audio_add_cursor:
10511  * @audio: the #AgsAudio
10512  * @cursor: the #GObject implementing #AgsCursor
10513  *
10514  * Adds a cursor.
10515  *
10516  * Since: 3.0.0
10517  */
10518 void
ags_audio_add_cursor(AgsAudio * audio,GObject * cursor)10519 ags_audio_add_cursor(AgsAudio *audio, GObject *cursor)
10520 {
10521   gboolean success;
10522 
10523   GRecMutex *audio_mutex;
10524 
10525   if(!AGS_IS_AUDIO(audio) ||
10526      !AGS_IS_CURSOR(cursor)){
10527     return;
10528   }
10529 
10530   /* get audio mutex */
10531   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
10532 
10533   /* add cursor */
10534   success = FALSE;
10535 
10536   g_rec_mutex_lock(audio_mutex);
10537 
10538   if(g_list_find(audio->cursor,
10539 		 cursor) == NULL){
10540     success = TRUE;
10541 
10542     g_object_ref(cursor);
10543     audio->cursor = g_list_prepend(audio->cursor,
10544 				   (GObject *) cursor);
10545   }
10546 
10547   g_rec_mutex_unlock(audio_mutex);
10548 
10549   if(success){
10550     g_object_set(cursor,
10551 		 "audio", audio,
10552 		 NULL);
10553   }
10554 }
10555 
10556 /**
10557  * ags_audio_remove_cursor:
10558  * @audio: the #AgsAudio
10559  * @cursor: the #GObject implementing #AgsCursor
10560  *
10561  * Removes a cursor.
10562  *
10563  * Since: 3.0.0
10564  */
10565 void
ags_audio_remove_cursor(AgsAudio * audio,GObject * cursor)10566 ags_audio_remove_cursor(AgsAudio *audio, GObject *cursor)
10567 {
10568   gboolean success;
10569 
10570   GRecMutex *audio_mutex;
10571 
10572   if(!AGS_IS_AUDIO(audio) ||
10573      !AGS_IS_CURSOR(cursor)){
10574     return;
10575   }
10576 
10577   /* get audio mutex */
10578   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
10579 
10580   /* remove cursor */
10581   success = FALSE;
10582 
10583   g_rec_mutex_lock(audio_mutex);
10584 
10585   if(g_list_find(audio->cursor,
10586 		 cursor) != NULL){
10587     success = TRUE;
10588 
10589     audio->cursor = g_list_remove(audio->cursor,
10590 				  cursor);
10591   }
10592 
10593   g_rec_mutex_unlock(audio_mutex);
10594 
10595   if(success){
10596     g_object_set(cursor,
10597 		 "audio", NULL,
10598 		 NULL);
10599 
10600     g_object_unref(cursor);
10601   }
10602 }
10603 
10604 /**
10605  * ags_audio_get_notation:
10606  * @audio: the #AgsAudio
10607  *
10608  * Get notation.
10609  *
10610  * Returns: (element-type AgsAudio.Notation) (transfer full): the #GList-struct containig #AgsNotation
10611  *
10612  * Since: 3.1.0
10613  */
10614 GList*
ags_audio_get_notation(AgsAudio * audio)10615 ags_audio_get_notation(AgsAudio *audio)
10616 {
10617   GList *notation;
10618 
10619   if(!AGS_IS_AUDIO(audio)){
10620     return(NULL);
10621   }
10622 
10623   g_object_get(audio,
10624 	       "notation", &notation,
10625 	       NULL);
10626 
10627   return(notation);
10628 }
10629 
10630 /**
10631  * ags_audio_set_notation:
10632  * @audio: the #AgsAudio
10633  * @notation: (element-type AgsAudio.Notation) (transfer full): the #GList-struct containing #AgsNotation
10634  *
10635  * Set notation by replacing existing.
10636  *
10637  * Since: 3.1.0
10638  */
10639 void
ags_audio_set_notation(AgsAudio * audio,GList * notation)10640 ags_audio_set_notation(AgsAudio *audio, GList *notation)
10641 {
10642   GList *start_notation;
10643 
10644   GRecMutex *audio_mutex;
10645 
10646   if(!AGS_IS_AUDIO(audio)){
10647     return;
10648   }
10649 
10650   /* get audio mutex */
10651   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
10652 
10653   g_rec_mutex_lock(audio_mutex);
10654 
10655   start_notation = audio->notation;
10656   audio->notation = notation;
10657 
10658   g_rec_mutex_unlock(audio_mutex);
10659 
10660   g_list_free_full(start_notation,
10661 		   (GDestroyNotify) g_object_unref);
10662 }
10663 
10664 /**
10665  * ags_audio_add_notation:
10666  * @audio: the #AgsAudio
10667  * @notation: the #AgsNotation
10668  *
10669  * Adds a notation.
10670  *
10671  * Since: 3.0.0
10672  */
10673 void
ags_audio_add_notation(AgsAudio * audio,GObject * notation)10674 ags_audio_add_notation(AgsAudio *audio, GObject *notation)
10675 {
10676   gboolean success;
10677 
10678   GRecMutex *audio_mutex;
10679 
10680   if(!AGS_IS_AUDIO(audio) ||
10681      !AGS_IS_NOTATION(notation)){
10682     return;
10683   }
10684 
10685   /* get audio mutex */
10686   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
10687 
10688   /* add notation */
10689   success = FALSE;
10690 
10691   g_rec_mutex_lock(audio_mutex);
10692 
10693   if(g_list_find(audio->notation,
10694 		 notation) == NULL){
10695     success = TRUE;
10696 
10697     g_object_ref(notation);
10698     audio->notation = ags_notation_add(audio->notation,
10699 				       (AgsNotation *) notation);
10700   }
10701 
10702   g_rec_mutex_unlock(audio_mutex);
10703 
10704   if(success){
10705     g_object_set(notation,
10706 		 "audio", audio,
10707 		 NULL);
10708   }
10709 }
10710 
10711 /**
10712  * ags_audio_remove_notation:
10713  * @audio: the #AgsAudio
10714  * @notation: the #AgsNotation
10715  *
10716  * Removes a notation.
10717  *
10718  * Since: 3.0.0
10719  */
10720 void
ags_audio_remove_notation(AgsAudio * audio,GObject * notation)10721 ags_audio_remove_notation(AgsAudio *audio, GObject *notation)
10722 {
10723   gboolean success;
10724 
10725   GRecMutex *audio_mutex;
10726 
10727   if(!AGS_IS_AUDIO(audio) ||
10728      !AGS_IS_NOTATION(notation)){
10729     return;
10730   }
10731 
10732   /* get audio mutex */
10733   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
10734 
10735   /* remove notation */
10736   success = FALSE;
10737 
10738   g_rec_mutex_lock(audio_mutex);
10739 
10740   if(g_list_find(audio->notation,
10741 		 notation) != NULL){
10742     success = TRUE;
10743 
10744     audio->notation = g_list_remove(audio->notation,
10745 				    notation);
10746   }
10747 
10748   g_rec_mutex_unlock(audio_mutex);
10749 
10750   if(success){
10751     g_object_set(notation,
10752 		 "audio", NULL,
10753 		 NULL);
10754 
10755     g_object_unref(notation);
10756   }
10757 }
10758 
10759 /**
10760  * ags_audio_get_automation_port:
10761  * @audio: the #AgsAudio
10762  *
10763  * Get automation port.
10764  *
10765  * Returns: (transfer full): the string vector containing automation ports
10766  *
10767  * Since: 3.1.0
10768  */
10769 gchar**
ags_audio_get_automation_port(AgsAudio * audio)10770 ags_audio_get_automation_port(AgsAudio *audio)
10771 {
10772   gchar **automation_port;
10773 
10774   GRecMutex *audio_mutex;
10775 
10776   if(!AGS_IS_AUDIO(audio)){
10777     return(NULL);
10778   }
10779 
10780   /* get audio mutex */
10781   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
10782 
10783   g_rec_mutex_lock(audio_mutex);
10784 
10785   automation_port = g_strdupv(audio->automation_port);
10786 
10787   g_rec_mutex_unlock(audio_mutex);
10788 
10789   return(automation_port);
10790 }
10791 
10792 /**
10793  * ags_audio_set_automation_port:
10794  * @audio: the #AgsAudio
10795  * @automation_port: (transfer full): the string vector containing automation ports
10796  *
10797  *
10798  * Get automation port.
10799  *
10800  * Since: 3.1.0
10801  */
10802 void
ags_audio_set_automation_port(AgsAudio * audio,gchar ** automation_port)10803 ags_audio_set_automation_port(AgsAudio *audio,
10804 			      gchar **automation_port)
10805 {
10806   GRecMutex *audio_mutex;
10807 
10808   if(!AGS_IS_AUDIO(audio)){
10809     return;
10810   }
10811 
10812   /* get audio mutex */
10813   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
10814 
10815   g_rec_mutex_lock(audio_mutex);
10816 
10817   g_strfreev(audio->automation_port);
10818 
10819   audio->automation_port = automation_port;
10820 
10821   g_rec_mutex_unlock(audio_mutex);
10822 }
10823 
10824 /**
10825  * ags_audio_add_automation_port:
10826  * @audio: the #AgsAudio
10827  * @control_name: the control name
10828  *
10829  * Adds an automation port.
10830  *
10831  * Since: 3.0.0
10832  */
10833 void
ags_audio_add_automation_port(AgsAudio * audio,gchar * control_name)10834 ags_audio_add_automation_port(AgsAudio *audio, gchar *control_name)
10835 {
10836   guint length;
10837 
10838   GRecMutex *audio_mutex;
10839 
10840   if(!AGS_IS_AUDIO(audio) ||
10841      control_name == NULL){
10842     return;
10843   }
10844 
10845   /* get audio mutex */
10846   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
10847 
10848   g_rec_mutex_lock(audio_mutex);
10849 
10850   if(audio->automation_port != NULL &&
10851      g_strv_contains(audio->automation_port, control_name)){
10852     g_rec_mutex_unlock(audio_mutex);
10853 
10854     return;
10855   }
10856 
10857   if(audio->automation_port == NULL){
10858     audio->automation_port = (gchar **) malloc(2 * sizeof(gchar *));
10859 
10860     audio->automation_port[0] = g_strdup(control_name);
10861     audio->automation_port[1] = NULL;
10862   }else{
10863     length = g_strv_length(audio->automation_port);
10864 
10865     audio->automation_port = (gchar **) realloc(audio->automation_port,
10866 						(length + 2) * sizeof(gchar *));
10867 
10868     audio->automation_port[length] = g_strdup(control_name);
10869     audio->automation_port[length + 1] = NULL;
10870   }
10871 
10872   g_rec_mutex_unlock(audio_mutex);
10873 }
10874 
10875 /**
10876  * ags_audio_remove_automation_port:
10877  * @audio: the #AgsAudio
10878  * @control_name: the control name
10879  *
10880  * Removes an automation port.
10881  *
10882  * Since: 3.0.0
10883  */
10884 void
ags_audio_remove_automation_port(AgsAudio * audio,gchar * control_name)10885 ags_audio_remove_automation_port(AgsAudio *audio, gchar *control_name)
10886 {
10887   gchar **automation_port;
10888 
10889   guint length;
10890   guint i, j;
10891 
10892   GRecMutex *audio_mutex;
10893 
10894   if(!AGS_IS_AUDIO(audio) ||
10895      control_name == NULL){
10896     return;
10897   }
10898 
10899   /* get audio mutex */
10900   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
10901 
10902   g_rec_mutex_lock(audio_mutex);
10903 
10904   if(!g_strv_contains(audio->automation_port, control_name)){
10905     g_rec_mutex_unlock(audio_mutex);
10906 
10907     return;
10908   }
10909 
10910   length = g_strv_length(audio->automation_port);
10911 
10912   if(length == 1){
10913     g_strfreev(audio->automation_port);
10914 
10915     audio->automation_port = NULL;
10916   }else{
10917     automation_port = (gchar **) malloc((length) * sizeof(gchar *));
10918 
10919     for(i = 0, j = 0; i < length; i++){
10920       if(!g_strcmp0(audio->automation_port[i], control_name)){
10921 	g_free(audio->automation_port[i]);
10922       }else{
10923 	automation_port[j] = audio->automation_port[i];
10924 
10925 	j++;
10926       }
10927     }
10928 
10929     automation_port[j] = NULL;
10930 
10931     g_strfreev(audio->automation_port);
10932 
10933     audio->automation_port = automation_port;
10934   }
10935 
10936   g_rec_mutex_unlock(audio_mutex);
10937 }
10938 
10939 
10940 /**
10941  * ags_audio_get_automation:
10942  * @audio: the #AgsAudio
10943  *
10944  * Get automation.
10945  *
10946  * Returns: (element-type AgsAudio.Automation) (transfer full): the #GList-struct containig #AgsAutomation
10947  *
10948  * Since: 3.1.0
10949  */
10950 GList*
ags_audio_get_automation(AgsAudio * audio)10951 ags_audio_get_automation(AgsAudio *audio)
10952 {
10953   GList *automation;
10954 
10955   if(!AGS_IS_AUDIO(audio)){
10956     return(NULL);
10957   }
10958 
10959   g_object_get(audio,
10960 	       "automation", &automation,
10961 	       NULL);
10962 
10963   return(automation);
10964 }
10965 
10966 /**
10967  * ags_audio_set_automation:
10968  * @audio: the #AgsAudio
10969  * @automation: (element-type AgsAudio.Automation) (transfer full): the #GList-struct containing #AgsAutomation
10970  *
10971  * Set automation by replacing existing.
10972  *
10973  * Since: 3.1.0
10974  */
10975 void
ags_audio_set_automation(AgsAudio * audio,GList * automation)10976 ags_audio_set_automation(AgsAudio *audio, GList *automation)
10977 {
10978   GList *start_automation;
10979 
10980   GRecMutex *audio_mutex;
10981 
10982   if(!AGS_IS_AUDIO(audio)){
10983     return;
10984   }
10985 
10986   /* get audio mutex */
10987   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
10988 
10989   g_rec_mutex_lock(audio_mutex);
10990 
10991   start_automation = audio->automation;
10992   audio->automation = automation;
10993 
10994   g_rec_mutex_unlock(audio_mutex);
10995 
10996   g_list_free_full(start_automation,
10997 		   (GDestroyNotify) g_object_unref);
10998 }
10999 
11000 /**
11001  * ags_audio_add_automation:
11002  * @audio: the #AgsAudio
11003  * @automation: the #AgsAutomation
11004  *
11005  * Adds an automation.
11006  *
11007  * Since: 3.0.0
11008  */
11009 void
ags_audio_add_automation(AgsAudio * audio,GObject * automation)11010 ags_audio_add_automation(AgsAudio *audio, GObject *automation)
11011 {
11012   gboolean success;
11013 
11014   GRecMutex *audio_mutex;
11015 
11016   if(!AGS_IS_AUDIO(audio) ||
11017      !AGS_IS_AUTOMATION(automation)){
11018     return;
11019   }
11020 
11021   /* get audio mutex */
11022   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
11023 
11024   /* add automation */
11025   success = FALSE;
11026 
11027   g_rec_mutex_lock(audio_mutex);
11028 
11029   if(g_list_find(audio->automation,
11030 		 automation) == NULL){
11031     success = TRUE;
11032 
11033     g_object_ref(automation);
11034     audio->automation = ags_automation_add(audio->automation,
11035 					   (AgsAutomation *) automation);
11036   }
11037 
11038   g_rec_mutex_unlock(audio_mutex);
11039 
11040   if(success){
11041     g_object_set(automation,
11042 		 "audio", audio,
11043 		 NULL);
11044   }
11045 }
11046 
11047 /**
11048  * ags_audio_remove_automation:
11049  * @audio: the #AgsAudio
11050  * @automation: the #AgsAutomation
11051  *
11052  * Removes an automation.
11053  *
11054  * Since: 3.0.0
11055  */
11056 void
ags_audio_remove_automation(AgsAudio * audio,GObject * automation)11057 ags_audio_remove_automation(AgsAudio *audio, GObject *automation)
11058 {
11059   gboolean success;
11060 
11061   GRecMutex *audio_mutex;
11062 
11063   if(!AGS_IS_AUDIO(audio) ||
11064      !AGS_IS_AUTOMATION(automation)){
11065     return;
11066   }
11067 
11068   /* get audio mutex */
11069   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
11070 
11071   /* remove automation */
11072   success = FALSE;
11073 
11074   g_rec_mutex_lock(audio_mutex);
11075 
11076   if(g_list_find(audio->automation,
11077 		 automation) != NULL){
11078     success = TRUE;
11079 
11080     audio->automation = g_list_remove(audio->automation,
11081 				      automation);
11082   }
11083 
11084   g_rec_mutex_unlock(audio_mutex);
11085 
11086   if(success){
11087     g_object_set(automation,
11088 		 "audio", NULL,
11089 		 NULL);
11090 
11091     g_object_unref(automation);
11092   }
11093 }
11094 
11095 /**
11096  * ags_audio_get_wave:
11097  * @audio: the #AgsAudio
11098  *
11099  * Get wave.
11100  *
11101  * Returns: (element-type AgsAudio.Wave) (transfer full): the #GList-struct containig #AgsWave
11102  *
11103  * Since: 3.1.0
11104  */
11105 GList*
ags_audio_get_wave(AgsAudio * audio)11106 ags_audio_get_wave(AgsAudio *audio)
11107 {
11108   GList *wave;
11109 
11110   if(!AGS_IS_AUDIO(audio)){
11111     return(NULL);
11112   }
11113 
11114   g_object_get(audio,
11115 	       "wave", &wave,
11116 	       NULL);
11117 
11118   return(wave);
11119 }
11120 
11121 /**
11122  * ags_audio_set_wave:
11123  * @audio: the #AgsAudio
11124  * @wave: (element-type AgsAudio.Wave) (transfer full): the #GList-struct containing #AgsWave
11125  *
11126  * Set wave by replacing existing.
11127  *
11128  * Since: 3.1.0
11129  */
11130 void
ags_audio_set_wave(AgsAudio * audio,GList * wave)11131 ags_audio_set_wave(AgsAudio *audio, GList *wave)
11132 {
11133   GList *start_wave;
11134 
11135   GRecMutex *audio_mutex;
11136 
11137   if(!AGS_IS_AUDIO(audio)){
11138     return;
11139   }
11140 
11141   /* get audio mutex */
11142   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
11143 
11144   g_rec_mutex_lock(audio_mutex);
11145 
11146   start_wave = audio->wave;
11147   audio->wave = wave;
11148 
11149   g_rec_mutex_unlock(audio_mutex);
11150 
11151   g_list_free_full(start_wave,
11152 		   (GDestroyNotify) g_object_unref);
11153 }
11154 
11155 /**
11156  * ags_audio_add_wave:
11157  * @audio: the #AgsAudio
11158  * @wave: the #AgsWave
11159  *
11160  * Adds a wave.
11161  *
11162  * Since: 3.0.0
11163  */
11164 void
ags_audio_add_wave(AgsAudio * audio,GObject * wave)11165 ags_audio_add_wave(AgsAudio *audio, GObject *wave)
11166 {
11167   gboolean success;
11168 
11169   GRecMutex *audio_mutex;
11170 
11171   if(!AGS_IS_AUDIO(audio) ||
11172      !AGS_IS_WAVE(wave)){
11173     return;
11174   }
11175 
11176   /* get audio mutex */
11177   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
11178 
11179   /* add wave */
11180   success = FALSE;
11181 
11182   g_rec_mutex_lock(audio_mutex);
11183 
11184   if(g_list_find(audio->wave,
11185 		 wave) == NULL){
11186     success = TRUE;
11187 
11188     g_object_ref(wave);
11189     audio->wave = ags_wave_add(audio->wave,
11190 			       (AgsWave *) wave);
11191   }
11192 
11193   g_rec_mutex_unlock(audio_mutex);
11194 
11195   if(success){
11196     g_object_set(wave,
11197 		 "audio", audio,
11198 		 NULL);
11199   }
11200 }
11201 
11202 /**
11203  * ags_audio_remove_wave:
11204  * @audio: the #AgsAudio
11205  * @wave: the #AgsWave
11206  *
11207  * Removes a wave.
11208  *
11209  * Since: 3.0.0
11210  */
11211 void
ags_audio_remove_wave(AgsAudio * audio,GObject * wave)11212 ags_audio_remove_wave(AgsAudio *audio, GObject *wave)
11213 {
11214   gboolean success;
11215 
11216   GRecMutex *audio_mutex;
11217 
11218   if(!AGS_IS_AUDIO(audio) ||
11219      !AGS_IS_WAVE(wave)){
11220     return;
11221   }
11222 
11223   /* get audio mutex */
11224   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
11225 
11226   /* remove wave */
11227   success = FALSE;
11228 
11229   g_rec_mutex_lock(audio_mutex);
11230 
11231   if(g_list_find(audio->wave,
11232 		 wave) != NULL){
11233     success = TRUE;
11234 
11235     audio->wave = g_list_remove(audio->wave,
11236 				wave);
11237   }
11238 
11239   g_rec_mutex_unlock(audio_mutex);
11240 
11241   if(success){
11242     g_object_set(wave,
11243 		 "audio", NULL,
11244 		 NULL);
11245 
11246     g_object_unref(wave);
11247   }
11248 }
11249 
11250 /**
11251  * ags_audio_get_output_audio_file:
11252  * @audio: the #AgsAudio
11253  *
11254  * Get output audio file.
11255  *
11256  * Returns: (transfer full): the #GObject
11257  *
11258  * Since: 3.1.0
11259  */
11260 GObject*
ags_audio_get_output_audio_file(AgsAudio * audio)11261 ags_audio_get_output_audio_file(AgsAudio *audio)
11262 {
11263   GObject *output_audio_file;
11264 
11265   if(!AGS_IS_AUDIO(audio)){
11266     return(NULL);
11267   }
11268 
11269   g_object_get(audio,
11270 	       "output-audio-file", &output_audio_file,
11271 	       NULL);
11272 
11273   return(output_audio_file);
11274 }
11275 
11276 /**
11277  * ags_audio_set_output_audio_file:
11278  * @audio: the #AgsAudio
11279  * @output_audio_file: the #GObject
11280  *
11281  * Set output audio file.
11282  *
11283  * Since: 3.1.0
11284  */
11285 void
ags_audio_set_output_audio_file(AgsAudio * audio,GObject * output_audio_file)11286 ags_audio_set_output_audio_file(AgsAudio *audio, GObject *output_audio_file)
11287 {
11288   if(!AGS_IS_AUDIO(audio)){
11289     return;
11290   }
11291 
11292   g_object_set(audio,
11293 	       "output-audio-file", output_audio_file,
11294 	       NULL);
11295 }
11296 
11297 /**
11298  * ags_audio_get_input_audio_file:
11299  * @audio: the #AgsAudio
11300  *
11301  * Get input audio file.
11302  *
11303  * Returns: (transfer full): the #GObject
11304  *
11305  * Since: 3.1.0
11306  */
11307 GObject*
ags_audio_get_input_audio_file(AgsAudio * audio)11308 ags_audio_get_input_audio_file(AgsAudio *audio)
11309 {
11310   GObject *input_audio_file;
11311 
11312   if(!AGS_IS_AUDIO(audio)){
11313     return(NULL);
11314   }
11315 
11316   g_object_get(audio,
11317 	       "input-audio-file", &input_audio_file,
11318 	       NULL);
11319 
11320   return(input_audio_file);
11321 }
11322 
11323 /**
11324  * ags_audio_set_input_audio_file:
11325  * @audio: the #AgsAudio
11326  * @input_audio_file: the #GObject
11327  *
11328  * Set input audio file.
11329  *
11330  * Since: 3.1.0
11331  */
11332 void
ags_audio_set_input_audio_file(AgsAudio * audio,GObject * input_audio_file)11333 ags_audio_set_input_audio_file(AgsAudio *audio, GObject *input_audio_file)
11334 {
11335   if(!AGS_IS_AUDIO(audio)){
11336     return;
11337   }
11338 
11339   g_object_set(audio,
11340 	       "input-audio-file", input_audio_file,
11341 	       NULL);
11342 }
11343 
11344 /**
11345  * ags_audio_get_instrument_name:
11346  * @audio: the #AgsAudio
11347  *
11348  * Gets instrument name.
11349  *
11350  * Returns: the instrument name
11351  *
11352  * Since: 3.1.0
11353  */
11354 gchar*
ags_audio_get_instrument_name(AgsAudio * audio)11355 ags_audio_get_instrument_name(AgsAudio *audio)
11356 {
11357   gchar *instrument_name;
11358 
11359   if(!AGS_IS_AUDIO(audio)){
11360     return(NULL);
11361   }
11362 
11363   g_object_get(audio,
11364 	       "instrument-name", &instrument_name,
11365 	       NULL);
11366 
11367   return(instrument_name);
11368 }
11369 
11370 /**
11371  * ags_audio_set_instrument_name:
11372  * @audio: the #AgsAudio
11373  * @instrument_name: the instrument name
11374  *
11375  * Sets instrument name.
11376  *
11377  * Since: 3.1.0
11378  */
11379 void
ags_audio_set_instrument_name(AgsAudio * audio,gchar * instrument_name)11380 ags_audio_set_instrument_name(AgsAudio *audio, gchar *instrument_name)
11381 {
11382   if(!AGS_IS_AUDIO(audio)){
11383     return;
11384   }
11385 
11386   g_object_set(audio,
11387 	       "instrument-name", instrument_name,
11388 	       NULL);
11389 }
11390 
11391 /**
11392  * ags_audio_get_track_name:
11393  * @audio: the #AgsAudio
11394  *
11395  * Gets track name.
11396  *
11397  * Returns: the track name
11398  *
11399  * Since: 3.1.0
11400  */
11401 gchar*
ags_audio_get_track_name(AgsAudio * audio)11402 ags_audio_get_track_name(AgsAudio *audio)
11403 {
11404   gchar *track_name;
11405 
11406   if(!AGS_IS_AUDIO(audio)){
11407     return(NULL);
11408   }
11409 
11410   g_object_get(audio,
11411 	       "track-name", &track_name,
11412 	       NULL);
11413 
11414   return(track_name);
11415 }
11416 
11417 /**
11418  * ags_audio_set_track_name:
11419  * @audio: the #AgsAudio
11420  * @track_name: the track name
11421  *
11422  * Sets track name.
11423  *
11424  * Since: 3.1.0
11425  */
11426 void
ags_audio_set_track_name(AgsAudio * audio,gchar * track_name)11427 ags_audio_set_track_name(AgsAudio *audio, gchar *track_name)
11428 {
11429   if(!AGS_IS_AUDIO(audio)){
11430     return;
11431   }
11432 
11433   g_object_set(audio,
11434 	       "track-name", track_name,
11435 	       NULL);
11436 }
11437 
11438 /**
11439  * ags_audio_get_midi:
11440  * @audio: the #AgsAudio
11441  *
11442  * Get midi.
11443  *
11444  * Returns: (element-type AgsAudio.Midi) (transfer full): the #GList-struct containig #AgsMidi
11445  *
11446  * Since: 3.1.0
11447  */
11448 GList*
ags_audio_get_midi(AgsAudio * audio)11449 ags_audio_get_midi(AgsAudio *audio)
11450 {
11451   GList *midi;
11452 
11453   if(!AGS_IS_AUDIO(audio)){
11454     return(NULL);
11455   }
11456 
11457   g_object_get(audio,
11458 	       "midi", &midi,
11459 	       NULL);
11460 
11461   return(midi);
11462 }
11463 
11464 /**
11465  * ags_audio_set_midi:
11466  * @audio: the #AgsAudio
11467  * @midi: (element-type AgsAudio.Midi) (transfer full): the #GList-struct containing #AgsMidi
11468  *
11469  * Set midi by replacing existing.
11470  *
11471  * Since: 3.1.0
11472  */
11473 void
ags_audio_set_midi(AgsAudio * audio,GList * midi)11474 ags_audio_set_midi(AgsAudio *audio, GList *midi)
11475 {
11476   GList *start_midi;
11477 
11478   GRecMutex *audio_mutex;
11479 
11480   if(!AGS_IS_AUDIO(audio)){
11481     return;
11482   }
11483 
11484   /* get audio mutex */
11485   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
11486 
11487   g_rec_mutex_lock(audio_mutex);
11488 
11489   start_midi = audio->midi;
11490   audio->midi = midi;
11491 
11492   g_rec_mutex_unlock(audio_mutex);
11493 
11494   g_list_free_full(start_midi,
11495 		   (GDestroyNotify) g_object_unref);
11496 }
11497 
11498 /**
11499  * ags_audio_add_midi:
11500  * @audio: the #AgsAudio
11501  * @midi: the #AgsMidi
11502  *
11503  * Adds a midi.
11504  *
11505  * Since: 3.0.0
11506  */
11507 void
ags_audio_add_midi(AgsAudio * audio,GObject * midi)11508 ags_audio_add_midi(AgsAudio *audio, GObject *midi)
11509 {
11510   gboolean success;
11511 
11512   GRecMutex *audio_mutex;
11513 
11514   if(!AGS_IS_AUDIO(audio) ||
11515      !AGS_IS_MIDI(midi)){
11516     return;
11517   }
11518 
11519   /* get audio mutex */
11520   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
11521 
11522   /* add midi */
11523   success = FALSE;
11524 
11525   g_rec_mutex_lock(audio_mutex);
11526 
11527   if(g_list_find(audio->midi,
11528 		 midi) == NULL){
11529     success = TRUE;
11530 
11531     g_object_ref(midi);
11532     audio->midi = ags_midi_add(audio->midi,
11533 			       (AgsMidi *) midi);
11534   }
11535 
11536   g_rec_mutex_unlock(audio_mutex);
11537 
11538   if(success){
11539     g_object_set(midi,
11540 		 "audio", audio,
11541 		 NULL);
11542   }
11543 }
11544 
11545 /**
11546  * ags_audio_remove_midi:
11547  * @audio: the #AgsAudio
11548  * @midi: the #AgsMidi
11549  *
11550  * Removes a midi.
11551  *
11552  * Since: 3.0.0
11553  */
11554 void
ags_audio_remove_midi(AgsAudio * audio,GObject * midi)11555 ags_audio_remove_midi(AgsAudio *audio, GObject *midi)
11556 {
11557   gboolean success;
11558 
11559   GRecMutex *audio_mutex;
11560 
11561   if(!AGS_IS_AUDIO(audio) ||
11562      !AGS_IS_MIDI(midi)){
11563     return;
11564   }
11565 
11566   /* get audio mutex */
11567   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
11568 
11569   /* remove midi */
11570   success = FALSE;
11571 
11572   g_rec_mutex_lock(audio_mutex);
11573 
11574   if(g_list_find(audio->midi,
11575 		 midi) != NULL){
11576     success = TRUE;
11577 
11578     audio->midi = g_list_remove(audio->midi,
11579 				midi);
11580   }
11581 
11582   g_rec_mutex_unlock(audio_mutex);
11583 
11584   if(success){
11585     g_object_set(midi,
11586 		 "audio", NULL,
11587 		 NULL);
11588 
11589     g_object_unref(midi);
11590   }
11591 }
11592 
11593 /**
11594  * ags_audio_get_output_midi_file:
11595  * @audio: the #AgsAudio
11596  *
11597  * Get output MIDI file.
11598  *
11599  * Returns: (transfer full): the #GObject
11600  *
11601  * Since: 3.1.0
11602  */
11603 GObject*
ags_audio_get_output_midi_file(AgsAudio * audio)11604 ags_audio_get_output_midi_file(AgsAudio *audio)
11605 {
11606   GObject *output_midi_file;
11607 
11608   if(!AGS_IS_AUDIO(audio)){
11609     return(NULL);
11610   }
11611 
11612   g_object_get(audio,
11613 	       "output-midi-file", &output_midi_file,
11614 	       NULL);
11615 
11616   return(output_midi_file);
11617 }
11618 
11619 /**
11620  * ags_audio_set_output_midi_file:
11621  * @audio: the #AgsAudio
11622  * @output_midi_file: the #GObject
11623  *
11624  * Set output MIDI file.
11625  *
11626  * Since: 3.1.0
11627  */
11628 void
ags_audio_set_output_midi_file(AgsAudio * audio,GObject * output_midi_file)11629 ags_audio_set_output_midi_file(AgsAudio *audio, GObject *output_midi_file)
11630 {
11631   if(!AGS_IS_AUDIO(audio)){
11632     return;
11633   }
11634 
11635   g_object_set(audio,
11636 	       "output-midi-file", output_midi_file,
11637 	       NULL);
11638 }
11639 
11640 /**
11641  * ags_audio_get_input_midi_file:
11642  * @audio: the #AgsAudio
11643  *
11644  * Get input MIDI file.
11645  *
11646  * Returns: (transfer full): the #GObject
11647  *
11648  * Since: 3.1.0
11649  */
11650 GObject*
ags_audio_get_input_midi_file(AgsAudio * audio)11651 ags_audio_get_input_midi_file(AgsAudio *audio)
11652 {
11653   GObject *input_midi_file;
11654 
11655   if(!AGS_IS_AUDIO(audio)){
11656     return(NULL);
11657   }
11658 
11659   g_object_get(audio,
11660 	       "input-midi-file", &input_midi_file,
11661 	       NULL);
11662 
11663   return(input_midi_file);
11664 }
11665 
11666 /**
11667  * ags_audio_set_input_midi_file:
11668  * @audio: the #AgsAudio
11669  * @input_midi_file: the #GObject
11670  *
11671  * Set input MIDI file.
11672  *
11673  * Since: 3.1.0
11674  */
11675 void
ags_audio_set_input_midi_file(AgsAudio * audio,GObject * input_midi_file)11676 ags_audio_set_input_midi_file(AgsAudio *audio, GObject *input_midi_file)
11677 {
11678   if(!AGS_IS_AUDIO(audio)){
11679     return;
11680   }
11681 
11682   g_object_set(audio,
11683 	       "input-midi-file", input_midi_file,
11684 	       NULL);
11685 }
11686 
11687 /**
11688  * ags_audio_get_recall_id:
11689  * @audio: the #AgsAudio
11690  *
11691  * Get recall id.
11692  *
11693  * Returns: (element-type AgsAudio.RecallID) (transfer full): the #GList-struct containig #AgsRecallID
11694  *
11695  * Since: 3.1.0
11696  */
11697 GList*
ags_audio_get_recall_id(AgsAudio * audio)11698 ags_audio_get_recall_id(AgsAudio *audio)
11699 {
11700   GList *recall_id;
11701 
11702   if(!AGS_IS_AUDIO(audio)){
11703     return(NULL);
11704   }
11705 
11706   g_object_get(audio,
11707 	       "recall_id", &recall_id,
11708 	       NULL);
11709 
11710   return(recall_id);
11711 }
11712 
11713 /**
11714  * ags_audio_set_recall_id:
11715  * @audio: the #AgsAudio
11716  * @recall_id: (element-type AgsAudio.RecallID) (transfer full): the #GList-struct containing #AgsRecallID
11717  *
11718  * Set recall id by replacing existing.
11719  *
11720  * Since: 3.1.0
11721  */
11722 void
ags_audio_set_recall_id(AgsAudio * audio,GList * recall_id)11723 ags_audio_set_recall_id(AgsAudio *audio, GList *recall_id)
11724 {
11725   GList *start_recall_id;
11726 
11727   GRecMutex *audio_mutex;
11728 
11729   if(!AGS_IS_AUDIO(audio)){
11730     return;
11731   }
11732 
11733   /* get audio mutex */
11734   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
11735 
11736   g_rec_mutex_lock(audio_mutex);
11737 
11738   start_recall_id = audio->recall_id;
11739   audio->recall_id = recall_id;
11740 
11741   g_rec_mutex_unlock(audio_mutex);
11742 
11743   g_list_free_full(start_recall_id,
11744 		   (GDestroyNotify) g_object_unref);
11745 }
11746 
11747 /**
11748  * ags_audio_add_recall_id:
11749  * @audio: the #AgsAudio
11750  * @recall_id: the #AgsRecallID
11751  *
11752  * Adds a recall id.
11753  *
11754  * Since: 3.0.0
11755  */
11756 void
ags_audio_add_recall_id(AgsAudio * audio,GObject * recall_id)11757 ags_audio_add_recall_id(AgsAudio *audio, GObject *recall_id)
11758 {
11759   GRecMutex *audio_mutex;
11760 
11761   if(!AGS_IS_AUDIO(audio) ||
11762      !AGS_IS_RECALL_ID(recall_id)){
11763     return;
11764   }
11765 
11766   /* get audio mutex */
11767   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
11768 
11769   /* add recall id */
11770   g_rec_mutex_lock(audio_mutex);
11771 
11772   if(g_list_find(audio->recall_id,
11773 		 recall_id) == NULL){
11774     g_object_ref(recall_id);
11775     audio->recall_id = g_list_prepend(audio->recall_id,
11776 				      recall_id);
11777   }
11778 
11779   g_rec_mutex_unlock(audio_mutex);
11780 }
11781 
11782 /**
11783  * ags_audio_remove_recall_id:
11784  * @audio: the #AgsAudio
11785  * @recall_id: the #AgsRecallID
11786  *
11787  * Removes a recall id.
11788  *
11789  * Since: 3.0.0
11790  */
11791 void
ags_audio_remove_recall_id(AgsAudio * audio,GObject * recall_id)11792 ags_audio_remove_recall_id(AgsAudio *audio, GObject *recall_id)
11793 {
11794   GRecMutex *audio_mutex;
11795 
11796   if(!AGS_IS_AUDIO(audio) ||
11797      !AGS_IS_RECALL_ID(recall_id)){
11798     return;
11799   }
11800 
11801   /* get audio mutex */
11802   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
11803 
11804   /* remove recall id */
11805   g_rec_mutex_lock(audio_mutex);
11806 
11807   if(g_list_find(audio->recall_id,
11808 		 recall_id) != NULL){
11809     audio->recall_id = g_list_remove(audio->recall_id,
11810 				     recall_id);
11811     g_object_unref(recall_id);
11812   }
11813 
11814   g_rec_mutex_unlock(audio_mutex);
11815 }
11816 
11817 /**
11818  * ags_audio_get_recycling_context:
11819  * @audio: the #AgsAudio
11820  *
11821  * Get recycling_context.
11822  *
11823  * Returns: (element-type AgsAudio.RecyclingContext) (transfer full): the #GList-struct containig #AgsRecyclingContext
11824  *
11825  * Since: 3.1.0
11826  */
11827 GList*
ags_audio_get_recycling_context(AgsAudio * audio)11828 ags_audio_get_recycling_context(AgsAudio *audio)
11829 {
11830   GList *recycling_context;
11831 
11832   if(!AGS_IS_AUDIO(audio)){
11833     return(NULL);
11834   }
11835 
11836   g_object_get(audio,
11837 	       "recycling_context", &recycling_context,
11838 	       NULL);
11839 
11840   return(recycling_context);
11841 }
11842 
11843 /**
11844  * ags_audio_set_recycling_context:
11845  * @audio: the #AgsAudio
11846  * @recycling_context: (element-type AgsAudio.RecyclingContext) (transfer full): the #GList-struct containing #AgsRecyclingContext
11847  *
11848  * Set recycling_context by replacing existing.
11849  *
11850  * Since: 3.1.0
11851  */
11852 void
ags_audio_set_recycling_context(AgsAudio * audio,GList * recycling_context)11853 ags_audio_set_recycling_context(AgsAudio *audio, GList *recycling_context)
11854 {
11855   GList *start_recycling_context;
11856 
11857   GRecMutex *audio_mutex;
11858 
11859   if(!AGS_IS_AUDIO(audio)){
11860     return;
11861   }
11862 
11863   /* get audio mutex */
11864   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
11865 
11866   g_rec_mutex_lock(audio_mutex);
11867 
11868   start_recycling_context = audio->recycling_context;
11869   audio->recycling_context = recycling_context;
11870 
11871   g_rec_mutex_unlock(audio_mutex);
11872 
11873   g_list_free_full(start_recycling_context,
11874 		   (GDestroyNotify) g_object_unref);
11875 }
11876 
11877 /**
11878  * ags_audio_add_recycling_context:
11879  * @audio: the #AgsAudio
11880  * @recycling_context: the #AgsRecyclingContext
11881  *
11882  * Adds a recycling context.
11883  *
11884  * Since: 3.0.0
11885  */
11886 void
ags_audio_add_recycling_context(AgsAudio * audio,GObject * recycling_context)11887 ags_audio_add_recycling_context(AgsAudio *audio, GObject *recycling_context)
11888 {
11889   GRecMutex *audio_mutex;
11890 
11891   if(!AGS_IS_AUDIO(audio) ||
11892      !AGS_IS_RECYCLING_CONTEXT(recycling_context)){
11893     return;
11894   }
11895 
11896   /* get audio mutex */
11897   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
11898 
11899   /* add recycling context */
11900   g_rec_mutex_lock(audio_mutex);
11901 
11902   if(g_list_find(audio->recycling_context,
11903 		 recycling_context) == NULL){
11904     g_object_ref(recycling_context);
11905     audio->recycling_context = g_list_prepend(audio->recycling_context,
11906 					      recycling_context);
11907   }
11908 
11909   g_rec_mutex_unlock(audio_mutex);
11910 }
11911 
11912 /**
11913  * ags_audio_remove_recycling_context:
11914  * @audio: the #AgsAudio
11915  * @recycling_context: the #AgsRecyclingContext
11916  *
11917  * Removes a recycling context.
11918  *
11919  * Since: 3.0.0
11920  */
11921 void
ags_audio_remove_recycling_context(AgsAudio * audio,GObject * recycling_context)11922 ags_audio_remove_recycling_context(AgsAudio *audio, GObject *recycling_context)
11923 {
11924   GRecMutex *audio_mutex;
11925 
11926   if(!AGS_IS_AUDIO(audio) ||
11927      !AGS_IS_RECYCLING_CONTEXT(recycling_context)){
11928     return;
11929   }
11930 
11931   /* get audio mutex */
11932   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
11933 
11934   /* remove recycling container */
11935   g_rec_mutex_lock(audio_mutex);
11936 
11937   if(g_list_find(audio->recycling_context,
11938 		 recycling_context) != NULL){
11939     audio->recycling_context = g_list_remove(audio->recycling_context,
11940 					     recycling_context);
11941     g_object_unref(recycling_context);
11942   }
11943 
11944   g_rec_mutex_unlock(audio_mutex);
11945 }
11946 
11947 /**
11948  * ags_audio_get_recall_container:
11949  * @audio: the #AgsAudio
11950  *
11951  * Get recall_container.
11952  *
11953  * Returns: (element-type AgsAudio.RecallContainer) (transfer full): the #GList-struct containig #AgsRecallContainer
11954  *
11955  * Since: 3.1.0
11956  */
11957 GList*
ags_audio_get_recall_container(AgsAudio * audio)11958 ags_audio_get_recall_container(AgsAudio *audio)
11959 {
11960   GList *recall_container;
11961 
11962   if(!AGS_IS_AUDIO(audio)){
11963     return(NULL);
11964   }
11965 
11966   g_object_get(audio,
11967 	       "recall-container", &recall_container,
11968 	       NULL);
11969 
11970   return(recall_container);
11971 }
11972 
11973 /**
11974  * ags_audio_set_recall_container:
11975  * @audio: the #AgsAudio
11976  * @recall_container: (element-type AgsAudio.RecallContainer) (transfer full): the #GList-struct containing #AgsRecallContainer
11977  *
11978  * Set recall_container by replacing existing.
11979  *
11980  * Since: 3.1.0
11981  */
11982 void
ags_audio_set_recall_container(AgsAudio * audio,GList * recall_container)11983 ags_audio_set_recall_container(AgsAudio *audio, GList *recall_container)
11984 {
11985   GList *start_recall_container;
11986 
11987   GRecMutex *audio_mutex;
11988 
11989   if(!AGS_IS_AUDIO(audio)){
11990     return;
11991   }
11992 
11993   /* get audio mutex */
11994   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
11995 
11996   g_rec_mutex_lock(audio_mutex);
11997 
11998   start_recall_container = audio->recall_container;
11999   audio->recall_container = recall_container;
12000 
12001   g_rec_mutex_unlock(audio_mutex);
12002 
12003   g_list_free_full(start_recall_container,
12004 		   (GDestroyNotify) g_object_unref);
12005 }
12006 
12007 /**
12008  * ags_audio_add_recall_container:
12009  * @audio: the #AgsAudio
12010  * @recall_container: the #AgsRecallContainer
12011  *
12012  * Adds a recall container.
12013  *
12014  * Since: 3.0.0
12015  */
12016 void
ags_audio_add_recall_container(AgsAudio * audio,GObject * recall_container)12017 ags_audio_add_recall_container(AgsAudio *audio, GObject *recall_container)
12018 {
12019   GRecMutex *audio_mutex;
12020 
12021   if(!AGS_IS_AUDIO(audio) ||
12022      !AGS_IS_RECALL_CONTAINER(recall_container)){
12023     return;
12024   }
12025 
12026   /* get audio mutex */
12027   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
12028 
12029   /* add recall container */
12030   g_rec_mutex_lock(audio_mutex);
12031 
12032   if(g_list_find(audio->recall_container,
12033 		 recall_container) == NULL){
12034     g_object_ref(recall_container);
12035     audio->recall_container = g_list_prepend(audio->recall_container,
12036 					     recall_container);
12037   }
12038 
12039   g_rec_mutex_unlock(audio_mutex);
12040 }
12041 
12042 /**
12043  * ags_audio_remove_recall_container:
12044  * @audio: the #AgsAudio
12045  * @recall_container: the #AgsRecallContainer
12046  *
12047  * Removes a recall container.
12048  *
12049  * Since: 3.0.0
12050  */
12051 void
ags_audio_remove_recall_container(AgsAudio * audio,GObject * recall_container)12052 ags_audio_remove_recall_container(AgsAudio *audio, GObject *recall_container)
12053 {
12054   GRecMutex *audio_mutex;
12055 
12056   if(!AGS_IS_AUDIO(audio) ||
12057      !AGS_IS_RECALL_CONTAINER(recall_container)){
12058     return;
12059   }
12060 
12061   /* get audio mutex */
12062   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
12063 
12064   /* remove recall container */
12065   g_rec_mutex_lock(audio_mutex);
12066 
12067   if(g_list_find(audio->recall_container,
12068 		 recall_container) != NULL){
12069     audio->recall_container = g_list_remove(audio->recall_container,
12070 					    recall_container);
12071     g_object_unref(recall_container);
12072   }
12073 
12074   g_rec_mutex_unlock(audio_mutex);
12075 }
12076 
12077 /**
12078  * ags_audio_get_play:
12079  * @audio: the #AgsAudio
12080  *
12081  * Get play.
12082  *
12083  * Returns: (element-type AgsAudio.Recall) (transfer full): the #GList-struct containig #AgsRecall
12084  *
12085  * Since: 3.1.0
12086  */
12087 GList*
ags_audio_get_play(AgsAudio * audio)12088 ags_audio_get_play(AgsAudio *audio)
12089 {
12090   GList *play;
12091 
12092   if(!AGS_IS_AUDIO(audio)){
12093     return(NULL);
12094   }
12095 
12096   g_object_get(audio,
12097 	       "play", &play,
12098 	       NULL);
12099 
12100   return(play);
12101 }
12102 
12103 /**
12104  * ags_audio_set_play:
12105  * @audio: the #AgsAudio
12106  * @play: (element-type AgsAudio.Recall) (transfer full): the #GList-struct containing #AgsRecall
12107  *
12108  * Set play by replacing existing.
12109  *
12110  * Since: 3.1.0
12111  */
12112 void
ags_audio_set_play(AgsAudio * audio,GList * play)12113 ags_audio_set_play(AgsAudio *audio, GList *play)
12114 {
12115   GList *start_play;
12116 
12117   GRecMutex *audio_mutex;
12118 
12119   if(!AGS_IS_AUDIO(audio)){
12120     return;
12121   }
12122 
12123   /* get audio mutex */
12124   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
12125 
12126   g_rec_mutex_lock(audio_mutex);
12127 
12128   start_play = audio->play;
12129   audio->play = play;
12130 
12131   g_rec_mutex_unlock(audio_mutex);
12132 
12133   g_list_free_full(start_play,
12134 		   (GDestroyNotify) g_object_unref);
12135 }
12136 
12137 /**
12138  * ags_audio_get_recall:
12139  * @audio: the #AgsAudio
12140  *
12141  * Get recall.
12142  *
12143  * Returns: (element-type AgsAudio.Recall) (transfer full): the #GList-struct containig #AgsRecall
12144  *
12145  * Since: 3.1.0
12146  */
12147 GList*
ags_audio_get_recall(AgsAudio * audio)12148 ags_audio_get_recall(AgsAudio *audio)
12149 {
12150   GList *recall;
12151 
12152   if(!AGS_IS_AUDIO(audio)){
12153     return(NULL);
12154   }
12155 
12156   g_object_get(audio,
12157 	       "recall", &recall,
12158 	       NULL);
12159 
12160   return(recall);
12161 }
12162 
12163 /**
12164  * ags_audio_set_recall:
12165  * @audio: the #AgsAudio
12166  * @recall: (element-type AgsAudio.Recall) (transfer full): the #GList-struct containing #AgsRecall
12167  *
12168  * Set recall by replacing existing.
12169  *
12170  * Since: 3.1.0
12171  */
12172 void
ags_audio_set_recall(AgsAudio * audio,GList * recall)12173 ags_audio_set_recall(AgsAudio *audio, GList *recall)
12174 {
12175   GList *start_recall;
12176 
12177   GRecMutex *audio_mutex;
12178 
12179   if(!AGS_IS_AUDIO(audio)){
12180     return;
12181   }
12182 
12183   /* get audio mutex */
12184   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
12185 
12186   g_rec_mutex_lock(audio_mutex);
12187 
12188   start_recall = audio->recall;
12189   audio->recall = recall;
12190 
12191   g_rec_mutex_unlock(audio_mutex);
12192 
12193   g_list_free_full(start_recall,
12194 		   (GDestroyNotify) g_object_unref);
12195 }
12196 
12197 /**
12198  * ags_audio_add_recall:
12199  * @audio: the #AgsAudio
12200  * @recall: the #AgsRecall
12201  * @play_context: if %TRUE play context, else if %FALSE recall context
12202  *
12203  * Adds a recall to @audio.
12204  *
12205  * Since: 3.0.0
12206  */
12207 void
ags_audio_add_recall(AgsAudio * audio,GObject * recall,gboolean play_context)12208 ags_audio_add_recall(AgsAudio *audio, GObject *recall,
12209 		     gboolean play_context)
12210 {
12211   gboolean success;
12212 
12213   if(!AGS_IS_AUDIO(audio) ||
12214      !AGS_IS_RECALL(recall)){
12215     return;
12216   }
12217 
12218   success = FALSE;
12219 
12220   if(play_context){
12221     GRecMutex *play_mutex;
12222 
12223     /* get play mutex */
12224     play_mutex = AGS_AUDIO_GET_PLAY_MUTEX(audio);
12225 
12226     /* add recall */
12227     g_rec_mutex_lock(play_mutex);
12228 
12229     if(g_list_find(audio->play, recall) == NULL){
12230       success = TRUE;
12231 
12232       g_object_ref(G_OBJECT(recall));
12233 
12234       audio->play = g_list_prepend(audio->play,
12235 				   recall);
12236     }
12237 
12238     g_rec_mutex_unlock(play_mutex);
12239   }else{
12240     GRecMutex *recall_mutex;
12241 
12242     /* get recall mutex */
12243     recall_mutex = AGS_AUDIO_GET_RECALL_MUTEX(audio);
12244 
12245     /* add recall */
12246     g_rec_mutex_lock(recall_mutex);
12247 
12248     if(g_list_find(audio->recall, recall) == NULL){
12249       success = TRUE;
12250 
12251       g_object_ref(G_OBJECT(recall));
12252 
12253       audio->recall = g_list_prepend(audio->recall,
12254 				     recall);
12255     }
12256 
12257     g_rec_mutex_unlock(recall_mutex);
12258   }
12259 
12260   if(success){
12261     if(AGS_IS_RECALL_AUDIO(recall) ||
12262        AGS_IS_RECALL_AUDIO_RUN(recall)){
12263       g_object_set(recall,
12264 		   "audio", audio,
12265 		   NULL);
12266     }
12267   }
12268 }
12269 
12270 /**
12271  * ags_audio_insert_recall:
12272  * @audio: the #AgsAudio
12273  * @recall: the #AgsRecall
12274  * @play_context: if %TRUE play context, else if %FALSE recall context
12275  * @position: the position
12276  *
12277  * Insert @recall at @position in @audio's @play_context.
12278  *
12279  * Since: 3.3.0
12280  */
12281 void
ags_audio_insert_recall(AgsAudio * audio,GObject * recall,gboolean play_context,gint position)12282 ags_audio_insert_recall(AgsAudio *audio, GObject *recall,
12283 			gboolean play_context,
12284 			gint position)
12285 {
12286   gboolean success;
12287 
12288   if(!AGS_IS_AUDIO(audio) ||
12289      !AGS_IS_RECALL(recall)){
12290     return;
12291   }
12292 
12293   success = FALSE;
12294 
12295   if(play_context){
12296     GRecMutex *play_mutex;
12297 
12298     /* get play mutex */
12299     play_mutex = AGS_AUDIO_GET_PLAY_MUTEX(audio);
12300 
12301     /* add recall */
12302     g_rec_mutex_lock(play_mutex);
12303 
12304     if(g_list_find(audio->play, recall) == NULL){
12305       success = TRUE;
12306 
12307       g_object_ref(G_OBJECT(recall));
12308 
12309       audio->play = g_list_insert(audio->play,
12310 				  recall,
12311 				  position);
12312     }
12313 
12314     g_rec_mutex_unlock(play_mutex);
12315   }else{
12316     GRecMutex *recall_mutex;
12317 
12318     /* get recall mutex */
12319     recall_mutex = AGS_AUDIO_GET_RECALL_MUTEX(audio);
12320 
12321     /* add recall */
12322     g_rec_mutex_lock(recall_mutex);
12323 
12324     if(g_list_find(audio->recall, recall) == NULL){
12325       success = TRUE;
12326 
12327       g_object_ref(G_OBJECT(recall));
12328 
12329       audio->recall = g_list_insert(audio->recall,
12330 				    recall,
12331 				    position);
12332     }
12333 
12334     g_rec_mutex_unlock(recall_mutex);
12335   }
12336 
12337   if(success){
12338     if(AGS_IS_RECALL_AUDIO(recall) ||
12339        AGS_IS_RECALL_AUDIO_RUN(recall)){
12340       g_object_set(recall,
12341 		   "audio", audio,
12342 		   NULL);
12343     }
12344   }
12345 }
12346 
12347 /**
12348  * ags_audio_remove_recall:
12349  * @audio: the #AgsAudio
12350  * @recall: the #AgsRecall
12351  * @play_context: if %TRUE play context, else if %FALSE recall context
12352  *
12353  * Removes a recall from @audio.
12354  *
12355  * Since: 3.0.0
12356  */
12357 void
ags_audio_remove_recall(AgsAudio * audio,GObject * recall,gboolean play_context)12358 ags_audio_remove_recall(AgsAudio *audio, GObject *recall,
12359 			gboolean play_context)
12360 {
12361   gboolean success;
12362 
12363   if(!AGS_IS_AUDIO(audio) ||
12364      !AGS_IS_RECALL(recall)){
12365     return;
12366   }
12367 
12368   success = FALSE;
12369 
12370   if(play_context){
12371     GRecMutex *play_mutex;
12372 
12373     /* get play mutex */
12374     play_mutex = AGS_AUDIO_GET_PLAY_MUTEX(audio);
12375 
12376     /* add recall */
12377     g_rec_mutex_lock(play_mutex);
12378 
12379     if(g_list_find(audio->play, recall) != NULL){
12380       audio->play = g_list_remove(audio->play,
12381 				  recall);
12382     }
12383 
12384     g_rec_mutex_unlock(play_mutex);
12385   }else{
12386     GRecMutex *recall_mutex;
12387 
12388     /* get recall mutex */
12389     recall_mutex = AGS_AUDIO_GET_RECALL_MUTEX(audio);
12390 
12391     /* add recall */
12392     g_rec_mutex_lock(recall_mutex);
12393 
12394     if(g_list_find(audio->recall, recall) != NULL){
12395       audio->recall = g_list_remove(audio->recall,
12396 				    recall);
12397     }
12398 
12399     g_rec_mutex_unlock(recall_mutex);
12400   }
12401 
12402 #if 0
12403   if(success){
12404     if(AGS_IS_RECALL_AUDIO(recall) ||
12405        AGS_IS_RECALL_AUDIO_RUN(recall)){
12406       g_object_set(recall,
12407 		   "audio", NULL,
12408 		   NULL);
12409     }
12410 
12411     g_object_unref(G_OBJECT(recall));
12412   }
12413 #endif
12414 }
12415 
12416 void
ags_audio_real_duplicate_recall(AgsAudio * audio,AgsRecallID * recall_id,guint pad,guint audio_channel,guint line)12417 ags_audio_real_duplicate_recall(AgsAudio *audio,
12418 				AgsRecallID *recall_id,
12419 				guint pad, guint audio_channel,
12420 				guint line)
12421 {
12422   AgsRecall *recall, *copy_recall;
12423   AgsRecyclingContext *parent_recycling_context, *recycling_context;
12424 
12425   GList *list_start, *list;
12426 
12427   guint sound_scope;
12428   guint current_staging_flags;
12429   gboolean play_context;
12430 
12431   GRecMutex *audio_mutex;
12432   GRecMutex *recall_id_mutex;
12433   GRecMutex *recycling_context_mutex;
12434 
12435   if(!AGS_IS_RECALL_ID(recall_id)){
12436     return;
12437   }
12438 
12439   /* get recall id mutex */
12440   recall_id_mutex = AGS_RECALL_ID_GET_OBJ_MUTEX(recall_id);
12441 
12442   /* get some fields */
12443   g_rec_mutex_lock(recall_id_mutex);
12444 
12445   sound_scope = recall_id->sound_scope;
12446 
12447   g_rec_mutex_unlock(recall_id_mutex);
12448 
12449   if(sound_scope == -1){
12450     g_critical("can only duplicate for specific sound scope");
12451 
12452     return;
12453   }
12454 
12455   recycling_context = NULL;
12456 
12457   g_object_get(recall_id,
12458 	       "recycling-context", &recycling_context,
12459 	       NULL);
12460 
12461   /* get audio mutex */
12462   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
12463 
12464   /* get staging flags */
12465   g_rec_mutex_lock(audio_mutex);
12466 
12467   current_staging_flags = audio->staging_flags[sound_scope];
12468 
12469   g_rec_mutex_unlock(audio_mutex);
12470 
12471   if(!AGS_IS_RECYCLING_CONTEXT(recycling_context) ||
12472      (AGS_SOUND_STAGING_RUN_INIT_PRE & (current_staging_flags)) != 0){
12473     if(recycling_context != NULL){
12474       g_object_unref(recycling_context);
12475     }
12476 
12477     return;
12478   }
12479 
12480   /* get recycling context mutex */
12481   recycling_context_mutex = AGS_RECYCLING_CONTEXT_GET_OBJ_MUTEX(recycling_context);
12482 
12483   /* get parent recycling context */
12484   parent_recycling_context = NULL;
12485 
12486   g_object_get(recycling_context,
12487 	       "parent", &parent_recycling_context,
12488 	       NULL);
12489 
12490   /* get the appropriate list */
12491   if(parent_recycling_context == NULL){
12492     GRecMutex *play_mutex;
12493 
12494     play_context = TRUE;
12495 
12496     /* get play mutex */
12497     play_mutex = AGS_AUDIO_GET_PLAY_MUTEX(audio);
12498 
12499     /* copy play context */
12500     g_rec_mutex_lock(play_mutex);
12501 
12502     list_start = g_list_copy_deep(audio->play,
12503 				  (GCopyFunc) g_object_ref,
12504 				  NULL);
12505 
12506     g_rec_mutex_unlock(play_mutex);
12507 
12508     /* reverse play context */
12509     list =
12510       list_start = g_list_reverse(list_start);
12511   }else{
12512     GRecMutex *recall_mutex;
12513 
12514     play_context = FALSE;
12515 
12516     /* get recall mutex */
12517     recall_mutex = AGS_AUDIO_GET_RECALL_MUTEX(audio);
12518 
12519     /* copy recall context */
12520     g_rec_mutex_lock(recall_mutex);
12521 
12522     list_start = g_list_copy_deep(audio->recall,
12523 				  (GCopyFunc) g_object_ref,
12524 				  NULL);
12525 
12526     g_rec_mutex_unlock(recall_mutex);
12527 
12528     /* reverse recall context */
12529     list =
12530       list_start = g_list_reverse(list_start);
12531   }
12532 
12533   /* notify run */
12534   //  ags_recall_notify_dependency(AGS_RECALL(list->data), AGS_RECALL_NOTIFY_RUN, 1);
12535 
12536   /* return if already played */
12537   g_rec_mutex_lock(recall_id_mutex);
12538 
12539   if(ags_recall_id_check_state_flags(recall_id, AGS_SOUND_STATE_IS_WAITING) ||
12540      ags_recall_id_check_state_flags(recall_id, AGS_SOUND_STATE_IS_ACTIVE) ||
12541      ags_recall_id_check_state_flags(recall_id, AGS_SOUND_STATE_IS_PROCESSING) ||
12542      ags_recall_id_check_state_flags(recall_id, AGS_SOUND_STATE_IS_TERMINATING)){
12543     g_list_free_full(list_start,
12544 		     g_object_unref);
12545 
12546     if(parent_recycling_context != NULL){
12547       g_object_unref(parent_recycling_context);
12548     }
12549 
12550     if(recycling_context != NULL){
12551       g_object_unref(recycling_context);
12552     }
12553 
12554     g_rec_mutex_unlock(recall_id_mutex);
12555 
12556     return;
12557   }
12558 
12559 //  ags_recall_id_set_state_flags(recall_id,
12560 //				AGS_SOUND_STATE_IS_WAITING);
12561 
12562   g_rec_mutex_unlock(recall_id_mutex);
12563 
12564   /* duplicate */
12565   while(list != NULL){
12566     GRecMutex *current_recall_mutex;
12567 
12568     recall = AGS_RECALL(list->data);
12569 
12570     /* get current recall mutex */
12571     current_recall_mutex = AGS_RECALL_GET_OBJ_MUTEX(recall);
12572 
12573     /* some checks */
12574     g_rec_mutex_lock(current_recall_mutex);
12575 
12576     if(AGS_IS_RECALL_AUDIO(recall) ||
12577        (AGS_RECALL_TEMPLATE & (recall->flags)) == 0 ||
12578        recall->recall_id != NULL ||
12579        !ags_recall_match_ability_flags_to_scope(recall,
12580 						sound_scope)){
12581       list = list->next;
12582 
12583       g_rec_mutex_unlock(current_recall_mutex);
12584 
12585       continue;
12586     }
12587 
12588     g_rec_mutex_unlock(current_recall_mutex);
12589 
12590     /* duplicate the recall */
12591     copy_recall = ags_recall_duplicate(recall, recall_id,
12592 				       NULL, NULL, NULL);
12593 
12594     if(copy_recall == NULL){
12595       /* iterate */
12596       list = list->next;
12597 
12598       continue;
12599     }
12600 
12601     g_object_set(copy_recall,
12602 		 "pad", pad,
12603 		 "audio-channel", audio_channel,
12604 		 "line", line,
12605 		 NULL);
12606 
12607 #ifdef AGS_DEBUG
12608     g_message("recall duplicated: %s %s", G_OBJECT_TYPE_NAME(audio), G_OBJECT_TYPE_NAME(copy_recall));
12609 #endif
12610 
12611     /* set appropriate sound scope */
12612     ags_recall_set_sound_scope(copy_recall, sound_scope);
12613 
12614     /* append to AgsAudio */
12615     ags_audio_add_recall(audio,
12616 			 (GObject *) copy_recall,
12617 			 play_context);
12618     g_signal_connect(copy_recall, "done",
12619 		     G_CALLBACK(ags_audio_recall_done_callback), audio);
12620 
12621     /* connect */
12622     ags_connectable_connect(AGS_CONNECTABLE(copy_recall));
12623 
12624     /* notify run */
12625     ags_recall_notify_dependency(copy_recall, AGS_RECALL_NOTIFY_RUN, 1);
12626 
12627     /* iterate */
12628     list = list->next;
12629   }
12630 
12631   g_list_free_full(list_start,
12632 		   g_object_unref);
12633 
12634   if(parent_recycling_context != NULL){
12635     g_object_unref(parent_recycling_context);
12636   }
12637 
12638   if(recycling_context != NULL){
12639     g_object_unref(recycling_context);
12640   }
12641 }
12642 
12643 
12644 /**
12645  * ags_audio_duplicate_recall:
12646  * @audio: the #AgsAudio
12647  * @recall_id: an #AgsRecallID
12648  * @pad: the pad
12649  * @audio_channel: the audio channel
12650  * @line: the line
12651  *
12652  * Duplicate all #AgsRecall templates of @audio.
12653  *
12654  * Since: 3.0.0
12655  */
12656 void
ags_audio_duplicate_recall(AgsAudio * audio,AgsRecallID * recall_id,guint pad,guint audio_channel,guint line)12657 ags_audio_duplicate_recall(AgsAudio *audio,
12658 			   AgsRecallID *recall_id,
12659 			   guint pad, guint audio_channel,
12660 			   guint line)
12661 {
12662   g_return_if_fail(AGS_IS_AUDIO(audio));
12663 
12664   g_object_ref((GObject *) audio);
12665   g_signal_emit(G_OBJECT(audio),
12666 		audio_signals[DUPLICATE_RECALL], 0,
12667 		recall_id,
12668 		pad, audio_channel,
12669 		line);
12670   g_object_unref((GObject *) audio);
12671 }
12672 
12673 void
ags_audio_real_resolve_recall(AgsAudio * audio,AgsRecallID * recall_id)12674 ags_audio_real_resolve_recall(AgsAudio *audio,
12675 			      AgsRecallID *recall_id)
12676 {
12677   AgsRecall *recall;
12678   AgsRecyclingContext *parent_recycling_context, *recycling_context;
12679 
12680   GList *list_start, *list;
12681 
12682   guint sound_scope;
12683   guint current_staging_flags;
12684 
12685   GRecMutex *audio_mutex;
12686   GRecMutex *recall_id_mutex;
12687   GRecMutex *recycling_context_mutex;
12688 
12689   if(!AGS_IS_RECALL_ID(recall_id)){
12690     return;
12691   }
12692 
12693   /* get recall id mutex */
12694   recall_id_mutex = AGS_RECALL_ID_GET_OBJ_MUTEX(recall_id);
12695 
12696   /* get some fields */
12697   g_rec_mutex_lock(recall_id_mutex);
12698 
12699   sound_scope = recall_id->sound_scope;
12700 
12701   g_rec_mutex_unlock(recall_id_mutex);
12702 
12703   if(sound_scope == -1){
12704     g_critical("can only resolve for specific sound scope");
12705 
12706     return;
12707   }
12708 
12709   recycling_context = NULL;
12710 
12711   g_object_get(recall_id,
12712 	       "recycling-context", &recycling_context,
12713 	       NULL);
12714 
12715   /* get audio mutex */
12716   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
12717 
12718   /* get staging flags */
12719   g_rec_mutex_lock(audio_mutex);
12720 
12721   current_staging_flags = audio->staging_flags[sound_scope];
12722 
12723   g_rec_mutex_unlock(audio_mutex);
12724 
12725   if(!AGS_IS_RECYCLING_CONTEXT(recycling_context) ||
12726      (AGS_SOUND_STAGING_RUN_INIT_PRE & (current_staging_flags)) != 0){
12727     return;
12728   }
12729 
12730   /* get recycling context mutex */
12731   recycling_context_mutex = AGS_RECYCLING_CONTEXT_GET_OBJ_MUTEX(recycling_context);
12732 
12733   /* get parent recycling context */
12734   parent_recycling_context = NULL;
12735 
12736   g_object_get(recycling_context,
12737 	       "parent", &parent_recycling_context,
12738 	       NULL);
12739 
12740   /* get the appropriate lists */
12741   if(parent_recycling_context == NULL){
12742     GRecMutex *play_mutex;
12743 
12744     /* get play mutex */
12745     play_mutex = AGS_AUDIO_GET_PLAY_MUTEX(audio);
12746 
12747     /* copy play context */
12748     g_rec_mutex_lock(play_mutex);
12749 
12750     list =
12751       list_start = g_list_copy_deep(audio->play,
12752 				    (GCopyFunc) g_object_ref,
12753 				    NULL);
12754 
12755     g_rec_mutex_unlock(play_mutex);
12756 
12757     /* reverse play context */
12758     list =
12759       list_start = g_list_reverse(list_start);
12760   }else{
12761     GRecMutex *recall_mutex;
12762 
12763     /* get recall mutex */
12764     recall_mutex = AGS_AUDIO_GET_RECALL_MUTEX(audio);
12765 
12766     /* copy recall context */
12767     g_rec_mutex_lock(recall_mutex);
12768 
12769     list =
12770       list_start = g_list_copy_deep(audio->recall,
12771 				    (GCopyFunc) g_object_ref,
12772 				    NULL);
12773 
12774     g_rec_mutex_unlock(recall_mutex);
12775 
12776     /* reverse recall context */
12777     list =
12778       list_start = g_list_reverse(list_start);
12779   }
12780 
12781   /* resolve */
12782   while((list = ags_recall_find_recycling_context(list,
12783 						  (GObject *) recycling_context)) != NULL){
12784     recall = AGS_RECALL(list->data);
12785 
12786     ags_recall_resolve_dependency(recall);
12787 
12788     list = list->next;
12789   }
12790 
12791   g_list_free_full(list_start,
12792 		   g_object_unref);
12793 
12794   if(parent_recycling_context != NULL){
12795     g_object_unref(parent_recycling_context);
12796   }
12797 
12798   if(recycling_context != NULL){
12799     g_object_unref(recycling_context);
12800   }
12801 }
12802 
12803 /**
12804  * ags_audio_resolve_recall:
12805  * @audio: the #AgsAudio
12806  * @recall_id: the #AgsRecallID to use
12807  *
12808  * Performs resolving of recalls.
12809  *
12810  * Since: 3.0.0
12811  */
12812 void
ags_audio_resolve_recall(AgsAudio * audio,AgsRecallID * recall_id)12813 ags_audio_resolve_recall(AgsAudio *audio,
12814 			 AgsRecallID *recall_id)
12815 {
12816   g_return_if_fail(AGS_IS_AUDIO(audio));
12817 
12818   g_object_ref((GObject *) audio);
12819   g_signal_emit(G_OBJECT(audio),
12820 		audio_signals[RESOLVE_RECALL], 0,
12821 		recall_id);
12822   g_object_unref((GObject *) audio);
12823 }
12824 
12825 void
ags_audio_real_init_recall(AgsAudio * audio,AgsRecallID * recall_id,guint staging_flags)12826 ags_audio_real_init_recall(AgsAudio *audio,
12827 			   AgsRecallID *recall_id, guint staging_flags)
12828 {
12829   AgsRecall *recall;
12830   AgsRecyclingContext *parent_recycling_context, *recycling_context;
12831 
12832   GList *list_start, *list;
12833 
12834   guint sound_scope;
12835   guint current_staging_flags;
12836   static const guint staging_mask = (AGS_SOUND_STAGING_CHECK_RT_DATA |
12837 				     AGS_SOUND_STAGING_RUN_INIT_PRE |
12838 				     AGS_SOUND_STAGING_RUN_INIT_INTER |
12839 				     AGS_SOUND_STAGING_RUN_INIT_POST);
12840 
12841   GRecMutex *audio_mutex;
12842   GRecMutex *recall_id_mutex;
12843   GRecMutex *recycling_context_mutex;
12844 
12845   if(!AGS_IS_RECALL_ID(recall_id)){
12846     return;
12847   }
12848 
12849   /* get recall id mutex */
12850   recall_id_mutex = AGS_RECALL_ID_GET_OBJ_MUTEX(recall_id);
12851 
12852   /* get some fields */
12853   g_rec_mutex_lock(recall_id_mutex);
12854 
12855   sound_scope = recall_id->sound_scope;
12856 
12857   g_rec_mutex_unlock(recall_id_mutex);
12858 
12859   if(sound_scope == -1){
12860     g_critical("can only init for specific sound scope");
12861 
12862     return;
12863   }
12864 
12865   recycling_context = NULL;
12866 
12867   g_object_get(recall_id,
12868 	       "recycling-context", &recycling_context,
12869 	       NULL);
12870 
12871   /* get audio mutex */
12872   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
12873 
12874   /* get staging flags */
12875   g_rec_mutex_lock(audio_mutex);
12876 
12877   current_staging_flags = audio->staging_flags[sound_scope];
12878 
12879   g_rec_mutex_unlock(audio_mutex);
12880 
12881   if(!AGS_IS_RECYCLING_CONTEXT(recycling_context) ||
12882      (AGS_SOUND_STAGING_RUN_INIT_PRE & (current_staging_flags)) != 0){
12883     if(recycling_context != NULL){
12884       g_object_unref(recycling_context);
12885     }
12886 
12887     return;
12888   }
12889 
12890   /* get recycling context mutex */
12891   recycling_context_mutex = AGS_RECYCLING_CONTEXT_GET_OBJ_MUTEX(recycling_context);
12892 
12893   /* get parent recycling context */
12894   parent_recycling_context = NULL;
12895 
12896   g_object_get(recycling_context,
12897 	       "parent", &parent_recycling_context,
12898 	       NULL);
12899 
12900   /* get the appropriate lists */
12901   if(parent_recycling_context == NULL){
12902     GRecMutex *play_mutex;
12903 
12904     /* get play mutex */
12905     play_mutex = AGS_AUDIO_GET_PLAY_MUTEX(audio);
12906 
12907     /* copy play context */
12908     g_rec_mutex_lock(play_mutex);
12909 
12910     list =
12911       list_start = g_list_copy_deep(audio->play,
12912 				    (GCopyFunc) g_object_ref,
12913 				    NULL);
12914 
12915     g_rec_mutex_unlock(play_mutex);
12916 
12917     /* reverse play context */
12918     list =
12919       list_start = g_list_reverse(list_start);
12920   }else{
12921     GRecMutex *recall_mutex;
12922 
12923     /* get recall mutex */
12924     recall_mutex = AGS_AUDIO_GET_RECALL_MUTEX(audio);
12925 
12926     /* copy recall context */
12927     g_rec_mutex_lock(recall_mutex);
12928 
12929     list =
12930       list_start = g_list_copy_deep(audio->recall,
12931 				    (GCopyFunc) g_object_ref,
12932 				    NULL);
12933 
12934     g_rec_mutex_unlock(recall_mutex);
12935 
12936     /* reverse recall context */
12937     list =
12938       list_start = g_list_reverse(list_start);
12939   }
12940 
12941   /* init  */
12942   staging_flags = staging_mask & staging_flags;
12943 
12944   while((list = ags_recall_find_recycling_context(list,
12945 						  (GObject *) recycling_context)) != NULL){
12946     recall = AGS_RECALL(list->data);
12947 
12948     /* run init stages */
12949     ags_recall_set_staging_flags(recall,
12950 				 staging_flags);
12951 
12952     list = list->next;
12953   }
12954 
12955   g_list_free_full(list_start,
12956 		   g_object_unref);
12957 
12958 #if 0
12959   ags_audio_set_staging_flags(audio, sound_scope,
12960 			      staging_flags);
12961 #endif
12962 
12963   if(parent_recycling_context != NULL){
12964     g_object_unref(parent_recycling_context);
12965   }
12966 
12967   if(recycling_context != NULL){
12968     g_object_unref(recycling_context);
12969   }
12970 }
12971 
12972 /**
12973  * ags_audio_init_recall:
12974  * @audio: the #AgsAudio
12975  * @recall_id: the #AgsRecallID to use or #NULL
12976  * @staging_flags: staging flags, see #AgsSoundStagingFlags-enum
12977  *
12978  * Initializes the recalls of @audio
12979  *
12980  * Since: 3.0.0
12981  */
12982 void
ags_audio_init_recall(AgsAudio * audio,AgsRecallID * recall_id,guint staging_flags)12983 ags_audio_init_recall(AgsAudio *audio,
12984 		      AgsRecallID *recall_id, guint staging_flags)
12985 {
12986   g_return_if_fail(AGS_IS_AUDIO(audio));
12987 
12988   g_object_ref((GObject *) audio);
12989   g_signal_emit(G_OBJECT(audio),
12990 		audio_signals[INIT_RECALL], 0,
12991 		recall_id, staging_flags);
12992   g_object_unref((GObject *) audio);
12993 }
12994 
12995 void
ags_audio_real_play_recall(AgsAudio * audio,AgsRecallID * recall_id,guint staging_flags)12996 ags_audio_real_play_recall(AgsAudio *audio,
12997 			   AgsRecallID *recall_id, guint staging_flags)
12998 {
12999   AgsRecall *recall;
13000   AgsRecyclingContext *parent_recycling_context, *recycling_context;
13001 
13002   GList *list_start, *list;
13003 
13004   guint sound_scope;
13005   guint current_staging_flags;
13006   static const guint staging_mask = (AGS_SOUND_STAGING_RUN_INIT_PRE |
13007 				     AGS_SOUND_STAGING_RUN_INIT_INTER |
13008 				     AGS_SOUND_STAGING_RUN_INIT_POST |
13009 				     AGS_SOUND_STAGING_FEED_INPUT_QUEUE |
13010 				     AGS_SOUND_STAGING_AUTOMATE |
13011 				     AGS_SOUND_STAGING_RUN_PRE |
13012 				     AGS_SOUND_STAGING_RUN_INTER |
13013 				     AGS_SOUND_STAGING_RUN_POST |
13014 				     AGS_SOUND_STAGING_DO_FEEDBACK |
13015 				     AGS_SOUND_STAGING_FEED_OUTPUT_QUEUE |
13016 				     AGS_SOUND_STAGING_FINI);
13017 
13018   GRecMutex *audio_mutex;
13019   GRecMutex *recall_id_mutex;
13020   GRecMutex *recycling_context_mutex;
13021 
13022   if(!AGS_IS_RECALL_ID(recall_id)){
13023     return;
13024   }
13025 
13026   if(ags_recall_id_check_state_flags(recall_id, AGS_SOUND_STATE_IS_TERMINATING)){
13027     return;
13028   }
13029 
13030   /* get recall id mutex */
13031   recall_id_mutex = AGS_RECALL_ID_GET_OBJ_MUTEX(recall_id);
13032 
13033   /* get some fields */
13034   g_rec_mutex_lock(recall_id_mutex);
13035 
13036   sound_scope = recall_id->sound_scope;
13037 
13038   g_rec_mutex_unlock(recall_id_mutex);
13039 
13040   recycling_context = NULL;
13041 
13042   g_object_get(recall_id,
13043 	       "recycling-context", &recycling_context,
13044 	       NULL);
13045 
13046   /* get audio mutex */
13047   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
13048 
13049   /* get staging flags */
13050   g_rec_mutex_lock(audio_mutex);
13051 
13052   current_staging_flags = audio->staging_flags[sound_scope];
13053 
13054   g_rec_mutex_unlock(audio_mutex);
13055 
13056 #if 0
13057   if(!AGS_IS_RECYCLING_CONTEXT(recycling_context) ||
13058      (AGS_SOUND_STAGING_RUN_INIT_PRE & (current_staging_flags)) == 0 ||
13059      (AGS_SOUND_STAGING_RUN_INIT_INTER & (current_staging_flags)) == 0 ||
13060      (AGS_SOUND_STAGING_RUN_INIT_POST & (current_staging_flags)) == 0){
13061     return;
13062   }
13063 #endif
13064 
13065   /* get recycling context mutex */
13066   recycling_context_mutex = AGS_RECYCLING_CONTEXT_GET_OBJ_MUTEX(recycling_context);
13067 
13068   /* get parent recycling context */
13069   parent_recycling_context = NULL;
13070 
13071   g_object_get(recycling_context,
13072 	       "parent", &parent_recycling_context,
13073 	       NULL);
13074 
13075   /* get the appropriate lists */
13076   if(parent_recycling_context == NULL){
13077     GRecMutex *play_mutex;
13078 
13079     /* get play mutex */
13080     play_mutex = AGS_AUDIO_GET_PLAY_MUTEX(audio);
13081 
13082     /* copy play context */
13083     g_rec_mutex_lock(play_mutex);
13084 
13085     list_start = g_list_copy_deep(audio->play,
13086 				  (GCopyFunc) g_object_ref,
13087 				  NULL);
13088 
13089     g_rec_mutex_unlock(play_mutex);
13090 
13091     /* reverse play context */
13092     list =
13093       list_start = g_list_reverse(list_start);
13094   }else{
13095     GRecMutex *recall_mutex;
13096 
13097     /* get recall mutex */
13098     recall_mutex = AGS_AUDIO_GET_RECALL_MUTEX(audio);
13099 
13100     /* copy recall context */
13101     g_rec_mutex_lock(recall_mutex);
13102 
13103     list_start = g_list_copy_deep(audio->recall,
13104 				  (GCopyFunc) g_object_ref,
13105 				  NULL);
13106 
13107     g_rec_mutex_unlock(recall_mutex);
13108 
13109     /* reverse recall context */
13110     list =
13111       list_start = g_list_reverse(list_start);
13112   }
13113 
13114   /* automate and play  */
13115   if((AGS_SOUND_STAGING_FX & (staging_flags)) == 0){
13116     staging_flags = staging_flags & staging_mask;
13117 
13118     if((AGS_SOUND_STAGING_AUTOMATE & (staging_flags)) != 0){
13119       while(list != NULL){
13120 	recall = AGS_RECALL(list->data);
13121 
13122 	/* play stages */
13123 	if(AGS_IS_RECALL_AUDIO(recall)){
13124 	  ags_recall_set_staging_flags(recall,
13125 				       AGS_SOUND_STAGING_AUTOMATE);
13126 	  ags_recall_unset_staging_flags(recall,
13127 					 AGS_SOUND_STAGING_AUTOMATE);
13128 	}
13129 
13130 	list = list->next;
13131       }
13132     }
13133 
13134     staging_flags = staging_flags & (~AGS_SOUND_STAGING_AUTOMATE);
13135   }
13136 
13137   list = list_start;
13138 
13139   while((list = ags_recall_find_recycling_context(list,
13140 						  (GObject *) recycling_context)) != NULL){
13141     recall = AGS_RECALL(list->data);
13142 
13143     /* play stages */
13144     ags_recall_set_staging_flags(recall,
13145 				 staging_flags);
13146     ags_recall_unset_staging_flags(recall,
13147 				   staging_flags);
13148 
13149     list = list->next;
13150   }
13151 
13152   g_list_free_full(list_start,
13153 		   g_object_unref);
13154 
13155   if(parent_recycling_context != NULL){
13156     g_object_unref(parent_recycling_context);
13157   }
13158 
13159   if(recycling_context != NULL){
13160     g_object_unref(recycling_context);
13161   }
13162 
13163   //FIXME:JK: uncomment
13164   //  ags_audio_set_staging_flags(audio, sound_scope,
13165   //			      staging_flags);
13166 }
13167 
13168 /**
13169  * ags_audio_play_recall:
13170  * @audio: the #AgsAudio
13171  * @recall_id: the #AgsRecallID to apply to
13172  * @staging_flags: staging flags, see #AgsSoundStagingFlags-enum
13173  *
13174  * Performs play for the specified @staging_flags.
13175  *
13176  * Since: 3.0.0
13177  */
13178 void
ags_audio_play_recall(AgsAudio * audio,AgsRecallID * recall_id,guint staging_flags)13179 ags_audio_play_recall(AgsAudio *audio,
13180 		      AgsRecallID *recall_id, guint staging_flags)
13181 {
13182   g_return_if_fail(AGS_IS_AUDIO(audio) && AGS_IS_RECALL_ID(recall_id));
13183 
13184   g_object_ref((GObject *) audio);
13185   g_signal_emit(G_OBJECT(audio),
13186 		audio_signals[PLAY_RECALL], 0,
13187 		recall_id, staging_flags);
13188   g_object_unref((GObject *) audio);
13189 }
13190 
13191 void
ags_audio_real_done_recall(AgsAudio * audio,AgsRecallID * recall_id)13192 ags_audio_real_done_recall(AgsAudio *audio,
13193 			   AgsRecallID *recall_id)
13194 {
13195   AgsRecall *recall;
13196   AgsRecyclingContext *parent_recycling_context, *recycling_context;
13197 
13198   GList *list_start, *list;
13199 
13200   guint sound_scope;
13201   guint current_staging_flags;
13202   static const guint staging_flags = (AGS_SOUND_STAGING_DONE);
13203 
13204   GRecMutex *audio_mutex;
13205   GRecMutex *recall_id_mutex;
13206   GRecMutex *recycling_context_mutex;
13207 
13208   if(!AGS_IS_RECALL_ID(recall_id)){
13209     return;
13210   }
13211 
13212   /* get recall id mutex */
13213   recall_id_mutex = AGS_RECALL_ID_GET_OBJ_MUTEX(recall_id);
13214 
13215   /* get some fields */
13216   g_rec_mutex_lock(recall_id_mutex);
13217 
13218   sound_scope = recall_id->sound_scope;
13219 
13220   g_rec_mutex_unlock(recall_id_mutex);
13221 
13222   recycling_context = NULL;
13223 
13224   g_object_get(recall_id,
13225 	       "recycling-context", &recycling_context,
13226 	       NULL);
13227 
13228   /* get audio mutex */
13229   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
13230 
13231   /* get staging flags */
13232   g_rec_mutex_lock(audio_mutex);
13233 
13234   current_staging_flags = audio->staging_flags[sound_scope];
13235 
13236   g_rec_mutex_unlock(audio_mutex);
13237 
13238   if(!AGS_IS_RECYCLING_CONTEXT(recycling_context) ||
13239      (AGS_SOUND_STAGING_RUN_INIT_PRE & (current_staging_flags)) == 0 ||
13240      (AGS_SOUND_STAGING_RUN_INIT_INTER & (current_staging_flags)) == 0 ||
13241      (AGS_SOUND_STAGING_RUN_INIT_POST & (current_staging_flags)) == 0){
13242     if(recycling_context != NULL){
13243       g_object_unref(recycling_context);
13244     }
13245 
13246     return;
13247   }
13248 
13249   /* get recycling context mutex */
13250   recycling_context_mutex = AGS_RECYCLING_CONTEXT_GET_OBJ_MUTEX(recycling_context);
13251 
13252   /* get parent recycling context */
13253   parent_recycling_context = NULL;
13254 
13255   g_object_get(recycling_context,
13256 	       "parent", &parent_recycling_context,
13257 	       NULL);
13258 
13259   /* get the appropriate lists */
13260   if(parent_recycling_context == NULL){
13261     GRecMutex *play_mutex;
13262 
13263     /* get play mutex */
13264     play_mutex = AGS_AUDIO_GET_PLAY_MUTEX(audio);
13265 
13266     /* copy play context */
13267     g_rec_mutex_lock(play_mutex);
13268 
13269     list =
13270       list_start = g_list_copy_deep(audio->play,
13271 				    (GCopyFunc) g_object_ref,
13272 				    NULL);
13273 
13274     g_rec_mutex_unlock(play_mutex);
13275 
13276     /* reverse play context */
13277     list =
13278       list_start = g_list_reverse(list_start);
13279   }else{
13280     GRecMutex *recall_mutex;
13281 
13282     /* get recall mutex */
13283     recall_mutex = AGS_AUDIO_GET_RECALL_MUTEX(audio);
13284 
13285     /* copy recall context */
13286     g_rec_mutex_lock(recall_mutex);
13287 
13288     list =
13289       list_start = g_list_copy_deep(audio->recall,
13290 				    (GCopyFunc) g_object_ref,
13291 				    NULL);
13292 
13293     g_rec_mutex_unlock(recall_mutex);
13294 
13295     /* reverse recall context */
13296     list =
13297       list_start = g_list_reverse(list_start);
13298   }
13299 
13300   /* done  */
13301   while((list = ags_recall_find_recycling_context(list,
13302 						  (GObject *) recycling_context)) != NULL){
13303     recall = AGS_RECALL(list->data);
13304 
13305     /* done stages */
13306     ags_recall_set_staging_flags(recall,
13307 				 staging_flags);
13308 
13309     list = list->next;
13310   }
13311 
13312   g_list_free_full(list_start,
13313 		   g_object_unref);
13314 
13315   ags_audio_set_staging_flags(audio, sound_scope,
13316 			      staging_flags);
13317 
13318   if(parent_recycling_context != NULL){
13319     g_object_unref(parent_recycling_context);
13320   }
13321 
13322   if(recycling_context != NULL){
13323     g_object_unref(recycling_context);
13324   }
13325 }
13326 
13327 /**
13328  * ags_audio_done_recall:
13329  * @audio: the #AgsAudio
13330  * @recall_id: the #AgsRecallID to apply to
13331  *
13332  * Done processing audio data.
13333  *
13334  * Since: 3.0.0
13335  */
13336 void
ags_audio_done_recall(AgsAudio * audio,AgsRecallID * recall_id)13337 ags_audio_done_recall(AgsAudio *audio,
13338 		      AgsRecallID *recall_id)
13339 {
13340   g_return_if_fail(AGS_IS_AUDIO(audio));
13341 
13342   g_object_ref((GObject *) audio);
13343   g_signal_emit(G_OBJECT(audio),
13344 		audio_signals[DONE_RECALL], 0,
13345 		recall_id);
13346   g_object_unref((GObject *) audio);
13347 }
13348 
13349 void
ags_audio_real_cancel_recall(AgsAudio * audio,AgsRecallID * recall_id)13350 ags_audio_real_cancel_recall(AgsAudio *audio,
13351 			     AgsRecallID *recall_id)
13352 {
13353   AgsRecall *recall;
13354   AgsRecyclingContext *parent_recycling_context, *recycling_context;
13355 
13356   GList *list_start, *list;
13357 
13358   guint sound_scope;
13359   guint current_staging_flags;
13360   static const guint staging_flags = (AGS_SOUND_STAGING_CANCEL);
13361 
13362   GRecMutex *audio_mutex;
13363   GRecMutex *recall_id_mutex;
13364   GRecMutex *recycling_context_mutex;
13365 
13366   if(!AGS_IS_RECALL_ID(recall_id)){
13367     return;
13368   }
13369 
13370   /* get recall id mutex */
13371   recall_id_mutex = AGS_RECALL_ID_GET_OBJ_MUTEX(recall_id);
13372 
13373   /* get some fields */
13374   g_rec_mutex_lock(recall_id_mutex);
13375 
13376   sound_scope = recall_id->sound_scope;
13377 
13378   g_rec_mutex_unlock(recall_id_mutex);
13379 
13380   recycling_context = NULL;
13381 
13382   g_object_get(recall_id,
13383 	       "recycling-context", &recycling_context,
13384 	       NULL);
13385 
13386   /* get audio mutex */
13387   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
13388 
13389   /* get staging flags */
13390   g_rec_mutex_lock(audio_mutex);
13391 
13392   current_staging_flags = audio->staging_flags[sound_scope];
13393 
13394   g_rec_mutex_unlock(audio_mutex);
13395 
13396   if(!AGS_IS_RECYCLING_CONTEXT(recycling_context) ||
13397      (AGS_SOUND_STAGING_RUN_INIT_PRE & (current_staging_flags)) == 0 ||
13398      (AGS_SOUND_STAGING_RUN_INIT_INTER & (current_staging_flags)) == 0 ||
13399      (AGS_SOUND_STAGING_RUN_INIT_POST & (current_staging_flags)) == 0){
13400     if(recycling_context != NULL){
13401       g_object_unref(recycling_context);
13402     }
13403 
13404     return;
13405   }
13406 
13407   /* get recycling context mutex */
13408   recycling_context_mutex = AGS_RECYCLING_CONTEXT_GET_OBJ_MUTEX(recycling_context);
13409 
13410   /* get parent recycling context */
13411   parent_recycling_context = NULL;
13412 
13413   g_object_get(recycling_context,
13414 	       "parent", &parent_recycling_context,
13415 	       NULL);
13416 
13417   /* get the appropriate lists */
13418   if(parent_recycling_context == NULL){
13419     GRecMutex *play_mutex;
13420 
13421     /* get play mutex */
13422     play_mutex = AGS_AUDIO_GET_PLAY_MUTEX(audio);
13423 
13424     /* copy play context */
13425     g_rec_mutex_lock(play_mutex);
13426 
13427     list =
13428       list_start = g_list_copy_deep(audio->play,
13429 				    (GCopyFunc) g_object_ref,
13430 				    NULL);
13431 
13432     g_rec_mutex_unlock(play_mutex);
13433 
13434     /* reverse play context */
13435     list =
13436       list_start = g_list_reverse(list_start);
13437   }else{
13438     GRecMutex *recall_mutex;
13439 
13440     /* get recall mutex */
13441     recall_mutex = AGS_AUDIO_GET_RECALL_MUTEX(audio);
13442 
13443     /* copy recall context */
13444     g_rec_mutex_lock(recall_mutex);
13445 
13446     list =
13447       list_start = g_list_copy_deep(audio->recall,
13448 				    (GCopyFunc) g_object_ref,
13449 				    NULL);
13450 
13451     g_rec_mutex_unlock(recall_mutex);
13452 
13453     /* reverse recall context */
13454     list =
13455       list_start = g_list_reverse(list_start);
13456   }
13457 
13458   /* cancel  */
13459   while((list = ags_recall_find_recycling_context(list,
13460 						  (GObject *) recycling_context)) != NULL){
13461     recall = AGS_RECALL(list->data);
13462 
13463     /* cancel stages */
13464     ags_recall_set_staging_flags(recall,
13465 				 staging_flags);
13466 
13467     list = list->next;
13468   }
13469 
13470   g_list_free_full(list_start,
13471 		   g_object_unref);
13472 
13473   ags_audio_set_staging_flags(audio, sound_scope,
13474 			      staging_flags);
13475 
13476   if(parent_recycling_context != NULL){
13477     g_object_unref(parent_recycling_context);
13478   }
13479 
13480   if(recycling_context != NULL){
13481     g_object_unref(recycling_context);
13482   }
13483 }
13484 
13485 /**
13486  * ags_audio_cancel_recall:
13487  * @audio: the #AgsAudio
13488  * @recall_id: the #AgsRecallID to apply to
13489  *
13490  * Cancel processing audio data.
13491  *
13492  * Since: 3.0.0
13493  */
13494 void
ags_audio_cancel_recall(AgsAudio * audio,AgsRecallID * recall_id)13495 ags_audio_cancel_recall(AgsAudio *audio,
13496 			AgsRecallID *recall_id)
13497 {
13498   g_return_if_fail(AGS_IS_AUDIO(audio));
13499 
13500   g_object_ref((GObject *) audio);
13501   g_signal_emit(G_OBJECT(audio),
13502 		audio_signals[CANCEL_RECALL], 0,
13503 		recall_id);
13504   g_object_unref((GObject *) audio);
13505 }
13506 
13507 void
ags_audio_real_cleanup_recall(AgsAudio * audio,AgsRecallID * recall_id)13508 ags_audio_real_cleanup_recall(AgsAudio *audio,
13509 			      AgsRecallID *recall_id)
13510 {
13511   AgsRecall *recall;
13512   AgsRecyclingContext *parent_recycling_context, *recycling_context;
13513 
13514   GList *list_start, *list;
13515   GList *match_start, *match;
13516 
13517   gint sound_scope;
13518   guint current_staging_flags;
13519   gboolean play_context;
13520   gboolean remove_recycling_context;
13521 
13522   static const guint staging_mask = (AGS_SOUND_STAGING_CHECK_RT_DATA |
13523 				     AGS_SOUND_STAGING_RUN_INIT_PRE |
13524 				     AGS_SOUND_STAGING_RUN_INIT_INTER |
13525 				     AGS_SOUND_STAGING_RUN_INIT_POST);
13526 
13527   GRecMutex *audio_mutex;
13528   GRecMutex *recall_id_mutex;
13529   GRecMutex *recycling_context_mutex;
13530 
13531   if(!AGS_IS_RECALL_ID(recall_id)){
13532     return;
13533   }
13534 
13535   /* get recall id mutex */
13536   recall_id_mutex = AGS_RECALL_ID_GET_OBJ_MUTEX(recall_id);
13537 
13538   /* get some fields */
13539   g_rec_mutex_lock(recall_id_mutex);
13540 
13541   sound_scope = recall_id->sound_scope;
13542 
13543   g_rec_mutex_unlock(recall_id_mutex);
13544 
13545   recycling_context = NULL;
13546 
13547   g_object_get(recall_id,
13548 	       "recycling-context", &recycling_context,
13549 	       NULL);
13550 
13551   /* get audio mutex */
13552   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
13553 
13554   /* get staging flags */
13555   g_rec_mutex_lock(audio_mutex);
13556 
13557   current_staging_flags = audio->staging_flags[sound_scope];
13558 
13559   g_rec_mutex_unlock(audio_mutex);
13560 
13561   /* get recycling context mutex */
13562   recycling_context_mutex = AGS_RECYCLING_CONTEXT_GET_OBJ_MUTEX(recycling_context);
13563 
13564   /* get parent recycling context */
13565   parent_recycling_context = NULL;
13566 
13567   g_object_get(recycling_context,
13568 	       "parent", &parent_recycling_context,
13569 	       NULL);
13570 
13571   g_rec_mutex_lock(recycling_context_mutex);
13572 
13573   remove_recycling_context = FALSE;
13574 
13575   if((AgsRecallID *) recycling_context->recall_id == recall_id){
13576     remove_recycling_context = TRUE;
13577   }
13578 
13579   g_rec_mutex_unlock(recycling_context_mutex);
13580 
13581   /* get the appropriate lists */
13582   if(parent_recycling_context == NULL){
13583     GRecMutex *play_mutex;
13584 
13585     play_context = TRUE;
13586 
13587     /* get play mutex */
13588     play_mutex = AGS_AUDIO_GET_PLAY_MUTEX(audio);
13589 
13590     /* copy play context */
13591     g_rec_mutex_lock(play_mutex);
13592 
13593     list =
13594       list_start = g_list_copy_deep(audio->play,
13595 				    (GCopyFunc) g_object_ref,
13596 				    NULL);
13597 
13598     g_rec_mutex_unlock(play_mutex);
13599 
13600     /* reverse play context */
13601     list =
13602       list_start = g_list_reverse(list_start);
13603   }else{
13604     GRecMutex *recall_mutex;
13605 
13606     play_context = FALSE;
13607 
13608     /* get recall mutex */
13609     recall_mutex = AGS_AUDIO_GET_RECALL_MUTEX(audio);
13610 
13611     /* copy recall context */
13612     g_rec_mutex_lock(recall_mutex);
13613 
13614     list =
13615       list_start = g_list_copy_deep(audio->recall,
13616 				    (GCopyFunc) g_object_ref,
13617 				    NULL);
13618 
13619     g_rec_mutex_unlock(recall_mutex);
13620 
13621     /* reverse recall context */
13622     list =
13623       list_start = g_list_reverse(list_start);
13624   }
13625 
13626   /* cleanup  */
13627   match_start = NULL;
13628 
13629   while((list = ags_recall_find_recycling_context(list,
13630 						  (GObject *) recycling_context)) != NULL){
13631     recall = AGS_RECALL(list->data);
13632 
13633     /* remove recall */
13634     ags_audio_remove_recall(audio, (GObject *) recall, play_context);
13635     match_start = g_list_prepend(match_start,
13636 				 recall);
13637 
13638     list = list->next;
13639   }
13640 
13641   g_list_free_full(list_start,
13642 		   g_object_unref);
13643 
13644   /* destroy  */
13645   match = match_start;
13646 
13647   while(match != NULL){
13648     recall = AGS_RECALL(match->data);
13649 
13650     /* destroy */
13651     ags_connectable_disconnect(AGS_CONNECTABLE(recall));
13652     g_object_run_dispose((GObject *) recall);
13653 
13654     match = match->next;
13655   }
13656 
13657   g_list_free_full(match_start,
13658 		   g_object_unref);
13659 }
13660 
13661 /**
13662  * ags_audio_cleanup_recall:
13663  * @audio: the #AgsAudio
13664  * @recall_id: the #AgsRecallID to apply to
13665  *
13666  * Cleanup processing audio data.
13667  *
13668  * Since: 3.0.0
13669  */
13670 void
ags_audio_cleanup_recall(AgsAudio * audio,AgsRecallID * recall_id)13671 ags_audio_cleanup_recall(AgsAudio *audio,
13672 			 AgsRecallID *recall_id)
13673 {
13674   g_return_if_fail(AGS_IS_AUDIO(audio));
13675 
13676   g_object_ref((GObject *) audio);
13677   g_signal_emit(G_OBJECT(audio),
13678 		audio_signals[CLEANUP_RECALL], 0,
13679 		recall_id);
13680   g_object_unref((GObject *) audio);
13681 }
13682 
13683 void
ags_audio_recall_done_callback(AgsRecall * recall,AgsAudio * audio)13684 ags_audio_recall_done_callback(AgsRecall *recall,
13685 			       AgsAudio *audio)
13686 {
13687   AgsCancelAudio *cancel_audio;
13688 
13689   AgsTaskLauncher *task_launcher;
13690 
13691   AgsApplicationContext *application_context;
13692 
13693   gint sound_scope;
13694 
13695   if(!ags_recall_test_state_flags(recall, AGS_SOUND_STATE_IS_TERMINATING) &&
13696      (AGS_IS_COUNT_BEATS_AUDIO_RUN(recall) ||
13697       AGS_IS_FX_PATTERN_AUDIO_PROCESSOR(recall) ||
13698       AGS_IS_FX_NOTATION_AUDIO_PROCESSOR(recall) ||
13699       AGS_IS_FX_PLAYBACK_AUDIO_PROCESSOR(recall))){
13700     sound_scope = ags_recall_get_sound_scope(recall);
13701 
13702     application_context = ags_application_context_get_instance();
13703 
13704     task_launcher = ags_concurrency_provider_get_task_launcher(AGS_CONCURRENCY_PROVIDER(application_context));
13705 
13706     cancel_audio = ags_cancel_audio_new(audio,
13707 					sound_scope);
13708 
13709     ags_task_launcher_add_task(task_launcher,
13710 			       cancel_audio);
13711 
13712     g_object_unref(cancel_audio);
13713   }
13714 }
13715 
13716 GList*
ags_audio_real_start(AgsAudio * audio,gint sound_scope)13717 ags_audio_real_start(AgsAudio *audio,
13718 		     gint sound_scope)
13719 {
13720   AgsChannel *channel;
13721   AgsRecycling *first_recycling;
13722   AgsPlaybackDomain *playback_domain;
13723   AgsPlayback *playback;
13724   AgsRecallID *audio_recall_id;
13725   AgsRecallID *channel_recall_id;
13726   AgsRecallID *current_recall_id;
13727   AgsRecyclingContext *recycling_context;
13728 
13729   AgsThread *audio_loop;
13730   AgsThread *audio_thread;
13731   AgsThread *channel_thread;
13732   AgsMessageDelivery *message_delivery;
13733 
13734   AgsApplicationContext *application_context;
13735 
13736   GList *start_message_queue;
13737   GList *start_output_playback, *output_playback;
13738   GList *start_recall_id;
13739   GList *start_wait_thread, *wait_thread;
13740 
13741   gint64 start_wait_timeout;
13742   guint audio_channels;
13743   guint output_pads;
13744   gint i;
13745 
13746   static const guint staging_flags = (AGS_SOUND_STAGING_CHECK_RT_DATA |
13747 				      AGS_SOUND_STAGING_RUN_INIT_PRE |
13748 				      AGS_SOUND_STAGING_RUN_INIT_INTER |
13749 				      AGS_SOUND_STAGING_RUN_INIT_POST);
13750 
13751   if(sound_scope >= AGS_SOUND_SCOPE_LAST){
13752     return(NULL);
13753   }
13754 
13755   application_context = ags_application_context_get_instance();
13756 
13757   audio_loop = ags_concurrency_provider_get_main_loop(AGS_CONCURRENCY_PROVIDER(application_context));
13758 
13759   /* add audio to AgsAudioLoop */
13760   ags_audio_loop_add_audio(audio_loop,
13761 			   (GObject *) audio);
13762 
13763   ags_audio_loop_set_flags(audio_loop, AGS_AUDIO_LOOP_PLAY_AUDIO);
13764 
13765   /* get some fields */
13766   g_object_get(audio,
13767 	       "playback-domain", &playback_domain,
13768 	       NULL);
13769 
13770   g_object_get(playback_domain,
13771 	       "output-playback", &start_output_playback,
13772 	       NULL);
13773 
13774   /* initialize channel */
13775   start_recall_id = NULL;
13776 
13777   if(sound_scope >= 0){
13778     output_playback = start_output_playback;
13779 
13780     while(output_playback != NULL){
13781       playback = AGS_PLAYBACK(output_playback->data);
13782 
13783       current_recall_id = ags_playback_get_recall_id(playback,
13784 						     sound_scope);
13785 
13786       if(current_recall_id == NULL){
13787 	/* get some fields */
13788 	channel = NULL;
13789 
13790 	g_object_get(playback,
13791 		     "channel", &channel,
13792 		     NULL);
13793 
13794 	g_object_get(channel,
13795 		     "first-recycling", &first_recycling,
13796 		     NULL);
13797 
13798 	/* recycling context */
13799 	recycling_context = ags_recycling_context_new(1);
13800 	ags_audio_add_recycling_context(audio,
13801 					(GObject *) recycling_context);
13802 	ags_recycling_context_replace(recycling_context,
13803 				      first_recycling,
13804 				      0);
13805 
13806 	/* create audio recall id */
13807 	audio_recall_id = g_object_new(AGS_TYPE_RECALL_ID,
13808 				       "recycling-context", recycling_context,
13809 				       NULL);
13810 	ags_recall_id_set_sound_scope(audio_recall_id, sound_scope);
13811 	ags_audio_add_recall_id(audio,
13812 				(GObject *) audio_recall_id);
13813 
13814 	g_object_set(recycling_context,
13815 		     "recall-id", audio_recall_id,
13816 		     NULL);
13817 
13818 	/* create channel recall id */
13819 	channel_recall_id = g_object_new(AGS_TYPE_RECALL_ID,
13820 					 "recycling-context", recycling_context,
13821 					 NULL);
13822 	ags_recall_id_set_sound_scope(channel_recall_id, sound_scope);
13823 	ags_channel_add_recall_id(channel,
13824 				  (GObject *) channel_recall_id);
13825 
13826 	/* prepend recall id */
13827 	start_recall_id = g_list_prepend(start_recall_id,
13828 					 channel_recall_id);
13829 
13830 	/* set playback's recall id */
13831 	//NOTE:JK: we use audio recall id, although on AgsPlayback
13832 	ags_playback_set_recall_id(playback,
13833 				   audio_recall_id,
13834 				   sound_scope);
13835 
13836 	/* unref */
13837 	g_object_unref(channel);
13838 
13839 	g_object_unref(first_recycling);
13840       }else{
13841 	start_recall_id = g_list_prepend(start_recall_id,
13842 					 current_recall_id);
13843       }
13844 
13845       /* iterate */
13846       output_playback = output_playback->next;
13847     }
13848 
13849     /* play init */
13850     ags_audio_recursive_run_stage(audio,
13851 				  sound_scope, staging_flags);
13852 
13853     output_playback = start_output_playback;
13854 
13855     /* add to start queue */
13856     start_wait_thread = NULL;
13857 
13858     if(ags_playback_domain_test_flags(playback_domain, AGS_PLAYBACK_DOMAIN_SUPER_THREADED_AUDIO)){
13859       audio_thread = ags_playback_domain_get_audio_thread(playback_domain,
13860 							  sound_scope);
13861 
13862       if(audio_thread != NULL){
13863 	start_wait_thread = g_list_prepend(start_wait_thread,
13864 					   audio_thread);
13865 
13866 #if 1
13867 	ags_thread_add_start_queue(audio_loop,
13868 				   audio_thread);
13869 #else
13870 	ags_thread_start(audio_thread);
13871 #endif
13872       }
13873     }
13874 
13875     while(output_playback != NULL){
13876       playback = AGS_PLAYBACK(output_playback->data);
13877 
13878       if(ags_playback_test_flags(playback, AGS_PLAYBACK_SUPER_THREADED_CHANNEL)){
13879 	channel_thread = ags_playback_get_channel_thread(playback,
13880 							 sound_scope);
13881 
13882 	/* add to start queue */
13883 	if(channel_thread != NULL){
13884 	  start_wait_thread = g_list_prepend(start_wait_thread,
13885 					     channel_thread);
13886 
13887 #if 1
13888 	  ags_thread_add_start_queue(audio_loop,
13889 				     channel_thread);
13890 #else
13891 	  ags_thread_start(channel_thread);
13892 #endif
13893 	}
13894       }
13895 
13896 
13897       /* iterate */
13898       output_playback = output_playback->next;
13899     }
13900 
13901     /* unref */
13902 #if 0
13903     wait_thread = start_wait_thread;
13904 
13905     start_wait_timeout = g_get_monotonic_time() + 5 * G_USEC_PER_SEC;
13906 
13907     while(wait_thread != NULL){
13908       /* wait thread */
13909       g_mutex_lock(AGS_THREAD_GET_START_MUTEX(wait_thread->data));
13910 
13911       if(!ags_thread_test_status_flags(wait_thread->data, AGS_THREAD_STATUS_START_DONE)){
13912 	ags_thread_set_status_flags(wait_thread->data, AGS_THREAD_STATUS_START_WAIT);
13913 
13914 	while(ags_thread_test_status_flags(wait_thread->data, AGS_THREAD_STATUS_START_WAIT) &&
13915 	      !ags_thread_test_status_flags(wait_thread->data, AGS_THREAD_STATUS_START_DONE) &&
13916 	      g_get_monotonic_time() < start_wait_timeout){
13917 	  g_cond_wait_until(AGS_THREAD_GET_START_COND(wait_thread->data),
13918 			    AGS_THREAD_GET_START_MUTEX(wait_thread->data),
13919 			    start_wait_timeout);
13920 	}
13921       }
13922 
13923       g_mutex_unlock(AGS_THREAD_GET_START_MUTEX(wait_thread->data));
13924 
13925       if(g_get_monotonic_time() > start_wait_timeout){
13926 	g_critical("sync timeout");
13927 
13928 	goto ags_audio_real_start_ONE_SCOPE_TIMEOUT;
13929       }
13930 
13931       wait_thread = wait_thread->next;
13932     }
13933 #endif
13934 
13935   ags_audio_real_start_ONE_SCOPE_TIMEOUT:
13936     g_list_free_full(start_wait_thread,
13937 		     g_object_unref);
13938 
13939     start_wait_thread = NULL;
13940   }else{
13941     start_wait_thread = NULL;
13942 
13943     for(i = 0; i < AGS_SOUND_SCOPE_LAST; i++){
13944       output_playback = start_output_playback;
13945 
13946       while(output_playback != NULL){
13947 	playback = AGS_PLAYBACK(output_playback->data);
13948 
13949 	current_recall_id = ags_playback_get_recall_id(playback,
13950 						       i);
13951 
13952 	if(current_recall_id == NULL){
13953 	  /* get some fields */
13954 	  channel = NULL;
13955 
13956 	  g_object_get(playback,
13957 		       "channel", &channel,
13958 		       NULL);
13959 
13960 	  g_object_get(channel,
13961 		       "first-recycling", &first_recycling,
13962 		       NULL);
13963 
13964 	  /* recycling context */
13965 	  recycling_context = ags_recycling_context_new(1);
13966 	  ags_audio_add_recycling_context(audio,
13967 					  (GObject *) recycling_context);
13968 
13969 	  /* set recycling */
13970 	  ags_recycling_context_replace(recycling_context,
13971 					first_recycling,
13972 					0);
13973 
13974 	  /* create audio recall id */
13975 	  audio_recall_id = g_object_new(AGS_TYPE_RECALL_ID,
13976 					 "recycling-context", recycling_context,
13977 					 NULL);
13978 	  ags_recall_id_set_sound_scope(audio_recall_id, i);
13979 	  ags_audio_add_recall_id(audio,
13980 				  (GObject *) audio_recall_id);
13981 
13982 	  g_object_set(recycling_context,
13983 		       "recall-id", audio_recall_id,
13984 		       NULL);
13985 
13986 	  /* create channel recall id */
13987 	  channel_recall_id = g_object_new(AGS_TYPE_RECALL_ID,
13988 					   "recycling-context", recycling_context,
13989 					   NULL);
13990 	  ags_recall_id_set_sound_scope(channel_recall_id, i);
13991 	  ags_channel_add_recall_id(channel,
13992 				    (GObject *) channel_recall_id);
13993 
13994 	  /* prepend recall id */
13995 	  start_recall_id = g_list_prepend(start_recall_id,
13996 					   channel_recall_id);
13997 
13998 	  /* set playback's recall id */
13999 	  //NOTE:JK: we use audio recall id, although on AgsPlayback
14000 	  ags_playback_set_recall_id(playback,
14001 				     audio_recall_id,
14002 				     i);
14003 
14004 	  /* unref */
14005 	  g_object_unref(channel);
14006 
14007 	  g_object_unref(first_recycling);
14008 	}else{
14009 	  start_recall_id = g_list_prepend(start_recall_id,
14010 					   current_recall_id);
14011 	}
14012 
14013 	/* iterate */
14014 	output_playback = output_playback->next;
14015       }
14016 
14017       /* play init */
14018       ags_audio_recursive_run_stage(audio,
14019 				    i, staging_flags);
14020 
14021       output_playback = start_output_playback;
14022 
14023       /* add to start queue */
14024       if(ags_playback_domain_test_flags(playback_domain, AGS_PLAYBACK_DOMAIN_SUPER_THREADED_AUDIO)){
14025 	audio_thread = ags_playback_domain_get_audio_thread(playback_domain,
14026 							    i);
14027 
14028 	if(audio_thread != NULL){
14029 	  start_wait_thread = g_list_prepend(start_wait_thread,
14030 					     audio_thread);
14031 
14032 #if 1
14033 	  ags_thread_add_start_queue(audio_loop,
14034 				     audio_thread);
14035 #else
14036 	  ags_thread_start(audio_thread);
14037 #endif
14038 	}
14039       }
14040 
14041       while(output_playback != NULL){
14042 	playback = AGS_PLAYBACK(output_playback->data);
14043 
14044 	if(ags_playback_test_flags(playback, AGS_PLAYBACK_SUPER_THREADED_CHANNEL)){
14045 	  channel_thread = ags_playback_get_channel_thread(playback,
14046 							   i);
14047 
14048 	  if(channel_thread != NULL){
14049 	    start_wait_thread = g_list_prepend(start_wait_thread,
14050 					       channel_thread);
14051 
14052 	    /* add to start queue */
14053 #if 1
14054 	    ags_thread_add_start_queue(audio_loop,
14055 				       channel_thread);
14056 #else
14057 	    ags_thread_start(channel_thread);
14058 #endif
14059 	  }
14060 	}
14061 
14062 	/* iterate */
14063 	output_playback = output_playback->next;
14064       }
14065     }
14066 
14067     /* unref */
14068 #if 0
14069     wait_thread = start_wait_thread;
14070 
14071     start_wait_timeout = g_get_monotonic_time() + 5 * G_USEC_PER_SEC;
14072 
14073     while(wait_thread != NULL){
14074       /* wait thread */
14075       g_mutex_lock(AGS_THREAD_GET_START_MUTEX(wait_thread->data));
14076 
14077       if(!ags_thread_test_status_flags(wait_thread->data, AGS_THREAD_STATUS_START_DONE)){
14078 	ags_thread_set_status_flags(wait_thread->data, AGS_THREAD_STATUS_START_WAIT);
14079 
14080 	while(ags_thread_test_status_flags(wait_thread->data, AGS_THREAD_STATUS_START_WAIT) &&
14081 	      !ags_thread_test_status_flags(wait_thread->data, AGS_THREAD_STATUS_START_DONE) &&
14082 	      g_get_monotonic_time() < start_wait_timeout){
14083 	  g_cond_wait_until(AGS_THREAD_GET_START_COND(wait_thread->data),
14084 			    AGS_THREAD_GET_START_MUTEX(wait_thread->data),
14085 			    start_wait_timeout);
14086 	}
14087       }
14088 
14089       g_mutex_unlock(AGS_THREAD_GET_START_MUTEX(wait_thread->data));
14090 
14091       if(g_get_monotonic_time() > start_wait_timeout){
14092 	g_critical("sync timeout");
14093 
14094 	goto ags_audio_real_start_ALL_SCOPE_TIMEOUT;
14095       }
14096 
14097       wait_thread = wait_thread->next;
14098     }
14099 #endif
14100 
14101   ags_audio_real_start_ALL_SCOPE_TIMEOUT:
14102     g_list_free_full(start_wait_thread,
14103 		     g_object_unref);
14104 
14105     start_wait_thread = NULL;
14106   }
14107 
14108   g_object_unref(playback_domain);
14109 
14110   g_list_free_full(start_output_playback,
14111 		   g_object_unref);
14112 
14113   start_recall_id = g_list_reverse(start_recall_id);
14114 
14115   /* emit message */
14116   message_delivery = ags_message_delivery_get_instance();
14117 
14118   start_message_queue = ags_message_delivery_find_sender_namespace(message_delivery,
14119 								   "libags-audio");
14120 
14121   if(start_message_queue != NULL){
14122     AgsMessageEnvelope *message;
14123 
14124     xmlDoc *doc;
14125     xmlNode *root_node;
14126 
14127     /* specify message body */
14128     doc = xmlNewDoc("1.0");
14129 
14130     root_node = xmlNewNode(NULL,
14131 			   "ags-command");
14132     xmlDocSetRootElement(doc, root_node);
14133 
14134     xmlNewProp(root_node,
14135 	       "method",
14136 	       "AgsAudio::start");
14137 
14138     /* add message */
14139     message = ags_message_envelope_new((GObject *) audio,
14140 				       NULL,
14141 				       doc);
14142 
14143     /* set parameter */
14144     message->n_params = 2;
14145 
14146     message->parameter_name = (gchar **) malloc(3 * sizeof(gchar *));
14147     message->value = g_new0(GValue,
14148 			    2);
14149 
14150     /* sound scope */
14151     message->parameter_name[0] = "sound-scope";
14152     g_value_init(&(message->value[0]),
14153 		 G_TYPE_INT);
14154     g_value_set_int(&(message->value[0]),
14155 		    sound_scope);
14156 
14157     /* recall id */
14158     message->parameter_name[1] = "recall-id";
14159     g_value_init(&(message->value[1]),
14160 		 G_TYPE_POINTER);
14161     g_value_set_pointer(&(message->value[1]),
14162 			g_list_copy_deep(start_recall_id,
14163 					 (GCopyFunc) g_object_ref,
14164 					 NULL));
14165 
14166     /* terminate string vector */
14167     message->parameter_name[2] = NULL;
14168 
14169     /* add message */
14170     ags_message_delivery_add_message_envelope(message_delivery,
14171 					      "libags-audio",
14172 					      message);
14173 
14174     g_list_free_full(start_message_queue,
14175 		     (GDestroyNotify) g_object_unref);
14176   }
14177 
14178   return(start_recall_id);
14179 }
14180 
14181 /**
14182  * ags_audio_start:
14183  * @audio: the #AgsAudio
14184  * @sound_scope: the scope
14185  *
14186  * Is emitted as audio is started.
14187  *
14188  * Returns: (element-type AgsAudio.RecallID) (transfer full): the #GList-struct containing #AgsRecallID
14189  *
14190  * Since: 3.0.0
14191  */
14192 GList*
ags_audio_start(AgsAudio * audio,gint sound_scope)14193 ags_audio_start(AgsAudio *audio,
14194 		gint sound_scope)
14195 {
14196   GList *recall_id;
14197 
14198   g_return_val_if_fail(AGS_IS_AUDIO(audio), NULL);
14199 
14200   /* emit */
14201   recall_id = NULL;
14202 
14203   g_object_ref((GObject *) audio);
14204   g_signal_emit(G_OBJECT(audio),
14205 		audio_signals[START], 0,
14206 		sound_scope,
14207 		&recall_id);
14208   g_object_unref((GObject *) audio);
14209 
14210   return(recall_id);
14211 }
14212 
14213 void
ags_audio_real_stop(AgsAudio * audio,GList * recall_id,gint sound_scope)14214 ags_audio_real_stop(AgsAudio *audio,
14215 		    GList *recall_id, gint sound_scope)
14216 {
14217   AgsChannel *channel;
14218   AgsPlaybackDomain *playback_domain;
14219   AgsPlayback *playback;
14220   AgsRecallID *sequencer_recall_id, *notation_recall_id, *wave_recall_id, *midi_recall_id;
14221 
14222   AgsThread *audio_loop;
14223   AgsThread *audio_thread;
14224   AgsThread *channel_thread;
14225   AgsMessageDelivery *message_delivery;
14226 
14227   AgsApplicationContext *application_context;
14228 
14229   GList *list;
14230   GList *start_message_queue;
14231   GList *start_output_playback, *output_playback;
14232   GList *sequencer, *notation, *wave, *midi;
14233 
14234   gint i;
14235 
14236   static const guint staging_flags = (AGS_SOUND_STAGING_CANCEL |
14237 				      AGS_SOUND_STAGING_REMOVE);
14238 
14239   if(recall_id == NULL ||
14240      sound_scope >= AGS_SOUND_SCOPE_LAST){
14241     return;
14242   }
14243 
14244   list = recall_id;
14245 
14246   while(list != NULL){
14247     ags_recall_id_set_state_flags(list->data, AGS_SOUND_STATE_IS_TERMINATING);
14248 
14249     list = list->next;
14250   }
14251 
14252   application_context = ags_application_context_get_instance();
14253 
14254   audio_loop = ags_concurrency_provider_get_main_loop(AGS_CONCURRENCY_PROVIDER(application_context));
14255 
14256   /* get some fields */
14257   g_object_get(audio,
14258 	       "playback-domain", &playback_domain,
14259 	       NULL);
14260 
14261   g_object_get(playback_domain,
14262 	       "output-playback", &start_output_playback,
14263 	       NULL);
14264 
14265   if(sound_scope >= 0){
14266     /* stop thread */
14267     audio_thread = ags_playback_domain_get_audio_thread(playback_domain,
14268 							sound_scope);
14269 
14270     if(audio_thread != NULL){
14271       ags_thread_stop(audio_thread);
14272 
14273       g_object_unref(audio_thread);
14274     }
14275 
14276     output_playback = start_output_playback;
14277 
14278     while(output_playback != NULL){
14279       playback = AGS_PLAYBACK(output_playback->data);
14280 
14281       channel = NULL;
14282 
14283       g_object_get(playback,
14284 		   "channel", &channel,
14285 		   NULL);
14286 
14287       channel_thread = ags_playback_get_channel_thread(playback,
14288 						       sound_scope);
14289 
14290       if(channel_thread != NULL){
14291 	ags_thread_stop(channel_thread);
14292 
14293 	g_object_unref(channel_thread);
14294       }
14295 
14296       if(channel != NULL){
14297 	g_object_unref(channel);
14298       }
14299 
14300       /* iterate */
14301       output_playback = output_playback->next;
14302     }
14303 
14304     /* cancel */
14305     ags_audio_recursive_run_stage(audio,
14306 				  sound_scope, staging_flags);
14307 
14308     /* clean - fini */
14309     ags_audio_recursive_run_stage(audio,
14310 				  sound_scope, AGS_SOUND_STAGING_FINI);
14311 
14312     output_playback = start_output_playback;
14313 
14314     while(output_playback != NULL){
14315       playback = AGS_PLAYBACK(output_playback->data);
14316 
14317       ags_playback_set_recall_id(playback,
14318 				 NULL,
14319 				 sound_scope);
14320 
14321       /* iterate */
14322       output_playback = output_playback->next;
14323     }
14324   }else{
14325     for(i = 0; i < AGS_SOUND_SCOPE_LAST; i++){
14326       /* stop thread */
14327       audio_thread = ags_playback_domain_get_audio_thread(playback_domain,
14328 							  i);
14329 
14330       if(audio_thread != NULL){
14331 	ags_thread_stop(audio_thread);
14332 
14333 	g_object_unref(audio_thread);
14334       }
14335 
14336       output_playback = start_output_playback;
14337 
14338       while(output_playback != NULL){
14339 	playback = AGS_PLAYBACK(output_playback->data);
14340 
14341 	channel = NULL;
14342 
14343 	g_object_get(playback,
14344 		     "channel", &channel,
14345 		     NULL);
14346 
14347 	channel_thread = ags_playback_get_channel_thread(playback,
14348 							 i);
14349 
14350 	if(channel_thread != NULL){
14351 	  ags_thread_stop(channel_thread);
14352 
14353 	  g_object_unref(channel_thread);
14354 	}
14355 
14356 	if(channel != NULL){
14357 	  g_object_unref(channel);
14358 	}
14359 
14360 	/* iterate */
14361 	output_playback = output_playback->next;
14362       }
14363     }
14364 
14365     for(i = 0; i < AGS_SOUND_SCOPE_LAST; i++){
14366       /* cancel */
14367       ags_audio_recursive_run_stage(audio,
14368 				    i, staging_flags);
14369 
14370       /* clean - fini */
14371       ags_audio_recursive_run_stage(audio,
14372 				    i, AGS_SOUND_STAGING_FINI);
14373 
14374       output_playback = start_output_playback;
14375 
14376       while(output_playback != NULL){
14377 	playback = AGS_PLAYBACK(output_playback->data);
14378 
14379 	ags_playback_set_recall_id(playback,
14380 				   NULL,
14381 				   i);
14382 
14383 	/* iterate */
14384 	output_playback = output_playback->next;
14385       }
14386     }
14387   }
14388 
14389   list = recall_id;
14390 
14391   while(list != NULL){
14392     ags_audio_remove_recall_id(audio,
14393 			       (GObject *) list->data);
14394 
14395     list = list->next;
14396   }
14397 
14398   /* remove audio from AgsAudioLoop */
14399   sequencer = ags_audio_check_scope(audio,
14400 				    (AGS_SOUND_SCOPE_SEQUENCER));
14401   sequencer_recall_id = ags_recall_id_find_parent_recycling_context(sequencer,
14402 								    NULL);
14403 
14404   notation = ags_audio_check_scope(audio,
14405 				   (AGS_SOUND_SCOPE_NOTATION));
14406   notation_recall_id = ags_recall_id_find_parent_recycling_context(notation,
14407 								   NULL);
14408 
14409   wave = ags_audio_check_scope(audio,
14410 			       (AGS_SOUND_SCOPE_WAVE));
14411   wave_recall_id = ags_recall_id_find_parent_recycling_context(wave,
14412 							       NULL);
14413 
14414   midi = ags_audio_check_scope(audio,
14415 			       (AGS_SOUND_SCOPE_MIDI));
14416   midi_recall_id = ags_recall_id_find_parent_recycling_context(midi,
14417 							       NULL);
14418 
14419   if(sequencer_recall_id == NULL &&
14420      notation_recall_id == NULL &&
14421      wave_recall_id == NULL &&
14422      midi_recall_id == NULL){
14423     ags_audio_loop_remove_audio(audio_loop,
14424 				(GObject *) audio);
14425   }
14426 
14427   g_list_free_full(sequencer,
14428 		   g_object_unref);
14429   g_list_free_full(notation,
14430 		   g_object_unref);
14431   g_list_free_full(wave,
14432 		   g_object_unref);
14433   g_list_free_full(midi,
14434 		   g_object_unref);
14435 
14436   g_object_unref(playback_domain);
14437 
14438   g_list_free_full(start_output_playback,
14439 		   g_object_unref);
14440 
14441   /* emit message */
14442   message_delivery = ags_message_delivery_get_instance();
14443 
14444   start_message_queue = ags_message_delivery_find_sender_namespace(message_delivery,
14445 								   "libags-audio");
14446 
14447   if(start_message_queue != NULL){
14448     AgsMessageEnvelope *message;
14449 
14450     xmlDoc *doc;
14451     xmlNode *root_node;
14452 
14453     /* specify message body */
14454     doc = xmlNewDoc("1.0");
14455 
14456     root_node = xmlNewNode(NULL,
14457 			   "ags-command");
14458     xmlDocSetRootElement(doc, root_node);
14459 
14460     xmlNewProp(root_node,
14461 	       "method",
14462 	       "AgsAudio::stop");
14463 
14464     /* add message */
14465     message = ags_message_envelope_new((GObject *) audio,
14466 				       NULL,
14467 				       doc);
14468 
14469     /* set parameter */
14470     message->n_params = 2;
14471 
14472     message->parameter_name = (gchar **) malloc(3 * sizeof(gchar *));
14473     message->value = g_new0(GValue,
14474 			    2);
14475 
14476     /* recall id */
14477     message->parameter_name[0] = "recall-id";
14478 
14479     g_value_init(&(message->value[0]),
14480 		 G_TYPE_POINTER);
14481     g_value_set_pointer(&(message->value[0]),
14482 			recall_id);
14483 
14484     /* sound scope */
14485     message->parameter_name[1] = "sound-scope";
14486 
14487     g_value_init(&(message->value[1]),
14488 		 G_TYPE_INT);
14489     g_value_set_int(&(message->value[1]),
14490 		    sound_scope);
14491 
14492     /* terminate string vector */
14493     message->parameter_name[2] = NULL;
14494 
14495     /* add message */
14496     ags_message_delivery_add_message_envelope(message_delivery,
14497 					      "libags-audio",
14498 					      message);
14499 
14500     g_list_free_full(start_message_queue,
14501 		     (GDestroyNotify) g_object_unref);
14502   }
14503 }
14504 
14505 /**
14506  * ags_audio_stop:
14507  * @audio: the #AgsAudio
14508  * @recall_id: (element-type AgsAudio.RecallID) (transfer none): the #GList-struct containing #AgsRecallID
14509  * @sound_scope: the scope
14510  *
14511  * Is emitted as playing audio is stopped.
14512  *
14513  * Since: 3.0.0
14514  */
14515 void
ags_audio_stop(AgsAudio * audio,GList * recall_id,gint sound_scope)14516 ags_audio_stop(AgsAudio *audio,
14517 	       GList *recall_id, gint sound_scope)
14518 {
14519   g_return_if_fail(AGS_IS_AUDIO(audio));
14520 
14521   /* emit */
14522   g_object_ref((GObject *) audio);
14523   g_signal_emit(G_OBJECT(audio),
14524 		audio_signals[STOP], 0,
14525 		recall_id, sound_scope);
14526   g_object_unref((GObject *) audio);
14527 }
14528 
14529 GList*
ags_audio_real_check_scope(AgsAudio * audio,gint sound_scope)14530 ags_audio_real_check_scope(AgsAudio *audio, gint sound_scope)
14531 {
14532   GList *list_start, *list;
14533   GList *recall_id;
14534 
14535   gint i;
14536 
14537   /* get recall id */
14538   g_object_get(audio,
14539 	       "recall-id", &list_start,
14540 	       NULL);
14541 
14542   /* iterate recall id */
14543   list = list_start;
14544 
14545   recall_id = NULL;
14546 
14547   if(sound_scope >= 0){
14548     while(list != NULL){
14549       /* check sound scope */
14550       if(ags_recall_id_check_sound_scope(list->data, sound_scope)){
14551 	recall_id = g_list_prepend(recall_id,
14552 				   list->data);
14553       }
14554 
14555       /* iterate */
14556       list = list->next;
14557     }
14558   }else{
14559     for(i = 0; i < AGS_SOUND_SCOPE_LAST; i++){
14560       list = list_start;
14561 
14562       while(list != NULL){
14563 	/* check sound scope */
14564 	if(ags_recall_id_check_sound_scope(list->data, i)){
14565 	  recall_id = g_list_prepend(recall_id,
14566 				     list->data);
14567 	}
14568 
14569 	/* iterate */
14570 	list = list->next;
14571       }
14572     }
14573   }
14574 
14575   /* reverse recall id */
14576   recall_id = g_list_reverse(recall_id);
14577   g_list_foreach(recall_id,
14578 		 (GFunc) g_object_ref,
14579 		 NULL);
14580 
14581   /* unref */
14582   g_list_free_full(list_start,
14583 		   g_object_unref);
14584 
14585   return(recall_id);
14586 }
14587 
14588 /**
14589  * ags_audio_check_scope:
14590  * @audio: the #AgsAudio
14591  * @sound_scope: the scope
14592  *
14593  * Check scope's recall id.
14594  *
14595  * Returns: (element-type AgsAudio.RecallID) (transfer full): the scope's recall id of @audio
14596  *
14597  * Since: 3.0.0
14598  */
14599 GList*
ags_audio_check_scope(AgsAudio * audio,gint sound_scope)14600 ags_audio_check_scope(AgsAudio *audio, gint sound_scope)
14601 {
14602   GList *recall_id;
14603 
14604   g_return_val_if_fail(AGS_IS_AUDIO(audio),
14605 		       NULL);
14606 
14607   /* emit */
14608   g_object_ref((GObject *) audio);
14609   g_signal_emit(G_OBJECT(audio),
14610 		audio_signals[CHECK_SCOPE], 0,
14611 		sound_scope,
14612 		&recall_id);
14613   g_object_unref((GObject *) audio);
14614 
14615   return(recall_id);
14616 }
14617 
14618 /**
14619  * ags_audio_collect_all_audio_ports:
14620  * @audio: the #AgsAudio
14621  *
14622  * Retrieve all ports of #AgsAudio.
14623  *
14624  * Returns: (element-type AgsAudio.Port) (transfer full): a new #GList containing #AgsPort
14625  *
14626  * Since: 3.0.0
14627  */
14628 GList*
ags_audio_collect_all_audio_ports(AgsAudio * audio)14629 ags_audio_collect_all_audio_ports(AgsAudio *audio)
14630 {
14631   GList *recall_start, *recall;
14632   GList *list;
14633 
14634   GRecMutex *recall_mutex, *play_mutex;
14635   GRecMutex *mutex;
14636 
14637   if(!AGS_IS_AUDIO(audio)){
14638     return(NULL);
14639   }
14640 
14641   list = NULL;
14642 
14643   /* get play mutex */
14644   play_mutex = AGS_AUDIO_GET_PLAY_MUTEX(audio);
14645 
14646   /* collect port of playing recall */
14647   g_rec_mutex_lock(play_mutex);
14648 
14649   recall =
14650     recall_start = g_list_copy_deep(audio->play,
14651 				    (GCopyFunc) g_object_ref,
14652 				    NULL);
14653 
14654   g_rec_mutex_unlock(play_mutex);
14655 
14656   while(recall != NULL){
14657     AgsRecall *current;
14658 
14659     current = AGS_RECALL(recall->data);
14660 
14661     /* get mutex */
14662     mutex = AGS_RECALL_GET_OBJ_MUTEX(current);
14663 
14664     /* concat port */
14665     g_rec_mutex_lock(mutex);
14666 
14667     if(current->port != NULL){
14668       if(list == NULL){
14669 	list = g_list_copy_deep(current->port,
14670 				(GCopyFunc) g_object_ref,
14671 				NULL);
14672       }else{
14673 	if(current->port != NULL){
14674 	  list = g_list_concat(list,
14675 			       g_list_copy_deep(current->port,
14676 						(GCopyFunc) g_object_ref,
14677 						NULL));
14678 	}
14679       }
14680     }
14681 
14682     g_rec_mutex_unlock(mutex);
14683 
14684     /* iterate */
14685     recall = recall->next;
14686   }
14687 
14688   g_list_free_full(recall_start,
14689 		   g_object_unref);
14690 
14691   /* get recall mutex */
14692   recall_mutex = AGS_AUDIO_GET_RECALL_MUTEX(audio);
14693 
14694   /* the same for true recall */
14695   g_rec_mutex_lock(recall_mutex);
14696 
14697   recall =
14698     recall_start = g_list_copy_deep(audio->recall,
14699 				    (GCopyFunc) g_object_ref,
14700 				    NULL);
14701 
14702   g_rec_mutex_unlock(recall_mutex);
14703 
14704   while(recall != NULL){
14705     AgsRecall *current;
14706 
14707     current = AGS_RECALL(recall->data);
14708 
14709     /* get mutex */
14710     mutex = AGS_RECALL_GET_OBJ_MUTEX(current);
14711 
14712     /* concat port */
14713     g_rec_mutex_lock(mutex);
14714 
14715     if(current->port != NULL){
14716       if(list == NULL){
14717 	list = g_list_copy_deep(current->port,
14718 				(GCopyFunc) g_object_ref,
14719 				NULL);
14720       }else{
14721 	if(current->port != NULL){
14722 	  list = g_list_concat(list,
14723 			       g_list_copy_deep(current->port,
14724 						(GCopyFunc) g_object_ref,
14725 						NULL));
14726 	}
14727       }
14728     }
14729 
14730     g_rec_mutex_unlock(mutex);
14731 
14732     /* iterate */
14733     recall = recall->next;
14734   }
14735 
14736   g_list_free_full(recall_start,
14737 		   g_object_unref);
14738 
14739   /* reverse result */
14740   list = g_list_reverse(list);
14741 
14742   return(list);
14743 }
14744 
14745 /**
14746  * ags_audio_collect_all_audio_ports_by_specifier_and_context:
14747  * @audio: an #AgsAudio
14748  * @specifier: the port's name
14749  * @play_context: either %TRUE for play or %FALSE for recall
14750  *
14751  * Retrieve specified port of #AgsAudio
14752  *
14753  * Returns: (element-type AgsAudio.Port) (transfer full): a #GList-struct of #AgsPort if found, otherwise %NULL
14754  *
14755  * Since: 3.0.0
14756  */
14757 GList*
ags_audio_collect_all_audio_ports_by_specifier_and_context(AgsAudio * audio,gchar * specifier,gboolean play_context)14758 ags_audio_collect_all_audio_ports_by_specifier_and_context(AgsAudio *audio,
14759 							   gchar *specifier,
14760 							   gboolean play_context)
14761 {
14762   GList *recall_start, *recall;
14763   GList *port_start, *port;
14764   GList *list;
14765 
14766   GRecMutex *recall_mutex;
14767 
14768   if(!AGS_IS_AUDIO(audio)){
14769     return(NULL);
14770   }
14771 
14772   if(play_context){
14773     /* get play mutex */
14774     recall_mutex = AGS_AUDIO_GET_PLAY_MUTEX(audio);
14775 
14776     /* get recall */
14777     g_rec_mutex_lock(recall_mutex);
14778 
14779     recall =
14780       recall_start = g_list_copy_deep(audio->play,
14781 				      (GCopyFunc) g_object_ref,
14782 				      NULL);
14783 
14784     g_rec_mutex_unlock(recall_mutex);
14785   }else{
14786     /* get recall mutex */
14787     recall_mutex = AGS_AUDIO_GET_RECALL_MUTEX(audio);
14788 
14789     /* get recall */
14790     g_rec_mutex_lock(recall_mutex);
14791 
14792     recall =
14793       recall_start = g_list_copy_deep(audio->recall,
14794 				      (GCopyFunc) g_object_ref,
14795 				      NULL);
14796 
14797     g_rec_mutex_unlock(recall_mutex);
14798   }
14799 
14800   /* collect port of playing recall */
14801   list = NULL;
14802 
14803   while(recall != NULL){
14804     AgsRecall *current;
14805 
14806     GRecMutex *mutex;
14807 
14808     current = AGS_RECALL(recall->data);
14809 
14810     /* get mutex */
14811     mutex = AGS_RECALL_GET_OBJ_MUTEX(current);
14812 
14813     /* get port */
14814     g_rec_mutex_lock(mutex);
14815 
14816     port =
14817       port_start = g_list_copy_deep(current->port,
14818 				    (GCopyFunc) g_object_ref,
14819 				    NULL);
14820 
14821     g_rec_mutex_unlock(mutex);
14822 
14823     /* check specifier */
14824     while((port = ags_port_find_specifier(port, specifier)) != NULL){
14825       AgsPort *current;
14826 
14827       current = AGS_PORT(port->data);
14828 
14829       g_object_ref(current);
14830       list = g_list_prepend(list,
14831 			    current);
14832 
14833       /* iterate - port */
14834       port = port->next;
14835     }
14836 
14837     g_list_free_full(port_start,
14838 		     g_object_unref);
14839 
14840     /* iterate - recall */
14841     recall = recall->next;
14842   }
14843 
14844   g_list_free_full(recall_start,
14845 		   g_object_unref);
14846 
14847   /* reverse result */
14848   list = g_list_reverse(list);
14849 
14850   return(list);
14851 }
14852 
14853 /**
14854  * ags_audio_open_audio_file_as_channel:
14855  * @audio: the #AgsAudio
14856  * @filename: (element-type utf8) (transfer none): the files to open
14857  * @overwrite_channels: if existing channels should be assigned
14858  * @create_channels: if new channels should be created as not fitting if combined with @overwrite_channels
14859  *
14860  * Open some files.
14861  *
14862  * Since: 3.0.0
14863  */
14864 void
ags_audio_open_audio_file_as_channel(AgsAudio * audio,GSList * filename,gboolean overwrite_channels,gboolean create_channels)14865 ags_audio_open_audio_file_as_channel(AgsAudio *audio,
14866 				     GSList *filename,
14867 				     gboolean overwrite_channels,
14868 				     gboolean create_channels)
14869 {
14870   AgsChannel *start_input;
14871   AgsChannel *channel;
14872   AgsAudioFile *audio_file;
14873 
14874   GObject *soundcard;
14875 
14876   GList *audio_signal;
14877 
14878   guint input_pads;
14879   guint audio_channels;
14880   guint i, j;
14881   guint list_length;
14882 
14883   GError *error;
14884 
14885   GRecMutex *audio_mutex;
14886   GRecMutex *recycling_mutex;
14887 
14888   if(!AGS_IS_AUDIO(audio) ||
14889      filename == NULL ||
14890      (!overwrite_channels &&
14891       !create_channels)){
14892     return;
14893   }
14894 
14895   /* get audio mutex */
14896   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
14897 
14898   /* get audio fields */
14899   soundcard = NULL;
14900   start_input = NULL;
14901 
14902   g_object_get(audio,
14903 	       "output-soundcard", &soundcard,
14904 	       "input", &start_input,
14905 	       NULL);
14906 
14907   g_rec_mutex_lock(audio_mutex);
14908 
14909   input_pads = audio->input_pads;
14910   audio_channels = audio->audio_channels;
14911 
14912   g_rec_mutex_unlock(audio_mutex);
14913 
14914   /* overwriting existing channels */
14915   if(overwrite_channels){
14916     channel = start_input;
14917 
14918     g_object_ref(channel);
14919 
14920     if(channel != NULL){
14921       for(i = 0; i < input_pads && filename != NULL; i++){
14922 	audio_file = ags_audio_file_new((gchar *) filename->data,
14923 					soundcard,
14924 					-1);
14925 
14926 	if(!ags_audio_file_open(audio_file)){
14927 	  filename = filename->next;
14928 
14929 	  continue;
14930 	}
14931 
14932 	ags_audio_file_read_audio_signal(audio_file);
14933 	ags_audio_file_close(audio_file);
14934 
14935 	audio_signal = audio_file->audio_signal;
14936 
14937 	for(j = 0; j < audio_channels && audio_signal != NULL; j++){
14938 	  AgsChannel *next;
14939 	  AgsRecycling *recycling;
14940 
14941 	  AgsFileLink *file_link;
14942 
14943 	  /* reset link */
14944 	  error = NULL;
14945 
14946 	  ags_channel_set_link(channel, NULL,
14947 			       &error);
14948 
14949 	  if(error != NULL){
14950 	    g_warning("%s", error->message);
14951 
14952 
14953 	    g_error_free(error);
14954 	  }
14955 
14956 	  /* get recycling */
14957 	  recycling = NULL;
14958 
14959 	  file_link = NULL;
14960 
14961 	  g_object_get(channel,
14962 		       "first-recycling", &recycling,
14963 		       "file-link", &file_link,
14964 		       NULL);
14965 
14966 	  /* set filename and channel */
14967 	  if(file_link == NULL){
14968 	    file_link = g_object_new(AGS_TYPE_AUDIO_FILE_LINK,
14969 				     NULL);
14970 
14971 	    g_object_set(channel,
14972 			 "file-link", file_link,
14973 			 NULL);
14974 	  }
14975 
14976 	  g_object_set(file_link,
14977 		       "filename", filename->data,
14978 		       "audio-channel", j,
14979 		       NULL);
14980 
14981 	  g_object_unref(file_link);
14982 
14983 	  /* get recycling mutex */
14984 	  recycling_mutex = AGS_RECYCLING_GET_OBJ_MUTEX(recycling);
14985 
14986 	  /* replace template audio signal */
14987 	  AGS_AUDIO_SIGNAL(audio_signal->data)->flags |= AGS_AUDIO_SIGNAL_TEMPLATE;
14988 	  g_object_set(AGS_AUDIO_SIGNAL(audio_signal->data),
14989 		       "recycling", recycling,
14990 		       NULL);
14991 
14992 	  ags_recycling_add_audio_signal(recycling,
14993 					 audio_signal->data);
14994 
14995 	  /* iterate */
14996 	  audio_signal = audio_signal->next;
14997 
14998 	  next = ags_channel_next(channel);
14999 
15000 	  if(channel != NULL){
15001 	    g_object_unref(channel);
15002 	  }
15003 
15004 	  channel = next;
15005 	}
15006 
15007 	if(audio_file->file_audio_channels < audio_channels){
15008 	  AgsChannel *nth_channel;
15009 
15010 	  nth_channel = ags_channel_nth(channel,
15011 					audio_channels - audio_file->file_audio_channels);
15012 
15013 	  if(channel != NULL){
15014 	    g_object_unref(channel);
15015 	  }
15016 
15017 	  channel = nth_channel;
15018 	}
15019 
15020 	g_object_run_dispose(audio_file);
15021 	g_object_unref(audio_file);
15022 
15023 	filename = filename->next;
15024       }
15025     }
15026   }
15027 
15028   if(start_input != NULL){
15029     g_object_unref(start_input);
15030   }
15031 
15032   /* appending to channels */
15033   if(create_channels && filename != NULL){
15034     list_length = g_slist_length(filename);
15035 
15036     ags_audio_set_pads((AgsAudio *) audio, AGS_TYPE_INPUT,
15037 		       input_pads + list_length, 0);
15038 
15039     g_object_get(audio,
15040 		 "input-pads", &input_pads,
15041 		 "input", &start_input,
15042 		 NULL);
15043 
15044     channel = ags_channel_nth(start_input,
15045 			      (input_pads - list_length) * AGS_AUDIO(audio)->audio_channels);
15046 
15047     while(filename != NULL){
15048       audio_file = ags_audio_file_new((gchar *) filename->data,
15049 				      soundcard,
15050 				      -1);
15051 
15052       if(!ags_audio_file_open(audio_file)){
15053 	filename = filename->next;
15054 	continue;
15055       }
15056 
15057       ags_audio_file_read_audio_signal(audio_file);
15058       ags_audio_file_close(audio_file);
15059 
15060       audio_signal = audio_file->audio_signal;
15061 
15062       for(j = 0; j < audio_channels && audio_signal != NULL; j++){
15063 	AgsChannel *next;
15064 	AgsRecycling *recycling;
15065 
15066 	AgsFileLink *file_link;
15067 
15068 	/* get recycling */
15069 	recycling = NULL;
15070 
15071 	file_link = NULL;
15072 
15073 	g_object_get(channel,
15074 		     "first-recycling", &recycling,
15075 		     "file-link", &file_link,
15076 		     NULL);
15077 
15078 	/* set filename and channel */
15079 	if(file_link == NULL){
15080 	  file_link = g_object_new(AGS_TYPE_AUDIO_FILE_LINK,
15081 				   NULL);
15082 
15083 	  g_object_set(channel,
15084 		       "file-link", file_link,
15085 		       NULL);
15086 	}
15087 
15088 	g_object_set(file_link,
15089 		     "filename", filename->data,
15090 		     "audio-channel", j,
15091 		     NULL);
15092 
15093 	g_object_unref(file_link);
15094 
15095 	/* get recycling mutex */
15096 	recycling_mutex = AGS_RECYCLING_GET_OBJ_MUTEX(recycling);
15097 
15098 	/* replace template audio signal */
15099 	g_rec_mutex_lock(recycling_mutex);
15100 
15101 	AGS_AUDIO_SIGNAL(audio_signal->data)->flags |= AGS_AUDIO_SIGNAL_TEMPLATE;
15102 	AGS_AUDIO_SIGNAL(audio_signal->data)->recycling = (GObject *) recycling;
15103 
15104 	ags_recycling_add_audio_signal(recycling,
15105 				       audio_signal->data);
15106 
15107 	g_rec_mutex_unlock(recycling_mutex);
15108 
15109 	/* iterate */
15110 	audio_signal = audio_signal->next;
15111 
15112 	next = ags_channel_next(channel);
15113 
15114 	if(channel != NULL){
15115 	  g_object_unref(channel);
15116 	}
15117 
15118 	channel = next;
15119       }
15120 
15121       if(audio_channels > audio_file->file_audio_channels){
15122 	channel = ags_channel_nth(channel,
15123 				  audio_channels - audio_file->file_audio_channels);
15124 	g_object_unref(channel);
15125       }
15126 
15127       g_object_run_dispose(audio_file);
15128       g_object_unref(audio_file);
15129 
15130       filename = filename->next;
15131     }
15132 
15133     if(start_input != NULL){
15134       g_object_unref(start_input);
15135     }
15136   }
15137 }
15138 
15139 void
ags_audio_open_audio_file_as_wave(AgsAudio * audio,const gchar * filename,gboolean overwrite_channels,gboolean create_channels)15140 ags_audio_open_audio_file_as_wave(AgsAudio *audio,
15141 				  const gchar *filename,
15142 				  gboolean overwrite_channels,
15143 				  gboolean create_channels)
15144 {
15145   AgsChannel *channel;
15146   AgsAudioFile *audio_file;
15147 
15148   GObject *soundcard;
15149 
15150   GList *wave;
15151 
15152   guint audio_channels;
15153 
15154   GError *error;
15155 
15156   GRecMutex *audio_mutex;
15157   GRecMutex *channel_mutex;
15158 
15159   if(!AGS_IS_AUDIO(audio) ||
15160      filename == NULL ||
15161      (!overwrite_channels &&
15162       !create_channels)){
15163     return;
15164   }
15165 
15166   /* get audio mutex */
15167   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
15168 
15169   /* get audio fields */
15170   g_rec_mutex_lock(audio_mutex);
15171 
15172   audio_channels = audio->audio_channels;
15173 
15174   soundcard = audio->output_soundcard;
15175 
15176   g_rec_mutex_unlock(audio_mutex);
15177 
15178   /* open audio file */
15179   audio_file = ags_audio_file_new(filename,
15180 				  soundcard,
15181 				  -1);
15182 
15183   if(!ags_audio_file_open(audio_file)){
15184     return;
15185   }
15186 
15187   ags_audio_file_read_wave(audio_file,
15188 			   0,
15189 			   0.0, 0);
15190   ags_audio_file_close(audio_file);
15191 
15192   //TODO:JK: implement me
15193 }
15194 
15195 void
ags_audio_open_midi_file_as_midi(AgsAudio * audio,const gchar * filename,const gchar * instrument,const gchar * track_name,guint midi_channel)15196 ags_audio_open_midi_file_as_midi(AgsAudio *audio,
15197 				 const gchar *filename,
15198 				 const gchar *instrument,
15199 				 const gchar *track_name,
15200 				 guint midi_channel)
15201 {
15202   //TODO:JK: implement me
15203 }
15204 
15205 void
ags_audio_open_midi_file_as_notation(AgsAudio * audio,const gchar * filename,const gchar * instrument,const gchar * track_name,guint midi_channel)15206 ags_audio_open_midi_file_as_notation(AgsAudio *audio,
15207 				     const gchar *filename,
15208 				     const gchar *instrument,
15209 				     const gchar *track_name,
15210 				     guint midi_channel)
15211 {
15212   //TODO:JK: implement me
15213 }
15214 
15215 void
ags_audio_set_property_all(AgsAudio * audio,gint n_params,const gchar * parameter_name[],const GValue value[])15216 ags_audio_set_property_all(AgsAudio *audio,
15217 			   gint n_params,
15218 			   const gchar *parameter_name[], const GValue value[])
15219 {
15220   guint i;
15221 
15222   for(i = 0; i < n_params; i++){
15223     g_object_set_property(G_OBJECT(audio),
15224 			  parameter_name[i], &(value[i]));
15225   }
15226 }
15227 
15228 void
ags_audio_recursive_set_property_down(AgsChannel * channel,gint n_params,const gchar * parameter_name[],const GValue value[])15229 ags_audio_recursive_set_property_down(AgsChannel *channel,
15230 				      gint n_params,
15231 				      const gchar *parameter_name[], const GValue value[])
15232 {
15233   if(channel == NULL){
15234     return;
15235   }
15236 
15237   ags_audio_set_property_all(AGS_AUDIO(channel->audio),
15238 			     n_params,
15239 			     parameter_name, value);
15240 
15241   ags_audio_recursive_set_property_down_input(channel,
15242 					      n_params,
15243 					      parameter_name, value);
15244 }
15245 
15246 void
ags_audio_recursive_set_property_down_input(AgsChannel * channel,gint n_params,const gchar * parameter_name[],const GValue value[])15247 ags_audio_recursive_set_property_down_input(AgsChannel *channel,
15248 					    gint n_params,
15249 					    const gchar *parameter_name[], const GValue value[])
15250 {
15251   AgsAudio *audio;
15252   AgsChannel *input;
15253 
15254   if(channel == NULL){
15255     return;
15256   }
15257 
15258   audio = (AgsAudio *) channel->audio;
15259 
15260   if(audio == NULL){
15261     return;
15262   }
15263 
15264   input = ags_channel_nth(audio->input,
15265 			  channel->audio_channel);
15266   g_object_unref(input);
15267 
15268   while(input != NULL){
15269     ags_audio_recursive_set_property_down(input->link,
15270 					  n_params,
15271 					  parameter_name, value);
15272 
15273     input = input->next;
15274   }
15275 }
15276 
15277 /**
15278  * ags_audio_recursive_set_property:
15279  * @audio: the #AgsAudio
15280  * @n_params: the count of elements in following arrays
15281  * @parameter_name: the parameter's name array
15282  * @value: the value array
15283  *
15284  * Recursive set property for #AgsAudio.
15285  *
15286  * Since: 3.0.0
15287  */
15288 void
ags_audio_recursive_set_property(AgsAudio * audio,gint n_params,const gchar * parameter_name[],const GValue value[])15289 ags_audio_recursive_set_property(AgsAudio *audio,
15290 				 gint n_params,
15291 				 const gchar *parameter_name[], const GValue value[])
15292 {
15293   AgsChannel *channel;
15294 
15295   if(!AGS_IS_AUDIO(audio)){
15296     return;
15297   }
15298 
15299   ags_audio_set_property_all(audio,
15300 			     n_params,
15301 			     parameter_name, value);
15302 
15303   if(audio->input != NULL){
15304     channel = audio->input;
15305 
15306     while(channel != NULL){
15307       ags_audio_recursive_set_property_down(channel->link,
15308 					    n_params,
15309 					    parameter_name, value);
15310 
15311       channel = channel->next;
15312     }
15313   }
15314 }
15315 
15316 void
ags_audio_real_recursive_run_stage(AgsAudio * audio,gint sound_scope,guint staging_flags)15317 ags_audio_real_recursive_run_stage(AgsAudio *audio,
15318 				   gint sound_scope, guint staging_flags)
15319 {
15320   AgsChannel *channel;
15321 
15322   GRecMutex *audio_mutex;
15323   GRecMutex *channel_mutex;
15324 
15325   /* get audio mutex */
15326   audio_mutex = AGS_AUDIO_GET_OBJ_MUTEX(audio);
15327 
15328   /* get channel */
15329   g_rec_mutex_lock(audio_mutex);
15330 
15331   channel = audio->output;
15332 
15333   g_rec_mutex_unlock(audio_mutex);
15334 
15335   /* initialize return value */
15336   while(channel != NULL){
15337     /* reset recursive channel stage */
15338     ags_channel_recursive_run_stage(channel,
15339 				    sound_scope, staging_flags);
15340 
15341     /* get channel mutex */
15342     channel_mutex = AGS_CHANNEL_GET_OBJ_MUTEX(channel);
15343 
15344     /* iterate */
15345     g_rec_mutex_lock(channel_mutex);
15346 
15347     channel = channel->next;
15348 
15349     g_rec_mutex_unlock(channel_mutex);
15350   }
15351 }
15352 
15353 /**
15354  * ags_audio_recursive_run_stage:
15355  * @audio: the #AgsAudio object
15356  * @sound_scope: the scope to reset
15357  * @staging_flags: the stage to enable
15358  *
15359  * Resets @audio's @sound_scope specified by @staging_flags.
15360  *
15361  * Since: 3.0.0
15362  */
15363 void
ags_audio_recursive_run_stage(AgsAudio * audio,gint sound_scope,guint staging_flags)15364 ags_audio_recursive_run_stage(AgsAudio *audio,
15365 			      gint sound_scope, guint staging_flags)
15366 {
15367   g_return_if_fail(AGS_IS_AUDIO(audio));
15368 
15369   /* emit */
15370   g_object_ref((GObject *) audio);
15371   g_signal_emit(G_OBJECT(audio),
15372 		audio_signals[RECURSIVE_RUN_STAGE], 0,
15373 		sound_scope, staging_flags);
15374   g_object_unref((GObject *) audio);
15375 }
15376 
15377 /**
15378  * ags_audio_new:
15379  * @output_soundcard: the #AgsSoundcard to use for output
15380  *
15381  * Creates an #AgsAudio, with defaults of @output_soundcard.
15382  *
15383  * Returns: a new #AgsAudio
15384  *
15385  * Since: 3.0.0
15386  */
15387 AgsAudio*
ags_audio_new(GObject * output_soundcard)15388 ags_audio_new(GObject *output_soundcard)
15389 {
15390   AgsAudio *audio;
15391 
15392   audio = (AgsAudio *) g_object_new(AGS_TYPE_AUDIO,
15393 				    "output-soundcard", output_soundcard,
15394 				    NULL);
15395 
15396   return(audio);
15397 }
15398