Mercurial > mplayer.hg
annotate libao2/ao_alsa5.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 | 981a9e5118ce |
children | 91f801a94a59 |
rev | line source |
---|---|
996 | 1 /* |
1046
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
2 ao_alsa5 - ALSA-0.5.x output plugin for MPlayer |
996 | 3 |
4 (C) Alex Beregszaszi <alex@naxine.org> | |
5 | |
6 Thanks to Arpi for helping me ;) | |
7 */ | |
8 | |
9 #include <errno.h> | |
10 #include <sys/asoundlib.h> | |
11 | |
12 #include "../config.h" | |
13 | |
14 #include "audio_out.h" | |
15 #include "audio_out_internal.h" | |
1058 | 16 #include "afmt.h" |
996 | 17 |
18 extern int verbose; | |
19 | |
20 static ao_info_t info = | |
21 { | |
22 "ALSA-0.5.x audio output", | |
23 "alsa5", | |
24 "Alex Beregszaszi <alex@naxine.org>", | |
25 "" | |
26 }; | |
27 | |
28 LIBAO_EXTERN(alsa5) | |
29 | |
30 static snd_pcm_t *alsa_handler; | |
31 static snd_pcm_format_t alsa_format; | |
32 static int alsa_rate = SND_PCM_RATE_CONTINUOUS; | |
33 | |
34 /* to set/get/query special features/parameters */ | |
35 static int control(int cmd, int arg) | |
36 { | |
37 return(CONTROL_UNKNOWN); | |
38 } | |
39 | |
40 /* | |
41 open & setup audio device | |
42 return: 1=success 0=fail | |
43 */ | |
44 static int init(int rate_hz, int channels, int format, int flags) | |
45 { | |
46 int err; | |
47 int cards = -1; | |
48 snd_pcm_channel_params_t params; | |
49 snd_pcm_channel_setup_t setup; | |
50 snd_pcm_info_t info; | |
51 snd_pcm_channel_info_t chninfo; | |
52 | |
53 printf("alsa-init: requested format: %d Hz, %d channels, %s\n", rate_hz, | |
54 channels, audio_out_format_name(format)); | |
55 | |
56 alsa_handler = NULL; | |
57 | |
58 if (verbose) | |
59 printf("alsa-init: compiled for ALSA-%s (%d)\n", SND_LIB_VERSION_STR, | |
60 SND_LIB_VERSION); | |
61 | |
62 if ((cards = snd_cards()) < 0) | |
63 { | |
64 printf("alsa-init: no soundcards found\n"); | |
65 return(0); | |
66 } | |
67 | |
3095 | 68 ao_data.format = format; |
69 ao_data.channels = channels - 1; | |
70 ao_data.samplerate = rate_hz; | |
71 ao_data.bps = ao_data.samplerate*(ao_data.channels+1); | |
72 ao_data.outburst = OUTBURST; | |
73 ao_data.buffersize = 16384; | |
996 | 74 |
75 memset(&alsa_format, 0, sizeof(alsa_format)); | |
76 switch (format) | |
77 { | |
78 case AFMT_S8: | |
79 alsa_format.format = SND_PCM_SFMT_S8; | |
80 break; | |
81 case AFMT_U8: | |
82 alsa_format.format = SND_PCM_SFMT_U8; | |
83 break; | |
84 case AFMT_U16_LE: | |
85 alsa_format.format = SND_PCM_SFMT_U16_LE; | |
86 break; | |
87 case AFMT_U16_BE: | |
88 alsa_format.format = SND_PCM_SFMT_U16_BE; | |
89 break; | |
90 case AFMT_S16_LE: | |
91 alsa_format.format = SND_PCM_SFMT_S16_LE; | |
92 break; | |
93 case AFMT_S16_BE: | |
94 alsa_format.format = SND_PCM_SFMT_S16_BE; | |
95 break; | |
96 default: | |
97 alsa_format.format = SND_PCM_SFMT_MPEG; | |
98 break; | |
99 } | |
100 | |
101 switch(alsa_format.format) | |
102 { | |
103 case SND_PCM_SFMT_S16_LE: | |
104 case SND_PCM_SFMT_U16_LE: | |
3095 | 105 ao_data.bps *= 2; |
996 | 106 break; |
107 case -1: | |
108 printf("alsa-init: invalid format (%s) requested - output disabled\n", | |
109 audio_out_format_name(format)); | |
110 return(0); | |
1111 | 111 default: |
112 break; | |
996 | 113 } |
114 | |
115 switch(rate_hz) | |
116 { | |
117 case 8000: | |
118 alsa_rate = SND_PCM_RATE_8000; | |
119 break; | |
120 case 11025: | |
121 alsa_rate = SND_PCM_RATE_11025; | |
122 break; | |
123 case 16000: | |
124 alsa_rate = SND_PCM_RATE_16000; | |
125 break; | |
126 case 22050: | |
127 alsa_rate = SND_PCM_RATE_22050; | |
128 break; | |
129 case 32000: | |
130 alsa_rate = SND_PCM_RATE_32000; | |
131 break; | |
132 case 44100: | |
133 alsa_rate = SND_PCM_RATE_44100; | |
134 break; | |
135 case 48000: | |
136 alsa_rate = SND_PCM_RATE_48000; | |
137 break; | |
138 case 88200: | |
139 alsa_rate = SND_PCM_RATE_88200; | |
140 break; | |
141 case 96000: | |
142 alsa_rate = SND_PCM_RATE_96000; | |
143 break; | |
144 case 176400: | |
145 alsa_rate = SND_PCM_RATE_176400; | |
146 break; | |
147 case 192000: | |
148 alsa_rate = SND_PCM_RATE_192000; | |
149 break; | |
150 default: | |
151 alsa_rate = SND_PCM_RATE_CONTINUOUS; | |
152 break; | |
153 } | |
154 | |
3095 | 155 alsa_format.rate = ao_data.samplerate; |
156 alsa_format.voices = ao_data.channels*2; | |
996 | 157 alsa_format.interleave = 1; |
158 | |
159 if ((err = snd_pcm_open(&alsa_handler, 0, 0, SND_PCM_OPEN_PLAYBACK)) < 0) | |
160 { | |
161 printf("alsa-init: playback open error: %s\n", snd_strerror(err)); | |
162 return(0); | |
163 } | |
164 | |
165 if ((err = snd_pcm_info(alsa_handler, &info)) < 0) | |
166 { | |
167 printf("alsa-init: pcm info error: %s\n", snd_strerror(err)); | |
168 return(0); | |
169 } | |
170 | |
171 printf("alsa-init: %d soundcard%s found, using: %s\n", cards, | |
172 (cards == 1) ? "" : "s", info.name); | |
173 | |
174 if (info.flags & SND_PCM_INFO_PLAYBACK) | |
175 { | |
176 bzero(&chninfo, sizeof(chninfo)); | |
177 chninfo.channel = SND_PCM_CHANNEL_PLAYBACK; | |
178 if ((err = snd_pcm_channel_info(alsa_handler, &chninfo)) < 0) | |
179 { | |
180 printf("alsa-init: pcm channel info error: %s\n", snd_strerror(err)); | |
181 return(0); | |
182 } | |
3095 | 183 |
3087
08947e067d80
compiling under qnx, hope it works on all qnx release :)
alex
parents:
1111
diff
changeset
|
184 #ifndef __QNX__ |
996 | 185 if (chninfo.buffer_size) |
3095 | 186 ao_data.buffersize = chninfo.buffer_size; |
3087
08947e067d80
compiling under qnx, hope it works on all qnx release :)
alex
parents:
1111
diff
changeset
|
187 #endif |
3095 | 188 |
996 | 189 if (verbose) |
190 printf("alsa-init: setting preferred buffer size from driver: %d bytes\n", | |
3095 | 191 ao_data.buffersize); |
996 | 192 } |
193 | |
194 memset(¶ms, 0, sizeof(params)); | |
195 params.channel = SND_PCM_CHANNEL_PLAYBACK; | |
196 params.mode = SND_PCM_MODE_STREAM; | |
197 params.format = alsa_format; | |
198 params.start_mode = SND_PCM_START_DATA; | |
199 params.stop_mode = SND_PCM_STOP_ROLLOVER; | |
3095 | 200 params.buf.stream.queue_size = ao_data.buffersize; |
996 | 201 params.buf.stream.fill = SND_PCM_FILL_NONE; |
202 | |
203 if ((err = snd_pcm_channel_params(alsa_handler, ¶ms)) < 0) | |
204 { | |
205 printf("alsa-init: error setting parameters: %s\n", snd_strerror(err)); | |
206 return(0); | |
207 } | |
208 | |
209 memset(&setup, 0, sizeof(setup)); | |
210 setup.channel = SND_PCM_CHANNEL_PLAYBACK; | |
211 setup.mode = SND_PCM_MODE_STREAM; | |
212 setup.format = alsa_format; | |
3095 | 213 setup.buf.stream.queue_size = ao_data.buffersize; |
214 setup.msbits_per_sample = ao_data.bps; | |
996 | 215 |
216 if ((err = snd_pcm_channel_setup(alsa_handler, &setup)) < 0) | |
217 { | |
218 printf("alsa-init: error setting up channel: %s\n", snd_strerror(err)); | |
219 return(0); | |
220 } | |
221 | |
222 if ((err = snd_pcm_channel_prepare(alsa_handler, SND_PCM_CHANNEL_PLAYBACK)) < 0) | |
223 { | |
224 printf("alsa-init: channel prepare error: %s\n", snd_strerror(err)); | |
225 return(0); | |
226 } | |
227 | |
228 printf("AUDIO: %d Hz/%d channels/%d bps/%d bytes buffer/%s\n", | |
3095 | 229 ao_data.samplerate, ao_data.channels+1, ao_data.bps, ao_data.buffersize, |
996 | 230 snd_pcm_get_format_name(alsa_format.format)); |
231 return(1); | |
232 } | |
233 | |
234 /* close audio device */ | |
235 static void uninit() | |
236 { | |
1055 | 237 int err; |
238 | |
1046
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
239 if ((err = snd_pcm_playback_drain(alsa_handler)) < 0) |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
240 { |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
241 printf("alsa-uninit: playback drain error: %s\n", snd_strerror(err)); |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
242 return; |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
243 } |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
244 |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
245 if ((err = snd_pcm_channel_flush(alsa_handler, SND_PCM_CHANNEL_PLAYBACK)) < 0) |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
246 { |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
247 printf("alsa-uninit: playback flush error: %s\n", snd_strerror(err)); |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
248 return; |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
249 } |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
250 |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
251 if ((err = snd_pcm_close(alsa_handler)) < 0) |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
252 { |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
253 printf("alsa-uninit: pcm close error: %s\n", snd_strerror(err)); |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
254 return; |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
255 } |
996 | 256 } |
257 | |
258 /* stop playing and empty buffers (for seeking/pause) */ | |
259 static void reset() | |
260 { | |
261 int err; | |
262 | |
263 if ((err = snd_pcm_playback_drain(alsa_handler)) < 0) | |
264 { | |
265 printf("alsa-reset: playback drain error: %s\n", snd_strerror(err)); | |
266 return; | |
267 } | |
268 | |
269 if ((err = snd_pcm_channel_flush(alsa_handler, SND_PCM_CHANNEL_PLAYBACK)) < 0) | |
270 { | |
271 printf("alsa-reset: playback flush error: %s\n", snd_strerror(err)); | |
272 return; | |
273 } | |
274 | |
275 if ((err = snd_pcm_channel_prepare(alsa_handler, SND_PCM_CHANNEL_PLAYBACK)) < 0) | |
276 { | |
277 printf("alsa-reset: channel prepare error: %s\n", snd_strerror(err)); | |
278 return; | |
279 } | |
280 } | |
281 | |
1038
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
996
diff
changeset
|
282 /* stop playing, keep buffers (for pause) */ |
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
996
diff
changeset
|
283 static void audio_pause() |
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
996
diff
changeset
|
284 { |
1046
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
285 int err; |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
286 |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
287 if ((err = snd_pcm_playback_drain(alsa_handler)) < 0) |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
288 { |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
289 printf("alsa-pause: playback drain error: %s\n", snd_strerror(err)); |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
290 return; |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
291 } |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
292 |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
293 if ((err = snd_pcm_channel_flush(alsa_handler, SND_PCM_CHANNEL_PLAYBACK)) < 0) |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
294 { |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
295 printf("alsa-pause: playback flush error: %s\n", snd_strerror(err)); |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
296 return; |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
297 } |
1038
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
996
diff
changeset
|
298 } |
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
996
diff
changeset
|
299 |
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
996
diff
changeset
|
300 /* resume playing, after audio_pause() */ |
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
996
diff
changeset
|
301 static void audio_resume() |
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
996
diff
changeset
|
302 { |
1055 | 303 int err; |
1046
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
304 if ((err = snd_pcm_channel_prepare(alsa_handler, SND_PCM_CHANNEL_PLAYBACK)) < 0) |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
305 { |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
306 printf("alsa-resume: channel prepare error: %s\n", snd_strerror(err)); |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
307 return; |
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
308 } |
1038
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
996
diff
changeset
|
309 } |
b36fb1ae4b53
applied solaris8/netbsd/other fixes patch by J¸«ärgen Keil <jk@tools.de>
arpi_esp
parents:
996
diff
changeset
|
310 |
996 | 311 /* |
312 plays 'len' bytes of 'data' | |
313 returns: number of bytes played | |
314 */ | |
315 static int play(void* data, int len, int flags) | |
316 { | |
317 if ((len = snd_pcm_write(alsa_handler, data, len)) != len) | |
318 { | |
319 if (len == -EPIPE) /* underrun? */ | |
320 { | |
321 printf("alsa-play: alsa underrun, resetting stream\n"); | |
322 if ((len = snd_pcm_channel_prepare(alsa_handler, SND_PCM_CHANNEL_PLAYBACK)) < 0) | |
323 { | |
324 printf("alsa-play: playback prepare error: %s\n", snd_strerror(len)); | |
325 return(0); | |
326 } | |
327 if ((len = snd_pcm_write(alsa_handler, data, len)) != len) | |
328 { | |
329 printf("alsa-play: write error after reset: %s - giving up\n", | |
330 snd_strerror(len)); | |
331 return(0); | |
332 } | |
333 return(len); /* 2nd write was ok */ | |
334 } | |
335 printf("alsa-play: output error: %s\n", snd_strerror(len)); | |
336 } | |
337 return(len); | |
338 } | |
339 | |
340 /* how many byes are free in the buffer */ | |
341 static int get_space() | |
342 { | |
343 snd_pcm_channel_status_t ch_stat; | |
344 | |
345 ch_stat.channel = SND_PCM_CHANNEL_PLAYBACK; | |
346 | |
347 if (snd_pcm_channel_status(alsa_handler, &ch_stat) < 0) | |
1046
59fc1f75e486
audio_pause/resume implementacio es kozmetikai valtoztatasok
al3x
parents:
1038
diff
changeset
|
348 return(0); /* error occured */ |
996 | 349 else |
350 return(ch_stat.free); | |
351 } | |
352 | |
3095 | 353 /* delay in seconds between first and last sample in buffer */ |
354 static float get_delay() | |
996 | 355 { |
356 snd_pcm_channel_status_t ch_stat; | |
357 | |
358 ch_stat.channel = SND_PCM_CHANNEL_PLAYBACK; | |
359 | |
360 if (snd_pcm_channel_status(alsa_handler, &ch_stat) < 0) | |
3095 | 361 return((float)ao_data.buffersize/(float)ao_data.bps); /* error occured */ |
996 | 362 else |
3095 | 363 return((float)ch_stat.count/(float)ao_data.bps); |
996 | 364 } |