sync with en/mplayer.1 rev. 30611
[mplayer/glamo.git] / libao2 / ao_alsa5.c
bloba9b470e9d5e07beda52a99263b8f38db014cdc5a
1 /*
2 * ALSA 0.5.x audio output driver
4 * Copyright (C) 2001 Alex Beregszaszi
6 * Thanks to Arpi for helping me ;)
8 * MPlayer 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.
13 * MPlayer 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.
18 * You should have received a copy of the GNU General Public License along
19 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include <errno.h>
24 #include <sys/asoundlib.h>
26 #include "config.h"
28 #include "audio_out.h"
29 #include "audio_out_internal.h"
30 #include "libaf/af_format.h"
32 #include "mp_msg.h"
33 #include "help_mp.h"
35 static const ao_info_t info =
37 "ALSA-0.5.x audio output",
38 "alsa5",
39 "Alex Beregszaszi",
43 LIBAO_EXTERN(alsa5)
45 static snd_pcm_t *alsa_handler;
46 static snd_pcm_format_t alsa_format;
47 static int alsa_rate = SND_PCM_RATE_CONTINUOUS;
49 /* to set/get/query special features/parameters */
50 static int control(int cmd, void *arg)
52 return CONTROL_UNKNOWN;
56 open & setup audio device
57 return: 1=success 0=fail
59 static int init(int rate_hz, int channels, int format, int flags)
61 int err;
62 int cards = -1;
63 snd_pcm_channel_params_t params;
64 snd_pcm_channel_setup_t setup;
65 snd_pcm_info_t info;
66 snd_pcm_channel_info_t chninfo;
68 mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_ALSA5_InitInfo, rate_hz,
69 channels, af_fmt2str_short(format));
71 alsa_handler = NULL;
73 mp_msg(MSGT_AO, MSGL_V, "alsa-init: compiled for ALSA-%s (%d)\n", SND_LIB_VERSION_STR,
74 SND_LIB_VERSION);
76 if ((cards = snd_cards()) < 0)
78 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_SoundCardNotFound);
79 return 0;
82 ao_data.format = format;
83 ao_data.channels = channels;
84 ao_data.samplerate = rate_hz;
85 ao_data.bps = ao_data.samplerate*ao_data.channels;
86 ao_data.outburst = OUTBURST;
87 ao_data.buffersize = 16384;
89 memset(&alsa_format, 0, sizeof(alsa_format));
90 switch (format)
92 case AF_FORMAT_S8:
93 alsa_format.format = SND_PCM_SFMT_S8;
94 break;
95 case AF_FORMAT_U8:
96 alsa_format.format = SND_PCM_SFMT_U8;
97 break;
98 case AF_FORMAT_U16_LE:
99 alsa_format.format = SND_PCM_SFMT_U16_LE;
100 break;
101 case AF_FORMAT_U16_BE:
102 alsa_format.format = SND_PCM_SFMT_U16_BE;
103 break;
104 case AF_FORMAT_AC3_LE:
105 case AF_FORMAT_S16_LE:
106 alsa_format.format = SND_PCM_SFMT_S16_LE;
107 break;
108 case AF_FORMAT_AC3_BE:
109 case AF_FORMAT_S16_BE:
110 alsa_format.format = SND_PCM_SFMT_S16_BE;
111 break;
112 default:
113 alsa_format.format = SND_PCM_SFMT_MPEG;
114 break;
117 switch(alsa_format.format)
119 case SND_PCM_SFMT_S16_LE:
120 case SND_PCM_SFMT_U16_LE:
121 ao_data.bps *= 2;
122 break;
123 case -1:
124 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_InvalidFormatReq,af_fmt2str_short(format));
125 return 0;
126 default:
127 break;
130 switch(rate_hz)
132 case 8000:
133 alsa_rate = SND_PCM_RATE_8000;
134 break;
135 case 11025:
136 alsa_rate = SND_PCM_RATE_11025;
137 break;
138 case 16000:
139 alsa_rate = SND_PCM_RATE_16000;
140 break;
141 case 22050:
142 alsa_rate = SND_PCM_RATE_22050;
143 break;
144 case 32000:
145 alsa_rate = SND_PCM_RATE_32000;
146 break;
147 case 44100:
148 alsa_rate = SND_PCM_RATE_44100;
149 break;
150 case 48000:
151 alsa_rate = SND_PCM_RATE_48000;
152 break;
153 case 88200:
154 alsa_rate = SND_PCM_RATE_88200;
155 break;
156 case 96000:
157 alsa_rate = SND_PCM_RATE_96000;
158 break;
159 case 176400:
160 alsa_rate = SND_PCM_RATE_176400;
161 break;
162 case 192000:
163 alsa_rate = SND_PCM_RATE_192000;
164 break;
165 default:
166 alsa_rate = SND_PCM_RATE_CONTINUOUS;
167 break;
170 alsa_format.rate = ao_data.samplerate;
171 alsa_format.voices = ao_data.channels;
172 alsa_format.interleave = 1;
174 if ((err = snd_pcm_open(&alsa_handler, 0, 0, SND_PCM_OPEN_PLAYBACK)) < 0)
176 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_PlayBackError, snd_strerror(err));
177 return 0;
180 if ((err = snd_pcm_info(alsa_handler, &info)) < 0)
182 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_PcmInfoError, snd_strerror(err));
183 return 0;
186 mp_msg(MSGT_AO, MSGL_INFO, MSGTR_AO_ALSA5_SoundcardsFound,
187 cards, info.name);
189 if (info.flags & SND_PCM_INFO_PLAYBACK)
191 memset(&chninfo, 0, sizeof(chninfo));
192 chninfo.channel = SND_PCM_CHANNEL_PLAYBACK;
193 if ((err = snd_pcm_channel_info(alsa_handler, &chninfo)) < 0)
195 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_PcmChanInfoError, snd_strerror(err));
196 return 0;
199 #ifndef __QNX__
200 if (chninfo.buffer_size)
201 ao_data.buffersize = chninfo.buffer_size;
202 #endif
204 mp_msg(MSGT_AO, MSGL_V, "alsa-init: setting preferred buffer size from driver: %d bytes\n",
205 ao_data.buffersize);
208 memset(&params, 0, sizeof(params));
209 params.channel = SND_PCM_CHANNEL_PLAYBACK;
210 params.mode = SND_PCM_MODE_STREAM;
211 params.format = alsa_format;
212 params.start_mode = SND_PCM_START_DATA;
213 params.stop_mode = SND_PCM_STOP_ROLLOVER;
214 params.buf.stream.queue_size = ao_data.buffersize;
215 params.buf.stream.fill = SND_PCM_FILL_NONE;
217 if ((err = snd_pcm_channel_params(alsa_handler, &params)) < 0)
219 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_CantSetParms, snd_strerror(err));
220 return 0;
223 memset(&setup, 0, sizeof(setup));
224 setup.channel = SND_PCM_CHANNEL_PLAYBACK;
225 setup.mode = SND_PCM_MODE_STREAM;
226 setup.format = alsa_format;
227 setup.buf.stream.queue_size = ao_data.buffersize;
228 setup.msbits_per_sample = ao_data.bps;
230 if ((err = snd_pcm_channel_setup(alsa_handler, &setup)) < 0)
232 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_CantSetChan, snd_strerror(err));
233 return 0;
236 if ((err = snd_pcm_channel_prepare(alsa_handler, SND_PCM_CHANNEL_PLAYBACK)) < 0)
238 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_ChanPrepareError, snd_strerror(err));
239 return 0;
242 mp_msg(MSGT_AO, MSGL_INFO, "AUDIO: %d Hz/%d channels/%d bps/%d bytes buffer/%s\n",
243 ao_data.samplerate, ao_data.channels, ao_data.bps, ao_data.buffersize,
244 snd_pcm_get_format_name(alsa_format.format));
245 return 1;
248 /* close audio device */
249 static void uninit(int immed)
251 int err;
253 if ((err = snd_pcm_playback_drain(alsa_handler)) < 0)
255 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_DrainError, snd_strerror(err));
256 return;
259 if ((err = snd_pcm_channel_flush(alsa_handler, SND_PCM_CHANNEL_PLAYBACK)) < 0)
261 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_FlushError, snd_strerror(err));
262 return;
265 if ((err = snd_pcm_close(alsa_handler)) < 0)
267 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_PcmCloseError, snd_strerror(err));
268 return;
272 /* stop playing and empty buffers (for seeking/pause) */
273 static void reset(void)
275 int err;
277 if ((err = snd_pcm_playback_drain(alsa_handler)) < 0)
279 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_ResetDrainError, snd_strerror(err));
280 return;
283 if ((err = snd_pcm_channel_flush(alsa_handler, SND_PCM_CHANNEL_PLAYBACK)) < 0)
285 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_ResetFlushError, snd_strerror(err));
286 return;
289 if ((err = snd_pcm_channel_prepare(alsa_handler, SND_PCM_CHANNEL_PLAYBACK)) < 0)
291 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_ResetChanPrepareError, snd_strerror(err));
292 return;
296 /* stop playing, keep buffers (for pause) */
297 static void audio_pause(void)
299 int err;
301 if ((err = snd_pcm_playback_drain(alsa_handler)) < 0)
303 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_PauseDrainError, snd_strerror(err));
304 return;
307 if ((err = snd_pcm_channel_flush(alsa_handler, SND_PCM_CHANNEL_PLAYBACK)) < 0)
309 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_PauseFlushError, snd_strerror(err));
310 return;
314 /* resume playing, after audio_pause() */
315 static void audio_resume(void)
317 int err;
318 if ((err = snd_pcm_channel_prepare(alsa_handler, SND_PCM_CHANNEL_PLAYBACK)) < 0)
320 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_ResumePrepareError, snd_strerror(err));
321 return;
326 plays 'len' bytes of 'data'
327 returns: number of bytes played
329 static int play(void* data, int len, int flags)
331 int got_len;
333 if (!len)
334 return 0;
336 if ((got_len = snd_pcm_write(alsa_handler, data, len)) < 0)
338 if (got_len == -EPIPE) /* underrun? */
340 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_Underrun);
341 if ((got_len = snd_pcm_channel_prepare(alsa_handler, SND_PCM_CHANNEL_PLAYBACK)) < 0)
343 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_PlaybackPrepareError, snd_strerror(got_len));
344 return 0;
346 if ((got_len = snd_pcm_write(alsa_handler, data, len)) < 0)
348 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_WriteErrorAfterReset,
349 snd_strerror(got_len));
350 return 0;
352 return got_len; /* 2nd write was ok */
354 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ALSA5_OutPutError, snd_strerror(got_len));
355 return 0;
357 return got_len;
360 /* how many byes are free in the buffer */
361 static int get_space(void)
363 snd_pcm_channel_status_t ch_stat;
365 ch_stat.channel = SND_PCM_CHANNEL_PLAYBACK;
367 if (snd_pcm_channel_status(alsa_handler, &ch_stat) < 0)
368 return 0; /* error occurred */
369 else
370 return ch_stat.free;
373 /* delay in seconds between first and last sample in buffer */
374 static float get_delay(void)
376 snd_pcm_channel_status_t ch_stat;
378 ch_stat.channel = SND_PCM_CHANNEL_PLAYBACK;
380 if (snd_pcm_channel_status(alsa_handler, &ch_stat) < 0)
381 return (float)ao_data.buffersize/(float)ao_data.bps; /* error occurred */
382 else
383 return (float)ch_stat.count/(float)ao_data.bps;