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