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", ¬ation,
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