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/core-audio/ags_core_audio_devin.h>
21 
22 #include <ags/audio/ags_sound_provider.h>
23 #include <ags/audio/ags_soundcard_util.h>
24 #include <ags/audio/ags_audio_buffer_util.h>
25 
26 #include <ags/audio/core-audio/ags_core_audio_server.h>
27 #include <ags/audio/core-audio/ags_core_audio_client.h>
28 #include <ags/audio/core-audio/ags_core_audio_port.h>
29 
30 #include <ags/audio/task/ags_tic_device.h>
31 #include <ags/audio/task/ags_clear_buffer.h>
32 #include <ags/audio/task/ags_switch_buffer_flag.h>
33 
34 #include <ags/audio/thread/ags_audio_loop.h>
35 
36 #include <string.h>
37 #include <math.h>
38 #include <time.h>
39 
40 #include <ags/config.h>
41 #include <ags/i18n.h>
42 
43 void ags_core_audio_devin_class_init(AgsCoreAudioDevinClass *core_audio_devin);
44 void ags_core_audio_devin_connectable_interface_init(AgsConnectableInterface *connectable);
45 void ags_core_audio_devin_soundcard_interface_init(AgsSoundcardInterface *soundcard);
46 void ags_core_audio_devin_init(AgsCoreAudioDevin *core_audio_devin);
47 void ags_core_audio_devin_set_property(GObject *gobject,
48 				       guint prop_id,
49 				       const GValue *value,
50 				       GParamSpec *param_spec);
51 void ags_core_audio_devin_get_property(GObject *gobject,
52 				       guint prop_id,
53 				       GValue *value,
54 				       GParamSpec *param_spec);
55 void ags_core_audio_devin_dispose(GObject *gobject);
56 void ags_core_audio_devin_finalize(GObject *gobject);
57 
58 AgsUUID* ags_core_audio_devin_get_uuid(AgsConnectable *connectable);
59 gboolean ags_core_audio_devin_has_resource(AgsConnectable *connectable);
60 gboolean ags_core_audio_devin_is_ready(AgsConnectable *connectable);
61 void ags_core_audio_devin_add_to_registry(AgsConnectable *connectable);
62 void ags_core_audio_devin_remove_from_registry(AgsConnectable *connectable);
63 xmlNode* ags_core_audio_devin_list_resource(AgsConnectable *connectable);
64 xmlNode* ags_core_audio_devin_xml_compose(AgsConnectable *connectable);
65 void ags_core_audio_devin_xml_parse(AgsConnectable *connectable,
66 				    xmlNode *node);
67 gboolean ags_core_audio_devin_is_connected(AgsConnectable *connectable);
68 void ags_core_audio_devin_connect(AgsConnectable *connectable);
69 void ags_core_audio_devin_disconnect(AgsConnectable *connectable);
70 
71 void ags_core_audio_devin_set_device(AgsSoundcard *soundcard,
72 				     gchar *device);
73 gchar* ags_core_audio_devin_get_device(AgsSoundcard *soundcard);
74 
75 void ags_core_audio_devin_set_presets(AgsSoundcard *soundcard,
76 				      guint channels,
77 				      guint rate,
78 				      guint buffer_size,
79 				      guint format);
80 void ags_core_audio_devin_get_presets(AgsSoundcard *soundcard,
81 				      guint *channels,
82 				      guint *rate,
83 				      guint *buffer_size,
84 				      guint *format);
85 
86 void ags_core_audio_devin_list_cards(AgsSoundcard *soundcard,
87 				     GList **card_id, GList **card_name);
88 void ags_core_audio_devin_pcm_info(AgsSoundcard *soundcard, gchar *card_id,
89 				   guint *channels_min, guint *channels_max,
90 				   guint *rate_min, guint *rate_max,
91 				   guint *buffer_size_min, guint *buffer_size_max,
92 				   GError **error);
93 guint ags_core_audio_devin_get_capability(AgsSoundcard *soundcard);
94 
95 gboolean ags_core_audio_devin_is_starting(AgsSoundcard *soundcard);
96 gboolean ags_core_audio_devin_is_recording(AgsSoundcard *soundcard);
97 
98 gchar* ags_core_audio_devin_get_uptime(AgsSoundcard *soundcard);
99 
100 void ags_core_audio_devin_port_init(AgsSoundcard *soundcard,
101 				    GError **error);
102 void ags_core_audio_devin_port_record(AgsSoundcard *soundcard,
103 				      GError **error);
104 void ags_core_audio_devin_port_free(AgsSoundcard *soundcard);
105 
106 void ags_core_audio_devin_tic(AgsSoundcard *soundcard);
107 void ags_core_audio_devin_offset_changed(AgsSoundcard *soundcard,
108 					 guint note_offset);
109 
110 void ags_core_audio_devin_set_bpm(AgsSoundcard *soundcard,
111 				  gdouble bpm);
112 gdouble ags_core_audio_devin_get_bpm(AgsSoundcard *soundcard);
113 
114 void ags_core_audio_devin_set_delay_factor(AgsSoundcard *soundcard,
115 					   gdouble delay_factor);
116 gdouble ags_core_audio_devin_get_delay_factor(AgsSoundcard *soundcard);
117 
118 gdouble ags_core_audio_devin_get_absolute_delay(AgsSoundcard *soundcard);
119 
120 gdouble ags_core_audio_devin_get_delay(AgsSoundcard *soundcard);
121 guint ags_core_audio_devin_get_attack(AgsSoundcard *soundcard);
122 
123 void* ags_core_audio_devin_get_buffer(AgsSoundcard *soundcard);
124 void* ags_core_audio_devin_get_next_buffer(AgsSoundcard *soundcard);
125 void* ags_core_audio_devin_get_prev_buffer(AgsSoundcard *soundcard);
126 
127 void ags_core_audio_devin_lock_buffer(AgsSoundcard *soundcard,
128 				      void *buffer);
129 void ags_core_audio_devin_unlock_buffer(AgsSoundcard *soundcard,
130 					void *buffer);
131 
132 guint ags_core_audio_devin_get_delay_counter(AgsSoundcard *soundcard);
133 
134 void ags_core_audio_devin_set_start_note_offset(AgsSoundcard *soundcard,
135 						guint start_note_offset);
136 guint ags_core_audio_devin_get_start_note_offset(AgsSoundcard *soundcard);
137 
138 void ags_core_audio_devin_set_note_offset(AgsSoundcard *soundcard,
139 					  guint note_offset);
140 guint ags_core_audio_devin_get_note_offset(AgsSoundcard *soundcard);
141 
142 void ags_core_audio_devin_set_note_offset_absolute(AgsSoundcard *soundcard,
143 						   guint note_offset);
144 guint ags_core_audio_devin_get_note_offset_absolute(AgsSoundcard *soundcard);
145 
146 void ags_core_audio_devin_set_loop(AgsSoundcard *soundcard,
147 				   guint loop_left, guint loop_right,
148 				   gboolean do_loop);
149 void ags_core_audio_devin_get_loop(AgsSoundcard *soundcard,
150 				   guint *loop_left, guint *loop_right,
151 				   gboolean *do_loop);
152 
153 guint ags_core_audio_devin_get_loop_offset(AgsSoundcard *soundcard);
154 
155 /**
156  * SECTION:ags_core_audio_devin
157  * @short_description: Output to soundcard
158  * @title: AgsCoreAudioDevin
159  * @section_id:
160  * @include: ags/audio/core-audio/ags_core_audio_devin.h
161  *
162  * #AgsCoreAudioDevin represents a soundcard and supports output.
163  */
164 
165 enum{
166   PROP_0,
167   PROP_DEVICE,
168   PROP_DSP_CHANNELS,
169   PROP_PCM_CHANNELS,
170   PROP_FORMAT,
171   PROP_BUFFER_SIZE,
172   PROP_SAMPLERATE,
173   PROP_BUFFER,
174   PROP_BPM,
175   PROP_DELAY_FACTOR,
176   PROP_ATTACK,
177   PROP_CORE_AUDIO_CLIENT,
178   PROP_CORE_AUDIO_PORT,
179   PROP_CHANNEL,
180 };
181 
182 static gpointer ags_core_audio_devin_parent_class = NULL;
183 
184 GType
ags_core_audio_devin_get_type(void)185 ags_core_audio_devin_get_type (void)
186 {
187   static volatile gsize g_define_type_id__volatile = 0;
188 
189   if(g_once_init_enter (&g_define_type_id__volatile)){
190     GType ags_type_core_audio_devin = 0;
191 
192     static const GTypeInfo ags_core_audio_devin_info = {
193       sizeof(AgsCoreAudioDevinClass),
194       NULL, /* base_init */
195       NULL, /* base_finalize */
196       (GClassInitFunc) ags_core_audio_devin_class_init,
197       NULL, /* class_finalize */
198       NULL, /* class_data */
199       sizeof(AgsCoreAudioDevin),
200       0,    /* n_preallocs */
201       (GInstanceInitFunc) ags_core_audio_devin_init,
202     };
203 
204     static const GInterfaceInfo ags_connectable_interface_info = {
205       (GInterfaceInitFunc) ags_core_audio_devin_connectable_interface_init,
206       NULL, /* interface_finalize */
207       NULL, /* interface_data */
208     };
209 
210     static const GInterfaceInfo ags_soundcard_interface_info = {
211       (GInterfaceInitFunc) ags_core_audio_devin_soundcard_interface_init,
212       NULL, /* interface_finalize */
213       NULL, /* interface_data */
214     };
215 
216     ags_type_core_audio_devin = g_type_register_static(G_TYPE_OBJECT,
217 						       "AgsCoreAudioDevin",
218 						       &ags_core_audio_devin_info,
219 						       0);
220 
221     g_type_add_interface_static(ags_type_core_audio_devin,
222 				AGS_TYPE_CONNECTABLE,
223 				&ags_connectable_interface_info);
224 
225     g_type_add_interface_static(ags_type_core_audio_devin,
226 				AGS_TYPE_SOUNDCARD,
227 				&ags_soundcard_interface_info);
228 
229     g_once_init_leave(&g_define_type_id__volatile, ags_type_core_audio_devin);
230   }
231 
232   return g_define_type_id__volatile;
233 }
234 
235 void
ags_core_audio_devin_class_init(AgsCoreAudioDevinClass * core_audio_devin)236 ags_core_audio_devin_class_init(AgsCoreAudioDevinClass *core_audio_devin)
237 {
238   GObjectClass *gobject;
239   GParamSpec *param_spec;
240 
241   ags_core_audio_devin_parent_class = g_type_class_peek_parent(core_audio_devin);
242 
243   /* GObjectClass */
244   gobject = (GObjectClass *) core_audio_devin;
245 
246   gobject->set_property = ags_core_audio_devin_set_property;
247   gobject->get_property = ags_core_audio_devin_get_property;
248 
249   gobject->dispose = ags_core_audio_devin_dispose;
250   gobject->finalize = ags_core_audio_devin_finalize;
251 
252   /* properties */
253   /**
254    * AgsCoreAudioDevin:device:
255    *
256    * The core audio soundcard indentifier
257    *
258    * Since: 3.0.0
259    */
260   param_spec = g_param_spec_string("device",
261 				   i18n_pspec("the device identifier"),
262 				   i18n_pspec("The device to perform output to"),
263 				   "ags-core-audio-devin-0",
264 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
265   g_object_class_install_property(gobject,
266 				  PROP_DEVICE,
267 				  param_spec);
268 
269   /**
270    * AgsCoreAudioDevin:dsp-channels:
271    *
272    * The dsp channel count
273    *
274    * Since: 3.0.0
275    */
276   param_spec = g_param_spec_uint("dsp-channels",
277 				 i18n_pspec("count of DSP channels"),
278 				 i18n_pspec("The count of DSP channels to use"),
279 				 1,
280 				 64,
281 				 2,
282 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
283   g_object_class_install_property(gobject,
284 				  PROP_DSP_CHANNELS,
285 				  param_spec);
286 
287   /**
288    * AgsCoreAudioDevin:pcm-channels:
289    *
290    * The pcm channel count
291    *
292    * Since: 3.0.0
293    */
294   param_spec = g_param_spec_uint("pcm-channels",
295 				 i18n_pspec("count of PCM channels"),
296 				 i18n_pspec("The count of PCM channels to use"),
297 				 1,
298 				 64,
299 				 2,
300 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
301   g_object_class_install_property(gobject,
302 				  PROP_PCM_CHANNELS,
303 				  param_spec);
304 
305   /**
306    * AgsCoreAudioDevin:format:
307    *
308    * The precision of the buffer
309    *
310    * Since: 3.0.0
311    */
312   param_spec = g_param_spec_uint("format",
313 				 i18n_pspec("precision of buffer"),
314 				 i18n_pspec("The precision to use for a frame"),
315 				 1,
316 				 64,
317 				 AGS_SOUNDCARD_DEFAULT_FORMAT,
318 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
319   g_object_class_install_property(gobject,
320 				  PROP_FORMAT,
321 				  param_spec);
322 
323   /**
324    * AgsCoreAudioDevin:buffer-size:
325    *
326    * The buffer size
327    *
328    * Since: 3.0.0
329    */
330   param_spec = g_param_spec_uint("buffer-size",
331 				 i18n_pspec("frame count of a buffer"),
332 				 i18n_pspec("The count of frames a buffer contains"),
333 				 1,
334 				 44100,
335 				 940,
336 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
337   g_object_class_install_property(gobject,
338 				  PROP_BUFFER_SIZE,
339 				  param_spec);
340 
341   /**
342    * AgsCoreAudioDevin:samplerate:
343    *
344    * The samplerate
345    *
346    * Since: 3.0.0
347    */
348   param_spec = g_param_spec_uint("samplerate",
349 				 i18n_pspec("frames per second"),
350 				 i18n_pspec("The frames count played during a second"),
351 				 8000,
352 				 96000,
353 				 44100,
354 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
355   g_object_class_install_property(gobject,
356 				  PROP_SAMPLERATE,
357 				  param_spec);
358 
359   /**
360    * AgsCoreAudioDevin:buffer:
361    *
362    * The buffer
363    *
364    * Since: 3.0.0
365    */
366   param_spec = g_param_spec_pointer("buffer",
367 				    i18n_pspec("the buffer"),
368 				    i18n_pspec("The buffer to play"),
369 				    G_PARAM_READABLE);
370   g_object_class_install_property(gobject,
371 				  PROP_BUFFER,
372 				  param_spec);
373 
374   /**
375    * AgsCoreAudioDevin:bpm:
376    *
377    * Beats per minute
378    *
379    * Since: 3.0.0
380    */
381   param_spec = g_param_spec_double("bpm",
382 				   i18n_pspec("beats per minute"),
383 				   i18n_pspec("Beats per minute to use"),
384 				   1.0,
385 				   240.0,
386 				   120.0,
387 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
388   g_object_class_install_property(gobject,
389 				  PROP_BPM,
390 				  param_spec);
391 
392   /**
393    * AgsCoreAudioDevin:delay-factor:
394    *
395    * tact
396    *
397    * Since: 3.0.0
398    */
399   param_spec = g_param_spec_double("delay-factor",
400 				   i18n_pspec("delay factor"),
401 				   i18n_pspec("The delay factor"),
402 				   0.0,
403 				   16.0,
404 				   1.0,
405 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
406   g_object_class_install_property(gobject,
407 				  PROP_DELAY_FACTOR,
408 				  param_spec);
409 
410   /**
411    * AgsCoreAudioDevin:attack:
412    *
413    * Attack of the buffer
414    *
415    * Since: 3.0.0
416    */
417   param_spec = g_param_spec_pointer("attack",
418 				    i18n_pspec("attack of buffer"),
419 				    i18n_pspec("The attack to use for the buffer"),
420 				    G_PARAM_READABLE);
421   g_object_class_install_property(gobject,
422 				  PROP_ATTACK,
423 				  param_spec);
424 
425 
426   /**
427    * AgsCoreAudioDevin:core-audio-client:
428    *
429    * The assigned #AgsCoreAudioClient
430    *
431    * Since: 3.0.0
432    */
433   param_spec = g_param_spec_object("core-audio-client",
434 				   i18n_pspec("core audio client object"),
435 				   i18n_pspec("The core audio client object"),
436 				   AGS_TYPE_CORE_AUDIO_CLIENT,
437 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
438   g_object_class_install_property(gobject,
439 				  PROP_CORE_AUDIO_CLIENT,
440 				  param_spec);
441 
442   /**
443    * AgsCoreAudioDevin:core-audio-port:
444    *
445    * The assigned #AgsCoreAudioPort
446    *
447    * Since: 3.0.0
448    */
449   param_spec = g_param_spec_pointer("core-audio-port",
450 				    i18n_pspec("core audio port object"),
451 				    i18n_pspec("The core audio port object"),
452 				    G_PARAM_READABLE | G_PARAM_WRITABLE);
453   g_object_class_install_property(gobject,
454 				  PROP_CORE_AUDIO_PORT,
455 				  param_spec);
456 }
457 
458 GQuark
ags_core_audio_devin_error_quark()459 ags_core_audio_devin_error_quark()
460 {
461   return(g_quark_from_static_string("ags-core_audio_devin-error-quark"));
462 }
463 
464 void
ags_core_audio_devin_connectable_interface_init(AgsConnectableInterface * connectable)465 ags_core_audio_devin_connectable_interface_init(AgsConnectableInterface *connectable)
466 {
467   //TODO:JK: implement me
468 }
469 
470 void
ags_core_audio_devin_soundcard_interface_init(AgsSoundcardInterface * soundcard)471 ags_core_audio_devin_soundcard_interface_init(AgsSoundcardInterface *soundcard)
472 {
473   soundcard->set_device = ags_core_audio_devin_set_device;
474   soundcard->get_device = ags_core_audio_devin_get_device;
475 
476   soundcard->set_presets = ags_core_audio_devin_set_presets;
477   soundcard->get_presets = ags_core_audio_devin_get_presets;
478 
479   soundcard->list_cards = ags_core_audio_devin_list_cards;
480   soundcard->pcm_info = ags_core_audio_devin_pcm_info;
481   soundcard->get_capability = ags_core_audio_devin_get_capability;
482 
483   soundcard->is_available = NULL;
484 
485   soundcard->is_starting =  ags_core_audio_devin_is_starting;
486   soundcard->is_playing = NULL;
487   soundcard->is_recording = ags_core_audio_devin_is_recording;
488 
489   soundcard->get_uptime = ags_core_audio_devin_get_uptime;
490 
491   soundcard->play_init = NULL;
492   soundcard->play = NULL;
493 
494   soundcard->record_init = ags_core_audio_devin_port_init;
495   soundcard->record = ags_core_audio_devin_port_record;
496 
497   soundcard->stop = ags_core_audio_devin_port_free;
498 
499   soundcard->tic = ags_core_audio_devin_tic;
500   soundcard->offset_changed = ags_core_audio_devin_offset_changed;
501 
502   soundcard->set_bpm = ags_core_audio_devin_set_bpm;
503   soundcard->get_bpm = ags_core_audio_devin_get_bpm;
504 
505   soundcard->set_delay_factor = ags_core_audio_devin_set_delay_factor;
506   soundcard->get_delay_factor = ags_core_audio_devin_get_delay_factor;
507 
508   soundcard->get_absolute_delay = ags_core_audio_devin_get_absolute_delay;
509 
510   soundcard->get_delay = ags_core_audio_devin_get_delay;
511   soundcard->get_attack = ags_core_audio_devin_get_attack;
512 
513   soundcard->get_buffer = ags_core_audio_devin_get_buffer;
514   soundcard->get_next_buffer = ags_core_audio_devin_get_next_buffer;
515   soundcard->get_prev_buffer = ags_core_audio_devin_get_prev_buffer;
516 
517   soundcard->lock_buffer = ags_core_audio_devin_lock_buffer;
518   soundcard->unlock_buffer = ags_core_audio_devin_unlock_buffer;
519 
520   soundcard->get_delay_counter = ags_core_audio_devin_get_delay_counter;
521 
522   soundcard->set_start_note_offset = ags_core_audio_devin_set_start_note_offset;
523   soundcard->get_start_note_offset = ags_core_audio_devin_get_start_note_offset;
524 
525   soundcard->set_note_offset = ags_core_audio_devin_set_note_offset;
526   soundcard->get_note_offset = ags_core_audio_devin_get_note_offset;
527 
528   soundcard->set_note_offset_absolute = ags_core_audio_devin_set_note_offset_absolute;
529   soundcard->get_note_offset_absolute = ags_core_audio_devin_get_note_offset_absolute;
530 
531   soundcard->set_loop = ags_core_audio_devin_set_loop;
532   soundcard->get_loop = ags_core_audio_devin_get_loop;
533 
534   soundcard->get_loop_offset = ags_core_audio_devin_get_loop_offset;
535 }
536 
537 void
ags_core_audio_devin_init(AgsCoreAudioDevin * core_audio_devin)538 ags_core_audio_devin_init(AgsCoreAudioDevin *core_audio_devin)
539 {
540   AgsConfig *config;
541 
542   gchar *str;
543   gchar *segmentation;
544 
545   guint denominator, numerator;
546   guint i;
547 
548   /* flags */
549   core_audio_devin->flags = 0;
550   g_atomic_int_set(&(core_audio_devin->sync_flags),
551 		   AGS_CORE_AUDIO_DEVIN_PASS_THROUGH);
552 
553   /* devin mutex */
554   g_rec_mutex_init(&(core_audio_devin->obj_mutex));
555 
556   /* uuid */
557   core_audio_devin->uuid = ags_uuid_alloc();
558   ags_uuid_generate(core_audio_devin->uuid);
559 
560   /* presets */
561   config = ags_config_get_instance();
562 
563   core_audio_devin->dsp_channels = ags_soundcard_helper_config_get_dsp_channels(config);
564   core_audio_devin->pcm_channels = ags_soundcard_helper_config_get_pcm_channels(config);
565 
566   core_audio_devin->samplerate = ags_soundcard_helper_config_get_samplerate(config);
567   core_audio_devin->buffer_size = ags_soundcard_helper_config_get_buffer_size(config);
568   core_audio_devin->format = ags_soundcard_helper_config_get_format(config);
569 
570   /*  */
571   core_audio_devin->card_uri = NULL;
572   core_audio_devin->core_audio_client = NULL;
573 
574   core_audio_devin->port_name = NULL;
575   core_audio_devin->core_audio_port = NULL;
576 
577   /* buffer */
578   core_audio_devin->buffer_mutex = (GRecMutex **) malloc(8 * sizeof(GRecMutex *));
579 
580   for(i = 0; i < 8; i++){
581     core_audio_devin->buffer_mutex[i] = (GRecMutex *) malloc(sizeof(GRecMutex));
582 
583     g_rec_mutex_init(core_audio_devin->buffer_mutex[i]);
584   }
585 
586   core_audio_devin->buffer = (void **) malloc(8 * sizeof(void*));
587 
588   core_audio_devin->buffer[0] = NULL;
589   core_audio_devin->buffer[1] = NULL;
590   core_audio_devin->buffer[2] = NULL;
591   core_audio_devin->buffer[3] = NULL;
592   core_audio_devin->buffer[4] = NULL;
593   core_audio_devin->buffer[5] = NULL;
594   core_audio_devin->buffer[6] = NULL;
595   core_audio_devin->buffer[7] = NULL;
596 
597   ags_core_audio_devin_realloc_buffer(core_audio_devin);
598 
599   /* bpm */
600   core_audio_devin->bpm = AGS_SOUNDCARD_DEFAULT_BPM;
601 
602   /* delay factor */
603   core_audio_devin->delay_factor = AGS_SOUNDCARD_DEFAULT_DELAY_FACTOR;
604 
605   /* segmentation */
606   segmentation = ags_config_get_value(config,
607 				      AGS_CONFIG_GENERIC,
608 				      "segmentation");
609 
610   if(segmentation != NULL){
611     sscanf(segmentation, "%d/%d",
612 	   &denominator,
613 	   &numerator);
614 
615     core_audio_devin->delay_factor = 1.0 / numerator * (numerator / denominator);
616 
617     g_free(segmentation);
618   }
619 
620   /* delay and attack */
621   core_audio_devin->delay = (gdouble *) malloc((int) 2 * AGS_SOUNDCARD_DEFAULT_PERIOD *
622 						sizeof(gdouble));
623 
624   core_audio_devin->attack = (guint *) malloc((int) 2 * AGS_SOUNDCARD_DEFAULT_PERIOD *
625 					       sizeof(guint));
626 
627   ags_core_audio_devin_adjust_delay_and_attack(core_audio_devin);
628 
629   /* counters */
630   core_audio_devin->tact_counter = 0.0;
631   core_audio_devin->delay_counter = 0.0;
632   core_audio_devin->tic_counter = 0;
633 
634   core_audio_devin->start_note_offset = 0;
635   core_audio_devin->note_offset = 0;
636   core_audio_devin->note_offset_absolute = 0;
637 
638   core_audio_devin->loop_left = AGS_SOUNDCARD_DEFAULT_LOOP_LEFT;
639   core_audio_devin->loop_right = AGS_SOUNDCARD_DEFAULT_LOOP_RIGHT;
640 
641   core_audio_devin->do_loop = FALSE;
642 
643   core_audio_devin->loop_offset = 0;
644 
645   /* callback mutex */
646   g_mutex_init(&(core_audio_devin->callback_mutex));
647 
648   g_cond_init(&(core_audio_devin->callback_cond));
649 
650   /* callback finish mutex */
651   g_mutex_init(&(core_audio_devin->callback_finish_mutex));
652 
653   g_cond_init(&(core_audio_devin->callback_finish_cond));
654 }
655 
656 void
ags_core_audio_devin_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)657 ags_core_audio_devin_set_property(GObject *gobject,
658 				  guint prop_id,
659 				  const GValue *value,
660 				  GParamSpec *param_spec)
661 {
662   AgsCoreAudioDevin *core_audio_devin;
663 
664   GRecMutex *core_audio_devin_mutex;
665 
666   core_audio_devin = AGS_CORE_AUDIO_DEVIN(gobject);
667 
668   /* get core_audio devin mutex */
669   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
670 
671   switch(prop_id){
672   case PROP_DEVICE:
673     {
674       char *device;
675 
676       device = (char *) g_value_get_string(value);
677 
678       g_rec_mutex_lock(core_audio_devin_mutex);
679 
680       core_audio_devin->card_uri = g_strdup(device);
681 
682       g_rec_mutex_unlock(core_audio_devin_mutex);
683     }
684     break;
685   case PROP_DSP_CHANNELS:
686     {
687       guint dsp_channels;
688 
689       dsp_channels = g_value_get_uint(value);
690 
691       g_rec_mutex_lock(core_audio_devin_mutex);
692 
693       if(dsp_channels == core_audio_devin->dsp_channels){
694 	g_rec_mutex_unlock(core_audio_devin_mutex);
695 
696 	return;
697       }
698 
699       core_audio_devin->dsp_channels = dsp_channels;
700 
701       g_rec_mutex_unlock(core_audio_devin_mutex);
702     }
703     break;
704   case PROP_PCM_CHANNELS:
705     {
706       guint pcm_channels;
707 
708       pcm_channels = g_value_get_uint(value);
709 
710       g_rec_mutex_lock(core_audio_devin_mutex);
711 
712       if(pcm_channels == core_audio_devin->pcm_channels){
713 	g_rec_mutex_unlock(core_audio_devin_mutex);
714 
715 	return;
716       }
717 
718       core_audio_devin->pcm_channels = pcm_channels;
719 
720       g_rec_mutex_unlock(core_audio_devin_mutex);
721 
722       ags_core_audio_devin_realloc_buffer(core_audio_devin);
723     }
724     break;
725   case PROP_FORMAT:
726     {
727       guint format;
728 
729       format = g_value_get_uint(value);
730 
731       g_rec_mutex_lock(core_audio_devin_mutex);
732 
733       if(format == core_audio_devin->format){
734 	g_rec_mutex_unlock(core_audio_devin_mutex);
735 
736 	return;
737       }
738 
739       core_audio_devin->format = format;
740 
741       g_rec_mutex_unlock(core_audio_devin_mutex);
742 
743       ags_core_audio_devin_realloc_buffer(core_audio_devin);
744     }
745     break;
746   case PROP_BUFFER_SIZE:
747     {
748       guint buffer_size;
749 
750       buffer_size = g_value_get_uint(value);
751 
752       g_rec_mutex_lock(core_audio_devin_mutex);
753 
754       if(buffer_size == core_audio_devin->buffer_size){
755 	g_rec_mutex_unlock(core_audio_devin_mutex);
756 
757 	return;
758       }
759 
760       core_audio_devin->buffer_size = buffer_size;
761 
762       g_rec_mutex_unlock(core_audio_devin_mutex);
763 
764       ags_core_audio_devin_realloc_buffer(core_audio_devin);
765       ags_core_audio_devin_adjust_delay_and_attack(core_audio_devin);
766     }
767     break;
768   case PROP_SAMPLERATE:
769     {
770       guint samplerate;
771 
772       samplerate = g_value_get_uint(value);
773 
774       g_rec_mutex_lock(core_audio_devin_mutex);
775 
776       if(samplerate == core_audio_devin->samplerate){
777 	g_rec_mutex_unlock(core_audio_devin_mutex);
778 
779 	return;
780       }
781 
782       core_audio_devin->samplerate = samplerate;
783 
784       g_rec_mutex_unlock(core_audio_devin_mutex);
785 
786       ags_core_audio_devin_realloc_buffer(core_audio_devin);
787       ags_core_audio_devin_adjust_delay_and_attack(core_audio_devin);
788     }
789     break;
790   case PROP_BUFFER:
791     {
792       //TODO:JK: implement me
793     }
794     break;
795   case PROP_BPM:
796     {
797       gdouble bpm;
798 
799       bpm = g_value_get_double(value);
800 
801       g_rec_mutex_lock(core_audio_devin_mutex);
802 
803       core_audio_devin->bpm = bpm;
804 
805       g_rec_mutex_unlock(core_audio_devin_mutex);
806 
807       ags_core_audio_devin_adjust_delay_and_attack(core_audio_devin);
808     }
809     break;
810   case PROP_DELAY_FACTOR:
811     {
812       gdouble delay_factor;
813 
814       delay_factor = g_value_get_double(value);
815 
816       g_rec_mutex_lock(core_audio_devin_mutex);
817 
818       core_audio_devin->delay_factor = delay_factor;
819 
820       g_rec_mutex_unlock(core_audio_devin_mutex);
821 
822       ags_core_audio_devin_adjust_delay_and_attack(core_audio_devin);
823     }
824     break;
825   case PROP_CORE_AUDIO_CLIENT:
826     {
827       AgsCoreAudioClient *core_audio_client;
828 
829       core_audio_client = (AgsCoreAudioClient *) g_value_get_object(value);
830 
831       g_rec_mutex_lock(core_audio_devin_mutex);
832 
833       if(core_audio_devin->core_audio_client == (GObject *) core_audio_client){
834 	g_rec_mutex_unlock(core_audio_devin_mutex);
835 
836 	return;
837       }
838 
839       if(core_audio_devin->core_audio_client != NULL){
840 	g_object_unref(G_OBJECT(core_audio_devin->core_audio_client));
841       }
842 
843       if(core_audio_client != NULL){
844 	g_object_ref(core_audio_client);
845       }
846 
847       core_audio_devin->core_audio_client = (GObject *) core_audio_client;
848 
849       g_rec_mutex_unlock(core_audio_devin_mutex);
850     }
851     break;
852   case PROP_CORE_AUDIO_PORT:
853     {
854       AgsCoreAudioPort *core_audio_port;
855 
856       core_audio_port = (AgsCoreAudioPort *) g_value_get_pointer(value);
857 
858       g_rec_mutex_lock(core_audio_devin_mutex);
859 
860       if(!AGS_IS_CORE_AUDIO_PORT(core_audio_port) ||
861 	 g_list_find(core_audio_devin->core_audio_port, core_audio_port) != NULL){
862 	g_rec_mutex_unlock(core_audio_devin_mutex);
863 
864 	return;
865       }
866 
867       g_object_ref(core_audio_port);
868       core_audio_devin->core_audio_port = g_list_append(core_audio_devin->core_audio_port,
869 							core_audio_port);
870 
871       g_rec_mutex_unlock(core_audio_devin_mutex);
872     }
873     break;
874   default:
875     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
876     break;
877   }
878 }
879 
880 void
ags_core_audio_devin_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)881 ags_core_audio_devin_get_property(GObject *gobject,
882 				  guint prop_id,
883 				  GValue *value,
884 				  GParamSpec *param_spec)
885 {
886   AgsCoreAudioDevin *core_audio_devin;
887 
888   GRecMutex *core_audio_devin_mutex;
889 
890   core_audio_devin = AGS_CORE_AUDIO_DEVIN(gobject);
891 
892   /* get core_audio devin mutex */
893   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
894 
895   switch(prop_id){
896   case PROP_DEVICE:
897     {
898       g_rec_mutex_lock(core_audio_devin_mutex);
899 
900       g_value_set_string(value, core_audio_devin->card_uri);
901 
902       g_rec_mutex_unlock(core_audio_devin_mutex);
903     }
904     break;
905   case PROP_DSP_CHANNELS:
906     {
907       g_rec_mutex_lock(core_audio_devin_mutex);
908 
909       g_value_set_uint(value, core_audio_devin->dsp_channels);
910 
911       g_rec_mutex_unlock(core_audio_devin_mutex);
912     }
913     break;
914   case PROP_PCM_CHANNELS:
915     {
916       g_rec_mutex_lock(core_audio_devin_mutex);
917 
918       g_value_set_uint(value, core_audio_devin->pcm_channels);
919 
920       g_rec_mutex_unlock(core_audio_devin_mutex);
921     }
922     break;
923   case PROP_FORMAT:
924     {
925       g_rec_mutex_lock(core_audio_devin_mutex);
926 
927       g_value_set_uint(value, core_audio_devin->format);
928 
929       g_rec_mutex_unlock(core_audio_devin_mutex);
930     }
931     break;
932   case PROP_BUFFER_SIZE:
933     {
934       g_rec_mutex_lock(core_audio_devin_mutex);
935 
936       g_value_set_uint(value, core_audio_devin->buffer_size);
937 
938       g_rec_mutex_unlock(core_audio_devin_mutex);
939     }
940     break;
941   case PROP_SAMPLERATE:
942     {
943       g_rec_mutex_lock(core_audio_devin_mutex);
944 
945       g_value_set_uint(value, core_audio_devin->samplerate);
946 
947       g_rec_mutex_unlock(core_audio_devin_mutex);
948     }
949     break;
950   case PROP_BUFFER:
951     {
952       g_rec_mutex_lock(core_audio_devin_mutex);
953 
954       g_value_set_pointer(value, core_audio_devin->buffer);
955 
956       g_rec_mutex_unlock(core_audio_devin_mutex);
957     }
958     break;
959   case PROP_BPM:
960     {
961       g_rec_mutex_lock(core_audio_devin_mutex);
962 
963       g_value_set_double(value, core_audio_devin->bpm);
964 
965       g_rec_mutex_unlock(core_audio_devin_mutex);
966     }
967     break;
968   case PROP_DELAY_FACTOR:
969     {
970       g_rec_mutex_lock(core_audio_devin_mutex);
971 
972       g_value_set_double(value, core_audio_devin->delay_factor);
973 
974       g_rec_mutex_unlock(core_audio_devin_mutex);
975     }
976     break;
977   case PROP_ATTACK:
978     {
979       g_rec_mutex_lock(core_audio_devin_mutex);
980 
981       g_value_set_pointer(value, core_audio_devin->attack);
982 
983       g_rec_mutex_unlock(core_audio_devin_mutex);
984     }
985     break;
986   case PROP_CORE_AUDIO_CLIENT:
987     {
988       g_rec_mutex_lock(core_audio_devin_mutex);
989 
990       g_value_set_object(value, core_audio_devin->core_audio_client);
991 
992       g_rec_mutex_unlock(core_audio_devin_mutex);
993     }
994     break;
995   case PROP_CORE_AUDIO_PORT:
996     {
997       g_rec_mutex_lock(core_audio_devin_mutex);
998 
999       g_value_set_pointer(value,
1000 			  g_list_copy_deep(core_audio_devin->core_audio_port,
1001 					   (GCopyFunc) g_object_ref,
1002 					   NULL));
1003 
1004       g_rec_mutex_unlock(core_audio_devin_mutex);
1005     }
1006     break;
1007   default:
1008     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
1009     break;
1010   }
1011 }
1012 
1013 void
ags_core_audio_devin_dispose(GObject * gobject)1014 ags_core_audio_devin_dispose(GObject *gobject)
1015 {
1016   AgsCoreAudioDevin *core_audio_devin;
1017 
1018   GList *list;
1019 
1020   core_audio_devin = AGS_CORE_AUDIO_DEVIN(gobject);
1021 
1022   //TODO:JK: implement me
1023 
1024   /* call parent */
1025   G_OBJECT_CLASS(ags_core_audio_devin_parent_class)->dispose(gobject);
1026 }
1027 
1028 void
ags_core_audio_devin_finalize(GObject * gobject)1029 ags_core_audio_devin_finalize(GObject *gobject)
1030 {
1031   AgsCoreAudioDevin *core_audio_devin;
1032 
1033   core_audio_devin = AGS_CORE_AUDIO_DEVIN(gobject);
1034 
1035   //TODO:JK: implement me
1036 
1037   /* call parent */
1038   G_OBJECT_CLASS(ags_core_audio_devin_parent_class)->finalize(gobject);
1039 }
1040 
1041 /**
1042  * ags_core_audio_devin_test_flags:
1043  * @core_audio_devin: the #AgsCoreAudioDevin
1044  * @flags: the flags
1045  *
1046  * Test @flags to be set on @core_audio_devin.
1047  *
1048  * Returns: %TRUE if flags are set, else %FALSE
1049  *
1050  * Since: 3.0.0
1051  */
1052 gboolean
ags_core_audio_devin_test_flags(AgsCoreAudioDevin * core_audio_devin,guint flags)1053 ags_core_audio_devin_test_flags(AgsCoreAudioDevin *core_audio_devin, guint flags)
1054 {
1055   gboolean retval;
1056 
1057   GRecMutex *core_audio_devin_mutex;
1058 
1059   if(!AGS_IS_CORE_AUDIO_DEVIN(core_audio_devin)){
1060     return(FALSE);
1061   }
1062 
1063   /* get core_audio devin mutex */
1064   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
1065 
1066   /* test */
1067   g_rec_mutex_lock(core_audio_devin_mutex);
1068 
1069   retval = (flags & (core_audio_devin->flags)) ? TRUE: FALSE;
1070 
1071   g_rec_mutex_unlock(core_audio_devin_mutex);
1072 
1073   return(retval);
1074 }
1075 
1076 /**
1077  * ags_core_audio_devin_set_flags:
1078  * @core_audio_devin: the #AgsCoreAudioDevin
1079  * @flags: see #AgsCoreAudioDevinFlags-enum
1080  *
1081  * Enable a feature of @core_audio_devin.
1082  *
1083  * Since: 3.0.0
1084  */
1085 void
ags_core_audio_devin_set_flags(AgsCoreAudioDevin * core_audio_devin,guint flags)1086 ags_core_audio_devin_set_flags(AgsCoreAudioDevin *core_audio_devin, guint flags)
1087 {
1088   GRecMutex *core_audio_devin_mutex;
1089 
1090   if(!AGS_IS_CORE_AUDIO_DEVIN(core_audio_devin)){
1091     return;
1092   }
1093 
1094   /* get core_audio devin mutex */
1095   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
1096 
1097   //TODO:JK: add more?
1098 
1099   /* set flags */
1100   g_rec_mutex_lock(core_audio_devin_mutex);
1101 
1102   core_audio_devin->flags |= flags;
1103 
1104   g_rec_mutex_unlock(core_audio_devin_mutex);
1105 }
1106 
1107 /**
1108  * ags_core_audio_devin_unset_flags:
1109  * @core_audio_devin: the #AgsCoreAudioDevin
1110  * @flags: see #AgsCoreAudioDevinFlags-enum
1111  *
1112  * Disable a feature of @core_audio_devin.
1113  *
1114  * Since: 3.0.0
1115  */
1116 void
ags_core_audio_devin_unset_flags(AgsCoreAudioDevin * core_audio_devin,guint flags)1117 ags_core_audio_devin_unset_flags(AgsCoreAudioDevin *core_audio_devin, guint flags)
1118 {
1119   GRecMutex *core_audio_devin_mutex;
1120 
1121   if(!AGS_IS_CORE_AUDIO_DEVIN(core_audio_devin)){
1122     return;
1123   }
1124 
1125   /* get core_audio devin mutex */
1126   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
1127 
1128   //TODO:JK: add more?
1129 
1130   /* unset flags */
1131   g_rec_mutex_lock(core_audio_devin_mutex);
1132 
1133   core_audio_devin->flags &= (~flags);
1134 
1135   g_rec_mutex_unlock(core_audio_devin_mutex);
1136 }
1137 
1138 void
ags_core_audio_devin_set_device(AgsSoundcard * soundcard,gchar * device)1139 ags_core_audio_devin_set_device(AgsSoundcard *soundcard,
1140 				gchar *device)
1141 {
1142   AgsCoreAudioDevin *core_audio_devin;
1143 
1144   GList *core_audio_port, *core_audio_port_start;
1145 
1146   gchar *str;
1147 
1148   guint pcm_channels;
1149   int ret;
1150   guint nth_card;
1151   guint i;
1152 
1153   GRecMutex *core_audio_devin_mutex;
1154 
1155   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
1156 
1157   /* get core_audio devin mutex */
1158   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
1159 
1160   /* check device */
1161   g_rec_mutex_lock(core_audio_devin_mutex);
1162 
1163   if(core_audio_devin->card_uri == device ||
1164      (core_audio_devin->card_uri != NULL &&
1165       !g_ascii_strcasecmp(core_audio_devin->card_uri,
1166 			  device))){
1167     g_rec_mutex_unlock(core_audio_devin_mutex);
1168 
1169     return;
1170   }
1171 
1172   if(!g_str_has_prefix(device,
1173 		       "ags-core-audio-devin-")){
1174     g_rec_mutex_unlock(core_audio_devin_mutex);
1175 
1176     g_warning("invalid CoreAudio device prefix");
1177 
1178     return;
1179   }
1180 
1181   ret = sscanf(device,
1182 	       "ags-core-audio-devin-%u",
1183 	       &nth_card);
1184 
1185   if(ret != 1){
1186     g_rec_mutex_unlock(core_audio_devin_mutex);
1187 
1188     g_warning("invalid CoreAudio device specifier");
1189 
1190     return;
1191   }
1192 
1193   g_free(core_audio_devin->card_uri);
1194   core_audio_devin->card_uri = g_strdup(device);
1195 
1196   /* apply name to port */
1197   pcm_channels = core_audio_devin->pcm_channels;
1198 
1199   core_audio_port_start =
1200     core_audio_port = g_list_copy(core_audio_devin->core_audio_port);
1201 
1202   g_rec_mutex_unlock(core_audio_devin_mutex);
1203 
1204   for(i = 0; i < pcm_channels && core_audio_port != NULL; i++){
1205     str = g_strdup_printf("ags-soundcard%d-%04d",
1206 			  nth_card,
1207 			  i);
1208 
1209     g_object_set(core_audio_port->data,
1210 		 "port-name", str,
1211 		 NULL);
1212     g_free(str);
1213 
1214     core_audio_port = core_audio_port->next;
1215   }
1216 
1217   g_list_free(core_audio_port_start);
1218 }
1219 
1220 gchar*
ags_core_audio_devin_get_device(AgsSoundcard * soundcard)1221 ags_core_audio_devin_get_device(AgsSoundcard *soundcard)
1222 {
1223   AgsCoreAudioDevin *core_audio_devin;
1224 
1225   gchar *device;
1226 
1227   GRecMutex *core_audio_devin_mutex;
1228 
1229   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
1230 
1231   /* get core_audio devin mutex */
1232   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
1233 
1234   device = NULL;
1235 
1236   /* get device */
1237   g_rec_mutex_lock(core_audio_devin_mutex);
1238 
1239   device = g_strdup(core_audio_devin->card_uri);
1240 
1241   g_rec_mutex_unlock(core_audio_devin_mutex);
1242 
1243   return(device);
1244 }
1245 
1246 void
ags_core_audio_devin_set_presets(AgsSoundcard * soundcard,guint channels,guint rate,guint buffer_size,guint format)1247 ags_core_audio_devin_set_presets(AgsSoundcard *soundcard,
1248 				 guint channels,
1249 				 guint rate,
1250 				 guint buffer_size,
1251 				 guint format)
1252 {
1253   AgsCoreAudioDevin *core_audio_devin;
1254 
1255   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
1256 
1257   g_object_set(core_audio_devin,
1258 	       "pcm-channels", channels,
1259 	       "samplerate", rate,
1260 	       "buffer-size", buffer_size,
1261 	       "format", format,
1262 	       NULL);
1263 }
1264 
1265 void
ags_core_audio_devin_get_presets(AgsSoundcard * soundcard,guint * channels,guint * rate,guint * buffer_size,guint * format)1266 ags_core_audio_devin_get_presets(AgsSoundcard *soundcard,
1267 				 guint *channels,
1268 				 guint *rate,
1269 				 guint *buffer_size,
1270 				 guint *format)
1271 {
1272   AgsCoreAudioDevin *core_audio_devin;
1273 
1274   GRecMutex *core_audio_devin_mutex;
1275 
1276   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
1277 
1278   /* get core_audio devin mutex */
1279   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
1280 
1281   /* get presets */
1282   g_rec_mutex_lock(core_audio_devin_mutex);
1283 
1284   if(channels != NULL){
1285     *channels = core_audio_devin->pcm_channels;
1286   }
1287 
1288   if(rate != NULL){
1289     *rate = core_audio_devin->samplerate;
1290   }
1291 
1292   if(buffer_size != NULL){
1293     *buffer_size = core_audio_devin->buffer_size;
1294   }
1295 
1296   if(format != NULL){
1297     *format = core_audio_devin->format;
1298   }
1299 
1300   g_rec_mutex_unlock(core_audio_devin_mutex);
1301 }
1302 
1303 /**
1304  * ags_core_audio_devin_list_cards:
1305  * @soundcard: the #AgsSoundcard
1306  * @card_id: CORE_AUDIO identifier
1307  * @card_name: card name
1308  *
1309  * List available soundcards.
1310  *
1311  * Since: 3.0.0
1312  */
1313 void
ags_core_audio_devin_list_cards(AgsSoundcard * soundcard,GList ** card_id,GList ** card_name)1314 ags_core_audio_devin_list_cards(AgsSoundcard *soundcard,
1315 				GList **card_id, GList **card_name)
1316 {
1317   AgsCoreAudioClient *core_audio_client;
1318   AgsCoreAudioDevin *core_audio_devin;
1319 
1320   AgsApplicationContext *application_context;
1321 
1322   GList *list_start, *list;
1323 
1324   gchar *card_uri;
1325   gchar *client_name;
1326 
1327   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
1328 
1329   application_context = ags_application_context_get_instance();
1330 
1331   if(card_id != NULL){
1332     *card_id = NULL;
1333   }
1334 
1335   if(card_name != NULL){
1336     *card_name = NULL;
1337   }
1338 
1339   list =
1340     list_start = ags_sound_provider_get_soundcard(AGS_SOUND_PROVIDER(application_context));
1341 
1342   while(list != NULL){
1343     if(AGS_IS_CORE_AUDIO_DEVIN(list->data)){
1344       if(card_id != NULL){
1345 	card_uri = ags_soundcard_get_device(AGS_SOUNDCARD(list->data));
1346 
1347 	if(AGS_CORE_AUDIO_DEVIN(list->data)->card_uri != NULL){
1348 	  *card_id = g_list_prepend(*card_id,
1349 				    card_uri);
1350 	}else{
1351 	  *card_id = g_list_prepend(*card_id,
1352 				    g_strdup("(null)"));
1353 
1354 	  g_warning("ags_core_audio_devin_list_cards() - card id (null)");
1355 	}
1356       }
1357 
1358       if(card_name != NULL){
1359 	g_object_get(list->data,
1360 		     "core_audio-client", &core_audio_client,
1361 		     NULL);
1362 
1363 	if(core_audio_client != NULL){
1364 	  /* get client name */
1365 	  g_object_get(core_audio_client,
1366 		       "client-name", &client_name,
1367 		       NULL);
1368 
1369 	  *card_name = g_list_prepend(*card_name,
1370 				      client_name);
1371 
1372 	  g_object_unref(core_audio_client);
1373 	}else{
1374 	  *card_name = g_list_prepend(*card_name,
1375 				      g_strdup("(null)"));
1376 
1377 	  g_warning("ags_core_audio_devin_list_cards() - CORE_AUDIO client not connected (null)");
1378 	}
1379       }
1380     }
1381 
1382     list = list->next;
1383   }
1384 
1385   g_list_free_full(list_start,
1386 		   g_object_unref);
1387 
1388   if(card_id != NULL && *card_id != NULL){
1389     *card_id = g_list_reverse(*card_id);
1390   }
1391 
1392   if(card_name != NULL && *card_name != NULL){
1393     *card_name = g_list_reverse(*card_name);
1394   }
1395 }
1396 
1397 void
ags_core_audio_devin_pcm_info(AgsSoundcard * soundcard,char * card_id,guint * channels_min,guint * channels_max,guint * rate_min,guint * rate_max,guint * buffer_size_min,guint * buffer_size_max,GError ** error)1398 ags_core_audio_devin_pcm_info(AgsSoundcard *soundcard,
1399 			      char *card_id,
1400 			      guint *channels_min, guint *channels_max,
1401 			      guint *rate_min, guint *rate_max,
1402 			      guint *buffer_size_min, guint *buffer_size_max,
1403 			      GError **error)
1404 {
1405   if(channels_min != NULL){
1406     *channels_min = 1;
1407   }
1408 
1409   if(channels_max != NULL){
1410     *channels_max = 1024;
1411   }
1412 
1413   if(rate_min != NULL){
1414     *rate_min = 8000;
1415   }
1416 
1417   if(rate_max != NULL){
1418     *rate_max = 192000;
1419   }
1420 
1421   if(buffer_size_min != NULL){
1422     *buffer_size_min = 64;
1423   }
1424 
1425   if(buffer_size_max != NULL){
1426     *buffer_size_max = 8192;
1427   }
1428 }
1429 
1430 guint
ags_core_audio_devin_get_capability(AgsSoundcard * soundcard)1431 ags_core_audio_devin_get_capability(AgsSoundcard *soundcard)
1432 {
1433   return(AGS_SOUNDCARD_CAPABILITY_CAPTURE);
1434 }
1435 
1436 gboolean
ags_core_audio_devin_is_starting(AgsSoundcard * soundcard)1437 ags_core_audio_devin_is_starting(AgsSoundcard *soundcard)
1438 {
1439   AgsCoreAudioDevin *core_audio_devin;
1440 
1441   gboolean is_starting;
1442 
1443   GRecMutex *core_audio_devin_mutex;
1444 
1445   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
1446 
1447   /* get core_audio devin mutex */
1448   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
1449 
1450   /* check is starting */
1451   g_rec_mutex_lock(core_audio_devin_mutex);
1452 
1453   is_starting = ((AGS_CORE_AUDIO_DEVIN_START_RECORD & (core_audio_devin->flags)) != 0) ? TRUE: FALSE;
1454 
1455   g_rec_mutex_unlock(core_audio_devin_mutex);
1456 
1457   return(is_starting);
1458 }
1459 
1460 gboolean
ags_core_audio_devin_is_recording(AgsSoundcard * soundcard)1461 ags_core_audio_devin_is_recording(AgsSoundcard *soundcard)
1462 {
1463   AgsCoreAudioDevin *core_audio_devin;
1464 
1465   gboolean is_playing;
1466 
1467   GRecMutex *core_audio_devin_mutex;
1468 
1469   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
1470 
1471   /* get core_audio devin mutex */
1472   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
1473 
1474   /* check is starting */
1475   g_rec_mutex_lock(core_audio_devin_mutex);
1476 
1477   is_playing = ((AGS_CORE_AUDIO_DEVIN_RECORD & (core_audio_devin->flags)) != 0) ? TRUE: FALSE;
1478 
1479   g_rec_mutex_unlock(core_audio_devin_mutex);
1480 
1481   return(is_playing);
1482 }
1483 
1484 gchar*
ags_core_audio_devin_get_uptime(AgsSoundcard * soundcard)1485 ags_core_audio_devin_get_uptime(AgsSoundcard *soundcard)
1486 {
1487   gchar *uptime;
1488 
1489   if(ags_soundcard_is_playing(soundcard)){
1490     guint samplerate;
1491     guint buffer_size;
1492 
1493     guint note_offset;
1494     gdouble bpm;
1495     gdouble delay_factor;
1496 
1497     gdouble delay;
1498 
1499     ags_soundcard_get_presets(soundcard,
1500 			      NULL,
1501 			      &samplerate,
1502 			      &buffer_size,
1503 			      NULL);
1504 
1505     note_offset = ags_soundcard_get_note_offset_absolute(soundcard);
1506 
1507     bpm = ags_soundcard_get_bpm(soundcard);
1508     delay_factor = ags_soundcard_get_delay_factor(soundcard);
1509 
1510     /* calculate delays */
1511     delay = ags_soundcard_get_absolute_delay(soundcard);
1512 
1513     uptime = ags_time_get_uptime_from_offset(note_offset,
1514 					     bpm,
1515 					     delay,
1516 					     delay_factor);
1517   }else{
1518     uptime = g_strdup(AGS_TIME_ZERO);
1519   }
1520 
1521   return(uptime);
1522 }
1523 
1524 void
ags_core_audio_devin_port_init(AgsSoundcard * soundcard,GError ** error)1525 ags_core_audio_devin_port_init(AgsSoundcard *soundcard,
1526 			       GError **error)
1527 {
1528   AgsCoreAudioDevin *core_audio_devin;
1529 
1530   guint format, word_size;
1531 
1532   GRecMutex *core_audio_devin_mutex;
1533 
1534   if(ags_soundcard_is_recording(soundcard)){
1535     return;
1536   }
1537 
1538   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
1539 
1540   /* get core-audio devin mutex */
1541   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
1542 
1543   /* retrieve word size */
1544   g_rec_mutex_lock(core_audio_devin_mutex);
1545 
1546   switch(core_audio_devin->format){
1547   case AGS_SOUNDCARD_SIGNED_8_BIT:
1548     {
1549       word_size = sizeof(gint8);
1550     }
1551     break;
1552   case AGS_SOUNDCARD_SIGNED_16_BIT:
1553     {
1554       word_size = sizeof(gint16);
1555     }
1556     break;
1557   case AGS_SOUNDCARD_SIGNED_24_BIT:
1558     {
1559       //NOTE:JK: The 24-bit linear samples use 32-bit physical space
1560       word_size = sizeof(gint32);
1561     }
1562     break;
1563   case AGS_SOUNDCARD_SIGNED_32_BIT:
1564     {
1565       word_size = sizeof(gint32);
1566     }
1567     break;
1568   case AGS_SOUNDCARD_SIGNED_64_BIT:
1569     {
1570       word_size = sizeof(gint64);
1571     }
1572     break;
1573   default:
1574     g_rec_mutex_unlock(core_audio_devin_mutex);
1575 
1576     g_warning("ags_core_audio_devin_port_init(): unsupported word size");
1577 
1578     return;
1579   }
1580 
1581   /* prepare for playback */
1582   core_audio_devin->flags |= (AGS_CORE_AUDIO_DEVIN_BUFFER7 |
1583 			       AGS_CORE_AUDIO_DEVIN_START_RECORD |
1584 			       AGS_CORE_AUDIO_DEVIN_RECORD |
1585 			       AGS_CORE_AUDIO_DEVIN_NONBLOCKING);
1586 
1587   memset(core_audio_devin->buffer[0], 0, core_audio_devin->pcm_channels * core_audio_devin->buffer_size * word_size);
1588   memset(core_audio_devin->buffer[1], 0, core_audio_devin->pcm_channels * core_audio_devin->buffer_size * word_size);
1589   memset(core_audio_devin->buffer[2], 0, core_audio_devin->pcm_channels * core_audio_devin->buffer_size * word_size);
1590   memset(core_audio_devin->buffer[3], 0, core_audio_devin->pcm_channels * core_audio_devin->buffer_size * word_size);
1591   memset(core_audio_devin->buffer[4], 0, core_audio_devin->pcm_channels * core_audio_devin->buffer_size * word_size);
1592   memset(core_audio_devin->buffer[5], 0, core_audio_devin->pcm_channels * core_audio_devin->buffer_size * word_size);
1593   memset(core_audio_devin->buffer[6], 0, core_audio_devin->pcm_channels * core_audio_devin->buffer_size * word_size);
1594   memset(core_audio_devin->buffer[7], 0, core_audio_devin->pcm_channels * core_audio_devin->buffer_size * word_size);
1595 
1596   /*  */
1597   core_audio_devin->tact_counter = 0.0;
1598   core_audio_devin->delay_counter = floor(ags_soundcard_get_absolute_delay(AGS_SOUNDCARD(core_audio_devin)));
1599   core_audio_devin->tic_counter = 0;
1600 
1601   core_audio_devin->flags |= (AGS_CORE_AUDIO_DEVIN_INITIALIZED |
1602 			       AGS_CORE_AUDIO_DEVIN_START_RECORD |
1603 			       AGS_CORE_AUDIO_DEVIN_RECORD);
1604 
1605   g_atomic_int_or(&(core_audio_devin->sync_flags),
1606 		  AGS_CORE_AUDIO_DEVIN_INITIAL_CALLBACK);
1607 
1608   g_rec_mutex_unlock(core_audio_devin_mutex);
1609 }
1610 
1611 void
ags_core_audio_devin_port_record(AgsSoundcard * soundcard,GError ** error)1612 ags_core_audio_devin_port_record(AgsSoundcard *soundcard,
1613 				 GError **error)
1614 {
1615   AgsCoreAudioClient *core_audio_client;
1616   AgsCoreAudioDevin *core_audio_devin;
1617 
1618   AgsTicDevice *tic_device;
1619   AgsClearBuffer *clear_buffer;
1620   AgsSwitchBufferFlag *switch_buffer_flag;
1621 
1622   AgsTaskLauncher *task_launcher;
1623 
1624   AgsApplicationContext *application_context;
1625 
1626   GList *task;
1627   guint word_size;
1628   gboolean core_audio_client_activated;
1629 
1630   GRecMutex *core_audio_devin_mutex;
1631   GRecMutex *core_audio_client_mutex;
1632   GMutex *callback_mutex;
1633   GMutex *callback_finish_mutex;
1634 
1635   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
1636 
1637   application_context = ags_application_context_get_instance();
1638 
1639   /* get core-audio devin mutex */
1640   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
1641 
1642   /* client */
1643   g_rec_mutex_lock(core_audio_devin_mutex);
1644 
1645   core_audio_client = (AgsCoreAudioClient *) core_audio_devin->core_audio_client;
1646 
1647   callback_mutex = &(core_audio_devin->callback_mutex);
1648   callback_finish_mutex = &(core_audio_devin->callback_finish_mutex);
1649 
1650   /* do playback */
1651   core_audio_devin->flags &= (~AGS_CORE_AUDIO_DEVIN_START_RECORD);
1652 
1653   switch(core_audio_devin->format){
1654   case AGS_SOUNDCARD_SIGNED_16_BIT:
1655     {
1656       word_size = sizeof(gint16);
1657     }
1658     break;
1659   case AGS_SOUNDCARD_SIGNED_24_BIT:
1660     {
1661       //NOTE:JK: The 24-bit linear samples use 32-bit physical space
1662       word_size = sizeof(gint32);
1663     }
1664     break;
1665   case AGS_SOUNDCARD_SIGNED_32_BIT:
1666     {
1667       word_size = sizeof(gint32);
1668     }
1669     break;
1670   default:
1671     g_rec_mutex_unlock(core_audio_devin_mutex);
1672 
1673     g_warning("ags_core_audio_devin_port_record(): unsupported word size");
1674 
1675     return;
1676   }
1677 
1678   g_rec_mutex_unlock(core_audio_devin_mutex);
1679 
1680   /* get client mutex */
1681   core_audio_client_mutex = AGS_CORE_AUDIO_CLIENT_GET_OBJ_MUTEX(core_audio_client);
1682 
1683   /* get activated */
1684   g_rec_mutex_lock(core_audio_client_mutex);
1685 
1686   core_audio_client_activated = ((AGS_CORE_AUDIO_CLIENT_ACTIVATED & (core_audio_client->flags)) != 0) ? TRUE: FALSE;
1687 
1688   g_rec_mutex_unlock(core_audio_client_mutex);
1689 
1690   if(core_audio_client_activated){
1691     while((AGS_CORE_AUDIO_DEVIN_PASS_THROUGH & (g_atomic_int_get(&(core_audio_devin->sync_flags)))) != 0){
1692 	usleep(4);
1693     }
1694 
1695     /* signal */
1696     if((AGS_CORE_AUDIO_DEVIN_INITIAL_CALLBACK & (g_atomic_int_get(&(core_audio_devin->sync_flags)))) == 0){
1697       g_mutex_lock(callback_mutex);
1698 
1699       g_atomic_int_or(&(core_audio_devin->sync_flags),
1700 		      AGS_CORE_AUDIO_DEVIN_CALLBACK_DONE);
1701 
1702       if((AGS_CORE_AUDIO_DEVIN_CALLBACK_WAIT & (g_atomic_int_get(&(core_audio_devin->sync_flags)))) != 0){
1703 	g_cond_signal(&(core_audio_devin->callback_cond));
1704       }
1705 
1706       g_mutex_unlock(callback_mutex);
1707       //    }
1708 
1709       /* wait callback */
1710       g_mutex_lock(callback_finish_mutex);
1711 
1712       if((AGS_CORE_AUDIO_DEVIN_CALLBACK_FINISH_DONE & (g_atomic_int_get(&(core_audio_devin->sync_flags)))) == 0){
1713 	g_atomic_int_or(&(core_audio_devin->sync_flags),
1714 			AGS_CORE_AUDIO_DEVIN_CALLBACK_FINISH_WAIT);
1715 
1716 	while((AGS_CORE_AUDIO_DEVIN_CALLBACK_FINISH_DONE & (g_atomic_int_get(&(core_audio_devin->sync_flags)))) == 0 &&
1717 	      (AGS_CORE_AUDIO_DEVIN_CALLBACK_FINISH_WAIT & (g_atomic_int_get(&(core_audio_devin->sync_flags)))) != 0){
1718 	  g_cond_wait(&(core_audio_devin->callback_finish_cond),
1719 		      callback_finish_mutex);
1720 	}
1721       }
1722 
1723       g_atomic_int_and(&(core_audio_devin->sync_flags),
1724 		       (~(AGS_CORE_AUDIO_DEVIN_CALLBACK_FINISH_WAIT |
1725 			  AGS_CORE_AUDIO_DEVIN_CALLBACK_FINISH_DONE)));
1726 
1727       g_mutex_unlock(callback_finish_mutex);
1728     }else{
1729       g_atomic_int_and(&(core_audio_devin->sync_flags),
1730 		       (~AGS_CORE_AUDIO_DEVIN_INITIAL_CALLBACK));
1731     }
1732   }
1733 
1734   /* update soundcard */
1735   task_launcher = ags_concurrency_provider_get_task_launcher(AGS_CONCURRENCY_PROVIDER(application_context));
1736 
1737   task = NULL;
1738 
1739   /* tic soundcard */
1740   tic_device = ags_tic_device_new((GObject *) core_audio_devin);
1741   task = g_list_append(task,
1742 		       tic_device);
1743 
1744   /* reset - clear buffer */
1745   clear_buffer = ags_clear_buffer_new((GObject *) core_audio_devin);
1746   task = g_list_append(task,
1747 		       clear_buffer);
1748 
1749   /* reset - switch buffer flags */
1750   switch_buffer_flag = ags_switch_buffer_flag_new((GObject *) core_audio_devin);
1751   task = g_list_append(task,
1752 		       switch_buffer_flag);
1753 
1754   /* append tasks */
1755   ags_task_launcher_add_task_all(task_launcher,
1756 				 task);
1757 
1758   /* unref */
1759   g_object_unref(task_launcher);
1760 }
1761 
1762 void
ags_core_audio_devin_port_free(AgsSoundcard * soundcard)1763 ags_core_audio_devin_port_free(AgsSoundcard *soundcard)
1764 {
1765   AgsCoreAudioPort *core_audio_port;
1766   AgsCoreAudioDevin *core_audio_devin;
1767 
1768   guint word_size;
1769 
1770   GRecMutex *core_audio_devin_mutex;
1771   GMutex *callback_mutex;
1772   GMutex *callback_finish_mutex;
1773 
1774   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
1775 
1776   /* get core-audio devin mutex */
1777   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
1778 
1779   /*  */
1780   g_rec_mutex_lock(core_audio_devin_mutex);
1781 
1782   callback_mutex = &(core_audio_devin->callback_mutex);
1783   callback_finish_mutex = &(core_audio_devin->callback_finish_mutex);
1784 
1785   //  g_atomic_int_or(&(AGS_THREAD(application_context->main_loop)->flags),
1786   //		  AGS_THREAD_TIMING);
1787 
1788   core_audio_devin->flags &= (~(AGS_CORE_AUDIO_DEVIN_BUFFER0 |
1789 				 AGS_CORE_AUDIO_DEVIN_BUFFER1 |
1790 				 AGS_CORE_AUDIO_DEVIN_BUFFER2 |
1791 				 AGS_CORE_AUDIO_DEVIN_BUFFER3 |
1792 				 AGS_CORE_AUDIO_DEVIN_BUFFER4 |
1793 				 AGS_CORE_AUDIO_DEVIN_BUFFER5 |
1794 				 AGS_CORE_AUDIO_DEVIN_BUFFER6 |
1795 				 AGS_CORE_AUDIO_DEVIN_BUFFER7 |
1796 				 AGS_CORE_AUDIO_DEVIN_RECORD));
1797 
1798   g_atomic_int_or(&(core_audio_devin->sync_flags),
1799 		  AGS_CORE_AUDIO_DEVIN_PASS_THROUGH);
1800   g_atomic_int_and(&(core_audio_devin->sync_flags),
1801 		   (~AGS_CORE_AUDIO_DEVIN_INITIAL_CALLBACK));
1802 
1803   /* signal callback */
1804   g_mutex_lock(callback_mutex);
1805 
1806   g_atomic_int_or(&(core_audio_devin->sync_flags),
1807 		  AGS_CORE_AUDIO_DEVIN_CALLBACK_DONE);
1808 
1809   if((AGS_CORE_AUDIO_DEVIN_CALLBACK_WAIT & (g_atomic_int_get(&(core_audio_devin->sync_flags)))) != 0){
1810     g_cond_signal(&(core_audio_devin->callback_cond));
1811   }
1812 
1813   g_mutex_unlock(callback_mutex);
1814 
1815   /* signal thread */
1816   g_mutex_lock(callback_finish_mutex);
1817 
1818   g_atomic_int_or(&(core_audio_devin->sync_flags),
1819 		  AGS_CORE_AUDIO_DEVIN_CALLBACK_FINISH_DONE);
1820 
1821   if((AGS_CORE_AUDIO_DEVIN_CALLBACK_FINISH_WAIT & (g_atomic_int_get(&(core_audio_devin->sync_flags)))) != 0){
1822     g_cond_signal(&(core_audio_devin->callback_finish_cond));
1823   }
1824 
1825   g_mutex_unlock(callback_finish_mutex);
1826 
1827   /*  */
1828   core_audio_devin->note_offset = core_audio_devin->start_note_offset;
1829   core_audio_devin->note_offset_absolute = core_audio_devin->start_note_offset;
1830 
1831   switch(core_audio_devin->format){
1832   case AGS_SOUNDCARD_SIGNED_8_BIT:
1833     {
1834       word_size = sizeof(gint8);
1835     }
1836     break;
1837   case AGS_SOUNDCARD_SIGNED_16_BIT:
1838     {
1839       word_size = sizeof(gint16);
1840     }
1841     break;
1842   case AGS_SOUNDCARD_SIGNED_24_BIT:
1843     {
1844       word_size = sizeof(gint32);
1845     }
1846     break;
1847   case AGS_SOUNDCARD_SIGNED_32_BIT:
1848     {
1849       word_size = sizeof(gint32);
1850     }
1851     break;
1852   case AGS_SOUNDCARD_SIGNED_64_BIT:
1853     {
1854       word_size = sizeof(gint64);
1855     }
1856     break;
1857   default:
1858     word_size = 0;
1859 
1860     g_critical("ags_core_audio_devin_free(): unsupported word size");
1861   }
1862 
1863   g_rec_mutex_unlock(core_audio_devin_mutex);
1864 
1865   if(core_audio_devin->core_audio_port != NULL){
1866     core_audio_port = core_audio_devin->core_audio_port->data;
1867 
1868     while(!g_atomic_int_get(&(core_audio_port->is_empty))) usleep(500000);
1869   }
1870 
1871   g_rec_mutex_lock(core_audio_devin_mutex);
1872 
1873   memset(core_audio_devin->buffer[0], 0, (size_t) core_audio_devin->pcm_channels * core_audio_devin->buffer_size * word_size);
1874   memset(core_audio_devin->buffer[1], 0, (size_t) core_audio_devin->pcm_channels * core_audio_devin->buffer_size * word_size);
1875   memset(core_audio_devin->buffer[2], 0, (size_t) core_audio_devin->pcm_channels * core_audio_devin->buffer_size * word_size);
1876   memset(core_audio_devin->buffer[3], 0, (size_t) core_audio_devin->pcm_channels * core_audio_devin->buffer_size * word_size);
1877   memset(core_audio_devin->buffer[4], 0, (size_t) core_audio_devin->pcm_channels * core_audio_devin->buffer_size * word_size);
1878   memset(core_audio_devin->buffer[5], 0, (size_t) core_audio_devin->pcm_channels * core_audio_devin->buffer_size * word_size);
1879   memset(core_audio_devin->buffer[6], 0, (size_t) core_audio_devin->pcm_channels * core_audio_devin->buffer_size * word_size);
1880   memset(core_audio_devin->buffer[7], 0, (size_t) core_audio_devin->pcm_channels * core_audio_devin->buffer_size * word_size);
1881 
1882   g_rec_mutex_unlock(core_audio_devin_mutex);
1883 }
1884 
1885 void
ags_core_audio_devin_tic(AgsSoundcard * soundcard)1886 ags_core_audio_devin_tic(AgsSoundcard *soundcard)
1887 {
1888   AgsCoreAudioDevin *core_audio_devin;
1889 
1890   gdouble delay;
1891   gdouble delay_counter;
1892   guint note_offset_absolute;
1893   guint note_offset;
1894   guint loop_left, loop_right;
1895   gboolean do_loop;
1896 
1897   GRecMutex *core_audio_devin_mutex;
1898 
1899   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
1900 
1901   /* get core_audio devin mutex */
1902   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
1903 
1904   /* determine if attack should be switched */
1905   g_rec_mutex_lock(core_audio_devin_mutex);
1906 
1907   delay = core_audio_devin->delay[core_audio_devin->tic_counter];
1908   delay_counter = core_audio_devin->delay_counter;
1909 
1910   note_offset = core_audio_devin->note_offset;
1911   note_offset_absolute = core_audio_devin->note_offset_absolute;
1912 
1913   loop_left = core_audio_devin->loop_left;
1914   loop_right = core_audio_devin->loop_right;
1915 
1916   do_loop = core_audio_devin->do_loop;
1917 
1918   g_rec_mutex_unlock(core_audio_devin_mutex);
1919 
1920   if(delay_counter + 1.0 >= floor(delay)){
1921     if(do_loop &&
1922        note_offset + 1 == loop_right){
1923       ags_soundcard_set_note_offset(soundcard,
1924 				    loop_left);
1925     }else{
1926       ags_soundcard_set_note_offset(soundcard,
1927 				    note_offset + 1);
1928     }
1929 
1930     ags_soundcard_set_note_offset_absolute(soundcard,
1931 					   note_offset_absolute + 1);
1932 
1933     /* delay */
1934     ags_soundcard_offset_changed(soundcard,
1935 				 note_offset);
1936 
1937     /* reset - delay counter */
1938     g_rec_mutex_lock(core_audio_devin_mutex);
1939 
1940     core_audio_devin->delay_counter = delay_counter + 1.0 - delay;
1941     core_audio_devin->tact_counter += 1.0;
1942 
1943     g_rec_mutex_unlock(core_audio_devin_mutex);
1944   }else{
1945     g_rec_mutex_lock(core_audio_devin_mutex);
1946 
1947     core_audio_devin->delay_counter += 1.0;
1948 
1949     g_rec_mutex_unlock(core_audio_devin_mutex);
1950   }
1951 }
1952 
1953 void
ags_core_audio_devin_offset_changed(AgsSoundcard * soundcard,guint note_offset)1954 ags_core_audio_devin_offset_changed(AgsSoundcard *soundcard,
1955 				    guint note_offset)
1956 {
1957   AgsCoreAudioDevin *core_audio_devin;
1958 
1959   GRecMutex *core_audio_devin_mutex;
1960 
1961   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
1962 
1963   /* get core_audio devin mutex */
1964   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
1965 
1966   /* offset changed */
1967   g_rec_mutex_lock(core_audio_devin_mutex);
1968 
1969   core_audio_devin->tic_counter += 1;
1970 
1971   if(core_audio_devin->tic_counter == AGS_SOUNDCARD_DEFAULT_PERIOD){
1972     /* reset - tic counter i.e. modified delay index within period */
1973     core_audio_devin->tic_counter = 0;
1974   }
1975 
1976   g_rec_mutex_unlock(core_audio_devin_mutex);
1977 }
1978 
1979 void
ags_core_audio_devin_set_bpm(AgsSoundcard * soundcard,gdouble bpm)1980 ags_core_audio_devin_set_bpm(AgsSoundcard *soundcard,
1981 			     gdouble bpm)
1982 {
1983   AgsCoreAudioDevin *core_audio_devin;
1984 
1985   GRecMutex *core_audio_devin_mutex;
1986 
1987   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
1988 
1989   /* get core_audio devin mutex */
1990   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
1991 
1992   /* set bpm */
1993   g_rec_mutex_lock(core_audio_devin_mutex);
1994 
1995   core_audio_devin->bpm = bpm;
1996 
1997   g_rec_mutex_unlock(core_audio_devin_mutex);
1998 
1999   ags_core_audio_devin_adjust_delay_and_attack(core_audio_devin);
2000 }
2001 
2002 gdouble
ags_core_audio_devin_get_bpm(AgsSoundcard * soundcard)2003 ags_core_audio_devin_get_bpm(AgsSoundcard *soundcard)
2004 {
2005   AgsCoreAudioDevin *core_audio_devin;
2006 
2007   gdouble bpm;
2008 
2009   GRecMutex *core_audio_devin_mutex;
2010 
2011   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
2012 
2013   /* get core_audio devin mutex */
2014   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
2015 
2016   /* get bpm */
2017   g_rec_mutex_lock(core_audio_devin_mutex);
2018 
2019   bpm = core_audio_devin->bpm;
2020 
2021   g_rec_mutex_unlock(core_audio_devin_mutex);
2022 
2023   return(bpm);
2024 }
2025 
2026 void
ags_core_audio_devin_set_delay_factor(AgsSoundcard * soundcard,gdouble delay_factor)2027 ags_core_audio_devin_set_delay_factor(AgsSoundcard *soundcard,
2028 				      gdouble delay_factor)
2029 {
2030   AgsCoreAudioDevin *core_audio_devin;
2031 
2032   GRecMutex *core_audio_devin_mutex;
2033 
2034   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
2035 
2036   /* get core_audio devin mutex */
2037   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
2038 
2039   /* set delay factor */
2040   g_rec_mutex_lock(core_audio_devin_mutex);
2041 
2042   core_audio_devin->delay_factor = delay_factor;
2043 
2044   g_rec_mutex_unlock(core_audio_devin_mutex);
2045 
2046   ags_core_audio_devin_adjust_delay_and_attack(core_audio_devin);
2047 }
2048 
2049 gdouble
ags_core_audio_devin_get_delay_factor(AgsSoundcard * soundcard)2050 ags_core_audio_devin_get_delay_factor(AgsSoundcard *soundcard)
2051 {
2052   AgsCoreAudioDevin *core_audio_devin;
2053 
2054   gdouble delay_factor;
2055 
2056   GRecMutex *core_audio_devin_mutex;
2057 
2058   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
2059 
2060   /* get core_audio devin mutex */
2061   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
2062 
2063   /* get delay factor */
2064   g_rec_mutex_lock(core_audio_devin_mutex);
2065 
2066   delay_factor = core_audio_devin->delay_factor;
2067 
2068   g_rec_mutex_unlock(core_audio_devin_mutex);
2069 
2070   return(delay_factor);
2071 }
2072 
2073 gdouble
ags_core_audio_devin_get_delay(AgsSoundcard * soundcard)2074 ags_core_audio_devin_get_delay(AgsSoundcard *soundcard)
2075 {
2076   AgsCoreAudioDevin *core_audio_devin;
2077 
2078   guint delay_index;
2079   gdouble delay;
2080 
2081   GRecMutex *core_audio_devin_mutex;
2082 
2083   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
2084 
2085   /* get core_audio devin mutex */
2086   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
2087 
2088   /* get delay */
2089   g_rec_mutex_lock(core_audio_devin_mutex);
2090 
2091   delay_index = core_audio_devin->tic_counter;
2092 
2093   delay = core_audio_devin->delay[delay_index];
2094 
2095   g_rec_mutex_unlock(core_audio_devin_mutex);
2096 
2097   return(delay);
2098 }
2099 
2100 gdouble
ags_core_audio_devin_get_absolute_delay(AgsSoundcard * soundcard)2101 ags_core_audio_devin_get_absolute_delay(AgsSoundcard *soundcard)
2102 {
2103   AgsCoreAudioDevin *core_audio_devin;
2104 
2105   gdouble absolute_delay;
2106 
2107   GRecMutex *core_audio_devin_mutex;
2108 
2109   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
2110 
2111   /* get core_audio devin mutex */
2112   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
2113 
2114   /* get absolute delay */
2115   g_rec_mutex_lock(core_audio_devin_mutex);
2116 
2117   absolute_delay = (60.0 * (((gdouble) core_audio_devin->samplerate / (gdouble) core_audio_devin->buffer_size) / (gdouble) core_audio_devin->bpm) * ((1.0 / 16.0) * (1.0 / (gdouble) core_audio_devin->delay_factor)));
2118 
2119   g_rec_mutex_unlock(core_audio_devin_mutex);
2120 
2121   return(absolute_delay);
2122 }
2123 
2124 guint
ags_core_audio_devin_get_attack(AgsSoundcard * soundcard)2125 ags_core_audio_devin_get_attack(AgsSoundcard *soundcard)
2126 {
2127   AgsCoreAudioDevin *core_audio_devin;
2128 
2129   guint attack_index;
2130   guint attack;
2131 
2132   GRecMutex *core_audio_devin_mutex;
2133 
2134   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
2135 
2136   /* get core_audio devin mutex */
2137   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
2138 
2139   /* get attack */
2140   g_rec_mutex_lock(core_audio_devin_mutex);
2141 
2142   attack_index = core_audio_devin->tic_counter;
2143 
2144   attack = core_audio_devin->attack[attack_index];
2145 
2146   g_rec_mutex_unlock(core_audio_devin_mutex);
2147 
2148   return(attack);
2149 }
2150 
2151 void*
ags_core_audio_devin_get_buffer(AgsSoundcard * soundcard)2152 ags_core_audio_devin_get_buffer(AgsSoundcard *soundcard)
2153 {
2154   AgsCoreAudioDevin *core_audio_devin;
2155 
2156   void *buffer;
2157 
2158   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
2159 
2160   if(ags_core_audio_devin_test_flags(core_audio_devin, AGS_CORE_AUDIO_DEVIN_BUFFER0)){
2161     buffer = core_audio_devin->buffer[0];
2162   }else if(ags_core_audio_devin_test_flags(core_audio_devin, AGS_CORE_AUDIO_DEVIN_BUFFER1)){
2163     buffer = core_audio_devin->buffer[1];
2164   }else if(ags_core_audio_devin_test_flags(core_audio_devin, AGS_CORE_AUDIO_DEVIN_BUFFER2)){
2165     buffer = core_audio_devin->buffer[2];
2166   }else if(ags_core_audio_devin_test_flags(core_audio_devin, AGS_CORE_AUDIO_DEVIN_BUFFER3)){
2167     buffer = core_audio_devin->buffer[3];
2168   }else if(ags_core_audio_devin_test_flags(core_audio_devin, AGS_CORE_AUDIO_DEVIN_BUFFER4)){
2169     buffer = core_audio_devin->buffer[4];
2170   }else if(ags_core_audio_devin_test_flags(core_audio_devin, AGS_CORE_AUDIO_DEVIN_BUFFER5)){
2171     buffer = core_audio_devin->buffer[5];
2172   }else if(ags_core_audio_devin_test_flags(core_audio_devin, AGS_CORE_AUDIO_DEVIN_BUFFER6)){
2173     buffer = core_audio_devin->buffer[6];
2174   }else if(ags_core_audio_devin_test_flags(core_audio_devin, AGS_CORE_AUDIO_DEVIN_BUFFER7)){
2175     buffer = core_audio_devin->buffer[7];
2176   }else{
2177     buffer = NULL;
2178   }
2179 
2180   return(buffer);
2181 }
2182 
2183 void*
ags_core_audio_devin_get_next_buffer(AgsSoundcard * soundcard)2184 ags_core_audio_devin_get_next_buffer(AgsSoundcard *soundcard)
2185 {
2186   AgsCoreAudioDevin *core_audio_devin;
2187 
2188   void *buffer;
2189 
2190   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
2191 
2192   //  g_message("next - 0x%0x", ((AGS_CORE_AUDIO_DEVIN_BUFFER0 |
2193   //				AGS_CORE_AUDIO_DEVIN_BUFFER1 |
2194   //				AGS_CORE_AUDIO_DEVIN_BUFFER2 |
2195   //				AGS_CORE_AUDIO_DEVIN_BUFFER3) & (core_audio_devin->flags)));
2196 
2197   if(ags_core_audio_devin_test_flags(core_audio_devin, AGS_CORE_AUDIO_DEVIN_BUFFER0)){
2198     buffer = core_audio_devin->buffer[1];
2199   }else if(ags_core_audio_devin_test_flags(core_audio_devin, AGS_CORE_AUDIO_DEVIN_BUFFER1)){
2200     buffer = core_audio_devin->buffer[2];
2201   }else if(ags_core_audio_devin_test_flags(core_audio_devin, AGS_CORE_AUDIO_DEVIN_BUFFER2)){
2202     buffer = core_audio_devin->buffer[3];
2203   }else if(ags_core_audio_devin_test_flags(core_audio_devin, AGS_CORE_AUDIO_DEVIN_BUFFER3)){
2204     buffer = core_audio_devin->buffer[4];
2205   }else if(ags_core_audio_devin_test_flags(core_audio_devin, AGS_CORE_AUDIO_DEVIN_BUFFER4)){
2206     buffer = core_audio_devin->buffer[5];
2207   }else if(ags_core_audio_devin_test_flags(core_audio_devin, AGS_CORE_AUDIO_DEVIN_BUFFER5)){
2208     buffer = core_audio_devin->buffer[6];
2209   }else if(ags_core_audio_devin_test_flags(core_audio_devin, AGS_CORE_AUDIO_DEVIN_BUFFER6)){
2210     buffer = core_audio_devin->buffer[7];
2211   }else if(ags_core_audio_devin_test_flags(core_audio_devin, AGS_CORE_AUDIO_DEVIN_BUFFER7)){
2212     buffer = core_audio_devin->buffer[0];
2213   }else{
2214     buffer = NULL;
2215   }
2216 
2217   return(buffer);
2218 }
2219 
2220 void*
ags_core_audio_devin_get_prev_buffer(AgsSoundcard * soundcard)2221 ags_core_audio_devin_get_prev_buffer(AgsSoundcard *soundcard)
2222 {
2223   AgsCoreAudioDevin *core_audio_devin;
2224 
2225   void *buffer;
2226 
2227   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
2228 
2229   if(ags_core_audio_devin_test_flags(core_audio_devin, AGS_CORE_AUDIO_DEVIN_BUFFER0)){
2230     buffer = core_audio_devin->buffer[7];
2231   }else if(ags_core_audio_devin_test_flags(core_audio_devin, AGS_CORE_AUDIO_DEVIN_BUFFER1)){
2232     buffer = core_audio_devin->buffer[0];
2233   }else if(ags_core_audio_devin_test_flags(core_audio_devin, AGS_CORE_AUDIO_DEVIN_BUFFER2)){
2234     buffer = core_audio_devin->buffer[1];
2235   }else if(ags_core_audio_devin_test_flags(core_audio_devin, AGS_CORE_AUDIO_DEVIN_BUFFER3)){
2236     buffer = core_audio_devin->buffer[2];
2237   }else if(ags_core_audio_devin_test_flags(core_audio_devin, AGS_CORE_AUDIO_DEVIN_BUFFER4)){
2238     buffer = core_audio_devin->buffer[3];
2239   }else if(ags_core_audio_devin_test_flags(core_audio_devin, AGS_CORE_AUDIO_DEVIN_BUFFER5)){
2240     buffer = core_audio_devin->buffer[4];
2241   }else if(ags_core_audio_devin_test_flags(core_audio_devin, AGS_CORE_AUDIO_DEVIN_BUFFER6)){
2242     buffer = core_audio_devin->buffer[5];
2243   }else if(ags_core_audio_devin_test_flags(core_audio_devin, AGS_CORE_AUDIO_DEVIN_BUFFER7)){
2244     buffer = core_audio_devin->buffer[6];
2245   }else{
2246     buffer = NULL;
2247   }
2248 
2249   return(buffer);
2250 }
2251 
2252 void
ags_core_audio_devin_lock_buffer(AgsSoundcard * soundcard,void * buffer)2253 ags_core_audio_devin_lock_buffer(AgsSoundcard *soundcard,
2254 				  void *buffer)
2255 {
2256   AgsCoreAudioDevin *core_audio_devin;
2257 
2258   GRecMutex *buffer_mutex;
2259 
2260   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
2261 
2262   buffer_mutex = NULL;
2263 
2264   if(core_audio_devin->buffer != NULL){
2265     if(buffer == core_audio_devin->buffer[0]){
2266       buffer_mutex = core_audio_devin->buffer_mutex[0];
2267     }else if(buffer == core_audio_devin->buffer[1]){
2268       buffer_mutex = core_audio_devin->buffer_mutex[1];
2269     }else if(buffer == core_audio_devin->buffer[2]){
2270       buffer_mutex = core_audio_devin->buffer_mutex[2];
2271     }else if(buffer == core_audio_devin->buffer[3]){
2272       buffer_mutex = core_audio_devin->buffer_mutex[3];
2273     }else if(buffer == core_audio_devin->buffer[4]){
2274       buffer_mutex = core_audio_devin->buffer_mutex[4];
2275     }else if(buffer == core_audio_devin->buffer[5]){
2276       buffer_mutex = core_audio_devin->buffer_mutex[5];
2277     }else if(buffer == core_audio_devin->buffer[6]){
2278       buffer_mutex = core_audio_devin->buffer_mutex[6];
2279     }else if(buffer == core_audio_devin->buffer[7]){
2280       buffer_mutex = core_audio_devin->buffer_mutex[7];
2281     }
2282   }
2283 
2284   if(buffer_mutex != NULL){
2285     g_rec_mutex_lock(buffer_mutex);
2286   }
2287 }
2288 
2289 void
ags_core_audio_devin_unlock_buffer(AgsSoundcard * soundcard,void * buffer)2290 ags_core_audio_devin_unlock_buffer(AgsSoundcard *soundcard,
2291 				    void *buffer)
2292 {
2293   AgsCoreAudioDevin *core_audio_devin;
2294 
2295   GRecMutex *buffer_mutex;
2296 
2297   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
2298 
2299   buffer_mutex = NULL;
2300 
2301   if(core_audio_devin->buffer != NULL){
2302     if(buffer == core_audio_devin->buffer[0]){
2303       buffer_mutex = core_audio_devin->buffer_mutex[0];
2304     }else if(buffer == core_audio_devin->buffer[1]){
2305       buffer_mutex = core_audio_devin->buffer_mutex[1];
2306     }else if(buffer == core_audio_devin->buffer[2]){
2307       buffer_mutex = core_audio_devin->buffer_mutex[2];
2308     }else if(buffer == core_audio_devin->buffer[3]){
2309       buffer_mutex = core_audio_devin->buffer_mutex[3];
2310     }else if(buffer == core_audio_devin->buffer[4]){
2311       buffer_mutex = core_audio_devin->buffer_mutex[4];
2312     }else if(buffer == core_audio_devin->buffer[5]){
2313       buffer_mutex = core_audio_devin->buffer_mutex[5];
2314     }else if(buffer == core_audio_devin->buffer[6]){
2315       buffer_mutex = core_audio_devin->buffer_mutex[6];
2316     }else if(buffer == core_audio_devin->buffer[7]){
2317       buffer_mutex = core_audio_devin->buffer_mutex[7];
2318     }
2319   }
2320 
2321   if(buffer_mutex != NULL){
2322     g_rec_mutex_unlock(buffer_mutex);
2323   }
2324 }
2325 
2326 guint
ags_core_audio_devin_get_delay_counter(AgsSoundcard * soundcard)2327 ags_core_audio_devin_get_delay_counter(AgsSoundcard *soundcard)
2328 {
2329   AgsCoreAudioDevin *core_audio_devin;
2330 
2331   guint delay_counter;
2332 
2333   GRecMutex *core_audio_devin_mutex;
2334 
2335   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
2336 
2337   /* get core_audio devin mutex */
2338   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
2339 
2340   /* delay counter */
2341   g_rec_mutex_lock(core_audio_devin_mutex);
2342 
2343   delay_counter = core_audio_devin->delay_counter;
2344 
2345   g_rec_mutex_unlock(core_audio_devin_mutex);
2346 
2347   return(delay_counter);
2348 }
2349 
2350 void
ags_core_audio_devin_set_note_offset(AgsSoundcard * soundcard,guint note_offset)2351 ags_core_audio_devin_set_note_offset(AgsSoundcard *soundcard,
2352 				     guint note_offset)
2353 {
2354   AgsCoreAudioDevin *core_audio_devin;
2355 
2356   GRecMutex *core_audio_devin_mutex;
2357 
2358   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
2359 
2360   /* get core_audio devin mutex */
2361   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
2362 
2363   /* set note offset */
2364   g_rec_mutex_lock(core_audio_devin_mutex);
2365 
2366   core_audio_devin->note_offset = note_offset;
2367 
2368   g_rec_mutex_unlock(core_audio_devin_mutex);
2369 }
2370 
2371 guint
ags_core_audio_devin_get_start_note_offset(AgsSoundcard * soundcard)2372 ags_core_audio_devin_get_start_note_offset(AgsSoundcard *soundcard)
2373 {
2374   AgsCoreAudioDevin *core_audio_devin;
2375 
2376   guint start_note_offset;
2377 
2378   GRecMutex *core_audio_devin_mutex;
2379 
2380   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
2381 
2382   /* get core_audio devin mutex */
2383   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
2384 
2385   /* set note offset */
2386   g_rec_mutex_lock(core_audio_devin_mutex);
2387 
2388   start_note_offset = core_audio_devin->start_note_offset;
2389 
2390   g_rec_mutex_unlock(core_audio_devin_mutex);
2391 
2392   return(start_note_offset);
2393 }
2394 
2395 void
ags_core_audio_devin_set_start_note_offset(AgsSoundcard * soundcard,guint start_note_offset)2396 ags_core_audio_devin_set_start_note_offset(AgsSoundcard *soundcard,
2397 					   guint start_note_offset)
2398 {
2399   AgsCoreAudioDevin *core_audio_devin;
2400 
2401   GRecMutex *core_audio_devin_mutex;
2402 
2403   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
2404 
2405   /* get core_audio devin mutex */
2406   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
2407 
2408   /* set note offset */
2409   g_rec_mutex_lock(core_audio_devin_mutex);
2410 
2411   core_audio_devin->start_note_offset = start_note_offset;
2412 
2413   g_rec_mutex_unlock(core_audio_devin_mutex);
2414 }
2415 
2416 guint
ags_core_audio_devin_get_note_offset(AgsSoundcard * soundcard)2417 ags_core_audio_devin_get_note_offset(AgsSoundcard *soundcard)
2418 {
2419   AgsCoreAudioDevin *core_audio_devin;
2420 
2421   guint note_offset;
2422 
2423   GRecMutex *core_audio_devin_mutex;
2424 
2425   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
2426 
2427   /* get core_audio devin mutex */
2428   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
2429 
2430   /* set note offset */
2431   g_rec_mutex_lock(core_audio_devin_mutex);
2432 
2433   note_offset = core_audio_devin->note_offset;
2434 
2435   g_rec_mutex_unlock(core_audio_devin_mutex);
2436 
2437   return(note_offset);
2438 }
2439 
2440 void
ags_core_audio_devin_set_note_offset_absolute(AgsSoundcard * soundcard,guint note_offset_absolute)2441 ags_core_audio_devin_set_note_offset_absolute(AgsSoundcard *soundcard,
2442 					      guint note_offset_absolute)
2443 {
2444   AgsCoreAudioDevin *core_audio_devin;
2445 
2446   GRecMutex *core_audio_devin_mutex;
2447 
2448   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
2449 
2450   /* get core_audio devin mutex */
2451   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
2452 
2453   /* set note offset */
2454   g_rec_mutex_lock(core_audio_devin_mutex);
2455 
2456   core_audio_devin->note_offset_absolute = note_offset_absolute;
2457 
2458   g_rec_mutex_unlock(core_audio_devin_mutex);
2459 }
2460 
2461 guint
ags_core_audio_devin_get_note_offset_absolute(AgsSoundcard * soundcard)2462 ags_core_audio_devin_get_note_offset_absolute(AgsSoundcard *soundcard)
2463 {
2464   AgsCoreAudioDevin *core_audio_devin;
2465 
2466   guint note_offset_absolute;
2467 
2468   GRecMutex *core_audio_devin_mutex;
2469 
2470   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
2471 
2472   /* get core_audio devin mutex */
2473   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
2474 
2475   /* set note offset */
2476   g_rec_mutex_lock(core_audio_devin_mutex);
2477 
2478   note_offset_absolute = core_audio_devin->note_offset_absolute;
2479 
2480   g_rec_mutex_unlock(core_audio_devin_mutex);
2481 
2482   return(note_offset_absolute);
2483 }
2484 
2485 void
ags_core_audio_devin_set_loop(AgsSoundcard * soundcard,guint loop_left,guint loop_right,gboolean do_loop)2486 ags_core_audio_devin_set_loop(AgsSoundcard *soundcard,
2487 			      guint loop_left, guint loop_right,
2488 			      gboolean do_loop)
2489 {
2490   AgsCoreAudioDevin *core_audio_devin;
2491 
2492   GRecMutex *core_audio_devin_mutex;
2493 
2494   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
2495 
2496   /* get core_audio devin mutex */
2497   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
2498 
2499   /* set loop */
2500   g_rec_mutex_lock(core_audio_devin_mutex);
2501 
2502   core_audio_devin->loop_left = loop_left;
2503   core_audio_devin->loop_right = loop_right;
2504   core_audio_devin->do_loop = do_loop;
2505 
2506   if(do_loop){
2507     core_audio_devin->loop_offset = core_audio_devin->note_offset;
2508   }
2509 
2510   g_rec_mutex_unlock(core_audio_devin_mutex);
2511 }
2512 
2513 void
ags_core_audio_devin_get_loop(AgsSoundcard * soundcard,guint * loop_left,guint * loop_right,gboolean * do_loop)2514 ags_core_audio_devin_get_loop(AgsSoundcard *soundcard,
2515 			      guint *loop_left, guint *loop_right,
2516 			      gboolean *do_loop)
2517 {
2518   AgsCoreAudioDevin *core_audio_devin;
2519 
2520   GRecMutex *core_audio_devin_mutex;
2521 
2522   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
2523 
2524   /* get core_audio devin mutex */
2525   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
2526 
2527   /* get loop */
2528   g_rec_mutex_lock(core_audio_devin_mutex);
2529 
2530   if(loop_left != NULL){
2531     *loop_left = core_audio_devin->loop_left;
2532   }
2533 
2534   if(loop_right != NULL){
2535     *loop_right = core_audio_devin->loop_right;
2536   }
2537 
2538   if(do_loop != NULL){
2539     *do_loop = core_audio_devin->do_loop;
2540   }
2541 
2542   g_rec_mutex_unlock(core_audio_devin_mutex);
2543 }
2544 
2545 guint
ags_core_audio_devin_get_loop_offset(AgsSoundcard * soundcard)2546 ags_core_audio_devin_get_loop_offset(AgsSoundcard *soundcard)
2547 {
2548   AgsCoreAudioDevin *core_audio_devin;
2549 
2550   guint loop_offset;
2551 
2552   GRecMutex *core_audio_devin_mutex;
2553 
2554   core_audio_devin = AGS_CORE_AUDIO_DEVIN(soundcard);
2555 
2556   /* get core_audio devin mutex */
2557   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
2558 
2559   /* get loop offset */
2560   g_rec_mutex_lock(core_audio_devin_mutex);
2561 
2562   loop_offset = core_audio_devin->loop_offset;
2563 
2564   g_rec_mutex_unlock(core_audio_devin_mutex);
2565 
2566   return(loop_offset);
2567 }
2568 
2569 
2570 /**
2571  * ags_core_audio_devin_switch_buffer_flag:
2572  * @core_audio_devin: an #AgsCoreAudioDevin
2573  *
2574  * The buffer flag indicates the currently played buffer.
2575  *
2576  * Since: 3.0.0
2577  */
2578 void
ags_core_audio_devin_switch_buffer_flag(AgsCoreAudioDevin * core_audio_devin)2579 ags_core_audio_devin_switch_buffer_flag(AgsCoreAudioDevin *core_audio_devin)
2580 {
2581   GRecMutex *core_audio_devin_mutex;
2582 
2583   if(!AGS_IS_CORE_AUDIO_DEVIN(core_audio_devin)){
2584     return;
2585   }
2586 
2587   /* get core_audio devin mutex */
2588   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
2589 
2590   /* switch buffer flag */
2591   g_rec_mutex_lock(core_audio_devin_mutex);
2592 
2593   if((AGS_CORE_AUDIO_DEVIN_BUFFER0 & (core_audio_devin->flags)) != 0){
2594     core_audio_devin->flags &= (~AGS_CORE_AUDIO_DEVIN_BUFFER0);
2595     core_audio_devin->flags |= AGS_CORE_AUDIO_DEVIN_BUFFER1;
2596   }else if((AGS_CORE_AUDIO_DEVIN_BUFFER1 & (core_audio_devin->flags)) != 0){
2597     core_audio_devin->flags &= (~AGS_CORE_AUDIO_DEVIN_BUFFER1);
2598     core_audio_devin->flags |= AGS_CORE_AUDIO_DEVIN_BUFFER2;
2599   }else if((AGS_CORE_AUDIO_DEVIN_BUFFER2 & (core_audio_devin->flags)) != 0){
2600     core_audio_devin->flags &= (~AGS_CORE_AUDIO_DEVIN_BUFFER2);
2601     core_audio_devin->flags |= AGS_CORE_AUDIO_DEVIN_BUFFER3;
2602   }else if((AGS_CORE_AUDIO_DEVIN_BUFFER3 & (core_audio_devin->flags)) != 0){
2603     core_audio_devin->flags &= (~AGS_CORE_AUDIO_DEVIN_BUFFER3);
2604     core_audio_devin->flags |= AGS_CORE_AUDIO_DEVIN_BUFFER4;
2605   }else if((AGS_CORE_AUDIO_DEVIN_BUFFER4 & (core_audio_devin->flags)) != 0){
2606     core_audio_devin->flags &= (~AGS_CORE_AUDIO_DEVIN_BUFFER4);
2607     core_audio_devin->flags |= AGS_CORE_AUDIO_DEVIN_BUFFER5;
2608   }else if((AGS_CORE_AUDIO_DEVIN_BUFFER5 & (core_audio_devin->flags)) != 0){
2609     core_audio_devin->flags &= (~AGS_CORE_AUDIO_DEVIN_BUFFER5);
2610     core_audio_devin->flags |= AGS_CORE_AUDIO_DEVIN_BUFFER6;
2611   }else if((AGS_CORE_AUDIO_DEVIN_BUFFER6 & (core_audio_devin->flags)) != 0){
2612     core_audio_devin->flags &= (~AGS_CORE_AUDIO_DEVIN_BUFFER6);
2613     core_audio_devin->flags |= AGS_CORE_AUDIO_DEVIN_BUFFER7;
2614   }else if((AGS_CORE_AUDIO_DEVIN_BUFFER7 & (core_audio_devin->flags)) != 0){
2615     core_audio_devin->flags &= (~AGS_CORE_AUDIO_DEVIN_BUFFER7);
2616     core_audio_devin->flags |= AGS_CORE_AUDIO_DEVIN_BUFFER0;
2617   }
2618 
2619   g_rec_mutex_unlock(core_audio_devin_mutex);
2620 }
2621 
2622 /**
2623  * ags_core_audio_devin_adjust_delay_and_attack:
2624  * @core_audio_devin: the #AgsCoreAudioDevin
2625  *
2626  * Calculate delay and attack and reset it.
2627  *
2628  * Since: 3.0.0
2629  */
2630 void
ags_core_audio_devin_adjust_delay_and_attack(AgsCoreAudioDevin * core_audio_devin)2631 ags_core_audio_devin_adjust_delay_and_attack(AgsCoreAudioDevin *core_audio_devin)
2632 {
2633   if(!AGS_IS_CORE_AUDIO_DEVIN(core_audio_devin)){
2634     return;
2635   }
2636 
2637   ags_soundcard_util_adjust_delay_and_attack(core_audio_devin);
2638 }
2639 
2640 /**
2641  * ags_core_audio_devin_realloc_buffer:
2642  * @core_audio_devin: the #AgsCoreAudioDevin
2643  *
2644  * Reallocate the internal audio buffer.
2645  *
2646  * Since: 3.0.0
2647  */
2648 void
ags_core_audio_devin_realloc_buffer(AgsCoreAudioDevin * core_audio_devin)2649 ags_core_audio_devin_realloc_buffer(AgsCoreAudioDevin *core_audio_devin)
2650 {
2651   guint pcm_channels;
2652   guint buffer_size;
2653   guint format;
2654   guint word_size;
2655 
2656   GRecMutex *core_audio_devin_mutex;
2657 
2658   if(!AGS_IS_CORE_AUDIO_DEVIN(core_audio_devin)){
2659     return;
2660   }
2661 
2662   /* get core_audio devin mutex */
2663   core_audio_devin_mutex = AGS_CORE_AUDIO_DEVIN_GET_OBJ_MUTEX(core_audio_devin);
2664 
2665   /* get word size */
2666   g_rec_mutex_lock(core_audio_devin_mutex);
2667 
2668   pcm_channels = core_audio_devin->pcm_channels;
2669   buffer_size = core_audio_devin->buffer_size;
2670 
2671   format = core_audio_devin->format;
2672 
2673   g_rec_mutex_unlock(core_audio_devin_mutex);
2674 
2675   switch(format){
2676   case AGS_SOUNDCARD_SIGNED_16_BIT:
2677     {
2678       word_size = sizeof(gint16);
2679     }
2680     break;
2681   case AGS_SOUNDCARD_SIGNED_24_BIT:
2682     {
2683       word_size = sizeof(gint32);
2684     }
2685     break;
2686   case AGS_SOUNDCARD_SIGNED_32_BIT:
2687     {
2688       word_size = sizeof(gint32);
2689     }
2690     break;
2691   default:
2692     g_warning("ags_core_audio_devin_realloc_buffer(): unsupported word size");
2693     return;
2694   }
2695 
2696   /* AGS_CORE_AUDIO_DEVIN_BUFFER_0 */
2697   if(core_audio_devin->buffer[0] != NULL){
2698     free(core_audio_devin->buffer[0]);
2699   }
2700 
2701   core_audio_devin->buffer[0] = (void *) malloc(pcm_channels * buffer_size * word_size);
2702 
2703   /* AGS_CORE_AUDIO_DEVIN_BUFFER_1 */
2704   if(core_audio_devin->buffer[1] != NULL){
2705     free(core_audio_devin->buffer[1]);
2706   }
2707 
2708   core_audio_devin->buffer[1] = (void *) malloc(pcm_channels * buffer_size * word_size);
2709 
2710   /* AGS_CORE_AUDIO_DEVIN_BUFFER_2 */
2711   if(core_audio_devin->buffer[2] != NULL){
2712     free(core_audio_devin->buffer[2]);
2713   }
2714 
2715   core_audio_devin->buffer[2] = (void *) malloc(pcm_channels * buffer_size * word_size);
2716 
2717   /* AGS_CORE_AUDIO_DEVIN_BUFFER_3 */
2718   if(core_audio_devin->buffer[3] != NULL){
2719     free(core_audio_devin->buffer[3]);
2720   }
2721 
2722   core_audio_devin->buffer[3] = (void *) malloc(pcm_channels * buffer_size * word_size);
2723 
2724   /* AGS_CORE_AUDIO_DEVIN_BUFFER_4 */
2725   if(core_audio_devin->buffer[4] != NULL){
2726     free(core_audio_devin->buffer[4]);
2727   }
2728 
2729   core_audio_devin->buffer[4] = (void *) malloc(pcm_channels * buffer_size * word_size);
2730 
2731   /* AGS_CORE_AUDIO_DEVIN_BUFFER_5 */
2732   if(core_audio_devin->buffer[5] != NULL){
2733     free(core_audio_devin->buffer[5]);
2734   }
2735 
2736   core_audio_devin->buffer[5] = (void *) malloc(pcm_channels * buffer_size * word_size);
2737 
2738   /* AGS_CORE_AUDIO_DEVIN_BUFFER_6 */
2739   if(core_audio_devin->buffer[6] != NULL){
2740     free(core_audio_devin->buffer[6]);
2741   }
2742 
2743   core_audio_devin->buffer[6] = (void *) malloc(pcm_channels * buffer_size * word_size);
2744 
2745   /* AGS_CORE_AUDIO_DEVIN_BUFFER_7 */
2746   if(core_audio_devin->buffer[7] != NULL){
2747     free(core_audio_devin->buffer[7]);
2748   }
2749 
2750   core_audio_devin->buffer[7] = (void *) malloc(pcm_channels * buffer_size * word_size);
2751 }
2752 
2753 /**
2754  * ags_core_audio_devin_new:
2755  *
2756  * Creates a new instance of #AgsCoreAudioDevin.
2757  *
2758  * Returns: a new #AgsCoreAudioDevin
2759  *
2760  * Since: 3.0.0
2761  */
2762 AgsCoreAudioDevin*
ags_core_audio_devin_new()2763 ags_core_audio_devin_new()
2764 {
2765   AgsCoreAudioDevin *core_audio_devin;
2766 
2767   core_audio_devin = (AgsCoreAudioDevin *) g_object_new(AGS_TYPE_CORE_AUDIO_DEVIN,
2768 							NULL);
2769 
2770   return(core_audio_devin);
2771 }
2772