1 /* -*- c-file-style: "gnu" -*-
2 TiMidity++ -- MIDI to WAVE converter and player
3 Copyright (C) 1999-2002 Masanao Izumo <mo@goice.co.jp>
4 Copyright (C) 1995 Tuukka Toivonen <tt@cgs.fi>
5 ALSA 0.[56] support by Katsuhiro Ueno <katsu@blue.sky.or.jp>
6 rewritten by Takashi Iwai <tiwai@suse.de>
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program 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
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
22 alsa_a.c
23
24 Functions to play sound on the ALSA audio driver
25
26 */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif /* HAVE_CONFIG_H */
31 #define _GNU_SOURCE
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <fcntl.h>
36
37 #ifndef NO_STRING_H
38 #include <string.h>
39 #else
40 #include <strings.h>
41 #endif
42
43 /*ALSA header file*/
44 #if HAVE_ALSA_ASOUNDLIB_H
45 #define ALSA_PCM_OLD_HW_PARAMS_API
46 #define ALSA_PCM_OLD_SW_PARAMS_API
47 #include <alsa/asoundlib.h>
48 #else
49 #include <sys/asoundlib.h>
50 #endif
51
52 #if SND_LIB_MAJOR > 0
53 #define ALSA_LIB 9
54 #elif defined(SND_LIB_MINOR)
55 #define ALSA_LIB SND_LIB_MINOR
56 #else
57 #define ALSA_LIB 3
58 #endif
59
60 #if ALSA_LIB < 4
61 typedef void snd_pcm_t;
62 #endif
63
64 #include "timidity.h"
65 #include "common.h"
66 #include "output.h"
67 #include "controls.h"
68 #include "timer.h"
69 #include "instrum.h"
70 #include "playmidi.h"
71 #include "miditrace.h"
72
73 static int open_output(void); /* 0=success, 1=warning, -1=fatal error */
74 static void close_output(void);
75 static int output_data(char *buf, int32 nbytes);
76 static int acntl(int request, void *arg);
77 #if ALSA_LIB >= 5
78 static int detect(void);
79 #endif
80
81 /* export the playback mode */
82
83 #define dpm alsa_play_mode
84
85 PlayMode dpm = {
86 DEFAULT_RATE, PE_16BIT|PE_SIGNED, PF_PCM_STREAM|PF_CAN_TRACE|PF_BUFF_FRAGM_OPT,
87 -1,
88 {0}, /* default: get all the buffer fragments you can */
89 "ALSA pcm device", 's',
90 "", /* here leave it empty so that the pcm device name can be given
91 * via command line option.
92 */
93 open_output,
94 close_output,
95 output_data,
96 acntl,
97 #if ALSA_LIB >= 5
98 detect
99 #endif
100 };
101
102 /*************************************************************************/
103 /* We currently only honor the PE_MONO bit, the sample rate, and the
104 number of buffer fragments. We try 16-bit signed data first, and
105 then 8-bit unsigned if it fails. If you have a sound device that
106 can't handle either, let me know. */
107
108
109 /*ALSA PCM handler*/
110 static snd_pcm_t* handle = NULL;
111 #if ALSA_LIB <= 5
112 static int card = 0;
113 static int device = 0;
114 #endif
115 static int total_bytes = -1;
116 static int frag_size = 0;
117 static int sample_shift = 0;
118 static int output_counter;
119
120 #if ALSA_LIB > 5
alsa_device_name(void)121 static char *alsa_device_name(void)
122 {
123 if (dpm.name && *dpm.name)
124 return dpm.name;
125 else
126 return "alsa pcm";
127 }
128 #else
alsa_device_name(void)129 static char *alsa_device_name(void)
130 {
131 static char name[32];
132 sprintf(name, "card%d/device%d", card, device);
133 return name;
134 }
135 #endif
136
error_report(int snd_error)137 static void error_report (int snd_error)
138 {
139 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s",
140 alsa_device_name(), snd_strerror (snd_error));
141 }
142
143
144 #if ALSA_LIB < 6
145 /*return value == 0 sucess
146 == -1 fails
147 */
check_sound_cards(int * card__,int * device__,const int32 extra_param[5])148 static int check_sound_cards (int* card__, int* device__,
149 const int32 extra_param[5])
150 {
151 /*Search sound cards*/
152 struct snd_ctl_hw_info ctl_hw_info;
153 snd_pcm_info_t pcm_info;
154 snd_ctl_t* ctl_handle;
155 const char* env_sound_card = getenv ("TIMIDITY_SOUND_CARD");
156 const char* env_pcm_device = getenv ("TIMIDITY_PCM_DEVICE");
157 int tmp;
158
159 /*specify card*/
160 *card__ = 0;
161 if (env_sound_card != NULL)
162 *card__ = atoi (env_sound_card);
163 /*specify device*/
164 *device__ = 0;
165 if (env_pcm_device != NULL)
166 *device__ = atoi (env_pcm_device);
167
168 tmp = snd_cards ();
169 if (tmp == 0)
170 {
171 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "No sound card found.");
172 return -1;
173 }
174 if (tmp < 0)
175 {
176 error_report (tmp);
177 return -1;
178 }
179
180 if (*card__ < 0 || *card__ >= tmp)
181 {
182 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "There is %d sound cards."
183 " %d is invalid sound card. assuming 0.",
184 tmp, *card__);
185 *card__ = 0;
186 }
187
188 tmp = snd_ctl_open (&ctl_handle, *card__);
189 if (tmp < 0)
190 {
191 error_report (tmp);
192 return -1;
193 }
194
195 /*check whether sound card has pcm device(s)*/
196 tmp = snd_ctl_hw_info (ctl_handle, & ctl_hw_info);
197 if (ctl_hw_info.pcmdevs == 0)
198 {
199 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
200 "%d-th sound card(%s) has no pcm device",
201 ctl_hw_info.longname, *card__);
202 snd_ctl_close (ctl_handle);
203 return -1;
204 }
205
206 if (*device__ < 0 || *device__ >= ctl_hw_info.pcmdevs)
207 {
208 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
209 "%d-th sound cards(%s) has %d pcm device(s)."
210 " %d is invalid pcm device. assuming 0.",
211 *card__, ctl_hw_info.longname, ctl_hw_info.pcmdevs, *device__);
212 *device__ = 0;
213
214 if (ctl_hw_info.pcmdevs == 0)
215 {/*sound card has no pcm devices*/
216 snd_ctl_close (ctl_handle);
217 return -1;
218 }
219 }
220
221 /*check whether pcm device is able to playback*/
222 tmp = snd_ctl_pcm_info(ctl_handle, *device__, &pcm_info);
223 if (tmp < 0)
224 {
225 error_report (tmp);
226 snd_ctl_close (ctl_handle);
227 return -1;
228 }
229
230 if ((pcm_info.flags & SND_PCM_INFO_PLAYBACK) == 0)
231 {
232 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
233 "%d-th sound cards(%s), device=%d, "
234 "type=%d, flags=%d, id=%s, name=%s,"
235 " does not support playback",
236 *card__, ctl_hw_info.longname, ctl_hw_info.pcmdevs,
237 pcm_info.type, pcm_info.flags, pcm_info.id, pcm_info.name);
238 snd_ctl_close (ctl_handle);
239 return -1;
240 }
241
242 tmp = snd_ctl_close (ctl_handle);
243 if (tmp < 0)
244 {
245 error_report (tmp);
246 return -1;
247 }
248
249 return 0;
250 }
251 #endif
252
253
254 #if ALSA_LIB > 5
255 /*================================================================
256 * ALSA API version 0.9.x
257 *================================================================*/
258
get_pcm_name(void)259 static char *get_pcm_name(void)
260 {
261 char *name;
262 if (dpm.name && *dpm.name)
263 return dpm.name;
264 name = getenv("TIMIDITY_PCM_NAME");
265 if (! name || ! *name)
266 name = "default";
267 return name;
268 }
269
error_handle(const char * file,int line,const char * func,int err,const char * fmt,...)270 static void error_handle(const char *file, int line, const char *func, int err, const char *fmt, ...)
271 {
272 }
273
detect(void)274 static int detect(void)
275 {
276 snd_pcm_t *pcm;
277 snd_lib_error_set_handler(error_handle);
278 if (snd_pcm_open(&pcm, get_pcm_name(), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK) < 0)
279 return 0;
280 snd_pcm_close(pcm);
281 return 1; /* found */
282 }
283
284 /*return value == 0 sucess
285 == 1 warning
286 == -1 fails
287 */
open_output(void)288 static int open_output(void)
289 {
290 int orig_rate = dpm.rate;
291 int ret_val = 0;
292 int tmp, frags, r, pfds;
293 int rate;
294 snd_pcm_hw_params_t *pinfo;
295 snd_pcm_sw_params_t *swpinfo;
296
297 dpm.name = get_pcm_name();
298 snd_lib_error_set_handler(NULL);
299 tmp = snd_pcm_open(&handle, dpm.name, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); /* avoid blocking by open */
300 if (tmp < 0) {
301 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "Can't open pcm device '%s'.", dpm.name);
302 return -1;
303 }
304 snd_pcm_nonblock(handle, 0); /* set back to blocking mode */
305
306 snd_pcm_hw_params_alloca(&pinfo);
307 snd_pcm_sw_params_alloca(&swpinfo);
308
309 if (snd_pcm_hw_params_any(handle, pinfo) < 0) {
310 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
311 "ALSA pcm '%s' can't initialize hw_params",
312 alsa_device_name());
313 snd_pcm_close(handle);
314 return -1;
315 }
316
317 #ifdef LITTLE_ENDIAN
318 #define S16_FORMAT SND_PCM_FORMAT_S16_LE
319 #define U16_FORMAT SND_PCM_FORMAT_U16_LE
320 #else
321 #define S16_FORMAT SND_PCM_FORMAT_S16_BE
322 #define U16_FORMAT SND_PCM_FORMAT_U16_LE
323 #endif
324
325 dpm.encoding &= ~(PE_ULAW|PE_ALAW|PE_BYTESWAP);
326 /*check sample bit*/
327 if (snd_pcm_hw_params_test_format(handle, pinfo, S16_FORMAT) < 0 &&
328 snd_pcm_hw_params_test_format(handle, pinfo, U16_FORMAT) < 0)
329 dpm.encoding &= ~PE_16BIT; /*force 8bit samples*/
330 if (snd_pcm_hw_params_test_format(handle, pinfo, SND_PCM_FORMAT_U8) < 0 &&
331 snd_pcm_hw_params_test_format(handle, pinfo, SND_PCM_FORMAT_S8) < 0)
332 dpm.encoding |= PE_16BIT; /*force 16bit samples*/
333
334 /*check format*/
335 if (dpm.encoding & PE_16BIT) {
336 /*16bit*/
337 if (snd_pcm_hw_params_set_format(handle, pinfo, S16_FORMAT) == 0)
338 dpm.encoding |= PE_SIGNED;
339 else if (snd_pcm_hw_params_set_format(handle, pinfo, U16_FORMAT) == 0)
340 dpm.encoding &= ~PE_SIGNED;
341 else {
342 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
343 "ALSA pcm '%s' doesn't support 16 bit sample width",
344 alsa_device_name());
345 snd_pcm_close(handle);
346 return -1;
347 }
348 } else {
349 /*8bit*/
350 if (snd_pcm_hw_params_set_format(handle, pinfo, SND_PCM_FORMAT_U8) == 0)
351 dpm.encoding &= ~PE_SIGNED;
352 else if (snd_pcm_hw_params_set_format(handle, pinfo, SND_PCM_FORMAT_S8) == 0)
353 dpm.encoding |= PE_SIGNED;
354 else {
355 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
356 "ALSA pcm '%s' doesn't support 8 bit sample width",
357 alsa_device_name());
358 snd_pcm_close(handle);
359 return -1;
360 }
361 }
362
363 if (snd_pcm_hw_params_set_access(handle, pinfo,
364 SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
365 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
366 "ALSA pcm '%s' doesn't support interleaved data",
367 alsa_device_name());
368 snd_pcm_close(handle);
369 return -1;
370 }
371
372 /*check rate*/
373 r = snd_pcm_hw_params_get_rate_min(pinfo, NULL);
374 if (r >= 0 && r > dpm.rate) {
375 dpm.rate = r;
376 ret_val = 1;
377 }
378 r = snd_pcm_hw_params_get_rate_max(pinfo, NULL);
379 if (r >= 0 && r < dpm.rate) {
380 dpm.rate = r;
381 ret_val = 1;
382 }
383 if ((rate = snd_pcm_hw_params_set_rate_near(handle, pinfo, dpm.rate, 0)) < 0) {
384 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
385 "ALSA pcm '%s' can't set rate %d",
386 alsa_device_name(), dpm.rate);
387 snd_pcm_close(handle);
388 return -1;
389 }
390
391 /*check channels*/
392 if (dpm.encoding & PE_MONO) {
393 if (snd_pcm_hw_params_test_channels(handle, pinfo, 1) < 0)
394 dpm.encoding &= ~PE_MONO;
395 } else {
396 if (snd_pcm_hw_params_test_channels(handle, pinfo, 2) < 0)
397 dpm.encoding |= PE_MONO;
398 }
399
400 if (dpm.encoding & PE_MONO) {
401 if (snd_pcm_hw_params_set_channels(handle, pinfo, 1) < 0) {
402 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
403 "ALSA pcm '%s' can't set mono channel",
404 alsa_device_name());
405 snd_pcm_close(handle);
406 return -1;
407 }
408 } else {
409 if (snd_pcm_hw_params_set_channels(handle, pinfo, 2) < 0) {
410 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
411 "ALSA pcm '%s' can't set stereo channels",
412 alsa_device_name());
413 snd_pcm_close(handle);
414 return -1;
415 }
416 }
417
418 sample_shift = 0;
419 if (!(dpm.encoding & PE_MONO))
420 sample_shift++;
421 if (dpm.encoding & PE_16BIT)
422 sample_shift++;
423
424 /* Set buffer fragment size (in extra_param[1]) */
425 if (dpm.extra_param[1] != 0)
426 frag_size = dpm.extra_param[1];
427 else
428 frag_size = audio_buffer_size << sample_shift;
429
430 /* Set buffer fragments (in extra_param[0]) */
431 if (dpm.extra_param[0] == 0)
432 frags = 4;
433 else
434 frags = dpm.extra_param[0];
435
436 total_bytes = frag_size * frags;
437 ctl->cmsg(CMSG_INFO, VERB_VERBOSE,
438 "Requested buffer size %d, fragment size %d",
439 total_bytes, frag_size);
440 if ((tmp = snd_pcm_hw_params_set_buffer_size_near(handle, pinfo, total_bytes >> sample_shift)) < 0) {
441 ctl->cmsg(CMSG_WARNING, VERB_NORMAL,
442 "ALSA pcm '%s' can't set buffer size %d",
443 alsa_device_name(), total_bytes);
444 snd_pcm_close(handle);
445 return -1;
446 }
447
448 if ((tmp = snd_pcm_hw_params_set_period_size_near(handle, pinfo, frag_size >> sample_shift, 0)) < 0) {
449 ctl->cmsg(CMSG_WARNING, VERB_NORMAL,
450 "ALSA pcm '%s' can't set period size %d",
451 alsa_device_name(), frag_size);
452 snd_pcm_close(handle);
453 return -1;
454 }
455
456 if (snd_pcm_hw_params(handle, pinfo) < 0) {
457 snd_output_t *log;
458 ctl->cmsg(CMSG_WARNING, VERB_NORMAL,
459 "ALSA pcm '%s' can't set hw_params", alsa_device_name());
460 snd_output_stdio_attach(&log, stderr, 0);
461 snd_pcm_hw_params_dump(pinfo, log);
462 snd_pcm_close(handle);
463 return -1;
464 }
465
466 total_bytes = snd_pcm_hw_params_get_buffer_size(pinfo) << sample_shift;
467 frag_size = snd_pcm_hw_params_get_period_size(pinfo, NULL) << sample_shift;
468 ctl->cmsg(CMSG_INFO, VERB_VERBOSE,
469 "ALSA pcm '%s' set buffer size %d, period size %d bytes",
470 alsa_device_name(), total_bytes, frag_size);
471 tmp = snd_pcm_hw_params_get_rate(pinfo, NULL);
472 if (tmp > 0 && tmp != dpm.rate) {
473 dpm.rate = tmp;
474 ret_val = 1;
475 }
476 if (orig_rate != dpm.rate) {
477 ctl->cmsg(CMSG_WARNING, VERB_VERBOSE,
478 "Output rate adjusted to %d Hz (requested %d Hz)",
479 dpm.rate, orig_rate);
480 }
481 snd_pcm_sw_params_current(handle, swpinfo);
482 snd_pcm_sw_params_set_start_threshold(handle, swpinfo, total_bytes >> sample_shift);
483 snd_pcm_sw_params_set_stop_threshold(handle, swpinfo, total_bytes >> sample_shift);
484
485 tmp = snd_pcm_prepare(handle);
486 if (tmp < 0) {
487 ctl->cmsg(CMSG_WARNING, VERB_NORMAL,
488 "unable to prepare channel\n");
489 snd_pcm_close(handle);
490 return -1;
491 }
492
493 pfds = snd_pcm_poll_descriptors_count(handle);
494 if (pfds > 1) {
495 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "too many poll descriptors: %s",
496 alsa_device_name());
497 close_output ();
498 return -1;
499 } else if (pfds == 1) {
500 struct pollfd pfd;
501 if (snd_pcm_poll_descriptors(handle, &pfd, 1) >= 0)
502 dpm.fd = pfd.fd;
503 else
504 dpm.fd = -1;
505 } else
506 dpm.fd = -1;
507
508 output_counter = 0;
509
510 return ret_val;
511 }
512
close_output(void)513 static void close_output(void)
514 {
515 if (handle) {
516 int ret = snd_pcm_close (handle);
517 if (ret < 0)
518 error_report (ret);
519 handle = NULL;
520 }
521
522 dpm.fd = -1;
523 }
524
output_data(char * buf,int32 nbytes)525 static int output_data(char *buf, int32 nbytes)
526 {
527 int n;
528 int nframes, shift;
529
530 if (! handle)
531 return -1;
532
533 nframes = nbytes;
534 shift = 0;
535 if (!(dpm.encoding & PE_MONO))
536 shift++;
537 if (dpm.encoding & PE_16BIT)
538 shift++;
539 nframes >>= shift;
540
541 while (nframes > 0) {
542 n = snd_pcm_writei(handle, buf, nframes);
543 if (n == -EAGAIN || (n >= 0 && n < nframes)) {
544 snd_pcm_wait(handle, 1000);
545 } else if (n == -EPIPE) {
546 snd_pcm_status_t *status;
547 snd_pcm_status_alloca(&status);
548 if (snd_pcm_status(handle, status) < 0) {
549 ctl->cmsg(CMSG_WARNING, VERB_DEBUG, "%s: cannot get status", alsa_device_name());
550 return -1;
551 }
552 ctl->cmsg(CMSG_INFO, VERB_DEBUG,
553 "%s: underrun at %ld", alsa_device_name(), output_counter << sample_shift);
554 snd_pcm_prepare(handle);
555 } else if (n < 0) {
556 ctl->cmsg(CMSG_WARNING, VERB_DEBUG,
557 "%s: %s", alsa_device_name(),
558 (n < 0) ? snd_strerror(n) : "write error");
559 return -1;
560 }
561 if (n > 0) {
562 nframes -= n;
563 buf += n << shift;
564 output_counter += n;
565 }
566 }
567
568 return 0;
569 }
570
acntl(int request,void * arg)571 static int acntl(int request, void *arg)
572 {
573 snd_pcm_status_t *status;
574 snd_pcm_sframes_t delay;
575
576 if (handle == NULL)
577 return -1;
578
579 switch (request) {
580 case PM_REQ_GETFRAGSIZ:
581 if (frag_size == 0)
582 return -1;
583 *((int *)arg) = frag_size;
584 return 0;
585
586 case PM_REQ_GETQSIZ:
587 if (total_bytes == -1)
588 return -1;
589 *((int *)arg) = total_bytes;
590 return 0;
591
592 case PM_REQ_GETFILLABLE:
593 if (total_bytes == -1)
594 return -1;
595 snd_pcm_status_alloca(&status);
596 if (snd_pcm_status(handle, status) < 0)
597 return -1;
598 *((int *)arg) = snd_pcm_status_get_avail(status);
599 return 0;
600
601 case PM_REQ_GETFILLED:
602 if (total_bytes == -1)
603 return -1;
604 if (snd_pcm_delay(handle, &delay) < 0)
605 return -1;
606 *((int *)arg) = delay;
607 return 0;
608
609 case PM_REQ_GETSAMPLES:
610 if (total_bytes == -1)
611 return -1;
612 if (snd_pcm_delay(handle, &delay) < 0)
613 return -1;
614 *((int *)arg) = output_counter - delay;
615 return 0;
616
617 case PM_REQ_DISCARD:
618 if (snd_pcm_drop(handle) < 0)
619 return -1;
620 if (snd_pcm_prepare(handle) < 0)
621 return -1;
622 output_counter = 0;
623 return 0;
624
625 case PM_REQ_FLUSH:
626 if (snd_pcm_drain(handle) < 0)
627 return -1;
628 if (snd_pcm_prepare(handle) < 0)
629 return -1;
630 output_counter = 0;
631 return 0;
632
633 case PM_REQ_PLAY_START: /* Called just before playing */
634 case PM_REQ_PLAY_END: /* Called just after playing */
635 return 0;
636 }
637 return -1;
638 }
639
640
641 /* end ALSA API 0.9.x */
642
643
644 #elif ALSA_LIB == 5
645
646 /*================================================================
647 * ALSA API version 0.5.x
648 *================================================================*/
649
650 /*return value == 0 sucess
651 == 1 warning
652 == -1 fails
653 */
set_playback_info(snd_pcm_t * handle__,int32 * encoding__,int32 * rate__,const int32 extra_param[5])654 static int set_playback_info (snd_pcm_t* handle__,
655 int32* encoding__, int32* rate__,
656 const int32 extra_param[5])
657 {
658 int ret_val = 0;
659 const int32 orig_rate = *rate__;
660 int tmp;
661 snd_pcm_channel_info_t pinfo;
662 snd_pcm_channel_params_t pparams;
663 snd_pcm_channel_setup_t psetup;
664
665 memset (&pinfo, 0, sizeof (pinfo));
666 memset (&pparams, 0, sizeof (pparams));
667 pinfo.channel = SND_PCM_CHANNEL_PLAYBACK;
668 tmp = snd_pcm_channel_info (handle__, &pinfo);
669 if (tmp < 0)
670 {
671 error_report (tmp);
672 return -1;
673 }
674
675 /*check sample bit*/
676 if (!(pinfo.formats & ~(SND_PCM_FMT_S8 | SND_PCM_FMT_U8)))
677 *encoding__ &= ~PE_16BIT; /*force 8bit samples*/
678 if (!(pinfo.formats & ~(SND_PCM_FMT_S16 | SND_PCM_FMT_U16)))
679 *encoding__ |= PE_16BIT; /*force 16bit samples*/
680
681 /*check rate*/
682 if (pinfo.min_rate > *rate__)
683 *rate__ = pinfo.min_rate;
684 if (pinfo.max_rate < *rate__)
685 *rate__ = pinfo.max_rate;
686 pparams.format.rate = *rate__;
687
688 /*check channels*/
689 if ((*encoding__ & PE_MONO) != 0 && pinfo.min_voices > 1)
690 *encoding__ &= ~PE_MONO;
691 if ((*encoding__ & PE_MONO) == 0 && pinfo.max_voices < 2)
692 *encoding__ |= PE_MONO;
693
694 if ((*encoding__ & PE_MONO) != 0)
695 pparams.format.voices = 1; /*mono*/
696 else
697 pparams.format.voices = 2; /*stereo*/
698
699 /*check format*/
700 if ((*encoding__ & PE_16BIT) != 0)
701 { /*16bit*/
702 if ((pinfo.formats & SND_PCM_FMT_S16_LE) != 0)
703 {
704 pparams.format.format = SND_PCM_SFMT_S16_LE;
705 *encoding__ |= PE_SIGNED;
706 }
707 else if ((pinfo.formats & SND_PCM_FMT_U16_LE) != 0)
708 {
709 pparams.format.format = SND_PCM_SFMT_U16_LE;
710 *encoding__ &= ~PE_SIGNED;
711 }
712 else if ((pinfo.formats & SND_PCM_FMT_S16_BE) != 0)
713 {
714 pparams.format.format = SND_PCM_SFMT_S16_BE;
715 *encoding__ |= PE_SIGNED;
716 }
717 else if ((pinfo.formats & SND_PCM_FMT_U16_BE) != 0)
718 {
719 pparams.format.format = SND_PCM_SFMT_U16_BE;
720 *encoding__ &= ~PE_SIGNED;
721 }
722 else
723 {
724 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
725 "%s doesn't support 16 bit sample width",
726 alsa_device_name());
727 return -1;
728 }
729 }
730 else
731 { /*8bit*/
732 if ((pinfo.formats & SND_PCM_FMT_U8) != 0)
733 {
734 pparams.format.format = SND_PCM_SFMT_U8;
735 *encoding__ &= ~PE_SIGNED;
736 }
737 #if 0
738 else if ((pinfo.formats & SND_PCM_FMT_S8) != 0)
739 {
740 pcm_format.format = SND_PCM_SFMT_U16_LE;
741 *encoding__ |= PE_SIGNED;
742 }
743 #endif
744 else
745 {
746 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
747 "%s doesn't support 8 bit sample width",
748 alsa_device_name());
749 return -1;
750 }
751 }
752
753
754 sample_shift = 0;
755 if (!(dpm.encoding & PE_MONO))
756 sample_shift++;
757 if (dpm.encoding & PE_16BIT)
758 sample_shift++;
759
760 /* Set buffer fragment size (in extra_param[1]) */
761 if (extra_param[1] != 0)
762 tmp = extra_param[1];
763 else
764 tmp = audio_buffer_size << sample_shift;
765
766 /* Set buffer fragments (in extra_param[0]) */
767 pparams.buf.block.frag_size = tmp;
768 pparams.buf.block.frags_max = (extra_param[0] == 0) ? -1 : extra_param[0];
769 pparams.buf.block.frags_min = 1;
770 pparams.mode = SND_PCM_MODE_BLOCK;
771 pparams.channel = SND_PCM_CHANNEL_PLAYBACK;
772 pparams.start_mode = SND_PCM_START_DATA; /* .. should be START_FULL */
773 pparams.stop_mode = SND_PCM_STOP_STOP;
774 pparams.format.interleave = 1;
775 snd_pcm_channel_flush (handle__, SND_PCM_CHANNEL_PLAYBACK);
776 tmp = snd_pcm_channel_params (handle__, &pparams);
777 if (tmp < 0)
778 {
779 ctl->cmsg(CMSG_WARNING, VERB_NORMAL,
780 "%s doesn't support buffer fragments"
781 ":request size=%d, max=%d, min=%d\n",
782 alsa_device_name(),
783 pparams.buf.block.frag_size,
784 pparams.buf.block.frags_max,
785 pparams.buf.block.frags_min);
786 return -1;
787 }
788
789 tmp = snd_pcm_channel_prepare (handle__, SND_PCM_CHANNEL_PLAYBACK);
790 if (tmp < 0)
791 {
792 ctl->cmsg(CMSG_WARNING, VERB_NORMAL,
793 "unable to prepare channel\n");
794 return -1;
795 }
796
797 memset (&psetup, 0, sizeof(psetup));
798 psetup.channel = SND_PCM_CHANNEL_PLAYBACK;
799 tmp = snd_pcm_channel_setup (handle__, &psetup);
800 if (tmp == 0)
801 {
802 if(psetup.format.rate != orig_rate)
803 {
804 ctl->cmsg(CMSG_WARNING, VERB_VERBOSE,
805 "Output rate adjusted to %d Hz (requested %d Hz)",
806 psetup.format.rate, orig_rate);
807 dpm.rate = psetup.format.rate;
808 ret_val = 1;
809 }
810 frag_size = psetup.buf.block.frag_size;
811 total_bytes = frag_size * psetup.buf.block.frags;
812 }
813 else
814 {
815 frag_size = 0;
816 total_bytes = -1; /* snd_pcm_playback_status fails */
817 }
818
819 return ret_val;
820 }
821
822
detect(void)823 static int detect(void)
824 {
825 snd_pcm_t *pcm;
826 if (snd_pcm_open(&pcm, card, device, SND_PCM_OPEN_PLAYBACK | SND_PCM_OPEN_NONBLOCK) < 0)
827 return 0;
828 snd_pcm_close(pcm);
829 return 1; /* found */
830 }
831
open_output(void)832 static int open_output(void)
833 {
834 int tmp, warnings=0;
835 int ret;
836
837 tmp = check_sound_cards (&card, &device, dpm.extra_param);
838 if (tmp < 0)
839 return -1;
840
841 /* Open the audio device */
842 ret = snd_pcm_open (&handle, card, device, SND_PCM_OPEN_PLAYBACK | SND_PCM_OPEN_NONBLOCK);
843 if (ret < 0)
844 {
845 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s",
846 alsa_device_name(), snd_strerror (ret));
847 return -1;
848 }
849
850 snd_pcm_nonblock_mode(handle, 0); /* set back to blocking mode */
851 /* They can't mean these */
852 dpm.encoding &= ~(PE_ULAW|PE_ALAW|PE_BYTESWAP);
853 warnings = set_playback_info (handle, &dpm.encoding, &dpm.rate,
854 dpm.extra_param);
855 if (warnings < 0)
856 {
857 close_output ();
858 return -1;
859 }
860
861 dpm.fd = snd_pcm_file_descriptor (handle, SND_PCM_CHANNEL_PLAYBACK);
862 output_counter = 0;
863 return warnings;
864 }
865
close_output(void)866 static void close_output(void)
867 {
868 int ret;
869
870 if (handle == NULL)
871 return;
872
873 ret = snd_pcm_close (handle);
874 if (ret < 0 && ret != -EINVAL) /* Maybe alsa-driver 0.5 has a bug */
875 error_report (ret);
876 handle = NULL;
877
878 dpm.fd = -1;
879 }
880
output_data(char * buf,int32 nbytes)881 static int output_data(char *buf, int32 nbytes)
882 {
883 int n;
884 snd_pcm_channel_status_t status;
885
886 if (! handle)
887 return -1;
888 n = snd_pcm_write (handle, buf, nbytes);
889 if (n <= 0)
890 {
891 memset (&status, 0, sizeof(status));
892 status.channel = SND_PCM_CHANNEL_PLAYBACK;
893 if (snd_pcm_channel_status(handle, &status) < 0)
894 {
895 ctl->cmsg(CMSG_WARNING, VERB_DEBUG,
896 "%s: could not get channel status", alsa_device_name());
897 return -1;
898 }
899 if (status.status == SND_PCM_STATUS_UNDERRUN || n == -EPIPE)
900 {
901 ctl->cmsg(CMSG_INFO, VERB_DEBUG,
902 "%s: underrun at %d", alsa_device_name(), status.scount);
903 output_counter += status.scount;
904 snd_pcm_channel_flush (handle, SND_PCM_CHANNEL_PLAYBACK);
905 snd_pcm_channel_prepare (handle, SND_PCM_CHANNEL_PLAYBACK);
906 n = snd_pcm_write (handle, buf, nbytes);
907 }
908 if (n <= 0)
909 {
910 ctl->cmsg(CMSG_WARNING, VERB_DEBUG,
911 "%s: %s", alsa_device_name(),
912 (n < 0) ? snd_strerror(n) : "write error");
913 if (n != -EPIPE) /* buffer underrun is ignored */
914 return -1;
915 }
916 }
917 return 0;
918 }
919
920
acntl(int request,void * arg)921 static int acntl(int request, void *arg)
922 {
923 int i;
924 snd_pcm_channel_status_t pstatus;
925 memset (&pstatus, 0, sizeof (pstatus));
926 pstatus.channel = SND_PCM_CHANNEL_PLAYBACK;
927
928 if (handle == NULL)
929 return -1;
930
931 switch (request)
932 {
933 case PM_REQ_GETFRAGSIZ:
934 if (frag_size == 0)
935 return -1;
936 *((int *)arg) = frag_size;
937 return 0;
938
939 case PM_REQ_GETQSIZ:
940 if (total_bytes == -1)
941 return -1;
942 *((int *)arg) = total_bytes;
943 return 0;
944
945 case PM_REQ_GETFILLABLE:
946 if (total_bytes == -1)
947 return -1;
948 if (snd_pcm_channel_status(handle, &pstatus) < 0)
949 return -1;
950 i = pstatus.free >> sample_shift;
951 *((int *)arg) = i;
952 return 0;
953
954 case PM_REQ_GETFILLED:
955 if (total_bytes == -1)
956 return -1;
957 if (snd_pcm_channel_status(handle, &pstatus) < 0)
958 return -1;
959 i = pstatus.count >> sample_shift;
960 *((int *)arg) = i;
961 return 0;
962
963 case PM_REQ_GETSAMPLES:
964 if (total_bytes == -1)
965 return -1;
966 if (snd_pcm_channel_status(handle, &pstatus) < 0)
967 return -1;
968 i = (output_counter + pstatus.scount) >> sample_shift;
969 *((int *)arg) = i;
970 return 0;
971
972 case PM_REQ_DISCARD:
973 if (snd_pcm_playback_drain(handle) < 0)
974 return -1;
975 if (snd_pcm_channel_prepare(handle, SND_PCM_CHANNEL_PLAYBACK) < 0)
976 return -1;
977 output_counter = 0;
978 return 0;
979
980 case PM_REQ_FLUSH:
981 if (snd_pcm_channel_flush(handle, SND_PCM_CHANNEL_PLAYBACK) < 0)
982 return -1;
983 if (snd_pcm_channel_prepare(handle, SND_PCM_CHANNEL_PLAYBACK) < 0)
984 return -1;
985 output_counter = 0;
986 return 0;
987 }
988 return -1;
989 }
990
991 /* end ALSA API 0.5.x */
992
993 #elif ALSA_LIB < 5
994
995 /*================================================================
996 * ALSA API version 0.4.x
997 *================================================================*/
998
999 /*return value == 0 sucess
1000 == 1 warning
1001 == -1 fails
1002 */
set_playback_info(snd_pcm_t * handle__,int32 * encoding__,int32 * rate__,const int32 extra_param[5])1003 static int set_playback_info (snd_pcm_t* handle__,
1004 int32* encoding__, int32* rate__,
1005 const int32 extra_param[5])
1006 {
1007 int ret_val = 0;
1008 const int32 orig_encoding = *encoding__;
1009 const int32 orig_rate = *rate__;
1010 int tmp;
1011 snd_pcm_playback_info_t pinfo;
1012 snd_pcm_format_t pcm_format;
1013 struct snd_pcm_playback_params pparams;
1014 struct snd_pcm_playback_status pstatus;
1015 memset (&pcm_format, 0, sizeof (pcm_format));
1016
1017 memset (&pinfo, 0, sizeof (pinfo));
1018 memset (&pparams, 0, sizeof (pparams));
1019 tmp = snd_pcm_playback_info (handle__, &pinfo);
1020 if (tmp < 0)
1021 {
1022 error_report (tmp);
1023 return -1;
1024 }
1025
1026 /*check sample bit*/
1027 if ((pinfo.flags & SND_PCM_PINFO_8BITONLY) != 0)
1028 *encoding__ &= ~PE_16BIT; /*force 8bit samples*/
1029 if ((pinfo.flags & SND_PCM_PINFO_16BITONLY) != 0)
1030 *encoding__ |= PE_16BIT; /*force 16bit samples*/
1031
1032 /*check rate*/
1033 if (pinfo.min_rate > *rate__)
1034 *rate__ = pinfo.min_rate;
1035 if (pinfo.max_rate < *rate__)
1036 *rate__ = pinfo.max_rate;
1037 pcm_format.rate = *rate__;
1038
1039 /*check channels*/
1040 if ((*encoding__ & PE_MONO) != 0 && pinfo.min_channels > 1)
1041 *encoding__ &= ~PE_MONO;
1042 if ((*encoding__ & PE_MONO) == 0 && pinfo.max_channels < 2)
1043 *encoding__ |= PE_MONO;
1044
1045 if ((*encoding__ & PE_MONO) != 0)
1046 pcm_format.channels = 1; /*mono*/
1047 else
1048 pcm_format.channels = 2; /*stereo*/
1049
1050 /*check format*/
1051 if ((*encoding__ & PE_16BIT) != 0)
1052 { /*16bit*/
1053 if ((pinfo.formats & SND_PCM_FMT_S16_LE) != 0)
1054 {
1055 pcm_format.format = SND_PCM_SFMT_S16_LE;
1056 *encoding__ |= PE_SIGNED;
1057 }
1058 else
1059 {
1060 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1061 "%s doesn't support 16 bit sample width",
1062 alsa_device_name());
1063 return -1;
1064 }
1065 }
1066 else
1067 { /*8bit*/
1068 if ((pinfo.formats & SND_PCM_FMT_U8) != 0)
1069 {
1070 pcm_format.format = SND_PCM_SFMT_U8;
1071 *encoding__ &= ~PE_SIGNED;
1072 }
1073 #if 0
1074 else if ((pinfo.formats & SND_PCM_FMT_S8) != 0)
1075 {
1076 pcm_format.format = SND_PCM_SFMT_U16_LE;
1077 *encoding__ |= PE_SIGNED;
1078 }
1079 #endif
1080 else
1081 {
1082 ctl->cmsg(CMSG_ERROR, VERB_NORMAL,
1083 "%s doesn't support 8 bit sample width",
1084 alsa_device_name());
1085 return -1;
1086 }
1087 }
1088
1089
1090 tmp = snd_pcm_playback_format (handle__, &pcm_format);
1091 if (tmp < 0)
1092 {
1093 error_report (tmp);
1094 return -1;
1095 }
1096 /*check result of snd_pcm_playback_format*/
1097 if ((*encoding__ & PE_16BIT) != (orig_encoding & PE_16BIT ))
1098 {
1099 ctl->cmsg (CMSG_WARNING, VERB_VERBOSE,
1100 "Sample width adjusted to %d bits",
1101 ((*encoding__ & PE_16BIT) != 0)? 16:8);
1102 ret_val = 1;
1103 }
1104 if (((pcm_format.channels == 1)? PE_MONO:0) != (orig_encoding & PE_MONO))
1105 {
1106 ctl->cmsg(CMSG_WARNING, VERB_VERBOSE, "Sound adjusted to %sphonic",
1107 ((*encoding__ & PE_MONO) != 0)? "mono" : "stereo");
1108 ret_val = 1;
1109 }
1110
1111 sample_shift = 0;
1112 if (!(dpm.encoding & PE_MONO))
1113 sample_shift++;
1114 if (dpm.encoding & PE_16BIT)
1115 sample_shift++;
1116
1117 /* Set buffer fragment size (in extra_param[1]) */
1118 if (extra_param[1] != 0)
1119 tmp = extra_param[1];
1120 else
1121 tmp = audio_buffer_size << sample_shift;
1122
1123 /* Set buffer fragments (in extra_param[0]) */
1124 pparams.fragment_size = tmp;
1125 pparams.fragments_max = (extra_param[0] == 0) ? -1 : extra_param[0];
1126 pparams.fragments_room = 1;
1127 tmp = snd_pcm_playback_params (handle__, &pparams);
1128 if (tmp < 0)
1129 {
1130 ctl->cmsg(CMSG_WARNING, VERB_NORMAL,
1131 "%s doesn't support buffer fragments"
1132 ":request size=%d, max=%d, room=%d\n",
1133 alsa_device_name(),
1134 pparams.fragment_size,
1135 pparams.fragments_max,
1136 pparams.fragments_room);
1137 ret_val = 1;
1138 }
1139
1140 if (snd_pcm_playback_status(handle__, &pstatus) == 0)
1141 {
1142 if (pstatus.rate != orig_rate)
1143 {
1144 ctl->cmsg(CMSG_WARNING, VERB_VERBOSE,
1145 "Output rate adjusted to %d Hz (requested %d Hz)",
1146 pstatus.rate, orig_rate);
1147 dpm.rate = pstatus.rate;
1148 ret_val = 1;
1149 }
1150 frag_size = pstatus.fragment_size;
1151 total_bytes = pstatus.count;
1152 }
1153 else
1154 {
1155 frag_size = 0;
1156 total_bytes = -1; /* snd_pcm_playback_status fails */
1157 }
1158
1159 return ret_val;
1160 }
1161
open_output(void)1162 static int open_output(void)
1163 {
1164 int tmp, warnings=0;
1165 int ret;
1166
1167 tmp = check_sound_cards (&card, &device, dpm.extra_param);
1168 if (tmp < 0)
1169 return -1;
1170
1171 /* Open the audio device */
1172 ret = snd_pcm_open (&handle, card, device, SND_PCM_OPEN_PLAYBACK);
1173 if (ret < 0)
1174 {
1175 ctl->cmsg(CMSG_ERROR, VERB_NORMAL, "%s: %s",
1176 alsa_device_name(), snd_strerror (ret));
1177 return -1;
1178 }
1179
1180 /* They can't mean these */
1181 dpm.encoding &= ~(PE_ULAW|PE_ALAW|PE_BYTESWAP);
1182 warnings = set_playback_info (handle, &dpm.encoding, &dpm.rate,
1183 dpm.extra_param);
1184 if (warnings < 0)
1185 {
1186 close_output ();
1187 return -1;
1188 }
1189
1190 dpm.fd = snd_pcm_file_descriptor (handle);
1191 output_counter = 0;
1192 return warnings;
1193 }
1194
close_output(void)1195 static void close_output(void)
1196 {
1197 int ret;
1198
1199 if (handle == NULL)
1200 return;
1201
1202 ret = snd_pcm_close (handle);
1203 if (ret < 0)
1204 error_report (ret);
1205 handle = NULL;
1206
1207 dpm.fd = -1;
1208 }
1209
output_data(char * buf,int32 nbytes)1210 static int output_data(char *buf, int32 nbytes)
1211 {
1212 int n;
1213
1214 if (! handle)
1215 return -1;
1216 while (nbytes > 0)
1217 {
1218 n = snd_pcm_write (handle, buf, nbytes);
1219
1220 if (n < 0)
1221 {
1222 ctl->cmsg(CMSG_WARNING, VERB_DEBUG,
1223 "%s: %s", alsa_device_name(), snd_strerror(n));
1224 if (n == -EWOULDBLOCK)
1225 continue;
1226 return -1;
1227 }
1228 buf += n;
1229 nbytes -= n;
1230 output_counter += n;
1231 }
1232
1233 return 0;
1234 }
1235
acntl(int request,void * arg)1236 static int acntl(int request, void *arg)
1237 {
1238 int i;
1239 struct snd_pcm_playback_status pstatus;
1240
1241 if (handle == NULL)
1242 return -1;
1243
1244 switch (request)
1245 {
1246 case PM_REQ_GETFRAGSIZ:
1247 if (frag_size == 0)
1248 return -1;
1249 *((int *)arg) = frag_size;
1250 return 0;
1251
1252 case PM_REQ_GETQSIZ:
1253 if (total_bytes == -1)
1254 return -1;
1255 *((int *)arg) = total_bytes;
1256 return 0;
1257
1258 case PM_REQ_GETFILLABLE:
1259 if (total_bytes == -1)
1260 return -1;
1261 if (snd_pcm_playback_status(handle, &pstatus) < 0)
1262 return -1;
1263 i = pstatus.count >> sample_shift;
1264 *((int *)arg) = i;
1265 return 0;
1266
1267 case PM_REQ_GETFILLED:
1268 if (total_bytes == -1)
1269 return -1;
1270 if (snd_pcm_playback_status(handle, &pstatus) < 0)
1271 return -1;
1272 i = pstatus.queue >> sample_shift;
1273 *((int *)arg) = i;
1274 return 0;
1275
1276 case PM_REQ_GETSAMPLES:
1277 if (total_bytes == -1)
1278 return -1;
1279 if (snd_pcm_playback_status(handle, &pstatus) < 0)
1280 return -1;
1281 i = output_counter - pstatus.queue;
1282 i >>= sample_shift;
1283 *((int *)arg) = i;
1284 return 0;
1285
1286 case PM_REQ_DISCARD:
1287 if (snd_pcm_drain_playback (handle) < 0)
1288 return -1; /* error */
1289 output_counter = 0;
1290 return 0;
1291
1292 case PM_REQ_FLUSH:
1293 if (snd_pcm_flush_playback(handle) < 0)
1294 return -1; /* error */
1295 output_counter = 0;
1296 return 0;
1297 }
1298 return -1;
1299 }
1300
1301 /* end ALSA API 0.4.x */
1302
1303 #endif
1304
1305