Add explanatory comments to the #endif part of multiple inclusion guards.
[mplayer/greg.git] / libao2 / ao_esd.c
blob83b52093d930f29a8366d2ad33cb265ee2966592
1 /*
2 * ao_esd - EsounD audio output driver for MPlayer
4 * Juergen Keil <jk@tools.de>
6 * This driver is distributed under the terms of the GPL
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)
19 #include <sys/types.h>
20 #include <sys/time.h>
21 #include <sys/socket.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <fcntl.h>
27 #include <time.h>
28 #ifdef __svr4__
29 #include <stropts.h>
30 #endif
31 #include <esd.h>
33 #include "config.h"
34 #include "audio_out.h"
35 #include "audio_out_internal.h"
36 #include "libaf/af_format.h"
37 #include "mp_msg.h"
38 #include "help_mp.h"
41 #undef ESD_DEBUG
43 #if ESD_DEBUG
44 #define dprintf(...) printf(__VA_ARGS__)
45 #else
46 #define dprintf(...) /**/
47 #endif
50 #define ESD_CLIENT_NAME "MPlayer"
51 #define ESD_MAX_DELAY (1.0f) /* max amount of data buffered in esd (#sec) */
53 static ao_info_t info =
55 "EsounD audio output",
56 "esd",
57 "Juergen Keil <jk@tools.de>",
61 LIBAO_EXTERN(esd)
63 static int esd_fd = -1;
64 static int esd_play_fd = -1;
65 static esd_server_info_t *esd_svinfo;
66 static int esd_latency;
67 static int esd_bytes_per_sample;
68 static unsigned long esd_samples_written;
69 static struct timeval esd_play_start;
70 extern float audio_delay;
73 * to set/get/query special features/parameters
75 static int control(int cmd, void *arg)
77 esd_player_info_t *esd_pi;
78 esd_info_t *esd_i;
79 time_t now;
80 static time_t vol_cache_time;
81 static ao_control_vol_t vol_cache;
83 switch (cmd) {
84 case AOCONTROL_GET_VOLUME:
85 time(&now);
86 if (now == vol_cache_time) {
87 *(ao_control_vol_t *)arg = vol_cache;
88 return CONTROL_OK;
91 dprintf("esd: get vol\n");
92 if ((esd_i = esd_get_all_info(esd_fd)) == NULL)
93 return CONTROL_ERROR;
95 for (esd_pi = esd_i->player_list; esd_pi != NULL; esd_pi = esd_pi->next)
96 if (strcmp(esd_pi->name, ESD_CLIENT_NAME) == 0)
97 break;
99 if (esd_pi != NULL) {
100 ao_control_vol_t *vol = (ao_control_vol_t *)arg;
101 vol->left = esd_pi->left_vol_scale * 100 / ESD_VOLUME_BASE;
102 vol->right = esd_pi->right_vol_scale * 100 / ESD_VOLUME_BASE;
104 vol_cache = *vol;
105 vol_cache_time = now;
107 esd_free_all_info(esd_i);
109 return CONTROL_OK;
111 case AOCONTROL_SET_VOLUME:
112 dprintf("esd: set vol\n");
113 if ((esd_i = esd_get_all_info(esd_fd)) == NULL)
114 return CONTROL_ERROR;
116 for (esd_pi = esd_i->player_list; esd_pi != NULL; esd_pi = esd_pi->next)
117 if (strcmp(esd_pi->name, ESD_CLIENT_NAME) == 0)
118 break;
120 if (esd_pi != NULL) {
121 ao_control_vol_t *vol = (ao_control_vol_t *)arg;
122 esd_set_stream_pan(esd_fd, esd_pi->source_id,
123 vol->left * ESD_VOLUME_BASE / 100,
124 vol->right * ESD_VOLUME_BASE / 100);
126 vol_cache = *vol;
127 time(&vol_cache_time);
129 esd_free_all_info(esd_i);
130 return CONTROL_OK;
132 default:
133 return CONTROL_UNKNOWN;
139 * open & setup audio device
140 * return: 1=success 0=fail
142 static int init(int rate_hz, int channels, int format, int flags)
144 esd_format_t esd_fmt;
145 int bytes_per_sample;
146 int fl;
147 char *server = ao_subdevice; /* NULL for localhost */
148 float lag_seconds, lag_net, lag_serv;
149 struct timeval proto_start, proto_end;
151 if (esd_fd < 0) {
152 esd_fd = esd_open_sound(server);
153 if (esd_fd < 0) {
154 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ESD_CantOpenSound,
155 strerror(errno));
156 return 0;
159 /* get server info, and measure network latency */
160 gettimeofday(&proto_start, NULL);
161 esd_svinfo = esd_get_server_info(esd_fd);
162 if(server) {
163 gettimeofday(&proto_end, NULL);
164 lag_net = (proto_end.tv_sec - proto_start.tv_sec) +
165 (proto_end.tv_usec - proto_start.tv_usec) / 1000000.0;
166 lag_net /= 2.0; /* round trip -> one way */
167 } else
168 lag_net = 0.0; /* no network lag */
171 if (esd_svinfo) {
172 mp_msg(MSGT_AO, MSGL_INFO, "AO: [esd] server info:\n");
173 esd_print_server_info(esd_svinfo);
178 esd_fmt = ESD_STREAM | ESD_PLAY;
180 #if ESD_RESAMPLES
181 /* let the esd daemon convert sample rate */
182 #else
183 /* let mplayer's audio filter convert the sample rate */
184 if (esd_svinfo != NULL)
185 rate_hz = esd_svinfo->rate;
186 #endif
187 ao_data.samplerate = rate_hz;
189 /* EsounD can play mono or stereo */
190 switch (channels) {
191 case 1:
192 esd_fmt |= ESD_MONO;
193 ao_data.channels = bytes_per_sample = 1;
194 break;
195 default:
196 esd_fmt |= ESD_STEREO;
197 ao_data.channels = bytes_per_sample = 2;
198 break;
201 /* EsounD can play 8bit unsigned and 16bit signed native */
202 switch (format) {
203 case AF_FORMAT_S8:
204 case AF_FORMAT_U8:
205 esd_fmt |= ESD_BITS8;
206 ao_data.format = AF_FORMAT_U8;
207 break;
208 default:
209 esd_fmt |= ESD_BITS16;
210 ao_data.format = AF_FORMAT_S16_NE;
211 bytes_per_sample *= 2;
212 break;
215 /* modify audio_delay depending on esd_latency
216 * latency is number of samples @ 44.1khz stereo 16 bit
217 * adjust according to rate_hz & bytes_per_sample
219 #ifdef HAVE_ESD_LATENCY
220 esd_latency = esd_get_latency(esd_fd);
221 #else
222 esd_latency = ((channels == 1 ? 2 : 1) * ESD_DEFAULT_RATE *
223 (ESD_BUF_SIZE + 64 * (4.0f / bytes_per_sample))
224 ) / rate_hz;
225 esd_latency += ESD_BUF_SIZE * 2;
226 #endif
227 if(esd_latency > 0) {
228 lag_serv = (esd_latency * 4.0f) / (bytes_per_sample * rate_hz);
229 lag_seconds = lag_net + lag_serv;
230 audio_delay += lag_seconds;
231 mp_msg(MSGT_AO, MSGL_INFO,MSGTR_AO_ESD_LatencyInfo,
232 lag_serv, lag_net, lag_seconds);
235 esd_play_fd = esd_play_stream_fallback(esd_fmt, rate_hz,
236 server, ESD_CLIENT_NAME);
237 if (esd_play_fd < 0) {
238 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ESD_CantOpenPBStream, strerror(errno));
239 return 0;
242 /* enable non-blocking i/o on the socket connection to the esd server */
243 if ((fl = fcntl(esd_play_fd, F_GETFL)) >= 0)
244 fcntl(esd_play_fd, F_SETFL, O_NDELAY|fl);
246 #if ESD_DEBUG
248 int sbuf, rbuf, len;
249 len = sizeof(sbuf);
250 getsockopt(esd_play_fd, SOL_SOCKET, SO_SNDBUF, &sbuf, &len);
251 len = sizeof(rbuf);
252 getsockopt(esd_play_fd, SOL_SOCKET, SO_RCVBUF, &rbuf, &len);
253 dprintf("esd: send/receive socket buffer space %d/%d bytes\n",
254 sbuf, rbuf);
256 #endif
258 ao_data.bps = bytes_per_sample * rate_hz;
259 ao_data.outburst = ao_data.bps > 100000 ? 4*ESD_BUF_SIZE : 2*ESD_BUF_SIZE;
261 esd_play_start.tv_sec = 0;
262 esd_samples_written = 0;
263 esd_bytes_per_sample = bytes_per_sample;
265 return 1;
270 * close audio device
272 static void uninit(int immed)
274 if (esd_play_fd >= 0) {
275 esd_close(esd_play_fd);
276 esd_play_fd = -1;
279 if (esd_svinfo) {
280 esd_free_server_info(esd_svinfo);
281 esd_svinfo = NULL;
284 if (esd_fd >= 0) {
285 esd_close(esd_fd);
286 esd_fd = -1;
292 * plays 'len' bytes of 'data'
293 * it should round it down to outburst*n
294 * return: number of bytes played
296 static int play(void* data, int len, int flags)
298 int offs;
299 int nwritten;
300 int nsamples;
301 int n;
303 /* round down buffersize to a multiple of ESD_BUF_SIZE bytes */
304 len = len / ESD_BUF_SIZE * ESD_BUF_SIZE;
305 if (len <= 0)
306 return 0;
308 #define SINGLE_WRITE 0
309 #if SINGLE_WRITE
310 nwritten = write(esd_play_fd, data, len);
311 #else
312 for (offs = 0, nwritten=0; offs + ESD_BUF_SIZE <= len; offs += ESD_BUF_SIZE) {
314 * note: we're writing to a non-blocking socket here.
315 * A partial write means, that the socket buffer is full.
317 n = write(esd_play_fd, (char*)data + offs, ESD_BUF_SIZE);
318 if ( n < 0 ) {
319 if ( errno != EAGAIN )
320 dprintf("esd play: write failed: %s\n", strerror(errno));
321 break;
322 } else if ( n != ESD_BUF_SIZE ) {
323 nwritten += n;
324 break;
325 } else
326 nwritten += n;
328 #endif
330 if (nwritten > 0) {
331 if (!esd_play_start.tv_sec)
332 gettimeofday(&esd_play_start, NULL);
333 nsamples = nwritten / esd_bytes_per_sample;
334 esd_samples_written += nsamples;
336 dprintf("esd play: %d %lu\n", nsamples, esd_samples_written);
337 } else {
338 dprintf("esd play: blocked / %lu\n", esd_samples_written);
341 return nwritten;
346 * stop playing, keep buffers (for pause)
348 static void audio_pause(void)
351 * not possible with esd. the esd daemom will continue playing
352 * buffered data (not more than ESD_MAX_DELAY seconds of samples)
358 * resume playing, after audio_pause()
360 static void audio_resume(void)
363 * not possible with esd.
365 * Let's hope the pause was long enough that the esd ran out of
366 * buffered data; we restart our time based delay computation
367 * for an audio resume.
369 esd_play_start.tv_sec = 0;
370 esd_samples_written = 0;
375 * stop playing and empty buffers (for seeking/pause)
377 static void reset(void)
379 #ifdef __svr4__
380 /* throw away data buffered in the esd connection */
381 if (ioctl(esd_play_fd, I_FLUSH, FLUSHW))
382 perror("I_FLUSH");
383 #endif
388 * return: how many bytes can be played without blocking
390 static int get_space(void)
392 struct timeval tmout;
393 fd_set wfds;
394 float current_delay;
395 int space;
398 * Don't buffer too much data in the esd daemon.
400 * If we send too much, esd will block in write()s to the sound
401 * device, and the consequence is a huge slow down for things like
402 * esd_get_all_info().
404 if ((current_delay = get_delay()) >= ESD_MAX_DELAY) {
405 dprintf("esd get_space: too much data buffered\n");
406 return 0;
409 FD_ZERO(&wfds);
410 FD_SET(esd_play_fd, &wfds);
411 tmout.tv_sec = 0;
412 tmout.tv_usec = 0;
414 if (select(esd_play_fd + 1, NULL, &wfds, NULL, &tmout) != 1)
415 return 0;
417 if (!FD_ISSET(esd_play_fd, &wfds))
418 return 0;
420 /* try to fill 50% of the remaining "free" buffer space */
421 space = (ESD_MAX_DELAY - current_delay) * ao_data.bps * 0.5f;
423 /* round up to next multiple of ESD_BUF_SIZE */
424 space = (space + ESD_BUF_SIZE-1) / ESD_BUF_SIZE * ESD_BUF_SIZE;
426 dprintf("esd get_space: %d\n", space);
427 return space;
432 * return: delay in seconds between first and last sample in buffer
434 static float get_delay(void)
436 struct timeval now;
437 double buffered_samples_time;
438 double play_time;
440 if (!esd_play_start.tv_sec)
441 return 0;
443 buffered_samples_time = (float)esd_samples_written / ao_data.samplerate;
444 gettimeofday(&now, NULL);
445 play_time = now.tv_sec - esd_play_start.tv_sec;
446 play_time += (now.tv_usec - esd_play_start.tv_usec) / 1000000.;
448 /* dprintf("esd delay: %f %f\n", play_time, buffered_samples_time); */
450 if (play_time > buffered_samples_time) {
451 dprintf("esd: underflow\n");
452 esd_play_start.tv_sec = 0;
453 esd_samples_written = 0;
454 return 0;
457 dprintf("esd: get_delay %f\n", buffered_samples_time - play_time);
458 return buffered_samples_time - play_time;