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