Update to MPlayer SVN rev 29473 and FFmpeg SVN rev 19572.
[vaapi:athaifas-mplayer.git] / libao2 / .svn / text-base / ao_alsa.c.svn-base
1 /*
2  * ALSA 0.9.x-1.x audio output driver
3  *
4  * Copyright (C) 2004 Alex Beregszaszi
5  *
6  * modified for real ALSA 0.9.0 support by Zsolt Barat <joy@streamminister.de>
7  * additional AC-3 passthrough support by Andy Lo A Foe <andy@alsaplayer.org>
8  * 08/22/2002 iec958-init rewritten and merged with common init, zsolt
9  * 04/13/2004 merged with ao_alsa1.x, fixes provided by Jindrich Makovicka
10  * 04/25/2004 printfs converted to mp_msg, Zsolt.
11  *
12  * This file is part of MPlayer.
13  *
14  * MPlayer is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  *
19  * MPlayer is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License along
25  * with MPlayer; if not, write to the Free Software Foundation, Inc.,
26  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
27  */
28
29 #include <errno.h>
30 #include <sys/time.h>
31 #include <stdlib.h>
32 #include <stdarg.h>
33 #include <ctype.h>
34 #include <math.h>
35 #include <string.h>
36 #include <alloca.h>
37
38 #include "config.h"
39 #include "subopt-helper.h"
40 #include "mixer.h"
41 #include "mp_msg.h"
42 #include "help_mp.h"
43
44 #define ALSA_PCM_NEW_HW_PARAMS_API
45 #define ALSA_PCM_NEW_SW_PARAMS_API
46
47 #ifdef HAVE_SYS_ASOUNDLIB_H
48 #include <sys/asoundlib.h>
49 #elif defined(HAVE_ALSA_ASOUNDLIB_H)
50 #include <alsa/asoundlib.h>
51 #else
52 #error "asoundlib.h is not in sys/ or alsa/ - please bugreport"
53 #endif
54
55
56 #include "audio_out.h"
57 #include "audio_out_internal.h"
58 #include "libaf/af_format.h"
59
60 static const ao_info_t info =
61 {
62     "ALSA-0.9.x-1.x audio output",
63     "alsa",
64     "Alex Beregszaszi, Zsolt Barat <joy@streamminister.de>",
65     "under developement"
66 };
67
68 LIBAO_EXTERN(alsa)
69
70 static snd_pcm_t *alsa_handler;
71 static snd_pcm_format_t alsa_format;
72 static snd_pcm_hw_params_t *alsa_hwparams;
73 static snd_pcm_sw_params_t *alsa_swparams;
74
75 /* 16 sets buffersize to 16 * chunksize is as default 1024
76  * which seems to be good avarge for most situations
77  * so buffersize is 16384 frames by default */
78 static int alsa_fragcount = 16;
79 static snd_pcm_uframes_t chunk_size = 1024;
80
81 static size_t bytes_per_sample;
82
83 static int ao_noblock = 0;
84
85 static int open_mode;
86 static int alsa_can_pause = 0;
87
88 #define ALSA_DEVICE_SIZE 256
89
90 #undef BUFFERTIME
91 #define SET_CHUNKSIZE
92
93 static void alsa_error_handler(const char *file, int line, const char *function,
94                                int err, const char *format, ...)
95 {
96   char tmp[0xc00];
97   va_list va;
98
99   va_start(va, format);
100   vsnprintf(tmp, sizeof tmp, format, va);
101   va_end(va);
102   tmp[sizeof tmp - 1] = '\0';
103
104   if (err)
105     mp_msg(MSGT_AO, MSGL_ERR, "[AO_ALSA] alsa-lib: %s:%i:(%s) %s: %s\n",
106            file, line, function, tmp, snd_strerror(err));
107   else
108     mp_msg(MSGT_AO, MSGL_ERR, "[AO_ALSA] alsa-lib: %s:%i:(%s) %s\n",
109            file, line, function, tmp);
110 }
111
112 /* to set/get/query special features/parameters */
113 static int control(int cmd, void *arg)
114 {
115   switch(cmd) {
116   case AOCONTROL_QUERY_FORMAT:
117     return CONTROL_TRUE;
118   case AOCONTROL_GET_VOLUME:
119   case AOCONTROL_SET_VOLUME:
120     {
121       ao_control_vol_t *vol = (ao_control_vol_t *)arg;
122
123       int err;
124       snd_mixer_t *handle;
125       snd_mixer_elem_t *elem;
126       snd_mixer_selem_id_t *sid;
127
128       static char *mix_name = "PCM";
129       static char *card = "default";
130       static int mix_index = 0;
131
132       long pmin, pmax;
133       long get_vol, set_vol;
134       float f_multi;
135
136       if(ao_data.format == AF_FORMAT_AC3)
137         return CONTROL_TRUE;
138
139       if(mixer_channel) {
140          char *test_mix_index;
141
142          mix_name = strdup(mixer_channel);
143          if ((test_mix_index = strchr(mix_name, ','))){
144                 *test_mix_index = 0;
145                 test_mix_index++;
146                 mix_index = strtol(test_mix_index, &test_mix_index, 0);
147
148                 if (*test_mix_index){
149                   mp_msg(MSGT_AO,MSGL_ERR,
150                     MSGTR_AO_ALSA_InvalidMixerIndexDefaultingToZero);
151                   mix_index = 0 ;
152                 }
153          }
154       }
155       if(mixer_device) card = mixer_device;
156
157       //allocate simple id
158       snd_mixer_selem_id_alloca(&sid);
159
160       //sets simple-mixer index and name
161       snd_mixer_selem_id_set_index(sid, mix_index);
162       snd_mixer_selem_id_set_name(sid, mix_name);
163
164       if (mixer_channel) {
165         free(mix_name);
166         mix_name = NULL;
167       }
168
169       if ((err = snd_mixer_open(&handle, 0)) < 0) {
170         mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_MixerOpenError, snd_strerror(err));
171         return CONTROL_ERROR;
172       }
173
174       if ((err = snd_mixer_attach(handle, card)) < 0) {
175         mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_MixerAttachError,
176                card, snd_strerror(err));
177         snd_mixer_close(handle);
178         return CONTROL_ERROR;
179       }
180
181       if ((err = snd_mixer_selem_register(handle, NULL, NULL)) < 0) {
182         mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_MixerRegisterError, snd_strerror(err));
183         snd_mixer_close(handle);
184         return CONTROL_ERROR;
185       }
186       err = snd_mixer_load(handle);
187       if (err < 0) {
188         mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_MixerLoadError, snd_strerror(err));
189         snd_mixer_close(handle);
190         return CONTROL_ERROR;
191       }
192
193       elem = snd_mixer_find_selem(handle, sid);
194       if (!elem) {
195         mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToFindSimpleControl,
196                snd_mixer_selem_id_get_name(sid), snd_mixer_selem_id_get_index(sid));
197         snd_mixer_close(handle);
198         return CONTROL_ERROR;
199         }
200
201       snd_mixer_selem_get_playback_volume_range(elem,&pmin,&pmax);
202       f_multi = (100 / (float)(pmax - pmin));
203
204       if (cmd == AOCONTROL_SET_VOLUME) {
205
206         set_vol = vol->left / f_multi + pmin + 0.5;
207
208         //setting channels
209         if ((err = snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, set_vol)) < 0) {
210           mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_ErrorSettingLeftChannel,
211                  snd_strerror(err));
212           return CONTROL_ERROR;
213         }
214         mp_msg(MSGT_AO,MSGL_DBG2,"left=%li, ", set_vol);
215
216         set_vol = vol->right / f_multi + pmin + 0.5;
217
218         if ((err = snd_mixer_selem_set_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, set_vol)) < 0) {
219           mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_ErrorSettingRightChannel,
220                  snd_strerror(err));
221           return CONTROL_ERROR;
222         }
223         mp_msg(MSGT_AO,MSGL_DBG2,"right=%li, pmin=%li, pmax=%li, mult=%f\n",
224                set_vol, pmin, pmax, f_multi);
225
226         if (snd_mixer_selem_has_playback_switch(elem)) {
227           int lmute = (vol->left == 0.0);
228           int rmute = (vol->right == 0.0);
229           if (snd_mixer_selem_has_playback_switch_joined(elem)) {
230             lmute = rmute = lmute && rmute;
231           } else {
232             snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_RIGHT, !rmute);
233           }
234           snd_mixer_selem_set_playback_switch(elem, SND_MIXER_SCHN_FRONT_LEFT, !lmute);
235         }
236       }
237       else {
238         snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, &get_vol);
239         vol->left = (get_vol - pmin) * f_multi;
240         snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_RIGHT, &get_vol);
241         vol->right = (get_vol - pmin) * f_multi;
242
243         mp_msg(MSGT_AO,MSGL_DBG2,"left=%f, right=%f\n",vol->left,vol->right);
244       }
245       snd_mixer_close(handle);
246       return CONTROL_OK;
247     }
248
249   } //end switch
250   return CONTROL_UNKNOWN;
251 }
252
253 static void parse_device (char *dest, const char *src, int len)
254 {
255   char *tmp;
256   memmove(dest, src, len);
257   dest[len] = 0;
258   while ((tmp = strrchr(dest, '.')))
259     tmp[0] = ',';
260   while ((tmp = strrchr(dest, '=')))
261     tmp[0] = ':';
262 }
263
264 static void print_help (void)
265 {
266   mp_msg (MSGT_AO, MSGL_FATAL,
267            MSGTR_AO_ALSA_CommandlineHelp);
268 }
269
270 static int str_maxlen(strarg_t *str) {
271   if (str->len > ALSA_DEVICE_SIZE)
272     return 0;
273   return 1;
274 }
275
276 static int try_open_device(const char *device, int open_mode, int try_ac3)
277 {
278   int err, len;
279   char *ac3_device, *args;
280
281   if (try_ac3) {
282     /* to set the non-audio bit, use AES0=6 */
283     len = strlen(device);
284     ac3_device = malloc(len + 7 + 1);
285     if (!ac3_device)
286       return -ENOMEM;
287     strcpy(ac3_device, device);
288     args = strchr(ac3_device, ':');
289     if (!args) {
290       /* no existing parameters: add it behind device name */
291       strcat(ac3_device, ":AES0=6");
292     } else {
293       do
294         ++args;
295       while (isspace(*args));
296       if (*args == '\0') {
297         /* ":" but no parameters */
298         strcat(ac3_device, "AES0=6");
299       } else if (*args != '{') {
300         /* a simple list of parameters: add it at the end of the list */
301         strcat(ac3_device, ",AES0=6");
302       } else {
303         /* parameters in config syntax: add it inside the { } block */
304         do
305           --len;
306         while (len > 0 && isspace(ac3_device[len]));
307         if (ac3_device[len] == '}')
308           strcpy(ac3_device + len, " AES0=6}");
309       }
310     }
311     err = snd_pcm_open(&alsa_handler, ac3_device, SND_PCM_STREAM_PLAYBACK,
312                        open_mode);
313     free(ac3_device);
314   }
315   if (!try_ac3 || err < 0)
316     err = snd_pcm_open(&alsa_handler, device, SND_PCM_STREAM_PLAYBACK,
317                        open_mode);
318   return err;
319 }
320
321 /*
322     open & setup audio device
323     return: 1=success 0=fail
324 */
325 static int init(int rate_hz, int channels, int format, int flags)
326 {
327     int err;
328     int block;
329     strarg_t device;
330     snd_pcm_uframes_t bufsize;
331     snd_pcm_uframes_t boundary;
332     opt_t subopts[] = {
333       {"block", OPT_ARG_BOOL, &block, NULL},
334       {"device", OPT_ARG_STR, &device, (opt_test_f)str_maxlen},
335       {NULL}
336     };
337
338     char alsa_device[ALSA_DEVICE_SIZE + 1];
339     // make sure alsa_device is null-terminated even when using strncpy etc.
340     memset(alsa_device, 0, ALSA_DEVICE_SIZE + 1);
341
342     mp_msg(MSGT_AO,MSGL_V,"alsa-init: requested format: %d Hz, %d channels, %x\n", rate_hz,
343         channels, format);
344     alsa_handler = NULL;
345 #if SND_LIB_VERSION >= 0x010005
346     mp_msg(MSGT_AO,MSGL_V,"alsa-init: using ALSA %s\n", snd_asoundlib_version());
347 #else
348     mp_msg(MSGT_AO,MSGL_V,"alsa-init: compiled for ALSA-%s\n", SND_LIB_VERSION_STR);
349 #endif
350
351     snd_lib_error_set_handler(alsa_error_handler);
352
353     ao_data.samplerate = rate_hz;
354     ao_data.format = format;
355     ao_data.channels = channels;
356
357     switch (format)
358       {
359       case AF_FORMAT_S8:
360         alsa_format = SND_PCM_FORMAT_S8;
361         break;
362       case AF_FORMAT_U8:
363         alsa_format = SND_PCM_FORMAT_U8;
364         break;
365       case AF_FORMAT_U16_LE:
366         alsa_format = SND_PCM_FORMAT_U16_LE;
367         break;
368       case AF_FORMAT_U16_BE:
369         alsa_format = SND_PCM_FORMAT_U16_BE;
370         break;
371 #if !HAVE_BIGENDIAN
372       case AF_FORMAT_AC3:
373 #endif
374       case AF_FORMAT_S16_LE:
375         alsa_format = SND_PCM_FORMAT_S16_LE;
376         break;
377 #if HAVE_BIGENDIAN
378       case AF_FORMAT_AC3:
379 #endif
380       case AF_FORMAT_S16_BE:
381         alsa_format = SND_PCM_FORMAT_S16_BE;
382         break;
383       case AF_FORMAT_U32_LE:
384         alsa_format = SND_PCM_FORMAT_U32_LE;
385         break;
386       case AF_FORMAT_U32_BE:
387         alsa_format = SND_PCM_FORMAT_U32_BE;
388         break;
389       case AF_FORMAT_S32_LE:
390         alsa_format = SND_PCM_FORMAT_S32_LE;
391         break;
392       case AF_FORMAT_S32_BE:
393         alsa_format = SND_PCM_FORMAT_S32_BE;
394         break;
395       case AF_FORMAT_U24_LE:
396         alsa_format = SND_PCM_FORMAT_U24_3LE;
397         break;
398       case AF_FORMAT_U24_BE:
399         alsa_format = SND_PCM_FORMAT_U24_3BE;
400         break;
401       case AF_FORMAT_S24_LE:
402         alsa_format = SND_PCM_FORMAT_S24_3LE;
403         break;
404       case AF_FORMAT_S24_BE:
405         alsa_format = SND_PCM_FORMAT_S24_3BE;
406         break;
407       case AF_FORMAT_FLOAT_LE:
408         alsa_format = SND_PCM_FORMAT_FLOAT_LE;
409         break;
410       case AF_FORMAT_FLOAT_BE:
411         alsa_format = SND_PCM_FORMAT_FLOAT_BE;
412         break;
413       case AF_FORMAT_MU_LAW:
414         alsa_format = SND_PCM_FORMAT_MU_LAW;
415         break;
416       case AF_FORMAT_A_LAW:
417         alsa_format = SND_PCM_FORMAT_A_LAW;
418         break;
419
420       default:
421         alsa_format = SND_PCM_FORMAT_MPEG; //? default should be -1
422         break;
423       }
424
425     //subdevice parsing
426     // set defaults
427     block = 1;
428     /* switch for spdif
429      * sets opening sequence for SPDIF
430      * sets also the playback and other switches 'on the fly'
431      * while opening the abstract alias for the spdif subdevice
432      * 'iec958'
433      */
434     if (format == AF_FORMAT_AC3) {
435         device.str = "iec958";
436         mp_msg(MSGT_AO,MSGL_V,"alsa-spdif-init: playing AC3, %i channels\n", channels);
437     }
438   else
439         /* in any case for multichannel playback we should select
440          * appropriate device
441          */
442         switch (channels) {
443         case 1:
444         case 2:
445           device.str = "default";
446           mp_msg(MSGT_AO,MSGL_V,"alsa-init: setup for 1/2 channel(s)\n");
447           break;
448         case 4:
449           if (alsa_format == SND_PCM_FORMAT_FLOAT_LE)
450             // hack - use the converter plugin
451             device.str = "plug:surround40";
452           else
453             device.str = "surround40";
454           mp_msg(MSGT_AO,MSGL_V,"alsa-init: device set to surround40\n");
455           break;
456         case 6:
457           if (alsa_format == SND_PCM_FORMAT_FLOAT_LE)
458             device.str = "plug:surround51";
459           else
460             device.str = "surround51";
461           mp_msg(MSGT_AO,MSGL_V,"alsa-init: device set to surround51\n");
462           break;
463         default:
464           device.str = "default";
465           mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_ChannelsNotSupported,channels);
466         }
467     device.len = strlen(device.str);
468     if (subopt_parse(ao_subdevice, subopts) != 0) {
469         print_help();
470         return 0;
471     }
472     ao_noblock = !block;
473     parse_device(alsa_device, device.str, device.len);
474
475     mp_msg(MSGT_AO,MSGL_V,"alsa-init: using device %s\n", alsa_device);
476
477     //setting modes for block or nonblock-mode
478     if (ao_noblock) {
479       open_mode = SND_PCM_NONBLOCK;
480     }
481     else {
482       open_mode = 0;
483     }
484
485     //sets buff/chunksize if its set manually
486     if (ao_data.buffersize) {
487       switch (ao_data.buffersize)
488         {
489         case 1:
490           alsa_fragcount = 16;
491           chunk_size = 512;
492             mp_msg(MSGT_AO,MSGL_V,"alsa-init: buffersize set manually to 8192\n");
493             mp_msg(MSGT_AO,MSGL_V,"alsa-init: chunksize set manually to 512\n");
494           break;
495         case 2:
496           alsa_fragcount = 8;
497           chunk_size = 1024;
498             mp_msg(MSGT_AO,MSGL_V,"alsa-init: buffersize set manually to 8192\n");
499             mp_msg(MSGT_AO,MSGL_V,"alsa-init: chunksize set manually to 1024\n");
500           break;
501         case 3:
502           alsa_fragcount = 32;
503           chunk_size = 512;
504             mp_msg(MSGT_AO,MSGL_V,"alsa-init: buffersize set manually to 16384\n");
505             mp_msg(MSGT_AO,MSGL_V,"alsa-init: chunksize set manually to 512\n");
506           break;
507         case 4:
508           alsa_fragcount = 16;
509           chunk_size = 1024;
510             mp_msg(MSGT_AO,MSGL_V,"alsa-init: buffersize set manually to 16384\n");
511             mp_msg(MSGT_AO,MSGL_V,"alsa-init: chunksize set manually to 1024\n");
512           break;
513         default:
514           alsa_fragcount = 16;
515           chunk_size = 1024;
516           break;
517         }
518     }
519
520     if (!alsa_handler) {
521       //modes = 0, SND_PCM_NONBLOCK, SND_PCM_ASYNC
522       if ((err = try_open_device(alsa_device, open_mode, format == AF_FORMAT_AC3)) < 0)
523         {
524           if (err != -EBUSY && ao_noblock) {
525             mp_msg(MSGT_AO,MSGL_INFO,MSGTR_AO_ALSA_OpenInNonblockModeFailed);
526             if ((err = try_open_device(alsa_device, 0, format == AF_FORMAT_AC3)) < 0) {
527               mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PlaybackOpenError, snd_strerror(err));
528               return 0;
529             }
530           } else {
531             mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PlaybackOpenError, snd_strerror(err));
532             return 0;
533           }
534         }
535
536       if ((err = snd_pcm_nonblock(alsa_handler, 0)) < 0) {
537          mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_ErrorSetBlockMode, snd_strerror(err));
538       } else {
539         mp_msg(MSGT_AO,MSGL_V,"alsa-init: pcm opened in blocking mode\n");
540       }
541
542       snd_pcm_hw_params_alloca(&alsa_hwparams);
543       snd_pcm_sw_params_alloca(&alsa_swparams);
544
545       // setting hw-parameters
546       if ((err = snd_pcm_hw_params_any(alsa_handler, alsa_hwparams)) < 0)
547         {
548           mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToGetInitialParameters,
549                  snd_strerror(err));
550           return 0;
551         }
552
553       err = snd_pcm_hw_params_set_access(alsa_handler, alsa_hwparams,
554                                          SND_PCM_ACCESS_RW_INTERLEAVED);
555       if (err < 0) {
556         mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetAccessType,
557                snd_strerror(err));
558         return 0;
559       }
560
561       /* workaround for nonsupported formats
562          sets default format to S16_LE if the given formats aren't supported */
563       if ((err = snd_pcm_hw_params_test_format(alsa_handler, alsa_hwparams,
564                                              alsa_format)) < 0)
565       {
566          mp_msg(MSGT_AO,MSGL_INFO,
567                 MSGTR_AO_ALSA_FormatNotSupportedByHardware, af_fmt2str_short(format));
568          alsa_format = SND_PCM_FORMAT_S16_LE;
569          ao_data.format = AF_FORMAT_S16_LE;
570       }
571
572       if ((err = snd_pcm_hw_params_set_format(alsa_handler, alsa_hwparams,
573                                               alsa_format)) < 0)
574         {
575           mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetFormat,
576                  snd_strerror(err));
577           return 0;
578         }
579
580       if ((err = snd_pcm_hw_params_set_channels_near(alsa_handler, alsa_hwparams,
581                                                      &ao_data.channels)) < 0)
582         {
583           mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetChannels,
584                  snd_strerror(err));
585           return 0;
586         }
587
588       /* workaround for buggy rate plugin (should be fixed in ALSA 1.0.11)
589          prefer our own resampler */
590 #if SND_LIB_VERSION >= 0x010009
591       if ((err = snd_pcm_hw_params_set_rate_resample(alsa_handler, alsa_hwparams,
592                                                      0)) < 0)
593         {
594           mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToDisableResampling,
595                  snd_strerror(err));
596           return 0;
597         }
598 #endif
599
600       if ((err = snd_pcm_hw_params_set_rate_near(alsa_handler, alsa_hwparams,
601                                                  &ao_data.samplerate, NULL)) < 0)
602         {
603           mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetSamplerate2,
604                  snd_strerror(err));
605           return 0;
606         }
607
608       bytes_per_sample = snd_pcm_format_physical_width(alsa_format) / 8;
609       bytes_per_sample *= ao_data.channels;
610       ao_data.bps = ao_data.samplerate * bytes_per_sample;
611
612 #ifdef BUFFERTIME
613       {
614         int alsa_buffer_time = 500000; /* original 60 */
615         int alsa_period_time;
616         alsa_period_time = alsa_buffer_time/4;
617         if ((err = snd_pcm_hw_params_set_buffer_time_near(alsa_handler, alsa_hwparams,
618                                                           &alsa_buffer_time, NULL)) < 0)
619           {
620             mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetBufferTimeNear,
621                    snd_strerror(err));
622             return 0;
623           } else
624             alsa_buffer_time = err;
625
626         if ((err = snd_pcm_hw_params_set_period_time_near(alsa_handler, alsa_hwparams,
627                                                           &alsa_period_time, NULL)) < 0)
628           /* original: alsa_buffer_time/ao_data.bps */
629           {
630             mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetPeriodTime,
631                    snd_strerror(err));
632             return 0;
633           }
634         mp_msg(MSGT_AO,MSGL_INFO,MSGTR_AO_ALSA_BufferTimePeriodTime,
635                alsa_buffer_time, err);
636       }
637 #endif//end SET_BUFFERTIME
638
639 #ifdef SET_CHUNKSIZE
640       {
641         //set chunksize
642         if ((err = snd_pcm_hw_params_set_period_size_near(alsa_handler, alsa_hwparams,
643                                                           &chunk_size, NULL)) < 0)
644           {
645             mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetPeriodSize,
646                             chunk_size, snd_strerror(err));
647             return 0;
648           }
649         else {
650           mp_msg(MSGT_AO,MSGL_V,"alsa-init: chunksize set to %li\n", chunk_size);
651         }
652         if ((err = snd_pcm_hw_params_set_periods_near(alsa_handler, alsa_hwparams,
653                                                       &alsa_fragcount, NULL)) < 0) {
654           mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetPeriods,
655                  snd_strerror(err));
656           return 0;
657         }
658         else {
659           mp_msg(MSGT_AO,MSGL_V,"alsa-init: fragcount=%i\n", alsa_fragcount);
660         }
661       }
662 #endif//end SET_CHUNKSIZE
663
664       /* finally install hardware parameters */
665       if ((err = snd_pcm_hw_params(alsa_handler, alsa_hwparams)) < 0)
666         {
667           mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetHwParameters,
668                  snd_strerror(err));
669           return 0;
670         }
671       // end setting hw-params
672
673
674       // gets buffersize for control
675       if ((err = snd_pcm_hw_params_get_buffer_size(alsa_hwparams, &bufsize)) < 0)
676         {
677           mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToGetBufferSize, snd_strerror(err));
678           return 0;
679         }
680       else {
681         ao_data.buffersize = bufsize * bytes_per_sample;
682           mp_msg(MSGT_AO,MSGL_V,"alsa-init: got buffersize=%i\n", ao_data.buffersize);
683       }
684
685       if ((err = snd_pcm_hw_params_get_period_size(alsa_hwparams, &chunk_size, NULL)) < 0) {
686         mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToGetPeriodSize, snd_strerror(err));
687         return 0;
688       } else {
689         mp_msg(MSGT_AO,MSGL_V,"alsa-init: got period size %li\n", chunk_size);
690       }
691       ao_data.outburst = chunk_size * bytes_per_sample;
692
693       /* setting software parameters */
694       if ((err = snd_pcm_sw_params_current(alsa_handler, alsa_swparams)) < 0) {
695         mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToGetSwParameters,
696                snd_strerror(err));
697         return 0;
698       }
699 #if SND_LIB_VERSION >= 0x000901
700       if ((err = snd_pcm_sw_params_get_boundary(alsa_swparams, &boundary)) < 0) {
701         mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToGetBoundary,
702                snd_strerror(err));
703         return 0;
704       }
705 #else
706       boundary = 0x7fffffff;
707 #endif
708       /* start playing when one period has been written */
709       if ((err = snd_pcm_sw_params_set_start_threshold(alsa_handler, alsa_swparams, chunk_size)) < 0) {
710         mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetStartThreshold,
711                snd_strerror(err));
712         return 0;
713       }
714       /* disable underrun reporting */
715       if ((err = snd_pcm_sw_params_set_stop_threshold(alsa_handler, alsa_swparams, boundary)) < 0) {
716         mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetStopThreshold,
717                snd_strerror(err));
718         return 0;
719       }
720 #if SND_LIB_VERSION >= 0x000901
721       /* play silence when there is an underrun */
722       if ((err = snd_pcm_sw_params_set_silence_size(alsa_handler, alsa_swparams, boundary)) < 0) {
723         mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToSetSilenceSize,
724                snd_strerror(err));
725         return 0;
726       }
727 #endif
728       if ((err = snd_pcm_sw_params(alsa_handler, alsa_swparams)) < 0) {
729         mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_UnableToGetSwParameters,
730                snd_strerror(err));
731         return 0;
732       }
733       /* end setting sw-params */
734
735       mp_msg(MSGT_AO,MSGL_V,"alsa: %d Hz/%d channels/%d bpf/%d bytes buffer/%s\n",
736              ao_data.samplerate, ao_data.channels, (int)bytes_per_sample, ao_data.buffersize,
737              snd_pcm_format_description(alsa_format));
738
739     } // end switch alsa_handler (spdif)
740     alsa_can_pause = snd_pcm_hw_params_can_pause(alsa_hwparams);
741     return 1;
742 } // end init
743
744
745 /* close audio device */
746 static void uninit(int immed)
747 {
748
749   if (alsa_handler) {
750     int err;
751
752     if (!immed)
753       snd_pcm_drain(alsa_handler);
754
755     if ((err = snd_pcm_close(alsa_handler)) < 0)
756       {
757         mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PcmCloseError, snd_strerror(err));
758         return;
759       }
760     else {
761       alsa_handler = NULL;
762       mp_msg(MSGT_AO,MSGL_V,"alsa-uninit: pcm closed\n");
763     }
764   }
765   else {
766     mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_NoHandlerDefined);
767   }
768 }
769
770 static void audio_pause(void)
771 {
772     int err;
773
774     if (alsa_can_pause) {
775         if ((err = snd_pcm_pause(alsa_handler, 1)) < 0)
776         {
777             mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PcmPauseError, snd_strerror(err));
778             return;
779         }
780           mp_msg(MSGT_AO,MSGL_V,"alsa-pause: pause supported by hardware\n");
781     } else {
782         if ((err = snd_pcm_drop(alsa_handler)) < 0)
783         {
784             mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PcmDropError, snd_strerror(err));
785             return;
786         }
787     }
788 }
789
790 static void audio_resume(void)
791 {
792     int err;
793
794     if (snd_pcm_state(alsa_handler) == SND_PCM_STATE_SUSPENDED) {
795         mp_msg(MSGT_AO,MSGL_INFO,MSGTR_AO_ALSA_PcmInSuspendModeTryingResume);
796         while ((err = snd_pcm_resume(alsa_handler)) == -EAGAIN) sleep(1);
797     }
798     if (alsa_can_pause) {
799         if ((err = snd_pcm_pause(alsa_handler, 0)) < 0)
800         {
801             mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PcmResumeError, snd_strerror(err));
802             return;
803         }
804           mp_msg(MSGT_AO,MSGL_V,"alsa-resume: resume supported by hardware\n");
805     } else {
806         if ((err = snd_pcm_prepare(alsa_handler)) < 0)
807         {
808            mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PcmPrepareError, snd_strerror(err));
809             return;
810         }
811     }
812 }
813
814 /* stop playing and empty buffers (for seeking/pause) */
815 static void reset(void)
816 {
817     int err;
818
819     if ((err = snd_pcm_drop(alsa_handler)) < 0)
820     {
821         mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PcmPrepareError, snd_strerror(err));
822         return;
823     }
824     if ((err = snd_pcm_prepare(alsa_handler)) < 0)
825     {
826         mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PcmPrepareError, snd_strerror(err));
827         return;
828     }
829     return;
830 }
831
832 /*
833     plays 'len' bytes of 'data'
834     returns: number of bytes played
835     modified last at 29.06.02 by jp
836     thanxs for marius <marius@rospot.com> for giving us the light ;)
837 */
838
839 static int play(void* data, int len, int flags)
840 {
841   int num_frames = len / bytes_per_sample;
842   snd_pcm_sframes_t res = 0;
843
844   //mp_msg(MSGT_AO,MSGL_ERR,"alsa-play: frames=%i, len=%i\n",num_frames,len);
845
846   if (!alsa_handler) {
847     mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_DeviceConfigurationError);
848     return 0;
849   }
850
851   if (num_frames == 0)
852     return 0;
853
854   do {
855     res = snd_pcm_writei(alsa_handler, data, num_frames);
856
857       if (res == -EINTR) {
858         /* nothing to do */
859         res = 0;
860       }
861       else if (res == -ESTRPIPE) {      /* suspend */
862         mp_msg(MSGT_AO,MSGL_INFO,MSGTR_AO_ALSA_PcmInSuspendModeTryingResume);
863         while ((res = snd_pcm_resume(alsa_handler)) == -EAGAIN)
864           sleep(1);
865       }
866       if (res < 0) {
867         mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_WriteError, snd_strerror(res));
868         mp_msg(MSGT_AO,MSGL_INFO,MSGTR_AO_ALSA_TryingToResetSoundcard);
869         if ((res = snd_pcm_prepare(alsa_handler)) < 0) {
870           mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_PcmPrepareError, snd_strerror(res));
871           return 0;
872           break;
873         }
874       }
875   } while (res == 0);
876
877   return res < 0 ? res : res * bytes_per_sample;
878 }
879
880 /* how many byes are free in the buffer */
881 static int get_space(void)
882 {
883     snd_pcm_status_t *status;
884     int ret;
885
886     snd_pcm_status_alloca(&status);
887
888     if ((ret = snd_pcm_status(alsa_handler, status)) < 0)
889     {
890         mp_msg(MSGT_AO,MSGL_ERR,MSGTR_AO_ALSA_CannotGetPcmStatus, snd_strerror(ret));
891         return 0;
892     }
893
894     ret = snd_pcm_status_get_avail(status) * bytes_per_sample;
895     if (ret > ao_data.buffersize)  // Buffer underrun?
896         ret = ao_data.buffersize;
897     return ret;
898 }
899
900 /* delay in seconds between first and last sample in buffer */
901 static float get_delay(void)
902 {
903   if (alsa_handler) {
904     snd_pcm_sframes_t delay;
905
906     if (snd_pcm_delay(alsa_handler, &delay) < 0)
907       return 0;
908
909     if (delay < 0) {
910       /* underrun - move the application pointer forward to catch up */
911 #if SND_LIB_VERSION >= 0x000901 /* snd_pcm_forward() exists since 0.9.0rc8 */
912       snd_pcm_forward(alsa_handler, -delay);
913 #endif
914       delay = 0;
915     }
916     return (float)delay / (float)ao_data.samplerate;
917   } else {
918     return 0;
919   }
920 }