1 /* GSequencer - Advanced GTK Sequencer
2 * Copyright (C) 2005-2020 Joël Krähemann
3 *
4 * This file is part of GSequencer.
5 *
6 * GSequencer is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * GSequencer is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GSequencer. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <ags/audio/file/ags_audio_file.h>
21
22 #include <ags/ags_api_config.h>
23
24 #include <ags/audio/ags_audio_signal.h>
25 #include <ags/audio/ags_wave.h>
26 #include <ags/audio/ags_audio_buffer_util.h>
27
28 #include <ags/audio/file/ags_sound_resource.h>
29 #include <ags/audio/file/ags_sndfile.h>
30
31 #ifdef AGS_WITH_GSTREAMER
32 #include <ags/audio/file/ags_gstreamer_file.h>
33 #endif
34
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <math.h>
38 #include <sndfile.h>
39 #include <string.h>
40
41 #include <ags/i18n.h>
42
43 void ags_audio_file_class_init(AgsAudioFileClass *audio_file);
44 void ags_audio_file_connectable_interface_init(AgsConnectableInterface *connectable);
45 void ags_audio_file_init(AgsAudioFile *audio_file);
46 void ags_audio_file_set_property(GObject *gobject,
47 guint prop_id,
48 const GValue *value,
49 GParamSpec *param_spec);
50 void ags_audio_file_get_property(GObject *gobject,
51 guint prop_id,
52 GValue *value,
53 GParamSpec *param_spec);
54 void ags_audio_file_finalize(GObject *object);
55
56 AgsUUID* ags_audio_file_get_uuid(AgsConnectable *connectable);
57 gboolean ags_audio_file_has_resource(AgsConnectable *connectable);
58 gboolean ags_audio_file_is_ready(AgsConnectable *connectable);
59 void ags_audio_file_add_to_registry(AgsConnectable *connectable);
60 void ags_audio_file_remove_from_registry(AgsConnectable *connectable);
61 xmlNode* ags_audio_file_list_resource(AgsConnectable *connectable);
62 xmlNode* ags_audio_file_xml_compose(AgsConnectable *connectable);
63 void ags_audio_file_xml_parse(AgsConnectable *connectable,
64 xmlNode *node);
65 gboolean ags_audio_file_is_connected(AgsConnectable *connectable);
66 void ags_audio_file_connect(AgsConnectable *connectable);
67 void ags_audio_file_disconnect(AgsConnectable *connectable);
68
69 enum{
70 PROP_0,
71 PROP_SOUNDCARD,
72 PROP_FILENAME,
73 PROP_FILE_AUDIO_CHANNELS,
74 PROP_FILE_SAMPLERATE,
75 PROP_FILE_FRAME_COUNT,
76 PROP_AUDIO_CHANNEL,
77 PROP_SAMPLERATE,
78 PROP_BUFFER_SIZE,
79 PROP_FORMAT,
80 PROP_AUDIO_SIGNAL,
81 PROP_WAVE,
82 };
83
84 enum{
85 READ_BUFFER,
86 LAST_SIGNAL,
87 };
88
89 /**
90 * SECTION:ags_audio_file
91 * @short_description: Audio file input/output
92 * @title: AgsAudioFile
93 * @section_id:
94 * @include: ags/audio/file/ags_audio_file.h
95 *
96 * #AgsAudioFile is the base object to read/write audio data.
97 */
98
99 static gpointer ags_audio_file_parent_class = NULL;
100 static guint signals[LAST_SIGNAL];
101
102 GType
ags_audio_file_get_type()103 ags_audio_file_get_type()
104 {
105 static volatile gsize g_define_type_id__volatile = 0;
106
107 if(g_once_init_enter (&g_define_type_id__volatile)){
108 GType ags_type_audio_file = 0;
109
110 static const GTypeInfo ags_audio_file_info = {
111 sizeof (AgsAudioFileClass),
112 NULL, /* base_init */
113 NULL, /* base_finalize */
114 (GClassInitFunc) ags_audio_file_class_init,
115 NULL, /* class_finalize */
116 NULL, /* class_data */
117 sizeof (AgsAudioFile),
118 0, /* n_preallocs */
119 (GInstanceInitFunc) ags_audio_file_init,
120 };
121
122 static const GInterfaceInfo ags_connectable_interface_info = {
123 (GInterfaceInitFunc) ags_audio_file_connectable_interface_init,
124 NULL, /* interface_finalize */
125 NULL, /* interface_data */
126 };
127
128 ags_type_audio_file = g_type_register_static(G_TYPE_OBJECT,
129 "AgsAudioFile",
130 &ags_audio_file_info,
131 0);
132
133 g_type_add_interface_static(ags_type_audio_file,
134 AGS_TYPE_CONNECTABLE,
135 &ags_connectable_interface_info);
136
137 g_once_init_leave(&g_define_type_id__volatile, ags_type_audio_file);
138 }
139
140 return g_define_type_id__volatile;
141 }
142
143 void
ags_audio_file_class_init(AgsAudioFileClass * audio_file)144 ags_audio_file_class_init(AgsAudioFileClass *audio_file)
145 {
146 GObjectClass *gobject;
147 GParamSpec *param_spec;
148
149 ags_audio_file_parent_class = g_type_class_peek_parent(audio_file);
150
151 gobject = (GObjectClass *) audio_file;
152
153 gobject->set_property = ags_audio_file_set_property;
154 gobject->get_property = ags_audio_file_get_property;
155
156 gobject->finalize = ags_audio_file_finalize;
157
158 /* properties */
159 /**
160 * AgsAudioFile:soundcard:
161 *
162 * The assigned soundcard.
163 *
164 * Since: 3.0.0
165 */
166 param_spec = g_param_spec_object("soundcard",
167 i18n_pspec("soundcard of audio file"),
168 i18n_pspec("The soundcard what audio file has it's presets"),
169 G_TYPE_OBJECT,
170 G_PARAM_READABLE | G_PARAM_WRITABLE);
171 g_object_class_install_property(gobject,
172 PROP_SOUNDCARD,
173 param_spec);
174
175 /**
176 * AgsAudioFile:filename:
177 *
178 * The assigned filename.
179 *
180 * Since: 3.0.0
181 */
182 param_spec = g_param_spec_string("filename",
183 i18n_pspec("filename of audio file"),
184 i18n_pspec("The filename of audio file"),
185 NULL,
186 G_PARAM_READABLE | G_PARAM_WRITABLE);
187 g_object_class_install_property(gobject,
188 PROP_FILENAME,
189 param_spec);
190
191 /**
192 * AgsAudioFile:file-audio-channels:
193 *
194 * The audio channel count of this file.
195 *
196 * Since: 3.0.0
197 */
198 param_spec = g_param_spec_uint("file-audio-channels",
199 i18n_pspec("file audio channels"),
200 i18n_pspec("The audio channel count of the file"),
201 0, G_MAXUINT,
202 0,
203 G_PARAM_READABLE | G_PARAM_WRITABLE);
204 g_object_class_install_property(gobject,
205 PROP_FILE_AUDIO_CHANNELS,
206 param_spec);
207
208 /**
209 * AgsAudioFile:file-samplerate:
210 *
211 * The samplerate of this file.
212 *
213 * Since: 3.0.0
214 */
215 param_spec = g_param_spec_uint("file-samplerate",
216 i18n_pspec("file samplerate"),
217 i18n_pspec("The samplerate of the file"),
218 0, G_MAXUINT,
219 0,
220 G_PARAM_READABLE | G_PARAM_WRITABLE);
221 g_object_class_install_property(gobject,
222 PROP_FILE_SAMPLERATE,
223 param_spec);
224
225 /**
226 * AgsAudioFile:file-frame_count:
227 *
228 * The frame count of this file.
229 *
230 * Since: 3.0.0
231 */
232 param_spec = g_param_spec_uint("file-frame-count",
233 i18n_pspec("file frame count"),
234 i18n_pspec("The frame count of the file"),
235 0, G_MAXUINT,
236 0,
237 G_PARAM_READABLE | G_PARAM_WRITABLE);
238 g_object_class_install_property(gobject,
239 PROP_FILE_FRAME_COUNT,
240 param_spec);
241
242 /**
243 * AgsAudioFile:audio-channel:
244 *
245 * The audio channel to be read.
246 *
247 * Since: 3.0.0
248 */
249 param_spec = g_param_spec_int("audio-channel",
250 i18n_pspec("read audio channel"),
251 i18n_pspec("The audio channel to be read"),
252 -1, G_MAXINT,
253 0,
254 G_PARAM_READABLE | G_PARAM_WRITABLE);
255 g_object_class_install_property(gobject,
256 PROP_AUDIO_CHANNEL,
257 param_spec);
258
259 /**
260 * AgsAudioFile:samplerate:
261 *
262 * The samplerate to be used.
263 *
264 * Since: 3.0.0
265 */
266 param_spec = g_param_spec_uint("samplerate",
267 i18n_pspec("using samplerate"),
268 i18n_pspec("The samplerate to be used"),
269 0,
270 G_MAXUINT,
271 0,
272 G_PARAM_READABLE | G_PARAM_WRITABLE);
273 g_object_class_install_property(gobject,
274 PROP_SAMPLERATE,
275 param_spec);
276
277 /**
278 * AgsAudioFile:buffer-size:
279 *
280 * The buffer size to be used.
281 *
282 * Since: 3.0.0
283 */
284 param_spec = g_param_spec_uint("buffer-size",
285 i18n_pspec("using buffer size"),
286 i18n_pspec("The buffer size to be used"),
287 0,
288 G_MAXUINT,
289 0,
290 G_PARAM_READABLE | G_PARAM_WRITABLE);
291 g_object_class_install_property(gobject,
292 PROP_BUFFER_SIZE,
293 param_spec);
294
295 /**
296 * AgsAudioFile:format:
297 *
298 * The format to be used.
299 *
300 * Since: 3.0.0
301 */
302 param_spec = g_param_spec_uint("format",
303 i18n_pspec("using format"),
304 i18n_pspec("The format to be used"),
305 0,
306 G_MAXUINT,
307 0,
308 G_PARAM_READABLE | G_PARAM_WRITABLE);
309 g_object_class_install_property(gobject,
310 PROP_FORMAT,
311 param_spec);
312
313 /**
314 * AgsAudioFile:audio-signal: (type GList(AgsAudioSignal)) (transfer full)
315 *
316 * The containing #AgsAudioSignal.
317 *
318 * Since: 3.0.0
319 */
320 param_spec = g_param_spec_pointer("audio-signal",
321 i18n_pspec("containing audio signal"),
322 i18n_pspec("The audio signal it contains"),
323 G_PARAM_READABLE | G_PARAM_WRITABLE);
324 g_object_class_install_property(gobject,
325 PROP_AUDIO_SIGNAL,
326 param_spec);
327
328 /**
329 * AgsAudioFile:wave: (type GList(AgsWave)) (transfer full)
330 *
331 * The containing #AgsWave.
332 *
333 * Since: 3.0.0
334 */
335 param_spec = g_param_spec_pointer("wave",
336 i18n_pspec("containing wave"),
337 i18n_pspec("The wave it contains"),
338 G_PARAM_READABLE | G_PARAM_WRITABLE);
339 g_object_class_install_property(gobject,
340 PROP_WAVE,
341 param_spec);
342 }
343
344 void
ags_audio_file_connectable_interface_init(AgsConnectableInterface * connectable)345 ags_audio_file_connectable_interface_init(AgsConnectableInterface *connectable)
346 {
347 connectable->get_uuid = ags_audio_file_get_uuid;
348 connectable->has_resource = ags_audio_file_has_resource;
349 connectable->is_ready = ags_audio_file_is_ready;
350
351 connectable->add_to_registry = ags_audio_file_add_to_registry;
352 connectable->remove_from_registry = ags_audio_file_remove_from_registry;
353
354 connectable->list_resource = ags_audio_file_list_resource;
355 connectable->xml_compose = ags_audio_file_xml_compose;
356 connectable->xml_parse = ags_audio_file_xml_parse;
357
358 connectable->is_connected = ags_audio_file_is_connected;
359
360 connectable->connect = ags_audio_file_connect;
361 connectable->disconnect = ags_audio_file_disconnect;
362
363 connectable->connect_connection = NULL;
364 connectable->disconnect_connection = NULL;
365 }
366
367 void
ags_audio_file_init(AgsAudioFile * audio_file)368 ags_audio_file_init(AgsAudioFile *audio_file)
369 {
370 AgsConfig *config;
371
372 audio_file->flags = 0;
373
374 /* add audio file mutex */
375 g_rec_mutex_init(&(audio_file->obj_mutex));
376
377 /* uuid */
378 audio_file->uuid = ags_uuid_alloc();
379 ags_uuid_generate(audio_file->uuid);
380
381 audio_file->soundcard = NULL;
382
383 audio_file->filename = NULL;
384
385 audio_file->file_audio_channels = 0;
386 audio_file->file_samplerate = 0;
387 audio_file->file_frame_count = 0;
388
389 config = ags_config_get_instance();
390
391 audio_file->samplerate = ags_soundcard_helper_config_get_samplerate(config);
392 audio_file->buffer_size = ags_soundcard_helper_config_get_buffer_size(config);
393 audio_file->format = ags_soundcard_helper_config_get_format(config);
394
395 audio_file->audio_channel = -1;
396
397 audio_file->sound_resource = NULL;
398
399 audio_file->audio_signal = NULL;
400 audio_file->wave = NULL;
401 }
402
403 void
ags_audio_file_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)404 ags_audio_file_set_property(GObject *gobject,
405 guint prop_id,
406 const GValue *value,
407 GParamSpec *param_spec)
408 {
409 AgsAudioFile *audio_file;
410
411 GRecMutex *audio_file_mutex;
412
413 audio_file = AGS_AUDIO_FILE(gobject);
414
415 /* get audio file mutex */
416 audio_file_mutex = AGS_AUDIO_FILE_GET_OBJ_MUTEX(audio_file);
417
418 switch(prop_id){
419 case PROP_SOUNDCARD:
420 {
421 GObject *soundcard;
422
423 soundcard = (GObject *) g_value_get_object(value);
424
425 g_rec_mutex_lock(audio_file_mutex);
426
427 if(soundcard == ((GObject *) audio_file->soundcard)){
428 g_rec_mutex_unlock(audio_file_mutex);
429
430 return;
431 }
432
433 if(audio_file->soundcard != NULL){
434 g_object_unref(audio_file->soundcard);
435 }
436
437 if(soundcard != NULL){
438 g_object_ref(G_OBJECT(soundcard));
439 }
440
441 audio_file->soundcard = (GObject *) soundcard;
442
443 g_rec_mutex_unlock(audio_file_mutex);
444 }
445 break;
446 case PROP_FILENAME:
447 {
448 gchar *filename;
449
450 filename = (gchar *) g_value_get_string(value);
451
452 g_rec_mutex_lock(audio_file_mutex);
453
454 if(audio_file->filename == filename){
455 g_rec_mutex_unlock(audio_file_mutex);
456
457 return;
458 }
459
460 if(audio_file->filename != NULL){
461 g_free(audio_file->filename);
462 }
463
464 audio_file->filename = g_strdup(filename);
465
466 g_rec_mutex_unlock(audio_file_mutex);
467 }
468 break;
469 case PROP_FILE_AUDIO_CHANNELS:
470 {
471 g_rec_mutex_lock(audio_file_mutex);
472
473 audio_file->file_audio_channels = g_value_get_uint(value);
474
475 g_rec_mutex_unlock(audio_file_mutex);
476 }
477 break;
478 case PROP_FILE_SAMPLERATE:
479 {
480 g_rec_mutex_lock(audio_file_mutex);
481
482 audio_file->file_samplerate = g_value_get_uint(value);
483
484 g_rec_mutex_unlock(audio_file_mutex);
485 }
486 break;
487 case PROP_FILE_FRAME_COUNT:
488 {
489 g_rec_mutex_lock(audio_file_mutex);
490
491 audio_file->file_frame_count = g_value_get_uint(value);
492
493 g_rec_mutex_unlock(audio_file_mutex);
494 }
495 break;
496 case PROP_SAMPLERATE:
497 {
498 g_rec_mutex_lock(audio_file_mutex);
499
500 audio_file->samplerate = g_value_get_uint(value);
501
502 g_rec_mutex_unlock(audio_file_mutex);
503 }
504 break;
505 case PROP_BUFFER_SIZE:
506 {
507 g_rec_mutex_lock(audio_file_mutex);
508
509 audio_file->buffer_size = g_value_get_uint(value);
510
511 g_rec_mutex_unlock(audio_file_mutex);
512 }
513 break;
514 case PROP_FORMAT:
515 {
516 g_rec_mutex_lock(audio_file_mutex);
517
518 audio_file->format = g_value_get_uint(value);
519
520 g_rec_mutex_unlock(audio_file_mutex);
521 }
522 break;
523 case PROP_AUDIO_CHANNEL:
524 {
525 g_rec_mutex_lock(audio_file_mutex);
526
527 audio_file->audio_channel = g_value_get_int(value);
528
529 g_rec_mutex_unlock(audio_file_mutex);
530 }
531 break;
532 case PROP_AUDIO_SIGNAL:
533 {
534 AgsAudioSignal *audio_signal;
535
536 audio_signal = (AgsAudioSignal *) g_value_get_pointer(value);
537
538 g_rec_mutex_lock(audio_file_mutex);
539
540 if(audio_signal == NULL ||
541 g_list_find(audio_file->audio_signal, audio_signal) != NULL){
542 g_rec_mutex_unlock(audio_file_mutex);
543
544 return;
545 }
546
547 g_rec_mutex_unlock(audio_file_mutex);
548
549 ags_audio_file_add_audio_signal(audio_file,
550 (GObject *) audio_signal);
551 }
552 break;
553 case PROP_WAVE:
554 {
555 AgsWave *wave;
556
557 wave = (AgsWave *) g_value_get_pointer(value);
558
559 g_rec_mutex_lock(audio_file_mutex);
560
561 if(wave == NULL ||
562 g_list_find(audio_file->wave, wave) != NULL){
563 g_rec_mutex_unlock(audio_file_mutex);
564
565 return;
566 }
567
568 g_rec_mutex_unlock(audio_file_mutex);
569
570 ags_audio_file_add_wave(audio_file,
571 (GObject *) wave);
572 }
573 break;
574 default:
575 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
576 break;
577 }
578 }
579
580 void
ags_audio_file_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)581 ags_audio_file_get_property(GObject *gobject,
582 guint prop_id,
583 GValue *value,
584 GParamSpec *param_spec)
585 {
586 AgsAudioFile *audio_file;
587
588 GRecMutex *audio_file_mutex;
589
590 audio_file = AGS_AUDIO_FILE(gobject);
591
592 /* get audio file mutex */
593 audio_file_mutex = AGS_AUDIO_FILE_GET_OBJ_MUTEX(audio_file);
594
595 switch(prop_id){
596 case PROP_SOUNDCARD:
597 {
598 g_rec_mutex_lock(audio_file_mutex);
599
600 g_value_set_object(value, audio_file->soundcard);
601
602 g_rec_mutex_unlock(audio_file_mutex);
603 }
604 break;
605 case PROP_FILENAME:
606 {
607 g_rec_mutex_lock(audio_file_mutex);
608
609 g_value_set_string(value, audio_file->filename);
610
611 g_rec_mutex_unlock(audio_file_mutex);
612 }
613 break;
614 case PROP_FILE_AUDIO_CHANNELS:
615 {
616 g_rec_mutex_lock(audio_file_mutex);
617
618 g_value_set_uint(value, audio_file->file_audio_channels);
619
620 g_rec_mutex_unlock(audio_file_mutex);
621 }
622 break;
623 case PROP_FILE_SAMPLERATE:
624 {
625 g_rec_mutex_lock(audio_file_mutex);
626
627 g_value_set_uint(value, audio_file->file_samplerate);
628
629 g_rec_mutex_unlock(audio_file_mutex);
630 }
631 break;
632 case PROP_FILE_FRAME_COUNT:
633 {
634 g_rec_mutex_lock(audio_file_mutex);
635
636 g_value_set_uint(value, audio_file->file_frame_count);
637
638 g_rec_mutex_unlock(audio_file_mutex);
639 }
640 break;
641 case PROP_SAMPLERATE:
642 {
643 g_rec_mutex_lock(audio_file_mutex);
644
645 g_value_set_uint(value, audio_file->samplerate);
646
647 g_rec_mutex_unlock(audio_file_mutex);
648 }
649 break;
650 case PROP_BUFFER_SIZE:
651 {
652 g_rec_mutex_lock(audio_file_mutex);
653
654 g_value_set_uint(value, audio_file->buffer_size);
655
656 g_rec_mutex_unlock(audio_file_mutex);
657 }
658 break;
659 case PROP_FORMAT:
660 {
661 g_rec_mutex_lock(audio_file_mutex);
662
663 g_value_set_uint(value, audio_file->format);
664
665 g_rec_mutex_unlock(audio_file_mutex);
666 }
667 break;
668 case PROP_AUDIO_CHANNEL:
669 {
670 g_rec_mutex_lock(audio_file_mutex);
671
672 g_value_set_int(value, audio_file->audio_channel);
673
674 g_rec_mutex_unlock(audio_file_mutex);
675 }
676 break;
677 case PROP_AUDIO_SIGNAL:
678 {
679 g_rec_mutex_lock(audio_file_mutex);
680
681 g_value_set_pointer(value, g_list_copy_deep(audio_file->audio_signal,
682 (GCopyFunc) g_object_ref,
683 NULL));
684
685 g_rec_mutex_unlock(audio_file_mutex);
686 }
687 break;
688 case PROP_WAVE:
689 {
690 g_rec_mutex_lock(audio_file_mutex);
691
692 g_value_set_pointer(value, g_list_copy_deep(audio_file->wave,
693 (GCopyFunc) g_object_ref,
694 NULL));
695
696 g_rec_mutex_unlock(audio_file_mutex);
697 }
698 break;
699 default:
700 G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
701 break;
702 }
703 }
704
705 void
ags_audio_file_finalize(GObject * gobject)706 ags_audio_file_finalize(GObject *gobject)
707 {
708 AgsAudioFile *audio_file;
709
710 audio_file = AGS_AUDIO_FILE(gobject);
711
712 /* sound resource */
713 if(audio_file->sound_resource != NULL){
714 g_object_unref(audio_file->sound_resource);
715 }
716
717 /* AgsAudioSignal */
718 g_list_free_full(audio_file->audio_signal,
719 g_object_unref);
720
721 /* AgsWave */
722 g_list_free_full(audio_file->wave,
723 g_object_unref);
724
725 /* call parent */
726 G_OBJECT_CLASS(ags_audio_file_parent_class)->finalize(gobject);
727 }
728
729 AgsUUID*
ags_audio_file_get_uuid(AgsConnectable * connectable)730 ags_audio_file_get_uuid(AgsConnectable *connectable)
731 {
732 AgsAudioFile *audio_file;
733
734 AgsUUID *ptr;
735
736 GRecMutex *audio_file_mutex;
737
738 audio_file = AGS_AUDIO_FILE(connectable);
739
740 /* get audio file mutex */
741 audio_file_mutex = AGS_AUDIO_FILE_GET_OBJ_MUTEX(audio_file);
742
743 /* get UUID */
744 g_rec_mutex_lock(audio_file_mutex);
745
746 ptr = audio_file->uuid;
747
748 g_rec_mutex_unlock(audio_file_mutex);
749
750 return(ptr);
751 }
752
753 gboolean
ags_audio_file_has_resource(AgsConnectable * connectable)754 ags_audio_file_has_resource(AgsConnectable *connectable)
755 {
756 return(TRUE);
757 }
758
759 gboolean
ags_audio_file_is_ready(AgsConnectable * connectable)760 ags_audio_file_is_ready(AgsConnectable *connectable)
761 {
762 AgsAudioFile *audio_file;
763
764 gboolean is_ready;
765
766 audio_file = AGS_AUDIO_FILE(connectable);
767
768 /* check is ready */
769 is_ready = ags_audio_file_test_flags(audio_file, AGS_AUDIO_FILE_ADDED_TO_REGISTRY);
770
771 return(is_ready);
772 }
773
774 void
ags_audio_file_add_to_registry(AgsConnectable * connectable)775 ags_audio_file_add_to_registry(AgsConnectable *connectable)
776 {
777 AgsAudioFile *audio_file;
778
779 AgsRegistry *registry;
780 AgsRegistryEntry *entry;
781
782 AgsApplicationContext *application_context;
783
784 if(ags_connectable_is_ready(connectable)){
785 return;
786 }
787
788 audio_file = AGS_AUDIO_FILE(connectable);
789
790 ags_audio_file_set_flags(audio_file, AGS_AUDIO_FILE_ADDED_TO_REGISTRY);
791
792 application_context = ags_application_context_get_instance();
793
794 registry = (AgsRegistry *) ags_service_provider_get_registry(AGS_SERVICE_PROVIDER(application_context));
795
796 if(registry != NULL){
797 entry = ags_registry_entry_alloc(registry);
798 g_value_set_object(entry->entry,
799 (gpointer) audio_file);
800 ags_registry_add_entry(registry,
801 entry);
802 }
803 }
804
805 void
ags_audio_file_remove_from_registry(AgsConnectable * connectable)806 ags_audio_file_remove_from_registry(AgsConnectable *connectable)
807 {
808 if(!ags_connectable_is_ready(connectable)){
809 return;
810 }
811
812 //TODO:JK: implement me
813 }
814
815 xmlNode*
ags_audio_file_list_resource(AgsConnectable * connectable)816 ags_audio_file_list_resource(AgsConnectable *connectable)
817 {
818 xmlNode *node;
819
820 node = NULL;
821
822 //TODO:JK: implement me
823
824 return(node);
825 }
826
827 xmlNode*
ags_audio_file_xml_compose(AgsConnectable * connectable)828 ags_audio_file_xml_compose(AgsConnectable *connectable)
829 {
830 xmlNode *node;
831
832 node = NULL;
833
834 //TODO:JK: implement me
835
836 return(node);
837 }
838
839 void
ags_audio_file_xml_parse(AgsConnectable * connectable,xmlNode * node)840 ags_audio_file_xml_parse(AgsConnectable *connectable,
841 xmlNode *node)
842 {
843 //TODO:JK: implement me
844 }
845
846 gboolean
ags_audio_file_is_connected(AgsConnectable * connectable)847 ags_audio_file_is_connected(AgsConnectable *connectable)
848 {
849 AgsAudioFile *audio_file;
850
851 gboolean is_connected;
852
853 audio_file = AGS_AUDIO_FILE(connectable);
854
855 /* check is connected */
856 is_connected = ags_audio_file_test_flags(audio_file, AGS_AUDIO_FILE_CONNECTED);
857
858 return(is_connected);
859 }
860
861 void
ags_audio_file_connect(AgsConnectable * connectable)862 ags_audio_file_connect(AgsConnectable *connectable)
863 {
864 AgsAudioFile *audio_file;
865
866 if(ags_connectable_is_connected(connectable)){
867 return;
868 }
869
870 audio_file = AGS_AUDIO_FILE(connectable);
871
872 ags_audio_file_set_flags(audio_file, AGS_AUDIO_FILE_CONNECTED);
873 }
874
875 void
ags_audio_file_disconnect(AgsConnectable * connectable)876 ags_audio_file_disconnect(AgsConnectable *connectable)
877 {
878 AgsAudioFile *audio_file;
879
880 if(!ags_connectable_is_connected(connectable)){
881 return;
882 }
883
884 audio_file = AGS_AUDIO_FILE(connectable);
885
886 ags_audio_file_unset_flags(audio_file, AGS_AUDIO_FILE_CONNECTED);
887 }
888
889 /**
890 * ags_audio_file_test_flags:
891 * @audio_file: the #AgsAudioFile
892 * @flags: the flags
893 *
894 * Test @flags to be set on @audio_file.
895 *
896 * Returns: %TRUE if flags are set, else %FALSE
897 *
898 * Since: 3.0.0
899 */
900 gboolean
ags_audio_file_test_flags(AgsAudioFile * audio_file,guint flags)901 ags_audio_file_test_flags(AgsAudioFile *audio_file, guint flags)
902 {
903 gboolean retval;
904
905 GRecMutex *audio_file_mutex;
906
907 if(!AGS_IS_AUDIO_FILE(audio_file)){
908 return(FALSE);
909 }
910
911 /* get audio_file mutex */
912 audio_file_mutex = AGS_AUDIO_FILE_GET_OBJ_MUTEX(audio_file);
913
914 /* test */
915 g_rec_mutex_lock(audio_file_mutex);
916
917 retval = (flags & (audio_file->flags)) ? TRUE: FALSE;
918
919 g_rec_mutex_unlock(audio_file_mutex);
920
921 return(retval);
922 }
923
924 /**
925 * ags_audio_file_set_flags:
926 * @audio_file: the #AgsAudioFile
927 * @flags: see #AgsAudioFileFlags-enum
928 *
929 * Enable a feature of @audio_file.
930 *
931 * Since: 3.0.0
932 */
933 void
ags_audio_file_set_flags(AgsAudioFile * audio_file,guint flags)934 ags_audio_file_set_flags(AgsAudioFile *audio_file, guint flags)
935 {
936 GRecMutex *audio_file_mutex;
937
938 if(!AGS_IS_AUDIO_FILE(audio_file)){
939 return;
940 }
941
942 /* get audio_file mutex */
943 audio_file_mutex = AGS_AUDIO_FILE_GET_OBJ_MUTEX(audio_file);
944
945 //TODO:JK: add more?
946
947 /* set flags */
948 g_rec_mutex_lock(audio_file_mutex);
949
950 audio_file->flags |= flags;
951
952 g_rec_mutex_unlock(audio_file_mutex);
953 }
954
955 /**
956 * ags_audio_file_unset_flags:
957 * @audio_file: the #AgsAudioFile
958 * @flags: see #AgsAudioFileFlags-enum
959 *
960 * Disable a feature of @audio_file.
961 *
962 * Since: 3.0.0
963 */
964 void
ags_audio_file_unset_flags(AgsAudioFile * audio_file,guint flags)965 ags_audio_file_unset_flags(AgsAudioFile *audio_file, guint flags)
966 {
967 GRecMutex *audio_file_mutex;
968
969 if(!AGS_IS_AUDIO_FILE(audio_file)){
970 return;
971 }
972
973 /* get audio_file mutex */
974 audio_file_mutex = AGS_AUDIO_FILE_GET_OBJ_MUTEX(audio_file);
975
976 //TODO:JK: add more?
977
978 /* unset flags */
979 g_rec_mutex_lock(audio_file_mutex);
980
981 audio_file->flags &= (~flags);
982
983 g_rec_mutex_unlock(audio_file_mutex);
984 }
985
986 /**
987 * ags_audio_file_check_suffix:
988 * @filename: the filename
989 *
990 * Check suffix.
991 *
992 * Returns: %TRUE if suffix supported, else %FALSE
993 *
994 * Since: 3.0.0
995 */
996 gboolean
ags_audio_file_check_suffix(gchar * filename)997 ags_audio_file_check_suffix(gchar *filename)
998 {
999 if(ags_sndfile_check_suffix(filename)
1000 #ifdef AGS_WITH_GSTREAMER
1001 || ags_gstreamer_file_check_suffix(filename)
1002 #endif
1003 ){
1004
1005 return(TRUE);
1006 }
1007
1008 return(FALSE);
1009 }
1010
1011 /**
1012 * ags_audio_file_add_audio_signal:
1013 * @audio_file: the #AgsAudioFile
1014 * @audio_signal: the #AgsAudioSignal
1015 *
1016 * Add @audio_signal to @audio_file.
1017 *
1018 * Since: 3.0.0
1019 */
1020 void
ags_audio_file_add_audio_signal(AgsAudioFile * audio_file,GObject * audio_signal)1021 ags_audio_file_add_audio_signal(AgsAudioFile *audio_file, GObject *audio_signal)
1022 {
1023 GRecMutex *audio_file_mutex;
1024
1025 if(!AGS_IS_AUDIO_FILE(audio_file) ||
1026 !AGS_IS_AUDIO_SIGNAL(audio_signal)){
1027 return;
1028 }
1029
1030 /* get audio_file mutex */
1031 audio_file_mutex = AGS_AUDIO_FILE_GET_OBJ_MUTEX(audio_file);
1032
1033 /* */
1034 g_rec_mutex_lock(audio_file_mutex);
1035
1036 if(g_list_find(audio_file->audio_signal, audio_signal) == NULL){
1037 g_object_ref(audio_signal);
1038 audio_file->audio_signal = g_list_prepend(audio_file->audio_signal,
1039 audio_signal);
1040 }
1041
1042 g_rec_mutex_unlock(audio_file_mutex);
1043 }
1044
1045 /**
1046 * ags_audio_file_remove_audio_signal:
1047 * @audio_file: the #AgsAudioFile
1048 * @audio_signal: the #AgsAudioSignal
1049 *
1050 * Remove @audio_signal from @audio_file.
1051 *
1052 * Since: 3.0.0
1053 */
1054 void
ags_audio_file_remove_audio_signal(AgsAudioFile * audio_file,GObject * audio_signal)1055 ags_audio_file_remove_audio_signal(AgsAudioFile *audio_file, GObject *audio_signal)
1056 {
1057 GRecMutex *audio_file_mutex;
1058
1059 if(!AGS_IS_AUDIO_FILE(audio_file) ||
1060 !AGS_IS_AUDIO_SIGNAL(audio_signal)){
1061 return;
1062 }
1063
1064 /* get audio_file mutex */
1065 audio_file_mutex = AGS_AUDIO_FILE_GET_OBJ_MUTEX(audio_file);
1066
1067 /* */
1068 g_rec_mutex_lock(audio_file_mutex);
1069
1070 if(g_list_find(audio_file->audio_signal, audio_signal) != NULL){
1071 audio_file->audio_signal = g_list_prepend(audio_file->audio_signal,
1072 audio_signal);
1073 g_object_unref(audio_signal);
1074 }
1075
1076 g_rec_mutex_unlock(audio_file_mutex);
1077 }
1078
1079 /**
1080 * ags_audio_file_add_wave:
1081 * @audio_file: the #AgsAudioFile
1082 * @wave: the #AgsWave
1083 *
1084 * Add @wave to @audio_file.
1085 *
1086 * Since: 3.0.0
1087 */
1088 void
ags_audio_file_add_wave(AgsAudioFile * audio_file,GObject * wave)1089 ags_audio_file_add_wave(AgsAudioFile *audio_file, GObject *wave)
1090 {
1091 GRecMutex *audio_file_mutex;
1092
1093 if(!AGS_IS_AUDIO_FILE(audio_file) ||
1094 !AGS_IS_WAVE(wave)){
1095 return;
1096 }
1097
1098 /* get audio_file mutex */
1099 audio_file_mutex = AGS_AUDIO_FILE_GET_OBJ_MUTEX(audio_file);
1100
1101 /* */
1102 g_rec_mutex_lock(audio_file_mutex);
1103
1104 if(g_list_find(audio_file->wave, wave) == NULL){
1105 g_object_ref(wave);
1106 audio_file->wave = g_list_prepend(audio_file->wave,
1107 wave);
1108 }
1109
1110 g_rec_mutex_unlock(audio_file_mutex);
1111 }
1112
1113 /**
1114 * ags_audio_file_remove_wave:
1115 * @audio_file: the #AgsAudioFile
1116 * @wave: the #AgsWave
1117 *
1118 * Remove @wave from @audio_file.
1119 *
1120 * Since: 3.0.0
1121 */
1122 void
ags_audio_file_remove_wave(AgsAudioFile * audio_file,GObject * wave)1123 ags_audio_file_remove_wave(AgsAudioFile *audio_file, GObject *wave)
1124 {
1125 GRecMutex *audio_file_mutex;
1126
1127 if(!AGS_IS_AUDIO_FILE(audio_file) ||
1128 !AGS_IS_WAVE(wave)){
1129 return;
1130 }
1131
1132 /* get audio_file mutex */
1133 audio_file_mutex = AGS_AUDIO_FILE_GET_OBJ_MUTEX(audio_file);
1134
1135 /* */
1136 g_rec_mutex_lock(audio_file_mutex);
1137
1138 if(g_list_find(audio_file->wave, wave) != NULL){
1139 audio_file->wave = g_list_prepend(audio_file->wave,
1140 wave);
1141 g_object_unref(wave);
1142 }
1143
1144 g_rec_mutex_unlock(audio_file_mutex);
1145 }
1146
1147 /**
1148 * ags_audio_file_open:
1149 * @audio_file: the #AgsAudioFile
1150 *
1151 * Open the #AgsAudioFile in read mode.
1152 *
1153 * Returns: %TRUE on success, otherwise %FALSE
1154 *
1155 * Since: 3.0.0
1156 */
1157 gboolean
ags_audio_file_open(AgsAudioFile * audio_file)1158 ags_audio_file_open(AgsAudioFile *audio_file)
1159 {
1160 GObject *sound_resource;
1161
1162 gchar *filename;
1163 guint file_audio_channels;
1164 guint file_samplerate;
1165 guint file_frame_count;
1166 gboolean retval;
1167
1168 GRecMutex *audio_file_mutex;
1169
1170 if(!AGS_IS_AUDIO_FILE(audio_file)){
1171 return(FALSE);
1172 }
1173
1174 #ifdef AGS_DEBUG
1175 g_message("ags_audio_file_open: %s", audio_file->filename);
1176 #endif
1177
1178 /* get audio_file mutex */
1179 audio_file_mutex = AGS_AUDIO_FILE_GET_OBJ_MUTEX(audio_file);
1180
1181 sound_resource = NULL;
1182
1183 g_object_get(audio_file,
1184 "filename", &filename,
1185 NULL);
1186
1187 retval = FALSE;
1188
1189 if(g_file_test(filename, G_FILE_TEST_EXISTS)){
1190 if(ags_sndfile_check_suffix(filename)){
1191 g_rec_mutex_lock(audio_file_mutex);
1192
1193 sound_resource =
1194 audio_file->sound_resource = (GObject *) ags_sndfile_new();
1195 g_object_ref(audio_file->sound_resource);
1196
1197 g_rec_mutex_unlock(audio_file_mutex);
1198
1199 if(ags_sound_resource_open(AGS_SOUND_RESOURCE(sound_resource),
1200 filename)){
1201 //FIXME:JK: this call should occure just before reading frames because of the new iterate functions of an AgsPlayable
1202 ags_sound_resource_info(AGS_SOUND_RESOURCE(sound_resource),
1203 &file_frame_count,
1204 NULL, NULL);
1205
1206 g_object_set(audio_file,
1207 "file-frame-count", file_frame_count,
1208 NULL);
1209
1210 ags_sound_resource_get_presets(AGS_SOUND_RESOURCE(sound_resource),
1211 &file_audio_channels,
1212 &file_samplerate,
1213 NULL,
1214 NULL);
1215
1216 g_object_set(audio_file,
1217 "file-audio-channels", file_audio_channels,
1218 "file-samplerate", file_samplerate,
1219 NULL);
1220
1221 retval = TRUE;
1222 }
1223 #ifdef AGS_WITH_GSTREAMER
1224 }else if(ags_gstreamer_file_check_suffix(filename)){
1225 g_rec_mutex_lock(audio_file_mutex);
1226
1227 sound_resource =
1228 audio_file->sound_resource = (GObject *) ags_gstreamer_file_new();
1229 g_object_ref(audio_file->sound_resource);
1230
1231 g_rec_mutex_unlock(audio_file_mutex);
1232
1233 if(ags_sound_resource_open(AGS_SOUND_RESOURCE(sound_resource),
1234 filename)){
1235 //FIXME:JK: this call should occure just before reading frames because of the new iterate functions of an AgsPlayable
1236 ags_sound_resource_info(AGS_SOUND_RESOURCE(sound_resource),
1237 &file_frame_count,
1238 NULL, NULL);
1239
1240 g_object_set(audio_file,
1241 "file-frame-count", file_frame_count,
1242 NULL);
1243
1244 ags_sound_resource_get_presets(AGS_SOUND_RESOURCE(sound_resource),
1245 &file_audio_channels,
1246 &file_samplerate,
1247 NULL,
1248 NULL);
1249
1250 g_object_set(audio_file,
1251 "file-audio-channels", file_audio_channels,
1252 "file-samplerate", file_samplerate,
1253 NULL);
1254
1255 retval = TRUE;
1256 }
1257 #endif
1258 }else{
1259 g_message("ags_audio_file_open: unknown file type");
1260 }
1261 }
1262
1263 g_free(filename);
1264
1265 return(retval);
1266 }
1267
1268 /**
1269 * ags_audio_file_rw_open:
1270 * @audio_file: the #AgsAudioFile
1271 * @create: create the file
1272 *
1273 * Open the #AgsAudioFile in read/write mode.
1274 *
1275 * Returns: %TRUE on success, otherwise %FALSE
1276 *
1277 * Since: 3.0.0
1278 */
1279 gboolean
ags_audio_file_rw_open(AgsAudioFile * audio_file,gboolean create)1280 ags_audio_file_rw_open(AgsAudioFile *audio_file,
1281 gboolean create)
1282 {
1283 GObject *sound_resource;
1284
1285 gchar *filename;
1286 guint file_audio_channels;
1287 guint file_samplerate;
1288 gboolean retval;
1289
1290 GRecMutex *audio_file_mutex;
1291
1292 if(!AGS_IS_AUDIO_FILE(audio_file)){
1293 return(FALSE);
1294 }
1295
1296 #ifdef AGS_DEBUG
1297 g_message("ags_audio_file_rw_open: %s", audio_file->filename);
1298 #endif
1299
1300 /* get audio_file mutex */
1301 audio_file_mutex = AGS_AUDIO_FILE_GET_OBJ_MUTEX(audio_file);
1302
1303 sound_resource = NULL;
1304
1305 g_object_get(audio_file,
1306 "filename", &filename,
1307 "file-audio-channels", &file_audio_channels,
1308 "file-samplerate", &file_samplerate,
1309 NULL);
1310
1311 if(!create &&
1312 !g_file_test(filename, G_FILE_TEST_EXISTS)){
1313 g_free(filename);
1314
1315 return(FALSE);
1316 }
1317
1318 retval = FALSE;
1319
1320 if(ags_sndfile_check_suffix(audio_file->filename)){
1321 GError *error;
1322 guint loop_start, loop_end;
1323
1324 /* sound resource */
1325 g_rec_mutex_lock(audio_file_mutex);
1326
1327 sound_resource =
1328 audio_file->sound_resource = (GObject *) ags_sndfile_new();
1329 g_object_ref(audio_file->sound_resource);
1330
1331 g_rec_mutex_unlock(audio_file_mutex);
1332
1333 if(ags_sound_resource_rw_open(AGS_SOUND_RESOURCE(sound_resource),
1334 filename,
1335 file_audio_channels, file_samplerate,
1336 create)){
1337 retval = TRUE;
1338 }
1339 #ifdef AGS_WITH_GSTREAMER
1340 }else if(ags_gstreamer_file_check_suffix(audio_file->filename)){
1341 GError *error;
1342
1343 guint loop_start, loop_end;
1344
1345 /* sound resource */
1346 g_rec_mutex_lock(audio_file_mutex);
1347
1348 sound_resource =
1349 audio_file->sound_resource = (GObject *) ags_gstreamer_file_new();
1350 g_object_ref(audio_file->sound_resource);
1351
1352 g_rec_mutex_unlock(audio_file_mutex);
1353
1354 if(ags_sound_resource_rw_open(AGS_SOUND_RESOURCE(sound_resource),
1355 filename,
1356 file_audio_channels, file_samplerate,
1357 create)){
1358 retval = TRUE;
1359 }
1360 #endif
1361 }else{
1362 g_message("ags_audio_file_open: unknown file type");
1363 }
1364
1365 g_free(filename);
1366
1367 return(retval);
1368 }
1369
1370 /**
1371 * ags_audio_file_open_from_data:
1372 * @audio_file: the #AgsAudioFile
1373 * @data: the audio data
1374 *
1375 * Open #AgsAudioFile using virtual functions.
1376 *
1377 * Returns: %TRUE on success, otherwise %FALSE
1378 *
1379 * Since: 3.0.0
1380 */
1381 gboolean
ags_audio_file_open_from_data(AgsAudioFile * audio_file,gchar * data)1382 ags_audio_file_open_from_data(AgsAudioFile *audio_file, gchar *data)
1383 {
1384 GObject *sound_resource;
1385
1386 gchar *filename;
1387 guint file_audio_channels;
1388 guint file_samplerate;
1389 guint file_frame_count;
1390 gboolean retval;
1391
1392 GRecMutex *audio_file_mutex;
1393 GRecMutex *sound_resource_mutex;
1394
1395 if(!AGS_IS_AUDIO_FILE(audio_file)){
1396 return(FALSE);
1397 }
1398
1399 #ifdef AGS_DEBUG
1400 g_message("ags_audio_file_open_from_data:");
1401 #endif
1402
1403 /* get audio_file mutex */
1404 audio_file_mutex = AGS_AUDIO_FILE_GET_OBJ_MUTEX(audio_file);
1405
1406 sound_resource = NULL;
1407
1408 g_object_get(audio_file,
1409 "filename", &filename,
1410 NULL);
1411
1412 retval = FALSE;
1413
1414 if(data != NULL){
1415 if(ags_sndfile_check_suffix(filename)){
1416 guint loop_start, loop_end;
1417
1418 GError *error;
1419
1420 g_rec_mutex_lock(audio_file_mutex);
1421
1422 sound_resource =
1423 audio_file->sound_resource = (GObject *) ags_sndfile_new();
1424 g_object_ref(audio_file->sound_resource);
1425
1426 g_rec_mutex_unlock(audio_file_mutex);
1427
1428 /* get sndfile mutex */
1429 sound_resource_mutex = AGS_SNDFILE_GET_OBJ_MUTEX(sound_resource);
1430
1431 g_rec_mutex_lock(sound_resource_mutex);
1432
1433 AGS_SNDFILE(sound_resource)->flags = AGS_SNDFILE_VIRTUAL;
1434
1435 g_rec_mutex_unlock(sound_resource_mutex);
1436
1437 if(ags_sound_resource_open(AGS_SOUND_RESOURCE(sound_resource),
1438 filename)){
1439 g_rec_mutex_lock(sound_resource_mutex);
1440
1441 AGS_SNDFILE(sound_resource)->pointer = g_base64_decode(data,
1442 &(AGS_SNDFILE(sound_resource)->length));
1443 AGS_SNDFILE(sound_resource)->current = AGS_SNDFILE(audio_file->sound_resource)->pointer;
1444
1445
1446 g_rec_mutex_unlock(sound_resource_mutex);
1447
1448 ags_sound_resource_info(AGS_SOUND_RESOURCE(sound_resource),
1449 &file_frame_count,
1450 NULL, NULL);
1451
1452 g_object_set(audio_file,
1453 "file-frame-count", file_frame_count,
1454 NULL);
1455
1456 ags_sound_resource_get_presets(AGS_SOUND_RESOURCE(sound_resource),
1457 &file_audio_channels,
1458 &file_samplerate,
1459 NULL,
1460 NULL);
1461
1462 g_object_set(audio_file,
1463 "file-audio-channels", file_audio_channels,
1464 "file-samplerate", file_samplerate,
1465 NULL);
1466
1467 retval = TRUE;
1468 }
1469 #ifdef AGS_WITH_GSTREAMER
1470 }else if(ags_gstreamer_file_check_suffix(filename)){
1471 guint loop_start, loop_end;
1472
1473 GError *error;
1474
1475 g_rec_mutex_lock(audio_file_mutex);
1476
1477 sound_resource =
1478 audio_file->sound_resource = (GObject *) ags_gstreamer_file_new();
1479
1480 g_object_ref(audio_file->sound_resource);
1481
1482 g_rec_mutex_unlock(audio_file_mutex);
1483
1484 //TODO:JK: implement me
1485 #endif
1486 }else{
1487 g_message("ags_audio_file_open: unknown file type");
1488 }
1489 }
1490
1491 g_free(filename);
1492
1493 return(retval);
1494 }
1495
1496 /**
1497 * ags_audio_file_close:
1498 * @audio_file: the #AgsAudioFile
1499 *
1500 * Close the #AgsAudioFile.
1501 *
1502 * Since: 3.0.0
1503 */
1504 void
ags_audio_file_close(AgsAudioFile * audio_file)1505 ags_audio_file_close(AgsAudioFile *audio_file)
1506 {
1507 GObject *sound_resource;
1508
1509 GRecMutex *audio_file_mutex;
1510
1511 if(!AGS_IS_AUDIO_FILE(audio_file)){
1512 return;
1513 }
1514
1515 /* get audio_file mutex */
1516 audio_file_mutex = AGS_AUDIO_FILE_GET_OBJ_MUTEX(audio_file);
1517
1518 /* get sound resource */
1519 g_rec_mutex_lock(audio_file_mutex);
1520
1521 sound_resource = audio_file->sound_resource;
1522
1523 g_rec_mutex_unlock(audio_file_mutex);
1524
1525 /* close */
1526 ags_sound_resource_close(AGS_SOUND_RESOURCE(sound_resource));
1527 }
1528
1529 /**
1530 * ags_audio_file_read:
1531 * @audio_file: the #AgsAudioFile
1532 * @audio_channel: nth channel
1533 * @format: the format
1534 * @error: returned error
1535 *
1536 * Read audio buffer.
1537 *
1538 * Since: 3.0.0
1539 */
1540 void*
ags_audio_file_read(AgsAudioFile * audio_file,guint audio_channel,guint format,GError ** error)1541 ags_audio_file_read(AgsAudioFile *audio_file,
1542 guint audio_channel,
1543 guint format,
1544 GError **error)
1545 {
1546 GObject *sound_resource;
1547
1548 void *buffer;
1549
1550 guint file_frame_count;
1551
1552 GRecMutex *audio_file_mutex;
1553
1554 if(!AGS_IS_AUDIO_FILE(audio_file)){
1555 return(NULL);
1556 }
1557
1558 /* get audio_file mutex */
1559 audio_file_mutex = AGS_AUDIO_FILE_GET_OBJ_MUTEX(audio_file);
1560
1561 /* get sound resource */
1562 g_rec_mutex_lock(audio_file_mutex);
1563
1564 sound_resource = audio_file->sound_resource;
1565
1566 file_frame_count = audio_file->file_frame_count;
1567
1568 g_rec_mutex_unlock(audio_file_mutex);
1569
1570 /* read */
1571 buffer = ags_stream_alloc(file_frame_count,
1572 format);
1573
1574 ags_sound_resource_read(AGS_SOUND_RESOURCE(sound_resource),
1575 buffer, 1,
1576 audio_channel,
1577 file_frame_count, format);
1578
1579 return(buffer);
1580 }
1581
1582 /**
1583 * ags_audio_file_read_audio_signal:
1584 * @audio_file: the #AgsAudioFile
1585 *
1586 * Convert the #AgsAudioFile to a #GList-struct of #AgsAudioSignal.
1587 *
1588 * Since: 3.0.0
1589 */
1590 void
ags_audio_file_read_audio_signal(AgsAudioFile * audio_file)1591 ags_audio_file_read_audio_signal(AgsAudioFile *audio_file)
1592 {
1593 GObject *sound_resource;
1594 GObject *soundcard;
1595
1596 GList *list;
1597
1598 guint audio_channel;
1599
1600 GRecMutex *audio_file_mutex;
1601
1602 if(!AGS_IS_AUDIO_FILE(audio_file)){
1603 return;
1604 }
1605
1606 /* get audio_file mutex */
1607 audio_file_mutex = AGS_AUDIO_FILE_GET_OBJ_MUTEX(audio_file);
1608
1609 /* get sound resource */
1610 g_rec_mutex_lock(audio_file_mutex);
1611
1612 sound_resource = audio_file->sound_resource;
1613 soundcard = audio_file->soundcard;
1614
1615 audio_channel = audio_file->audio_channel;
1616
1617 g_rec_mutex_unlock(audio_file_mutex);
1618
1619 /* read audio signal */
1620 list = ags_sound_resource_read_audio_signal(AGS_SOUND_RESOURCE(sound_resource),
1621 soundcard,
1622 audio_channel);
1623
1624 /* set audio signal */
1625 g_rec_mutex_lock(audio_file_mutex);
1626
1627 audio_file->audio_signal = list;
1628
1629 g_rec_mutex_unlock(audio_file_mutex);
1630 }
1631
1632 /**
1633 * ags_audio_file_read_wave:
1634 * @audio_file: the #AgsAudioFile
1635 * @x_offset: the x offset
1636 * @delay: the delay
1637 * @attack: the attack
1638 *
1639 * Convert the #AgsAudioFile to a #GList-struct of buffers.
1640 *
1641 * Since: 3.0.0
1642 */
1643 void
ags_audio_file_read_wave(AgsAudioFile * audio_file,guint64 x_offset,gdouble delay,guint attack)1644 ags_audio_file_read_wave(AgsAudioFile *audio_file,
1645 guint64 x_offset,
1646 gdouble delay, guint attack)
1647 {
1648 GObject *sound_resource;
1649 GObject *soundcard;
1650
1651 GList *list;
1652
1653 guint audio_channel;
1654
1655 GRecMutex *audio_file_mutex;
1656
1657 if(!AGS_IS_AUDIO_FILE(audio_file)){
1658 return;
1659 }
1660
1661 /* get audio_file mutex */
1662 audio_file_mutex = AGS_AUDIO_FILE_GET_OBJ_MUTEX(audio_file);
1663
1664 /* get sound resource */
1665 g_rec_mutex_lock(audio_file_mutex);
1666
1667 sound_resource = audio_file->sound_resource;
1668 soundcard = audio_file->soundcard;
1669
1670 audio_channel = audio_file->audio_channel;
1671
1672 g_rec_mutex_unlock(audio_file_mutex);
1673
1674 /* read wave */
1675 list = ags_sound_resource_read_wave(AGS_SOUND_RESOURCE(sound_resource),
1676 soundcard,
1677 audio_channel,
1678 x_offset,
1679 delay, attack);
1680
1681 /* set wave */
1682 g_rec_mutex_lock(audio_file_mutex);
1683
1684 audio_file->wave = list;
1685
1686 g_rec_mutex_unlock(audio_file_mutex);
1687 }
1688
1689 /**
1690 * ags_audio_file_seek:
1691 * @audio_file: the #AgsAudioFile
1692 * @frames: number of frames to seek
1693 * @whence: SEEK_SET, SEEK_CUR, or SEEK_END
1694 *
1695 * Position the #AgsAudioFile's internal data address.
1696 *
1697 * Since: 3.0.0
1698 */
1699 void
ags_audio_file_seek(AgsAudioFile * audio_file,guint frames,gint whence)1700 ags_audio_file_seek(AgsAudioFile *audio_file, guint frames, gint whence)
1701 {
1702 GObject *sound_resource;
1703
1704 GRecMutex *audio_file_mutex;
1705
1706 if(!AGS_IS_AUDIO_FILE(audio_file)){
1707 return;
1708 }
1709
1710 /* get audio_file mutex */
1711 audio_file_mutex = AGS_AUDIO_FILE_GET_OBJ_MUTEX(audio_file);
1712
1713 /* get sound resource */
1714 g_rec_mutex_lock(audio_file_mutex);
1715
1716 sound_resource = audio_file->sound_resource;
1717
1718 g_rec_mutex_unlock(audio_file_mutex);
1719
1720 /* seek */
1721 ags_sound_resource_seek(AGS_SOUND_RESOURCE(sound_resource),
1722 frames, whence);
1723 }
1724
1725 /**
1726 * ags_audio_file_write:
1727 * @audio_file: the #AgsAudioFile
1728 * @buffer: the audio data
1729 * @buffer_size: the count of frames to write
1730 * @format: the format
1731 *
1732 * Write the buffer to #AgsAudioFile.
1733 *
1734 * Since: 3.0.0
1735 */
1736 void
ags_audio_file_write(AgsAudioFile * audio_file,void * buffer,guint buffer_size,guint format)1737 ags_audio_file_write(AgsAudioFile *audio_file,
1738 void *buffer,
1739 guint buffer_size, guint format)
1740 {
1741 GObject *sound_resource;
1742
1743 guint file_audio_channels;
1744 gint audio_channel;
1745 guint i;
1746
1747 GRecMutex *audio_file_mutex;
1748
1749 if(!AGS_IS_AUDIO_FILE(audio_file) ||
1750 buffer == NULL){
1751 return;
1752 }
1753
1754 /* get audio_file mutex */
1755 audio_file_mutex = AGS_AUDIO_FILE_GET_OBJ_MUTEX(audio_file);
1756
1757 /* get sound resource */
1758 g_rec_mutex_lock(audio_file_mutex);
1759
1760 sound_resource = audio_file->sound_resource;
1761
1762 file_audio_channels = audio_file->file_audio_channels;
1763 audio_channel = audio_file->audio_channel;
1764
1765 g_rec_mutex_unlock(audio_file_mutex);
1766
1767 if(audio_channel == -1){
1768 for(i = 0; i < file_audio_channels; i++){
1769 ags_sound_resource_write(AGS_SOUND_RESOURCE(sound_resource),
1770 buffer, file_audio_channels,
1771 i,
1772 buffer_size, format);
1773 }
1774 }else{
1775 ags_sound_resource_write(AGS_SOUND_RESOURCE(sound_resource),
1776 buffer, 1,
1777 audio_channel,
1778 buffer_size, format);
1779 }
1780 }
1781
1782 /**
1783 * ags_audio_file_flush:
1784 * @audio_file: the #AgsAudioFile
1785 *
1786 * Flushes the #AgsAudioFile's internal buffer.
1787 *
1788 * Since: 3.0.0
1789 */
1790 void
ags_audio_file_flush(AgsAudioFile * audio_file)1791 ags_audio_file_flush(AgsAudioFile *audio_file)
1792 {
1793 GObject *sound_resource;
1794
1795 GRecMutex *audio_file_mutex;
1796
1797 if(!AGS_IS_AUDIO_FILE(audio_file)){
1798 return;
1799 }
1800
1801 /* get audio_file mutex */
1802 audio_file_mutex = AGS_AUDIO_FILE_GET_OBJ_MUTEX(audio_file);
1803
1804 /* get sound resource */
1805 g_rec_mutex_lock(audio_file_mutex);
1806
1807 sound_resource = audio_file->sound_resource;
1808
1809 g_rec_mutex_unlock(audio_file_mutex);
1810
1811 /* flush */
1812 ags_sound_resource_flush(AGS_SOUND_RESOURCE(sound_resource));
1813 }
1814
1815 /**
1816 * ags_audio_file_new:
1817 * @filename: the filename
1818 * @soundcard: defaults of #AgsSoundcard
1819 * @audio_channel: the audio channel to read
1820 *
1821 * Create a new instance of #AgsAudioFile.
1822 *
1823 * Returns: the new #AgsAudioFile.
1824 *
1825 * Since: 3.0.0
1826 */
1827 AgsAudioFile*
ags_audio_file_new(gchar * filename,GObject * soundcard,gint audio_channel)1828 ags_audio_file_new(gchar *filename,
1829 GObject *soundcard,
1830 gint audio_channel)
1831 {
1832 AgsAudioFile *audio_file;
1833
1834 audio_file = (AgsAudioFile *) g_object_new(AGS_TYPE_AUDIO_FILE,
1835 "filename", filename,
1836 "soundcard", soundcard,
1837 "audio-channel", audio_channel,
1838 NULL);
1839
1840 return(audio_file);
1841 }
1842