Mercurial > mplayer.hg
annotate libao2/ao_alsa1x.c @ 5835:104fce2b92b6
fix fullscreen (?)
author | pontscho |
---|---|
date | Thu, 25 Apr 2002 21:52:47 +0000 |
parents | d141f1e9cc36 |
children | c21948cd027d |
rev | line source |
---|---|
1050 | 1 /* |
2 ao_alsa9 - ALSA-0.9.x output plugin for MPlayer | |
3 | |
4 (C) Alex Beregszaszi <alex@naxine.org> | |
1180 | 5 |
2209 | 6 modified for better alsa-0.9.0beta8a-support by Joy Winter <joy@pingfm.org> |
7 | |
8 This driver is still at alpha stage. | |
9 If you want stable sound-support use the OSS emulation instead. | |
10 | |
11 Any bugreports regarding to this driver are welcome either to the mplayer-user-mailinglist or directly to the authors. | |
1050 | 12 */ |
13 | |
14 #include <errno.h> | |
15 #include <sys/asoundlib.h> | |
16 | |
17 #include "../config.h" | |
18 | |
19 #include "audio_out.h" | |
20 #include "audio_out_internal.h" | |
1058 | 21 #include "afmt.h" |
1050 | 22 |
23 extern int verbose; | |
24 | |
25 static ao_info_t info = | |
26 { | |
27 "ALSA-0.9.x audio output", | |
28 "alsa9", | |
2209 | 29 "Alex Beregszaszi <alex@naxine.org>, Joy Winter <joy@pingfm.org>", |
1050 | 30 "under developement" |
31 }; | |
32 | |
33 LIBAO_EXTERN(alsa9) | |
34 | |
35 | |
36 static snd_pcm_t *alsa_handler; | |
37 static snd_pcm_format_t alsa_format; | |
38 static snd_pcm_hw_params_t *alsa_hwparams; | |
39 static snd_pcm_sw_params_t *alsa_swparams; | |
40 static char *alsa_device; | |
2209 | 41 #define ALSA_DEVICE_SIZE 48 |
1050 | 42 |
2209 | 43 static int alsa_fragsize = 8192; /* possible 4096, original 8192 */ |
44 static int alsa_fragcount = 8; | |
45 | |
46 static int chunk_size = -1; | |
47 static int start_delay = 1; | |
1128 | 48 |
1050 | 49 /* to set/get/query special features/parameters */ |
50 static int control(int cmd, int arg) | |
51 { | |
52 switch(cmd) | |
53 { | |
54 case AOCONTROL_GET_DEVICE: | |
1146
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
55 return((char *)alsa_device); /* egy kicsit brutalis, dehat :) */ |
1050 | 56 case AOCONTROL_SET_DEVICE: |
1146
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
57 { |
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
58 int ret; |
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
59 |
1050 | 60 strncpy(alsa_device, (char *)arg, ALSA_DEVICE_SIZE); |
1146
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
61 uninit(); |
3095 | 62 ret = init(ao_data.samplerate, ao_data.channels, ao_data.format, 0); |
1146
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
63 if (ret == 0) |
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
64 return(CONTROL_ERROR); |
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
65 else |
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
66 return(CONTROL_OK); |
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
67 } |
1050 | 68 } |
69 return(CONTROL_UNKNOWN); | |
70 } | |
71 | |
2209 | 72 #undef start /* orig. undef */ |
3135 | 73 #define buffsize |
2209 | 74 #define buffertime /* orig. undef? */ |
1128 | 75 #define set_period |
2209 | 76 #define sw_params /* orig. undef */ |
77 #undef set_start_mode /* orig. undef */ | |
1128 | 78 |
1050 | 79 /* |
80 open & setup audio device | |
81 return: 1=success 0=fail | |
82 */ | |
83 static int init(int rate_hz, int channels, int format, int flags) | |
84 { | |
85 int err; | |
86 int cards = -1; | |
87 snd_pcm_info_t *alsa_info; | |
1180 | 88 |
2209 | 89 size_t xfer_align; //new |
90 snd_pcm_uframes_t start_threshold, stop_threshold; //new | |
1050 | 91 |
2209 | 92 printf("alsa-init: this driver is still at alpha-stage. if you want stable sound support use the OSS emulation instead.\n"); |
1050 | 93 printf("alsa-init: requested format: %d Hz, %d channels, %s\n", rate_hz, |
94 channels, audio_out_format_name(format)); | |
95 | |
96 alsa_handler = NULL; | |
97 | |
98 if (verbose) | |
2059 | 99 printf("alsa-init: compiled for ALSA-%s\n", SND_LIB_VERSION_STR); |
1050 | 100 |
101 if ((err = snd_card_next(&cards)) < 0 || cards < 0) | |
102 { | |
103 printf("alsa-init: no soundcards found: %s\n", snd_strerror(err)); | |
104 return(0); | |
105 } | |
106 | |
3095 | 107 ao_data.samplerate = rate_hz; |
108 ao_data.bps = channels; /* really this is bytes per frame so bad varname */ | |
109 ao_data.format = format; | |
110 ao_data.channels = channels; | |
111 ao_data.outburst = OUTBURST; | |
112 ao_data.buffersize = 16384; | |
1050 | 113 |
114 switch (format) | |
115 { | |
116 case AFMT_S8: | |
117 alsa_format = SND_PCM_FORMAT_S8; | |
118 break; | |
119 case AFMT_U8: | |
120 alsa_format = SND_PCM_FORMAT_U8; | |
121 break; | |
122 case AFMT_U16_LE: | |
123 alsa_format = SND_PCM_FORMAT_U16_LE; | |
124 break; | |
125 case AFMT_U16_BE: | |
126 alsa_format = SND_PCM_FORMAT_U16_BE; | |
127 break; | |
5790 | 128 #ifndef WORDS_BIGENDIAN |
129 case AFMT_AC3: | |
130 #endif | |
1050 | 131 case AFMT_S16_LE: |
132 alsa_format = SND_PCM_FORMAT_S16_LE; | |
133 break; | |
5790 | 134 #ifdef WORDS_BIGENDIAN |
135 case AFMT_AC3: | |
136 #endif | |
1050 | 137 case AFMT_S16_BE: |
138 alsa_format = SND_PCM_FORMAT_S16_BE; | |
139 break; | |
140 default: | |
141 alsa_format = SND_PCM_FORMAT_MPEG; | |
142 break; | |
143 } | |
144 | |
145 switch(alsa_format) | |
146 { | |
147 case SND_PCM_FORMAT_S16_LE: | |
148 case SND_PCM_FORMAT_U16_LE: | |
3095 | 149 ao_data.bps *= 2; |
1050 | 150 break; |
151 case -1: | |
152 printf("alsa-init: invalid format (%s) requested - output disabled\n", | |
153 audio_out_format_name(format)); | |
154 return(0); | |
1115
a16b569f2702
-Wall style cleanups, TEST IT, it can be working by others
al3x
parents:
1058
diff
changeset
|
155 default: |
a16b569f2702
-Wall style cleanups, TEST IT, it can be working by others
al3x
parents:
1058
diff
changeset
|
156 break; |
1050 | 157 } |
1128 | 158 |
1050 | 159 if ((err = snd_pcm_info_malloc(&alsa_info)) < 0) |
160 { | |
161 printf("alsa-init: memory allocation error: %s\n", snd_strerror(err)); | |
162 return(0); | |
163 } | |
164 | |
3129 | 165 if (ao_subdevice != NULL) |
166 alsa_device = ao_subdevice; | |
1207 | 167 |
1146
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
168 if (alsa_device == NULL) |
1050 | 169 { |
1146
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
170 if ((alsa_device = malloc(ALSA_DEVICE_SIZE)) == NULL) |
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
171 { |
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
172 printf("alsa-init: memory allocation error: %s\n", strerror(errno)); |
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
173 return(0); |
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
174 } |
1050 | 175 |
1146
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
176 snprintf(alsa_device, ALSA_DEVICE_SIZE, "hw:%d,%d", |
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
177 snd_pcm_info_get_device(alsa_info), |
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
178 snd_pcm_info_get_subdevice(alsa_info)); |
1050 | 179 |
1146
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
180 snd_pcm_info_free(alsa_info); |
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
181 } |
1050 | 182 |
183 printf("alsa-init: %d soundcard%s found, using: %s\n", cards+1, | |
184 (cards >= 0) ? "" : "s", alsa_device); | |
185 | |
186 if ((err = snd_pcm_open(&alsa_handler, alsa_device, SND_PCM_STREAM_PLAYBACK, | |
187 0)) < 0) | |
188 { | |
189 printf("alsa-init: playback open error: %s\n", snd_strerror(err)); | |
190 return(0); | |
191 } | |
192 | |
193 snd_pcm_hw_params_malloc(&alsa_hwparams); | |
2209 | 194 //snd_pcm_sw_params_malloc(&alsa_swparams); |
195 snd_pcm_sw_params_alloca(&alsa_swparams); | |
1050 | 196 if ((err = snd_pcm_hw_params_any(alsa_handler, alsa_hwparams)) < 0) |
197 { | |
198 printf("alsa-init: unable to get initial parameters: %s\n", | |
199 snd_strerror(err)); | |
200 return(0); | |
201 } | |
202 | |
203 if ((err = snd_pcm_hw_params_set_access(alsa_handler, alsa_hwparams, | |
204 SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) | |
205 { | |
206 printf("alsa-init: unable to set access type: %s\n", | |
207 snd_strerror(err)); | |
208 return(0); | |
209 } | |
210 | |
211 if ((err = snd_pcm_hw_params_set_format(alsa_handler, alsa_hwparams, | |
212 alsa_format)) < 0) | |
213 { | |
214 printf("alsa-init: unable to set format: %s\n", | |
215 snd_strerror(err)); | |
216 return(0); | |
217 } | |
218 | |
219 if ((err = snd_pcm_hw_params_set_channels(alsa_handler, alsa_hwparams, | |
3095 | 220 ao_data.channels)) < 0) |
1050 | 221 { |
222 printf("alsa-init: unable to set channels: %s\n", | |
223 snd_strerror(err)); | |
224 return(0); | |
225 } | |
226 | |
3095 | 227 if ((err = snd_pcm_hw_params_set_rate_near(alsa_handler, alsa_hwparams, ao_data.samplerate, 0)) < 0) |
2209 | 228 /* was originally only snd_pcm_hw_params_set_rate jp*/ |
2059 | 229 { |
230 printf("alsa-init: unable to set samplerate-2: %s\n", | |
231 snd_strerror(err)); | |
2209 | 232 //snd_pcm_hw_params_dump(alsa_hwparams, errlog); jp |
2059 | 233 return(0); |
234 } | |
1050 | 235 |
1128 | 236 #ifdef set_period |
1115
a16b569f2702
-Wall style cleanups, TEST IT, it can be working by others
al3x
parents:
1058
diff
changeset
|
237 { |
1128 | 238 if ((err = snd_pcm_hw_params_set_period_size(alsa_handler, alsa_hwparams, alsa_fragsize / 4, 0)) < 0) |
239 { | |
240 printf("alsa-init: unable to set periodsize: %s\n", | |
241 snd_strerror(err)); | |
242 return(0); | |
243 } | |
2209 | 244 if ((err = snd_pcm_hw_params_set_periods(alsa_handler, alsa_hwparams, alsa_fragcount, 0)) < 0) |
245 { | |
246 printf("alsa-init: unable to set periods: %s\n", | |
247 snd_strerror(err)); | |
248 return(0); | |
249 } | |
1115
a16b569f2702
-Wall style cleanups, TEST IT, it can be working by others
al3x
parents:
1058
diff
changeset
|
250 } |
1128 | 251 #endif |
3135 | 252 #ifdef buffsize |
1050 | 253 if ((err = snd_pcm_hw_params_get_buffer_size(alsa_hwparams)) < 0) |
254 { | |
255 printf("alsa-init: unable to get buffer size: %s\n", | |
256 snd_strerror(err)); | |
257 return(0); | |
258 } else | |
1128 | 259 { |
3095 | 260 ao_data.buffersize = err; |
1146
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
261 if (verbose) |
3095 | 262 printf("alsa-init: got buffersize %i\n", ao_data.buffersize); |
1128 | 263 } |
1050 | 264 #endif |
265 | |
266 #ifdef buffertime | |
267 { | |
2209 | 268 int alsa_buffer_time = 500000; /* original 60 */ |
1050 | 269 |
2059 | 270 if ((err = snd_pcm_hw_params_set_buffer_time_near(alsa_handler, alsa_hwparams, alsa_buffer_time, 0)) < 0) |
1050 | 271 { |
272 printf("alsa-init: unable to set buffer time near: %s\n", | |
273 snd_strerror(err)); | |
274 return(0); | |
275 } else | |
276 alsa_buffer_time = err; | |
277 | |
2209 | 278 if ((err = snd_pcm_hw_params_set_period_time_near(alsa_handler, alsa_hwparams, alsa_buffer_time/4, 0)) < 0) |
3095 | 279 /* original: alsa_buffer_time/ao_data.bps */ |
1050 | 280 { |
281 printf("alsa-init: unable to set period time: %s\n", | |
282 snd_strerror(err)); | |
283 return(0); | |
284 } | |
1128 | 285 printf("alsa-init: buffer_time: %d, period_time :%d\n", |
286 alsa_buffer_time, err); | |
1050 | 287 } |
288 #endif | |
289 | |
290 if ((err = snd_pcm_hw_params(alsa_handler, alsa_hwparams)) < 0) | |
291 { | |
292 printf("alsa-init: unable to set parameters: %s\n", | |
293 snd_strerror(err)); | |
294 return(0); | |
295 } | |
1128 | 296 |
297 #ifdef sw_params | |
2209 | 298 { |
299 chunk_size = snd_pcm_hw_params_get_period_size(alsa_hwparams, 0); | |
3095 | 300 start_threshold = (double) ao_data.samplerate * start_delay / 1000000; |
2209 | 301 xfer_align = snd_pcm_sw_params_get_xfer_align(alsa_swparams); |
302 | |
1050 | 303 if ((err = snd_pcm_sw_params_current(alsa_handler, alsa_swparams)) < 0) |
304 { | |
305 printf("alsa-init: unable to get parameters: %s\n", | |
306 snd_strerror(err)); | |
307 return(0); | |
2209 | 308 } |
309 | |
310 if ((err = snd_pcm_sw_params_set_avail_min(alsa_handler, alsa_swparams, chunk_size)) < 0) | |
311 { | |
312 printf("alsa-init: unable to set avail_min %s\n",snd_strerror(err)); | |
313 return(0); | |
314 } | |
315 | |
316 | |
317 | |
318 if ((err = snd_pcm_sw_params_set_start_threshold(alsa_handler, alsa_swparams, start_threshold)) < 0) | |
319 { | |
320 printf("alsa-init: unable to set start_threshold %s\n",snd_strerror(err)); | |
321 return(0); | |
322 } | |
323 } | |
324 // if ((err = snd_pcm_sw_params_set_xfer_align(alsa_handler, alsa_swparams, xfer_align)) < 0) | |
325 //{ | |
326 // printf("alsa-init: unable to set xfer_align: %s\n", | |
327 // snd_strerror(err)); | |
328 // return(0); | |
329 //} | |
1050 | 330 |
1128 | 331 #ifdef set_start_mode |
1050 | 332 if ((err = snd_pcm_sw_params_set_start_mode(alsa_handler, alsa_swparams, |
333 SND_PCM_START_DATA)) < 0) | |
334 { | |
335 printf("alsa-init: unable to set start mode: %s\n", | |
336 snd_strerror(err)); | |
337 return(0); | |
338 } | |
1128 | 339 #endif |
1050 | 340 |
341 if ((err = snd_pcm_sw_params(alsa_handler, alsa_swparams)) < 0) | |
342 { | |
343 printf("alsa-init: unable to set parameters: %s\n", | |
344 snd_strerror(err)); | |
345 return(0); | |
346 } | |
347 | |
1128 | 348 // snd_pcm_sw_params_default(alsa_handler, alsa_swparams); |
349 #endif | |
1050 | 350 if ((err = snd_pcm_prepare(alsa_handler)) < 0) |
351 { | |
352 printf("alsa-init: pcm prepare error: %s\n", snd_strerror(err)); | |
353 return(0); | |
354 } | |
355 | |
1115
a16b569f2702
-Wall style cleanups, TEST IT, it can be working by others
al3x
parents:
1058
diff
changeset
|
356 #ifdef start |
1050 | 357 if ((err = snd_pcm_start(alsa_handler)) < 0) |
358 { | |
359 printf("alsa-init: pcm start error: %s\n", snd_strerror(err)); | |
360 if (err != -EPIPE) | |
361 return(0); | |
362 if ((err = snd_pcm_start(alsa_handler)) < 0) | |
363 { | |
364 printf("alsa-init: pcm start error: %s\n", snd_strerror(err)); | |
365 return(0); | |
366 } | |
367 } | |
1115
a16b569f2702
-Wall style cleanups, TEST IT, it can be working by others
al3x
parents:
1058
diff
changeset
|
368 #endif |
1128 | 369 printf("AUDIO: %d Hz/%d channels/%d bpf/%d bytes buffer/%s\n", |
3095 | 370 ao_data.samplerate, ao_data.channels, ao_data.bps, ao_data.buffersize, |
1050 | 371 snd_pcm_format_description(alsa_format)); |
372 return(1); | |
373 } | |
374 | |
375 /* close audio device */ | |
376 static void uninit() | |
377 { | |
378 int err; | |
379 | |
380 if (alsa_device != NULL) | |
381 free(alsa_device); | |
382 | |
383 snd_pcm_hw_params_free(alsa_hwparams); | |
384 snd_pcm_sw_params_free(alsa_swparams); | |
385 | |
386 if ((err = snd_pcm_drain(alsa_handler)) < 0) | |
387 { | |
388 printf("alsa-uninit: pcm drain error: %s\n", snd_strerror(err)); | |
389 return; | |
390 } | |
391 | |
1129 | 392 #ifdef start |
1050 | 393 if ((err = snd_pcm_reset(alsa_handler)) < 0) |
394 { | |
395 printf("alsa-uninit: pcm reset error: %s\n", snd_strerror(err)); | |
396 return; | |
397 } | |
1129 | 398 #endif |
1050 | 399 |
400 if ((err = snd_pcm_close(alsa_handler)) < 0) | |
401 { | |
402 printf("alsa-uninit: pcm close error: %s\n", snd_strerror(err)); | |
403 return; | |
404 } | |
405 } | |
406 | |
407 static void audio_pause() | |
408 { | |
409 int err; | |
410 | |
411 if ((err = snd_pcm_drain(alsa_handler)) < 0) | |
412 { | |
413 printf("alsa-pause: pcm drain error: %s\n", snd_strerror(err)); | |
414 return; | |
415 } | |
416 | |
1129 | 417 #ifdef reset |
1050 | 418 if ((err = snd_pcm_reset(alsa_handler)) < 0) |
419 { | |
420 printf("alsa-pause: pcm reset error: %s\n", snd_strerror(err)); | |
421 return; | |
422 } | |
1129 | 423 #endif |
1050 | 424 } |
425 | |
426 static void audio_resume() | |
427 { | |
428 int err; | |
429 | |
430 if ((err = snd_pcm_prepare(alsa_handler)) < 0) | |
431 { | |
432 printf("alsa-resume: pcm prepare error: %s\n", snd_strerror(err)); | |
433 return; | |
434 } | |
435 | |
1129 | 436 #ifdef start |
1050 | 437 if ((err = snd_pcm_start(alsa_handler)) < 0) |
438 { | |
439 printf("alsa-resume: pcm start error: %s\n", snd_strerror(err)); | |
440 return; | |
441 } | |
1129 | 442 #endif |
1050 | 443 } |
444 | |
445 /* stop playing and empty buffers (for seeking/pause) */ | |
446 static void reset() | |
447 { | |
448 int err; | |
449 | |
450 if ((err = snd_pcm_drain(alsa_handler)) < 0) | |
451 { | |
452 printf("alsa-reset: pcm drain error: %s\n", snd_strerror(err)); | |
453 return; | |
454 } | |
455 | |
1129 | 456 #ifdef start |
1050 | 457 if ((err = snd_pcm_reset(alsa_handler)) < 0) |
458 { | |
459 printf("alsa-reset: pcm reset error: %s\n", snd_strerror(err)); | |
460 return; | |
461 } | |
1129 | 462 #endif |
1050 | 463 |
464 if ((err = snd_pcm_prepare(alsa_handler)) < 0) | |
465 { | |
466 printf("alsa-reset: pcm prepare error: %s\n", snd_strerror(err)); | |
467 return; | |
468 } | |
469 | |
1129 | 470 #ifdef start |
1050 | 471 if ((err = snd_pcm_start(alsa_handler)) < 0) |
472 { | |
473 printf("alsa-reset: pcm start error: %s\n", snd_strerror(err)); | |
474 return; | |
475 } | |
1129 | 476 #endif |
1050 | 477 } |
478 | |
479 /* | |
480 plays 'len' bytes of 'data' | |
481 returns: number of bytes played | |
482 */ | |
483 static int play(void* data, int len, int flags) | |
484 { | |
1115
a16b569f2702
-Wall style cleanups, TEST IT, it can be working by others
al3x
parents:
1058
diff
changeset
|
485 int got_len; |
a16b569f2702
-Wall style cleanups, TEST IT, it can be working by others
al3x
parents:
1058
diff
changeset
|
486 |
2059 | 487 got_len = snd_pcm_writei(alsa_handler, data, len / 4); |
488 | |
3095 | 489 //if ((got_len = snd_pcm_writei(alsa_handler, data, (len/ao_data.bps))) != (len/ao_data.bps)) { |
2209 | 490 //SHOULD BE FIXED |
1115
a16b569f2702
-Wall style cleanups, TEST IT, it can be working by others
al3x
parents:
1058
diff
changeset
|
491 if (got_len == -EPIPE) /* underrun? */ |
1050 | 492 { |
493 printf("alsa-play: alsa underrun, resetting stream\n"); | |
1128 | 494 if ((got_len = snd_pcm_prepare(alsa_handler)) < 0) |
1050 | 495 { |
1128 | 496 printf("alsa-play: playback prepare error: %s\n", snd_strerror(got_len)); |
1050 | 497 return(0); |
498 } | |
3095 | 499 if ((got_len = snd_pcm_writei(alsa_handler, data, (len/ao_data.bps))) != (len/ao_data.bps)) |
1050 | 500 { |
501 printf("alsa-play: write error after reset: %s - giving up\n", | |
1128 | 502 snd_strerror(got_len)); |
1050 | 503 return(0); |
504 } | |
505 return(len); /* 2nd write was ok */ | |
506 } | |
507 return(len); | |
2209 | 508 //} |
1050 | 509 } |
510 | |
511 /* how many byes are free in the buffer */ | |
512 static int get_space() | |
513 { | |
514 snd_pcm_status_t *status; | |
515 int ret; | |
516 | |
517 if ((ret = snd_pcm_status_malloc(&status)) < 0) | |
518 { | |
519 printf("alsa-space: memory allocation error: %s\n", snd_strerror(ret)); | |
520 return(0); | |
521 } | |
522 | |
523 if ((ret = snd_pcm_status(alsa_handler, status)) < 0) | |
524 { | |
525 printf("alsa-space: cannot get pcm status: %s\n", snd_strerror(ret)); | |
526 return(0); | |
527 } | |
528 | |
529 switch(snd_pcm_status_get_state(status)) | |
530 { | |
531 case SND_PCM_STATE_OPEN: | |
532 case SND_PCM_STATE_PREPARED: | |
533 case SND_PCM_STATE_RUNNING: | |
3095 | 534 ret = snd_pcm_status_get_avail(status) * ao_data.bps; |
1050 | 535 break; |
536 default: | |
537 ret = 0; | |
538 } | |
539 | |
540 snd_pcm_status_free(status); | |
1129 | 541 |
542 if (ret < 0) | |
543 ret = 0; | |
1050 | 544 return(ret); |
545 } | |
546 | |
3095 | 547 /* delay in seconds between first and last sample in buffer */ |
548 static float get_delay() | |
1050 | 549 { |
550 snd_pcm_status_t *status; | |
3095 | 551 float ret; |
1050 | 552 |
553 if ((ret = snd_pcm_status_malloc(&status)) < 0) | |
554 { | |
555 printf("alsa-delay: memory allocation error: %s\n", snd_strerror(ret)); | |
556 return(0); | |
557 } | |
558 | |
559 if ((ret = snd_pcm_status(alsa_handler, status)) < 0) | |
560 { | |
561 printf("alsa-delay: cannot get pcm status: %s\n", snd_strerror(ret)); | |
562 return(0); | |
563 } | |
564 | |
565 switch(snd_pcm_status_get_state(status)) | |
566 { | |
567 case SND_PCM_STATE_OPEN: | |
568 case SND_PCM_STATE_PREPARED: | |
569 case SND_PCM_STATE_RUNNING: | |
3095 | 570 ret = (float)snd_pcm_status_get_delay(status)/(float)ao_data.samplerate; |
1050 | 571 break; |
572 default: | |
573 ret = 0; | |
574 } | |
575 | |
576 snd_pcm_status_free(status); | |
1129 | 577 |
578 if (ret < 0) | |
579 ret = 0; | |
1050 | 580 return(ret); |
581 } |