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_devout.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_devout_class_init(AgsCoreAudioDevoutClass *core_audio_devout);
44 void ags_core_audio_devout_connectable_interface_init(AgsConnectableInterface *connectable);
45 void ags_core_audio_devout_soundcard_interface_init(AgsSoundcardInterface *soundcard);
46 void ags_core_audio_devout_init(AgsCoreAudioDevout *core_audio_devout);
47 void ags_core_audio_devout_set_property(GObject *gobject,
48 					guint prop_id,
49 					const GValue *value,
50 					GParamSpec *param_spec);
51 void ags_core_audio_devout_get_property(GObject *gobject,
52 					guint prop_id,
53 					GValue *value,
54 					GParamSpec *param_spec);
55 void ags_core_audio_devout_dispose(GObject *gobject);
56 void ags_core_audio_devout_finalize(GObject *gobject);
57 
58 AgsUUID* ags_core_audio_devout_get_uuid(AgsConnectable *connectable);
59 gboolean ags_core_audio_devout_has_resource(AgsConnectable *connectable);
60 gboolean ags_core_audio_devout_is_ready(AgsConnectable *connectable);
61 void ags_core_audio_devout_add_to_registry(AgsConnectable *connectable);
62 void ags_core_audio_devout_remove_from_registry(AgsConnectable *connectable);
63 xmlNode* ags_core_audio_devout_list_resource(AgsConnectable *connectable);
64 xmlNode* ags_core_audio_devout_xml_compose(AgsConnectable *connectable);
65 void ags_core_audio_devout_xml_parse(AgsConnectable *connectable,
66 			       xmlNode *node);
67 gboolean ags_core_audio_devout_is_connected(AgsConnectable *connectable);
68 void ags_core_audio_devout_connect(AgsConnectable *connectable);
69 void ags_core_audio_devout_disconnect(AgsConnectable *connectable);
70 
71 void ags_core_audio_devout_set_device(AgsSoundcard *soundcard,
72 				      gchar *device);
73 gchar* ags_core_audio_devout_get_device(AgsSoundcard *soundcard);
74 
75 void ags_core_audio_devout_set_presets(AgsSoundcard *soundcard,
76 				       guint channels,
77 				       guint rate,
78 				       guint buffer_size,
79 				       guint format);
80 void ags_core_audio_devout_get_presets(AgsSoundcard *soundcard,
81 				       guint *channels,
82 				       guint *rate,
83 				       guint *buffer_size,
84 				       guint *format);
85 
86 void ags_core_audio_devout_list_cards(AgsSoundcard *soundcard,
87 				      GList **card_id, GList **card_name);
88 void ags_core_audio_devout_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_devout_get_capability(AgsSoundcard *soundcard);
94 
95 gboolean ags_core_audio_devout_is_starting(AgsSoundcard *soundcard);
96 gboolean ags_core_audio_devout_is_playing(AgsSoundcard *soundcard);
97 
98 gchar* ags_core_audio_devout_get_uptime(AgsSoundcard *soundcard);
99 
100 void ags_core_audio_devout_port_init(AgsSoundcard *soundcard,
101 				     GError **error);
102 void ags_core_audio_devout_port_play(AgsSoundcard *soundcard,
103 				     GError **error);
104 void ags_core_audio_devout_port_free(AgsSoundcard *soundcard);
105 
106 void ags_core_audio_devout_tic(AgsSoundcard *soundcard);
107 void ags_core_audio_devout_offset_changed(AgsSoundcard *soundcard,
108 					  guint note_offset);
109 
110 void ags_core_audio_devout_set_bpm(AgsSoundcard *soundcard,
111 				   gdouble bpm);
112 gdouble ags_core_audio_devout_get_bpm(AgsSoundcard *soundcard);
113 
114 void ags_core_audio_devout_set_delay_factor(AgsSoundcard *soundcard,
115 					    gdouble delay_factor);
116 gdouble ags_core_audio_devout_get_delay_factor(AgsSoundcard *soundcard);
117 
118 gdouble ags_core_audio_devout_get_absolute_delay(AgsSoundcard *soundcard);
119 
120 gdouble ags_core_audio_devout_get_delay(AgsSoundcard *soundcard);
121 guint ags_core_audio_devout_get_attack(AgsSoundcard *soundcard);
122 
123 void* ags_core_audio_devout_get_buffer(AgsSoundcard *soundcard);
124 void* ags_core_audio_devout_get_next_buffer(AgsSoundcard *soundcard);
125 void* ags_core_audio_devout_get_prev_buffer(AgsSoundcard *soundcard);
126 
127 void ags_core_audio_devout_lock_buffer(AgsSoundcard *soundcard,
128 				       void *buffer);
129 void ags_core_audio_devout_unlock_buffer(AgsSoundcard *soundcard,
130 					 void *buffer);
131 
132 guint ags_core_audio_devout_get_delay_counter(AgsSoundcard *soundcard);
133 
134 void ags_core_audio_devout_set_start_note_offset(AgsSoundcard *soundcard,
135 						 guint start_note_offset);
136 guint ags_core_audio_devout_get_start_note_offset(AgsSoundcard *soundcard);
137 
138 void ags_core_audio_devout_set_note_offset(AgsSoundcard *soundcard,
139 					   guint note_offset);
140 guint ags_core_audio_devout_get_note_offset(AgsSoundcard *soundcard);
141 
142 void ags_core_audio_devout_set_note_offset_absolute(AgsSoundcard *soundcard,
143 						    guint note_offset);
144 guint ags_core_audio_devout_get_note_offset_absolute(AgsSoundcard *soundcard);
145 
146 void ags_core_audio_devout_set_loop(AgsSoundcard *soundcard,
147 				    guint loop_left, guint loop_right,
148 				    gboolean do_loop);
149 void ags_core_audio_devout_get_loop(AgsSoundcard *soundcard,
150 				    guint *loop_left, guint *loop_right,
151 				    gboolean *do_loop);
152 
153 guint ags_core_audio_devout_get_loop_offset(AgsSoundcard *soundcard);
154 
155 guint ags_core_audio_devout_get_sub_block_count(AgsSoundcard *soundcard);
156 
157 gboolean ags_core_audio_devout_trylock_sub_block(AgsSoundcard *soundcard,
158 						 void *buffer, guint sub_block);
159 void ags_core_audio_devout_unlock_sub_block(AgsSoundcard *soundcard,
160 					    void *buffer, guint sub_block);
161 
162 /**
163  * SECTION:ags_core_audio_devout
164  * @short_description: Output to soundcard
165  * @title: AgsCoreAudioDevout
166  * @section_id:
167  * @include: ags/audio/core-audio/ags_core_audio_devout.h
168  *
169  * #AgsCoreAudioDevout represents a soundcard and supports output.
170  */
171 
172 enum{
173   PROP_0,
174   PROP_DEVICE,
175   PROP_DSP_CHANNELS,
176   PROP_PCM_CHANNELS,
177   PROP_FORMAT,
178   PROP_BUFFER_SIZE,
179   PROP_SAMPLERATE,
180   PROP_BUFFER,
181   PROP_BPM,
182   PROP_DELAY_FACTOR,
183   PROP_ATTACK,
184   PROP_CORE_AUDIO_CLIENT,
185   PROP_CORE_AUDIO_PORT,
186   PROP_CHANNEL,
187 };
188 
189 static gpointer ags_core_audio_devout_parent_class = NULL;
190 
191 GType
ags_core_audio_devout_get_type(void)192 ags_core_audio_devout_get_type (void)
193 {
194   static volatile gsize g_define_type_id__volatile = 0;
195 
196   if(g_once_init_enter (&g_define_type_id__volatile)){
197     GType ags_type_core_audio_devout = 0;
198 
199     static const GTypeInfo ags_core_audio_devout_info = {
200       sizeof(AgsCoreAudioDevoutClass),
201       NULL, /* base_init */
202       NULL, /* base_finalize */
203       (GClassInitFunc) ags_core_audio_devout_class_init,
204       NULL, /* class_finalize */
205       NULL, /* class_data */
206       sizeof(AgsCoreAudioDevout),
207       0,    /* n_preallocs */
208       (GInstanceInitFunc) ags_core_audio_devout_init,
209     };
210 
211     static const GInterfaceInfo ags_connectable_interface_info = {
212       (GInterfaceInitFunc) ags_core_audio_devout_connectable_interface_init,
213       NULL, /* interface_finalize */
214       NULL, /* interface_data */
215     };
216 
217     static const GInterfaceInfo ags_soundcard_interface_info = {
218       (GInterfaceInitFunc) ags_core_audio_devout_soundcard_interface_init,
219       NULL, /* interface_finalize */
220       NULL, /* interface_data */
221     };
222 
223     ags_type_core_audio_devout = g_type_register_static(G_TYPE_OBJECT,
224 							"AgsCoreAudioDevout",
225 							&ags_core_audio_devout_info,
226 							0);
227 
228     g_type_add_interface_static(ags_type_core_audio_devout,
229 				AGS_TYPE_CONNECTABLE,
230 				&ags_connectable_interface_info);
231 
232     g_type_add_interface_static(ags_type_core_audio_devout,
233 				AGS_TYPE_SOUNDCARD,
234 				&ags_soundcard_interface_info);
235 
236     g_once_init_leave(&g_define_type_id__volatile, ags_type_core_audio_devout);
237   }
238 
239   return g_define_type_id__volatile;
240 }
241 
242 void
ags_core_audio_devout_class_init(AgsCoreAudioDevoutClass * core_audio_devout)243 ags_core_audio_devout_class_init(AgsCoreAudioDevoutClass *core_audio_devout)
244 {
245   GObjectClass *gobject;
246   GParamSpec *param_spec;
247 
248   ags_core_audio_devout_parent_class = g_type_class_peek_parent(core_audio_devout);
249 
250   /* GObjectClass */
251   gobject = (GObjectClass *) core_audio_devout;
252 
253   gobject->set_property = ags_core_audio_devout_set_property;
254   gobject->get_property = ags_core_audio_devout_get_property;
255 
256   gobject->dispose = ags_core_audio_devout_dispose;
257   gobject->finalize = ags_core_audio_devout_finalize;
258 
259   /* properties */
260   /**
261    * AgsCoreAudioDevout:device:
262    *
263    * The core audio soundcard indentifier
264    *
265    * Since: 3.0.0
266    */
267   param_spec = g_param_spec_string("device",
268 				   i18n_pspec("the device identifier"),
269 				   i18n_pspec("The device to perform output to"),
270 				   "ags-core-audio-devout-0",
271 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
272   g_object_class_install_property(gobject,
273 				  PROP_DEVICE,
274 				  param_spec);
275 
276   /**
277    * AgsCoreAudioDevout:dsp-channels:
278    *
279    * The dsp channel count
280    *
281    * Since: 3.0.0
282    */
283   param_spec = g_param_spec_uint("dsp-channels",
284 				 i18n_pspec("count of DSP channels"),
285 				 i18n_pspec("The count of DSP channels to use"),
286 				 1,
287 				 64,
288 				 2,
289 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
290   g_object_class_install_property(gobject,
291 				  PROP_DSP_CHANNELS,
292 				  param_spec);
293 
294   /**
295    * AgsCoreAudioDevout:pcm-channels:
296    *
297    * The pcm channel count
298    *
299    * Since: 3.0.0
300    */
301   param_spec = g_param_spec_uint("pcm-channels",
302 				 i18n_pspec("count of PCM channels"),
303 				 i18n_pspec("The count of PCM channels to use"),
304 				 1,
305 				 64,
306 				 2,
307 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
308   g_object_class_install_property(gobject,
309 				  PROP_PCM_CHANNELS,
310 				  param_spec);
311 
312   /**
313    * AgsCoreAudioDevout:format:
314    *
315    * The precision of the buffer
316    *
317    * Since: 3.0.0
318    */
319   param_spec = g_param_spec_uint("format",
320 				 i18n_pspec("precision of buffer"),
321 				 i18n_pspec("The precision to use for a frame"),
322 				 1,
323 				 64,
324 				 AGS_SOUNDCARD_DEFAULT_FORMAT,
325 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
326   g_object_class_install_property(gobject,
327 				  PROP_FORMAT,
328 				  param_spec);
329 
330   /**
331    * AgsCoreAudioDevout:buffer-size:
332    *
333    * The buffer size
334    *
335    * Since: 3.0.0
336    */
337   param_spec = g_param_spec_uint("buffer-size",
338 				 i18n_pspec("frame count of a buffer"),
339 				 i18n_pspec("The count of frames a buffer contains"),
340 				 1,
341 				 44100,
342 				 940,
343 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
344   g_object_class_install_property(gobject,
345 				  PROP_BUFFER_SIZE,
346 				  param_spec);
347 
348   /**
349    * AgsCoreAudioDevout:samplerate:
350    *
351    * The samplerate
352    *
353    * Since: 3.0.0
354    */
355   param_spec = g_param_spec_uint("samplerate",
356 				 i18n_pspec("frames per second"),
357 				 i18n_pspec("The frames count played during a second"),
358 				 8000,
359 				 96000,
360 				 44100,
361 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
362   g_object_class_install_property(gobject,
363 				  PROP_SAMPLERATE,
364 				  param_spec);
365 
366   /**
367    * AgsCoreAudioDevout:buffer:
368    *
369    * The buffer
370    *
371    * Since: 3.0.0
372    */
373   param_spec = g_param_spec_pointer("buffer",
374 				    i18n_pspec("the buffer"),
375 				    i18n_pspec("The buffer to play"),
376 				    G_PARAM_READABLE);
377   g_object_class_install_property(gobject,
378 				  PROP_BUFFER,
379 				  param_spec);
380 
381   /**
382    * AgsCoreAudioDevout:bpm:
383    *
384    * Beats per minute
385    *
386    * Since: 3.0.0
387    */
388   param_spec = g_param_spec_double("bpm",
389 				   i18n_pspec("beats per minute"),
390 				   i18n_pspec("Beats per minute to use"),
391 				   1.0,
392 				   240.0,
393 				   120.0,
394 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
395   g_object_class_install_property(gobject,
396 				  PROP_BPM,
397 				  param_spec);
398 
399   /**
400    * AgsCoreAudioDevout:delay-factor:
401    *
402    * tact
403    *
404    * Since: 3.0.0
405    */
406   param_spec = g_param_spec_double("delay-factor",
407 				   i18n_pspec("delay factor"),
408 				   i18n_pspec("The delay factor"),
409 				   0.0,
410 				   16.0,
411 				   1.0,
412 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
413   g_object_class_install_property(gobject,
414 				  PROP_DELAY_FACTOR,
415 				  param_spec);
416 
417   /**
418    * AgsCoreAudioDevout:attack:
419    *
420    * Attack of the buffer
421    *
422    * Since: 3.0.0
423    */
424   param_spec = g_param_spec_pointer("attack",
425 				    i18n_pspec("attack of buffer"),
426 				    i18n_pspec("The attack to use for the buffer"),
427 				    G_PARAM_READABLE);
428   g_object_class_install_property(gobject,
429 				  PROP_ATTACK,
430 				  param_spec);
431 
432 
433   /**
434    * AgsCoreAudioDevout:core-audio-client:
435    *
436    * The assigned #AgsCoreAudioClient
437    *
438    * Since: 3.0.0
439    */
440   param_spec = g_param_spec_object("core-audio-client",
441 				   i18n_pspec("core audio client object"),
442 				   i18n_pspec("The core audio client object"),
443 				   AGS_TYPE_CORE_AUDIO_CLIENT,
444 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
445   g_object_class_install_property(gobject,
446 				  PROP_CORE_AUDIO_CLIENT,
447 				  param_spec);
448 
449   /**
450    * AgsCoreAudioDevout:core-audio-port:
451    *
452    * The assigned #AgsCoreAudioPort
453    *
454    * Since: 3.0.0
455    */
456   param_spec = g_param_spec_pointer("core-audio-port",
457 				    i18n_pspec("core audio port object"),
458 				    i18n_pspec("The core audio port object"),
459 				    G_PARAM_READABLE | G_PARAM_WRITABLE);
460   g_object_class_install_property(gobject,
461 				  PROP_CORE_AUDIO_PORT,
462 				  param_spec);
463 }
464 
465 GQuark
ags_core_audio_devout_error_quark()466 ags_core_audio_devout_error_quark()
467 {
468   return(g_quark_from_static_string("ags-core_audio_devout-error-quark"));
469 }
470 
471 void
ags_core_audio_devout_connectable_interface_init(AgsConnectableInterface * connectable)472 ags_core_audio_devout_connectable_interface_init(AgsConnectableInterface *connectable)
473 {
474   connectable->get_uuid = ags_core_audio_devout_get_uuid;
475   connectable->has_resource = ags_core_audio_devout_has_resource;
476 
477   connectable->is_ready = ags_core_audio_devout_is_ready;
478   connectable->add_to_registry = ags_core_audio_devout_add_to_registry;
479   connectable->remove_from_registry = ags_core_audio_devout_remove_from_registry;
480 
481   connectable->list_resource = ags_core_audio_devout_list_resource;
482   connectable->xml_compose = ags_core_audio_devout_xml_compose;
483   connectable->xml_parse = ags_core_audio_devout_xml_parse;
484 
485   connectable->is_connected = ags_core_audio_devout_is_connected;
486   connectable->connect = ags_core_audio_devout_connect;
487   connectable->disconnect = ags_core_audio_devout_disconnect;
488 
489   connectable->connect_connection = NULL;
490   connectable->disconnect_connection = NULL;
491 }
492 
493 void
ags_core_audio_devout_soundcard_interface_init(AgsSoundcardInterface * soundcard)494 ags_core_audio_devout_soundcard_interface_init(AgsSoundcardInterface *soundcard)
495 {
496   soundcard->set_device = ags_core_audio_devout_set_device;
497   soundcard->get_device = ags_core_audio_devout_get_device;
498 
499   soundcard->set_presets = ags_core_audio_devout_set_presets;
500   soundcard->get_presets = ags_core_audio_devout_get_presets;
501 
502   soundcard->list_cards = ags_core_audio_devout_list_cards;
503   soundcard->pcm_info = ags_core_audio_devout_pcm_info;
504   soundcard->get_capability = ags_core_audio_devout_get_capability;
505 
506   soundcard->is_available = NULL;
507 
508   soundcard->is_starting =  ags_core_audio_devout_is_starting;
509   soundcard->is_playing = ags_core_audio_devout_is_playing;
510   soundcard->is_recording = NULL;
511 
512   soundcard->get_uptime = ags_core_audio_devout_get_uptime;
513 
514   soundcard->play_init = ags_core_audio_devout_port_init;
515   soundcard->play = ags_core_audio_devout_port_play;
516 
517   soundcard->record_init = NULL;
518   soundcard->record = NULL;
519 
520   soundcard->stop = ags_core_audio_devout_port_free;
521 
522   soundcard->tic = ags_core_audio_devout_tic;
523   soundcard->offset_changed = ags_core_audio_devout_offset_changed;
524 
525   soundcard->set_bpm = ags_core_audio_devout_set_bpm;
526   soundcard->get_bpm = ags_core_audio_devout_get_bpm;
527 
528   soundcard->set_delay_factor = ags_core_audio_devout_set_delay_factor;
529   soundcard->get_delay_factor = ags_core_audio_devout_get_delay_factor;
530 
531   soundcard->get_absolute_delay = ags_core_audio_devout_get_absolute_delay;
532 
533   soundcard->get_delay = ags_core_audio_devout_get_delay;
534   soundcard->get_attack = ags_core_audio_devout_get_attack;
535 
536   soundcard->get_buffer = ags_core_audio_devout_get_buffer;
537   soundcard->get_next_buffer = ags_core_audio_devout_get_next_buffer;
538   soundcard->get_prev_buffer = ags_core_audio_devout_get_prev_buffer;
539 
540   soundcard->lock_buffer = ags_core_audio_devout_lock_buffer;
541   soundcard->unlock_buffer = ags_core_audio_devout_unlock_buffer;
542 
543   soundcard->get_delay_counter = ags_core_audio_devout_get_delay_counter;
544 
545   soundcard->set_start_note_offset = ags_core_audio_devout_set_start_note_offset;
546   soundcard->get_start_note_offset = ags_core_audio_devout_get_start_note_offset;
547 
548   soundcard->set_note_offset = ags_core_audio_devout_set_note_offset;
549   soundcard->get_note_offset = ags_core_audio_devout_get_note_offset;
550 
551   soundcard->set_note_offset_absolute = ags_core_audio_devout_set_note_offset_absolute;
552   soundcard->get_note_offset_absolute = ags_core_audio_devout_get_note_offset_absolute;
553 
554   soundcard->set_loop = ags_core_audio_devout_set_loop;
555   soundcard->get_loop = ags_core_audio_devout_get_loop;
556 
557   soundcard->get_loop_offset = ags_core_audio_devout_get_loop_offset;
558 
559   soundcard->get_sub_block_count = ags_core_audio_devout_get_sub_block_count;
560 
561   soundcard->trylock_sub_block = ags_core_audio_devout_trylock_sub_block;
562   soundcard->unlock_sub_block = ags_core_audio_devout_unlock_sub_block;
563 }
564 
565 void
ags_core_audio_devout_init(AgsCoreAudioDevout * core_audio_devout)566 ags_core_audio_devout_init(AgsCoreAudioDevout *core_audio_devout)
567 {
568   AgsConfig *config;
569 
570   gchar *str;
571   gchar *segmentation;
572 
573   guint denominator, numerator;
574   guint i;
575 
576   /* flags */
577   core_audio_devout->flags = 0;
578   g_atomic_int_set(&(core_audio_devout->sync_flags),
579 		   AGS_CORE_AUDIO_DEVOUT_PASS_THROUGH);
580 
581   /* devout mutex */
582   g_rec_mutex_init(&(core_audio_devout->obj_mutex));
583 
584   /* uuid */
585   core_audio_devout->uuid = ags_uuid_alloc();
586   ags_uuid_generate(core_audio_devout->uuid);
587 
588   /* presets */
589   config = ags_config_get_instance();
590 
591   core_audio_devout->dsp_channels = ags_soundcard_helper_config_get_dsp_channels(config);
592   core_audio_devout->pcm_channels = ags_soundcard_helper_config_get_pcm_channels(config);
593 
594   core_audio_devout->samplerate = ags_soundcard_helper_config_get_samplerate(config);
595   core_audio_devout->buffer_size = ags_soundcard_helper_config_get_buffer_size(config);
596   core_audio_devout->format = ags_soundcard_helper_config_get_format(config);
597 
598   /*  */
599   core_audio_devout->card_uri = NULL;
600   core_audio_devout->core_audio_client = NULL;
601 
602   core_audio_devout->port_name = NULL;
603   core_audio_devout->core_audio_port = NULL;
604 
605   /* buffer */
606   core_audio_devout->buffer_mutex = (GRecMutex **) malloc(8 * sizeof(GRecMutex *));
607 
608   for(i = 0; i < 8; i++){
609     core_audio_devout->buffer_mutex[i] = (GRecMutex *) malloc(sizeof(GRecMutex));
610 
611     g_rec_mutex_init(core_audio_devout->buffer_mutex[i]);
612   }
613 
614   core_audio_devout->sub_block_count = AGS_SOUNDCARD_DEFAULT_SUB_BLOCK_COUNT;
615   core_audio_devout->sub_block_mutex = (GRecMutex **) malloc(8 * core_audio_devout->sub_block_count * core_audio_devout->pcm_channels * sizeof(GRecMutex *));
616 
617   for(i = 0; i < 8 * core_audio_devout->sub_block_count * core_audio_devout->pcm_channels; i++){
618     core_audio_devout->sub_block_mutex[i] = (GRecMutex *) malloc(sizeof(GRecMutex));
619 
620     g_rec_mutex_init(core_audio_devout->sub_block_mutex[i]);
621   }
622 
623   core_audio_devout->buffer = (void **) malloc(8 * sizeof(void*));
624 
625   core_audio_devout->buffer[0] = NULL;
626   core_audio_devout->buffer[1] = NULL;
627   core_audio_devout->buffer[2] = NULL;
628   core_audio_devout->buffer[3] = NULL;
629   core_audio_devout->buffer[4] = NULL;
630   core_audio_devout->buffer[5] = NULL;
631   core_audio_devout->buffer[6] = NULL;
632   core_audio_devout->buffer[7] = NULL;
633 
634   ags_core_audio_devout_realloc_buffer(core_audio_devout);
635 
636   /* bpm */
637   core_audio_devout->bpm = AGS_SOUNDCARD_DEFAULT_BPM;
638 
639   /* delay factor */
640   core_audio_devout->delay_factor = AGS_SOUNDCARD_DEFAULT_DELAY_FACTOR;
641 
642   /* segmentation */
643   segmentation = ags_config_get_value(config,
644 				      AGS_CONFIG_GENERIC,
645 				      "segmentation");
646 
647   if(segmentation != NULL){
648     sscanf(segmentation, "%d/%d",
649 	   &denominator,
650 	   &numerator);
651 
652     core_audio_devout->delay_factor = 1.0 / numerator * (numerator / denominator);
653 
654     g_free(segmentation);
655   }
656 
657   /* delay and attack */
658   core_audio_devout->delay = (gdouble *) malloc((int) 2 * AGS_SOUNDCARD_DEFAULT_PERIOD *
659 						sizeof(gdouble));
660 
661   core_audio_devout->attack = (guint *) malloc((int) 2 * AGS_SOUNDCARD_DEFAULT_PERIOD *
662 					       sizeof(guint));
663 
664   ags_core_audio_devout_adjust_delay_and_attack(core_audio_devout);
665 
666   /* counters */
667   core_audio_devout->tact_counter = 0.0;
668   core_audio_devout->delay_counter = 0.0;
669   core_audio_devout->tic_counter = 0;
670 
671   core_audio_devout->start_note_offset = 0;
672   core_audio_devout->note_offset = 0;
673   core_audio_devout->note_offset_absolute = 0;
674 
675   core_audio_devout->loop_left = AGS_SOUNDCARD_DEFAULT_LOOP_LEFT;
676   core_audio_devout->loop_right = AGS_SOUNDCARD_DEFAULT_LOOP_RIGHT;
677 
678   core_audio_devout->do_loop = FALSE;
679 
680   core_audio_devout->loop_offset = 0;
681 
682   /* callback mutex */
683   g_mutex_init(&(core_audio_devout->callback_mutex));
684 
685   g_cond_init(&(core_audio_devout->callback_cond));
686 
687   /* callback finish mutex */
688   g_mutex_init(&(core_audio_devout->callback_finish_mutex));
689 
690   g_cond_init(&(core_audio_devout->callback_finish_cond));
691 }
692 
693 void
ags_core_audio_devout_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)694 ags_core_audio_devout_set_property(GObject *gobject,
695 				   guint prop_id,
696 				   const GValue *value,
697 				   GParamSpec *param_spec)
698 {
699   AgsCoreAudioDevout *core_audio_devout;
700 
701   GRecMutex *core_audio_devout_mutex;
702 
703   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(gobject);
704 
705   /* get core_audio devout mutex */
706   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
707 
708   switch(prop_id){
709   case PROP_DEVICE:
710     {
711       char *device;
712 
713       device = (char *) g_value_get_string(value);
714 
715       g_rec_mutex_lock(core_audio_devout_mutex);
716 
717       core_audio_devout->card_uri = g_strdup(device);
718 
719       g_rec_mutex_unlock(core_audio_devout_mutex);
720     }
721     break;
722   case PROP_DSP_CHANNELS:
723     {
724       guint dsp_channels;
725 
726       dsp_channels = g_value_get_uint(value);
727 
728       g_rec_mutex_lock(core_audio_devout_mutex);
729 
730       if(dsp_channels == core_audio_devout->dsp_channels){
731 	g_rec_mutex_unlock(core_audio_devout_mutex);
732 
733 	return;
734       }
735 
736       core_audio_devout->dsp_channels = dsp_channels;
737 
738       g_rec_mutex_unlock(core_audio_devout_mutex);
739     }
740     break;
741   case PROP_PCM_CHANNELS:
742     {
743       guint pcm_channels, old_pcm_channels;
744       guint i;
745 
746       pcm_channels = g_value_get_uint(value);
747 
748       g_rec_mutex_lock(core_audio_devout_mutex);
749 
750       if(pcm_channels == core_audio_devout->pcm_channels){
751 	g_rec_mutex_unlock(core_audio_devout_mutex);
752 
753 	return;
754       }
755 
756       old_pcm_channels = core_audio_devout->pcm_channels;
757 
758       /* destroy if less pcm-channels */
759       for(i = 8 * core_audio_devout->sub_block_count * pcm_channels; i < 8 * core_audio_devout->sub_block_count * old_pcm_channels; i++){
760 	g_rec_mutex_clear(core_audio_devout->sub_block_mutex[i]);
761 
762 	free(core_audio_devout->sub_block_mutex[i]);
763       }
764 
765       core_audio_devout->sub_block_mutex = (GRecMutex **) realloc(core_audio_devout->sub_block_mutex,
766 									8 * core_audio_devout->sub_block_count * pcm_channels * sizeof(GRecMutex *));
767 
768       /* create if more pcm-channels */
769       for(i = 8 * core_audio_devout->sub_block_count * old_pcm_channels; i < 8 * core_audio_devout->sub_block_count * pcm_channels; i++){
770 	core_audio_devout->sub_block_mutex[i] = (GRecMutex *) malloc(sizeof(GRecMutex));
771 
772 	g_rec_mutex_init(core_audio_devout->sub_block_mutex[i]);
773       }
774 
775       core_audio_devout->pcm_channels = pcm_channels;
776 
777       g_rec_mutex_unlock(core_audio_devout_mutex);
778 
779       ags_core_audio_devout_realloc_buffer(core_audio_devout);
780     }
781     break;
782   case PROP_FORMAT:
783     {
784       guint format;
785 
786       format = g_value_get_uint(value);
787 
788       g_rec_mutex_lock(core_audio_devout_mutex);
789 
790       if(format == core_audio_devout->format){
791 	g_rec_mutex_unlock(core_audio_devout_mutex);
792 
793 	return;
794       }
795 
796       core_audio_devout->format = format;
797 
798       g_rec_mutex_unlock(core_audio_devout_mutex);
799 
800       ags_core_audio_devout_realloc_buffer(core_audio_devout);
801     }
802     break;
803   case PROP_BUFFER_SIZE:
804     {
805       guint buffer_size;
806 
807       buffer_size = g_value_get_uint(value);
808 
809       g_rec_mutex_lock(core_audio_devout_mutex);
810 
811       if(buffer_size == core_audio_devout->buffer_size){
812 	g_rec_mutex_unlock(core_audio_devout_mutex);
813 
814 	return;
815       }
816 
817       core_audio_devout->buffer_size = buffer_size;
818 
819       g_rec_mutex_unlock(core_audio_devout_mutex);
820 
821       ags_core_audio_devout_realloc_buffer(core_audio_devout);
822       ags_core_audio_devout_adjust_delay_and_attack(core_audio_devout);
823     }
824     break;
825   case PROP_SAMPLERATE:
826     {
827       guint samplerate;
828 
829       samplerate = g_value_get_uint(value);
830 
831       g_rec_mutex_lock(core_audio_devout_mutex);
832 
833       if(samplerate == core_audio_devout->samplerate){
834 	g_rec_mutex_unlock(core_audio_devout_mutex);
835 
836 	return;
837       }
838 
839       core_audio_devout->samplerate = samplerate;
840 
841       g_rec_mutex_unlock(core_audio_devout_mutex);
842 
843       ags_core_audio_devout_realloc_buffer(core_audio_devout);
844       ags_core_audio_devout_adjust_delay_and_attack(core_audio_devout);
845     }
846     break;
847   case PROP_BUFFER:
848     {
849       //TODO:JK: implement me
850     }
851     break;
852   case PROP_BPM:
853     {
854       gdouble bpm;
855 
856       bpm = g_value_get_double(value);
857 
858       g_rec_mutex_lock(core_audio_devout_mutex);
859 
860       core_audio_devout->bpm = bpm;
861 
862       g_rec_mutex_unlock(core_audio_devout_mutex);
863 
864       ags_core_audio_devout_adjust_delay_and_attack(core_audio_devout);
865     }
866     break;
867   case PROP_DELAY_FACTOR:
868     {
869       gdouble delay_factor;
870 
871       delay_factor = g_value_get_double(value);
872 
873       g_rec_mutex_lock(core_audio_devout_mutex);
874 
875       core_audio_devout->delay_factor = delay_factor;
876 
877       g_rec_mutex_unlock(core_audio_devout_mutex);
878 
879       ags_core_audio_devout_adjust_delay_and_attack(core_audio_devout);
880     }
881     break;
882   case PROP_CORE_AUDIO_CLIENT:
883     {
884       AgsCoreAudioClient *core_audio_client;
885 
886       core_audio_client = (AgsCoreAudioClient *) g_value_get_object(value);
887 
888       g_rec_mutex_lock(core_audio_devout_mutex);
889 
890       if(core_audio_devout->core_audio_client == (GObject *) core_audio_client){
891 	g_rec_mutex_unlock(core_audio_devout_mutex);
892 
893 	return;
894       }
895 
896       if(core_audio_devout->core_audio_client != NULL){
897 	g_object_unref(G_OBJECT(core_audio_devout->core_audio_client));
898       }
899 
900       if(core_audio_client != NULL){
901 	g_object_ref(core_audio_client);
902       }
903 
904       core_audio_devout->core_audio_client = (GObject *) core_audio_client;
905 
906       g_rec_mutex_unlock(core_audio_devout_mutex);
907     }
908     break;
909   case PROP_CORE_AUDIO_PORT:
910     {
911       AgsCoreAudioPort *core_audio_port;
912 
913       core_audio_port = (AgsCoreAudioPort *) g_value_get_pointer(value);
914 
915       g_rec_mutex_lock(core_audio_devout_mutex);
916 
917       if(!AGS_IS_CORE_AUDIO_PORT(core_audio_port) ||
918 	 g_list_find(core_audio_devout->core_audio_port, core_audio_port) != NULL){
919 	g_rec_mutex_unlock(core_audio_devout_mutex);
920 
921 	return;
922       }
923 
924       g_object_ref(core_audio_port);
925       core_audio_devout->core_audio_port = g_list_append(core_audio_devout->core_audio_port,
926 					     core_audio_port);
927 
928       g_rec_mutex_unlock(core_audio_devout_mutex);
929     }
930     break;
931   default:
932     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
933     break;
934   }
935 }
936 
937 void
ags_core_audio_devout_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)938 ags_core_audio_devout_get_property(GObject *gobject,
939 				   guint prop_id,
940 				   GValue *value,
941 				   GParamSpec *param_spec)
942 {
943   AgsCoreAudioDevout *core_audio_devout;
944 
945   GRecMutex *core_audio_devout_mutex;
946 
947   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(gobject);
948 
949   /* get core_audio devout mutex */
950   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
951 
952   switch(prop_id){
953   case PROP_DEVICE:
954     {
955       g_rec_mutex_lock(core_audio_devout_mutex);
956 
957       g_value_set_string(value, core_audio_devout->card_uri);
958 
959       g_rec_mutex_unlock(core_audio_devout_mutex);
960     }
961     break;
962   case PROP_DSP_CHANNELS:
963     {
964       g_rec_mutex_lock(core_audio_devout_mutex);
965 
966       g_value_set_uint(value, core_audio_devout->dsp_channels);
967 
968       g_rec_mutex_unlock(core_audio_devout_mutex);
969     }
970     break;
971   case PROP_PCM_CHANNELS:
972     {
973       g_rec_mutex_lock(core_audio_devout_mutex);
974 
975       g_value_set_uint(value, core_audio_devout->pcm_channels);
976 
977       g_rec_mutex_unlock(core_audio_devout_mutex);
978     }
979     break;
980   case PROP_FORMAT:
981     {
982       g_rec_mutex_lock(core_audio_devout_mutex);
983 
984       g_value_set_uint(value, core_audio_devout->format);
985 
986       g_rec_mutex_unlock(core_audio_devout_mutex);
987     }
988     break;
989   case PROP_BUFFER_SIZE:
990     {
991       g_rec_mutex_lock(core_audio_devout_mutex);
992 
993       g_value_set_uint(value, core_audio_devout->buffer_size);
994 
995       g_rec_mutex_unlock(core_audio_devout_mutex);
996     }
997     break;
998   case PROP_SAMPLERATE:
999     {
1000       g_rec_mutex_lock(core_audio_devout_mutex);
1001 
1002       g_value_set_uint(value, core_audio_devout->samplerate);
1003 
1004       g_rec_mutex_unlock(core_audio_devout_mutex);
1005     }
1006     break;
1007   case PROP_BUFFER:
1008     {
1009       g_rec_mutex_lock(core_audio_devout_mutex);
1010 
1011       g_value_set_pointer(value, core_audio_devout->buffer);
1012 
1013       g_rec_mutex_unlock(core_audio_devout_mutex);
1014     }
1015     break;
1016   case PROP_BPM:
1017     {
1018       g_rec_mutex_lock(core_audio_devout_mutex);
1019 
1020       g_value_set_double(value, core_audio_devout->bpm);
1021 
1022       g_rec_mutex_unlock(core_audio_devout_mutex);
1023     }
1024     break;
1025   case PROP_DELAY_FACTOR:
1026     {
1027       g_rec_mutex_lock(core_audio_devout_mutex);
1028 
1029       g_value_set_double(value, core_audio_devout->delay_factor);
1030 
1031       g_rec_mutex_unlock(core_audio_devout_mutex);
1032     }
1033     break;
1034   case PROP_ATTACK:
1035     {
1036       g_rec_mutex_lock(core_audio_devout_mutex);
1037 
1038       g_value_set_pointer(value, core_audio_devout->attack);
1039 
1040       g_rec_mutex_unlock(core_audio_devout_mutex);
1041     }
1042     break;
1043   case PROP_CORE_AUDIO_CLIENT:
1044     {
1045       g_rec_mutex_lock(core_audio_devout_mutex);
1046 
1047       g_value_set_object(value, core_audio_devout->core_audio_client);
1048 
1049       g_rec_mutex_unlock(core_audio_devout_mutex);
1050     }
1051     break;
1052   case PROP_CORE_AUDIO_PORT:
1053     {
1054       g_rec_mutex_lock(core_audio_devout_mutex);
1055 
1056       g_value_set_pointer(value,
1057 			  g_list_copy_deep(core_audio_devout->core_audio_port,
1058 					   (GCopyFunc) g_object_ref,
1059 					   NULL));
1060 
1061       g_rec_mutex_unlock(core_audio_devout_mutex);
1062     }
1063     break;
1064   default:
1065     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
1066     break;
1067   }
1068 }
1069 
1070 void
ags_core_audio_devout_dispose(GObject * gobject)1071 ags_core_audio_devout_dispose(GObject *gobject)
1072 {
1073   AgsCoreAudioDevout *core_audio_devout;
1074 
1075   GList *list;
1076 
1077   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(gobject);
1078 
1079   /* core_audio client */
1080   if(core_audio_devout->core_audio_client != NULL){
1081     g_object_unref(core_audio_devout->core_audio_client);
1082 
1083     core_audio_devout->core_audio_client = NULL;
1084   }
1085 
1086   /* core_audio port */
1087   g_list_free_full(core_audio_devout->core_audio_port,
1088 		   g_object_unref);
1089 
1090   core_audio_devout->core_audio_port = NULL;
1091 
1092   /* call parent */
1093   G_OBJECT_CLASS(ags_core_audio_devout_parent_class)->dispose(gobject);
1094 }
1095 
1096 void
ags_core_audio_devout_finalize(GObject * gobject)1097 ags_core_audio_devout_finalize(GObject *gobject)
1098 {
1099   AgsCoreAudioDevout *core_audio_devout;
1100 
1101   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(gobject);
1102 
1103   /* free output buffer */
1104   free(core_audio_devout->buffer[0]);
1105   free(core_audio_devout->buffer[1]);
1106   free(core_audio_devout->buffer[2]);
1107   free(core_audio_devout->buffer[3]);
1108   free(core_audio_devout->buffer[4]);
1109   free(core_audio_devout->buffer[5]);
1110   free(core_audio_devout->buffer[6]);
1111   free(core_audio_devout->buffer[7]);
1112 
1113   /* free buffer array */
1114   free(core_audio_devout->buffer);
1115 
1116   /* free AgsAttack */
1117   free(core_audio_devout->attack);
1118 
1119   /* core_audio client */
1120   if(core_audio_devout->core_audio_client != NULL){
1121     g_object_unref(core_audio_devout->core_audio_client);
1122   }
1123 
1124   /* core_audio port */
1125   g_list_free_full(core_audio_devout->core_audio_port,
1126 		   g_object_unref);
1127 
1128   /* call parent */
1129   G_OBJECT_CLASS(ags_core_audio_devout_parent_class)->finalize(gobject);
1130 }
1131 
1132 AgsUUID*
ags_core_audio_devout_get_uuid(AgsConnectable * connectable)1133 ags_core_audio_devout_get_uuid(AgsConnectable *connectable)
1134 {
1135   AgsCoreAudioDevout *core_audio_devout;
1136 
1137   AgsUUID *ptr;
1138 
1139   GRecMutex *core_audio_devout_mutex;
1140 
1141   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(connectable);
1142 
1143   /* get core_audio devout signal mutex */
1144   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
1145 
1146   /* get UUID */
1147   g_rec_mutex_lock(core_audio_devout_mutex);
1148 
1149   ptr = core_audio_devout->uuid;
1150 
1151   g_rec_mutex_unlock(core_audio_devout_mutex);
1152 
1153   return(ptr);
1154 }
1155 
1156 gboolean
ags_core_audio_devout_has_resource(AgsConnectable * connectable)1157 ags_core_audio_devout_has_resource(AgsConnectable *connectable)
1158 {
1159   return(FALSE);
1160 }
1161 
1162 gboolean
ags_core_audio_devout_is_ready(AgsConnectable * connectable)1163 ags_core_audio_devout_is_ready(AgsConnectable *connectable)
1164 {
1165   AgsCoreAudioDevout *core_audio_devout;
1166 
1167   gboolean is_ready;
1168 
1169   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(connectable);
1170 
1171   /* check is added */
1172   is_ready = ags_core_audio_devout_test_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_ADDED_TO_REGISTRY);
1173 
1174   return(is_ready);
1175 }
1176 
1177 void
ags_core_audio_devout_add_to_registry(AgsConnectable * connectable)1178 ags_core_audio_devout_add_to_registry(AgsConnectable *connectable)
1179 {
1180   AgsCoreAudioDevout *core_audio_devout;
1181 
1182   if(ags_connectable_is_ready(connectable)){
1183     return;
1184   }
1185 
1186   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(connectable);
1187 
1188   ags_core_audio_devout_set_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_ADDED_TO_REGISTRY);
1189 }
1190 
1191 void
ags_core_audio_devout_remove_from_registry(AgsConnectable * connectable)1192 ags_core_audio_devout_remove_from_registry(AgsConnectable *connectable)
1193 {
1194   AgsCoreAudioDevout *core_audio_devout;
1195 
1196   if(!ags_connectable_is_ready(connectable)){
1197     return;
1198   }
1199 
1200   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(connectable);
1201 
1202   ags_core_audio_devout_unset_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_ADDED_TO_REGISTRY);
1203 }
1204 
1205 xmlNode*
ags_core_audio_devout_list_resource(AgsConnectable * connectable)1206 ags_core_audio_devout_list_resource(AgsConnectable *connectable)
1207 {
1208   xmlNode *node;
1209 
1210   node = NULL;
1211 
1212   //TODO:JK: implement me
1213 
1214   return(node);
1215 }
1216 
1217 xmlNode*
ags_core_audio_devout_xml_compose(AgsConnectable * connectable)1218 ags_core_audio_devout_xml_compose(AgsConnectable *connectable)
1219 {
1220   xmlNode *node;
1221 
1222   node = NULL;
1223 
1224   //TODO:JK: implement me
1225 
1226   return(node);
1227 }
1228 
1229 void
ags_core_audio_devout_xml_parse(AgsConnectable * connectable,xmlNode * node)1230 ags_core_audio_devout_xml_parse(AgsConnectable *connectable,
1231 		      xmlNode *node)
1232 {
1233   //TODO:JK: implement me
1234 }
1235 
1236 gboolean
ags_core_audio_devout_is_connected(AgsConnectable * connectable)1237 ags_core_audio_devout_is_connected(AgsConnectable *connectable)
1238 {
1239   AgsCoreAudioDevout *core_audio_devout;
1240 
1241   gboolean is_connected;
1242 
1243   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(connectable);
1244 
1245   /* check is connected */
1246   is_connected = ags_core_audio_devout_test_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_CONNECTED);
1247 
1248   return(is_connected);
1249 }
1250 
1251 void
ags_core_audio_devout_connect(AgsConnectable * connectable)1252 ags_core_audio_devout_connect(AgsConnectable *connectable)
1253 {
1254   AgsCoreAudioDevout *core_audio_devout;
1255 
1256   if(ags_connectable_is_connected(connectable)){
1257     return;
1258   }
1259 
1260   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(connectable);
1261 
1262   ags_core_audio_devout_set_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_CONNECTED);
1263 }
1264 
1265 void
ags_core_audio_devout_disconnect(AgsConnectable * connectable)1266 ags_core_audio_devout_disconnect(AgsConnectable *connectable)
1267 {
1268 
1269   AgsCoreAudioDevout *core_audio_devout;
1270 
1271   if(!ags_connectable_is_connected(connectable)){
1272     return;
1273   }
1274 
1275   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(connectable);
1276 
1277   ags_core_audio_devout_unset_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_CONNECTED);
1278 }
1279 
1280 /**
1281  * ags_core_audio_devout_test_flags:
1282  * @core_audio_devout: the #AgsCoreAudioDevout
1283  * @flags: the flags
1284  *
1285  * Test @flags to be set on @core_audio_devout.
1286  *
1287  * Returns: %TRUE if flags are set, else %FALSE
1288  *
1289  * Since: 3.0.0
1290  */
1291 gboolean
ags_core_audio_devout_test_flags(AgsCoreAudioDevout * core_audio_devout,guint flags)1292 ags_core_audio_devout_test_flags(AgsCoreAudioDevout *core_audio_devout, guint flags)
1293 {
1294   gboolean retval;
1295 
1296   GRecMutex *core_audio_devout_mutex;
1297 
1298   if(!AGS_IS_CORE_AUDIO_DEVOUT(core_audio_devout)){
1299     return(FALSE);
1300   }
1301 
1302   /* get core_audio devout mutex */
1303   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
1304 
1305   /* test */
1306   g_rec_mutex_lock(core_audio_devout_mutex);
1307 
1308   retval = (flags & (core_audio_devout->flags)) ? TRUE: FALSE;
1309 
1310   g_rec_mutex_unlock(core_audio_devout_mutex);
1311 
1312   return(retval);
1313 }
1314 
1315 /**
1316  * ags_core_audio_devout_set_flags:
1317  * @core_audio_devout: the #AgsCoreAudioDevout
1318  * @flags: see #AgsCoreAudioDevoutFlags-enum
1319  *
1320  * Enable a feature of @core_audio_devout.
1321  *
1322  * Since: 3.0.0
1323  */
1324 void
ags_core_audio_devout_set_flags(AgsCoreAudioDevout * core_audio_devout,guint flags)1325 ags_core_audio_devout_set_flags(AgsCoreAudioDevout *core_audio_devout, guint flags)
1326 {
1327   GRecMutex *core_audio_devout_mutex;
1328 
1329   if(!AGS_IS_CORE_AUDIO_DEVOUT(core_audio_devout)){
1330     return;
1331   }
1332 
1333   /* get core_audio devout mutex */
1334   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
1335 
1336   //TODO:JK: add more?
1337 
1338   /* set flags */
1339   g_rec_mutex_lock(core_audio_devout_mutex);
1340 
1341   core_audio_devout->flags |= flags;
1342 
1343   g_rec_mutex_unlock(core_audio_devout_mutex);
1344 }
1345 
1346 /**
1347  * ags_core_audio_devout_unset_flags:
1348  * @core_audio_devout: the #AgsCoreAudioDevout
1349  * @flags: see #AgsCoreAudioDevoutFlags-enum
1350  *
1351  * Disable a feature of @core_audio_devout.
1352  *
1353  * Since: 3.0.0
1354  */
1355 void
ags_core_audio_devout_unset_flags(AgsCoreAudioDevout * core_audio_devout,guint flags)1356 ags_core_audio_devout_unset_flags(AgsCoreAudioDevout *core_audio_devout, guint flags)
1357 {
1358   GRecMutex *core_audio_devout_mutex;
1359 
1360   if(!AGS_IS_CORE_AUDIO_DEVOUT(core_audio_devout)){
1361     return;
1362   }
1363 
1364   /* get core_audio devout mutex */
1365   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
1366 
1367   //TODO:JK: add more?
1368 
1369   /* unset flags */
1370   g_rec_mutex_lock(core_audio_devout_mutex);
1371 
1372   core_audio_devout->flags &= (~flags);
1373 
1374   g_rec_mutex_unlock(core_audio_devout_mutex);
1375 }
1376 
1377 void
ags_core_audio_devout_set_device(AgsSoundcard * soundcard,gchar * device)1378 ags_core_audio_devout_set_device(AgsSoundcard *soundcard,
1379 				 gchar *device)
1380 {
1381   AgsCoreAudioDevout *core_audio_devout;
1382 
1383   GList *core_audio_port, *core_audio_port_start;
1384 
1385   gchar *str;
1386 
1387   guint pcm_channels;
1388   int ret;
1389   guint nth_card;
1390   guint i;
1391 
1392   GRecMutex *core_audio_devout_mutex;
1393 
1394   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
1395 
1396   /* get core_audio devout mutex */
1397   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
1398 
1399   /* check device */
1400   g_rec_mutex_lock(core_audio_devout_mutex);
1401 
1402   if(core_audio_devout->card_uri == device ||
1403      (core_audio_devout->card_uri != NULL &&
1404       !g_ascii_strcasecmp(core_audio_devout->card_uri,
1405 			  device))){
1406     g_rec_mutex_unlock(core_audio_devout_mutex);
1407 
1408     return;
1409   }
1410 
1411   if(!g_str_has_prefix(device,
1412 		       "ags-core_audio-devout-")){
1413     g_rec_mutex_unlock(core_audio_devout_mutex);
1414 
1415     g_warning("invalid core_audioaudio device prefix");
1416 
1417     return;
1418   }
1419 
1420   ret = sscanf(device,
1421 	       "ags-core_audio-devout-%u",
1422 	       &nth_card);
1423 
1424   if(ret != 1){
1425     g_rec_mutex_unlock(core_audio_devout_mutex);
1426 
1427     g_warning("invalid core_audioaudio device specifier");
1428 
1429     return;
1430   }
1431 
1432   g_free(core_audio_devout->card_uri);
1433   core_audio_devout->card_uri = g_strdup(device);
1434 
1435   /* apply name to port */
1436   g_rec_mutex_lock(core_audio_devout_mutex);
1437 
1438   core_audio_port_start =
1439     core_audio_port = g_list_copy(core_audio_devout->core_audio_port);
1440 
1441   g_rec_mutex_unlock(core_audio_devout_mutex);
1442 
1443   str = g_strdup_printf("ags-soundcard%d",
1444 			nth_card);
1445 
1446   g_object_set(core_audio_port->data,
1447 	       "port-name", str,
1448 	       NULL);
1449   g_free(str);
1450 
1451   g_list_free(core_audio_port_start);
1452 }
1453 
1454 gchar*
ags_core_audio_devout_get_device(AgsSoundcard * soundcard)1455 ags_core_audio_devout_get_device(AgsSoundcard *soundcard)
1456 {
1457   AgsCoreAudioDevout *core_audio_devout;
1458 
1459   gchar *device;
1460 
1461   GRecMutex *core_audio_devout_mutex;
1462 
1463   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
1464 
1465   /* get core_audio devout mutex */
1466   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
1467 
1468   device = NULL;
1469 
1470   /* get device */
1471   g_rec_mutex_lock(core_audio_devout_mutex);
1472 
1473   device = g_strdup(core_audio_devout->card_uri);
1474 
1475   g_rec_mutex_unlock(core_audio_devout_mutex);
1476 
1477   return(device);
1478 }
1479 
1480 void
ags_core_audio_devout_set_presets(AgsSoundcard * soundcard,guint channels,guint rate,guint buffer_size,guint format)1481 ags_core_audio_devout_set_presets(AgsSoundcard *soundcard,
1482 				  guint channels,
1483 				  guint rate,
1484 				  guint buffer_size,
1485 				  guint format)
1486 {
1487   AgsCoreAudioDevout *core_audio_devout;
1488 
1489   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
1490 
1491   g_object_set(core_audio_devout,
1492 	       "pcm-channels", channels,
1493 	       "samplerate", rate,
1494 	       "buffer-size", buffer_size,
1495 	       "format", format,
1496 	       NULL);
1497 }
1498 
1499 void
ags_core_audio_devout_get_presets(AgsSoundcard * soundcard,guint * channels,guint * rate,guint * buffer_size,guint * format)1500 ags_core_audio_devout_get_presets(AgsSoundcard *soundcard,
1501 				  guint *channels,
1502 				  guint *rate,
1503 				  guint *buffer_size,
1504 				  guint *format)
1505 {
1506   AgsCoreAudioDevout *core_audio_devout;
1507 
1508   GRecMutex *core_audio_devout_mutex;
1509 
1510   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
1511 
1512   /* get core_audio devout mutex */
1513   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
1514 
1515   /* get presets */
1516   g_rec_mutex_lock(core_audio_devout_mutex);
1517 
1518   if(channels != NULL){
1519     *channels = core_audio_devout->pcm_channels;
1520   }
1521 
1522   if(rate != NULL){
1523     *rate = core_audio_devout->samplerate;
1524   }
1525 
1526   if(buffer_size != NULL){
1527     *buffer_size = core_audio_devout->buffer_size;
1528   }
1529 
1530   if(format != NULL){
1531     *format = core_audio_devout->format;
1532   }
1533 
1534   g_rec_mutex_unlock(core_audio_devout_mutex);
1535 }
1536 
1537 void
ags_core_audio_devout_list_cards(AgsSoundcard * soundcard,GList ** card_id,GList ** card_name)1538 ags_core_audio_devout_list_cards(AgsSoundcard *soundcard,
1539 				 GList **card_id, GList **card_name)
1540 {
1541   AgsCoreAudioClient *core_audio_client;
1542   AgsCoreAudioDevout *core_audio_devout;
1543 
1544   AgsApplicationContext *application_context;
1545 
1546   GList *list_start, *list;
1547 
1548   gchar *card_uri;
1549   gchar *client_name;
1550 
1551   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
1552 
1553   application_context = ags_application_context_get_instance();
1554 
1555   if(card_id != NULL){
1556     *card_id = NULL;
1557   }
1558 
1559   if(card_name != NULL){
1560     *card_name = NULL;
1561   }
1562 
1563   list =
1564     list_start = ags_sound_provider_get_soundcard(AGS_SOUND_PROVIDER(application_context));
1565 
1566   while(list != NULL){
1567     if(AGS_IS_CORE_AUDIO_DEVOUT(list->data)){
1568       if(card_id != NULL){
1569 	card_uri = ags_soundcard_get_device(AGS_SOUNDCARD(list->data));
1570 
1571 	if(AGS_CORE_AUDIO_DEVOUT(list->data)->card_uri != NULL){
1572 	  *card_id = g_list_prepend(*card_id,
1573 				    card_uri);
1574 	}else{
1575 	  *card_id = g_list_prepend(*card_id,
1576 				    g_strdup("(null)"));
1577 
1578 	  g_warning("ags_core_audio_devout_list_cards() - card id (null)");
1579 	}
1580       }
1581 
1582       if(card_name != NULL){
1583 	g_object_get(list->data,
1584 		     "core_audio-client", &core_audio_client,
1585 		     NULL);
1586 
1587 	if(core_audio_client != NULL){
1588 	  /* get client name */
1589 	  g_object_get(core_audio_client,
1590 		       "client-name", &client_name,
1591 		       NULL);
1592 
1593 	  *card_name = g_list_prepend(*card_name,
1594 				      client_name);
1595 
1596 	  g_object_unref(core_audio_client);
1597 	}else{
1598 	  *card_name = g_list_prepend(*card_name,
1599 				      g_strdup("(null)"));
1600 
1601 	  g_warning("ags_core_audio_devout_list_cards() - core_audioaudio client not connected (null)");
1602 	}
1603       }
1604     }
1605 
1606     list = list->next;
1607   }
1608 
1609   g_list_free_full(list_start,
1610 		   g_object_unref);
1611 
1612   if(card_id != NULL && *card_id != NULL){
1613     *card_id = g_list_reverse(*card_id);
1614   }
1615 
1616   if(card_name != NULL && *card_name != NULL){
1617     *card_name = g_list_reverse(*card_name);
1618   }
1619 }
1620 
1621 void
ags_core_audio_devout_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)1622 ags_core_audio_devout_pcm_info(AgsSoundcard *soundcard,
1623 			       char *card_id,
1624 			       guint *channels_min, guint *channels_max,
1625 			       guint *rate_min, guint *rate_max,
1626 			       guint *buffer_size_min, guint *buffer_size_max,
1627 			       GError **error)
1628 {
1629   if(channels_min != NULL){
1630     *channels_min = 1;
1631   }
1632 
1633   if(channels_max != NULL){
1634     *channels_max = 1024;
1635   }
1636 
1637   if(rate_min != NULL){
1638     *rate_min = 8000;
1639   }
1640 
1641   if(rate_max != NULL){
1642     *rate_max = 192000;
1643   }
1644 
1645   if(buffer_size_min != NULL){
1646     *buffer_size_min = 64;
1647   }
1648 
1649   if(buffer_size_max != NULL){
1650     *buffer_size_max = 8192;
1651   }
1652 }
1653 
1654 guint
ags_core_audio_devout_get_capability(AgsSoundcard * soundcard)1655 ags_core_audio_devout_get_capability(AgsSoundcard *soundcard)
1656 {
1657   return(AGS_SOUNDCARD_CAPABILITY_PLAYBACK);
1658 }
1659 
1660 gboolean
ags_core_audio_devout_is_starting(AgsSoundcard * soundcard)1661 ags_core_audio_devout_is_starting(AgsSoundcard *soundcard)
1662 {
1663   AgsCoreAudioDevout *core_audio_devout;
1664 
1665   gboolean is_starting;
1666 
1667   GRecMutex *core_audio_devout_mutex;
1668 
1669   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
1670 
1671   /* get core_audio devout mutex */
1672   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
1673 
1674   /* check is starting */
1675   g_rec_mutex_lock(core_audio_devout_mutex);
1676 
1677   is_starting = ((AGS_CORE_AUDIO_DEVOUT_START_PLAY & (core_audio_devout->flags)) != 0) ? TRUE: FALSE;
1678 
1679   g_rec_mutex_unlock(core_audio_devout_mutex);
1680 
1681   return(is_starting);
1682 }
1683 
1684 gboolean
ags_core_audio_devout_is_playing(AgsSoundcard * soundcard)1685 ags_core_audio_devout_is_playing(AgsSoundcard *soundcard)
1686 {
1687   AgsCoreAudioDevout *core_audio_devout;
1688 
1689   gboolean is_playing;
1690 
1691   GRecMutex *core_audio_devout_mutex;
1692 
1693   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
1694 
1695   /* get core_audio devout mutex */
1696   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
1697 
1698   /* check is starting */
1699   g_rec_mutex_lock(core_audio_devout_mutex);
1700 
1701   is_playing = ((AGS_CORE_AUDIO_DEVOUT_PLAY & (core_audio_devout->flags)) != 0) ? TRUE: FALSE;
1702 
1703   g_rec_mutex_unlock(core_audio_devout_mutex);
1704 
1705   return(is_playing);
1706 }
1707 
1708 gchar*
ags_core_audio_devout_get_uptime(AgsSoundcard * soundcard)1709 ags_core_audio_devout_get_uptime(AgsSoundcard *soundcard)
1710 {
1711   gchar *uptime;
1712 
1713   if(ags_soundcard_is_playing(soundcard)){
1714     guint samplerate;
1715     guint buffer_size;
1716 
1717     guint note_offset;
1718     gdouble bpm;
1719     gdouble delay_factor;
1720 
1721     gdouble delay;
1722 
1723     ags_soundcard_get_presets(soundcard,
1724 			      NULL,
1725 			      &samplerate,
1726 			      &buffer_size,
1727 			      NULL);
1728 
1729     note_offset = ags_soundcard_get_note_offset_absolute(soundcard);
1730 
1731     bpm = ags_soundcard_get_bpm(soundcard);
1732     delay_factor = ags_soundcard_get_delay_factor(soundcard);
1733 
1734     /* calculate delays */
1735     delay = ags_soundcard_get_absolute_delay(soundcard);
1736 
1737     uptime = ags_time_get_uptime_from_offset(note_offset,
1738 					     bpm,
1739 					     delay,
1740 					     delay_factor);
1741   }else{
1742     uptime = g_strdup(AGS_TIME_ZERO);
1743   }
1744 
1745   return(uptime);
1746 }
1747 
1748 void
ags_core_audio_devout_port_init(AgsSoundcard * soundcard,GError ** error)1749 ags_core_audio_devout_port_init(AgsSoundcard *soundcard,
1750 				GError **error)
1751 {
1752   AgsCoreAudioPort *core_audio_port;
1753   AgsCoreAudioDevout *core_audio_devout;
1754 
1755   guint format, word_size;
1756   gboolean use_cache;
1757 
1758   GRecMutex *core_audio_port_mutex;
1759   GRecMutex *core_audio_devout_mutex;
1760 
1761   if(ags_soundcard_is_playing(soundcard)){
1762     return;
1763   }
1764 
1765   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
1766 
1767   /* get core-audio devout mutex */
1768   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
1769 
1770   /* port */
1771   g_rec_mutex_lock(core_audio_devout_mutex);
1772 
1773   core_audio_port = (AgsCoreAudioPort *) core_audio_devout->core_audio_port->data;
1774 
1775   g_rec_mutex_unlock(core_audio_devout_mutex);
1776 
1777   /* get port mutex */
1778   core_audio_port_mutex = AGS_CORE_AUDIO_PORT_GET_OBJ_MUTEX(core_audio_port);
1779 
1780   /* check use cache */
1781   g_rec_mutex_lock(core_audio_port_mutex);
1782 
1783   use_cache = core_audio_port->use_cache;
1784 
1785   if(use_cache){
1786     core_audio_port->completed_cache = 0;
1787     core_audio_port->current_cache = 1;
1788   }
1789 
1790   g_rec_mutex_unlock(core_audio_port_mutex);
1791 
1792   /* retrieve word size */
1793   g_rec_mutex_lock(core_audio_devout_mutex);
1794 
1795   switch(core_audio_devout->format){
1796   case AGS_SOUNDCARD_SIGNED_8_BIT:
1797     {
1798       word_size = sizeof(gint8);
1799     }
1800     break;
1801   case AGS_SOUNDCARD_SIGNED_16_BIT:
1802     {
1803       word_size = sizeof(gint16);
1804     }
1805     break;
1806   case AGS_SOUNDCARD_SIGNED_24_BIT:
1807     {
1808       //NOTE:JK: The 24-bit linear samples use 32-bit physical space
1809       word_size = sizeof(gint32);
1810     }
1811     break;
1812   case AGS_SOUNDCARD_SIGNED_32_BIT:
1813     {
1814       word_size = sizeof(gint32);
1815     }
1816     break;
1817   case AGS_SOUNDCARD_SIGNED_64_BIT:
1818     {
1819       word_size = sizeof(gint64);
1820     }
1821     break;
1822   default:
1823     g_rec_mutex_unlock(core_audio_devout_mutex);
1824 
1825     g_warning("ags_core_audio_devout_port_init(): unsupported word size");
1826 
1827     return;
1828   }
1829 
1830   /* prepare for playback */
1831   core_audio_devout->flags |= (AGS_CORE_AUDIO_DEVOUT_BUFFER7 |
1832 			       AGS_CORE_AUDIO_DEVOUT_START_PLAY |
1833 			       AGS_CORE_AUDIO_DEVOUT_PLAY |
1834 			       AGS_CORE_AUDIO_DEVOUT_NONBLOCKING);
1835 
1836   memset(core_audio_devout->buffer[0], 0, core_audio_devout->pcm_channels * core_audio_devout->buffer_size * word_size);
1837   memset(core_audio_devout->buffer[1], 0, core_audio_devout->pcm_channels * core_audio_devout->buffer_size * word_size);
1838   memset(core_audio_devout->buffer[2], 0, core_audio_devout->pcm_channels * core_audio_devout->buffer_size * word_size);
1839   memset(core_audio_devout->buffer[3], 0, core_audio_devout->pcm_channels * core_audio_devout->buffer_size * word_size);
1840   memset(core_audio_devout->buffer[4], 0, core_audio_devout->pcm_channels * core_audio_devout->buffer_size * word_size);
1841   memset(core_audio_devout->buffer[5], 0, core_audio_devout->pcm_channels * core_audio_devout->buffer_size * word_size);
1842   memset(core_audio_devout->buffer[6], 0, core_audio_devout->pcm_channels * core_audio_devout->buffer_size * word_size);
1843   memset(core_audio_devout->buffer[7], 0, core_audio_devout->pcm_channels * core_audio_devout->buffer_size * word_size);
1844 
1845   /*  */
1846   core_audio_devout->tact_counter = 0.0;
1847   core_audio_devout->delay_counter = floor(ags_soundcard_get_absolute_delay(AGS_SOUNDCARD(core_audio_devout)));
1848   core_audio_devout->tic_counter = 0;
1849 
1850   core_audio_devout->flags |= (AGS_CORE_AUDIO_DEVOUT_INITIALIZED |
1851 			       AGS_CORE_AUDIO_DEVOUT_START_PLAY |
1852 			       AGS_CORE_AUDIO_DEVOUT_PLAY);
1853 
1854   g_atomic_int_or(&(core_audio_devout->sync_flags),
1855 		  AGS_CORE_AUDIO_DEVOUT_INITIAL_CALLBACK);
1856 
1857   g_rec_mutex_unlock(core_audio_devout_mutex);
1858 }
1859 
1860 void
ags_core_audio_devout_port_play(AgsSoundcard * soundcard,GError ** error)1861 ags_core_audio_devout_port_play(AgsSoundcard *soundcard,
1862 				GError **error)
1863 {
1864   AgsCoreAudioClient *core_audio_client;
1865   AgsCoreAudioDevout *core_audio_devout;
1866   AgsCoreAudioPort *core_audio_port;
1867 
1868   AgsTicDevice *tic_device;
1869   AgsClearBuffer *clear_buffer;
1870   AgsSwitchBufferFlag *switch_buffer_flag;
1871 
1872   AgsTaskLauncher *task_launcher;
1873 
1874   AgsApplicationContext *application_context;
1875 
1876   GList *task;
1877   guint word_size;
1878   gboolean use_cache;
1879   gboolean core_audio_client_activated;
1880 
1881   GRecMutex *core_audio_devout_mutex;
1882   GRecMutex *core_audio_client_mutex;
1883   GRecMutex *core_audio_port_mutex;
1884   GMutex *callback_mutex;
1885   GMutex *callback_finish_mutex;
1886 
1887   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
1888 
1889   application_context = ags_application_context_get_instance();
1890 
1891   /* get core-audio devout mutex */
1892   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
1893 
1894   /* client */
1895   g_rec_mutex_lock(core_audio_devout_mutex);
1896 
1897   core_audio_client = (AgsCoreAudioClient *) core_audio_devout->core_audio_client;
1898   core_audio_port = (AgsCoreAudioPort *) core_audio_devout->core_audio_port->data;
1899 
1900   callback_mutex = &(core_audio_devout->callback_mutex);
1901   callback_finish_mutex = &(core_audio_devout->callback_finish_mutex);
1902 
1903   /* do playback */
1904   core_audio_devout->flags &= (~AGS_CORE_AUDIO_DEVOUT_START_PLAY);
1905 
1906   if((AGS_CORE_AUDIO_DEVOUT_INITIALIZED & (core_audio_devout->flags)) == 0){
1907     g_rec_mutex_unlock(core_audio_devout_mutex);
1908 
1909     return;
1910   }
1911 
1912   switch(core_audio_devout->format){
1913   case AGS_SOUNDCARD_SIGNED_16_BIT:
1914     {
1915       word_size = sizeof(gint16);
1916     }
1917     break;
1918   case AGS_SOUNDCARD_SIGNED_24_BIT:
1919     {
1920       //NOTE:JK: The 24-bit linear samples use 32-bit physical space
1921       word_size = sizeof(gint32);
1922     }
1923     break;
1924   case AGS_SOUNDCARD_SIGNED_32_BIT:
1925     {
1926       word_size = sizeof(gint32);
1927     }
1928     break;
1929   default:
1930     g_rec_mutex_unlock(core_audio_devout_mutex);
1931 
1932     g_warning("ags_core_audio_devout_port_play(): unsupported word size");
1933 
1934     return;
1935   }
1936 
1937   g_rec_mutex_unlock(core_audio_devout_mutex);
1938 
1939   /* get port mutex */
1940   core_audio_port_mutex = AGS_CORE_AUDIO_PORT_GET_OBJ_MUTEX(core_audio_port);
1941 
1942   /* check use cache */
1943   g_rec_mutex_lock(core_audio_port_mutex);
1944 
1945   use_cache = core_audio_port->use_cache;
1946 
1947   g_rec_mutex_unlock(core_audio_port_mutex);
1948 
1949   if(use_cache){
1950     void *buffer;
1951 
1952     guint current_cache;
1953     guint completed_cache;
1954     guint write_cache;
1955     guint cache_buffer_size;
1956     guint cache_offset;
1957     guint pcm_channels;
1958     guint buffer_size;
1959     guint format;
1960 
1961     struct timespec idle_time = {
1962       0,
1963       0,
1964     };
1965 
1966     idle_time.tv_nsec = ags_core_audio_port_get_latency(core_audio_port) / 8;
1967 
1968     g_rec_mutex_lock(core_audio_port_mutex);
1969 
1970     completed_cache = core_audio_port->completed_cache;
1971 
1972     cache_buffer_size = core_audio_port->cache_buffer_size;
1973 
1974     cache_offset = core_audio_port->cache_offset;
1975 
1976     g_rec_mutex_unlock(core_audio_port_mutex);
1977 
1978     if(completed_cache == 3){
1979       write_cache = 0;
1980     }else{
1981       write_cache = completed_cache + 1;
1982     }
1983 
1984     /* wait until ready */
1985     g_rec_mutex_lock(core_audio_port_mutex);
1986 
1987     current_cache = core_audio_port->current_cache;
1988 
1989     g_rec_mutex_unlock(core_audio_port_mutex);
1990 
1991     while(write_cache == current_cache){
1992       nanosleep(&idle_time, NULL);
1993 
1994       g_rec_mutex_lock(core_audio_port_mutex);
1995 
1996       current_cache = core_audio_port->current_cache;
1997 
1998       g_rec_mutex_unlock(core_audio_port_mutex);
1999     }
2000 
2001     /* fill cache */
2002     g_rec_mutex_lock(core_audio_devout_mutex);
2003 
2004     pcm_channels = core_audio_devout->pcm_channels;
2005     buffer_size = core_audio_devout->buffer_size;
2006     format = core_audio_devout->format;
2007 
2008     g_rec_mutex_unlock(core_audio_devout_mutex);
2009 
2010     buffer = ags_soundcard_get_buffer(AGS_SOUNDCARD(core_audio_devout));
2011 
2012     // g_message("w %d", write_cache);
2013 
2014     switch(format){
2015     case AGS_SOUNDCARD_SIGNED_16_BIT:
2016       {
2017 	if(cache_offset == 0){
2018 	  ags_audio_buffer_util_clear_buffer(core_audio_port->cache[write_cache], 1,
2019 					     pcm_channels * cache_buffer_size, AGS_AUDIO_BUFFER_UTIL_S16);
2020 	}
2021 
2022 	if(buffer != NULL){
2023 	  ags_audio_buffer_util_copy_s16_to_s16((gint16 *) core_audio_port->cache[write_cache] + (pcm_channels * cache_offset), 1,
2024 						(gint16 *) buffer, 1,
2025 						pcm_channels * buffer_size);
2026 	}
2027       }
2028       break;
2029     case AGS_SOUNDCARD_SIGNED_24_BIT:
2030       {
2031 	if(cache_offset == 0){
2032 	  ags_audio_buffer_util_clear_buffer(core_audio_port->cache[write_cache], 1,
2033 					     pcm_channels * cache_buffer_size, AGS_AUDIO_BUFFER_UTIL_S32);
2034 	}
2035 
2036 	if(buffer != NULL){
2037 	  ags_audio_buffer_util_copy_s24_to_s24((gint32 *) core_audio_port->cache[write_cache] + (pcm_channels * cache_offset), 1,
2038 						(gint32 *) buffer, 1,
2039 						pcm_channels * buffer_size);
2040 	}
2041       }
2042       break;
2043     case AGS_SOUNDCARD_SIGNED_32_BIT:
2044       {
2045 	if(cache_offset == 0){
2046 	  ags_audio_buffer_util_clear_buffer(core_audio_port->cache[write_cache], 1,
2047 					     pcm_channels * cache_buffer_size, AGS_AUDIO_BUFFER_UTIL_S32);
2048 	}
2049 
2050 	if(buffer != NULL){
2051 	  ags_audio_buffer_util_copy_s32_to_s32((gint32 *) core_audio_port->cache[write_cache] + (pcm_channels * cache_offset), 1,
2052 						(gint32 *) buffer, 1,
2053 						pcm_channels * buffer_size);
2054 	}
2055       }
2056       break;
2057     }
2058 
2059     /* seek cache */
2060     if(cache_offset + buffer_size >= cache_buffer_size){
2061       g_rec_mutex_lock(core_audio_port_mutex);
2062 
2063       core_audio_port->completed_cache = write_cache;
2064       core_audio_port->cache_offset = 0;
2065 
2066       g_rec_mutex_unlock(core_audio_port_mutex);
2067     }else{
2068       g_rec_mutex_lock(core_audio_port_mutex);
2069 
2070       core_audio_port->cache_offset += buffer_size;
2071 
2072       g_rec_mutex_unlock(core_audio_port_mutex);
2073     }
2074   }else{
2075     /* get client mutex */
2076     core_audio_client_mutex = AGS_CORE_AUDIO_CLIENT_GET_OBJ_MUTEX(core_audio_client);
2077 
2078     /* get activated */
2079     g_rec_mutex_lock(core_audio_client_mutex);
2080 
2081     core_audio_client_activated = ((AGS_CORE_AUDIO_CLIENT_ACTIVATED & (core_audio_client->flags)) != 0) ? TRUE: FALSE;
2082 
2083     g_rec_mutex_unlock(core_audio_client_mutex);
2084 
2085     if(core_audio_client_activated){
2086       while((AGS_CORE_AUDIO_DEVOUT_PASS_THROUGH & (g_atomic_int_get(&(core_audio_devout->sync_flags)))) != 0){
2087 	usleep(4);
2088       }
2089 
2090       /* signal */
2091       if((AGS_CORE_AUDIO_DEVOUT_INITIAL_CALLBACK & (g_atomic_int_get(&(core_audio_devout->sync_flags)))) == 0){
2092 	g_mutex_lock(callback_mutex);
2093 
2094 	g_atomic_int_or(&(core_audio_devout->sync_flags),
2095 			AGS_CORE_AUDIO_DEVOUT_CALLBACK_DONE);
2096 
2097 	if((AGS_CORE_AUDIO_DEVOUT_CALLBACK_WAIT & (g_atomic_int_get(&(core_audio_devout->sync_flags)))) != 0){
2098 	  g_cond_signal(&(core_audio_devout->callback_cond));
2099 	}
2100 
2101 	g_mutex_unlock(callback_mutex);
2102 	//    }
2103 
2104 	/* wait callback */
2105 	g_mutex_lock(callback_finish_mutex);
2106 
2107 	if((AGS_CORE_AUDIO_DEVOUT_CALLBACK_FINISH_DONE & (g_atomic_int_get(&(core_audio_devout->sync_flags)))) == 0){
2108 	  g_atomic_int_or(&(core_audio_devout->sync_flags),
2109 			  AGS_CORE_AUDIO_DEVOUT_CALLBACK_FINISH_WAIT);
2110 
2111 	  while((AGS_CORE_AUDIO_DEVOUT_CALLBACK_FINISH_DONE & (g_atomic_int_get(&(core_audio_devout->sync_flags)))) == 0 &&
2112 		(AGS_CORE_AUDIO_DEVOUT_CALLBACK_FINISH_WAIT & (g_atomic_int_get(&(core_audio_devout->sync_flags)))) != 0){
2113 	    g_cond_wait(&(core_audio_devout->callback_finish_cond),
2114 			callback_finish_mutex);
2115 	  }
2116 	}
2117 
2118 	g_atomic_int_and(&(core_audio_devout->sync_flags),
2119 			 (~(AGS_CORE_AUDIO_DEVOUT_CALLBACK_FINISH_WAIT |
2120 			    AGS_CORE_AUDIO_DEVOUT_CALLBACK_FINISH_DONE)));
2121 
2122 	g_mutex_unlock(callback_finish_mutex);
2123       }else{
2124 	g_atomic_int_and(&(core_audio_devout->sync_flags),
2125 			 (~AGS_CORE_AUDIO_DEVOUT_INITIAL_CALLBACK));
2126       }
2127     }
2128   }
2129 
2130   /* update soundcard */
2131   task_launcher = ags_concurrency_provider_get_task_launcher(AGS_CONCURRENCY_PROVIDER(application_context));
2132 
2133   task = NULL;
2134 
2135   /* tic soundcard */
2136   tic_device = ags_tic_device_new((GObject *) core_audio_devout);
2137   task = g_list_append(task,
2138 		       tic_device);
2139 
2140   /* reset - clear buffer */
2141   clear_buffer = ags_clear_buffer_new((GObject *) core_audio_devout);
2142   task = g_list_append(task,
2143 		       clear_buffer);
2144 
2145   /* reset - switch buffer flags */
2146   switch_buffer_flag = ags_switch_buffer_flag_new((GObject *) core_audio_devout);
2147   task = g_list_append(task,
2148 		       switch_buffer_flag);
2149 
2150   /* append tasks */
2151   ags_task_launcher_add_task_all(task_launcher,
2152 				 task);
2153 
2154   /* unref */
2155   g_object_unref(task_launcher);
2156 }
2157 
2158 void
ags_core_audio_devout_port_free(AgsSoundcard * soundcard)2159 ags_core_audio_devout_port_free(AgsSoundcard *soundcard)
2160 {
2161   AgsCoreAudioPort *core_audio_port;
2162   AgsCoreAudioDevout *core_audio_devout;
2163 
2164   guint pcm_channels;
2165   guint cache_buffer_size;
2166   guint word_size;
2167   gboolean use_cache;
2168 
2169   GRecMutex *core_audio_port_mutex;
2170   GRecMutex *core_audio_devout_mutex;
2171   GMutex *callback_mutex;
2172   GMutex *callback_finish_mutex;
2173 
2174   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
2175 
2176   /* get core-audio devout mutex */
2177   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
2178 
2179   /* port */
2180   g_rec_mutex_lock(core_audio_devout_mutex);
2181 
2182   core_audio_port = (AgsCoreAudioPort *) core_audio_devout->core_audio_port->data;
2183   pcm_channels = core_audio_devout->pcm_channels;
2184 
2185   g_rec_mutex_unlock(core_audio_devout_mutex);
2186 
2187   /* get port mutex */
2188   core_audio_port_mutex = AGS_CORE_AUDIO_PORT_GET_OBJ_MUTEX(core_audio_port);
2189 
2190   /* check use cache */
2191   g_rec_mutex_lock(core_audio_port_mutex);
2192 
2193   cache_buffer_size = core_audio_port->cache_buffer_size;
2194   use_cache = core_audio_port->use_cache;
2195 
2196   if(use_cache){
2197     core_audio_port->completed_cache = 0;
2198     core_audio_port->current_cache = 0;
2199     core_audio_port->cache_offset = 0;
2200   }
2201 
2202   switch(core_audio_port->format){
2203   case AGS_SOUNDCARD_SIGNED_16_BIT:
2204     {
2205       ags_audio_buffer_util_clear_buffer(core_audio_port->cache[0], 1,
2206 					 pcm_channels * cache_buffer_size, AGS_AUDIO_BUFFER_UTIL_S16);
2207       ags_audio_buffer_util_clear_buffer(core_audio_port->cache[1], 1,
2208 					 pcm_channels * cache_buffer_size, AGS_AUDIO_BUFFER_UTIL_S16);
2209       ags_audio_buffer_util_clear_buffer(core_audio_port->cache[2], 1,
2210 					 pcm_channels * cache_buffer_size, AGS_AUDIO_BUFFER_UTIL_S16);
2211       ags_audio_buffer_util_clear_buffer(core_audio_port->cache[3], 1,
2212 					 pcm_channels * cache_buffer_size, AGS_AUDIO_BUFFER_UTIL_S16);
2213     }
2214     break;
2215   case AGS_SOUNDCARD_SIGNED_24_BIT:
2216     {
2217       ags_audio_buffer_util_clear_buffer(core_audio_port->cache[0], 1,
2218 					 pcm_channels * cache_buffer_size, AGS_AUDIO_BUFFER_UTIL_S32);
2219       ags_audio_buffer_util_clear_buffer(core_audio_port->cache[1], 1,
2220 					 pcm_channels * cache_buffer_size, AGS_AUDIO_BUFFER_UTIL_S32);
2221       ags_audio_buffer_util_clear_buffer(core_audio_port->cache[2], 1,
2222 					 pcm_channels * cache_buffer_size, AGS_AUDIO_BUFFER_UTIL_S32);
2223       ags_audio_buffer_util_clear_buffer(core_audio_port->cache[3], 1,
2224 					 pcm_channels * cache_buffer_size, AGS_AUDIO_BUFFER_UTIL_S32);
2225     }
2226     break;
2227   case AGS_SOUNDCARD_SIGNED_32_BIT:
2228     {
2229       ags_audio_buffer_util_clear_buffer(core_audio_port->cache[0], 1,
2230 					 pcm_channels * cache_buffer_size, AGS_AUDIO_BUFFER_UTIL_S32);
2231       ags_audio_buffer_util_clear_buffer(core_audio_port->cache[1], 1,
2232 					 pcm_channels * cache_buffer_size, AGS_AUDIO_BUFFER_UTIL_S32);
2233       ags_audio_buffer_util_clear_buffer(core_audio_port->cache[2], 1,
2234 					 pcm_channels * cache_buffer_size, AGS_AUDIO_BUFFER_UTIL_S32);
2235       ags_audio_buffer_util_clear_buffer(core_audio_port->cache[3], 1,
2236 					 pcm_channels * cache_buffer_size, AGS_AUDIO_BUFFER_UTIL_S32);
2237     }
2238     break;
2239   }
2240 
2241   g_rec_mutex_unlock(core_audio_port_mutex);
2242 
2243   /*  */
2244   g_rec_mutex_lock(core_audio_devout_mutex);
2245 
2246   if((AGS_CORE_AUDIO_DEVOUT_INITIALIZED & (core_audio_devout->flags)) == 0){
2247     g_rec_mutex_unlock(core_audio_devout_mutex);
2248 
2249     return;
2250   }
2251 
2252   callback_mutex = &(core_audio_devout->callback_mutex);
2253   callback_finish_mutex = &(core_audio_devout->callback_finish_mutex);
2254 
2255   //  g_atomic_int_or(&(AGS_THREAD(application_context->main_loop)->flags),
2256   //		  AGS_THREAD_TIMING);
2257 
2258   core_audio_devout->flags &= (~(AGS_CORE_AUDIO_DEVOUT_BUFFER0 |
2259 				 AGS_CORE_AUDIO_DEVOUT_BUFFER1 |
2260 				 AGS_CORE_AUDIO_DEVOUT_BUFFER2 |
2261 				 AGS_CORE_AUDIO_DEVOUT_BUFFER3 |
2262 				 AGS_CORE_AUDIO_DEVOUT_BUFFER4 |
2263 				 AGS_CORE_AUDIO_DEVOUT_BUFFER5 |
2264 				 AGS_CORE_AUDIO_DEVOUT_BUFFER6 |
2265 				 AGS_CORE_AUDIO_DEVOUT_BUFFER7 |
2266 				 AGS_CORE_AUDIO_DEVOUT_PLAY));
2267 
2268   g_atomic_int_or(&(core_audio_devout->sync_flags),
2269 		  AGS_CORE_AUDIO_DEVOUT_PASS_THROUGH);
2270   g_atomic_int_and(&(core_audio_devout->sync_flags),
2271 		   (~AGS_CORE_AUDIO_DEVOUT_INITIAL_CALLBACK));
2272 
2273   /* signal callback */
2274   g_rec_mutex_lock(callback_mutex);
2275 
2276   g_atomic_int_or(&(core_audio_devout->sync_flags),
2277 		  AGS_CORE_AUDIO_DEVOUT_CALLBACK_DONE);
2278 
2279   if((AGS_CORE_AUDIO_DEVOUT_CALLBACK_WAIT & (g_atomic_int_get(&(core_audio_devout->sync_flags)))) != 0){
2280     g_cond_signal(&(core_audio_devout->callback_cond));
2281   }
2282 
2283   g_rec_mutex_unlock(callback_mutex);
2284 
2285   /* signal thread */
2286   g_rec_mutex_lock(callback_finish_mutex);
2287 
2288   g_atomic_int_or(&(core_audio_devout->sync_flags),
2289 		  AGS_CORE_AUDIO_DEVOUT_CALLBACK_FINISH_DONE);
2290 
2291   if((AGS_CORE_AUDIO_DEVOUT_CALLBACK_FINISH_WAIT & (g_atomic_int_get(&(core_audio_devout->sync_flags)))) != 0){
2292     g_cond_signal(&(core_audio_devout->callback_finish_cond));
2293   }
2294 
2295   g_rec_mutex_unlock(callback_finish_mutex);
2296 
2297   /*  */
2298   core_audio_devout->note_offset = core_audio_devout->start_note_offset;
2299   core_audio_devout->note_offset_absolute = core_audio_devout->start_note_offset;
2300 
2301   switch(core_audio_devout->format){
2302   case AGS_SOUNDCARD_SIGNED_8_BIT:
2303     {
2304       word_size = sizeof(gint8);
2305     }
2306     break;
2307   case AGS_SOUNDCARD_SIGNED_16_BIT:
2308     {
2309       word_size = sizeof(gint16);
2310     }
2311     break;
2312   case AGS_SOUNDCARD_SIGNED_24_BIT:
2313     {
2314       word_size = sizeof(gint32);
2315     }
2316     break;
2317   case AGS_SOUNDCARD_SIGNED_32_BIT:
2318     {
2319       word_size = sizeof(gint32);
2320     }
2321     break;
2322   case AGS_SOUNDCARD_SIGNED_64_BIT:
2323     {
2324       word_size = sizeof(gint64);
2325     }
2326     break;
2327   default:
2328     word_size = 0;
2329 
2330     g_critical("ags_core_audio_devout_free(): unsupported word size");
2331   }
2332 
2333   g_rec_mutex_unlock(core_audio_devout_mutex);
2334 
2335   if(core_audio_devout->core_audio_port != NULL){
2336     core_audio_port = core_audio_devout->core_audio_port->data;
2337 
2338     while(!g_atomic_int_get(&(core_audio_port->is_empty))) usleep(500000);
2339   }
2340 
2341   g_rec_mutex_lock(core_audio_devout_mutex);
2342 
2343   memset(core_audio_devout->buffer[0], 0, (size_t) core_audio_devout->pcm_channels * core_audio_devout->buffer_size * word_size);
2344   memset(core_audio_devout->buffer[1], 0, (size_t) core_audio_devout->pcm_channels * core_audio_devout->buffer_size * word_size);
2345   memset(core_audio_devout->buffer[2], 0, (size_t) core_audio_devout->pcm_channels * core_audio_devout->buffer_size * word_size);
2346   memset(core_audio_devout->buffer[3], 0, (size_t) core_audio_devout->pcm_channels * core_audio_devout->buffer_size * word_size);
2347   memset(core_audio_devout->buffer[4], 0, (size_t) core_audio_devout->pcm_channels * core_audio_devout->buffer_size * word_size);
2348   memset(core_audio_devout->buffer[5], 0, (size_t) core_audio_devout->pcm_channels * core_audio_devout->buffer_size * word_size);
2349   memset(core_audio_devout->buffer[6], 0, (size_t) core_audio_devout->pcm_channels * core_audio_devout->buffer_size * word_size);
2350   memset(core_audio_devout->buffer[7], 0, (size_t) core_audio_devout->pcm_channels * core_audio_devout->buffer_size * word_size);
2351 
2352   g_rec_mutex_unlock(core_audio_devout_mutex);
2353 }
2354 
2355 void
ags_core_audio_devout_tic(AgsSoundcard * soundcard)2356 ags_core_audio_devout_tic(AgsSoundcard *soundcard)
2357 {
2358   AgsCoreAudioDevout *core_audio_devout;
2359 
2360   gdouble delay;
2361   gdouble delay_counter;
2362   guint note_offset_absolute;
2363   guint note_offset;
2364   guint loop_left, loop_right;
2365   gboolean do_loop;
2366 
2367   GRecMutex *core_audio_devout_mutex;
2368 
2369   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
2370 
2371   /* get core_audio devout mutex */
2372   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
2373 
2374   /* determine if attack should be switched */
2375   g_rec_mutex_lock(core_audio_devout_mutex);
2376 
2377   delay = core_audio_devout->delay[core_audio_devout->tic_counter];
2378   delay_counter = core_audio_devout->delay_counter;
2379 
2380   note_offset = core_audio_devout->note_offset;
2381   note_offset_absolute = core_audio_devout->note_offset_absolute;
2382 
2383   loop_left = core_audio_devout->loop_left;
2384   loop_right = core_audio_devout->loop_right;
2385 
2386   do_loop = core_audio_devout->do_loop;
2387 
2388   g_rec_mutex_unlock(core_audio_devout_mutex);
2389 
2390   if(delay_counter + 1.0 >= floor(delay)){
2391     if(do_loop &&
2392        note_offset + 1 == loop_right){
2393       ags_soundcard_set_note_offset(soundcard,
2394 				    loop_left);
2395     }else{
2396       ags_soundcard_set_note_offset(soundcard,
2397 				    note_offset + 1);
2398     }
2399 
2400     ags_soundcard_set_note_offset_absolute(soundcard,
2401 					   note_offset_absolute + 1);
2402 
2403     /* delay */
2404     ags_soundcard_offset_changed(soundcard,
2405 				 note_offset);
2406 
2407     /* reset - delay counter */
2408     g_rec_mutex_lock(core_audio_devout_mutex);
2409 
2410     core_audio_devout->delay_counter = delay_counter + 1.0 - delay;
2411     core_audio_devout->tact_counter += 1.0;
2412 
2413     g_rec_mutex_unlock(core_audio_devout_mutex);
2414   }else{
2415     g_rec_mutex_lock(core_audio_devout_mutex);
2416 
2417     core_audio_devout->delay_counter += 1.0;
2418 
2419     g_rec_mutex_unlock(core_audio_devout_mutex);
2420   }
2421 }
2422 
2423 void
ags_core_audio_devout_offset_changed(AgsSoundcard * soundcard,guint note_offset)2424 ags_core_audio_devout_offset_changed(AgsSoundcard *soundcard,
2425 			       guint note_offset)
2426 {
2427   AgsCoreAudioDevout *core_audio_devout;
2428 
2429   GRecMutex *core_audio_devout_mutex;
2430 
2431   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
2432 
2433   /* get core_audio devout mutex */
2434   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
2435 
2436   /* offset changed */
2437   g_rec_mutex_lock(core_audio_devout_mutex);
2438 
2439   core_audio_devout->tic_counter += 1;
2440 
2441   if(core_audio_devout->tic_counter == AGS_SOUNDCARD_DEFAULT_PERIOD){
2442     /* reset - tic counter i.e. modified delay index within period */
2443     core_audio_devout->tic_counter = 0;
2444   }
2445 
2446   g_rec_mutex_unlock(core_audio_devout_mutex);
2447 }
2448 
2449 void
ags_core_audio_devout_set_bpm(AgsSoundcard * soundcard,gdouble bpm)2450 ags_core_audio_devout_set_bpm(AgsSoundcard *soundcard,
2451 			gdouble bpm)
2452 {
2453   AgsCoreAudioDevout *core_audio_devout;
2454 
2455   GRecMutex *core_audio_devout_mutex;
2456 
2457   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
2458 
2459   /* get core_audio devout mutex */
2460   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
2461 
2462   /* set bpm */
2463   g_rec_mutex_lock(core_audio_devout_mutex);
2464 
2465   core_audio_devout->bpm = bpm;
2466 
2467   g_rec_mutex_unlock(core_audio_devout_mutex);
2468 
2469   ags_core_audio_devout_adjust_delay_and_attack(core_audio_devout);
2470 }
2471 
2472 gdouble
ags_core_audio_devout_get_bpm(AgsSoundcard * soundcard)2473 ags_core_audio_devout_get_bpm(AgsSoundcard *soundcard)
2474 {
2475   AgsCoreAudioDevout *core_audio_devout;
2476 
2477   gdouble bpm;
2478 
2479   GRecMutex *core_audio_devout_mutex;
2480 
2481   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
2482 
2483   /* get core_audio devout mutex */
2484   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
2485 
2486   /* get bpm */
2487   g_rec_mutex_lock(core_audio_devout_mutex);
2488 
2489   bpm = core_audio_devout->bpm;
2490 
2491   g_rec_mutex_unlock(core_audio_devout_mutex);
2492 
2493   return(bpm);
2494 }
2495 
2496 void
ags_core_audio_devout_set_delay_factor(AgsSoundcard * soundcard,gdouble delay_factor)2497 ags_core_audio_devout_set_delay_factor(AgsSoundcard *soundcard,
2498 				 gdouble delay_factor)
2499 {
2500   AgsCoreAudioDevout *core_audio_devout;
2501 
2502   GRecMutex *core_audio_devout_mutex;
2503 
2504   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
2505 
2506   /* get core_audio devout mutex */
2507   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
2508 
2509   /* set delay factor */
2510   g_rec_mutex_lock(core_audio_devout_mutex);
2511 
2512   core_audio_devout->delay_factor = delay_factor;
2513 
2514   g_rec_mutex_unlock(core_audio_devout_mutex);
2515 
2516   ags_core_audio_devout_adjust_delay_and_attack(core_audio_devout);
2517 }
2518 
2519 gdouble
ags_core_audio_devout_get_delay_factor(AgsSoundcard * soundcard)2520 ags_core_audio_devout_get_delay_factor(AgsSoundcard *soundcard)
2521 {
2522   AgsCoreAudioDevout *core_audio_devout;
2523 
2524   gdouble delay_factor;
2525 
2526   GRecMutex *core_audio_devout_mutex;
2527 
2528   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
2529 
2530   /* get core_audio devout mutex */
2531   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
2532 
2533   /* get delay factor */
2534   g_rec_mutex_lock(core_audio_devout_mutex);
2535 
2536   delay_factor = core_audio_devout->delay_factor;
2537 
2538   g_rec_mutex_unlock(core_audio_devout_mutex);
2539 
2540   return(delay_factor);
2541 }
2542 
2543 gdouble
ags_core_audio_devout_get_delay(AgsSoundcard * soundcard)2544 ags_core_audio_devout_get_delay(AgsSoundcard *soundcard)
2545 {
2546   AgsCoreAudioDevout *core_audio_devout;
2547 
2548   guint delay_index;
2549   gdouble delay;
2550 
2551   GRecMutex *core_audio_devout_mutex;
2552 
2553   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
2554 
2555   /* get core_audio devout mutex */
2556   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
2557 
2558   /* get delay */
2559   g_rec_mutex_lock(core_audio_devout_mutex);
2560 
2561   delay_index = core_audio_devout->tic_counter;
2562 
2563   delay = core_audio_devout->delay[delay_index];
2564 
2565   g_rec_mutex_unlock(core_audio_devout_mutex);
2566 
2567   return(delay);
2568 }
2569 
2570 gdouble
ags_core_audio_devout_get_absolute_delay(AgsSoundcard * soundcard)2571 ags_core_audio_devout_get_absolute_delay(AgsSoundcard *soundcard)
2572 {
2573   AgsCoreAudioDevout *core_audio_devout;
2574 
2575   gdouble absolute_delay;
2576 
2577   GRecMutex *core_audio_devout_mutex;
2578 
2579   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
2580 
2581   /* get core_audio devout mutex */
2582   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
2583 
2584   /* get absolute delay */
2585   g_rec_mutex_lock(core_audio_devout_mutex);
2586 
2587   absolute_delay = (60.0 * (((gdouble) core_audio_devout->samplerate / (gdouble) core_audio_devout->buffer_size) / (gdouble) core_audio_devout->bpm) * ((1.0 / 16.0) * (1.0 / (gdouble) core_audio_devout->delay_factor)));
2588 
2589   g_rec_mutex_unlock(core_audio_devout_mutex);
2590 
2591   return(absolute_delay);
2592 }
2593 
2594 guint
ags_core_audio_devout_get_attack(AgsSoundcard * soundcard)2595 ags_core_audio_devout_get_attack(AgsSoundcard *soundcard)
2596 {
2597   AgsCoreAudioDevout *core_audio_devout;
2598 
2599   guint attack_index;
2600   guint attack;
2601 
2602   GRecMutex *core_audio_devout_mutex;
2603 
2604   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
2605 
2606   /* get core_audio devout mutex */
2607   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
2608 
2609   /* get attack */
2610   g_rec_mutex_lock(core_audio_devout_mutex);
2611 
2612   attack_index = core_audio_devout->tic_counter;
2613 
2614   attack = core_audio_devout->attack[attack_index];
2615 
2616   g_rec_mutex_unlock(core_audio_devout_mutex);
2617 
2618   return(attack);
2619 }
2620 
2621 void*
ags_core_audio_devout_get_buffer(AgsSoundcard * soundcard)2622 ags_core_audio_devout_get_buffer(AgsSoundcard *soundcard)
2623 {
2624   AgsCoreAudioDevout *core_audio_devout;
2625 
2626   void *buffer;
2627 
2628   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
2629 
2630   if(ags_core_audio_devout_test_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_BUFFER0)){
2631     buffer = core_audio_devout->buffer[0];
2632   }else if(ags_core_audio_devout_test_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_BUFFER1)){
2633     buffer = core_audio_devout->buffer[1];
2634   }else if(ags_core_audio_devout_test_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_BUFFER2)){
2635     buffer = core_audio_devout->buffer[2];
2636   }else if(ags_core_audio_devout_test_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_BUFFER3)){
2637     buffer = core_audio_devout->buffer[3];
2638   }else if(ags_core_audio_devout_test_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_BUFFER4)){
2639     buffer = core_audio_devout->buffer[4];
2640   }else if(ags_core_audio_devout_test_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_BUFFER5)){
2641     buffer = core_audio_devout->buffer[5];
2642   }else if(ags_core_audio_devout_test_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_BUFFER6)){
2643     buffer = core_audio_devout->buffer[6];
2644   }else if(ags_core_audio_devout_test_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_BUFFER7)){
2645     buffer = core_audio_devout->buffer[7];
2646   }else{
2647     buffer = NULL;
2648   }
2649 
2650   return(buffer);
2651 }
2652 
2653 void*
ags_core_audio_devout_get_next_buffer(AgsSoundcard * soundcard)2654 ags_core_audio_devout_get_next_buffer(AgsSoundcard *soundcard)
2655 {
2656   AgsCoreAudioDevout *core_audio_devout;
2657 
2658   void *buffer;
2659 
2660   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
2661 
2662   if(ags_core_audio_devout_test_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_BUFFER0)){
2663     buffer = core_audio_devout->buffer[1];
2664   }else if(ags_core_audio_devout_test_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_BUFFER1)){
2665     buffer = core_audio_devout->buffer[2];
2666   }else if(ags_core_audio_devout_test_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_BUFFER2)){
2667     buffer = core_audio_devout->buffer[3];
2668   }else if(ags_core_audio_devout_test_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_BUFFER3)){
2669     buffer = core_audio_devout->buffer[4];
2670   }else if(ags_core_audio_devout_test_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_BUFFER4)){
2671     buffer = core_audio_devout->buffer[5];
2672   }else if(ags_core_audio_devout_test_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_BUFFER5)){
2673     buffer = core_audio_devout->buffer[6];
2674   }else if(ags_core_audio_devout_test_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_BUFFER6)){
2675     buffer = core_audio_devout->buffer[7];
2676   }else if(ags_core_audio_devout_test_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_BUFFER7)){
2677     buffer = core_audio_devout->buffer[0];
2678   }else{
2679     buffer = NULL;
2680   }
2681 
2682   return(buffer);
2683 }
2684 
2685 void*
ags_core_audio_devout_get_prev_buffer(AgsSoundcard * soundcard)2686 ags_core_audio_devout_get_prev_buffer(AgsSoundcard *soundcard)
2687 {
2688   AgsCoreAudioDevout *core_audio_devout;
2689 
2690   void *buffer;
2691 
2692   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
2693 
2694   if(ags_core_audio_devout_test_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_BUFFER0)){
2695     buffer = core_audio_devout->buffer[7];
2696   }else if(ags_core_audio_devout_test_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_BUFFER1)){
2697     buffer = core_audio_devout->buffer[0];
2698   }else if(ags_core_audio_devout_test_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_BUFFER2)){
2699     buffer = core_audio_devout->buffer[1];
2700   }else if(ags_core_audio_devout_test_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_BUFFER3)){
2701     buffer = core_audio_devout->buffer[2];
2702   }else if(ags_core_audio_devout_test_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_BUFFER4)){
2703     buffer = core_audio_devout->buffer[3];
2704   }else if(ags_core_audio_devout_test_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_BUFFER5)){
2705     buffer = core_audio_devout->buffer[4];
2706   }else if(ags_core_audio_devout_test_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_BUFFER6)){
2707     buffer = core_audio_devout->buffer[5];
2708   }else if(ags_core_audio_devout_test_flags(core_audio_devout, AGS_CORE_AUDIO_DEVOUT_BUFFER7)){
2709     buffer = core_audio_devout->buffer[6];
2710   }else{
2711     buffer = NULL;
2712   }
2713 
2714   return(buffer);
2715 }
2716 
2717 void
ags_core_audio_devout_lock_buffer(AgsSoundcard * soundcard,void * buffer)2718 ags_core_audio_devout_lock_buffer(AgsSoundcard *soundcard,
2719 				  void *buffer)
2720 {
2721   AgsCoreAudioDevout *core_audio_devout;
2722 
2723   GRecMutex *buffer_mutex;
2724 
2725   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
2726 
2727   buffer_mutex = NULL;
2728 
2729   if(core_audio_devout->buffer != NULL){
2730     if(buffer == core_audio_devout->buffer[0]){
2731       buffer_mutex = core_audio_devout->buffer_mutex[0];
2732     }else if(buffer == core_audio_devout->buffer[1]){
2733       buffer_mutex = core_audio_devout->buffer_mutex[1];
2734     }else if(buffer == core_audio_devout->buffer[2]){
2735       buffer_mutex = core_audio_devout->buffer_mutex[2];
2736     }else if(buffer == core_audio_devout->buffer[3]){
2737       buffer_mutex = core_audio_devout->buffer_mutex[3];
2738     }else if(buffer == core_audio_devout->buffer[4]){
2739       buffer_mutex = core_audio_devout->buffer_mutex[4];
2740     }else if(buffer == core_audio_devout->buffer[5]){
2741       buffer_mutex = core_audio_devout->buffer_mutex[5];
2742     }else if(buffer == core_audio_devout->buffer[6]){
2743       buffer_mutex = core_audio_devout->buffer_mutex[6];
2744     }else if(buffer == core_audio_devout->buffer[7]){
2745       buffer_mutex = core_audio_devout->buffer_mutex[7];
2746     }
2747   }
2748 
2749   if(buffer_mutex != NULL){
2750     g_rec_mutex_lock(buffer_mutex);
2751   }
2752 }
2753 
2754 void
ags_core_audio_devout_unlock_buffer(AgsSoundcard * soundcard,void * buffer)2755 ags_core_audio_devout_unlock_buffer(AgsSoundcard *soundcard,
2756 				    void *buffer)
2757 {
2758   AgsCoreAudioDevout *core_audio_devout;
2759 
2760   GRecMutex *buffer_mutex;
2761 
2762   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
2763 
2764   buffer_mutex = NULL;
2765 
2766   if(core_audio_devout->buffer != NULL){
2767     if(buffer == core_audio_devout->buffer[0]){
2768       buffer_mutex = core_audio_devout->buffer_mutex[0];
2769     }else if(buffer == core_audio_devout->buffer[1]){
2770       buffer_mutex = core_audio_devout->buffer_mutex[1];
2771     }else if(buffer == core_audio_devout->buffer[2]){
2772       buffer_mutex = core_audio_devout->buffer_mutex[2];
2773     }else if(buffer == core_audio_devout->buffer[3]){
2774       buffer_mutex = core_audio_devout->buffer_mutex[3];
2775     }else if(buffer == core_audio_devout->buffer[4]){
2776       buffer_mutex = core_audio_devout->buffer_mutex[4];
2777     }else if(buffer == core_audio_devout->buffer[5]){
2778       buffer_mutex = core_audio_devout->buffer_mutex[5];
2779     }else if(buffer == core_audio_devout->buffer[6]){
2780       buffer_mutex = core_audio_devout->buffer_mutex[6];
2781     }else if(buffer == core_audio_devout->buffer[7]){
2782       buffer_mutex = core_audio_devout->buffer_mutex[7];
2783     }
2784   }
2785 
2786   if(buffer_mutex != NULL){
2787     g_rec_mutex_unlock(buffer_mutex);
2788   }
2789 }
2790 
2791 guint
ags_core_audio_devout_get_delay_counter(AgsSoundcard * soundcard)2792 ags_core_audio_devout_get_delay_counter(AgsSoundcard *soundcard)
2793 {
2794   AgsCoreAudioDevout *core_audio_devout;
2795 
2796   guint delay_counter;
2797 
2798   GRecMutex *core_audio_devout_mutex;
2799 
2800   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
2801 
2802   /* get core_audio devout mutex */
2803   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
2804 
2805   /* delay counter */
2806   g_rec_mutex_lock(core_audio_devout_mutex);
2807 
2808   delay_counter = core_audio_devout->delay_counter;
2809 
2810   g_rec_mutex_unlock(core_audio_devout_mutex);
2811 
2812   return(delay_counter);
2813 }
2814 
2815 void
ags_core_audio_devout_set_start_note_offset(AgsSoundcard * soundcard,guint start_note_offset)2816 ags_core_audio_devout_set_start_note_offset(AgsSoundcard *soundcard,
2817 					    guint start_note_offset)
2818 {
2819   AgsCoreAudioDevout *core_audio_devout;
2820 
2821   GRecMutex *core_audio_devout_mutex;
2822 
2823   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
2824 
2825   /* get core_audio devout mutex */
2826   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
2827 
2828   /* set note offset */
2829   g_rec_mutex_lock(core_audio_devout_mutex);
2830 
2831   core_audio_devout->start_note_offset = start_note_offset;
2832 
2833   g_rec_mutex_unlock(core_audio_devout_mutex);
2834 }
2835 
2836 guint
ags_core_audio_devout_get_start_note_offset(AgsSoundcard * soundcard)2837 ags_core_audio_devout_get_start_note_offset(AgsSoundcard *soundcard)
2838 {
2839   AgsCoreAudioDevout *core_audio_devout;
2840 
2841   guint start_note_offset;
2842 
2843   GRecMutex *core_audio_devout_mutex;
2844 
2845   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
2846 
2847   /* get core_audio devout mutex */
2848   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
2849 
2850   /* set note offset */
2851   g_rec_mutex_lock(core_audio_devout_mutex);
2852 
2853   start_note_offset = core_audio_devout->start_note_offset;
2854 
2855   g_rec_mutex_unlock(core_audio_devout_mutex);
2856 
2857   return(start_note_offset);
2858 }
2859 
2860 void
ags_core_audio_devout_set_note_offset(AgsSoundcard * soundcard,guint note_offset)2861 ags_core_audio_devout_set_note_offset(AgsSoundcard *soundcard,
2862 				      guint note_offset)
2863 {
2864   AgsCoreAudioDevout *core_audio_devout;
2865 
2866   GRecMutex *core_audio_devout_mutex;
2867 
2868   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
2869 
2870   /* get core_audio devout mutex */
2871   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
2872 
2873   /* set note offset */
2874   g_rec_mutex_lock(core_audio_devout_mutex);
2875 
2876   core_audio_devout->note_offset = note_offset;
2877 
2878   g_rec_mutex_unlock(core_audio_devout_mutex);
2879 }
2880 
2881 guint
ags_core_audio_devout_get_note_offset(AgsSoundcard * soundcard)2882 ags_core_audio_devout_get_note_offset(AgsSoundcard *soundcard)
2883 {
2884   AgsCoreAudioDevout *core_audio_devout;
2885 
2886   guint note_offset;
2887 
2888   GRecMutex *core_audio_devout_mutex;
2889 
2890   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
2891 
2892   /* get core_audio devout mutex */
2893   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
2894 
2895   /* set note offset */
2896   g_rec_mutex_lock(core_audio_devout_mutex);
2897 
2898   note_offset = core_audio_devout->note_offset;
2899 
2900   g_rec_mutex_unlock(core_audio_devout_mutex);
2901 
2902   return(note_offset);
2903 }
2904 
2905 void
ags_core_audio_devout_set_note_offset_absolute(AgsSoundcard * soundcard,guint note_offset_absolute)2906 ags_core_audio_devout_set_note_offset_absolute(AgsSoundcard *soundcard,
2907 					 guint note_offset_absolute)
2908 {
2909   AgsCoreAudioDevout *core_audio_devout;
2910 
2911   GRecMutex *core_audio_devout_mutex;
2912 
2913   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
2914 
2915   /* get core_audio devout mutex */
2916   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
2917 
2918   /* set note offset */
2919   g_rec_mutex_lock(core_audio_devout_mutex);
2920 
2921   core_audio_devout->note_offset_absolute = note_offset_absolute;
2922 
2923   g_rec_mutex_unlock(core_audio_devout_mutex);
2924 }
2925 
2926 guint
ags_core_audio_devout_get_note_offset_absolute(AgsSoundcard * soundcard)2927 ags_core_audio_devout_get_note_offset_absolute(AgsSoundcard *soundcard)
2928 {
2929   AgsCoreAudioDevout *core_audio_devout;
2930 
2931   guint note_offset_absolute;
2932 
2933   GRecMutex *core_audio_devout_mutex;
2934 
2935   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
2936 
2937   /* get core_audio devout mutex */
2938   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
2939 
2940   /* set note offset */
2941   g_rec_mutex_lock(core_audio_devout_mutex);
2942 
2943   note_offset_absolute = core_audio_devout->note_offset_absolute;
2944 
2945   g_rec_mutex_unlock(core_audio_devout_mutex);
2946 
2947   return(note_offset_absolute);
2948 }
2949 
2950 void
ags_core_audio_devout_set_loop(AgsSoundcard * soundcard,guint loop_left,guint loop_right,gboolean do_loop)2951 ags_core_audio_devout_set_loop(AgsSoundcard *soundcard,
2952 			       guint loop_left, guint loop_right,
2953 			       gboolean do_loop)
2954 {
2955   AgsCoreAudioDevout *core_audio_devout;
2956 
2957   GRecMutex *core_audio_devout_mutex;
2958 
2959   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
2960 
2961   /* get core_audio devout mutex */
2962   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
2963 
2964   /* set loop */
2965   g_rec_mutex_lock(core_audio_devout_mutex);
2966 
2967   core_audio_devout->loop_left = loop_left;
2968   core_audio_devout->loop_right = loop_right;
2969   core_audio_devout->do_loop = do_loop;
2970 
2971   if(do_loop){
2972     core_audio_devout->loop_offset = core_audio_devout->note_offset;
2973   }
2974 
2975   g_rec_mutex_unlock(core_audio_devout_mutex);
2976 }
2977 
2978 void
ags_core_audio_devout_get_loop(AgsSoundcard * soundcard,guint * loop_left,guint * loop_right,gboolean * do_loop)2979 ags_core_audio_devout_get_loop(AgsSoundcard *soundcard,
2980 			       guint *loop_left, guint *loop_right,
2981 			       gboolean *do_loop)
2982 {
2983   AgsCoreAudioDevout *core_audio_devout;
2984 
2985   GRecMutex *core_audio_devout_mutex;
2986 
2987   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
2988 
2989   /* get core_audio devout mutex */
2990   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
2991 
2992   /* get loop */
2993   g_rec_mutex_lock(core_audio_devout_mutex);
2994 
2995   if(loop_left != NULL){
2996     *loop_left = core_audio_devout->loop_left;
2997   }
2998 
2999   if(loop_right != NULL){
3000     *loop_right = core_audio_devout->loop_right;
3001   }
3002 
3003   if(do_loop != NULL){
3004     *do_loop = core_audio_devout->do_loop;
3005   }
3006 
3007   g_rec_mutex_unlock(core_audio_devout_mutex);
3008 }
3009 
3010 guint
ags_core_audio_devout_get_loop_offset(AgsSoundcard * soundcard)3011 ags_core_audio_devout_get_loop_offset(AgsSoundcard *soundcard)
3012 {
3013   AgsCoreAudioDevout *core_audio_devout;
3014 
3015   guint loop_offset;
3016 
3017   GRecMutex *core_audio_devout_mutex;
3018 
3019   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
3020 
3021   /* get core_audio devout mutex */
3022   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
3023 
3024   /* get loop offset */
3025   g_rec_mutex_lock(core_audio_devout_mutex);
3026 
3027   loop_offset = core_audio_devout->loop_offset;
3028 
3029   g_rec_mutex_unlock(core_audio_devout_mutex);
3030 
3031   return(loop_offset);
3032 }
3033 
3034 guint
ags_core_audio_devout_get_sub_block_count(AgsSoundcard * soundcard)3035 ags_core_audio_devout_get_sub_block_count(AgsSoundcard *soundcard)
3036 {
3037   AgsCoreAudioDevout *core_audio_devout;
3038 
3039   guint sub_block_count;
3040 
3041   GRecMutex *core_audio_devout_mutex;
3042 
3043   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
3044 
3045   /* get core_audio devout mutex */
3046   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
3047 
3048   /* get loop offset */
3049   g_rec_mutex_lock(core_audio_devout_mutex);
3050 
3051   sub_block_count = core_audio_devout->sub_block_count;
3052 
3053   g_rec_mutex_unlock(core_audio_devout_mutex);
3054 
3055   return(sub_block_count);
3056 }
3057 
3058 gboolean
ags_core_audio_devout_trylock_sub_block(AgsSoundcard * soundcard,void * buffer,guint sub_block)3059 ags_core_audio_devout_trylock_sub_block(AgsSoundcard *soundcard,
3060 					void *buffer, guint sub_block)
3061 {
3062   AgsCoreAudioDevout *core_audio_devout;
3063 
3064   guint pcm_channels;
3065   guint sub_block_count;
3066   gboolean success;
3067 
3068   GRecMutex *core_audio_devout_mutex;
3069   GRecMutex *sub_block_mutex;
3070 
3071   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
3072 
3073   /* get core_audio devout mutex */
3074   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
3075 
3076   /* get loop offset */
3077   g_rec_mutex_lock(core_audio_devout_mutex);
3078 
3079   pcm_channels = core_audio_devout->pcm_channels;
3080   sub_block_count = core_audio_devout->sub_block_count;
3081 
3082   g_rec_mutex_unlock(core_audio_devout_mutex);
3083 
3084   sub_block_mutex = NULL;
3085 
3086   success = FALSE;
3087 
3088   if(core_audio_devout->buffer != NULL){
3089     if(buffer == core_audio_devout->buffer[0]){
3090       sub_block_mutex = core_audio_devout->sub_block_mutex[sub_block];
3091     }else if(buffer == core_audio_devout->buffer[1]){
3092       sub_block_mutex = core_audio_devout->sub_block_mutex[pcm_channels * sub_block_count + sub_block];
3093     }else if(buffer == core_audio_devout->buffer[2]){
3094       sub_block_mutex = core_audio_devout->sub_block_mutex[2 * pcm_channels * sub_block_count + sub_block];
3095     }else if(buffer == core_audio_devout->buffer[3]){
3096       sub_block_mutex = core_audio_devout->sub_block_mutex[3 * pcm_channels * sub_block_count + sub_block];
3097     }else if(buffer == core_audio_devout->buffer[4]){
3098       sub_block_mutex = core_audio_devout->sub_block_mutex[4 * pcm_channels * sub_block_count + sub_block];
3099     }else if(buffer == core_audio_devout->buffer[5]){
3100       sub_block_mutex = core_audio_devout->sub_block_mutex[5 * pcm_channels * sub_block_count + sub_block];
3101     }else if(buffer == core_audio_devout->buffer[6]){
3102       sub_block_mutex = core_audio_devout->sub_block_mutex[6 * pcm_channels * sub_block_count + sub_block];
3103     }else if(buffer == core_audio_devout->buffer[7]){
3104       sub_block_mutex = core_audio_devout->sub_block_mutex[7 * pcm_channels * sub_block_count + sub_block];
3105     }
3106   }
3107 
3108   if(sub_block_mutex != NULL){
3109     if(g_rec_mutex_trylock(sub_block_mutex)){
3110       success = TRUE;
3111     }
3112   }
3113 
3114   return(success);
3115 }
3116 
3117 void
ags_core_audio_devout_unlock_sub_block(AgsSoundcard * soundcard,void * buffer,guint sub_block)3118 ags_core_audio_devout_unlock_sub_block(AgsSoundcard *soundcard,
3119 				       void *buffer, guint sub_block)
3120 {
3121   AgsCoreAudioDevout *core_audio_devout;
3122 
3123   guint pcm_channels;
3124   guint sub_block_count;
3125 
3126   GRecMutex *core_audio_devout_mutex;
3127   GRecMutex *sub_block_mutex;
3128 
3129   core_audio_devout = AGS_CORE_AUDIO_DEVOUT(soundcard);
3130 
3131   /* get core_audio devout mutex */
3132   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
3133 
3134   /* get loop offset */
3135   g_rec_mutex_lock(core_audio_devout_mutex);
3136 
3137   pcm_channels = core_audio_devout->pcm_channels;
3138   sub_block_count = core_audio_devout->sub_block_count;
3139 
3140   g_rec_mutex_unlock(core_audio_devout_mutex);
3141 
3142   sub_block_mutex = NULL;
3143 
3144   if(core_audio_devout->buffer != NULL){
3145     if(buffer == core_audio_devout->buffer[0]){
3146       sub_block_mutex = core_audio_devout->sub_block_mutex[sub_block];
3147     }else if(buffer == core_audio_devout->buffer[1]){
3148       sub_block_mutex = core_audio_devout->sub_block_mutex[pcm_channels * sub_block_count + sub_block];
3149     }else if(buffer == core_audio_devout->buffer[2]){
3150       sub_block_mutex = core_audio_devout->sub_block_mutex[2 * pcm_channels * sub_block_count + sub_block];
3151     }else if(buffer == core_audio_devout->buffer[3]){
3152       sub_block_mutex = core_audio_devout->sub_block_mutex[3 * pcm_channels * sub_block_count + sub_block];
3153     }else if(buffer == core_audio_devout->buffer[4]){
3154       sub_block_mutex = core_audio_devout->sub_block_mutex[4 * pcm_channels * sub_block_count + sub_block];
3155     }else if(buffer == core_audio_devout->buffer[5]){
3156       sub_block_mutex = core_audio_devout->sub_block_mutex[5 * pcm_channels * sub_block_count + sub_block];
3157     }else if(buffer == core_audio_devout->buffer[6]){
3158       sub_block_mutex = core_audio_devout->sub_block_mutex[6 * pcm_channels * sub_block_count + sub_block];
3159     }else if(buffer == core_audio_devout->buffer[7]){
3160       sub_block_mutex = core_audio_devout->sub_block_mutex[7 * pcm_channels * sub_block_count + sub_block];
3161     }
3162   }
3163 
3164   if(sub_block_mutex != NULL){
3165     g_rec_mutex_unlock(sub_block_mutex);
3166   }
3167 }
3168 
3169 /**
3170  * ags_core_audio_devout_switch_buffer_flag:
3171  * @core_audio_devout: an #AgsCoreAudioDevout
3172  *
3173  * The buffer flag indicates the currently played buffer.
3174  *
3175  * Since: 3.0.0
3176  */
3177 void
ags_core_audio_devout_switch_buffer_flag(AgsCoreAudioDevout * core_audio_devout)3178 ags_core_audio_devout_switch_buffer_flag(AgsCoreAudioDevout *core_audio_devout)
3179 {
3180   GRecMutex *core_audio_devout_mutex;
3181 
3182   if(!AGS_IS_CORE_AUDIO_DEVOUT(core_audio_devout)){
3183     return;
3184   }
3185 
3186   /* get core_audio devout mutex */
3187   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
3188 
3189   /* switch buffer flag */
3190   g_rec_mutex_lock(core_audio_devout_mutex);
3191 
3192   if((AGS_CORE_AUDIO_DEVOUT_BUFFER0 & (core_audio_devout->flags)) != 0){
3193     core_audio_devout->flags &= (~AGS_CORE_AUDIO_DEVOUT_BUFFER0);
3194     core_audio_devout->flags |= AGS_CORE_AUDIO_DEVOUT_BUFFER1;
3195   }else if((AGS_CORE_AUDIO_DEVOUT_BUFFER1 & (core_audio_devout->flags)) != 0){
3196     core_audio_devout->flags &= (~AGS_CORE_AUDIO_DEVOUT_BUFFER1);
3197     core_audio_devout->flags |= AGS_CORE_AUDIO_DEVOUT_BUFFER2;
3198   }else if((AGS_CORE_AUDIO_DEVOUT_BUFFER2 & (core_audio_devout->flags)) != 0){
3199     core_audio_devout->flags &= (~AGS_CORE_AUDIO_DEVOUT_BUFFER2);
3200     core_audio_devout->flags |= AGS_CORE_AUDIO_DEVOUT_BUFFER3;
3201   }else if((AGS_CORE_AUDIO_DEVOUT_BUFFER3 & (core_audio_devout->flags)) != 0){
3202     core_audio_devout->flags &= (~AGS_CORE_AUDIO_DEVOUT_BUFFER3);
3203     core_audio_devout->flags |= AGS_CORE_AUDIO_DEVOUT_BUFFER4;
3204   }else if((AGS_CORE_AUDIO_DEVOUT_BUFFER4 & (core_audio_devout->flags)) != 0){
3205     core_audio_devout->flags &= (~AGS_CORE_AUDIO_DEVOUT_BUFFER4);
3206     core_audio_devout->flags |= AGS_CORE_AUDIO_DEVOUT_BUFFER5;
3207   }else if((AGS_CORE_AUDIO_DEVOUT_BUFFER5 & (core_audio_devout->flags)) != 0){
3208     core_audio_devout->flags &= (~AGS_CORE_AUDIO_DEVOUT_BUFFER5);
3209     core_audio_devout->flags |= AGS_CORE_AUDIO_DEVOUT_BUFFER6;
3210   }else if((AGS_CORE_AUDIO_DEVOUT_BUFFER6 & (core_audio_devout->flags)) != 0){
3211     core_audio_devout->flags &= (~AGS_CORE_AUDIO_DEVOUT_BUFFER6);
3212     core_audio_devout->flags |= AGS_CORE_AUDIO_DEVOUT_BUFFER7;
3213   }else if((AGS_CORE_AUDIO_DEVOUT_BUFFER7 & (core_audio_devout->flags)) != 0){
3214     core_audio_devout->flags &= (~AGS_CORE_AUDIO_DEVOUT_BUFFER7);
3215     core_audio_devout->flags |= AGS_CORE_AUDIO_DEVOUT_BUFFER0;
3216   }
3217 
3218   g_rec_mutex_unlock(core_audio_devout_mutex);
3219 }
3220 
3221 /**
3222  * ags_core_audio_devout_adjust_delay_and_attack:
3223  * @core_audio_devout: the #AgsCoreAudioDevout
3224  *
3225  * Calculate delay and attack and reset it.
3226  *
3227  * Since: 3.0.0
3228  */
3229 void
ags_core_audio_devout_adjust_delay_and_attack(AgsCoreAudioDevout * core_audio_devout)3230 ags_core_audio_devout_adjust_delay_and_attack(AgsCoreAudioDevout *core_audio_devout)
3231 {
3232   if(!AGS_IS_CORE_AUDIO_DEVOUT(core_audio_devout)){
3233     return;
3234   }
3235 
3236   ags_soundcard_util_adjust_delay_and_attack(core_audio_devout);
3237 }
3238 
3239 /**
3240  * ags_core_audio_devout_realloc_buffer:
3241  * @core_audio_devout: the #AgsCoreAudioDevout
3242  *
3243  * Reallocate the internal audio buffer.
3244  *
3245  * Since: 3.0.0
3246  */
3247 void
ags_core_audio_devout_realloc_buffer(AgsCoreAudioDevout * core_audio_devout)3248 ags_core_audio_devout_realloc_buffer(AgsCoreAudioDevout *core_audio_devout)
3249 {
3250   guint pcm_channels;
3251   guint buffer_size;
3252   guint format;
3253   guint word_size;
3254 
3255   GRecMutex *core_audio_devout_mutex;
3256 
3257   if(!AGS_IS_CORE_AUDIO_DEVOUT(core_audio_devout)){
3258     return;
3259   }
3260 
3261   /* get core_audio devout mutex */
3262   core_audio_devout_mutex = AGS_CORE_AUDIO_DEVOUT_GET_OBJ_MUTEX(core_audio_devout);
3263 
3264   /* get word size */
3265   g_rec_mutex_lock(core_audio_devout_mutex);
3266 
3267   pcm_channels = core_audio_devout->pcm_channels;
3268   buffer_size = core_audio_devout->buffer_size;
3269 
3270   format = core_audio_devout->format;
3271 
3272   g_rec_mutex_unlock(core_audio_devout_mutex);
3273 
3274   switch(format){
3275   case AGS_SOUNDCARD_SIGNED_16_BIT:
3276     {
3277       word_size = sizeof(gint16);
3278     }
3279     break;
3280   case AGS_SOUNDCARD_SIGNED_24_BIT:
3281     {
3282       word_size = sizeof(gint32);
3283     }
3284     break;
3285   case AGS_SOUNDCARD_SIGNED_32_BIT:
3286     {
3287       word_size = sizeof(gint32);
3288     }
3289     break;
3290   default:
3291     g_warning("ags_core_audio_devout_realloc_buffer(): unsupported word size");
3292     return;
3293   }
3294 
3295   /* AGS_CORE_AUDIO_DEVOUT_BUFFER_0 */
3296   if(core_audio_devout->buffer[0] != NULL){
3297     free(core_audio_devout->buffer[0]);
3298   }
3299 
3300   core_audio_devout->buffer[0] = (void *) malloc(pcm_channels * buffer_size * word_size);
3301 
3302   /* AGS_CORE_AUDIO_DEVOUT_BUFFER_1 */
3303   if(core_audio_devout->buffer[1] != NULL){
3304     free(core_audio_devout->buffer[1]);
3305   }
3306 
3307   core_audio_devout->buffer[1] = (void *) malloc(pcm_channels * buffer_size * word_size);
3308 
3309   /* AGS_CORE_AUDIO_DEVOUT_BUFFER_2 */
3310   if(core_audio_devout->buffer[2] != NULL){
3311     free(core_audio_devout->buffer[2]);
3312   }
3313 
3314   core_audio_devout->buffer[2] = (void *) malloc(pcm_channels * buffer_size * word_size);
3315 
3316   /* AGS_CORE_AUDIO_DEVOUT_BUFFER_3 */
3317   if(core_audio_devout->buffer[3] != NULL){
3318     free(core_audio_devout->buffer[3]);
3319   }
3320 
3321   core_audio_devout->buffer[3] = (void *) malloc(pcm_channels * buffer_size * word_size);
3322 
3323   /* AGS_CORE_AUDIO_DEVOUT_BUFFER_4 */
3324   if(core_audio_devout->buffer[4] != NULL){
3325     free(core_audio_devout->buffer[4]);
3326   }
3327 
3328   core_audio_devout->buffer[4] = (void *) malloc(pcm_channels * buffer_size * word_size);
3329 
3330   /* AGS_CORE_AUDIO_DEVOUT_BUFFER_5 */
3331   if(core_audio_devout->buffer[5] != NULL){
3332     free(core_audio_devout->buffer[5]);
3333   }
3334 
3335   core_audio_devout->buffer[5] = (void *) malloc(pcm_channels * buffer_size * word_size);
3336 
3337   /* AGS_CORE_AUDIO_DEVOUT_BUFFER_6 */
3338   if(core_audio_devout->buffer[6] != NULL){
3339     free(core_audio_devout->buffer[6]);
3340   }
3341 
3342   core_audio_devout->buffer[6] = (void *) malloc(pcm_channels * buffer_size * word_size);
3343 
3344   /* AGS_CORE_AUDIO_DEVOUT_BUFFER_7 */
3345   if(core_audio_devout->buffer[7] != NULL){
3346     free(core_audio_devout->buffer[7]);
3347   }
3348 
3349   core_audio_devout->buffer[7] = (void *) malloc(pcm_channels * buffer_size * word_size);
3350 }
3351 
3352 /**
3353  * ags_core_audio_devout_new:
3354  *
3355  * Creates a new instance of #AgsCoreAudioDevout.
3356  *
3357  * Returns: a new #AgsCoreAudioDevout
3358  *
3359  * Since: 3.0.0
3360  */
3361 AgsCoreAudioDevout*
ags_core_audio_devout_new()3362 ags_core_audio_devout_new()
3363 {
3364   AgsCoreAudioDevout *core_audio_devout;
3365 
3366   core_audio_devout = (AgsCoreAudioDevout *) g_object_new(AGS_TYPE_CORE_AUDIO_DEVOUT,
3367 							  NULL);
3368 
3369   return(core_audio_devout);
3370 }
3371