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