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