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(¶ms);
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