1
2 /*
3 * alsa.c -- The Advanced Linux Sound System backend for Speech Dispatcher
4 *
5 * Copyright (C) 2005,2006 Brailcom, o.p.s.
6 * Copyright (C) 2019 Samuel Thibault <samuel.thibault@ens-lyon.org>
7 *
8 * This is free software; you can redistribute it and/or modify it under the
9 * terms of the GNU Lesser General Public License as published by the Free
10 * Software Foundation; either version 2.1, or (at your option) any later
11 * version.
12 *
13 * This software is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <https://www.gnu.org/licenses/>.
20 *
21 * $Id: alsa.c,v 1.30 2008-10-15 17:27:32 hanke Exp $
22 */
23
24 /* NOTE: This module uses the non-blocking write() / poll() approach to
25 alsa-lib functions.*/
26
27 #ifdef HAVE_CONFIG_H
28 #include <config.h>
29 #endif
30
31 #include <stdio.h>
32 #include <sys/time.h>
33 #include <time.h>
34 #include <pthread.h>
35 #include <glib.h>
36
37 #include <alsa/asoundlib.h>
38 #include <alsa/pcm.h>
39
40 #define SPD_AUDIO_PLUGIN_ENTRY spd_alsa_LTX_spd_audio_plugin_get
41 #include <spd_audio_plugin.h>
42
43 typedef struct {
44 AudioID id;
45 snd_pcm_t *alsa_pcm; /* identifier of the ALSA device */
46 snd_pcm_hw_params_t *alsa_hw_params; /* parameters of sound */
47 snd_pcm_sw_params_t *alsa_sw_params; /* parameters of playback */
48 snd_pcm_uframes_t alsa_buffer_size;
49 pthread_mutex_t alsa_pcm_mutex; /* mutex to guard the state of the device */
50 pthread_mutex_t alsa_pipe_mutex; /* mutex to guard the stop pipes */
51 pthread_cond_t alsa_pipe_cond; /* mutex to guard the stop pipes */
52 int alsa_stop_pipe[2]; /* Pipe for communication about stop requests */
53 int stop_requested; /* Whether we want to stop */
54 int alsa_fd_count; /* Counter of descriptors to poll */
55 struct pollfd *alsa_poll_fds; /* Descriptors to poll */
56 int alsa_opened; /* 1 between snd_pcm_open and _close, 0 otherwise */
57 char *alsa_device_name; /* the name of the device to open */
58 } spd_alsa_id_t;
59
60 static int _alsa_close(spd_alsa_id_t * id);
61 static int _alsa_open(spd_alsa_id_t * id);
62
63 static int xrun(spd_alsa_id_t * id);
64 static int suspend(spd_alsa_id_t * id);
65
66 static int wait_for_poll(spd_alsa_id_t * id, struct pollfd *alsa_poll_fds,
67 unsigned int count, int draining);
68
69 #ifndef timersub
70 #define timersub(a, b, result) \
71 do { \
72 (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
73 (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
74 if ((result)->tv_usec < 0) { \
75 --(result)->tv_sec; \
76 (result)->tv_usec += 1000000; \
77 } \
78 } while (0)
79 #endif
80
81 /* Put a message into the logfile (stderr) */
82 #define MSG(level, arg...) \
83 if(level <= alsa_log_level){ \
84 time_t t; \
85 struct timeval tv; \
86 char *tstr; \
87 t = time(NULL); \
88 tstr = g_strdup(ctime(&t)); \
89 tstr[strlen(tstr)-1] = 0; \
90 gettimeofday(&tv,NULL); \
91 fprintf(stderr," %s [%d.%06d]",tstr, (int)tv.tv_sec % 10, (int) tv.tv_usec); \
92 fprintf(stderr," ALSA: "); \
93 fprintf(stderr,arg); \
94 fprintf(stderr,"\n"); \
95 fflush(stderr); \
96 g_free(tstr); \
97 }
98
99 #define ERR(arg...) \
100 { \
101 time_t t; \
102 struct timeval tv; \
103 char *tstr; \
104 t = time(NULL); \
105 tstr = g_strdup(ctime(&t)); \
106 tstr[strlen(tstr)-1] = 0; \
107 gettimeofday(&tv,NULL); \
108 fprintf(stderr," %s [%d]",tstr, (int) tv.tv_usec); \
109 fprintf(stderr," ALSA ERROR: "); \
110 fprintf(stderr,arg); \
111 fprintf(stderr,"\n"); \
112 fflush(stderr); \
113 g_free(tstr); \
114 }
115
116 static int alsa_log_level;
117 static char const *alsa_play_cmd = "aplay";
118
119 /* I/O error handler */
xrun(spd_alsa_id_t * id)120 static int xrun(spd_alsa_id_t * id)
121 {
122 snd_pcm_status_t *status;
123 int res;
124
125 if (id == NULL)
126 return -1;
127
128 MSG(1, "WARNING: Entering XRUN handler");
129
130 snd_pcm_status_alloca(&status);
131 if ((res = snd_pcm_status(id->alsa_pcm, status)) < 0) {
132 ERR("status error: %s", snd_strerror(res));
133
134 return -1;
135 }
136 if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN) {
137 struct timeval now, diff, tstamp;
138 gettimeofday(&now, 0);
139 snd_pcm_status_get_trigger_tstamp(status, &tstamp);
140 timersub(&now, &tstamp, &diff);
141 MSG(1, "underrun!!! (at least %.3f ms long)",
142 diff.tv_sec * 1000 + diff.tv_usec / 1000.0);
143 if ((res = snd_pcm_prepare(id->alsa_pcm)) < 0) {
144 ERR("xrun: prepare error: %s", snd_strerror(res));
145
146 return -1;
147 }
148
149 return 0; /* ok, data should be accepted again */
150 }
151 ERR("read/write error, state = %s",
152 snd_pcm_state_name(snd_pcm_status_get_state(status)));
153
154 return -1;
155 }
156
157 /* I/O suspend handler */
suspend(spd_alsa_id_t * id)158 static int suspend(spd_alsa_id_t * id)
159 {
160 int res;
161
162 MSG(1, "WARNING: Entering SUSPEND handler.");
163
164 if (id == NULL)
165 return -1;
166
167 while ((res = snd_pcm_resume(id->alsa_pcm)) == -EAGAIN)
168 sleep(1); /* wait until suspend flag is released */
169
170 if (res < 0) {
171 if ((res = snd_pcm_prepare(id->alsa_pcm)) < 0) {
172 ERR("suspend: prepare error: %s", snd_strerror(res));
173
174 return -1;
175 }
176 }
177
178 return 0;
179 }
180
181 /* Open the device so that it's ready for playing on the default
182 device. Internal function used by the public alsa_open. */
_alsa_open(spd_alsa_id_t * id)183 static int _alsa_open(spd_alsa_id_t * id)
184 {
185 int err;
186
187 MSG(1, "Opening ALSA device");
188 fflush(stderr);
189
190 /* Open the device */
191 if ((err = snd_pcm_open(&id->alsa_pcm, id->alsa_device_name,
192 SND_PCM_STREAM_PLAYBACK,
193 SND_PCM_NONBLOCK)) < 0) {
194 ERR("Cannot open audio device %s (%s)", id->alsa_device_name,
195 snd_strerror(err));
196 return -1;
197 }
198
199 /* Allocate space for hw_params (description of the sound parameters) */
200 /* Allocate space for sw_params (description of the sound parameters) */
201 MSG(2, "Allocating new sw_params structure");
202 if ((err = snd_pcm_sw_params_malloc(&id->alsa_sw_params)) < 0) {
203 ERR("Cannot allocate hardware parameter structure (%s)",
204 snd_strerror(err));
205 return -1;
206 }
207
208 MSG(1, "Opening ALSA device ... success");
209
210 return 0;
211 }
212
213 /*
214 Close the device. Internal function used by public alsa_close.
215 */
216
_alsa_close(spd_alsa_id_t * id)217 static int _alsa_close(spd_alsa_id_t * id)
218 {
219 int err;
220
221 MSG(1, "Closing ALSA device");
222
223 pthread_mutex_lock(&id->alsa_pipe_mutex);
224
225 if (id->alsa_opened == 0) {
226 pthread_mutex_unlock(&id->alsa_pipe_mutex);
227 return 0;
228 }
229
230 id->alsa_opened = 0;
231
232 if ((err = snd_pcm_close(id->alsa_pcm)) < 0) {
233 MSG(2, "Cannot close ALSA device (%s)", snd_strerror(err));
234 pthread_mutex_unlock(&id->alsa_pipe_mutex);
235 return -1;
236 }
237
238 snd_pcm_sw_params_free(id->alsa_sw_params);
239
240 g_free(id->alsa_poll_fds);
241 pthread_mutex_unlock(&id->alsa_pipe_mutex);
242
243 MSG(1, "Closing ALSA device ... success");
244
245 return 0;
246 }
247
248 /* Open ALSA for playback.
249
250 These parameters are passed in pars:
251 (char*) pars[0] ... null-terminated string containing the name
252 of the device to be used for sound output
253 on ALSA
254 (void*) pars[1] ... =NULL
255 */
alsa_open(void ** pars)256 static AudioID *alsa_open(void **pars)
257 {
258 spd_alsa_id_t *alsa_id;
259 int ret;
260
261 if (pars[1] == NULL) {
262 ERR("Can't open ALSA sound output, missing parameters in argument.");
263 return NULL;
264 }
265
266 alsa_id = (spd_alsa_id_t *) g_malloc(sizeof(spd_alsa_id_t));
267
268 pthread_mutex_init(&alsa_id->alsa_pipe_mutex, NULL);
269 pthread_cond_init(&alsa_id->alsa_pipe_cond, NULL);
270
271 alsa_id->alsa_opened = 0;
272
273 MSG(1, "Opening ALSA sound output");
274
275 alsa_id->alsa_device_name = g_strdup(pars[1]);
276
277 ret = _alsa_open(alsa_id);
278 if (ret) {
279 ERR("Cannot initialize Alsa device '%s': Can't open.",
280 alsa_id->alsa_device_name);
281 g_free(alsa_id);
282 return NULL;
283 }
284
285 MSG(1, "Device '%s' initialized successfully.",
286 alsa_id->alsa_device_name);
287
288 return (AudioID *) alsa_id;
289 }
290
291 /* Close ALSA */
alsa_close(AudioID * id)292 static int alsa_close(AudioID * id)
293 {
294 int err;
295 spd_alsa_id_t *alsa_id = (spd_alsa_id_t *) id;
296
297 /* Close device */
298 if ((err = _alsa_close(alsa_id)) < 0) {
299 ERR("Cannot close audio device");
300 return -1;
301 }
302 MSG(1, "ALSA closed.");
303
304 g_free(alsa_id->alsa_device_name);
305 g_free(alsa_id);
306 id = NULL;
307
308 return 0;
309 }
310
311 /* Wait until ALSA is readdy for more samples or alsa_stop() was called.
312
313 Returns 0 if ALSA is ready for more input, +1 if a request to stop
314 the sound output was received and a negative value on error. */
315
wait_for_poll(spd_alsa_id_t * id,struct pollfd * alsa_poll_fds,unsigned int count,int draining)316 int wait_for_poll(spd_alsa_id_t * id, struct pollfd *alsa_poll_fds,
317 unsigned int count, int draining)
318 {
319 unsigned short revents;
320 snd_pcm_state_t state;
321 int ret;
322
323 // MSG("Waiting for poll");
324
325 /* Wait for certain events */
326 while (1) {
327 ret = poll(id->alsa_poll_fds, count, -1);
328 // MSG("wait_for_poll: activity on %d descriptors", ret);
329
330 /* Check for stop request from alsa_stop on the last file
331 descriptors */
332 revents = id->alsa_poll_fds[count - 1].revents;
333 if (0 != revents) {
334 if (revents & POLLIN) {
335 MSG(4, "wait_for_poll: stop requested");
336 return 1;
337 }
338 }
339
340 /* Check the first count-1 descriptors for ALSA events */
341 snd_pcm_poll_descriptors_revents(id->alsa_pcm,
342 id->alsa_poll_fds, count - 1,
343 &revents);
344
345 /* Ensure we are in the right state */
346 state = snd_pcm_state(id->alsa_pcm);
347 // MSG("State after poll returned is %s", snd_pcm_state_name(state));
348
349 if (SND_PCM_STATE_XRUN == state) {
350 if (!draining) {
351 MSG(1, "WARNING: Buffer underrun detected!");
352 if (xrun(id) != 0)
353 return -1;
354 return 0;
355 } else {
356 MSG(4, "Poll: Playback terminated");
357 return 0;
358 }
359 }
360
361 if (SND_PCM_STATE_SUSPENDED == state) {
362 MSG(1, "WARNING: Suspend detected!");
363 if (suspend(id) != 0)
364 return -1;
365 return 0;
366 }
367
368 /* Check for errors */
369 if (revents & POLLERR) {
370 MSG(4, "wait_for_poll: poll revents says POLLERR");
371 return -EIO;
372 }
373
374 /* Is ALSA ready for more input? */
375 if ((revents & POLLOUT)) {
376 MSG(5, "Poll: Ready for more input");
377 return 0;
378 }
379 }
380 }
381
382 #define ERROR_EXIT() do {\
383 g_free(track_volume.samples); \
384 ERR("alsa_play() abnormal exit"); \
385 _alsa_close(alsa_id); \
386 return -1; \
387 } while (0)
388
389 /* Configure ALSA playback for the given configuration of track
390 But do not play anything yet */
alsa_begin(AudioID * id,AudioTrack track)391 static int alsa_begin(AudioID * id, AudioTrack track)
392 {
393 snd_pcm_format_t format;
394 spd_alsa_id_t *alsa_id = (spd_alsa_id_t *) id;
395
396 int err;
397
398 snd_pcm_uframes_t period_size;
399 unsigned int sr;
400
401 snd_pcm_state_t state;
402
403 struct pollfd alsa_stop_pipe_pfd;
404
405 if (alsa_id == NULL) {
406 ERR("Invalid device passed to alsa_play()");
407 return -1;
408 }
409
410 pthread_mutex_lock(&alsa_id->alsa_pipe_mutex);
411
412 MSG(2, "Start of playback on ALSA");
413
414 /* Is it not an empty track? */
415 /* Passing an empty track is not an error */
416 if (track.samples == NULL) {
417 pthread_mutex_unlock(&alsa_id->alsa_pipe_mutex);
418 return 0;
419 }
420 /* Allocate space for hw_params (description of the sound parameters) */
421 MSG(2, "Allocating new hw_params structure");
422 if ((err = snd_pcm_hw_params_malloc(&alsa_id->alsa_hw_params)) < 0) {
423 ERR("Cannot allocate hardware parameter structure (%s)",
424 snd_strerror(err));
425 pthread_mutex_unlock(&alsa_id->alsa_pipe_mutex);
426 return -1;
427 }
428
429 /* Initialize hw_params on our pcm */
430 if ((err =
431 snd_pcm_hw_params_any(alsa_id->alsa_pcm,
432 alsa_id->alsa_hw_params)) < 0) {
433 ERR("Cannot initialize hardware parameter structure (%s)",
434 snd_strerror(err));
435 pthread_mutex_unlock(&alsa_id->alsa_pipe_mutex);
436 return -1;
437 }
438
439 /* Create the pipe for communication about stop requests */
440 if (pipe(alsa_id->alsa_stop_pipe)) {
441 ERR("Stop pipe creation failed (%s)", strerror(errno));
442 pthread_mutex_unlock(&alsa_id->alsa_pipe_mutex);
443 return -1;
444 }
445 alsa_id->stop_requested = 0;
446
447 /* Find how many descriptors we will get for poll() */
448 alsa_id->alsa_fd_count =
449 snd_pcm_poll_descriptors_count(alsa_id->alsa_pcm);
450 if (alsa_id->alsa_fd_count <= 0) {
451 ERR("Invalid poll descriptors count returned from ALSA.");
452 pthread_mutex_unlock(&alsa_id->alsa_pipe_mutex);
453 return -1;
454 }
455
456 /* Create and fill in struct pollfd *alsa_poll_fds with ALSA descriptors */
457 alsa_id->alsa_poll_fds =
458 g_malloc((alsa_id->alsa_fd_count + 1) * sizeof(struct pollfd));
459 assert(alsa_id->alsa_poll_fds);
460 if ((err =
461 snd_pcm_poll_descriptors(alsa_id->alsa_pcm, alsa_id->alsa_poll_fds,
462 alsa_id->alsa_fd_count)) < 0) {
463 ERR("Unable to obtain poll descriptors for playback: %s\n",
464 snd_strerror(err));
465 pthread_mutex_unlock(&alsa_id->alsa_pipe_mutex);
466 return -1;
467 }
468
469 /* Create a new pollfd structure for requests by alsa_stop() */
470 alsa_stop_pipe_pfd.fd = alsa_id->alsa_stop_pipe[0];
471 alsa_stop_pipe_pfd.events = POLLIN;
472 alsa_stop_pipe_pfd.revents = 0;
473
474 /* Join this our own pollfd to the ALSAs ones */
475 alsa_id->alsa_poll_fds[alsa_id->alsa_fd_count] = alsa_stop_pipe_pfd;
476 alsa_id->alsa_fd_count++;
477
478 alsa_id->alsa_opened = 1;
479 pthread_mutex_unlock(&alsa_id->alsa_pipe_mutex);
480
481 /* Report current state */
482 state = snd_pcm_state(alsa_id->alsa_pcm);
483 MSG(4, "PCM state before setting audio parameters: %s",
484 snd_pcm_state_name(state));
485
486 /* Choose the correct format */
487 if (track.bits == 16) {
488 switch (alsa_id->id.format) {
489 case SPD_AUDIO_LE:
490 format = SND_PCM_FORMAT_S16_LE;
491 break;
492 case SPD_AUDIO_BE:
493 format = SND_PCM_FORMAT_S16_BE;
494 break;
495 default:
496 ERR("unknown audio format (%d)", alsa_id->id.format);
497 return -1;
498 }
499 } else if (track.bits == 8) {
500 format = SND_PCM_FORMAT_S8;
501 } else {
502 ERR("Unsupported sound data format, track.bits = %d",
503 track.bits);
504 return -1;
505 }
506
507 /* Set access mode, bitrate, sample rate and channels */
508 MSG(4, "Setting access type to INTERLEAVED");
509 if ((err = snd_pcm_hw_params_set_access(alsa_id->alsa_pcm,
510 alsa_id->alsa_hw_params,
511 SND_PCM_ACCESS_RW_INTERLEAVED)
512 ) < 0) {
513 ERR("Cannot set access type (%s)", snd_strerror(err));
514 return -1;
515 }
516
517 MSG(4, "Setting sample format to %s", snd_pcm_format_name(format));
518 if ((err =
519 snd_pcm_hw_params_set_format(alsa_id->alsa_pcm,
520 alsa_id->alsa_hw_params,
521 format)) < 0) {
522 ERR("Cannot set sample format (%s)", snd_strerror(err));
523 return -1;
524 }
525
526 MSG(4, "Setting sample rate to %i", track.sample_rate);
527 sr = track.sample_rate;
528 if ((err =
529 snd_pcm_hw_params_set_rate_near(alsa_id->alsa_pcm,
530 alsa_id->alsa_hw_params, &sr,
531 0)) < 0) {
532 ERR("Cannot set sample rate (%s)", snd_strerror(err));
533
534 return -1;
535 }
536
537 MSG(4, "Setting channel count to %i", track.num_channels);
538 if ((err =
539 snd_pcm_hw_params_set_channels(alsa_id->alsa_pcm,
540 alsa_id->alsa_hw_params,
541 track.num_channels)) < 0) {
542 MSG(4, "cannot set channel count (%s)", snd_strerror(err));
543 return -1;
544 }
545
546 MSG(4, "Setting hardware parameters on the ALSA device");
547 if ((err =
548 snd_pcm_hw_params(alsa_id->alsa_pcm,
549 alsa_id->alsa_hw_params)) < 0) {
550 MSG(4, "cannot set parameters (%s) state=%s", snd_strerror(err),
551 snd_pcm_state_name(snd_pcm_state(alsa_id->alsa_pcm)));
552 return -1;
553 }
554
555 /* Get the current swparams */
556 if ((err =
557 snd_pcm_sw_params_current(alsa_id->alsa_pcm,
558 alsa_id->alsa_sw_params)) < 0) {
559 ERR("Unable to determine current swparams for playback: %s\n",
560 snd_strerror(err));
561 return -1;
562 }
563 // MSG("Checking buffer size");
564 if ((err =
565 snd_pcm_hw_params_get_buffer_size(alsa_id->alsa_hw_params,
566 &(alsa_id->alsa_buffer_size))) <
567 0) {
568 ERR("Unable to get buffer size for playback: %s\n",
569 snd_strerror(err));
570 return -1;
571 }
572 MSG(4, "Buffer size on ALSA device is %d frames",
573 (int)alsa_id->alsa_buffer_size);
574
575 /* This is probably better left for the device driver to decide */
576 /* allow the transfer when at least period_size samples can be processed */
577 /* err = snd_pcm_sw_params_set_avail_min(id->alsa_pcm, id->alsa_sw_params, id->alsa_buffer_size/4);
578 if (err < 0) {
579 ERR("Unable to set avail min for playback: %s\n", snd_strerror(err));
580 return err;
581 } */
582
583 /* Get period size. */
584 snd_pcm_hw_params_get_period_size(alsa_id->alsa_hw_params, &period_size,
585 0);
586 MSG(4, "Period size on ALSA device is %lu frames", (unsigned long) period_size);
587
588 MSG(4, "Preparing device for playback");
589 if ((err = snd_pcm_prepare(alsa_id->alsa_pcm)) < 0) {
590 ERR("Cannot prepare audio interface for playback (%s)",
591 snd_strerror(err));
592
593 return -1;
594 }
595
596 return 0;
597 }
598
599 /* Push audio track to ALSA playback */
alsa_feed(AudioID * id,AudioTrack track)600 static int alsa_feed(AudioID * id, AudioTrack track)
601 {
602 int bytes_per_sample;
603 int num_bytes;
604 spd_alsa_id_t *alsa_id = (spd_alsa_id_t *) id;
605
606 AudioTrack track_volume;
607 float real_volume;
608 int i;
609
610 signed short *output_samples;
611
612 int err;
613 int ret;
614
615 snd_pcm_state_t state;
616
617 snd_pcm_uframes_t framecount;
618 size_t volume_size;
619
620 bytes_per_sample = track.bits / 8;
621
622 /* Calculate space needed to round up to nearest period size. */
623 volume_size = bytes_per_sample * track.num_samples;
624 MSG(4, "volume size = %i", (int)volume_size);
625
626 /* Create a copy of track with adjusted volume. */
627 MSG(4, "Making copy of track and adjusting volume");
628 track_volume = track;
629 track_volume.samples = (short *)g_malloc(volume_size);
630 real_volume = ((float)alsa_id->id.volume + 100) / (float)200;
631 for (i = 0; i <= track.num_samples - 1; i++)
632 track_volume.samples[i] = track.samples[i] * real_volume;
633
634 /* Loop until all samples are played on the device. */
635 output_samples = track_volume.samples;
636 num_bytes = volume_size;
637 MSG(4, "%d bytes to be played", num_bytes);
638 while (num_bytes > 0) {
639
640 /* Write as much samples as possible */
641 framecount = num_bytes / bytes_per_sample / track.num_channels;
642
643 /* Report current state state */
644 state = snd_pcm_state(alsa_id->alsa_pcm);
645 // MSG("PCM state before writei: %s",
646 // snd_pcm_state_name(state));
647
648 /* MSG("snd_pcm_writei() called") */
649 ret =
650 snd_pcm_writei(alsa_id->alsa_pcm, output_samples,
651 framecount);
652 if (ret >= 0)
653 MSG(5, "Sent %d of %d remaining bytes", ret*bytes_per_sample*track.num_channels, num_bytes);
654
655 if (ret == -EAGAIN) {
656 MSG(4, "Warning: Forced wait!");
657 snd_pcm_wait(alsa_id->alsa_pcm, 100);
658 } else if (ret == -EPIPE) {
659 MSG(4, "Warning: returned EPIPE!");
660 if (xrun(alsa_id) != 0)
661 ERROR_EXIT();
662 #ifdef ESTRPIPE
663 } else if (ret == -ESTRPIPE) {
664 MSG(4, "Warning: returned ESTRPIPE!");
665 if (suspend(alsa_id) != 0)
666 ERROR_EXIT();
667 #endif
668 } else if (ret == -EBUSY) {
669 MSG(4, "WARNING: sleeping while PCM BUSY");
670 usleep(100);
671 continue;
672 } else if (ret < 0) {
673 ERR("Write to audio interface failed (%s)",
674 snd_strerror(ret));
675 ERROR_EXIT();
676 }
677
678 if (ret > 0) {
679 /* Update counter of bytes left and move the data pointer */
680 num_bytes -=
681 ret * bytes_per_sample * track.num_channels;
682 output_samples +=
683 ret * bytes_per_sample * track.num_channels / 2;
684 }
685
686 /* Report current state */
687 state = snd_pcm_state(alsa_id->alsa_pcm);
688 // MSG("PCM state before polling: %s",
689 // snd_pcm_state_name(state));
690
691 err =
692 wait_for_poll(alsa_id, alsa_id->alsa_poll_fds,
693 alsa_id->alsa_fd_count, 0);
694 if (err < 0) {
695 ERR("Wait for poll() failed\n");
696 ERROR_EXIT();
697 } else if (err == 1) {
698 MSG(4, "Playback stopped");
699
700 /* Drop the playback on the sound device (probably
701 still in progress up till now) */
702 err = snd_pcm_drop(alsa_id->alsa_pcm);
703 if (err < 0) {
704 ERR("snd_pcm_drop() failed: %s",
705 snd_strerror(err));
706 return -1;
707 }
708
709 /* Terminating (successfully or after a stop) */
710 goto terminate;
711 }
712
713 if (num_bytes <= 0)
714 break;
715 // MSG("ALSA ready for more samples");
716
717 /* Stop requests can be issued again */
718 }
719
720 terminate:
721 if (track_volume.samples != NULL)
722 g_free(track_volume.samples);
723
724 return 0;
725 }
726
727 /* Drain ALSA playback until only `left' samples are left in the buffer */
alsa_drain_left(AudioID * id,snd_pcm_uframes_t left)728 static int alsa_drain_left(AudioID * id, snd_pcm_uframes_t left)
729 {
730 spd_alsa_id_t *alsa_id = (spd_alsa_id_t *) id;
731
732 int err;
733
734 MSG(4, "Draining until %lu frames left...", (unsigned long) left);
735
736 /* We want to get next "device ready" notification only after the buffer
737 is already empty */
738 err =
739 snd_pcm_sw_params_set_avail_min(alsa_id->alsa_pcm,
740 alsa_id->alsa_sw_params,
741 alsa_id->alsa_buffer_size - left);
742 if (err < 0) {
743 ERR("Unable to set avail min for playback: %s\n",
744 snd_strerror(err));
745 return err;
746 }
747 /* write the parameters to the playback device */
748 err = snd_pcm_sw_params(alsa_id->alsa_pcm, alsa_id->alsa_sw_params);
749 if (err < 0) {
750 ERR("Unable to set sw params for playback: %s\n",
751 snd_strerror(err));
752 return -1;
753 }
754
755 err =
756 wait_for_poll(alsa_id, alsa_id->alsa_poll_fds,
757 alsa_id->alsa_fd_count, 1);
758 if (err < 0) {
759 ERR("Wait for poll() failed\n");
760 return -1;
761 } else if (err == 1) {
762 MSG(4, "Playback stopped while draining");
763
764 /* Drop the playback on the sound device (probably
765 still in progress up till now) */
766 err = snd_pcm_drop(alsa_id->alsa_pcm);
767 if (err < 0) {
768 ERR("snd_pcm_drop() failed: %s", snd_strerror(err));
769 return -1;
770 }
771 }
772
773 /* When ALSA is going through Pulseaudio, wait_for_poll returns too
774 early because the file descriptor is always availble for writing
775 :/ */
776 while (!alsa_id->stop_requested)
777 {
778 snd_pcm_sframes_t frames;
779 snd_pcm_state_t state;
780 struct timeval tv;
781 struct timespec ts;
782
783 /* Poll server */
784 frames = snd_pcm_avail(alsa_id->alsa_pcm);
785 if (frames < 0) {
786 MSG(4, "Drain: Buffer clear");
787 break;
788 }
789
790 MSG(5, "Drain: %lu frames left in buffer",
791 (unsigned long) alsa_id->alsa_buffer_size - frames);
792 if (alsa_id->alsa_buffer_size - frames <= left) {
793 MSG(4, "Drain: Buffer clear enough");
794 break;
795 }
796
797 state = snd_pcm_state(alsa_id->alsa_pcm);
798 if (err != 0) {
799 MSG(4, "Drain: Status error %d", err);
800 break;
801 }
802 if (state == SND_PCM_STATE_XRUN) {
803 MSG(4, "Drain: Playback terminated");
804 break;
805 }
806
807 /* Poll every 10ms */
808 gettimeofday(&tv, NULL);
809 ts.tv_sec = tv.tv_sec;
810 ts.tv_nsec = tv.tv_usec * 1000 + 10000000;
811 if (ts.tv_nsec >= 1000000000) {
812 ts.tv_sec += 1;
813 ts.tv_nsec -= 1000000000;
814 }
815
816 pthread_mutex_lock(&alsa_id->alsa_pipe_mutex);
817 if (!alsa_id->stop_requested)
818 pthread_cond_timedwait(&alsa_id->alsa_pipe_cond,
819 &alsa_id->alsa_pipe_mutex, &ts);
820 pthread_mutex_unlock(&alsa_id->alsa_pipe_mutex);
821 }
822
823 MSG(4, "Draining terminated");
824
825 return 0;
826 }
827
828 /* Drain until the amount of samples left in the buffer is big enough to make
829 sure we will have time to push the rest of the audio */
alsa_drain_overlap(AudioID * id,AudioTrack track)830 static int alsa_drain_overlap(AudioID * id, AudioTrack track)
831 {
832 /* We typically want 20ms overlap: usually about a period size, and
833 small enough to be unnoticeable */
834 unsigned min_ms = 20;
835
836 spd_alsa_id_t *alsa_id = (spd_alsa_id_t *) id;
837 snd_pcm_uframes_t min;
838 snd_pcm_uframes_t period_size;
839 snd_pcm_uframes_t min2;
840 snd_pcm_uframes_t left;
841
842 min = (min_ms * track.sample_rate) / 1000;
843
844 /* Get period size. */
845 snd_pcm_hw_params_get_period_size(alsa_id->alsa_hw_params, &period_size,
846 0);
847
848 /* Round minimum to two period size */
849 if (2*period_size >= min)
850 min2 = 2*period_size;
851 else
852 min2 = (min + period_size - 1) / period_size;
853
854 /* Usually the buffer size will be far enough */
855 if (alsa_id->alsa_buffer_size >= min2)
856 left = min2;
857 else
858 /* That's very odd. Just wait for some room to be available */
859 left = alsa_id->alsa_buffer_size - 1;
860
861 MSG(4, "Draining with at least %ums left, i.e. %lu frames, with period %lu frames, thus %lu frames, i.e. %lu left of %lu",
862 min_ms, (unsigned long) min, (unsigned long) period_size,
863 (unsigned long) min2, (unsigned long) left, (unsigned long)
864 alsa_id->alsa_buffer_size);
865
866 return alsa_drain_left(id, left);
867 }
868
alsa_drain(AudioID * id)869 static int alsa_drain(AudioID * id)
870 {
871 return alsa_drain_left(id, 0);
872 }
873
alsa_feed_sync(AudioID * id,AudioTrack track)874 static int alsa_feed_sync(AudioID * id, AudioTrack track)
875 {
876 int ret;
877
878 ret = alsa_feed(id, track);
879 if (ret)
880 return ret;
881
882 return alsa_drain(id);
883 }
884
alsa_feed_sync_overlap(AudioID * id,AudioTrack track)885 static int alsa_feed_sync_overlap(AudioID * id, AudioTrack track)
886 {
887 int ret;
888
889 ret = alsa_feed(id, track);
890 if (ret)
891 return ret;
892
893 return alsa_drain_overlap(id, track);
894 }
895
alsa_end(AudioID * id)896 static int alsa_end(AudioID * id)
897 {
898 spd_alsa_id_t *alsa_id = (spd_alsa_id_t *) id;
899 int err;
900
901 if (!alsa_id->stop_requested)
902 alsa_drain(id);
903
904 err = snd_pcm_drop(alsa_id->alsa_pcm);
905 if (err < 0) {
906 ERR("snd_pcm_drop() failed: %s", snd_strerror(err));
907 return -1;
908 }
909
910 MSG(2, "Freeing HW parameters");
911 snd_pcm_hw_params_free(alsa_id->alsa_hw_params);
912
913 pthread_mutex_lock(&alsa_id->alsa_pipe_mutex);
914 alsa_id->alsa_opened = 0;
915 close(alsa_id->alsa_stop_pipe[0]);
916 close(alsa_id->alsa_stop_pipe[1]);
917
918 g_free(alsa_id->alsa_poll_fds);
919 pthread_mutex_unlock(&alsa_id->alsa_pipe_mutex);
920
921 MSG(1, "End of playback on ALSA");
922
923 return 0;
924 }
925
926 /* Play the track _track_ (see spd_audio.h) using the id->alsa_pcm device and
927 id-hw_params parameters. This is a blocking function, however, it's possible
928 to interrupt playing from a different thread with alsa_stop(). alsa_play
929 returns after and immediatelly after the whole sound was played on the
930 speakers.
931
932 The idea is that we get the ALSA file descriptors and we will poll() to see
933 when alsa is ready for more input while sleeping in the meantime. We will
934 additionally poll() for one more descriptor used by alsa_stop() to notify the
935 thread with alsa_play() that the stop of the playback is requested. The
936 variable can_be_stopped is used for very simple synchronization between the
937 two threads. */
alsa_play(AudioID * id,AudioTrack track)938 static int alsa_play(AudioID * id, AudioTrack track)
939 {
940 int ret;
941
942 ret = alsa_begin(id, track);
943 if (ret)
944 return ret;
945
946 ret = alsa_feed_sync(id, track);
947 if (ret)
948 return ret;
949
950 return alsa_end(id);
951 }
952
953 #undef ERROR_EXIT
954
955 /*
956 Stop the playback on the device and interrupt alsa_play()
957 */
alsa_stop(AudioID * id)958 static int alsa_stop(AudioID * id)
959 {
960 char buf;
961 int ret;
962 spd_alsa_id_t *alsa_id = (spd_alsa_id_t *) id;
963
964 MSG(1, "STOP!");
965
966 if (alsa_id == NULL)
967 return 0;
968
969 pthread_mutex_lock(&alsa_id->alsa_pipe_mutex);
970 if (alsa_id->alsa_opened) {
971 alsa_id->stop_requested = 1;
972
973 /* This constant is arbitrary */
974 buf = 42;
975
976 ret = write(alsa_id->alsa_stop_pipe[1], &buf, 1);
977 if (ret <= 0) {
978 ERR("Can't write stop request to pipe, err %d: %s",
979 errno, strerror(errno));
980 }
981 pthread_cond_broadcast(&alsa_id->alsa_pipe_cond);
982 }
983 pthread_mutex_unlock(&alsa_id->alsa_pipe_mutex);
984
985 return 0;
986 }
987
988 /*
989 Set volume
990
991 Comments: It's not possible to set individual track volume with Alsa, so we
992 handle volume in alsa_play() by multiplication of each sample.
993 */
alsa_set_volume(AudioID * id,int volume)994 static int alsa_set_volume(AudioID * id, int volume)
995 {
996 return 0;
997 }
998
alsa_set_loglevel(int level)999 static void alsa_set_loglevel(int level)
1000 {
1001 if (level) {
1002 alsa_log_level = level;
1003 }
1004 }
1005
alsa_get_playcmd(void)1006 static char const *alsa_get_playcmd(void)
1007 {
1008 return alsa_play_cmd;
1009 }
1010
1011 /* Provide the Alsa backend. */
1012 static spd_audio_plugin_t alsa_functions = {
1013 "alsa",
1014 alsa_open,
1015 alsa_play,
1016 alsa_stop,
1017 alsa_close,
1018 alsa_set_volume,
1019 alsa_set_loglevel,
1020 alsa_get_playcmd,
1021 alsa_begin,
1022 alsa_feed_sync,
1023 alsa_feed_sync_overlap,
1024 alsa_end,
1025 };
1026
alsa_plugin_get(void)1027 spd_audio_plugin_t *alsa_plugin_get(void)
1028 {
1029 return &alsa_functions;
1030 }
1031
1032 spd_audio_plugin_t *SPD_AUDIO_PLUGIN_ENTRY(void)
1033 __attribute__ ((weak, alias("alsa_plugin_get")));
1034 #undef MSG
1035 #undef ERR
1036