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