Mercurial > mplayer.hg
annotate libao2/ao_alsa1x.c @ 3639:64ee21b3bd09
Modified the sync code once again, commented out hardware pts sync (I'll likely burn in hell before understanding how to get this bastard to sync well)
Added automagic setup of aspect ratio, will remove the "aspect-bug" (I hope). As well as please you rich 16:9 doods ;)
author | mswitch |
---|---|
date | Thu, 20 Dec 2001 20:50:35 +0000 |
parents | 168b7ed7ec55 |
children | d141f1e9cc36 |
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; | |
128 case AFMT_S16_LE: | |
129 alsa_format = SND_PCM_FORMAT_S16_LE; | |
130 break; | |
131 case AFMT_S16_BE: | |
132 alsa_format = SND_PCM_FORMAT_S16_BE; | |
133 break; | |
134 default: | |
135 alsa_format = SND_PCM_FORMAT_MPEG; | |
136 break; | |
137 } | |
138 | |
139 switch(alsa_format) | |
140 { | |
141 case SND_PCM_FORMAT_S16_LE: | |
142 case SND_PCM_FORMAT_U16_LE: | |
3095 | 143 ao_data.bps *= 2; |
1050 | 144 break; |
145 case -1: | |
146 printf("alsa-init: invalid format (%s) requested - output disabled\n", | |
147 audio_out_format_name(format)); | |
148 return(0); | |
1115
a16b569f2702
-Wall style cleanups, TEST IT, it can be working by others
al3x
parents:
1058
diff
changeset
|
149 default: |
a16b569f2702
-Wall style cleanups, TEST IT, it can be working by others
al3x
parents:
1058
diff
changeset
|
150 break; |
1050 | 151 } |
1128 | 152 |
1050 | 153 if ((err = snd_pcm_info_malloc(&alsa_info)) < 0) |
154 { | |
155 printf("alsa-init: memory allocation error: %s\n", snd_strerror(err)); | |
156 return(0); | |
157 } | |
158 | |
3129 | 159 if (ao_subdevice != NULL) |
160 alsa_device = ao_subdevice; | |
1207 | 161 |
1146
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
162 if (alsa_device == NULL) |
1050 | 163 { |
1146
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
164 if ((alsa_device = malloc(ALSA_DEVICE_SIZE)) == NULL) |
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
165 { |
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
166 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
|
167 return(0); |
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
168 } |
1050 | 169 |
1146
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
170 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
|
171 snd_pcm_info_get_device(alsa_info), |
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
172 snd_pcm_info_get_subdevice(alsa_info)); |
1050 | 173 |
1146
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
174 snd_pcm_info_free(alsa_info); |
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
175 } |
1050 | 176 |
177 printf("alsa-init: %d soundcard%s found, using: %s\n", cards+1, | |
178 (cards >= 0) ? "" : "s", alsa_device); | |
179 | |
180 if ((err = snd_pcm_open(&alsa_handler, alsa_device, SND_PCM_STREAM_PLAYBACK, | |
181 0)) < 0) | |
182 { | |
183 printf("alsa-init: playback open error: %s\n", snd_strerror(err)); | |
184 return(0); | |
185 } | |
186 | |
187 snd_pcm_hw_params_malloc(&alsa_hwparams); | |
2209 | 188 //snd_pcm_sw_params_malloc(&alsa_swparams); |
189 snd_pcm_sw_params_alloca(&alsa_swparams); | |
1050 | 190 if ((err = snd_pcm_hw_params_any(alsa_handler, alsa_hwparams)) < 0) |
191 { | |
192 printf("alsa-init: unable to get initial parameters: %s\n", | |
193 snd_strerror(err)); | |
194 return(0); | |
195 } | |
196 | |
197 if ((err = snd_pcm_hw_params_set_access(alsa_handler, alsa_hwparams, | |
198 SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) | |
199 { | |
200 printf("alsa-init: unable to set access type: %s\n", | |
201 snd_strerror(err)); | |
202 return(0); | |
203 } | |
204 | |
205 if ((err = snd_pcm_hw_params_set_format(alsa_handler, alsa_hwparams, | |
206 alsa_format)) < 0) | |
207 { | |
208 printf("alsa-init: unable to set format: %s\n", | |
209 snd_strerror(err)); | |
210 return(0); | |
211 } | |
212 | |
213 if ((err = snd_pcm_hw_params_set_channels(alsa_handler, alsa_hwparams, | |
3095 | 214 ao_data.channels)) < 0) |
1050 | 215 { |
216 printf("alsa-init: unable to set channels: %s\n", | |
217 snd_strerror(err)); | |
218 return(0); | |
219 } | |
220 | |
3095 | 221 if ((err = snd_pcm_hw_params_set_rate_near(alsa_handler, alsa_hwparams, ao_data.samplerate, 0)) < 0) |
2209 | 222 /* was originally only snd_pcm_hw_params_set_rate jp*/ |
2059 | 223 { |
224 printf("alsa-init: unable to set samplerate-2: %s\n", | |
225 snd_strerror(err)); | |
2209 | 226 //snd_pcm_hw_params_dump(alsa_hwparams, errlog); jp |
2059 | 227 return(0); |
228 } | |
1050 | 229 |
1128 | 230 #ifdef set_period |
1115
a16b569f2702
-Wall style cleanups, TEST IT, it can be working by others
al3x
parents:
1058
diff
changeset
|
231 { |
1128 | 232 if ((err = snd_pcm_hw_params_set_period_size(alsa_handler, alsa_hwparams, alsa_fragsize / 4, 0)) < 0) |
233 { | |
234 printf("alsa-init: unable to set periodsize: %s\n", | |
235 snd_strerror(err)); | |
236 return(0); | |
237 } | |
2209 | 238 if ((err = snd_pcm_hw_params_set_periods(alsa_handler, alsa_hwparams, alsa_fragcount, 0)) < 0) |
239 { | |
240 printf("alsa-init: unable to set periods: %s\n", | |
241 snd_strerror(err)); | |
242 return(0); | |
243 } | |
1115
a16b569f2702
-Wall style cleanups, TEST IT, it can be working by others
al3x
parents:
1058
diff
changeset
|
244 } |
1128 | 245 #endif |
3135 | 246 #ifdef buffsize |
1050 | 247 if ((err = snd_pcm_hw_params_get_buffer_size(alsa_hwparams)) < 0) |
248 { | |
249 printf("alsa-init: unable to get buffer size: %s\n", | |
250 snd_strerror(err)); | |
251 return(0); | |
252 } else | |
1128 | 253 { |
3095 | 254 ao_data.buffersize = err; |
1146
a84610bb5476
hacked aocontrol_set_device working, and cleaned up a bit
al3x
parents:
1129
diff
changeset
|
255 if (verbose) |
3095 | 256 printf("alsa-init: got buffersize %i\n", ao_data.buffersize); |
1128 | 257 } |
1050 | 258 #endif |
259 | |
260 #ifdef buffertime | |
261 { | |
2209 | 262 int alsa_buffer_time = 500000; /* original 60 */ |
1050 | 263 |
2059 | 264 if ((err = snd_pcm_hw_params_set_buffer_time_near(alsa_handler, alsa_hwparams, alsa_buffer_time, 0)) < 0) |
1050 | 265 { |
266 printf("alsa-init: unable to set buffer time near: %s\n", | |
267 snd_strerror(err)); | |
268 return(0); | |
269 } else | |
270 alsa_buffer_time = err; | |
271 | |
2209 | 272 if ((err = snd_pcm_hw_params_set_period_time_near(alsa_handler, alsa_hwparams, alsa_buffer_time/4, 0)) < 0) |
3095 | 273 /* original: alsa_buffer_time/ao_data.bps */ |
1050 | 274 { |
275 printf("alsa-init: unable to set period time: %s\n", | |
276 snd_strerror(err)); | |
277 return(0); | |
278 } | |
1128 | 279 printf("alsa-init: buffer_time: %d, period_time :%d\n", |
280 alsa_buffer_time, err); | |
1050 | 281 } |
282 #endif | |
283 | |
284 if ((err = snd_pcm_hw_params(alsa_handler, alsa_hwparams)) < 0) | |
285 { | |
286 printf("alsa-init: unable to set parameters: %s\n", | |
287 snd_strerror(err)); | |
288 return(0); | |
289 } | |
1128 | 290 |
291 #ifdef sw_params | |
2209 | 292 { |
293 chunk_size = snd_pcm_hw_params_get_period_size(alsa_hwparams, 0); | |
3095 | 294 start_threshold = (double) ao_data.samplerate * start_delay / 1000000; |
2209 | 295 xfer_align = snd_pcm_sw_params_get_xfer_align(alsa_swparams); |
296 | |
1050 | 297 if ((err = snd_pcm_sw_params_current(alsa_handler, alsa_swparams)) < 0) |
298 { | |
299 printf("alsa-init: unable to get parameters: %s\n", | |
300 snd_strerror(err)); | |
301 return(0); | |
2209 | 302 } |
303 | |
304 if ((err = snd_pcm_sw_params_set_avail_min(alsa_handler, alsa_swparams, chunk_size)) < 0) | |
305 { | |
306 printf("alsa-init: unable to set avail_min %s\n",snd_strerror(err)); | |
307 return(0); | |
308 } | |
309 | |
310 | |
311 | |
312 if ((err = snd_pcm_sw_params_set_start_threshold(alsa_handler, alsa_swparams, start_threshold)) < 0) | |
313 { | |
314 printf("alsa-init: unable to set start_threshold %s\n",snd_strerror(err)); | |
315 return(0); | |
316 } | |
317 } | |
318 // if ((err = snd_pcm_sw_params_set_xfer_align(alsa_handler, alsa_swparams, xfer_align)) < 0) | |
319 //{ | |
320 // printf("alsa-init: unable to set xfer_align: %s\n", | |
321 // snd_strerror(err)); | |
322 // return(0); | |
323 //} | |
1050 | 324 |
1128 | 325 #ifdef set_start_mode |
1050 | 326 if ((err = snd_pcm_sw_params_set_start_mode(alsa_handler, alsa_swparams, |
327 SND_PCM_START_DATA)) < 0) | |
328 { | |
329 printf("alsa-init: unable to set start mode: %s\n", | |
330 snd_strerror(err)); | |
331 return(0); | |
332 } | |
1128 | 333 #endif |
1050 | 334 |
335 if ((err = snd_pcm_sw_params(alsa_handler, alsa_swparams)) < 0) | |
336 { | |
337 printf("alsa-init: unable to set parameters: %s\n", | |
338 snd_strerror(err)); | |
339 return(0); | |
340 } | |
341 | |
1128 | 342 // snd_pcm_sw_params_default(alsa_handler, alsa_swparams); |
343 #endif | |
1050 | 344 if ((err = snd_pcm_prepare(alsa_handler)) < 0) |
345 { | |
346 printf("alsa-init: pcm prepare error: %s\n", snd_strerror(err)); | |
347 return(0); | |
348 } | |
349 | |
1115
a16b569f2702
-Wall style cleanups, TEST IT, it can be working by others
al3x
parents:
1058
diff
changeset
|
350 #ifdef start |
1050 | 351 if ((err = snd_pcm_start(alsa_handler)) < 0) |
352 { | |
353 printf("alsa-init: pcm start error: %s\n", snd_strerror(err)); | |
354 if (err != -EPIPE) | |
355 return(0); | |
356 if ((err = snd_pcm_start(alsa_handler)) < 0) | |
357 { | |
358 printf("alsa-init: pcm start error: %s\n", snd_strerror(err)); | |
359 return(0); | |
360 } | |
361 } | |
1115
a16b569f2702
-Wall style cleanups, TEST IT, it can be working by others
al3x
parents:
1058
diff
changeset
|
362 #endif |
1128 | 363 printf("AUDIO: %d Hz/%d channels/%d bpf/%d bytes buffer/%s\n", |
3095 | 364 ao_data.samplerate, ao_data.channels, ao_data.bps, ao_data.buffersize, |
1050 | 365 snd_pcm_format_description(alsa_format)); |
366 return(1); | |
367 } | |
368 | |
369 /* close audio device */ | |
370 static void uninit() | |
371 { | |
372 int err; | |
373 | |
374 if (alsa_device != NULL) | |
375 free(alsa_device); | |
376 | |
377 snd_pcm_hw_params_free(alsa_hwparams); | |
378 snd_pcm_sw_params_free(alsa_swparams); | |
379 | |
380 if ((err = snd_pcm_drain(alsa_handler)) < 0) | |
381 { | |
382 printf("alsa-uninit: pcm drain error: %s\n", snd_strerror(err)); | |
383 return; | |
384 } | |
385 | |
1129 | 386 #ifdef start |
1050 | 387 if ((err = snd_pcm_reset(alsa_handler)) < 0) |
388 { | |
389 printf("alsa-uninit: pcm reset error: %s\n", snd_strerror(err)); | |
390 return; | |
391 } | |
1129 | 392 #endif |
1050 | 393 |
394 if ((err = snd_pcm_close(alsa_handler)) < 0) | |
395 { | |
396 printf("alsa-uninit: pcm close error: %s\n", snd_strerror(err)); | |
397 return; | |
398 } | |
399 } | |
400 | |
401 static void audio_pause() | |
402 { | |
403 int err; | |
404 | |
405 if ((err = snd_pcm_drain(alsa_handler)) < 0) | |
406 { | |
407 printf("alsa-pause: pcm drain error: %s\n", snd_strerror(err)); | |
408 return; | |
409 } | |
410 | |
1129 | 411 #ifdef reset |
1050 | 412 if ((err = snd_pcm_reset(alsa_handler)) < 0) |
413 { | |
414 printf("alsa-pause: pcm reset error: %s\n", snd_strerror(err)); | |
415 return; | |
416 } | |
1129 | 417 #endif |
1050 | 418 } |
419 | |
420 static void audio_resume() | |
421 { | |
422 int err; | |
423 | |
424 if ((err = snd_pcm_prepare(alsa_handler)) < 0) | |
425 { | |
426 printf("alsa-resume: pcm prepare error: %s\n", snd_strerror(err)); | |
427 return; | |
428 } | |
429 | |
1129 | 430 #ifdef start |
1050 | 431 if ((err = snd_pcm_start(alsa_handler)) < 0) |
432 { | |
433 printf("alsa-resume: pcm start error: %s\n", snd_strerror(err)); | |
434 return; | |
435 } | |
1129 | 436 #endif |
1050 | 437 } |
438 | |
439 /* stop playing and empty buffers (for seeking/pause) */ | |
440 static void reset() | |
441 { | |
442 int err; | |
443 | |
444 if ((err = snd_pcm_drain(alsa_handler)) < 0) | |
445 { | |
446 printf("alsa-reset: pcm drain error: %s\n", snd_strerror(err)); | |
447 return; | |
448 } | |
449 | |
1129 | 450 #ifdef start |
1050 | 451 if ((err = snd_pcm_reset(alsa_handler)) < 0) |
452 { | |
453 printf("alsa-reset: pcm reset error: %s\n", snd_strerror(err)); | |
454 return; | |
455 } | |
1129 | 456 #endif |
1050 | 457 |
458 if ((err = snd_pcm_prepare(alsa_handler)) < 0) | |
459 { | |
460 printf("alsa-reset: pcm prepare error: %s\n", snd_strerror(err)); | |
461 return; | |
462 } | |
463 | |
1129 | 464 #ifdef start |
1050 | 465 if ((err = snd_pcm_start(alsa_handler)) < 0) |
466 { | |
467 printf("alsa-reset: pcm start error: %s\n", snd_strerror(err)); | |
468 return; | |
469 } | |
1129 | 470 #endif |
1050 | 471 } |
472 | |
473 /* | |
474 plays 'len' bytes of 'data' | |
475 returns: number of bytes played | |
476 */ | |
477 static int play(void* data, int len, int flags) | |
478 { | |
1115
a16b569f2702
-Wall style cleanups, TEST IT, it can be working by others
al3x
parents:
1058
diff
changeset
|
479 int got_len; |
a16b569f2702
-Wall style cleanups, TEST IT, it can be working by others
al3x
parents:
1058
diff
changeset
|
480 |
2059 | 481 got_len = snd_pcm_writei(alsa_handler, data, len / 4); |
482 | |
3095 | 483 //if ((got_len = snd_pcm_writei(alsa_handler, data, (len/ao_data.bps))) != (len/ao_data.bps)) { |
2209 | 484 //SHOULD BE FIXED |
1115
a16b569f2702
-Wall style cleanups, TEST IT, it can be working by others
al3x
parents:
1058
diff
changeset
|
485 if (got_len == -EPIPE) /* underrun? */ |
1050 | 486 { |
487 printf("alsa-play: alsa underrun, resetting stream\n"); | |
1128 | 488 if ((got_len = snd_pcm_prepare(alsa_handler)) < 0) |
1050 | 489 { |
1128 | 490 printf("alsa-play: playback prepare error: %s\n", snd_strerror(got_len)); |
1050 | 491 return(0); |
492 } | |
3095 | 493 if ((got_len = snd_pcm_writei(alsa_handler, data, (len/ao_data.bps))) != (len/ao_data.bps)) |
1050 | 494 { |
495 printf("alsa-play: write error after reset: %s - giving up\n", | |
1128 | 496 snd_strerror(got_len)); |
1050 | 497 return(0); |
498 } | |
499 return(len); /* 2nd write was ok */ | |
500 } | |
501 return(len); | |
2209 | 502 //} |
1050 | 503 } |
504 | |
505 /* how many byes are free in the buffer */ | |
506 static int get_space() | |
507 { | |
508 snd_pcm_status_t *status; | |
509 int ret; | |
510 | |
511 if ((ret = snd_pcm_status_malloc(&status)) < 0) | |
512 { | |
513 printf("alsa-space: memory allocation error: %s\n", snd_strerror(ret)); | |
514 return(0); | |
515 } | |
516 | |
517 if ((ret = snd_pcm_status(alsa_handler, status)) < 0) | |
518 { | |
519 printf("alsa-space: cannot get pcm status: %s\n", snd_strerror(ret)); | |
520 return(0); | |
521 } | |
522 | |
523 switch(snd_pcm_status_get_state(status)) | |
524 { | |
525 case SND_PCM_STATE_OPEN: | |
526 case SND_PCM_STATE_PREPARED: | |
527 case SND_PCM_STATE_RUNNING: | |
3095 | 528 ret = snd_pcm_status_get_avail(status) * ao_data.bps; |
1050 | 529 break; |
530 default: | |
531 ret = 0; | |
532 } | |
533 | |
534 snd_pcm_status_free(status); | |
1129 | 535 |
536 if (ret < 0) | |
537 ret = 0; | |
1050 | 538 return(ret); |
539 } | |
540 | |
3095 | 541 /* delay in seconds between first and last sample in buffer */ |
542 static float get_delay() | |
1050 | 543 { |
544 snd_pcm_status_t *status; | |
3095 | 545 float ret; |
1050 | 546 |
547 if ((ret = snd_pcm_status_malloc(&status)) < 0) | |
548 { | |
549 printf("alsa-delay: memory allocation error: %s\n", snd_strerror(ret)); | |
550 return(0); | |
551 } | |
552 | |
553 if ((ret = snd_pcm_status(alsa_handler, status)) < 0) | |
554 { | |
555 printf("alsa-delay: cannot get pcm status: %s\n", snd_strerror(ret)); | |
556 return(0); | |
557 } | |
558 | |
559 switch(snd_pcm_status_get_state(status)) | |
560 { | |
561 case SND_PCM_STATE_OPEN: | |
562 case SND_PCM_STATE_PREPARED: | |
563 case SND_PCM_STATE_RUNNING: | |
3095 | 564 ret = (float)snd_pcm_status_get_delay(status)/(float)ao_data.samplerate; |
1050 | 565 break; |
566 default: | |
567 ret = 0; | |
568 } | |
569 | |
570 snd_pcm_status_free(status); | |
1129 | 571 |
572 if (ret < 0) | |
573 ret = 0; | |
1050 | 574 return(ret); |
575 } |