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