2 * Copyright 2004-2005 Timo Hirvonen
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
24 * SND_PCM_STATE_OPEN = 0,
27 * SND_PCM_STATE_SETUP = 1,
30 * SND_PCM_STATE_PREPARED = 2,
33 * SND_PCM_STATE_RUNNING = 3,
35 * Stopped: underrun (playback) or overrun (capture) detected
36 * SND_PCM_STATE_XRUN = 4,
38 * Draining: running (playback) or stopped (capture)
39 * SND_PCM_STATE_DRAINING = 5,
42 * SND_PCM_STATE_PAUSED = 6,
44 * Hardware is suspended
45 * SND_PCM_STATE_SUSPENDED = 7,
47 * Hardware is disconnected
48 * SND_PCM_STATE_DISCONNECTED = 8,
57 #define ALSA_PCM_NEW_HW_PARAMS_API
58 #define ALSA_PCM_NEW_SW_PARAMS_API
60 #include <alsa/asoundlib.h>
62 /* without one of these play-back won't start */
63 #define SET_BUFFER_TIME
64 #define SET_PERIOD_TIME
68 /* with this alsa hangs sometimes (ogg, not enough data with first write?) */
69 /* #define SET_START_THRESHOLD */
71 static sample_format_t alsa_sf
;
72 static snd_pcm_t
*alsa_handle
;
73 static snd_pcm_format_t alsa_fmt
;
74 static int alsa_can_pause
;
75 static snd_pcm_status_t
*status
;
77 /* bytes (bits * channels / 8) */
78 static int alsa_frame_size
;
81 static char *alsa_dsp_device
= NULL
;
83 #ifdef SET_START_THRESHOLD
84 static int alsa_buffer_size
;
88 static int alsa_period_size
;
92 #define debug_ret(func, ret) \
93 d_print("%s returned %d %s\n", func, ret, ret < 0 ? snd_strerror(ret) : "")
95 #define debug_ret(func, ret) do { } while (0)
98 static int alsa_error_to_op_error(int err
)
101 if (err
< SND_ERROR_BEGIN
) {
103 return -OP_ERROR_ERRNO
;
105 return -OP_ERROR_INTERNAL
;
108 /* we don't want error messages to stderr */
109 static void error_handler(const char *file
, int line
, const char *function
, int err
, const char *fmt
, ...)
113 static int op_alsa_init(void)
117 snd_lib_error_set_handler(error_handler
);
119 if (alsa_dsp_device
== NULL
)
120 alsa_dsp_device
= xstrdup("default");
121 rc
= snd_pcm_status_malloc(&status
);
123 free(alsa_dsp_device
);
124 alsa_dsp_device
= NULL
;
126 return -OP_ERROR_ERRNO
;
131 static int op_alsa_exit(void)
133 snd_pcm_status_free(status
);
134 free(alsa_dsp_device
);
135 alsa_dsp_device
= NULL
;
139 /* randomize hw params */
140 static int alsa_set_hw_params(void)
142 snd_pcm_hw_params_t
*hwparams
;
146 #if defined(SET_AVAIL_MIN) || defined(SET_START_THRESHOLD)
147 snd_pcm_uframes_t frames
;
149 #ifdef SET_BUFFER_TIME
150 unsigned int alsa_buffer_time
= 500e3
;
152 #ifdef SET_PERIOD_TIME
153 unsigned int alsa_period_time
= 50e3
;
156 snd_pcm_hw_params_alloca(&hwparams
);
158 cmd
= "snd_pcm_hw_params_any";
159 rc
= snd_pcm_hw_params_any(alsa_handle
, hwparams
);
163 alsa_can_pause
= snd_pcm_hw_params_can_pause(hwparams
);
164 d_print("can pause = %d\n", alsa_can_pause
);
166 cmd
= "snd_pcm_hw_params_set_access";
167 rc
= snd_pcm_hw_params_set_access(alsa_handle
, hwparams
,
168 SND_PCM_ACCESS_RW_INTERLEAVED
);
172 alsa_fmt
= snd_pcm_build_linear_format(sf_get_bits(alsa_sf
), sf_get_bits(alsa_sf
),
173 sf_get_signed(alsa_sf
) ? 0 : 1,
174 sf_get_bigendian(alsa_sf
));
175 cmd
= "snd_pcm_hw_params_set_format";
176 rc
= snd_pcm_hw_params_set_format(alsa_handle
, hwparams
, alsa_fmt
);
180 cmd
= "snd_pcm_hw_params_set_channels";
181 rc
= snd_pcm_hw_params_set_channels(alsa_handle
, hwparams
, sf_get_channels(alsa_sf
));
185 cmd
= "snd_pcm_hw_params_set_rate";
186 rate
= sf_get_rate(alsa_sf
);
188 rc
= snd_pcm_hw_params_set_rate_near(alsa_handle
, hwparams
, &rate
, &dir
);
191 d_print("rate=%d\n", rate
);
193 #ifdef SET_BUFFER_TIME
194 cmd
= "snd_pcm_hw_params_set_buffer_time_near";
196 rc
= snd_pcm_hw_params_set_buffer_time_near(alsa_handle
, hwparams
, &alsa_buffer_time
, &dir
);
201 #ifdef SET_PERIOD_TIME
202 cmd
= "snd_pcm_hw_params_set_period_time_near";
204 rc
= snd_pcm_hw_params_set_period_time_near(alsa_handle
, hwparams
, &alsa_period_time
, &dir
);
210 rc
= snd_pcm_hw_params_get_period_size(hwparams
, &frames
, &dir
);
212 alsa_period_size
= -1;
214 alsa_period_size
= frames
* alsa_frame_size
;
216 d_print("period_size = %d (dir = %d)\n", alsa_period_size
, dir
);
219 #ifdef SET_START_THRESHOLD
220 rc
= snd_pcm_hw_params_get_buffer_size(hwparams
, &frames
);
222 alsa_buffer_size
= -1;
224 alsa_buffer_size
= frames
* alsa_frame_size
;
226 d_print("buffer_size = %d\n", alsa_buffer_size
);
229 cmd
= "snd_pcm_hw_params";
230 rc
= snd_pcm_hw_params(alsa_handle
, hwparams
);
235 d_print("%s: error: %s\n", cmd
, snd_strerror(rc
));
239 /* randomize sw params */
240 static int alsa_set_sw_params(void)
242 #if defined(SET_START_THRESHOLD) || defined(SET_AVAIL_MIN)
243 snd_pcm_sw_params_t
*swparams
;
247 /* allocate the software parameter structure */
248 snd_pcm_sw_params_alloca(&swparams
);
250 /* fetch the current software parameters */
251 cmd
= "snd_pcm_sw_params_current";
252 rc
= snd_pcm_sw_params_current(alsa_handle
, swparams
);
256 #ifdef SET_START_THRESHOLD
257 if (alsa_buffer_size
> 0) {
258 /* start the transfer when N frames available */
259 cmd
= "snd_pcm_sw_params_set_start_threshold";
260 /* start playing when hardware buffer is full (64 kB, 372 ms) */
261 rc
= snd_pcm_sw_params_set_start_threshold(alsa_handle
, swparams
, alsa_buffer_size
/ alsa_frame_size
);
268 if (alsa_period_size
> 0) {
269 snd_pcm_uframes_t frames
= alsa_period_size
/ alsa_frame_size
;
271 /* minimum avail frames to consider pcm ready. must be power of 2 */
272 cmd
= "snd_pcm_sw_params_set_avail_min";
273 /* underrun when available is <8192 B or 46.5 ms */
274 rc
= snd_pcm_sw_params_set_avail_min(alsa_handle
, swparams
, frames
);
278 cmd
= "snd_pcm_sw_params_set_silence_threshold";
279 rc
= snd_pcm_sw_params_set_silence_threshold(alsa_handle
, swparams
, frames
);
285 /* commit the params structure to ALSA */
286 cmd
= "snd_pcm_sw_params";
287 rc
= snd_pcm_sw_params(alsa_handle
, swparams
);
292 d_print("%s: error: %s\n", cmd
, snd_strerror(rc
));
299 static int op_alsa_open(sample_format_t sf
)
304 alsa_frame_size
= sf_get_frame_size(alsa_sf
);
306 rc
= snd_pcm_open(&alsa_handle
, alsa_dsp_device
, SND_PCM_STREAM_PLAYBACK
, 0);
310 rc
= alsa_set_hw_params();
313 rc
= alsa_set_sw_params();
317 rc
= snd_pcm_prepare(alsa_handle
);
322 snd_pcm_close(alsa_handle
);
324 return alsa_error_to_op_error(rc
);
327 static unsigned int period_fill
= 0;
329 static int op_alsa_write(const char *buffer
, int count
);
331 static int op_alsa_close(void)
335 /* it is impossible to calculate period_fill if period_size is -1 */
336 if (alsa_period_size
> 0 && period_fill
) {
338 int silence_bytes
= alsa_period_size
- period_fill
;
340 if (silence_bytes
> sizeof(buf
)) {
341 d_print("silence buf not big enough %d\n", silence_bytes
);
342 silence_bytes
= sizeof(buf
);
344 d_print("silencing %d bytes\n", silence_bytes
);
345 snd_pcm_format_set_silence(alsa_fmt
, buf
, silence_bytes
/ sf_get_sample_size(alsa_sf
));
346 op_alsa_write(buf
, silence_bytes
);
350 rc
= snd_pcm_drain(alsa_handle
);
351 debug_ret("snd_pcm_drain", rc
);
353 rc
= snd_pcm_close(alsa_handle
);
354 debug_ret("snd_pcm_close", rc
);
358 static int op_alsa_drop(void)
364 /* infinite timeout */
365 rc
= snd_pcm_wait(alsa_handle
, -1);
366 debug_ret("snd_pcm_wait", rc
);
368 rc
= snd_pcm_drop(alsa_handle
);
369 debug_ret("snd_pcm_drop", rc
);
371 rc
= snd_pcm_prepare(alsa_handle
);
372 debug_ret("snd_pcm_prepare", rc
);
374 /* drop set state to SETUP
375 * prepare set state to PREPARED
377 * so if old state was PAUSED we can't UNPAUSE (see op_alsa_unpause)
382 static int op_alsa_write(const char *buffer
, int count
)
387 len
= count
/ alsa_frame_size
;
389 rc
= snd_pcm_writei(alsa_handle
, buffer
, len
);
391 // rc _should_ be either -EBADFD, -EPIPE or -ESTRPIPE
392 if (!recovered
&& (rc
== -EINTR
|| rc
== -EPIPE
|| rc
== -ESTRPIPE
)) {
393 d_print("snd_pcm_writei failed: %s, trying to recover\n",
396 // this handles -EINTR, -EPIPE and -ESTRPIPE
397 // for other errors it just returns the error code
398 rc
= snd_pcm_recover(alsa_handle
, rc
, 1);
403 /* this handles EAGAIN too which is not critical error */
404 return alsa_error_to_op_error(rc
);
407 rc
*= alsa_frame_size
;
409 period_fill
%= alsa_period_size
;
413 static int op_alsa_buffer_space(void)
418 rc
= snd_pcm_status(alsa_handle
, status
);
420 debug_ret("snd_pcm_status", rc
);
421 return alsa_error_to_op_error(rc
);
424 f
= snd_pcm_status_get_avail(status
);
426 d_print("snd_pcm_status_get_avail returned huge number: %lu\n", f
);
429 return f
* alsa_frame_size
;
432 static int op_alsa_pause(void)
434 if (alsa_can_pause
) {
435 snd_pcm_state_t state
;
438 state
= snd_pcm_state(alsa_handle
);
439 if (state
== SND_PCM_STATE_PREPARED
) {
440 // state is PREPARED -> no need to pause
441 } else if (state
== SND_PCM_STATE_RUNNING
) {
442 // state is RUNNING - > pause
445 rc
= snd_pcm_wait(alsa_handle
, -1);
446 debug_ret("snd_pcm_wait", rc
);
448 rc
= snd_pcm_pause(alsa_handle
, 1);
449 debug_ret("snd_pcm_pause", rc
);
451 d_print("error: state is not RUNNING or PREPARED\n");
457 static int op_alsa_unpause(void)
459 if (alsa_can_pause
) {
460 snd_pcm_state_t state
;
463 state
= snd_pcm_state(alsa_handle
);
464 if (state
== SND_PCM_STATE_PREPARED
) {
465 // state is PREPARED -> no need to unpause
466 } else if (state
== SND_PCM_STATE_PAUSED
) {
467 // state is PAUSED -> unpause
470 rc
= snd_pcm_wait(alsa_handle
, -1);
471 debug_ret("snd_pcm_wait", rc
);
473 rc
= snd_pcm_pause(alsa_handle
, 0);
474 debug_ret("snd_pcm_pause", rc
);
476 d_print("error: state is not PAUSED nor PREPARED\n");
482 static int op_alsa_set_option(int key
, const char *val
)
486 free(alsa_dsp_device
);
487 alsa_dsp_device
= xstrdup(val
);
490 return -OP_ERROR_NOT_OPTION
;
495 static int op_alsa_get_option(int key
, char **val
)
500 *val
= xstrdup(alsa_dsp_device
);
503 return -OP_ERROR_NOT_OPTION
;
508 const struct output_plugin_ops op_pcm_ops
= {
509 .init
= op_alsa_init
,
510 .exit
= op_alsa_exit
,
511 .open
= op_alsa_open
,
512 .close
= op_alsa_close
,
513 .drop
= op_alsa_drop
,
514 .write
= op_alsa_write
,
515 .buffer_space
= op_alsa_buffer_space
,
516 .pause
= op_alsa_pause
,
517 .unpause
= op_alsa_unpause
,
518 .set_option
= op_alsa_set_option
,
519 .get_option
= op_alsa_get_option
522 const char * const op_pcm_options
[] = {
527 const int op_priority
= 0;