1 /* GSequencer - Advanced GTK Sequencer
2  * Copyright (C) 2005-2021 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/ags_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/task/ags_tic_device.h>
27 #include <ags/audio/task/ags_clear_buffer.h>
28 #include <ags/audio/task/ags_switch_buffer_flag.h>
29 
30 #include <sys/stat.h>
31 #include <sys/types.h>
32 
33 #ifndef AGS_W32API
34 #include <fcntl.h>
35 #include <sys/ioctl.h>
36 
37 #ifndef __APPLE__
38 #include <sys/soundcard.h>
39 #endif
40 #endif
41 #include <errno.h>
42 
43 #define _GNU_SOURCE
44 #include <signal.h>
45 
46 #include <string.h>
47 #include <math.h>
48 
49 #include <time.h>
50 #include <signal.h>
51 #include <strings.h>
52 #include <unistd.h>
53 
54 #include <ags/config.h>
55 #include <ags/i18n.h>
56 
57 void ags_devout_class_init(AgsDevoutClass *devout);
58 void ags_devout_connectable_interface_init(AgsConnectableInterface *connectable);
59 void ags_devout_soundcard_interface_init(AgsSoundcardInterface *soundcard);
60 void ags_devout_init(AgsDevout *devout);
61 void ags_devout_set_property(GObject *gobject,
62 			     guint prop_id,
63 			     const GValue *value,
64 			     GParamSpec *param_spec);
65 void ags_devout_get_property(GObject *gobject,
66 			     guint prop_id,
67 			     GValue *value,
68 			     GParamSpec *param_spec);
69 void ags_devout_dispose(GObject *gobject);
70 void ags_devout_finalize(GObject *gobject);
71 
72 AgsUUID* ags_devout_get_uuid(AgsConnectable *connectable);
73 gboolean ags_devout_has_resource(AgsConnectable *connectable);
74 gboolean ags_devout_is_ready(AgsConnectable *connectable);
75 void ags_devout_add_to_registry(AgsConnectable *connectable);
76 void ags_devout_remove_from_registry(AgsConnectable *connectable);
77 xmlNode* ags_devout_list_resource(AgsConnectable *connectable);
78 xmlNode* ags_devout_xml_compose(AgsConnectable *connectable);
79 void ags_devout_xml_parse(AgsConnectable *connectable,
80 			   xmlNode *node);
81 gboolean ags_devout_is_connected(AgsConnectable *connectable);
82 void ags_devout_connect(AgsConnectable *connectable);
83 void ags_devout_disconnect(AgsConnectable *connectable);
84 
85 void ags_devout_set_device(AgsSoundcard *soundcard,
86 			   gchar *device);
87 gchar* ags_devout_get_device(AgsSoundcard *soundcard);
88 
89 void ags_devout_set_presets(AgsSoundcard *soundcard,
90 			    guint channels,
91 			    guint rate,
92 			    guint buffer_size,
93 			    guint format);
94 void ags_devout_get_presets(AgsSoundcard *soundcard,
95 			    guint *channels,
96 			    guint *rate,
97 			    guint *buffer_size,
98 			    guint *format);
99 
100 void ags_devout_list_cards(AgsSoundcard *soundcard,
101 			   GList **card_id, GList **card_name);
102 void ags_devout_pcm_info(AgsSoundcard *soundcard, gchar *card_id,
103 			 guint *channels_min, guint *channels_max,
104 			 guint *rate_min, guint *rate_max,
105 			 guint *buffer_size_min, guint *buffer_size_max,
106 			 GError **error);
107 guint ags_devout_get_capability(AgsSoundcard *soundcard);
108 
109 gboolean ags_devout_is_available(AgsSoundcard *soundcard);
110 
111 gboolean ags_devout_is_starting(AgsSoundcard *soundcard);
112 gboolean ags_devout_is_playing(AgsSoundcard *soundcard);
113 
114 gchar* ags_devout_get_uptime(AgsSoundcard *soundcard);
115 
116 void ags_devout_delegate_play_init(AgsSoundcard *soundcard,
117 				   GError **error);
118 void ags_devout_delegate_play(AgsSoundcard *soundcard,
119 			      GError **error);
120 void ags_devout_delegate_stop(AgsSoundcard *soundcard);
121 
122 void ags_devout_oss_init(AgsSoundcard *soundcard,
123 			 GError **error);
124 void ags_devout_oss_play_fill_ring_buffer(void *buffer,
125 					  guint ags_format,
126 					  unsigned char *ring_buffer,
127 					  guint channels,
128 					  guint buffer_size);
129 
130 gboolean ags_devout_oss_io_func(GIOChannel *source,
131 				GIOCondition condition,
132 				AgsDevout *devout);
133 
134 void ags_devout_oss_play(AgsSoundcard *soundcard,
135 			 GError **error);
136 void ags_devout_oss_free(AgsSoundcard *soundcard);
137 
138 gboolean ags_devout_alsa_io_func(GIOChannel *source,
139 				 GIOCondition condition,
140 				 AgsDevout *devout);
141 
142 void ags_devout_alsa_init(AgsSoundcard *soundcard,
143 			  GError **error);
144 void ags_devout_alsa_play_fill_ring_buffer(void *buffer,
145 					   guint ags_format,
146 					   unsigned char *ring_buffer,
147 					   guint channels,
148 					   guint buffer_size);
149 void ags_devout_alsa_play(AgsSoundcard *soundcard,
150 			  GError **error);
151 void ags_devout_alsa_free(AgsSoundcard *soundcard);
152 
153 void ags_devout_tic(AgsSoundcard *soundcard);
154 void ags_devout_offset_changed(AgsSoundcard *soundcard,
155 			       guint note_offset);
156 
157 void ags_devout_set_bpm(AgsSoundcard *soundcard,
158 			gdouble bpm);
159 gdouble ags_devout_get_bpm(AgsSoundcard *soundcard);
160 
161 void ags_devout_set_delay_factor(AgsSoundcard *soundcard,
162 				 gdouble delay_factor);
163 gdouble ags_devout_get_delay_factor(AgsSoundcard *soundcard);
164 
165 gdouble ags_devout_get_absolute_delay(AgsSoundcard *soundcard);
166 
167 gdouble ags_devout_get_delay(AgsSoundcard *soundcard);
168 guint ags_devout_get_attack(AgsSoundcard *soundcard);
169 
170 void* ags_devout_get_buffer(AgsSoundcard *soundcard);
171 void* ags_devout_get_next_buffer(AgsSoundcard *soundcard);
172 void* ags_devout_get_prev_buffer(AgsSoundcard *soundcard);
173 
174 void ags_devout_lock_buffer(AgsSoundcard *soundcard,
175 			    void *buffer);
176 void ags_devout_unlock_buffer(AgsSoundcard *soundcard,
177 			      void *buffer);
178 
179 guint ags_devout_get_delay_counter(AgsSoundcard *soundcard);
180 
181 void ags_devout_set_start_note_offset(AgsSoundcard *soundcard,
182 				      guint start_note_offset);
183 guint ags_devout_get_start_note_offset(AgsSoundcard *soundcard);
184 
185 void ags_devout_set_note_offset(AgsSoundcard *soundcard,
186 				guint note_offset);
187 guint ags_devout_get_note_offset(AgsSoundcard *soundcard);
188 
189 void ags_devout_set_note_offset_absolute(AgsSoundcard *soundcard,
190 					 guint note_offset);
191 guint ags_devout_get_note_offset_absolute(AgsSoundcard *soundcard);
192 
193 void ags_devout_set_loop(AgsSoundcard *soundcard,
194 			 guint loop_left, guint loop_right,
195 			 gboolean do_loop);
196 void ags_devout_get_loop(AgsSoundcard *soundcard,
197 			 guint *loop_left, guint *loop_right,
198 			 gboolean *do_loop);
199 
200 guint ags_devout_get_loop_offset(AgsSoundcard *soundcard);
201 
202 guint ags_devout_get_sub_block_count(AgsSoundcard *soundcard);
203 
204 gboolean ags_devout_trylock_sub_block(AgsSoundcard *soundcard,
205 				      void *buffer, guint sub_block);
206 void ags_devout_unlock_sub_block(AgsSoundcard *soundcard,
207 				 void *buffer, guint sub_block);
208 
209 /**
210  * SECTION:ags_devout
211  * @short_description: Output to soundcard
212  * @title: AgsDevout
213  * @section_id:
214  * @include: ags/audio/ags_devout.h
215  *
216  * #AgsDevout represents a soundcard and supports output.
217  */
218 
219 enum{
220   PROP_0,
221   PROP_DEVICE,
222   PROP_DSP_CHANNELS,
223   PROP_PCM_CHANNELS,
224   PROP_FORMAT,
225   PROP_BUFFER_SIZE,
226   PROP_SAMPLERATE,
227   PROP_BUFFER,
228   PROP_BPM,
229   PROP_DELAY_FACTOR,
230   PROP_ATTACK,
231 };
232 
233 static gpointer ags_devout_parent_class = NULL;
234 
235 GType
ags_devout_get_type(void)236 ags_devout_get_type (void)
237 {
238   static volatile gsize g_define_type_id__volatile = 0;
239 
240   if(g_once_init_enter (&g_define_type_id__volatile)){
241     GType ags_type_devout = 0;
242 
243     static const GTypeInfo ags_devout_info = {
244       sizeof(AgsDevoutClass),
245       NULL, /* base_init */
246       NULL, /* base_finalize */
247       (GClassInitFunc) ags_devout_class_init,
248       NULL, /* class_finalize */
249       NULL, /* class_data */
250       sizeof(AgsDevout),
251       0,    /* n_preallocs */
252       (GInstanceInitFunc) ags_devout_init,
253     };
254 
255     static const GInterfaceInfo ags_connectable_interface_info = {
256       (GInterfaceInitFunc) ags_devout_connectable_interface_init,
257       NULL, /* interface_finalize */
258       NULL, /* interface_data */
259     };
260 
261     static const GInterfaceInfo ags_soundcard_interface_info = {
262       (GInterfaceInitFunc) ags_devout_soundcard_interface_init,
263       NULL, /* interface_finalize */
264       NULL, /* interface_data */
265     };
266 
267     ags_type_devout = g_type_register_static(G_TYPE_OBJECT,
268 					     "AgsDevout",
269 					     &ags_devout_info,
270 					     0);
271 
272     g_type_add_interface_static(ags_type_devout,
273 				AGS_TYPE_CONNECTABLE,
274 				&ags_connectable_interface_info);
275 
276     g_type_add_interface_static(ags_type_devout,
277 				AGS_TYPE_SOUNDCARD,
278 				&ags_soundcard_interface_info);
279 
280     g_once_init_leave(&g_define_type_id__volatile, ags_type_devout);
281   }
282 
283   return g_define_type_id__volatile;
284 }
285 
286 GType
ags_devout_flags_get_type()287 ags_devout_flags_get_type()
288 {
289   static volatile gsize g_flags_type_id__volatile;
290 
291   if(g_once_init_enter (&g_flags_type_id__volatile)){
292     static const GFlagsValue values[] = {
293       { AGS_DEVOUT_ADDED_TO_REGISTRY, "AGS_DEVOUT_ADDED_TO_REGISTRY", "devout-added-to-registry" },
294       { AGS_DEVOUT_CONNECTED, "AGS_DEVOUT_CONNECTED", "devout-connected" },
295       { AGS_DEVOUT_BUFFER0, "AGS_DEVOUT_BUFFER0", "devout-buffer0" },
296       { AGS_DEVOUT_BUFFER1, "AGS_DEVOUT_BUFFER1", "devout-buffer1" },
297       { AGS_DEVOUT_BUFFER2, "AGS_DEVOUT_BUFFER2", "devout-buffer2" },
298       { AGS_DEVOUT_BUFFER3, "AGS_DEVOUT_BUFFER3", "devout-buffer3" },
299       { AGS_DEVOUT_ATTACK_FIRST, "AGS_DEVOUT_ATTACK_FIRST", "devout-attack-first" },
300       { AGS_DEVOUT_PLAY, "AGS_DEVOUT_PLAY", "devout-play" },
301       { AGS_DEVOUT_OSS, "AGS_DEVOUT_OSS", "devout-oss" },
302       { AGS_DEVOUT_ALSA, "AGS_DEVOUT_ALSA", "devout-alsa" },
303       { AGS_DEVOUT_SHUTDOWN, "AGS_DEVOUT_SHUTDOWN", "devout-shutdown" },
304       { AGS_DEVOUT_START_PLAY, "AGS_DEVOUT_START_PLAY", "devout-start-play" },
305       { AGS_DEVOUT_NONBLOCKING, "AGS_DEVOUT_NONBLOCKING", "devout-nonblocking" },
306       { AGS_DEVOUT_INITIALIZED, "AGS_DEVOUT_INITIALIZED", "devout-initialized" },
307       { 0, NULL, NULL }
308     };
309 
310     GType g_flags_type_id = g_flags_register_static(g_intern_static_string("AgsDevoutFlags"), values);
311 
312     g_once_init_leave (&g_flags_type_id__volatile, g_flags_type_id);
313   }
314 
315   return g_flags_type_id__volatile;
316 }
317 
318 void
ags_devout_class_init(AgsDevoutClass * devout)319 ags_devout_class_init(AgsDevoutClass *devout)
320 {
321   GObjectClass *gobject;
322 
323   GParamSpec *param_spec;
324 
325   ags_devout_parent_class = g_type_class_peek_parent(devout);
326 
327   /* GObjectClass */
328   gobject = (GObjectClass *) devout;
329 
330   gobject->set_property = ags_devout_set_property;
331   gobject->get_property = ags_devout_get_property;
332 
333   gobject->dispose = ags_devout_dispose;
334   gobject->finalize = ags_devout_finalize;
335 
336   /* properties */
337   /**
338    * AgsDevout:device:
339    *
340    * The alsa soundcard indentifier
341    *
342    * Since: 3.0.0
343    */
344   param_spec = g_param_spec_string("device",
345 				   i18n_pspec("the device identifier"),
346 				   i18n_pspec("The device to perform output to"),
347 				   AGS_DEVOUT_DEFAULT_ALSA_DEVICE,
348 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
349   g_object_class_install_property(gobject,
350 				  PROP_DEVICE,
351 				  param_spec);
352 
353   /**
354    * AgsDevout:dsp-channels:
355    *
356    * The dsp channel count
357    *
358    * Since: 3.0.0
359    */
360   param_spec = g_param_spec_uint("dsp-channels",
361 				 i18n_pspec("count of DSP channels"),
362 				 i18n_pspec("The count of DSP channels to use"),
363 				 AGS_SOUNDCARD_MIN_DSP_CHANNELS,
364 				 AGS_SOUNDCARD_MAX_DSP_CHANNELS,
365 				 AGS_SOUNDCARD_DEFAULT_DSP_CHANNELS,
366 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
367   g_object_class_install_property(gobject,
368 				  PROP_DSP_CHANNELS,
369 				  param_spec);
370 
371   /**
372    * AgsDevout:pcm-channels:
373    *
374    * The pcm channel count
375    *
376    * Since: 3.0.0
377    */
378   param_spec = g_param_spec_uint("pcm-channels",
379 				 i18n_pspec("count of PCM channels"),
380 				 i18n_pspec("The count of PCM channels to use"),
381 				 AGS_SOUNDCARD_MIN_PCM_CHANNELS,
382 				 AGS_SOUNDCARD_MAX_PCM_CHANNELS,
383 				 AGS_SOUNDCARD_DEFAULT_PCM_CHANNELS,
384 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
385   g_object_class_install_property(gobject,
386 				  PROP_PCM_CHANNELS,
387 				  param_spec);
388 
389   /**
390    * AgsDevout:format:
391    *
392    * The precision of the buffer
393    *
394    * Since: 3.0.0
395    */
396   param_spec = g_param_spec_uint("format",
397 				 i18n_pspec("precision of buffer"),
398 				 i18n_pspec("The precision to use for a frame"),
399 				 0,
400 				 G_MAXUINT32,
401 				 AGS_SOUNDCARD_DEFAULT_FORMAT,
402 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
403   g_object_class_install_property(gobject,
404 				  PROP_FORMAT,
405 				  param_spec);
406 
407   /**
408    * AgsDevout:buffer-size:
409    *
410    * The buffer size
411    *
412    * Since: 3.0.0
413    */
414   param_spec = g_param_spec_uint("buffer-size",
415 				 i18n_pspec("frame count of a buffer"),
416 				 i18n_pspec("The count of frames a buffer contains"),
417 				 AGS_SOUNDCARD_MIN_BUFFER_SIZE,
418 				 AGS_SOUNDCARD_MAX_BUFFER_SIZE,
419 				 AGS_SOUNDCARD_DEFAULT_BUFFER_SIZE,
420 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
421   g_object_class_install_property(gobject,
422 				  PROP_BUFFER_SIZE,
423 				  param_spec);
424 
425   /**
426    * AgsDevout:samplerate:
427    *
428    * The samplerate
429    *
430    * Since: 3.0.0
431    */
432   param_spec = g_param_spec_uint("samplerate",
433 				 i18n_pspec("frames per second"),
434 				 i18n_pspec("The frames count played during a second"),
435 				 (guint) AGS_SOUNDCARD_MIN_SAMPLERATE,
436 				 (guint) AGS_SOUNDCARD_MAX_SAMPLERATE,
437 				 (guint) AGS_SOUNDCARD_DEFAULT_SAMPLERATE,
438 				 G_PARAM_READABLE | G_PARAM_WRITABLE);
439   g_object_class_install_property(gobject,
440 				  PROP_SAMPLERATE,
441 				  param_spec);
442 
443   /**
444    * AgsDevout:buffer:
445    *
446    * The buffer
447    *
448    * Since: 3.0.0
449    */
450   param_spec = g_param_spec_pointer("buffer",
451 				    i18n_pspec("the buffer"),
452 				    i18n_pspec("The buffer to play"),
453 				    G_PARAM_READABLE);
454   g_object_class_install_property(gobject,
455 				  PROP_BUFFER,
456 				  param_spec);
457 
458   /**
459    * AgsDevout:bpm:
460    *
461    * Beats per minute
462    *
463    * Since: 3.0.0
464    */
465   param_spec = g_param_spec_double("bpm",
466 				   i18n_pspec("beats per minute"),
467 				   i18n_pspec("Beats per minute to use"),
468 				   1.0,
469 				   240.0,
470 				   AGS_SOUNDCARD_DEFAULT_BPM,
471 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
472   g_object_class_install_property(gobject,
473 				  PROP_BPM,
474 				  param_spec);
475 
476   /**
477    * AgsDevout:delay-factor:
478    *
479    * tact
480    *
481    * Since: 3.0.0
482    */
483   param_spec = g_param_spec_double("delay-factor",
484 				   i18n_pspec("delay factor"),
485 				   i18n_pspec("The delay factor"),
486 				   0.0,
487 				   16.0,
488 				   1.0,
489 				   G_PARAM_READABLE | G_PARAM_WRITABLE);
490   g_object_class_install_property(gobject,
491 				  PROP_DELAY_FACTOR,
492 				  param_spec);
493 
494   /**
495    * AgsDevout:attack:
496    *
497    * Attack of the buffer
498    *
499    * Since: 3.0.0
500    */
501   param_spec = g_param_spec_pointer("attack",
502 				    i18n_pspec("attack of buffer"),
503 				    i18n_pspec("The attack to use for the buffer"),
504 				    G_PARAM_READABLE);
505   g_object_class_install_property(gobject,
506 				  PROP_ATTACK,
507 				  param_spec);
508 
509   /* AgsDevoutClass */
510 }
511 
512 GQuark
ags_devout_error_quark()513 ags_devout_error_quark()
514 {
515   return(g_quark_from_static_string("ags-devout-error-quark"));
516 }
517 
518 void
ags_devout_connectable_interface_init(AgsConnectableInterface * connectable)519 ags_devout_connectable_interface_init(AgsConnectableInterface *connectable)
520 {
521   connectable->get_uuid = ags_devout_get_uuid;
522   connectable->has_resource = ags_devout_has_resource;
523 
524   connectable->is_ready = ags_devout_is_ready;
525   connectable->add_to_registry = ags_devout_add_to_registry;
526   connectable->remove_from_registry = ags_devout_remove_from_registry;
527 
528   connectable->list_resource = ags_devout_list_resource;
529   connectable->xml_compose = ags_devout_xml_compose;
530   connectable->xml_parse = ags_devout_xml_parse;
531 
532   connectable->is_connected = ags_devout_is_connected;
533   connectable->connect = ags_devout_connect;
534   connectable->disconnect = ags_devout_disconnect;
535 
536   connectable->connect_connection = NULL;
537   connectable->disconnect_connection = NULL;
538 }
539 
540 void
ags_devout_soundcard_interface_init(AgsSoundcardInterface * soundcard)541 ags_devout_soundcard_interface_init(AgsSoundcardInterface *soundcard)
542 {
543   soundcard->set_device = ags_devout_set_device;
544   soundcard->get_device = ags_devout_get_device;
545 
546   soundcard->set_presets = ags_devout_set_presets;
547   soundcard->get_presets = ags_devout_get_presets;
548 
549   soundcard->list_cards = ags_devout_list_cards;
550   soundcard->pcm_info = ags_devout_pcm_info;
551   soundcard->get_capability = ags_devout_get_capability;
552 
553   soundcard->is_available = ags_devout_is_available;
554 
555   soundcard->is_starting =  ags_devout_is_starting;
556   soundcard->is_playing = ags_devout_is_playing;
557   soundcard->is_recording = NULL;
558 
559   soundcard->get_uptime = ags_devout_get_uptime;
560 
561   soundcard->play_init = ags_devout_delegate_play_init;
562   soundcard->play = ags_devout_delegate_play;
563 
564   soundcard->record_init = NULL;
565   soundcard->record = NULL;
566 
567   soundcard->stop = ags_devout_delegate_stop;
568 
569   soundcard->tic = ags_devout_tic;
570   soundcard->offset_changed = ags_devout_offset_changed;
571 
572   soundcard->set_bpm = ags_devout_set_bpm;
573   soundcard->get_bpm = ags_devout_get_bpm;
574 
575   soundcard->set_delay_factor = ags_devout_set_delay_factor;
576   soundcard->get_delay_factor = ags_devout_get_delay_factor;
577 
578   soundcard->get_absolute_delay = ags_devout_get_absolute_delay;
579 
580   soundcard->get_delay = ags_devout_get_delay;
581   soundcard->get_attack = ags_devout_get_attack;
582 
583   soundcard->get_buffer = ags_devout_get_buffer;
584   soundcard->get_next_buffer = ags_devout_get_next_buffer;
585   soundcard->get_prev_buffer = ags_devout_get_prev_buffer;
586 
587   soundcard->lock_buffer = ags_devout_lock_buffer;
588   soundcard->unlock_buffer = ags_devout_unlock_buffer;
589 
590   soundcard->get_delay_counter = ags_devout_get_delay_counter;
591 
592   soundcard->set_start_note_offset = ags_devout_set_start_note_offset;
593   soundcard->get_start_note_offset = ags_devout_get_start_note_offset;
594 
595   soundcard->set_note_offset = ags_devout_set_note_offset;
596   soundcard->get_note_offset = ags_devout_get_note_offset;
597 
598   soundcard->set_note_offset_absolute = ags_devout_set_note_offset_absolute;
599   soundcard->get_note_offset_absolute = ags_devout_get_note_offset_absolute;
600 
601   soundcard->set_loop = ags_devout_set_loop;
602   soundcard->get_loop = ags_devout_get_loop;
603 
604   soundcard->get_loop_offset = ags_devout_get_loop_offset;
605 
606   soundcard->get_sub_block_count = ags_devout_get_sub_block_count;
607 
608   soundcard->trylock_sub_block = ags_devout_trylock_sub_block;
609   soundcard->unlock_sub_block = ags_devout_unlock_sub_block;
610 }
611 
612 void
ags_devout_init(AgsDevout * devout)613 ags_devout_init(AgsDevout *devout)
614 {
615   AgsConfig *config;
616 
617   gchar *str;
618   gchar *segmentation;
619 
620   guint i;
621   guint denominator, numerator;
622   gboolean use_alsa;
623 
624   devout->flags = 0;
625 
626   /* insert devout mutex */
627   g_rec_mutex_init(&(devout->obj_mutex));
628 
629   /* uuid */
630   devout->uuid = ags_uuid_alloc();
631   ags_uuid_generate(devout->uuid);
632 
633   /* flags */
634   config = ags_config_get_instance();
635 
636 #ifdef AGS_WITH_ALSA
637   use_alsa = TRUE;
638 #else
639   use_alsa = FALSE;
640 #endif
641 
642   str = ags_config_get_value(config,
643 			     AGS_CONFIG_SOUNDCARD,
644 			     "backend");
645 
646   if(str == NULL){
647     str = ags_config_get_value(config,
648 			       AGS_CONFIG_SOUNDCARD_0,
649 			       "backend");
650   }
651 
652   if(str != NULL &&
653      !g_ascii_strncasecmp(str,
654 			  "oss",
655 			  4)){
656     use_alsa = FALSE;
657   }
658 
659   if(use_alsa){
660     devout->flags |= (AGS_DEVOUT_ALSA);
661   }else{
662     devout->flags |= (AGS_DEVOUT_OSS);
663   }
664 
665   g_free(str);
666 
667   /* presets */
668   devout->dsp_channels = ags_soundcard_helper_config_get_dsp_channels(config);
669   devout->pcm_channels = ags_soundcard_helper_config_get_pcm_channels(config);
670 
671   devout->samplerate = ags_soundcard_helper_config_get_samplerate(config);
672   devout->buffer_size = ags_soundcard_helper_config_get_buffer_size(config);
673   devout->format = ags_soundcard_helper_config_get_format(config);
674 
675   /* device */
676   if(use_alsa){
677     devout->out.alsa.handle = NULL;
678     devout->out.alsa.device = AGS_DEVOUT_DEFAULT_ALSA_DEVICE;
679   }else{
680     devout->out.oss.device_fd = -1;
681     devout->out.oss.device = AGS_DEVOUT_DEFAULT_OSS_DEVICE;
682   }
683 
684   /* buffer */
685   devout->buffer_mutex = (GRecMutex **) malloc(4 * sizeof(GRecMutex *));
686 
687   for(i = 0; i < 4; i++){
688     devout->buffer_mutex[i] = (GRecMutex *) malloc(sizeof(GRecMutex));
689 
690     g_rec_mutex_init(devout->buffer_mutex[i]);
691   }
692 
693   devout->sub_block_count = AGS_SOUNDCARD_DEFAULT_SUB_BLOCK_COUNT;
694   devout->sub_block_mutex = (GRecMutex **) malloc(4 * devout->sub_block_count * devout->pcm_channels * sizeof(GRecMutex *));
695 
696   for(i = 0; i < 4 * devout->sub_block_count * devout->pcm_channels; i++){
697     devout->sub_block_mutex[i] = (GRecMutex *) malloc(sizeof(GRecMutex));
698 
699     g_rec_mutex_init(devout->sub_block_mutex[i]);
700   }
701 
702   devout->buffer = (void **) malloc(4 * sizeof(void *));
703 
704   devout->buffer[0] = NULL;
705   devout->buffer[1] = NULL;
706   devout->buffer[2] = NULL;
707   devout->buffer[3] = NULL;
708 
709   g_atomic_int_set(&(devout->available),
710 		   TRUE);
711 
712   devout->ring_buffer_size = AGS_DEVOUT_DEFAULT_RING_BUFFER_SIZE;
713   devout->nth_ring_buffer = 0;
714 
715   devout->ring_buffer = NULL;
716 
717   ags_devout_realloc_buffer(devout);
718 
719   /* bpm */
720   devout->bpm = AGS_SOUNDCARD_DEFAULT_BPM;
721 
722   /* delay factor */
723   devout->delay_factor = AGS_SOUNDCARD_DEFAULT_DELAY_FACTOR;
724 
725   /* segmentation */
726   segmentation = ags_config_get_value(config,
727 				      AGS_CONFIG_GENERIC,
728 				      "segmentation");
729 
730   if(segmentation != NULL){
731     sscanf(segmentation, "%d/%d",
732 	   &denominator,
733 	   &numerator);
734 
735     devout->delay_factor = 1.0 / numerator * (numerator / denominator);
736 
737     g_free(segmentation);
738   }
739 
740   /* delay and attack */
741   devout->delay = (gdouble *) malloc((int) 2 * AGS_SOUNDCARD_DEFAULT_PERIOD *
742 				     sizeof(gdouble));
743 
744   devout->attack = (guint *) malloc((int) 2 * AGS_SOUNDCARD_DEFAULT_PERIOD *
745 				    sizeof(guint));
746 
747   ags_devout_adjust_delay_and_attack(devout);
748 
749   /* counters */
750   devout->tact_counter = 0.0;
751   devout->delay_counter = 0;
752   devout->tic_counter = 0;
753 
754   devout->start_note_offset = 0;
755   devout->note_offset = 0;
756   devout->note_offset_absolute = 0;
757 
758   devout->loop_left = AGS_SOUNDCARD_DEFAULT_LOOP_LEFT;
759   devout->loop_right = AGS_SOUNDCARD_DEFAULT_LOOP_RIGHT;
760 
761   devout->do_loop = FALSE;
762 
763   devout->loop_offset = 0;
764 
765   devout->io_channel = NULL;
766   devout->tag = NULL;
767 }
768 
769 void
ags_devout_set_property(GObject * gobject,guint prop_id,const GValue * value,GParamSpec * param_spec)770 ags_devout_set_property(GObject *gobject,
771 			guint prop_id,
772 			const GValue *value,
773 			GParamSpec *param_spec)
774 {
775   AgsDevout *devout;
776 
777   GRecMutex *devout_mutex;
778 
779   devout = AGS_DEVOUT(gobject);
780 
781   /* get devout mutex */
782   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
783 
784   switch(prop_id){
785   case PROP_DEVICE:
786     {
787       char *device;
788 
789       device = (char *) g_value_get_string(value);
790 
791       g_rec_mutex_lock(devout_mutex);
792 
793       if((AGS_DEVOUT_OSS & (devout->flags)) != 0){
794 	devout->out.oss.device = g_strdup(device);
795       }else if((AGS_DEVOUT_ALSA & (devout->flags)) != 0){
796 	devout->out.alsa.device = g_strdup(device);
797       }
798 
799       g_rec_mutex_unlock(devout_mutex);
800     }
801     break;
802   case PROP_DSP_CHANNELS:
803     {
804       guint dsp_channels;
805 
806       dsp_channels = g_value_get_uint(value);
807 
808       g_rec_mutex_lock(devout_mutex);
809 
810       if(dsp_channels == devout->dsp_channels){
811 	g_rec_mutex_unlock(devout_mutex);
812 
813 	return;
814       }
815 
816       devout->dsp_channels = dsp_channels;
817 
818       g_rec_mutex_unlock(devout_mutex);
819     }
820     break;
821   case PROP_PCM_CHANNELS:
822     {
823       guint pcm_channels, old_pcm_channels;
824       guint i;
825 
826       pcm_channels = g_value_get_uint(value);
827 
828       g_rec_mutex_lock(devout_mutex);
829 
830       if(pcm_channels == devout->pcm_channels){
831 	g_rec_mutex_unlock(devout_mutex);
832 
833 	return;
834       }
835 
836       old_pcm_channels = devout->pcm_channels;
837 
838       /* destroy if less pcm-channels */
839       for(i = 4 * devout->sub_block_count * pcm_channels; i < 4 * devout->sub_block_count * old_pcm_channels; i++){
840 	g_rec_mutex_clear(devout->sub_block_mutex[i]);
841 
842 	free(devout->sub_block_mutex[i]);
843       }
844 
845       devout->sub_block_mutex = (GRecMutex **) realloc(devout->sub_block_mutex,
846 							     4 * devout->sub_block_count * pcm_channels * sizeof(GRecMutex *));
847 
848       /* create if more pcm-channels */
849       for(i = 4 * devout->sub_block_count * old_pcm_channels; i < 4 * devout->sub_block_count * pcm_channels; i++){
850 	devout->sub_block_mutex[i] = (GRecMutex *) malloc(sizeof(GRecMutex));
851 
852 	g_rec_mutex_init(devout->sub_block_mutex[i]);
853       }
854 
855       devout->pcm_channels = pcm_channels;
856 
857       g_rec_mutex_unlock(devout_mutex);
858 
859       ags_devout_realloc_buffer(devout);
860     }
861     break;
862   case PROP_FORMAT:
863     {
864       guint format;
865 
866       format = g_value_get_uint(value);
867 
868       g_rec_mutex_lock(devout_mutex);
869 
870       if(format == devout->format){
871 	g_rec_mutex_unlock(devout_mutex);
872 
873 	return;
874       }
875 
876       devout->format = format;
877 
878       g_rec_mutex_unlock(devout_mutex);
879 
880       ags_devout_realloc_buffer(devout);
881     }
882     break;
883   case PROP_BUFFER_SIZE:
884     {
885       guint buffer_size;
886 
887       buffer_size = g_value_get_uint(value);
888 
889       g_rec_mutex_lock(devout_mutex);
890 
891       if(buffer_size == devout->buffer_size){
892 	g_rec_mutex_unlock(devout_mutex);
893 
894 	return;
895       }
896 
897       devout->buffer_size = buffer_size;
898 
899       g_rec_mutex_unlock(devout_mutex);
900 
901       ags_devout_realloc_buffer(devout);
902       ags_devout_adjust_delay_and_attack(devout);
903     }
904     break;
905   case PROP_SAMPLERATE:
906     {
907       guint samplerate;
908 
909       samplerate = g_value_get_uint(value);
910 
911       g_rec_mutex_lock(devout_mutex);
912 
913       if(samplerate == devout->samplerate){
914 	g_rec_mutex_unlock(devout_mutex);
915 
916 	return;
917       }
918 
919       devout->samplerate = samplerate;
920 
921       g_rec_mutex_unlock(devout_mutex);
922 
923       ags_devout_adjust_delay_and_attack(devout);
924     }
925     break;
926   case PROP_BUFFER:
927     {
928       //TODO:JK: implement me
929     }
930     break;
931   case PROP_BPM:
932     {
933       gdouble bpm;
934 
935       bpm = g_value_get_double(value);
936 
937       g_rec_mutex_lock(devout_mutex);
938 
939       if(bpm == devout->bpm){
940 	g_rec_mutex_unlock(devout_mutex);
941 
942 	return;
943       }
944 
945       devout->bpm = bpm;
946 
947       g_rec_mutex_unlock(devout_mutex);
948 
949       ags_devout_adjust_delay_and_attack(devout);
950     }
951     break;
952   case PROP_DELAY_FACTOR:
953     {
954       gdouble delay_factor;
955 
956       delay_factor = g_value_get_double(value);
957 
958       g_rec_mutex_lock(devout_mutex);
959 
960       if(delay_factor == devout->delay_factor){
961 	g_rec_mutex_unlock(devout_mutex);
962 
963 	return;
964       }
965 
966       devout->delay_factor = delay_factor;
967 
968       g_rec_mutex_unlock(devout_mutex);
969 
970       ags_devout_adjust_delay_and_attack(devout);
971     }
972     break;
973   default:
974     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
975     break;
976   }
977 }
978 
979 void
ags_devout_get_property(GObject * gobject,guint prop_id,GValue * value,GParamSpec * param_spec)980 ags_devout_get_property(GObject *gobject,
981 			guint prop_id,
982 			GValue *value,
983 			GParamSpec *param_spec)
984 {
985   AgsDevout *devout;
986 
987   GRecMutex *devout_mutex;
988 
989   devout = AGS_DEVOUT(gobject);
990 
991   /* get devout mutex */
992   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
993 
994   switch(prop_id){
995   case PROP_DEVICE:
996     {
997       g_rec_mutex_lock(devout_mutex);
998 
999       if((AGS_DEVOUT_OSS & (devout->flags)) != 0){
1000 	g_value_set_string(value, devout->out.oss.device);
1001       }else if((AGS_DEVOUT_ALSA & (devout->flags)) != 0){
1002 	g_value_set_string(value, devout->out.alsa.device);
1003       }
1004 
1005       g_rec_mutex_unlock(devout_mutex);
1006     }
1007     break;
1008   case PROP_DSP_CHANNELS:
1009     {
1010       g_rec_mutex_lock(devout_mutex);
1011 
1012       g_value_set_uint(value, devout->dsp_channels);
1013 
1014       g_rec_mutex_unlock(devout_mutex);
1015     }
1016     break;
1017   case PROP_PCM_CHANNELS:
1018     {
1019       g_rec_mutex_lock(devout_mutex);
1020 
1021       g_value_set_uint(value, devout->pcm_channels);
1022 
1023       g_rec_mutex_unlock(devout_mutex);
1024     }
1025     break;
1026   case PROP_FORMAT:
1027     {
1028       g_rec_mutex_lock(devout_mutex);
1029 
1030       g_value_set_uint(value, devout->format);
1031 
1032       g_rec_mutex_unlock(devout_mutex);
1033     }
1034     break;
1035   case PROP_BUFFER_SIZE:
1036     {
1037       g_rec_mutex_lock(devout_mutex);
1038 
1039       g_value_set_uint(value, devout->buffer_size);
1040 
1041       g_rec_mutex_unlock(devout_mutex);
1042     }
1043     break;
1044   case PROP_SAMPLERATE:
1045     {
1046       g_rec_mutex_lock(devout_mutex);
1047 
1048       g_value_set_uint(value, devout->samplerate);
1049 
1050       g_rec_mutex_unlock(devout_mutex);
1051     }
1052     break;
1053   case PROP_BUFFER:
1054     {
1055       g_rec_mutex_lock(devout_mutex);
1056 
1057       g_value_set_pointer(value, devout->buffer);
1058 
1059       g_rec_mutex_unlock(devout_mutex);
1060     }
1061     break;
1062   case PROP_BPM:
1063     {
1064       g_rec_mutex_lock(devout_mutex);
1065 
1066       g_value_set_double(value, devout->bpm);
1067 
1068       g_rec_mutex_unlock(devout_mutex);
1069     }
1070     break;
1071   case PROP_DELAY_FACTOR:
1072     {
1073       g_rec_mutex_lock(devout_mutex);
1074 
1075       g_value_set_double(value, devout->delay_factor);
1076 
1077       g_rec_mutex_unlock(devout_mutex);
1078     }
1079     break;
1080   case PROP_ATTACK:
1081     {
1082       g_rec_mutex_lock(devout_mutex);
1083 
1084       g_value_set_pointer(value, devout->attack);
1085 
1086       g_rec_mutex_unlock(devout_mutex);
1087     }
1088     break;
1089   default:
1090     G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, prop_id, param_spec);
1091     break;
1092   }
1093 }
1094 
1095 void
ags_devout_dispose(GObject * gobject)1096 ags_devout_dispose(GObject *gobject)
1097 {
1098   AgsDevout *devout;
1099 
1100   devout = AGS_DEVOUT(gobject);
1101 
1102   /* call parent */
1103   G_OBJECT_CLASS(ags_devout_parent_class)->dispose(gobject);
1104 }
1105 
1106 void
ags_devout_finalize(GObject * gobject)1107 ags_devout_finalize(GObject *gobject)
1108 {
1109   AgsDevout *devout;
1110 
1111   devout = AGS_DEVOUT(gobject);
1112 
1113   ags_uuid_free(devout->uuid);
1114 
1115   /* free output buffer */
1116   free(devout->buffer[0]);
1117   free(devout->buffer[1]);
1118   free(devout->buffer[2]);
1119   free(devout->buffer[3]);
1120 
1121   /* free buffer array */
1122   free(devout->buffer);
1123 
1124   /* free AgsAttack */
1125   free(devout->attack);
1126 
1127   /* call parent */
1128   G_OBJECT_CLASS(ags_devout_parent_class)->finalize(gobject);
1129 }
1130 
1131 AgsUUID*
ags_devout_get_uuid(AgsConnectable * connectable)1132 ags_devout_get_uuid(AgsConnectable *connectable)
1133 {
1134   AgsDevout *devout;
1135 
1136   AgsUUID *ptr;
1137 
1138   GRecMutex *devout_mutex;
1139 
1140   devout = AGS_DEVOUT(connectable);
1141 
1142   /* get devout mutex */
1143   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
1144 
1145   /* get UUID */
1146   g_rec_mutex_lock(devout_mutex);
1147 
1148   ptr = devout->uuid;
1149 
1150   g_rec_mutex_unlock(devout_mutex);
1151 
1152   return(ptr);
1153 }
1154 
1155 gboolean
ags_devout_has_resource(AgsConnectable * connectable)1156 ags_devout_has_resource(AgsConnectable *connectable)
1157 {
1158   return(FALSE);
1159 }
1160 
1161 gboolean
ags_devout_is_ready(AgsConnectable * connectable)1162 ags_devout_is_ready(AgsConnectable *connectable)
1163 {
1164   AgsDevout *devout;
1165 
1166   gboolean is_ready;
1167 
1168   devout = AGS_DEVOUT(connectable);
1169 
1170   /* check is added */
1171   is_ready = ags_devout_test_flags(devout, AGS_DEVOUT_ADDED_TO_REGISTRY);
1172 
1173   return(is_ready);
1174 }
1175 
1176 void
ags_devout_add_to_registry(AgsConnectable * connectable)1177 ags_devout_add_to_registry(AgsConnectable *connectable)
1178 {
1179   AgsDevout *devout;
1180 
1181   if(ags_connectable_is_ready(connectable)){
1182     return;
1183   }
1184 
1185   devout = AGS_DEVOUT(connectable);
1186 
1187   ags_devout_set_flags(devout, AGS_DEVOUT_ADDED_TO_REGISTRY);
1188 }
1189 
1190 void
ags_devout_remove_from_registry(AgsConnectable * connectable)1191 ags_devout_remove_from_registry(AgsConnectable *connectable)
1192 {
1193   AgsDevout *devout;
1194 
1195   if(!ags_connectable_is_ready(connectable)){
1196     return;
1197   }
1198 
1199   devout = AGS_DEVOUT(connectable);
1200 
1201   ags_devout_unset_flags(devout, AGS_DEVOUT_ADDED_TO_REGISTRY);
1202 }
1203 
1204 xmlNode*
ags_devout_list_resource(AgsConnectable * connectable)1205 ags_devout_list_resource(AgsConnectable *connectable)
1206 {
1207   xmlNode *node;
1208 
1209   node = NULL;
1210 
1211   //TODO:JK: implement me
1212 
1213   return(node);
1214 }
1215 
1216 xmlNode*
ags_devout_xml_compose(AgsConnectable * connectable)1217 ags_devout_xml_compose(AgsConnectable *connectable)
1218 {
1219   xmlNode *node;
1220 
1221   node = NULL;
1222 
1223   //TODO:JK: implement me
1224 
1225   return(node);
1226 }
1227 
1228 void
ags_devout_xml_parse(AgsConnectable * connectable,xmlNode * node)1229 ags_devout_xml_parse(AgsConnectable *connectable,
1230 		      xmlNode *node)
1231 {
1232   //TODO:JK: implement me
1233 }
1234 
1235 gboolean
ags_devout_is_connected(AgsConnectable * connectable)1236 ags_devout_is_connected(AgsConnectable *connectable)
1237 {
1238   AgsDevout *devout;
1239 
1240   gboolean is_connected;
1241 
1242   devout = AGS_DEVOUT(connectable);
1243 
1244   /* check is connected */
1245   is_connected = ags_devout_test_flags(devout, AGS_DEVOUT_CONNECTED);
1246 
1247   return(is_connected);
1248 }
1249 
1250 void
ags_devout_connect(AgsConnectable * connectable)1251 ags_devout_connect(AgsConnectable *connectable)
1252 {
1253   AgsDevout *devout;
1254 
1255   if(ags_connectable_is_connected(connectable)){
1256     return;
1257   }
1258 
1259   devout = AGS_DEVOUT(connectable);
1260 
1261   ags_devout_set_flags(devout, AGS_DEVOUT_CONNECTED);
1262 }
1263 
1264 void
ags_devout_disconnect(AgsConnectable * connectable)1265 ags_devout_disconnect(AgsConnectable *connectable)
1266 {
1267 
1268   AgsDevout *devout;
1269 
1270   if(!ags_connectable_is_connected(connectable)){
1271     return;
1272   }
1273 
1274   devout = AGS_DEVOUT(connectable);
1275 
1276   ags_devout_unset_flags(devout, AGS_DEVOUT_CONNECTED);
1277 }
1278 
1279 /**
1280  * ags_devout_test_flags:
1281  * @devout: the #AgsDevout
1282  * @flags: the flags
1283  *
1284  * Test @flags to be set on @devout.
1285  *
1286  * Returns: %TRUE if flags are set, else %FALSE
1287  *
1288  * Since: 3.0.0
1289  */
1290 gboolean
ags_devout_test_flags(AgsDevout * devout,guint flags)1291 ags_devout_test_flags(AgsDevout *devout, guint flags)
1292 {
1293   gboolean retval;
1294 
1295   GRecMutex *devout_mutex;
1296 
1297   if(!AGS_IS_DEVOUT(devout)){
1298     return(FALSE);
1299   }
1300 
1301   /* get devout mutex */
1302   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
1303 
1304   /* test */
1305   g_rec_mutex_lock(devout_mutex);
1306 
1307   retval = (flags & (devout->flags)) ? TRUE: FALSE;
1308 
1309   g_rec_mutex_unlock(devout_mutex);
1310 
1311   return(retval);
1312 }
1313 
1314 /**
1315  * ags_devout_set_flags:
1316  * @devout: the #AgsDevout
1317  * @flags: see #AgsDevoutFlags-enum
1318  *
1319  * Enable a feature of @devout.
1320  *
1321  * Since: 3.0.0
1322  */
1323 void
ags_devout_set_flags(AgsDevout * devout,guint flags)1324 ags_devout_set_flags(AgsDevout *devout, guint flags)
1325 {
1326   GRecMutex *devout_mutex;
1327 
1328   if(!AGS_IS_DEVOUT(devout)){
1329     return;
1330   }
1331 
1332   /* get devout mutex */
1333   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
1334 
1335   //TODO:JK: add more?
1336 
1337   /* set flags */
1338   g_rec_mutex_lock(devout_mutex);
1339 
1340   devout->flags |= flags;
1341 
1342   g_rec_mutex_unlock(devout_mutex);
1343 }
1344 
1345 /**
1346  * ags_devout_unset_flags:
1347  * @devout: the #AgsDevout
1348  * @flags: see #AgsDevoutFlags-enum
1349  *
1350  * Disable a feature of @devout.
1351  *
1352  * Since: 3.0.0
1353  */
1354 void
ags_devout_unset_flags(AgsDevout * devout,guint flags)1355 ags_devout_unset_flags(AgsDevout *devout, guint flags)
1356 {
1357   GRecMutex *devout_mutex;
1358 
1359   if(!AGS_IS_DEVOUT(devout)){
1360     return;
1361   }
1362 
1363   /* get devout mutex */
1364   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
1365 
1366   //TODO:JK: add more?
1367 
1368   /* unset flags */
1369   g_rec_mutex_lock(devout_mutex);
1370 
1371   devout->flags &= (~flags);
1372 
1373   g_rec_mutex_unlock(devout_mutex);
1374 }
1375 
1376 void
ags_devout_set_device(AgsSoundcard * soundcard,gchar * device)1377 ags_devout_set_device(AgsSoundcard *soundcard,
1378 		      gchar *device)
1379 {
1380   AgsDevout *devout;
1381 
1382   GList *card_id, *card_id_start, *card_name, *card_name_start;
1383 
1384   GRecMutex *devout_mutex;
1385 
1386   devout = AGS_DEVOUT(soundcard);
1387 
1388   /* get devout mutex */
1389   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
1390 
1391   /* list cards */
1392   card_id = NULL;
1393   card_name = NULL;
1394 
1395   ags_soundcard_list_cards(soundcard,
1396 			   &card_id, &card_name);
1397 
1398   card_id_start = card_id;
1399   card_name_start = card_name;
1400 
1401   /* check card */
1402   g_rec_mutex_lock(devout_mutex);
1403 
1404   while(card_id != NULL){
1405     if(!g_ascii_strncasecmp(card_id->data,
1406 			    device,
1407 			    strlen(card_id->data))){
1408       if((AGS_DEVOUT_ALSA & (devout->flags)) != 0){
1409 	devout->out.alsa.device = g_strdup(device);
1410       }else if((AGS_DEVOUT_OSS & (devout->flags)) != 0){
1411 	devout->out.oss.device = g_strdup(device);
1412       }
1413 
1414       break;
1415     }
1416 
1417     card_id = card_id->next;
1418   }
1419 
1420   g_rec_mutex_unlock(devout_mutex);
1421 
1422   /* free card id and name */
1423   g_list_free_full(card_id_start,
1424 		   g_free);
1425   g_list_free_full(card_name_start,
1426 		   g_free);
1427 }
1428 
1429 gchar*
ags_devout_get_device(AgsSoundcard * soundcard)1430 ags_devout_get_device(AgsSoundcard *soundcard)
1431 {
1432   AgsDevout *devout;
1433 
1434   gchar *device;
1435 
1436   GRecMutex *devout_mutex;
1437 
1438   devout = AGS_DEVOUT(soundcard);
1439 
1440   /* get devout mutex */
1441   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
1442 
1443   device = NULL;
1444 
1445   g_rec_mutex_lock(devout_mutex);
1446 
1447   if((AGS_DEVOUT_ALSA & (devout->flags)) != 0){
1448 #ifdef AGS_WITH_ALSA
1449     device = g_strdup(devout->out.alsa.device);
1450 #endif
1451   }else if((AGS_DEVOUT_OSS & (devout->flags)) != 0){
1452 #ifdef AGS_WITH_OSS
1453     device = g_strdup(devout->out.oss.device);
1454 #endif
1455   }
1456 
1457   g_rec_mutex_unlock(devout_mutex);
1458 
1459   return(device);
1460 }
1461 
1462 void
ags_devout_set_presets(AgsSoundcard * soundcard,guint channels,guint samplerate,guint buffer_size,guint format)1463 ags_devout_set_presets(AgsSoundcard *soundcard,
1464 		       guint channels,
1465 		       guint samplerate,
1466 		       guint buffer_size,
1467 		       guint format)
1468 {
1469   AgsDevout *devout;
1470 
1471   devout = AGS_DEVOUT(soundcard);
1472 
1473   g_object_set(devout,
1474 	       "pcm-channels", channels,
1475 	       "samplerate", samplerate,
1476 	       "buffer-size", buffer_size,
1477 	       "format", format,
1478 	       NULL);
1479 }
1480 
1481 void
ags_devout_get_presets(AgsSoundcard * soundcard,guint * channels,guint * samplerate,guint * buffer_size,guint * format)1482 ags_devout_get_presets(AgsSoundcard *soundcard,
1483 		       guint *channels,
1484 		       guint *samplerate,
1485 		       guint *buffer_size,
1486 		       guint *format)
1487 {
1488   AgsDevout *devout;
1489 
1490   GRecMutex *devout_mutex;
1491 
1492   devout = AGS_DEVOUT(soundcard);
1493 
1494   /* get devout mutex */
1495   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
1496 
1497   /* get presets */
1498   g_rec_mutex_lock(devout_mutex);
1499 
1500   if(channels != NULL){
1501     *channels = devout->pcm_channels;
1502   }
1503 
1504   if(samplerate != NULL){
1505     *samplerate = devout->samplerate;
1506   }
1507 
1508   if(buffer_size != NULL){
1509     *buffer_size = devout->buffer_size;
1510   }
1511 
1512   if(format != NULL){
1513     *format = devout->format;
1514   }
1515 
1516   g_rec_mutex_unlock(devout_mutex);
1517 }
1518 
1519 void
ags_devout_list_cards(AgsSoundcard * soundcard,GList ** card_id,GList ** card_name)1520 ags_devout_list_cards(AgsSoundcard *soundcard,
1521 		      GList **card_id, GList **card_name)
1522 {
1523   AgsDevout *devout;
1524 
1525   GRecMutex *devout_mutex;
1526 
1527   devout = AGS_DEVOUT(soundcard);
1528 
1529   /* get devout mutex */
1530   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
1531 
1532   if(card_id != NULL){
1533     *card_id = NULL;
1534   }
1535 
1536   if(card_name != NULL){
1537     *card_name = NULL;
1538   }
1539 
1540   g_rec_mutex_lock(devout_mutex);
1541 
1542   if((AGS_DEVOUT_ALSA & (devout->flags)) != 0){
1543 #ifdef AGS_WITH_ALSA
1544     snd_ctl_t *card_handle;
1545     snd_ctl_card_info_t *card_info;
1546 
1547     char *name;
1548     gchar *str;
1549     gchar *str_err;
1550 
1551     int card_num;
1552     int device;
1553     int error;
1554 
1555     /* the default device */
1556     str = g_strdup("default");
1557     error = snd_ctl_open(&card_handle, str, 0);
1558 
1559     if(error < 0){
1560       g_free(str);
1561 
1562       goto ags_devout_list_cards_NO_DEFAULT_0;
1563     }
1564 
1565     snd_ctl_card_info_alloca(&card_info);
1566     error = snd_ctl_card_info(card_handle, card_info);
1567 
1568     if(error < 0){
1569       g_free(str);
1570 
1571       goto ags_devout_list_cards_NO_DEFAULT_0;
1572     }
1573 
1574     if(card_id != NULL){
1575       *card_id = g_list_prepend(*card_id, str);
1576     }
1577 
1578     if(card_name != NULL){
1579       *card_name = g_list_prepend(*card_name, g_strdup(snd_ctl_card_info_get_name(card_info)));
1580     }
1581 
1582     snd_ctl_close(card_handle);
1583 
1584   ags_devout_list_cards_NO_DEFAULT_0:
1585 
1586     /* enumerated devices */
1587     card_num = -1;
1588 
1589     while(TRUE){
1590       char *iface;
1591       char **hints, **iter;
1592 
1593       error = snd_card_next(&card_num);
1594 
1595       if(card_num < 0 || error < 0){
1596 	str_err = snd_strerror(error);
1597 	g_message("Can't get the next card number: %s", str_err);
1598 
1599 	//free(str_err);
1600 
1601 	break;
1602       }
1603 
1604       str = g_strdup_printf("hw:%d", card_num);
1605 
1606 #ifdef AGS_DEBUG
1607       g_message("found soundcard - %s", str);
1608 #endif
1609 
1610       error = snd_ctl_open(&card_handle, str, 0);
1611 
1612       if(error < 0){
1613 	g_free(str);
1614 
1615 	continue;
1616       }
1617 
1618       snd_ctl_card_info_alloca(&card_info);
1619       error = snd_ctl_card_info(card_handle, card_info);
1620 
1621       if(error < 0){
1622 	snd_ctl_close(card_handle);
1623 	g_free(str);
1624 
1625 	continue;
1626       }
1627 
1628       device = -1;
1629       error = snd_ctl_pcm_next_device(card_handle, &device);
1630 
1631       if(error < 0){
1632 	snd_ctl_close(card_handle);
1633 	g_free(str);
1634 
1635 	continue;
1636       }
1637 
1638       iface = "pcm";
1639       hints = NULL;
1640 
1641       error = snd_device_name_hint(card_num,
1642 				   iface,
1643 				   &hints);
1644 
1645       if(hints != NULL){
1646 	for(iter = hints; iter[0] != NULL; iter++){
1647 	  if(card_id != NULL){
1648 	    char *hint;
1649 
1650 	    hint = snd_device_name_get_hint(iter[0],
1651 					    "NAME");
1652 
1653 	    *card_id = g_list_prepend(*card_id,
1654 				      g_strdup(hint));
1655 
1656 	    if(hint != NULL){
1657 	      free(hint);
1658 	    }
1659 	  }
1660 
1661 	  if(card_name != NULL){
1662 	    char *name;
1663 
1664 	    name = snd_ctl_card_info_get_name(card_info);
1665 
1666 	    *card_name = g_list_prepend(*card_name, g_strdup(name));
1667 	  }
1668 	}
1669 
1670 	snd_device_name_free_hint(hints);
1671       }
1672 
1673       snd_ctl_close(card_handle);
1674 
1675       g_free(str);
1676     }
1677 
1678     snd_config_update_free_global();
1679 #endif
1680   }else{
1681 #ifdef AGS_WITH_OSS
1682     oss_sysinfo sysinfo;
1683     oss_audioinfo ai;
1684 
1685     char *mixer_device;
1686 
1687     int mixerfd = -1;
1688 
1689     int next, n;
1690     int i;
1691 
1692     if((mixer_device = getenv("OSS_MIXERDEV")) == NULL){
1693       mixer_device = "/dev/mixer";
1694     }
1695 
1696     if((mixerfd = open(mixer_device, O_RDONLY, 0)) == -1){
1697       int e = errno;
1698 
1699       switch(e){
1700       case ENXIO:
1701       case ENODEV:
1702 	{
1703 	  g_warning("Open Sound System is not running in your system.");
1704 	}
1705 	break;
1706       case ENOENT:
1707 	{
1708 	  g_warning("No %s device available in your system.\nPerhaps Open Sound System is not installed or running.", mixer_device);
1709 	}
1710 	break;
1711       default:
1712 	g_warning("%s", strerror(e));
1713       }
1714     }
1715 
1716     if(ioctl(mixerfd, SNDCTL_SYSINFO, &sysinfo) == -1){
1717       if(errno == ENXIO){
1718 	g_warning("OSS has not detected any supported sound hardware in your system.");
1719       }else{
1720 	g_warning("SNDCTL_SYSINFO");
1721 
1722 	if(errno == EINVAL){
1723 	  g_warning("Error: OSS version 4.0 or later is required");
1724 	}
1725       }
1726 
1727       n = 0;
1728     }else{
1729       n = sysinfo.numaudios;
1730     }
1731 
1732     memset(&ai, 0, sizeof(oss_audioinfo));
1733     ioctl(mixerfd, SNDCTL_AUDIOINFO_EX, &ai);
1734 
1735     for(i = 0; i < n; i++){
1736       ai.dev = i;
1737 
1738       if(ioctl(mixerfd, SNDCTL_ENGINEINFO, &ai) == -1){
1739 	int e = errno;
1740 
1741 	g_warning("Can't get device info for /dev/dsp%d (SNDCTL_AUDIOINFO)\nerrno = %d: %s", i, e, strerror(e));
1742 
1743 	continue;
1744       }
1745 
1746       if((DSP_CAP_OUTPUT & (ai.caps)) != 0){
1747 	if(card_id != NULL){
1748 	  *card_id = g_list_prepend(*card_id,
1749 				    g_strdup_printf("/dev/dsp%i", i));
1750 	}
1751 
1752 	if(card_name != NULL){
1753 	  *card_name = g_list_prepend(*card_name,
1754 				      g_strdup(ai.name));
1755 	}
1756       }
1757 
1758       next = ai.next_play_engine;
1759 
1760       if(next <= 0){
1761 	break;
1762       }
1763     }
1764 #endif
1765   }
1766 
1767   g_rec_mutex_unlock(devout_mutex);
1768 
1769   if(card_id != NULL){
1770     *card_id = g_list_reverse(*card_id);
1771   }
1772 
1773   if(card_name != NULL){
1774     *card_name = g_list_reverse(*card_name);
1775   }
1776 }
1777 
1778 void
ags_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)1779 ags_devout_pcm_info(AgsSoundcard *soundcard,
1780 		    char *card_id,
1781 		    guint *channels_min, guint *channels_max,
1782 		    guint *rate_min, guint *rate_max,
1783 		    guint *buffer_size_min, guint *buffer_size_max,
1784 		    GError **error)
1785 {
1786   AgsDevout *devout;
1787 
1788   GRecMutex *devout_mutex;
1789 
1790   if(card_id == NULL){
1791     return;
1792   }
1793 
1794   devout = AGS_DEVOUT(soundcard);
1795 
1796   /* get devout mutex */
1797   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
1798 
1799   /* pcm info */
1800   g_rec_mutex_lock(devout_mutex);
1801 
1802   if((AGS_DEVOUT_ALSA & (devout->flags)) != 0){
1803 #ifdef AGS_WITH_ALSA
1804     snd_pcm_t *handle;
1805     snd_pcm_hw_params_t *params;
1806 
1807     gchar *str;
1808 
1809     unsigned int val;
1810     int dir;
1811     snd_pcm_uframes_t frames;
1812 
1813     int rc;
1814     int err;
1815 
1816     /* Open PCM device for playback. */
1817     handle = NULL;
1818 
1819     rc = snd_pcm_open(&handle, card_id, SND_PCM_STREAM_PLAYBACK, 0);
1820 
1821     if(rc < 0){
1822       str = snd_strerror(rc);
1823       g_message("unable to open pcm device (attempting fixup): %s", str);
1824 
1825       if(index(card_id,
1826 	       ',') != NULL){
1827 	gchar *device_fixup;
1828 
1829 	device_fixup = g_strndup(card_id,
1830 				 index(card_id,
1831 				       ',') - card_id);
1832 	handle = NULL;
1833 
1834 	rc = snd_pcm_open(&handle, device_fixup, SND_PCM_STREAM_PLAYBACK, 0);
1835 
1836 	if(rc < 0){
1837 	  if(error != NULL){
1838 	    g_set_error(error,
1839 			AGS_DEVOUT_ERROR,
1840 			AGS_DEVOUT_ERROR_LOCKED_SOUNDCARD,
1841 			"unable to open pcm device: %s\n",
1842 			str);
1843 	  }
1844 
1845 	  //    free(str);
1846 
1847 	  goto ags_devout_pcm_info_ERR;
1848 	}
1849       }else{
1850 	if(error != NULL){
1851 	  g_set_error(error,
1852 		      AGS_DEVOUT_ERROR,
1853 		      AGS_DEVOUT_ERROR_LOCKED_SOUNDCARD,
1854 		      "unable to open pcm device: %s\n",
1855 		      str);
1856 	}
1857 
1858 	goto ags_devout_pcm_info_ERR;
1859       }
1860     }
1861 
1862     /* Allocate a hardware parameters object. */
1863     snd_pcm_hw_params_alloca(&params);
1864 
1865     /* Fill it in with default values. */
1866     snd_pcm_hw_params_any(handle, params);
1867 
1868     /* channels */
1869     snd_pcm_hw_params_get_channels_min(params, &val);
1870     *channels_min = val;
1871 
1872     snd_pcm_hw_params_get_channels_max(params, &val);
1873     *channels_max = val;
1874 
1875     /* samplerate */
1876     dir = 0;
1877     snd_pcm_hw_params_get_rate_min(params, &val, &dir);
1878     *rate_min = val;
1879 
1880     dir = 0;
1881     snd_pcm_hw_params_get_rate_max(params, &val, &dir);
1882     *rate_max = val;
1883 
1884     /* buffer size */
1885     dir = 0;
1886     snd_pcm_hw_params_get_buffer_size_min(params, &frames);
1887     *buffer_size_min = frames;
1888 
1889     dir = 0;
1890     snd_pcm_hw_params_get_buffer_size_max(params, &frames);
1891     *buffer_size_max = frames;
1892 
1893     snd_pcm_close(handle);
1894 #endif
1895   }else{
1896 #ifdef AGS_WITH_OSS
1897     oss_audioinfo ainfo;
1898 
1899     gchar *str;
1900 
1901     int mixerfd;
1902     int acc;
1903     unsigned int cmd;
1904 
1905     mixerfd = open(card_id, O_RDWR, 0);
1906 
1907     if(mixerfd == -1){
1908       int e = errno;
1909 
1910       str = strerror(e);
1911       g_message("unable to open pcm device: %s\n", str);
1912 
1913       if(error != NULL){
1914 	g_set_error(error,
1915 		    AGS_DEVOUT_ERROR,
1916 		    AGS_DEVOUT_ERROR_LOCKED_SOUNDCARD,
1917 		    "unable to open pcm device: %s\n",
1918 		    str);
1919       }
1920 
1921       goto ags_devout_pcm_info_ERR;
1922     }
1923 
1924     memset(&ainfo, 0, sizeof (ainfo));
1925 
1926     cmd = SNDCTL_AUDIOINFO;
1927 
1928     if(card_id != NULL &&
1929        !g_ascii_strncasecmp(card_id,
1930 			    "/dev/dsp",
1931 			    8)){
1932       if(strlen(card_id) > 8){
1933 	sscanf(card_id,
1934 	       "/dev/dsp%d",
1935 	       &(ainfo.dev));
1936       }else{
1937 	ainfo.dev = 0;
1938       }
1939     }else{
1940       goto ags_devout_pcm_info_ERR;
1941     }
1942 
1943     if(ioctl(mixerfd, cmd, &ainfo) == -1){
1944       int e = errno;
1945 
1946       str = strerror(e);
1947       g_message("unable to retrieve audio info: %s\n", str);
1948 
1949       if(error != NULL){
1950 	g_set_error(error,
1951 		    AGS_DEVOUT_ERROR,
1952 		    AGS_DEVOUT_ERROR_LOCKED_SOUNDCARD,
1953 		    "unable to retrieve audio info: %s\n",
1954 		    str);
1955       }
1956 
1957       return;
1958     }
1959 
1960     *channels_min = ainfo.min_channels;
1961     *channels_max = ainfo.max_channels;
1962     *rate_min = ainfo.min_rate;
1963     *rate_max = ainfo.max_rate;
1964     *buffer_size_min = 64;
1965     *buffer_size_max = 8192;
1966 #endif
1967   }
1968 
1969  ags_devout_pcm_info_ERR:
1970 
1971   g_rec_mutex_unlock(devout_mutex);
1972 }
1973 
1974 guint
ags_devout_get_capability(AgsSoundcard * soundcard)1975 ags_devout_get_capability(AgsSoundcard *soundcard)
1976 {
1977   return(AGS_SOUNDCARD_CAPABILITY_PLAYBACK);
1978 }
1979 
1980 gboolean
ags_devout_is_available(AgsSoundcard * soundcard)1981 ags_devout_is_available(AgsSoundcard *soundcard)
1982 {
1983   AgsDevout *devout;
1984 
1985 #ifdef AGS_WITH_ALSA
1986   snd_pcm_t *handle;
1987 
1988   struct pollfd fds;
1989 #endif
1990 
1991   gboolean is_available;
1992 
1993   GRecMutex *devout_mutex;
1994 
1995   devout = AGS_DEVOUT(soundcard);
1996 
1997   /* get devout mutex */
1998   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
1999 
2000 #ifdef AGS_WITH_ALSA
2001   /* check is starting */
2002   g_rec_mutex_lock(devout_mutex);
2003 
2004   handle = devout->out.alsa.handle;
2005 
2006   g_rec_mutex_unlock(devout_mutex);
2007 
2008   if(handle != NULL){
2009     fds.events = POLLOUT;
2010 
2011     snd_pcm_poll_descriptors(handle, &fds, 1);
2012 
2013     poll(&fds, 1, 0);
2014 
2015     /* check available */
2016     is_available = ((POLLOUT & (fds.revents)) != 0) ? TRUE: FALSE;
2017   }else{
2018     is_available = FALSE;
2019   }
2020 #else
2021   is_available = FALSE;
2022 #endif
2023 
2024   return(is_available);
2025 }
2026 
2027 gboolean
ags_devout_is_starting(AgsSoundcard * soundcard)2028 ags_devout_is_starting(AgsSoundcard *soundcard)
2029 {
2030   AgsDevout *devout;
2031 
2032   gboolean is_starting;
2033 
2034   GRecMutex *devout_mutex;
2035 
2036   devout = AGS_DEVOUT(soundcard);
2037 
2038   /* get devout mutex */
2039   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
2040 
2041   /* check is starting */
2042   g_rec_mutex_lock(devout_mutex);
2043 
2044   is_starting = ((AGS_DEVOUT_START_PLAY & (devout->flags)) != 0) ? TRUE: FALSE;
2045 
2046   g_rec_mutex_unlock(devout_mutex);
2047 
2048   return(is_starting);
2049 }
2050 
2051 gboolean
ags_devout_is_playing(AgsSoundcard * soundcard)2052 ags_devout_is_playing(AgsSoundcard *soundcard)
2053 {
2054   AgsDevout *devout;
2055 
2056   gboolean is_playing;
2057 
2058   GRecMutex *devout_mutex;
2059 
2060   devout = AGS_DEVOUT(soundcard);
2061 
2062   /* get devout mutex */
2063   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
2064 
2065   /* check is starting */
2066   g_rec_mutex_lock(devout_mutex);
2067 
2068   is_playing = ((AGS_DEVOUT_PLAY & (devout->flags)) != 0) ? TRUE: FALSE;
2069 
2070   g_rec_mutex_unlock(devout_mutex);
2071 
2072   return(is_playing);
2073 }
2074 
2075 gchar*
ags_devout_get_uptime(AgsSoundcard * soundcard)2076 ags_devout_get_uptime(AgsSoundcard *soundcard)
2077 {
2078   gchar *uptime;
2079 
2080   if(ags_soundcard_is_playing(soundcard)){
2081     guint samplerate;
2082     guint buffer_size;
2083 
2084     guint note_offset;
2085     gdouble bpm;
2086     gdouble delay_factor;
2087 
2088     gdouble delay;
2089 
2090     ags_soundcard_get_presets(soundcard,
2091 			      NULL,
2092 			      &samplerate,
2093 			      &buffer_size,
2094 			      NULL);
2095 
2096     note_offset = ags_soundcard_get_note_offset_absolute(soundcard);
2097 
2098     bpm = ags_soundcard_get_bpm(soundcard);
2099     delay_factor = ags_soundcard_get_delay_factor(soundcard);
2100 
2101     /* calculate delays */
2102     delay = ags_soundcard_get_absolute_delay(soundcard);
2103 
2104     uptime = ags_time_get_uptime_from_offset(note_offset,
2105 					     bpm,
2106 					     delay,
2107 					     delay_factor);
2108   }else{
2109     uptime = g_strdup(AGS_TIME_ZERO);
2110   }
2111 
2112   return(uptime);
2113 }
2114 
2115 void
ags_devout_delegate_play_init(AgsSoundcard * soundcard,GError ** error)2116 ags_devout_delegate_play_init(AgsSoundcard *soundcard,
2117 			      GError **error)
2118 {
2119   AgsDevout *devout;
2120 
2121   devout = AGS_DEVOUT(soundcard);
2122 
2123   if(ags_devout_test_flags(devout, AGS_DEVOUT_ALSA)){
2124     ags_devout_alsa_init(soundcard,
2125 			 error);
2126   }else if(ags_devout_test_flags(devout, AGS_DEVOUT_OSS)){
2127     ags_devout_oss_init(soundcard,
2128 			error);
2129   }
2130 }
2131 
2132 void
ags_devout_delegate_play(AgsSoundcard * soundcard,GError ** error)2133 ags_devout_delegate_play(AgsSoundcard *soundcard,
2134 			 GError **error)
2135 {
2136   AgsDevout *devout;
2137 
2138   devout = AGS_DEVOUT(soundcard);
2139 
2140   if(ags_devout_test_flags(devout, AGS_DEVOUT_ALSA)){
2141     ags_devout_alsa_play(soundcard,
2142 			 error);
2143   }else if(ags_devout_test_flags(devout, AGS_DEVOUT_OSS)){
2144     ags_devout_oss_play(soundcard,
2145 			error);
2146   }
2147 }
2148 
2149 void
ags_devout_delegate_stop(AgsSoundcard * soundcard)2150 ags_devout_delegate_stop(AgsSoundcard *soundcard)
2151 {
2152   AgsDevout *devout;
2153 
2154   devout = AGS_DEVOUT(soundcard);
2155 
2156   if(ags_devout_test_flags(devout, AGS_DEVOUT_ALSA)){
2157     ags_devout_alsa_free(soundcard);
2158   }else if(ags_devout_test_flags(devout, AGS_DEVOUT_OSS)){
2159     ags_devout_oss_free(soundcard);
2160   }
2161 }
2162 
2163 void
ags_devout_oss_init(AgsSoundcard * soundcard,GError ** error)2164 ags_devout_oss_init(AgsSoundcard *soundcard,
2165 		    GError **error)
2166 {
2167   AgsDevout *devout;
2168 
2169   GIOChannel *io_channel;
2170 
2171   guint tag;
2172 
2173   gchar *str;
2174 
2175   guint word_size;
2176   int format;
2177   int tmp;
2178   guint i;
2179 
2180   GRecMutex *devout_mutex;
2181 
2182   if(ags_soundcard_is_playing(soundcard)){
2183     return;
2184   }
2185 
2186   devout = AGS_DEVOUT(soundcard);
2187 
2188   /* get devout mutex */
2189   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
2190 
2191   /* retrieve word size */
2192   g_rec_mutex_lock(devout_mutex);
2193 
2194   switch(devout->format){
2195   case AGS_SOUNDCARD_SIGNED_8_BIT:
2196     {
2197 #ifdef AGS_WITH_OSS
2198       format = AFMT_U8;
2199 #endif
2200 
2201       word_size = sizeof(gint8);
2202     }
2203     break;
2204   case AGS_SOUNDCARD_SIGNED_16_BIT:
2205     {
2206 #ifdef AGS_WITH_OSS
2207       format = AFMT_S16_NE;
2208 #endif
2209 
2210       word_size = sizeof(gint16);
2211     }
2212     break;
2213   case AGS_SOUNDCARD_SIGNED_24_BIT:
2214     {
2215 #ifdef AGS_WITH_OSS
2216       format = AFMT_S24_NE;
2217 #endif
2218 
2219       word_size = sizeof(gint32);
2220     }
2221     break;
2222   case AGS_SOUNDCARD_SIGNED_32_BIT:
2223     {
2224 #ifdef AGS_WITH_OSS
2225       format = AFMT_S32_NE;
2226 #endif
2227 
2228       word_size = sizeof(gint32);
2229     }
2230     break;
2231   case AGS_SOUNDCARD_SIGNED_64_BIT:
2232     {
2233       word_size = sizeof(gint64);
2234     }
2235   default:
2236     g_warning("ags_devout_oss_init(): unsupported word size");
2237     return;
2238   }
2239 
2240   /* prepare for playback */
2241   devout->flags |= (AGS_DEVOUT_START_PLAY |
2242 		    AGS_DEVOUT_PLAY |
2243 		    AGS_DEVOUT_NONBLOCKING);
2244 
2245   memset(devout->buffer[0], 0, devout->pcm_channels * devout->buffer_size * word_size);
2246   memset(devout->buffer[1], 0, devout->pcm_channels * devout->buffer_size * word_size);
2247   memset(devout->buffer[2], 0, devout->pcm_channels * devout->buffer_size * word_size);
2248   memset(devout->buffer[3], 0, devout->pcm_channels * devout->buffer_size * word_size);
2249 
2250   /* allocate ring buffer */
2251   g_atomic_int_set(&(devout->available),
2252 		   FALSE);
2253 
2254     devout->ring_buffer = (unsigned char **) malloc(devout->ring_buffer_size * sizeof(unsigned char *));
2255 
2256   for(i = 0; i < devout->ring_buffer_size; i++){
2257     devout->ring_buffer[i] = (unsigned char *) malloc(devout->pcm_channels *
2258 						      devout->buffer_size * word_size *
2259 						      sizeof(unsigned char));
2260   }
2261 
2262 #ifdef AGS_WITH_OSS
2263   /* open device fd */
2264   str = devout->out.oss.device;
2265   devout->out.oss.device_fd = open(str, O_WRONLY, 0);
2266 
2267   if(devout->out.oss.device_fd == -1){
2268     devout->flags &= (~(AGS_DEVOUT_START_PLAY |
2269 			AGS_DEVOUT_PLAY |
2270 			AGS_DEVOUT_NONBLOCKING));
2271 
2272     g_rec_mutex_unlock(devout_mutex);
2273 
2274     g_warning("couldn't open device %s", devout->out.oss.device);
2275 
2276     if(error != NULL){
2277       g_set_error(error,
2278 		  AGS_DEVOUT_ERROR,
2279 		  AGS_DEVOUT_ERROR_LOCKED_SOUNDCARD,
2280 		  "unable to open dsp device: %s\n",
2281 		  str);
2282     }
2283 
2284     return;
2285   }
2286 
2287   //NOTE:JK: unsupported on kfreebsd 9.0
2288   //  tmp = APF_NORMAL;
2289   //  ioctl(devout->out.oss.device_fd, SNDCTL_DSP_PROFILE, &tmp);
2290 
2291   tmp = format;
2292 
2293   if(ioctl(devout->out.oss.device_fd, SNDCTL_DSP_SETFMT, &tmp) == -1){
2294     devout->flags &= (~(AGS_DEVOUT_START_PLAY |
2295 			AGS_DEVOUT_PLAY |
2296 			AGS_DEVOUT_NONBLOCKING));
2297 
2298     g_rec_mutex_unlock(devout_mutex);
2299 
2300     str = strerror(errno);
2301     g_warning("failed to select bits/sample");
2302 
2303     if(error != NULL){
2304       g_set_error(error,
2305 		  AGS_DEVOUT_ERROR,
2306 		  AGS_DEVOUT_ERROR_SAMPLE_FORMAT_NOT_AVAILABLE,
2307 		  "unable to open dsp device: %s",
2308 		  str);
2309     }
2310 
2311     devout->out.oss.device_fd = -1;
2312 
2313     return;
2314   }
2315 
2316   if(tmp != format){
2317     devout->flags &= (~(AGS_DEVOUT_START_PLAY |
2318 			AGS_DEVOUT_PLAY |
2319 			AGS_DEVOUT_NONBLOCKING));
2320 
2321     g_rec_mutex_unlock(devout_mutex);
2322 
2323     str = strerror(errno);
2324     g_warning("failed to select bits/sample");
2325 
2326     if(error != NULL){
2327       g_set_error(error,
2328 		  AGS_DEVOUT_ERROR,
2329 		  AGS_DEVOUT_ERROR_SAMPLE_FORMAT_NOT_AVAILABLE,
2330 		  "unable to open dsp device: %s",
2331 		  str);
2332     }
2333 
2334     devout->out.oss.device_fd = -1;
2335 
2336     return;
2337   }
2338 
2339   tmp = devout->dsp_channels;
2340 
2341   if(ioctl(devout->out.oss.device_fd, SNDCTL_DSP_CHANNELS, &tmp) == -1){
2342     devout->flags &= (~(AGS_DEVOUT_START_PLAY |
2343 			AGS_DEVOUT_PLAY |
2344 			AGS_DEVOUT_NONBLOCKING));
2345 
2346     g_rec_mutex_unlock(devout_mutex);
2347 
2348     str = strerror(errno);
2349     g_warning("Channels count (%i) not available for playbacks: %s", devout->dsp_channels, str);
2350 
2351     if(error != NULL){
2352       g_set_error(error,
2353 		  AGS_DEVOUT_ERROR,
2354 		  AGS_DEVOUT_ERROR_CHANNELS_NOT_AVAILABLE,
2355 		  "unable to open pcm device: %s",
2356 		  str);
2357     }
2358 
2359     devout->out.oss.device_fd = -1;
2360 
2361     return;
2362   }
2363 
2364   if(tmp != devout->dsp_channels){
2365     devout->flags &= (~(AGS_DEVOUT_START_PLAY |
2366 			AGS_DEVOUT_PLAY |
2367 			AGS_DEVOUT_NONBLOCKING));
2368 
2369     g_rec_mutex_unlock(devout_mutex);
2370 
2371     str = strerror(errno);
2372     g_warning("Channels count (%i) not available for playbacks: %s", devout->dsp_channels, str);
2373 
2374     if(error != NULL){
2375       g_set_error(error,
2376 		  AGS_DEVOUT_ERROR,
2377 		  AGS_DEVOUT_ERROR_CHANNELS_NOT_AVAILABLE,
2378 		  "unable to open pcm device: %s",
2379 		  str);
2380     }
2381 
2382     devout->out.oss.device_fd = -1;
2383 
2384     return;
2385   }
2386 
2387   tmp = devout->samplerate;
2388 
2389   if(ioctl(devout->out.oss.device_fd, SNDCTL_DSP_SPEED, &tmp) == -1){
2390     devout->flags &= (~(AGS_DEVOUT_START_PLAY |
2391 			AGS_DEVOUT_PLAY |
2392 			AGS_DEVOUT_NONBLOCKING));
2393 
2394     g_rec_mutex_unlock(devout_mutex);
2395 
2396     str = strerror(errno);
2397     g_warning("Rate %iHz not available for playback: %s", devout->samplerate, str);
2398 
2399     if(error != NULL){
2400       g_set_error(error,
2401 		  AGS_DEVOUT_ERROR,
2402 		  AGS_DEVOUT_ERROR_SAMPLERATE_NOT_AVAILABLE,
2403 		  "unable to open pcm device: %s",
2404 		  str);
2405     }
2406 
2407     devout->out.oss.device_fd = -1;
2408 
2409     return;
2410   }
2411 
2412   if(tmp != devout->samplerate){
2413     g_warning("Warning: Playback using %d Hz (file %d Hz)",
2414 	      tmp,
2415 	      devout->samplerate);
2416   }
2417 
2418   io_channel = g_io_channel_unix_new(devout->out.oss.device_fd);
2419   tag = g_io_add_watch(io_channel,
2420 		       G_IO_OUT,
2421 		       (GIOFunc) ags_devout_oss_io_func,
2422 		       devout);
2423 
2424   devout->io_channel = g_list_prepend(devout->io_channel,
2425 				      io_channel);
2426   devout->tag = g_list_prepend(devout->tag,
2427 			       GUINT_TO_POINTER(tag));
2428 
2429 #endif
2430 
2431   devout->tact_counter = 0.0;
2432   devout->delay_counter = floor(ags_soundcard_get_absolute_delay(AGS_SOUNDCARD(devout)));
2433   devout->tic_counter = 0;
2434 
2435   devout->nth_ring_buffer = 0;
2436 
2437 #ifdef AGS_WITH_OSS
2438   devout->flags |= AGS_DEVOUT_INITIALIZED;
2439 #endif
2440   devout->flags |= AGS_DEVOUT_BUFFER0;
2441   devout->flags &= (~(AGS_DEVOUT_BUFFER1 |
2442 		      AGS_DEVOUT_BUFFER2 |
2443 		      AGS_DEVOUT_BUFFER3));
2444 
2445   g_rec_mutex_unlock(devout_mutex);
2446 }
2447 
2448 void
ags_devout_oss_play_fill_ring_buffer(void * buffer,guint ags_format,unsigned char * ring_buffer,guint channels,guint buffer_size)2449 ags_devout_oss_play_fill_ring_buffer(void *buffer,
2450 				     guint ags_format,
2451 				     unsigned char *ring_buffer,
2452 				     guint channels,
2453 				     guint buffer_size)
2454 {
2455   int format_bits;
2456   guint word_size;
2457 
2458   int bps;
2459   int res;
2460   guint chn;
2461   guint count, i;
2462 
2463   switch(ags_format){
2464   case AGS_SOUNDCARD_SIGNED_8_BIT:
2465   {
2466     word_size = sizeof(char);
2467     bps = 1;
2468   }
2469   break;
2470   case AGS_SOUNDCARD_SIGNED_16_BIT:
2471   {
2472     word_size = sizeof(short);
2473     bps = 2;
2474   }
2475   break;
2476   case AGS_SOUNDCARD_SIGNED_24_BIT:
2477   {
2478     word_size = sizeof(long);
2479     bps = 3;
2480   }
2481   break;
2482   case AGS_SOUNDCARD_SIGNED_32_BIT:
2483   {
2484     word_size = sizeof(long);
2485     bps = 4;
2486   }
2487   break;
2488   default:
2489     g_warning("ags_devout_oss_play(): unsupported word size");
2490     return;
2491   }
2492 
2493   /* fill the channel areas */
2494   for(count = 0; count < buffer_size; count++){
2495     for(chn = 0; chn < channels; chn++){
2496       res = 0;
2497 
2498       switch(ags_format){
2499       case AGS_SOUNDCARD_SIGNED_8_BIT:
2500       {
2501 	res = (int) ((gint8 *) buffer)[count * channels + chn];
2502       }
2503       break;
2504       case AGS_SOUNDCARD_SIGNED_16_BIT:
2505       {
2506 	res = (int) ((gint16 *) buffer)[count * channels + chn];
2507       }
2508       break;
2509       case AGS_SOUNDCARD_SIGNED_24_BIT:
2510       {
2511 	res = (int) ((gint32 *) buffer)[count * channels + chn];
2512       }
2513       break;
2514       case AGS_SOUNDCARD_SIGNED_32_BIT:
2515       {
2516 	res = (int) ((gint32 *) buffer)[count * channels + chn];
2517       }
2518       break;
2519       }
2520 
2521       /* Generate data in native endian format */
2522       if(ags_endian_host_is_be()){
2523 	for(i = 0; i < bps; i++){
2524 	  *(ring_buffer + chn * bps + word_size - 1 - i) = (res >> i * 8) & 0xff;
2525 	}
2526       }else{
2527 	for(i = 0; i < bps; i++){
2528 	  *(ring_buffer + chn * bps + i) = (res >>  i * 8) & 0xff;
2529 	}
2530       }
2531     }
2532 
2533     ring_buffer += channels * bps;
2534   }
2535 }
2536 
2537 gboolean
ags_devout_oss_io_func(GIOChannel * source,GIOCondition condition,AgsDevout * devout)2538 ags_devout_oss_io_func(GIOChannel *source,
2539 		       GIOCondition condition,
2540 		       AgsDevout *devout)
2541 {
2542   g_atomic_int_set(&(devout->available), TRUE);
2543 
2544   return(TRUE);
2545 }
2546 
2547 void
ags_devout_oss_play(AgsSoundcard * soundcard,GError ** error)2548 ags_devout_oss_play(AgsSoundcard *soundcard,
2549 		    GError **error)
2550 {
2551   AgsDevout *devout;
2552 
2553   AgsTicDevice *tic_device;
2554   AgsClearBuffer *clear_buffer;
2555   AgsSwitchBufferFlag *switch_buffer_flag;
2556 
2557   AgsTaskLauncher *task_launcher;
2558 
2559   AgsApplicationContext *application_context;
2560 
2561   GList *task;
2562   GList *list;
2563 
2564   gchar *str;
2565 
2566   gint64 poll_timeout;
2567   guint word_size;
2568   guint nth_buffer;
2569 
2570   int n_write;
2571 
2572   GRecMutex *devout_mutex;
2573 
2574   devout = AGS_DEVOUT(soundcard);
2575 
2576   application_context = ags_application_context_get_instance();
2577 
2578   /* get devout mutex */
2579   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
2580 
2581   /* lock */
2582   g_rec_mutex_lock(devout_mutex);
2583 
2584   /* retrieve word size */
2585   switch(devout->format){
2586   case AGS_SOUNDCARD_SIGNED_8_BIT:
2587     {
2588       word_size = sizeof(gint8);
2589     }
2590     break;
2591   case AGS_SOUNDCARD_SIGNED_16_BIT:
2592     {
2593       word_size = sizeof(gint16);
2594     }
2595     break;
2596   case AGS_SOUNDCARD_SIGNED_24_BIT:
2597     {
2598       word_size = sizeof(gint32);
2599     }
2600     break;
2601   case AGS_SOUNDCARD_SIGNED_32_BIT:
2602     {
2603       word_size = sizeof(gint32);
2604     }
2605     break;
2606   case AGS_SOUNDCARD_SIGNED_64_BIT:
2607     {
2608       word_size = sizeof(gint64);
2609     }
2610     //NOTE:JK: not available    break;
2611   default:
2612     g_warning("ags_devout_oss_play(): unsupported word size");
2613     return;
2614   }
2615 
2616   /* do playback */
2617   devout->flags &= (~AGS_DEVOUT_START_PLAY);
2618 
2619   if((AGS_DEVOUT_INITIALIZED & (devout->flags)) == 0){
2620     g_rec_mutex_unlock(devout_mutex);
2621 
2622     return;
2623   }
2624 
2625   /* check buffer flag */
2626   nth_buffer = 0;
2627 
2628   if((AGS_DEVOUT_BUFFER0 & (devout->flags)) != 0){
2629     nth_buffer = 0;
2630   }else if((AGS_DEVOUT_BUFFER1 & (devout->flags)) != 0){
2631     nth_buffer = 1;
2632   }else if((AGS_DEVOUT_BUFFER2 & (devout->flags)) != 0){
2633     nth_buffer = 2;
2634   }else if((AGS_DEVOUT_BUFFER3 & (devout->flags)) != 0){
2635     nth_buffer = 3;
2636   }
2637 
2638 #ifdef AGS_WITH_OSS
2639   /* fill ring buffer */
2640   ags_soundcard_lock_buffer(soundcard,
2641 			    devout->buffer[nth_buffer]);
2642 
2643   ags_devout_oss_play_fill_ring_buffer(devout->buffer[nth_buffer],
2644 				       devout->format,
2645 				       devout->ring_buffer[devout->nth_ring_buffer],
2646 				       devout->pcm_channels,
2647 				       devout->buffer_size);
2648 
2649   ags_soundcard_unlock_buffer(soundcard,
2650 			      devout->buffer[nth_buffer]);
2651 
2652   /* wait until available */
2653   poll_timeout = g_get_monotonic_time() + (G_USEC_PER_SEC * (1.0 / (gdouble) devout->samplerate * (gdouble) devout->buffer_size));
2654 
2655   g_rec_mutex_unlock(devout_mutex);
2656 
2657   //TODO:JK: implement me
2658 
2659   while(!ags_soundcard_is_available(AGS_SOUNDCARD(devout))){
2660     g_usleep(1);
2661 
2662     if(g_get_monotonic_time() > poll_timeout){
2663       break;
2664     }
2665   }
2666 
2667   g_atomic_int_set(&(devout->available),
2668 		   FALSE);
2669 
2670   g_rec_mutex_lock(devout_mutex);
2671 
2672   /* write ring buffer */
2673   n_write = write(devout->out.oss.device_fd,
2674 		  devout->ring_buffer[devout->nth_ring_buffer],
2675 		  devout->pcm_channels * devout->buffer_size * word_size * sizeof (char));
2676 
2677   if(n_write != devout->pcm_channels * devout->buffer_size * word_size * sizeof (char)){
2678     g_critical("write() return doesn't match written bytes");
2679   }
2680 #endif
2681 
2682   /* increment nth ring-buffer */
2683   if(devout->nth_ring_buffer + 1 >= devout->ring_buffer_size){
2684     devout->nth_ring_buffer = 0;
2685   }else{
2686     devout->nth_ring_buffer += 1;
2687   }
2688 
2689   g_rec_mutex_unlock(devout_mutex);
2690 
2691   /* update soundcard */
2692   task_launcher = ags_concurrency_provider_get_task_launcher(AGS_CONCURRENCY_PROVIDER(application_context));
2693 
2694   task = NULL;
2695 
2696   /* tic soundcard */
2697   tic_device = ags_tic_device_new((GObject *) devout);
2698   task = g_list_append(task,
2699 		       tic_device);
2700 
2701   /* reset - clear buffer */
2702   clear_buffer = ags_clear_buffer_new((GObject *) devout);
2703   task = g_list_append(task,
2704 		       clear_buffer);
2705 
2706   /* reset - clear buffer */
2707   clear_buffer = ags_clear_buffer_new((GObject *) devout);
2708   task = g_list_append(task,
2709 		       clear_buffer);
2710 
2711   /* reset - switch buffer flags */
2712   switch_buffer_flag = ags_switch_buffer_flag_new((GObject *) devout);
2713   task = g_list_append(task,
2714 		       switch_buffer_flag);
2715 
2716   /* append tasks */
2717   ags_task_launcher_add_task_all(task_launcher,
2718 				 task);
2719 
2720   /* unref */
2721   g_object_unref(task_launcher);
2722 }
2723 
2724 void
ags_devout_oss_free(AgsSoundcard * soundcard)2725 ags_devout_oss_free(AgsSoundcard *soundcard)
2726 {
2727   AgsDevout *devout;
2728 
2729   guint i;
2730 
2731   GRecMutex *devout_mutex;
2732 
2733   devout = AGS_DEVOUT(soundcard);
2734 
2735   /* get devout mutex */
2736   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
2737 
2738   /*  */
2739   g_rec_mutex_lock(devout_mutex);
2740 
2741   if((AGS_DEVOUT_INITIALIZED & (devout->flags)) == 0){
2742     g_rec_mutex_unlock(devout_mutex);
2743 
2744     return;
2745   }
2746 
2747   close(devout->out.oss.device_fd);
2748   devout->out.oss.device_fd = -1;
2749 
2750   /* free ring-buffer */
2751   g_atomic_int_set(&(devout->available), TRUE);
2752 
2753   if(devout->ring_buffer != NULL){
2754     for(i = 0; i < devout->ring_buffer_size; i++){
2755       free(devout->ring_buffer[i]);
2756     }
2757 
2758     free(devout->ring_buffer);
2759   }
2760 
2761   devout->ring_buffer = NULL;
2762 
2763   /* reset flags */
2764   devout->flags &= (~(AGS_DEVOUT_BUFFER0 |
2765 		      AGS_DEVOUT_BUFFER1 |
2766 		      AGS_DEVOUT_BUFFER2 |
2767 		      AGS_DEVOUT_BUFFER3 |
2768 		      AGS_DEVOUT_PLAY |
2769 		      AGS_DEVOUT_INITIALIZED));
2770 
2771   devout->note_offset = devout->start_note_offset;
2772   devout->note_offset_absolute = devout->start_note_offset;
2773 
2774   g_rec_mutex_unlock(devout_mutex);
2775 }
2776 
2777 gboolean
ags_devout_alsa_io_func(GIOChannel * source,GIOCondition condition,AgsDevout * devout)2778 ags_devout_alsa_io_func(GIOChannel *source,
2779 			GIOCondition condition,
2780 			AgsDevout *devout)
2781 {
2782   g_atomic_int_set(&(devout->available), TRUE);
2783 
2784   return(TRUE);
2785 }
2786 
2787 void
ags_devout_alsa_init(AgsSoundcard * soundcard,GError ** error)2788 ags_devout_alsa_init(AgsSoundcard *soundcard,
2789 		     GError **error)
2790 {
2791   AgsDevout *devout;
2792 
2793 #ifdef AGS_WITH_ALSA
2794 
2795   snd_pcm_t *handle;
2796   snd_pcm_hw_params_t *hwparams;
2797   snd_pcm_sw_params_t *swparams;
2798 
2799   gchar *str;
2800 
2801   int rc;
2802   unsigned int val;
2803   snd_pcm_uframes_t frames;
2804   unsigned int rate;
2805   unsigned int rrate;
2806   unsigned int channels;
2807   snd_pcm_uframes_t size;
2808   snd_pcm_sframes_t buffer_size;
2809   snd_pcm_sframes_t period_size;
2810   snd_pcm_format_t format;
2811 
2812   int period_event;
2813 
2814   int err, dir;
2815 #endif
2816 
2817   guint word_size;
2818   guint i, i_stop;
2819 
2820   GRecMutex *devout_mutex;
2821 
2822   static unsigned int period_time = 100000;
2823   static unsigned int buffer_time = 100000;
2824 
2825   if(ags_soundcard_is_playing(soundcard)){
2826     return;
2827   }
2828 
2829   devout = AGS_DEVOUT(soundcard);
2830 
2831   /* get devout mutex */
2832   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
2833 
2834   /* retrieve word size */
2835   g_rec_mutex_lock(devout_mutex);
2836 
2837   if(devout->out.alsa.device == NULL){
2838     g_rec_mutex_unlock(devout_mutex);
2839 
2840     return;
2841   }
2842 
2843 #ifdef AGS_WITH_ALSA
2844   format = SND_PCM_FORMAT_S16;
2845 #endif
2846 
2847   switch(devout->format){
2848   case AGS_SOUNDCARD_SIGNED_8_BIT:
2849     {
2850 #ifdef AGS_WITH_ALSA
2851       format = SND_PCM_FORMAT_S8;
2852 #endif
2853 
2854       word_size = sizeof(gint8);
2855     }
2856     break;
2857   case AGS_SOUNDCARD_SIGNED_16_BIT:
2858     {
2859 #ifdef AGS_WITH_ALSA
2860       format = SND_PCM_FORMAT_S16;
2861 #endif
2862 
2863       word_size = sizeof(gint16);
2864     }
2865     break;
2866   case AGS_SOUNDCARD_SIGNED_24_BIT:
2867     {
2868 #ifdef AGS_WITH_ALSA
2869       format = SND_PCM_FORMAT_S24;
2870 #endif
2871 
2872       //NOTE:JK: The 24-bit linear samples use 32-bit physical space
2873       word_size = sizeof(gint32);
2874     }
2875     break;
2876   case AGS_SOUNDCARD_SIGNED_32_BIT:
2877     {
2878 #ifdef AGS_WITH_ALSA
2879       format = SND_PCM_FORMAT_S32;
2880 #endif
2881 
2882       word_size = sizeof(gint32);
2883     }
2884     break;
2885   case AGS_SOUNDCARD_SIGNED_64_BIT:
2886     {
2887       word_size = sizeof(gint64);
2888     }
2889     break;
2890   default:
2891     g_rec_mutex_unlock(devout_mutex);
2892 
2893     g_warning("ags_devout_alsa_init(): unsupported word size");
2894 
2895     return;
2896   }
2897 
2898   /* prepare for playback */
2899   devout->flags |= (AGS_DEVOUT_START_PLAY |
2900 		    AGS_DEVOUT_PLAY |
2901 		    AGS_DEVOUT_NONBLOCKING);
2902 
2903   memset(devout->buffer[0], 0, devout->pcm_channels * devout->buffer_size * word_size);
2904   memset(devout->buffer[1], 0, devout->pcm_channels * devout->buffer_size * word_size);
2905   memset(devout->buffer[2], 0, devout->pcm_channels * devout->buffer_size * word_size);
2906   memset(devout->buffer[3], 0, devout->pcm_channels * devout->buffer_size * word_size);
2907 
2908   /* allocate ring buffer */
2909 #ifdef AGS_WITH_ALSA
2910   devout->ring_buffer = (unsigned char **) malloc(devout->ring_buffer_size * sizeof(unsigned char *));
2911 
2912   for(i = 0; i < devout->ring_buffer_size; i++){
2913     devout->ring_buffer[i] = (unsigned char *) malloc(devout->pcm_channels *
2914 						      devout->buffer_size * (snd_pcm_format_physical_width(format) / 8) *
2915 						      sizeof(unsigned char));
2916   }
2917 
2918   /*  */
2919   period_event = 0;
2920 
2921   /* Open PCM device for playback. */
2922   handle = NULL;
2923 
2924   if((err = snd_pcm_open(&handle, devout->out.alsa.device, SND_PCM_STREAM_PLAYBACK, 0)) < 0){
2925     gchar *device_fixup;
2926 
2927     str = snd_strerror(err);
2928     g_warning("Playback open error (attempting fixup): %s", str);
2929 
2930     device_fixup = g_strdup_printf("%s,0",
2931 				   devout->out.alsa.device);
2932 
2933     handle = NULL;
2934 
2935     if((err = snd_pcm_open(&handle, device_fixup, SND_PCM_STREAM_PLAYBACK, 0)) < 0){
2936       devout->flags &= (~(AGS_DEVOUT_START_PLAY |
2937 			  AGS_DEVOUT_PLAY |
2938 			  AGS_DEVOUT_NONBLOCKING));
2939 
2940       g_rec_mutex_unlock(devout_mutex);
2941 
2942       if(error != NULL){
2943 	g_set_error(error,
2944 		    AGS_DEVOUT_ERROR,
2945 		    AGS_DEVOUT_ERROR_LOCKED_SOUNDCARD,
2946 		    "unable to open pcm device: %s",
2947 		    str);
2948       }
2949 
2950       return;
2951     }
2952   }
2953 
2954   snd_pcm_hw_params_alloca(&hwparams);
2955   snd_pcm_sw_params_alloca(&swparams);
2956 
2957   /* choose all parameters */
2958   err = snd_pcm_hw_params_any(handle, hwparams);
2959 
2960   if (err < 0) {
2961     devout->flags &= (~(AGS_DEVOUT_START_PLAY |
2962 			AGS_DEVOUT_PLAY |
2963 			AGS_DEVOUT_NONBLOCKING));
2964 
2965     g_rec_mutex_unlock(devout_mutex);
2966 
2967     str = snd_strerror(err);
2968     g_warning("Broken configuration for playback: no configurations available: %s", str);
2969 
2970     if(error != NULL){
2971       g_set_error(error,
2972 		  AGS_DEVOUT_ERROR,
2973 		  AGS_DEVOUT_ERROR_BROKEN_CONFIGURATION,
2974 		  "unable to open pcm device: %s",
2975 		  str);
2976     }
2977 
2978     devout->out.alsa.handle = NULL;
2979 
2980     //    free(str);
2981 
2982     return;
2983   }
2984 
2985   /* set hardware resampling * /
2986      err = snd_pcm_hw_params_set_rate_resample(handle, hwparams, 0);
2987      if (err < 0) {
2988      g_rec_mutex_unlock(devout_mutex);
2989 
2990      str = snd_strerror(err);
2991      g_warning("Resampling setup failed for playback: %s\n", str);
2992 
2993      //    free(str);
2994 
2995      return;
2996      }
2997   */
2998 
2999   /* set the interleaved read/write format */
3000   err = snd_pcm_hw_params_set_access(handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED);
3001   if (err < 0) {
3002     devout->flags &= (~(AGS_DEVOUT_START_PLAY |
3003 			AGS_DEVOUT_PLAY |
3004 			AGS_DEVOUT_NONBLOCKING));
3005 
3006     g_rec_mutex_unlock(devout_mutex);
3007 
3008     str = snd_strerror(err);
3009     g_warning("Access type not available for playback: %s", str);
3010 
3011     if(error != NULL){
3012       g_set_error(error,
3013 		  AGS_DEVOUT_ERROR,
3014 		  AGS_DEVOUT_ERROR_ACCESS_TYPE_NOT_AVAILABLE,
3015 		  "unable to open pcm device: %s",
3016 		  str);
3017     }
3018 
3019     devout->out.alsa.handle = NULL;
3020 
3021     //    free(str);
3022 
3023     return;
3024   }
3025 
3026   /* set the sample format */
3027   err = snd_pcm_hw_params_set_format(handle, hwparams, format);
3028   if (err < 0) {
3029     devout->flags &= (~(AGS_DEVOUT_START_PLAY |
3030 			AGS_DEVOUT_PLAY |
3031 			AGS_DEVOUT_NONBLOCKING));
3032 
3033     g_rec_mutex_unlock(devout_mutex);
3034 
3035     str = snd_strerror(err);
3036     g_warning("Sample format not available for playback: %s", str);
3037 
3038     if(error != NULL){
3039       g_set_error(error,
3040 		  AGS_DEVOUT_ERROR,
3041 		  AGS_DEVOUT_ERROR_SAMPLE_FORMAT_NOT_AVAILABLE,
3042 		  "unable to open pcm device: %s",
3043 		  str);
3044     }
3045 
3046     devout->out.alsa.handle = NULL;
3047 
3048     //    free(str);
3049 
3050     return;
3051   }
3052 
3053   /* set the count of channels */
3054   channels = devout->pcm_channels;
3055   err = snd_pcm_hw_params_set_channels(handle, hwparams, channels);
3056   if (err < 0) {
3057     devout->flags &= (~(AGS_DEVOUT_START_PLAY |
3058 			AGS_DEVOUT_PLAY |
3059 			AGS_DEVOUT_NONBLOCKING));
3060 
3061     g_rec_mutex_unlock(devout_mutex);
3062 
3063     str = snd_strerror(err);
3064     g_warning("Channels count (%i) not available for playbacks: %s", channels, str);
3065 
3066     if(error != NULL){
3067       g_set_error(error,
3068 		  AGS_DEVOUT_ERROR,
3069 		  AGS_DEVOUT_ERROR_CHANNELS_NOT_AVAILABLE,
3070 		  "unable to open pcm device: %s",
3071 		  str);
3072     }
3073 
3074     devout->out.alsa.handle = NULL;
3075 
3076     //    free(str);
3077 
3078     return;
3079   }
3080 
3081   /* set the stream rate */
3082   rate = devout->samplerate;
3083   rrate = rate;
3084   err = snd_pcm_hw_params_set_rate_near(handle, hwparams, &rrate, 0);
3085   if (err < 0) {
3086     devout->flags &= (~(AGS_DEVOUT_START_PLAY |
3087 			AGS_DEVOUT_PLAY |
3088 			AGS_DEVOUT_NONBLOCKING));
3089 
3090     g_rec_mutex_unlock(devout_mutex);
3091 
3092     str = snd_strerror(err);
3093     g_warning("Rate %iHz not available for playback: %s", rate, str);
3094 
3095     if(error != NULL){
3096       g_set_error(error,
3097 		  AGS_DEVOUT_ERROR,
3098 		  AGS_DEVOUT_ERROR_SAMPLERATE_NOT_AVAILABLE,
3099 		  "unable to open pcm device: %s",
3100 		  str);
3101     }
3102 
3103     devout->out.alsa.handle = NULL;
3104 
3105     //    free(str);
3106 
3107     return;
3108   }
3109 
3110   if (rrate != rate) {
3111     devout->flags &= (~(AGS_DEVOUT_START_PLAY |
3112 			AGS_DEVOUT_PLAY |
3113 			AGS_DEVOUT_NONBLOCKING));
3114 
3115     g_rec_mutex_unlock(devout_mutex);
3116 
3117     g_warning("Rate doesn't match (requested %iHz, get %iHz)", rate, err);
3118 
3119     if(error != NULL){
3120       g_set_error(error,
3121 		  AGS_DEVOUT_ERROR,
3122 		  AGS_DEVOUT_ERROR_SAMPLERATE_NOT_AVAILABLE,
3123 		  "unable to open pcm device");
3124     }
3125 
3126     devout->out.alsa.handle = NULL;
3127 
3128     return;
3129   }
3130 
3131   /* set the buffer size */
3132   size = 2 * devout->buffer_size;
3133   err = snd_pcm_hw_params_set_buffer_size(handle, hwparams, size);
3134 
3135   if (err < 0) {
3136     devout->flags &= (~(AGS_DEVOUT_START_PLAY |
3137 			AGS_DEVOUT_PLAY |
3138 			AGS_DEVOUT_NONBLOCKING));
3139 
3140     g_rec_mutex_unlock(devout_mutex);
3141 
3142     str = snd_strerror(err);
3143     g_warning("Unable to set buffer size %lu for playback: %s", size, str);
3144 
3145     if(error != NULL){
3146       g_set_error(error,
3147 		  AGS_DEVOUT_ERROR,
3148 		  AGS_DEVOUT_ERROR_BUFFER_SIZE_NOT_AVAILABLE,
3149 		  "unable to open pcm device: %s",
3150 		  str);
3151     }
3152 
3153     devout->out.alsa.handle = NULL;
3154 
3155     //    free(str);
3156 
3157     return;
3158   }
3159 
3160   /* set the period size * /
3161      period_size = devout->buffer_size;
3162      err = snd_pcm_hw_params_set_period_size_near(handle, hwparams, period_size, dir);
3163      if (err < 0) {
3164      g_rec_mutex_unlock(devout_mutex);
3165 
3166      str = snd_strerror(err);
3167      g_warning("Unable to get period size for playback: %s\n", str);
3168 
3169      //    free(str);
3170 
3171      return;
3172      }
3173   */
3174 
3175   /* write the parameters to device */
3176   err = snd_pcm_hw_params(handle, hwparams);
3177 
3178   if (err < 0) {
3179     devout->flags &= (~(AGS_DEVOUT_START_PLAY |
3180 			AGS_DEVOUT_PLAY |
3181 			AGS_DEVOUT_NONBLOCKING));
3182 
3183     g_rec_mutex_unlock(devout_mutex);
3184 
3185     str = snd_strerror(err);
3186     g_warning("Unable to set hw params for playback: %s", str);
3187 
3188     if(error != NULL){
3189       g_set_error(error,
3190 		  AGS_DEVOUT_ERROR,
3191 		  AGS_DEVOUT_ERROR_HW_PARAMETERS_NOT_AVAILABLE,
3192 		  "unable to open pcm device: %s",
3193 		  str);
3194     }
3195 
3196     devout->out.alsa.handle = NULL;
3197 
3198     //    free(str);
3199 
3200     return;
3201   }
3202 
3203   /* get the current swparams * /
3204      err = snd_pcm_sw_params_current(handle, swparams);
3205      if (err < 0) {
3206      g_rec_mutex_unlock(devout_mutex);
3207 
3208      str = snd_strerror(err);
3209      g_warning("Unable to determine current swparams for playback: %s\n", str);
3210 
3211      //    free(str);
3212 
3213      return;
3214      }
3215   */
3216   /* start the transfer when the buffer is almost full: */
3217   /* (buffer_size / avail_min) * avail_min * /
3218      err = snd_pcm_sw_params_set_start_threshold(handle, swparams, (buffer_size / period_size) * period_size);
3219      if (err < 0) {
3220      g_rec_mutex_unlock(devout_mutex);
3221 
3222      str = snd_strerror(err);
3223      g_warning("Unable to set start threshold mode for playback: %s\n", str);
3224 
3225      //    free(str);
3226 
3227      return;
3228      }
3229   */
3230   /* allow the transfer when at least period_size samples can be processed */
3231   /* or disable this mechanism when period event is enabled (aka interrupt like style processing) * /
3232      err = snd_pcm_sw_params_set_avail_min(handle, swparams, period_event ? buffer_size : period_size);
3233      if (err < 0) {
3234      g_rec_mutex_unlock(devout_mutex);
3235 
3236      str = snd_strerror(err);
3237      g_warning("Unable to set avail min for playback: %s\n", str);
3238 
3239      //    free(str);
3240 
3241      return;
3242      }
3243 
3244      /* write the parameters to the playback device * /
3245      err = snd_pcm_sw_params(handle, swparams);
3246      if (err < 0) {
3247      g_rec_mutex_unlock(devout_mutex);
3248 
3249      str = snd_strerror(err);
3250      g_warning("Unable to set sw params for playback: %s\n", str);
3251 
3252      //    free(str);
3253 
3254      return;
3255      }
3256   */
3257 
3258   /*  */
3259   devout->out.alsa.handle = handle;
3260 
3261 #if 0
3262   i_stop = snd_pcm_poll_descriptors_count(devout->out.alsa.handle);
3263 
3264   if(i_stop > 0){
3265     struct pollfd *fds;
3266 
3267     fds = (struct pollfd *) malloc(i_stop * sizeof(struct pollfd));
3268 
3269     snd_pcm_poll_descriptors(devout->out.alsa.handle, fds, i_stop);
3270 
3271     for(i = 0; i < i_stop; i++){
3272       GIOChannel *io_channel;
3273 
3274       guint tag;
3275 
3276       io_channel = g_io_channel_unix_new(fds[i].fd);
3277       tag = g_io_add_watch(io_channel,
3278 			   G_IO_OUT,
3279 			   (GIOFunc) ags_devout_alsa_io_func,
3280 			   devout);
3281 
3282       devout->io_channel = g_list_prepend(devout->io_channel,
3283 					  io_channel);
3284       devout->tag = g_list_prepend(devout->tag,
3285 				   GUINT_TO_POINTER(tag));
3286     }
3287   }
3288 #endif
3289 #endif
3290 
3291   devout->tact_counter = 0.0;
3292   devout->delay_counter = floor(ags_soundcard_get_absolute_delay(AGS_SOUNDCARD(devout)));
3293   devout->tic_counter = 0;
3294 
3295   devout->nth_ring_buffer = 0;
3296 
3297 #ifdef AGS_WITH_ALSA
3298   devout->flags |= AGS_DEVOUT_INITIALIZED;
3299 #endif
3300   devout->flags |= AGS_DEVOUT_BUFFER0;
3301   devout->flags &= (~(AGS_DEVOUT_BUFFER1 |
3302 		      AGS_DEVOUT_BUFFER2 |
3303 		      AGS_DEVOUT_BUFFER3));
3304 
3305   g_rec_mutex_unlock(devout_mutex);
3306 }
3307 
3308 void
ags_devout_alsa_play_fill_ring_buffer(void * buffer,guint ags_format,unsigned char * ring_buffer,guint channels,guint buffer_size)3309 ags_devout_alsa_play_fill_ring_buffer(void *buffer,
3310 				      guint ags_format,
3311 				      unsigned char *ring_buffer,
3312 				      guint channels,
3313 				      guint buffer_size)
3314 {
3315 #ifdef AGS_WITH_ALSA
3316   snd_pcm_format_t format;
3317 
3318   int format_bits;
3319 
3320   unsigned int max_val;
3321 
3322   int bps; /* bytes per sample */
3323   int phys_bps;
3324 
3325   int big_endian;
3326   int to_unsigned;
3327 
3328   int res[8];
3329 
3330   gint count;
3331   guint i, chn;
3332 
3333   format = SND_PCM_FORMAT_S16;
3334 
3335   switch(ags_format){
3336   case AGS_SOUNDCARD_SIGNED_8_BIT:
3337   {
3338     format = SND_PCM_FORMAT_S8;
3339   }
3340   break;
3341   case AGS_SOUNDCARD_SIGNED_16_BIT:
3342   {
3343     format = SND_PCM_FORMAT_S16;
3344   }
3345   break;
3346   case AGS_SOUNDCARD_SIGNED_24_BIT:
3347   {
3348     format = SND_PCM_FORMAT_S24;
3349   }
3350   break;
3351   case AGS_SOUNDCARD_SIGNED_32_BIT:
3352   {
3353     format = SND_PCM_FORMAT_S32;
3354   }
3355   break;
3356   default:
3357     g_warning("ags_devout_alsa_play(): unsupported word size");
3358     return;
3359   }
3360 
3361   count = buffer_size;
3362   format_bits = snd_pcm_format_width(format);
3363 
3364   max_val = (1 << (format_bits - 1)) - 1;
3365 
3366   bps = format_bits / 8;
3367   phys_bps = snd_pcm_format_physical_width(format) / 8;
3368 
3369   big_endian = snd_pcm_format_big_endian(format) == 1;
3370   to_unsigned = snd_pcm_format_unsigned(format) == 1;
3371 
3372   /* fill the channel areas */
3373   for(count = 0; count < buffer_size - (buffer_size % 8);){
3374     for(chn = 0; chn < channels; chn++){
3375       switch(ags_format){
3376       case AGS_SOUNDCARD_SIGNED_8_BIT:
3377       {
3378 	res[0] = (int) ((gint8 *) buffer)[count * channels + chn];
3379 	res[1] = (int) ((gint8 *) buffer)[(count + 1) * channels + chn];
3380 	res[2] = (int) ((gint8 *) buffer)[(count + 2) * channels + chn];
3381 	res[3] = (int) ((gint8 *) buffer)[(count + 3) * channels + chn];
3382 	res[4] = (int) ((gint8 *) buffer)[(count + 4) * channels + chn];
3383 	res[5] = (int) ((gint8 *) buffer)[(count + 5) * channels + chn];
3384 	res[6] = (int) ((gint8 *) buffer)[(count + 6) * channels + chn];
3385 	res[7] = (int) ((gint8 *) buffer)[(count + 7) * channels + chn];
3386       }
3387       break;
3388       case AGS_SOUNDCARD_SIGNED_16_BIT:
3389       {
3390 	res[0] = (int) ((gint16 *) buffer)[count * channels + chn];
3391 	res[1] = (int) ((gint16 *) buffer)[(count + 1) * channels + chn];
3392 	res[2] = (int) ((gint16 *) buffer)[(count + 2) * channels + chn];
3393 	res[3] = (int) ((gint16 *) buffer)[(count + 3) * channels + chn];
3394 	res[4] = (int) ((gint16 *) buffer)[(count + 4) * channels + chn];
3395 	res[5] = (int) ((gint16 *) buffer)[(count + 5) * channels + chn];
3396 	res[6] = (int) ((gint16 *) buffer)[(count + 6) * channels + chn];
3397 	res[7] = (int) ((gint16 *) buffer)[(count + 7) * channels + chn];
3398       }
3399       break;
3400       case AGS_SOUNDCARD_SIGNED_24_BIT:
3401       {
3402 	res[0] = (int) ((gint32 *) buffer)[count * channels + chn];
3403 	res[1] = (int) ((gint32 *) buffer)[(count + 1) * channels + chn];
3404 	res[2] = (int) ((gint32 *) buffer)[(count + 2) * channels + chn];
3405 	res[3] = (int) ((gint32 *) buffer)[(count + 3) * channels + chn];
3406 	res[4] = (int) ((gint32 *) buffer)[(count + 4) * channels + chn];
3407 	res[5] = (int) ((gint32 *) buffer)[(count + 5) * channels + chn];
3408 	res[6] = (int) ((gint32 *) buffer)[(count + 6) * channels + chn];
3409 	res[7] = (int) ((gint32 *) buffer)[(count + 7) * channels + chn];
3410       }
3411       break;
3412       case AGS_SOUNDCARD_SIGNED_32_BIT:
3413       {
3414 	res[0] = (int) ((gint32 *) buffer)[count * channels + chn];
3415 	res[1] = (int) ((gint32 *) buffer)[(count + 1) * channels + chn];
3416 	res[2] = (int) ((gint32 *) buffer)[(count + 2) * channels + chn];
3417 	res[3] = (int) ((gint32 *) buffer)[(count + 3) * channels + chn];
3418 	res[4] = (int) ((gint32 *) buffer)[(count + 4) * channels + chn];
3419 	res[5] = (int) ((gint32 *) buffer)[(count + 5) * channels + chn];
3420 	res[6] = (int) ((gint32 *) buffer)[(count + 6) * channels + chn];
3421 	res[7] = (int) ((gint32 *) buffer)[(count + 7) * channels + chn];
3422       }
3423       break;
3424       default:
3425 	res[0] = 0;
3426 	res[1] = 0;
3427 	res[2] = 0;
3428 	res[3] = 0;
3429 	res[4] = 0;
3430 	res[5] = 0;
3431 	res[6] = 0;
3432 	res[7] = 0;
3433       }
3434 
3435       if(to_unsigned){
3436 	res[0] ^= 1U << (format_bits - 1);
3437 	res[1] ^= 1U << (format_bits - 1);
3438 	res[2] ^= 1U << (format_bits - 1);
3439 	res[3] ^= 1U << (format_bits - 1);
3440 	res[4] ^= 1U << (format_bits - 1);
3441 	res[5] ^= 1U << (format_bits - 1);
3442 	res[6] ^= 1U << (format_bits - 1);
3443 	res[7] ^= 1U << (format_bits - 1);
3444       }
3445 
3446       /* Generate data in native endian format */
3447       if(big_endian){
3448 	for(i = 0; i < bps; i++){
3449 	  *(ring_buffer + chn * bps + phys_bps - 1 - i) = (res[0] >> i * 8) & 0xff;
3450 	  *(ring_buffer + channels * bps + chn * bps + phys_bps - 1 - i) = (res[1] >> i * 8) & 0xff;
3451 	  *(ring_buffer + 2 * channels * bps + chn * bps + phys_bps - 1 - i) = (res[2] >> i * 8) & 0xff;
3452 	  *(ring_buffer + 3 * channels * bps + chn * bps + phys_bps - 1 - i) = (res[3] >> i * 8) & 0xff;
3453 	  *(ring_buffer + 4 * channels * bps + chn * bps + phys_bps - 1 - i) = (res[4] >> i * 8) & 0xff;
3454 	  *(ring_buffer + 5 * channels * bps + chn * bps + phys_bps - 1 - i) = (res[5] >> i * 8) & 0xff;
3455 	  *(ring_buffer + 6 * channels * bps + chn * bps + phys_bps - 1 - i) = (res[6] >> i * 8) & 0xff;
3456 	  *(ring_buffer + 7 * channels * bps + chn * bps + phys_bps - 1 - i) = (res[7] >> i * 8) & 0xff;
3457 	}
3458       }else{
3459 	for(i = 0; i < bps; i++){
3460 	  *(ring_buffer + chn * bps + i) = (res[0] >> i * 8) & 0xff;
3461 	  *(ring_buffer + channels * bps + chn * bps + i) = (res[1] >>  i * 8) & 0xff;
3462 	  *(ring_buffer + 2 * channels * bps + chn * bps + i) = (res[2] >>  i * 8) & 0xff;
3463 	  *(ring_buffer + 3 * channels * bps + chn * bps + i) = (res[3] >>  i * 8) & 0xff;
3464 	  *(ring_buffer + 4 * channels * bps + chn * bps + i) = (res[4] >>  i * 8) & 0xff;
3465 	  *(ring_buffer + 5 * channels * bps + chn * bps + i) = (res[5] >>  i * 8) & 0xff;
3466 	  *(ring_buffer + 6 * channels * bps + chn * bps + i) = (res[6] >>  i * 8) & 0xff;
3467 	  *(ring_buffer + 7 * channels * bps + chn * bps + i) = (res[7] >>  i * 8) & 0xff;
3468 	}
3469       }
3470     }
3471 
3472     ring_buffer += 8 * channels * bps;
3473     count += 8;
3474   }
3475 
3476   for(; count < buffer_size; count++){
3477     for(chn = 0; chn < channels; chn++){
3478       switch(ags_format){
3479       case AGS_SOUNDCARD_SIGNED_8_BIT:
3480       {
3481 	res[0] = (int) ((gint8 *) buffer)[count * channels + chn];
3482       }
3483       break;
3484       case AGS_SOUNDCARD_SIGNED_16_BIT:
3485       {
3486 	res[0] = (int) ((gint16 *) buffer)[count * channels + chn];
3487       }
3488       break;
3489       case AGS_SOUNDCARD_SIGNED_24_BIT:
3490       {
3491 	res[0] = (int) ((gint32 *) buffer)[count * channels + chn];
3492       }
3493       break;
3494       case AGS_SOUNDCARD_SIGNED_32_BIT:
3495       {
3496 	res[0] = (int) ((gint32 *) buffer)[count * channels + chn];
3497       }
3498       break;
3499       default:
3500 	res[0] = 0;
3501       }
3502 
3503       if(to_unsigned){
3504 	res[0] ^= 1U << (format_bits - 1);
3505       }
3506 
3507       /* Generate data in native endian format */
3508       if(big_endian){
3509 	for(i = 0; i < bps; i++){
3510 	  *(ring_buffer + chn * bps + phys_bps - 1 - i) = (res[0] >> i * 8) & 0xff;
3511 	}
3512       }else{
3513 	for(i = 0; i < bps; i++){
3514 	  *(ring_buffer + chn * bps + i) = (res[0] >>  i * 8) & 0xff;
3515 	}
3516       }
3517     }
3518 
3519     ring_buffer += channels * bps;
3520   }
3521 #endif
3522 }
3523 
3524 void
ags_devout_alsa_play(AgsSoundcard * soundcard,GError ** error)3525 ags_devout_alsa_play(AgsSoundcard *soundcard,
3526 		     GError **error)
3527 {
3528   AgsDevout *devout;
3529 
3530   AgsTicDevice *tic_device;
3531   AgsClearBuffer *clear_buffer;
3532   AgsSwitchBufferFlag *switch_buffer_flag;
3533 
3534   AgsTaskLauncher *task_launcher;
3535 
3536   AgsApplicationContext *application_context;
3537 
3538   GList *task;
3539   GList *list;
3540 
3541   gchar *str;
3542 
3543   gint64 poll_timeout;
3544   guint word_size;
3545   guint nth_buffer;
3546 
3547   GRecMutex *devout_mutex;
3548 
3549   devout = AGS_DEVOUT(soundcard);
3550 
3551   application_context = ags_application_context_get_instance();
3552 
3553   /* get devout mutex */
3554   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
3555 
3556   /* lock */
3557   g_rec_mutex_lock(devout_mutex);
3558 
3559   /* retrieve word size */
3560   switch(devout->format){
3561   case AGS_SOUNDCARD_SIGNED_8_BIT:
3562     {
3563       word_size = sizeof(gint8);
3564     }
3565     break;
3566   case AGS_SOUNDCARD_SIGNED_16_BIT:
3567     {
3568       word_size = sizeof(gint16);
3569     }
3570     break;
3571   case AGS_SOUNDCARD_SIGNED_24_BIT:
3572     {
3573       word_size = sizeof(gint32);
3574     }
3575     break;
3576   case AGS_SOUNDCARD_SIGNED_32_BIT:
3577     {
3578       word_size = sizeof(gint32);
3579     }
3580     break;
3581   case AGS_SOUNDCARD_SIGNED_64_BIT:
3582     {
3583       word_size = sizeof(gint64);
3584     }
3585     break;
3586   default:
3587     g_rec_mutex_unlock(devout_mutex);
3588 
3589     g_warning("ags_devout_alsa_play(): unsupported word size");
3590 
3591     return;
3592   }
3593 
3594   /* do playback */
3595   devout->flags &= (~AGS_DEVOUT_START_PLAY);
3596 
3597   if((AGS_DEVOUT_INITIALIZED & (devout->flags)) == 0){
3598     g_rec_mutex_unlock(devout_mutex);
3599 
3600     return;
3601   }
3602 
3603   //  g_message("play - 0x%0x", ((AGS_DEVOUT_BUFFER0 |
3604   //				AGS_DEVOUT_BUFFER1 |
3605   //				AGS_DEVOUT_BUFFER2 |
3606   //				AGS_DEVOUT_BUFFER3) & (devout->flags)));
3607 
3608   /* check buffer flag */
3609   nth_buffer = 0;
3610 
3611   if((AGS_DEVOUT_BUFFER0 & (devout->flags)) != 0){
3612     nth_buffer = 0;
3613   }else if((AGS_DEVOUT_BUFFER1 & (devout->flags)) != 0){
3614     nth_buffer = 1;
3615   }else if((AGS_DEVOUT_BUFFER2 & (devout->flags)) != 0){
3616     nth_buffer = 2;
3617   }else if((AGS_DEVOUT_BUFFER3 & (devout->flags)) != 0){
3618     nth_buffer = 3;
3619   }
3620 
3621 #ifdef AGS_WITH_ALSA
3622 
3623   /* fill ring buffer */
3624   ags_soundcard_lock_buffer(soundcard,
3625 			    devout->buffer[nth_buffer]);
3626 
3627   ags_devout_alsa_play_fill_ring_buffer(devout->buffer[nth_buffer], devout->format,
3628 					devout->ring_buffer[devout->nth_ring_buffer],
3629 					devout->pcm_channels, devout->buffer_size);
3630 
3631   ags_soundcard_unlock_buffer(soundcard,
3632 			      devout->buffer[nth_buffer]);
3633 
3634   /* wait until available */
3635   poll_timeout = g_get_monotonic_time() + (G_USEC_PER_SEC * (1.0 / (gdouble) devout->samplerate * (gdouble) devout->buffer_size));
3636 
3637   g_rec_mutex_unlock(devout_mutex);
3638 
3639   //TODO:JK: implement me
3640   while(!ags_soundcard_is_available(AGS_SOUNDCARD(devout))){
3641     g_usleep(1);
3642 
3643     if(g_get_monotonic_time() > poll_timeout){
3644       break;
3645     }
3646   }
3647 
3648   g_atomic_int_set(&(devout->available),
3649 		   FALSE);
3650 
3651   g_rec_mutex_lock(devout_mutex);
3652 
3653   /* write ring buffer */
3654 //  g_message("write %d", devout->buffer_size);
3655 
3656   devout->out.alsa.rc = snd_pcm_writei(devout->out.alsa.handle,
3657 				       devout->ring_buffer[devout->nth_ring_buffer],
3658 				       (snd_pcm_uframes_t) (devout->buffer_size));
3659 
3660   /* check error flag */
3661   if((AGS_DEVOUT_NONBLOCKING & (devout->flags)) == 0){
3662     if(devout->out.alsa.rc == -EPIPE){
3663       /* EPIPE means underrun */
3664       snd_pcm_prepare(devout->out.alsa.handle);
3665 
3666 #ifdef AGS_DEBUG
3667       g_message("underrun occurred");
3668 #endif
3669     }else if(devout->out.alsa.rc == -ESTRPIPE){
3670       static const struct timespec idle = {
3671 	0,
3672 	4000,
3673       };
3674 
3675       int err;
3676 
3677       while((err = snd_pcm_resume(devout->out.alsa.handle)) < 0){ // == -EAGAIN
3678 	nanosleep(&idle, NULL); /* wait until the suspend flag is released */
3679       }
3680 
3681       if(err < 0){
3682 	err = snd_pcm_prepare(devout->out.alsa.handle);
3683       }
3684     }else if(devout->out.alsa.rc < 0){
3685       str = snd_strerror(devout->out.alsa.rc);
3686 
3687       g_message("error from writei: %s", str);
3688     }else if(devout->out.alsa.rc != (int) devout->buffer_size) {
3689       g_message("short write, write %d frames", devout->out.alsa.rc);
3690     }
3691   }
3692 
3693 #endif
3694 
3695   /* increment nth ring-buffer */
3696   if(devout->nth_ring_buffer + 1 >= devout->ring_buffer_size){
3697     devout->nth_ring_buffer = 0;
3698   }else{
3699     devout->nth_ring_buffer += 1;
3700   }
3701 
3702   g_rec_mutex_unlock(devout_mutex);
3703 
3704   /* update soundcard */
3705   task_launcher = ags_concurrency_provider_get_task_launcher(AGS_CONCURRENCY_PROVIDER(application_context));
3706 
3707   task = NULL;
3708 
3709   /* tic soundcard */
3710   tic_device = ags_tic_device_new((GObject *) devout);
3711 
3712   task = g_list_prepend(task,
3713 			tic_device);
3714 
3715   /* reset - clear buffer */
3716   clear_buffer = ags_clear_buffer_new((GObject *) devout);
3717 
3718   task = g_list_prepend(task,
3719 			clear_buffer);
3720 
3721   /* reset - switch buffer flags */
3722   switch_buffer_flag = ags_switch_buffer_flag_new((GObject *) devout);
3723 
3724   task = g_list_prepend(task,
3725 			switch_buffer_flag);
3726 
3727   /* append tasks */
3728   task = g_list_reverse(task);
3729 
3730   ags_task_launcher_add_task_all(task_launcher,
3731 				 task);
3732 
3733   g_list_free_full(task,
3734 		   g_object_unref);
3735 
3736 #ifdef AGS_WITH_ALSA
3737   snd_pcm_prepare(devout->out.alsa.handle);
3738 #endif
3739 
3740   /* unref */
3741   g_object_unref(task_launcher);
3742 }
3743 
3744 void
ags_devout_alsa_free(AgsSoundcard * soundcard)3745 ags_devout_alsa_free(AgsSoundcard *soundcard)
3746 {
3747   AgsDevout *devout;
3748 
3749   GList *start_list, *list;
3750 
3751   guint i;
3752 
3753   GRecMutex *devout_mutex;
3754 
3755   devout = AGS_DEVOUT(soundcard);
3756 
3757   /* get devout mutex */
3758   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
3759 
3760   /* lock */
3761   g_rec_mutex_lock(devout_mutex);
3762 
3763   if((AGS_DEVOUT_INITIALIZED & (devout->flags)) == 0){
3764     g_rec_mutex_unlock(devout_mutex);
3765 
3766     return;
3767   }
3768 
3769   g_rec_mutex_unlock(devout_mutex);
3770 
3771 #ifdef AGS_WITH_ALSA
3772   //  snd_pcm_drain(devout->out.alsa.handle);
3773   snd_pcm_close(devout->out.alsa.handle);
3774   devout->out.alsa.handle = NULL;
3775 #endif
3776 
3777   /* free ring-buffer */
3778   g_rec_mutex_lock(devout_mutex);
3779 
3780   if(devout->ring_buffer != NULL){
3781     for(i = 0; i < devout->ring_buffer_size; i++){
3782       free(devout->ring_buffer[i]);
3783     }
3784 
3785     free(devout->ring_buffer);
3786   }
3787 
3788   devout->ring_buffer = NULL;
3789 
3790   /* reset flags */
3791   devout->flags &= (~(AGS_DEVOUT_BUFFER0 |
3792 		      AGS_DEVOUT_BUFFER1 |
3793 		      AGS_DEVOUT_BUFFER2 |
3794 		      AGS_DEVOUT_BUFFER3 |
3795 		      AGS_DEVOUT_PLAY |
3796 		      AGS_DEVOUT_INITIALIZED));
3797 
3798   g_rec_mutex_unlock(devout_mutex);
3799 
3800   g_rec_mutex_lock(devout_mutex);
3801 
3802   devout->note_offset = devout->start_note_offset;
3803   devout->note_offset_absolute = devout->start_note_offset;
3804 
3805   list = devout->tag;
3806 
3807   while(list != NULL){
3808     g_source_remove(GPOINTER_TO_UINT(list->data));
3809 
3810     list = list->next;
3811   }
3812 
3813   g_list_free(devout->tag);
3814 
3815   devout->tag = NULL;
3816 
3817   g_list_free_full(devout->io_channel,
3818 		   g_io_channel_unref);
3819 
3820   devout->io_channel = NULL;
3821 
3822   g_atomic_int_set(&(devout->available), TRUE);
3823 
3824   g_rec_mutex_unlock(devout_mutex);
3825 }
3826 
3827 void
ags_devout_tic(AgsSoundcard * soundcard)3828 ags_devout_tic(AgsSoundcard *soundcard)
3829 {
3830   AgsDevout *devout;
3831 
3832   gdouble delay;
3833   gdouble delay_counter;
3834   guint note_offset_absolute;
3835   guint note_offset;
3836   guint loop_left, loop_right;
3837   gboolean do_loop;
3838 
3839   GRecMutex *devout_mutex;
3840 
3841   devout = AGS_DEVOUT(soundcard);
3842 
3843   /* get devout mutex */
3844   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
3845 
3846   /* determine if attack should be switched */
3847   g_rec_mutex_lock(devout_mutex);
3848 
3849   delay = devout->delay[devout->tic_counter];
3850   delay_counter = devout->delay_counter;
3851 
3852   note_offset = devout->note_offset;
3853   note_offset_absolute = devout->note_offset_absolute;
3854 
3855   loop_left = devout->loop_left;
3856   loop_right = devout->loop_right;
3857 
3858   do_loop = devout->do_loop;
3859 
3860   g_rec_mutex_unlock(devout_mutex);
3861 
3862   if(delay_counter + 1.0 >= floor(delay)){
3863     if(do_loop &&
3864        note_offset + 1 == loop_right){
3865       ags_soundcard_set_note_offset(soundcard,
3866 				    loop_left);
3867     }else{
3868       ags_soundcard_set_note_offset(soundcard,
3869 				    note_offset + 1);
3870     }
3871 
3872     ags_soundcard_set_note_offset_absolute(soundcard,
3873 					   note_offset_absolute + 1);
3874 
3875     /* delay */
3876     ags_soundcard_offset_changed(soundcard,
3877 				 note_offset);
3878 
3879     /* reset - delay counter */
3880     g_rec_mutex_lock(devout_mutex);
3881 
3882     devout->delay_counter = delay_counter + 1.0 - delay;
3883     devout->tact_counter += 1.0;
3884 
3885     g_rec_mutex_unlock(devout_mutex);
3886   }else{
3887     g_rec_mutex_lock(devout_mutex);
3888 
3889     devout->delay_counter += 1.0;
3890 
3891     g_rec_mutex_unlock(devout_mutex);
3892   }
3893 }
3894 
3895 void
ags_devout_offset_changed(AgsSoundcard * soundcard,guint note_offset)3896 ags_devout_offset_changed(AgsSoundcard *soundcard,
3897 			  guint note_offset)
3898 {
3899   AgsDevout *devout;
3900 
3901   GRecMutex *devout_mutex;
3902 
3903   devout = AGS_DEVOUT(soundcard);
3904 
3905   /* get devout mutex */
3906   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
3907 
3908   /* offset changed */
3909   g_rec_mutex_lock(devout_mutex);
3910 
3911   devout->tic_counter += 1;
3912 
3913   if(devout->tic_counter == AGS_SOUNDCARD_DEFAULT_PERIOD){
3914     /* reset - tic counter i.e. modified delay index within period */
3915     devout->tic_counter = 0;
3916   }
3917 
3918   g_rec_mutex_unlock(devout_mutex);
3919 }
3920 
3921 void
ags_devout_set_bpm(AgsSoundcard * soundcard,gdouble bpm)3922 ags_devout_set_bpm(AgsSoundcard *soundcard,
3923 		   gdouble bpm)
3924 {
3925   AgsDevout *devout;
3926 
3927   GRecMutex *devout_mutex;
3928 
3929   devout = AGS_DEVOUT(soundcard);
3930 
3931   /* get devout mutex */
3932   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
3933 
3934   /* set bpm */
3935   g_rec_mutex_lock(devout_mutex);
3936 
3937   devout->bpm = bpm;
3938 
3939   g_rec_mutex_unlock(devout_mutex);
3940 
3941   ags_devout_adjust_delay_and_attack(devout);
3942 }
3943 
3944 gdouble
ags_devout_get_bpm(AgsSoundcard * soundcard)3945 ags_devout_get_bpm(AgsSoundcard *soundcard)
3946 {
3947   AgsDevout *devout;
3948 
3949   gdouble bpm;
3950 
3951   GRecMutex *devout_mutex;
3952 
3953   devout = AGS_DEVOUT(soundcard);
3954 
3955   /* get devout mutex */
3956   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
3957 
3958   /* get bpm */
3959   g_rec_mutex_lock(devout_mutex);
3960 
3961   bpm = devout->bpm;
3962 
3963   g_rec_mutex_unlock(devout_mutex);
3964 
3965   return(bpm);
3966 }
3967 
3968 void
ags_devout_set_delay_factor(AgsSoundcard * soundcard,gdouble delay_factor)3969 ags_devout_set_delay_factor(AgsSoundcard *soundcard,
3970 			    gdouble delay_factor)
3971 {
3972   AgsDevout *devout;
3973 
3974   GRecMutex *devout_mutex;
3975 
3976   devout = AGS_DEVOUT(soundcard);
3977 
3978   /* get devout mutex */
3979   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
3980 
3981   /* set delay factor */
3982   g_rec_mutex_lock(devout_mutex);
3983 
3984   devout->delay_factor = delay_factor;
3985 
3986   g_rec_mutex_unlock(devout_mutex);
3987 
3988   ags_devout_adjust_delay_and_attack(devout);
3989 }
3990 
3991 gdouble
ags_devout_get_delay_factor(AgsSoundcard * soundcard)3992 ags_devout_get_delay_factor(AgsSoundcard *soundcard)
3993 {
3994   AgsDevout *devout;
3995 
3996   gdouble delay_factor;
3997 
3998   GRecMutex *devout_mutex;
3999 
4000   devout = AGS_DEVOUT(soundcard);
4001 
4002   /* get devout mutex */
4003   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
4004 
4005   /* get delay factor */
4006   g_rec_mutex_lock(devout_mutex);
4007 
4008   delay_factor = devout->delay_factor;
4009 
4010   g_rec_mutex_unlock(devout_mutex);
4011 
4012   return(delay_factor);
4013 }
4014 
4015 gdouble
ags_devout_get_delay(AgsSoundcard * soundcard)4016 ags_devout_get_delay(AgsSoundcard *soundcard)
4017 {
4018   AgsDevout *devout;
4019 
4020   guint delay_index;
4021   gdouble delay;
4022 
4023   GRecMutex *devout_mutex;
4024 
4025   devout = AGS_DEVOUT(soundcard);
4026 
4027   /* get devout mutex */
4028   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
4029 
4030   /* get delay */
4031   g_rec_mutex_lock(devout_mutex);
4032 
4033   delay_index = devout->tic_counter;
4034 
4035   delay = devout->delay[delay_index];
4036 
4037   g_rec_mutex_unlock(devout_mutex);
4038 
4039   return(delay);
4040 }
4041 
4042 gdouble
ags_devout_get_absolute_delay(AgsSoundcard * soundcard)4043 ags_devout_get_absolute_delay(AgsSoundcard *soundcard)
4044 {
4045   AgsDevout *devout;
4046 
4047   gdouble absolute_delay;
4048 
4049   GRecMutex *devout_mutex;
4050 
4051   devout = AGS_DEVOUT(soundcard);
4052 
4053   /* get devout mutex */
4054   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
4055 
4056   /* get absolute delay */
4057   g_rec_mutex_lock(devout_mutex);
4058 
4059   absolute_delay = (60.0 * (((gdouble) devout->samplerate / (gdouble) devout->buffer_size) / (gdouble) devout->bpm) * ((1.0 / 16.0) * (1.0 / (gdouble) devout->delay_factor)));
4060 
4061   g_rec_mutex_unlock(devout_mutex);
4062 
4063   return(absolute_delay);
4064 }
4065 
4066 guint
ags_devout_get_attack(AgsSoundcard * soundcard)4067 ags_devout_get_attack(AgsSoundcard *soundcard)
4068 {
4069   AgsDevout *devout;
4070 
4071   guint attack_index;
4072   guint attack;
4073 
4074   GRecMutex *devout_mutex;
4075 
4076   devout = AGS_DEVOUT(soundcard);
4077 
4078   /* get devout mutex */
4079   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
4080 
4081   /* get attack */
4082   g_rec_mutex_lock(devout_mutex);
4083 
4084   attack_index = devout->tic_counter;
4085 
4086   attack = devout->attack[attack_index];
4087 
4088   g_rec_mutex_unlock(devout_mutex);
4089 
4090   return(attack);
4091 }
4092 
4093 void*
ags_devout_get_buffer(AgsSoundcard * soundcard)4094 ags_devout_get_buffer(AgsSoundcard *soundcard)
4095 {
4096   AgsDevout *devout;
4097 
4098   void *buffer;
4099 
4100   devout = AGS_DEVOUT(soundcard);
4101 
4102   if(ags_devout_test_flags(devout, AGS_DEVOUT_BUFFER0)){
4103     buffer = devout->buffer[0];
4104   }else if(ags_devout_test_flags(devout, AGS_DEVOUT_BUFFER1)){
4105     buffer = devout->buffer[1];
4106   }else if(ags_devout_test_flags(devout, AGS_DEVOUT_BUFFER2)){
4107     buffer = devout->buffer[2];
4108   }else if(ags_devout_test_flags(devout, AGS_DEVOUT_BUFFER3)){
4109     buffer = devout->buffer[3];
4110   }else{
4111     buffer = NULL;
4112   }
4113 
4114   return(buffer);
4115 }
4116 
4117 void*
ags_devout_get_next_buffer(AgsSoundcard * soundcard)4118 ags_devout_get_next_buffer(AgsSoundcard *soundcard)
4119 {
4120   AgsDevout *devout;
4121 
4122   void *buffer;
4123 
4124   devout = AGS_DEVOUT(soundcard);
4125 
4126   //  g_message("next - 0x%0x", ((AGS_DEVOUT_BUFFER0 |
4127   //				AGS_DEVOUT_BUFFER1 |
4128   //				AGS_DEVOUT_BUFFER2 |
4129   //				AGS_DEVOUT_BUFFER3) & (devout->flags)));
4130 
4131   if(ags_devout_test_flags(devout, AGS_DEVOUT_BUFFER0)){
4132     buffer = devout->buffer[1];
4133   }else if(ags_devout_test_flags(devout, AGS_DEVOUT_BUFFER1)){
4134     buffer = devout->buffer[2];
4135   }else if(ags_devout_test_flags(devout, AGS_DEVOUT_BUFFER2)){
4136     buffer = devout->buffer[3];
4137   }else if(ags_devout_test_flags(devout, AGS_DEVOUT_BUFFER3)){
4138     buffer = devout->buffer[0];
4139   }else{
4140     buffer = NULL;
4141   }
4142 
4143   return(buffer);
4144 }
4145 
4146 void*
ags_devout_get_prev_buffer(AgsSoundcard * soundcard)4147 ags_devout_get_prev_buffer(AgsSoundcard *soundcard)
4148 {
4149   AgsDevout *devout;
4150 
4151   void *buffer;
4152 
4153   devout = AGS_DEVOUT(soundcard);
4154 
4155   if(ags_devout_test_flags(devout, AGS_DEVOUT_BUFFER0)){
4156     buffer = devout->buffer[3];
4157   }else if(ags_devout_test_flags(devout, AGS_DEVOUT_BUFFER1)){
4158     buffer = devout->buffer[0];
4159   }else if(ags_devout_test_flags(devout, AGS_DEVOUT_BUFFER2)){
4160     buffer = devout->buffer[1];
4161   }else if(ags_devout_test_flags(devout, AGS_DEVOUT_BUFFER3)){
4162     buffer = devout->buffer[2];
4163   }else{
4164     buffer = NULL;
4165   }
4166 
4167   return(buffer);
4168 }
4169 
4170 void
ags_devout_lock_buffer(AgsSoundcard * soundcard,void * buffer)4171 ags_devout_lock_buffer(AgsSoundcard *soundcard,
4172 		       void *buffer)
4173 {
4174   AgsDevout *devout;
4175 
4176   GRecMutex *buffer_mutex;
4177 
4178   devout = AGS_DEVOUT(soundcard);
4179 
4180   buffer_mutex = NULL;
4181 
4182   if(devout->buffer != NULL){
4183     if(buffer == devout->buffer[0]){
4184       buffer_mutex = devout->buffer_mutex[0];
4185     }else if(buffer == devout->buffer[1]){
4186       buffer_mutex = devout->buffer_mutex[1];
4187     }else if(buffer == devout->buffer[2]){
4188       buffer_mutex = devout->buffer_mutex[2];
4189     }else if(buffer == devout->buffer[3]){
4190       buffer_mutex = devout->buffer_mutex[3];
4191     }
4192   }
4193 
4194   if(buffer_mutex != NULL){
4195     g_rec_mutex_lock(buffer_mutex);
4196   }
4197 }
4198 
4199 void
ags_devout_unlock_buffer(AgsSoundcard * soundcard,void * buffer)4200 ags_devout_unlock_buffer(AgsSoundcard *soundcard,
4201 			 void *buffer)
4202 {
4203   AgsDevout *devout;
4204 
4205   GRecMutex *buffer_mutex;
4206 
4207   devout = AGS_DEVOUT(soundcard);
4208 
4209   buffer_mutex = NULL;
4210 
4211   if(devout->buffer != NULL){
4212     if(buffer == devout->buffer[0]){
4213       buffer_mutex = devout->buffer_mutex[0];
4214     }else if(buffer == devout->buffer[1]){
4215       buffer_mutex = devout->buffer_mutex[1];
4216     }else if(buffer == devout->buffer[2]){
4217       buffer_mutex = devout->buffer_mutex[2];
4218     }else if(buffer == devout->buffer[3]){
4219       buffer_mutex = devout->buffer_mutex[3];
4220     }
4221   }
4222 
4223   if(buffer_mutex != NULL){
4224     g_rec_mutex_unlock(buffer_mutex);
4225   }
4226 }
4227 
4228 guint
ags_devout_get_delay_counter(AgsSoundcard * soundcard)4229 ags_devout_get_delay_counter(AgsSoundcard *soundcard)
4230 {
4231   AgsDevout *devout;
4232 
4233   guint delay_counter;
4234 
4235   GRecMutex *devout_mutex;
4236 
4237   devout = AGS_DEVOUT(soundcard);
4238 
4239   /* get devout mutex */
4240   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
4241 
4242   /* delay counter */
4243   g_rec_mutex_lock(devout_mutex);
4244 
4245   delay_counter = devout->delay_counter;
4246 
4247   g_rec_mutex_unlock(devout_mutex);
4248 
4249   return(delay_counter);
4250 }
4251 
4252 void
ags_devout_set_start_note_offset(AgsSoundcard * soundcard,guint start_note_offset)4253 ags_devout_set_start_note_offset(AgsSoundcard *soundcard,
4254 				 guint start_note_offset)
4255 {
4256   AgsDevout *devout;
4257 
4258   GRecMutex *devout_mutex;
4259 
4260   devout = AGS_DEVOUT(soundcard);
4261 
4262   /* get devout mutex */
4263   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
4264 
4265   /* set note offset */
4266   g_rec_mutex_lock(devout_mutex);
4267 
4268   devout->start_note_offset = start_note_offset;
4269 
4270   g_rec_mutex_unlock(devout_mutex);
4271 }
4272 
4273 guint
ags_devout_get_start_note_offset(AgsSoundcard * soundcard)4274 ags_devout_get_start_note_offset(AgsSoundcard *soundcard)
4275 {
4276   AgsDevout *devout;
4277 
4278   guint start_note_offset;
4279 
4280   GRecMutex *devout_mutex;
4281 
4282   devout = AGS_DEVOUT(soundcard);
4283 
4284   /* get devout mutex */
4285   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
4286 
4287   /* set note offset */
4288   g_rec_mutex_lock(devout_mutex);
4289 
4290   start_note_offset = devout->start_note_offset;
4291 
4292   g_rec_mutex_unlock(devout_mutex);
4293 
4294   return(start_note_offset);
4295 }
4296 
4297 void
ags_devout_set_note_offset(AgsSoundcard * soundcard,guint note_offset)4298 ags_devout_set_note_offset(AgsSoundcard *soundcard,
4299 			   guint note_offset)
4300 {
4301   AgsDevout *devout;
4302 
4303   GRecMutex *devout_mutex;
4304 
4305   devout = AGS_DEVOUT(soundcard);
4306 
4307   /* get devout mutex */
4308   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
4309 
4310   /* set note offset */
4311   g_rec_mutex_lock(devout_mutex);
4312 
4313   devout->note_offset = note_offset;
4314 
4315   g_rec_mutex_unlock(devout_mutex);
4316 }
4317 
4318 guint
ags_devout_get_note_offset(AgsSoundcard * soundcard)4319 ags_devout_get_note_offset(AgsSoundcard *soundcard)
4320 {
4321   AgsDevout *devout;
4322 
4323   guint note_offset;
4324 
4325   GRecMutex *devout_mutex;
4326 
4327   devout = AGS_DEVOUT(soundcard);
4328 
4329   /* get devout mutex */
4330   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
4331 
4332   /* set note offset */
4333   g_rec_mutex_lock(devout_mutex);
4334 
4335   note_offset = devout->note_offset;
4336 
4337   g_rec_mutex_unlock(devout_mutex);
4338 
4339   return(note_offset);
4340 }
4341 
4342 void
ags_devout_set_note_offset_absolute(AgsSoundcard * soundcard,guint note_offset_absolute)4343 ags_devout_set_note_offset_absolute(AgsSoundcard *soundcard,
4344 				    guint note_offset_absolute)
4345 {
4346   AgsDevout *devout;
4347 
4348   GRecMutex *devout_mutex;
4349 
4350   devout = AGS_DEVOUT(soundcard);
4351 
4352   /* get devout mutex */
4353   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
4354 
4355   /* set note offset */
4356   g_rec_mutex_lock(devout_mutex);
4357 
4358   devout->note_offset_absolute = note_offset_absolute;
4359 
4360   g_rec_mutex_unlock(devout_mutex);
4361 }
4362 
4363 guint
ags_devout_get_note_offset_absolute(AgsSoundcard * soundcard)4364 ags_devout_get_note_offset_absolute(AgsSoundcard *soundcard)
4365 {
4366   AgsDevout *devout;
4367 
4368   guint note_offset_absolute;
4369 
4370   GRecMutex *devout_mutex;
4371 
4372   devout = AGS_DEVOUT(soundcard);
4373 
4374   /* get devout mutex */
4375   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
4376 
4377   /* set note offset */
4378   g_rec_mutex_lock(devout_mutex);
4379 
4380   note_offset_absolute = devout->note_offset_absolute;
4381 
4382   g_rec_mutex_unlock(devout_mutex);
4383 
4384   return(note_offset_absolute);
4385 }
4386 
4387 void
ags_devout_set_loop(AgsSoundcard * soundcard,guint loop_left,guint loop_right,gboolean do_loop)4388 ags_devout_set_loop(AgsSoundcard *soundcard,
4389 		    guint loop_left, guint loop_right,
4390 		    gboolean do_loop)
4391 {
4392   AgsDevout *devout;
4393 
4394   GRecMutex *devout_mutex;
4395 
4396   devout = AGS_DEVOUT(soundcard);
4397 
4398   /* get devout mutex */
4399   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
4400 
4401   /* set loop */
4402   g_rec_mutex_lock(devout_mutex);
4403 
4404   devout->loop_left = loop_left;
4405   devout->loop_right = loop_right;
4406   devout->do_loop = do_loop;
4407 
4408   if(do_loop){
4409     devout->loop_offset = devout->note_offset;
4410   }
4411 
4412   g_rec_mutex_unlock(devout_mutex);
4413 }
4414 
4415 void
ags_devout_get_loop(AgsSoundcard * soundcard,guint * loop_left,guint * loop_right,gboolean * do_loop)4416 ags_devout_get_loop(AgsSoundcard *soundcard,
4417 		    guint *loop_left, guint *loop_right,
4418 		    gboolean *do_loop)
4419 {
4420   AgsDevout *devout;
4421 
4422   GRecMutex *devout_mutex;
4423 
4424   devout = AGS_DEVOUT(soundcard);
4425 
4426   /* get devout mutex */
4427   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
4428 
4429   /* get loop */
4430   g_rec_mutex_lock(devout_mutex);
4431 
4432   if(loop_left != NULL){
4433     *loop_left = devout->loop_left;
4434   }
4435 
4436   if(loop_right != NULL){
4437     *loop_right = devout->loop_right;
4438   }
4439 
4440   if(do_loop != NULL){
4441     *do_loop = devout->do_loop;
4442   }
4443 
4444   g_rec_mutex_unlock(devout_mutex);
4445 }
4446 
4447 guint
ags_devout_get_loop_offset(AgsSoundcard * soundcard)4448 ags_devout_get_loop_offset(AgsSoundcard *soundcard)
4449 {
4450   AgsDevout *devout;
4451 
4452   guint loop_offset;
4453 
4454   GRecMutex *devout_mutex;
4455 
4456   devout = AGS_DEVOUT(soundcard);
4457 
4458   /* get devout mutex */
4459   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
4460 
4461   /* get loop offset */
4462   g_rec_mutex_lock(devout_mutex);
4463 
4464   loop_offset = devout->loop_offset;
4465 
4466   g_rec_mutex_unlock(devout_mutex);
4467 
4468   return(loop_offset);
4469 }
4470 
4471 guint
ags_devout_get_sub_block_count(AgsSoundcard * soundcard)4472 ags_devout_get_sub_block_count(AgsSoundcard *soundcard)
4473 {
4474   AgsDevout *devout;
4475 
4476   guint sub_block_count;
4477 
4478   GRecMutex *devout_mutex;
4479 
4480   devout = AGS_DEVOUT(soundcard);
4481 
4482   /* get devout mutex */
4483   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
4484 
4485   /* get loop offset */
4486   g_rec_mutex_lock(devout_mutex);
4487 
4488   sub_block_count = devout->sub_block_count;
4489 
4490   g_rec_mutex_unlock(devout_mutex);
4491 
4492   return(sub_block_count);
4493 }
4494 
4495 gboolean
ags_devout_trylock_sub_block(AgsSoundcard * soundcard,void * buffer,guint sub_block)4496 ags_devout_trylock_sub_block(AgsSoundcard *soundcard,
4497 			     void *buffer, guint sub_block)
4498 {
4499   AgsDevout *devout;
4500 
4501   guint pcm_channels;
4502   guint sub_block_count;
4503   gboolean success;
4504 
4505   GRecMutex *devout_mutex;
4506   GRecMutex *sub_block_mutex;
4507 
4508   devout = AGS_DEVOUT(soundcard);
4509 
4510   /* get devout mutex */
4511   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
4512 
4513   /* get loop offset */
4514   g_rec_mutex_lock(devout_mutex);
4515 
4516   pcm_channels = devout->pcm_channels;
4517   sub_block_count = devout->sub_block_count;
4518 
4519   g_rec_mutex_unlock(devout_mutex);
4520 
4521   sub_block_mutex = NULL;
4522 
4523   success = FALSE;
4524 
4525   if(devout->buffer != NULL){
4526     if(buffer == devout->buffer[0]){
4527       sub_block_mutex = devout->sub_block_mutex[sub_block];
4528     }else if(buffer == devout->buffer[1]){
4529       sub_block_mutex = devout->sub_block_mutex[pcm_channels * sub_block_count + sub_block];
4530     }else if(buffer == devout->buffer[2]){
4531       sub_block_mutex = devout->sub_block_mutex[2 * pcm_channels * sub_block_count + sub_block];
4532     }else if(buffer == devout->buffer[3]){
4533       sub_block_mutex = devout->sub_block_mutex[3 * pcm_channels * sub_block_count + sub_block];
4534     }
4535   }
4536 
4537   if(sub_block_mutex != NULL){
4538     if(g_rec_mutex_trylock(sub_block_mutex)){
4539       success = TRUE;
4540     }
4541   }
4542 
4543   return(success);
4544 }
4545 
4546 void
ags_devout_unlock_sub_block(AgsSoundcard * soundcard,void * buffer,guint sub_block)4547 ags_devout_unlock_sub_block(AgsSoundcard *soundcard,
4548 			    void *buffer, guint sub_block)
4549 {
4550   AgsDevout *devout;
4551 
4552   guint pcm_channels;
4553   guint sub_block_count;
4554 
4555   GRecMutex *devout_mutex;
4556   GRecMutex *sub_block_mutex;
4557 
4558   devout = AGS_DEVOUT(soundcard);
4559 
4560   /* get devout mutex */
4561   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
4562 
4563   /* get loop offset */
4564   g_rec_mutex_lock(devout_mutex);
4565 
4566   pcm_channels = devout->pcm_channels;
4567   sub_block_count = devout->sub_block_count;
4568 
4569   g_rec_mutex_unlock(devout_mutex);
4570 
4571   sub_block_mutex = NULL;
4572 
4573   if(devout->buffer != NULL){
4574     if(buffer == devout->buffer[0]){
4575       sub_block_mutex = devout->sub_block_mutex[sub_block];
4576     }else if(buffer == devout->buffer[1]){
4577       sub_block_mutex = devout->sub_block_mutex[pcm_channels * sub_block_count + sub_block];
4578     }else if(buffer == devout->buffer[2]){
4579       sub_block_mutex = devout->sub_block_mutex[2 * pcm_channels * sub_block_count + sub_block];
4580     }else if(buffer == devout->buffer[3]){
4581       sub_block_mutex = devout->sub_block_mutex[3 * pcm_channels * sub_block_count + sub_block];
4582     }
4583   }
4584 
4585   if(sub_block_mutex != NULL){
4586     g_rec_mutex_unlock(sub_block_mutex);
4587   }
4588 }
4589 
4590 /**
4591  * ags_devout_switch_buffer_flag:
4592  * @devout: the #AgsDevout
4593  *
4594  * The buffer flag indicates the currently played buffer.
4595  *
4596  * Since: 3.0.0
4597  */
4598 void
ags_devout_switch_buffer_flag(AgsDevout * devout)4599 ags_devout_switch_buffer_flag(AgsDevout *devout)
4600 {
4601   GRecMutex *devout_mutex;
4602 
4603   if(!AGS_IS_DEVOUT(devout)){
4604     return;
4605   }
4606 
4607   /* get devout mutex */
4608   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
4609 
4610   /* switch buffer flag */
4611   g_rec_mutex_lock(devout_mutex);
4612 
4613   if((AGS_DEVOUT_BUFFER0 & (devout->flags)) != 0){
4614     devout->flags &= (~AGS_DEVOUT_BUFFER0);
4615     devout->flags |= AGS_DEVOUT_BUFFER1;
4616   }else if((AGS_DEVOUT_BUFFER1 & (devout->flags)) != 0){
4617     devout->flags &= (~AGS_DEVOUT_BUFFER1);
4618     devout->flags |= AGS_DEVOUT_BUFFER2;
4619   }else if((AGS_DEVOUT_BUFFER2 & (devout->flags)) != 0){
4620     devout->flags &= (~AGS_DEVOUT_BUFFER2);
4621     devout->flags |= AGS_DEVOUT_BUFFER3;
4622   }else if((AGS_DEVOUT_BUFFER3 & (devout->flags)) != 0){
4623     devout->flags &= (~AGS_DEVOUT_BUFFER3);
4624     devout->flags |= AGS_DEVOUT_BUFFER0;
4625   }
4626 
4627   g_rec_mutex_unlock(devout_mutex);
4628 }
4629 
4630 /**
4631  * ags_devout_adjust_delay_and_attack:
4632  * @devout: the #AgsDevout
4633  *
4634  * Calculate delay and attack and reset it.
4635  *
4636  * Since: 3.0.0
4637  */
4638 void
ags_devout_adjust_delay_and_attack(AgsDevout * devout)4639 ags_devout_adjust_delay_and_attack(AgsDevout *devout)
4640 {
4641   if(!AGS_IS_DEVOUT(devout)){
4642     return;
4643   }
4644 
4645   ags_soundcard_util_adjust_delay_and_attack(devout);
4646 }
4647 
4648 /**
4649  * ags_devout_realloc_buffer:
4650  * @devout: the #AgsDevout
4651  *
4652  * Reallocate the internal audio buffer.
4653  *
4654  * Since: 3.0.0
4655  */
4656 void
ags_devout_realloc_buffer(AgsDevout * devout)4657 ags_devout_realloc_buffer(AgsDevout *devout)
4658 {
4659   guint pcm_channels;
4660   guint buffer_size;
4661   guint word_size;
4662 
4663   GRecMutex *devout_mutex;
4664 
4665   if(!AGS_IS_DEVOUT(devout)){
4666     return;
4667   }
4668 
4669   /* get devout mutex */
4670   devout_mutex = AGS_DEVOUT_GET_OBJ_MUTEX(devout);
4671 
4672   /* get word size */
4673   g_rec_mutex_lock(devout_mutex);
4674 
4675   pcm_channels = devout->pcm_channels;
4676   buffer_size = devout->buffer_size;
4677 
4678   switch(devout->format){
4679   case AGS_SOUNDCARD_SIGNED_8_BIT:
4680     {
4681       word_size = sizeof(gint8);
4682     }
4683     break;
4684   case AGS_SOUNDCARD_SIGNED_16_BIT:
4685     {
4686       word_size = sizeof(gint16);
4687     }
4688     break;
4689   case AGS_SOUNDCARD_SIGNED_24_BIT:
4690     {
4691       word_size = sizeof(gint32);
4692     }
4693     break;
4694   case AGS_SOUNDCARD_SIGNED_32_BIT:
4695     {
4696       word_size = sizeof(gint32);
4697     }
4698     break;
4699   case AGS_SOUNDCARD_SIGNED_64_BIT:
4700     {
4701       word_size = sizeof(gint64);
4702     }
4703     break;
4704   default:
4705     g_warning("ags_devout_realloc_buffer(): unsupported word size");
4706     return;
4707   }
4708 
4709   g_rec_mutex_unlock(devout_mutex);
4710 
4711   //NOTE:JK: there is no lock applicable to buffer
4712 
4713   /* AGS_DEVOUT_BUFFER_0 */
4714   if(devout->buffer[0] != NULL){
4715     free(devout->buffer[0]);
4716   }
4717 
4718   devout->buffer[0] = (void *) malloc(pcm_channels * buffer_size * word_size);
4719 
4720   /* AGS_DEVOUT_BUFFER_1 */
4721   if(devout->buffer[1] != NULL){
4722     free(devout->buffer[1]);
4723   }
4724 
4725   devout->buffer[1] = (void *) malloc(pcm_channels * buffer_size * word_size);
4726 
4727   /* AGS_DEVOUT_BUFFER_2 */
4728   if(devout->buffer[2] != NULL){
4729     free(devout->buffer[2]);
4730   }
4731 
4732   devout->buffer[2] = (void *) malloc(pcm_channels * buffer_size * word_size);
4733 
4734   /* AGS_DEVOUT_BUFFER_3 */
4735   if(devout->buffer[3] != NULL){
4736     free(devout->buffer[3]);
4737   }
4738 
4739   devout->buffer[3] = (void *) malloc(pcm_channels * buffer_size * word_size);
4740 }
4741 
4742 /**
4743  * ags_devout_new:
4744  *
4745  * Creates a new instance of #AgsDevout.
4746  *
4747  * Returns: the new #AgsDevout
4748  *
4749  * Since: 3.0.0
4750  */
4751 AgsDevout*
ags_devout_new()4752 ags_devout_new()
4753 {
4754   AgsDevout *devout;
4755 
4756   devout = (AgsDevout *) g_object_new(AGS_TYPE_DEVOUT,
4757 				      NULL);
4758 
4759   return(devout);
4760 }
4761