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