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