comparison libao2/ao_esd.c @ 8572:46dbfa8c1999

new EsounD audio driver (-ao esd)
author jkeil
date Fri, 27 Dec 2002 16:02:57 +0000
parents
children 440301fef3fe
comparison
equal deleted inserted replaced
8571:3a12d4e79322 8572:46dbfa8c1999
1 /*
2 * ao_esd - EsounD audio output driver for MPlayer
3 *
4 * Juergen Keil <jk@tools.de>
5 *
6 * This driver is distributed under the terms of the GPL
7 *
8 * TODO / known problems:
9 * - does not work well when the esd daemon has autostandby disabled
10 * (workaround: run esd with option "-as 2" - fortunatelly this is
11 * the default)
12 * - plays noise on a linux 2.4.4 kernel with a SB16PCI card, when using
13 * a local tcp connection to the esd daemon; there is no noise when using
14 * a unix domain socket connection.
15 * (there are EIO errors reported by the sound card driver, so this is
16 * most likely a linux sound card driver problem)
17 */
18
19 #include "../config.h"
20
21 #include <sys/types.h>
22 #include <sys/time.h>
23 #include <sys/socket.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <errno.h>
28 #include <fcntl.h>
29 #ifdef __svr4__
30 #include <stropts.h>
31 #endif
32 #include <esd.h>
33
34 #include "audio_out.h"
35 #include "audio_out_internal.h"
36 #include "afmt.h"
37 #include "../config.h"
38 #include "../mp_msg.h"
39
40
41 #undef ESD_DEBUG
42
43 #if ESD_DEBUG
44 #define dprintf(...) printf(__VA_ARGS__)
45 #else
46 #define dprintf(...) /**/
47 #endif
48
49
50 #define ESD_CLIENT_NAME "MPlayer"
51 #define ESD_MAX_DELAY (1.0f) /* max amount of data buffered in esd (#sec) */
52
53
54 static ao_info_t info =
55 {
56 "EsounD audio output",
57 "esd",
58 "Juergen Keil <jk@tools.de>",
59 ""
60 };
61
62 LIBAO_EXTERN(esd)
63
64 static int esd_fd = -1;
65 static int esd_play_fd = -1;
66 static esd_server_info_t *esd_svinfo;
67 static int esd_latency;
68 static int esd_bytes_per_sample;
69 static unsigned long esd_samples_written;
70 static struct timeval esd_play_start;
71
72
73 /*
74 * to set/get/query special features/parameters
75 */
76 static int control(int cmd, int arg)
77 {
78 esd_player_info_t *esd_pi;
79 esd_info_t *esd_i;
80 time_t now;
81 static time_t vol_cache_time;
82 static ao_control_vol_t vol_cache;
83
84 switch (cmd) {
85 case AOCONTROL_GET_VOLUME:
86 time(&now);
87 if (now == vol_cache_time) {
88 *(ao_control_vol_t *)arg = vol_cache;
89 return CONTROL_OK;
90 }
91
92 dprintf("esd: get vol\n");
93 if ((esd_i = esd_get_all_info(esd_fd)) == NULL)
94 return CONTROL_ERROR;
95
96 for (esd_pi = esd_i->player_list; esd_pi != NULL; esd_pi = esd_pi->next)
97 if (strcmp(esd_pi->name, ESD_CLIENT_NAME) == 0)
98 break;
99
100 if (esd_pi != NULL) {
101 ao_control_vol_t *vol = (ao_control_vol_t *)arg;
102 vol->left = esd_pi->left_vol_scale * 100 / ESD_VOLUME_BASE;
103 vol->right = esd_pi->right_vol_scale * 100 / ESD_VOLUME_BASE;
104
105 vol_cache = *vol;
106 vol_cache_time = now;
107 }
108 esd_free_all_info(esd_i);
109
110 return CONTROL_OK;
111
112 case AOCONTROL_SET_VOLUME:
113 dprintf("esd: set vol\n");
114 if ((esd_i = esd_get_all_info(esd_fd)) == NULL)
115 return CONTROL_ERROR;
116
117 for (esd_pi = esd_i->player_list; esd_pi != NULL; esd_pi = esd_pi->next)
118 if (strcmp(esd_pi->name, ESD_CLIENT_NAME) == 0)
119 break;
120
121 if (esd_pi != NULL) {
122 ao_control_vol_t *vol = (ao_control_vol_t *)arg;
123 esd_set_stream_pan(esd_fd, esd_pi->source_id,
124 vol->left * ESD_VOLUME_BASE / 100,
125 vol->right * ESD_VOLUME_BASE / 100);
126
127 vol_cache = *vol;
128 time(&vol_cache_time);
129 }
130 esd_free_all_info(esd_i);
131 return CONTROL_OK;
132
133 default:
134 return CONTROL_UNKNOWN;
135 }
136 }
137
138
139 /*
140 * open & setup audio device
141 * return: 1=success 0=fail
142 */
143 static int init(int rate_hz, int channels, int format, int flags)
144 {
145 esd_format_t esd_fmt;
146 int bytes_per_sample;
147 int fl;
148
149 if (esd_fd < 0) {
150 esd_fd = esd_open_sound(NULL);
151 if (esd_fd < 0) {
152 mp_msg(MSGT_AO, MSGL_ERR, "AO: [esd] esd_open_sound failed: %s\n",
153 strerror(errno));
154 return 0;
155 }
156
157 esd_svinfo = esd_get_server_info(esd_fd);
158 /*
159 if (esd_svinfo) {
160 mp_msg(MSGT_AO, MSGL_INFO, "AO: [esd] server info:\n");
161 esd_print_server_info(esd_svinfo);
162 }
163 */
164
165 esd_latency = esd_get_latency(esd_fd);
166 /* mp_msg(MSGT_AO, MSGL_INFO, "AO: [esd] latency: %d\n", esd_latency); */
167 }
168
169 esd_fmt = ESD_STREAM | ESD_PLAY;
170
171 #if ESD_RESAMPLES
172 /* let the esd daemon convert sample rate */
173 #else
174 /* let mplayer's audio filter convert the sample rate */
175 if (esd_svinfo != NULL)
176 rate_hz = esd_svinfo->rate;
177 #endif
178 ao_data.samplerate = rate_hz;
179
180
181 /* EsounD can play mono or stereo */
182 switch (channels) {
183 case 1:
184 esd_fmt |= ESD_MONO;
185 ao_data.channels = bytes_per_sample = 1;
186 break;
187 default:
188 esd_fmt |= ESD_STEREO;
189 ao_data.channels = bytes_per_sample = 2;
190 break;
191 }
192
193 /* EsounD can play 8bit unsigned and 16bit signed native */
194 switch (format) {
195 case AFMT_S8:
196 case AFMT_U8:
197 esd_fmt |= ESD_BITS8;
198 ao_data.format = AFMT_U8;
199 break;
200 default:
201 esd_fmt |= ESD_BITS16;
202 ao_data.format = AFMT_S16_NE;
203 bytes_per_sample *= 2;
204 break;
205 }
206
207 esd_play_fd = esd_play_stream_fallback(esd_fmt, rate_hz,
208 NULL, ESD_CLIENT_NAME);
209 if (esd_play_fd < 0) {
210 mp_msg(MSGT_AO, MSGL_ERR,
211 "AO: [esd] failed to open esd playback stream: %s\n",
212 strerror(errno));
213 return 0;
214 }
215
216 /* enable non-blocking i/o on the socket connection to the esd server */
217 if ((fl = fcntl(esd_play_fd, F_GETFL)) >= 0)
218 fcntl(esd_play_fd, F_SETFL, O_NDELAY|fl);
219
220 #if ESD_DEBUG
221 {
222 int sbuf, rbuf, len;
223 len = sizeof(sbuf);
224 getsockopt(esd_play_fd, SOL_SOCKET, SO_SNDBUF, &sbuf, &len);
225 len = sizeof(rbuf);
226 getsockopt(esd_play_fd, SOL_SOCKET, SO_RCVBUF, &rbuf, &len);
227 dprintf("esd: send/receive socket buffer space %d/%d bytes\n",
228 sbuf, rbuf);
229 }
230 #endif
231
232 ao_data.bps = bytes_per_sample * rate_hz;
233 ao_data.outburst = ao_data.bps > 100000 ? 4*ESD_BUF_SIZE : 2*ESD_BUF_SIZE;
234
235 esd_play_start.tv_sec = 0;
236 esd_samples_written = 0;
237 esd_bytes_per_sample = bytes_per_sample;
238
239 return 1;
240 }
241
242
243 /*
244 * close audio device
245 */
246 static void uninit()
247 {
248 if (esd_play_fd >= 0) {
249 esd_close(esd_play_fd);
250 esd_play_fd = -1;
251 }
252
253 if (esd_svinfo) {
254 esd_free_server_info(esd_svinfo);
255 esd_svinfo = NULL;
256 }
257
258 if (esd_fd >= 0) {
259 esd_close(esd_fd);
260 esd_fd = -1;
261 }
262 }
263
264
265 /*
266 * plays 'len' bytes of 'data'
267 * it should round it down to outburst*n
268 * return: number of bytes played
269 */
270 static int play(void* data, int len, int flags)
271 {
272 int offs;
273 int nwritten;
274 int nsamples;
275 int remainder, n;
276 int saved_fl;
277
278 /* round down buffersize to a multiple of ESD_BUF_SIZE bytes */
279 len = len / ESD_BUF_SIZE * ESD_BUF_SIZE;
280 if (len <= 0)
281 return 0;
282
283 #define SINGLE_WRITE 0
284 #if SINGLE_WRITE
285 nwritten = write(esd_play_fd, data, len);
286 #else
287 for (offs = 0; offs + ESD_BUF_SIZE <= len; offs += ESD_BUF_SIZE) {
288 /*
289 * note: we're writing to a non-blocking socket here.
290 * A partial write means, that the socket buffer is full.
291 */
292 nwritten = write(esd_play_fd, (char*)data + offs, ESD_BUF_SIZE);
293 if (nwritten != ESD_BUF_SIZE) {
294 if (nwritten < 0 && errno != EAGAIN) {
295 dprintf("esd play: write failed: %s\n", strerror(errno));
296 }
297 break;
298 }
299 }
300 nwritten = offs;
301 #endif
302
303 if (nwritten > 0 && nwritten % ESD_BUF_SIZE != 0) {
304
305 /*
306 * partial write of an audio block of ESD_BUF_SIZE bytes.
307 *
308 * Send the remainder of that block as well; this avoids a busy
309 * polling loop in the esd daemon, which waits for the rest of
310 * the incomplete block using reads from a non-blocking
311 * socket. This busy polling loop wastes CPU cycles on the
312 * esd server machine, and we're trying to avoid that.
313 * (esd 0.2.28+ has the busy polling read loop, 0.2.22 inserts
314 * 0 samples which is bad as well)
315 *
316 * Let's hope the blocking write does not consume too much time.
317 *
318 * (fortunatelly, this piece of code is not used when playing
319 * sound on the local machine - on solaris at least)
320 */
321 remainder = ESD_BUF_SIZE - nwritten % ESD_BUF_SIZE;
322 dprintf("esd play: partial audio block written, remainder %d \n",
323 remainder);
324
325 /* blocking write of remaining bytes for the partial audio block */
326 saved_fl = fcntl(esd_play_fd, F_GETFL);
327 fcntl(esd_play_fd, F_SETFL, saved_fl & ~O_NDELAY);
328 n = write(esd_play_fd, (char *)data + nwritten, remainder);
329 fcntl(esd_play_fd, F_SETFL, saved_fl);
330
331 if (n != remainder) {
332 mp_msg(MSGT_AO, MSGL_ERR,
333 "AO: [esd] send remainer of audio block failed, %d/%d\n",
334 n, remainder);
335 } else
336 nwritten += n;
337 }
338
339 if (nwritten > 0) {
340 if (!esd_play_start.tv_sec)
341 gettimeofday(&esd_play_start, NULL);
342 nsamples = nwritten / esd_bytes_per_sample;
343 esd_samples_written += nsamples;
344
345 dprintf("esd play: %d %lu\n", nsamples, esd_samples_written);
346 } else {
347 dprintf("esd play: blocked / %lu\n", esd_samples_written);
348 }
349
350 return nwritten;
351 }
352
353
354 /*
355 * stop playing, keep buffers (for pause)
356 */
357 static void audio_pause()
358 {
359 /*
360 * not possible with esd. the esd daemom will continue playing
361 * buffered data (not more than ESD_MAX_DELAY seconds of samples)
362 */
363 }
364
365
366 /*
367 * resume playing, after audio_pause()
368 */
369 static void audio_resume()
370 {
371 /*
372 * not possible with esd.
373 *
374 * Let's hope the pause was long enough that the esd ran out of
375 * buffered data; we restart our time based delay computation
376 * for an audio resume.
377 */
378 esd_play_start.tv_sec = 0;
379 esd_samples_written = 0;
380 }
381
382
383 /*
384 * stop playing and empty buffers (for seeking/pause)
385 */
386 static void reset()
387 {
388 #ifdef __svr4__
389 /* throw away data buffered in the esd connection */
390 if (ioctl(esd_play_fd, I_FLUSH, FLUSHW))
391 perror("I_FLUSH");
392 #endif
393 }
394
395
396 /*
397 * return: how many bytes can be played without blocking
398 */
399 static int get_space()
400 {
401 struct timeval tmout;
402 fd_set wfds;
403 float current_delay;
404 int space;
405
406 /*
407 * Don't buffer too much data in the esd daemon.
408 *
409 * If we send too much, esd will block in write()s to the sound
410 * device, and the consequence is a huge slow down for things like
411 * esd_get_all_info().
412 */
413 if ((current_delay = get_delay()) >= ESD_MAX_DELAY) {
414 dprintf("esd get_space: too much data buffered\n");
415 return 0;
416 }
417
418 FD_ZERO(&wfds);
419 FD_SET(esd_play_fd, &wfds);
420 tmout.tv_sec = 0;
421 tmout.tv_usec = 0;
422
423 if (select(esd_play_fd + 1, NULL, &wfds, NULL, &tmout) != 1)
424 return 0;
425
426 if (!FD_ISSET(esd_play_fd, &wfds))
427 return 0;
428
429 /* try to fill 50% of the remaining "free" buffer space */
430 space = (ESD_MAX_DELAY - current_delay) * ao_data.bps * 0.5f;
431
432 /* round up to next multiple of ESD_BUF_SIZE */
433 space = (space + ESD_BUF_SIZE-1) / ESD_BUF_SIZE * ESD_BUF_SIZE;
434
435 dprintf("esd get_space: %d\n", space);
436 return space;
437 }
438
439
440 /*
441 * return: delay in seconds between first and last sample in buffer
442 */
443 static float get_delay()
444 {
445 struct timeval now;
446 double buffered_samples_time;
447 double play_time;
448
449 if (!esd_play_start.tv_sec)
450 return 0;
451
452 buffered_samples_time = (float)esd_samples_written / ao_data.samplerate;
453 gettimeofday(&now, NULL);
454 play_time = now.tv_sec - esd_play_start.tv_sec;
455 play_time += (now.tv_usec - esd_play_start.tv_usec) / 1000000.;
456
457 /* dprintf("esd delay: %f %f\n", play_time, buffered_samples_time); */
458
459 if (play_time > buffered_samples_time) {
460 dprintf("esd: underflow\n");
461 esd_play_start.tv_sec = 0;
462 esd_samples_written = 0;
463 return 0;
464 }
465
466 dprintf("esd: get_delay %f\n", buffered_samples_time - play_time);
467 return buffered_samples_time - play_time;
468 }