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
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>
21 #include <sys/socket.h>
34 #include "audio_out.h"
35 #include "audio_out_internal.h"
36 #include "libaf/af_format.h"
44 #define dprintf(...) printf(__VA_ARGS__)
46 #define dprintf(...) /**/
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",
57 "Juergen Keil <jk@tools.de>",
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
;
80 static time_t vol_cache_time
;
81 static ao_control_vol_t vol_cache
;
84 case AOCONTROL_GET_VOLUME
:
86 if (now
== vol_cache_time
) {
87 *(ao_control_vol_t
*)arg
= vol_cache
;
91 dprintf("esd: get vol\n");
92 if ((esd_i
= esd_get_all_info(esd_fd
)) == NULL
)
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)
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
;
105 vol_cache_time
= now
;
107 esd_free_all_info(esd_i
);
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)
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);
127 time(&vol_cache_time
);
129 esd_free_all_info(esd_i
);
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
;
147 char *server
= ao_subdevice
; /* NULL for localhost */
148 float lag_seconds
, lag_net
, lag_serv
;
149 struct timeval proto_start
, proto_end
;
152 esd_fd
= esd_open_sound(server
);
154 mp_msg(MSGT_AO
, MSGL_ERR
, MSGTR_AO_ESD_CantOpenSound
,
159 /* get server info, and measure network latency */
160 gettimeofday(&proto_start
, NULL
);
161 esd_svinfo
= esd_get_server_info(esd_fd
);
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 */
168 lag_net
= 0.0; /* no network lag */
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
;
181 /* let the esd daemon convert sample rate */
183 /* let mplayer's audio filter convert the sample rate */
184 if (esd_svinfo
!= NULL
)
185 rate_hz
= esd_svinfo
->rate
;
187 ao_data
.samplerate
= rate_hz
;
189 /* EsounD can play mono or stereo */
193 ao_data
.channels
= bytes_per_sample
= 1;
196 esd_fmt
|= ESD_STEREO
;
197 ao_data
.channels
= bytes_per_sample
= 2;
201 /* EsounD can play 8bit unsigned and 16bit signed native */
205 esd_fmt
|= ESD_BITS8
;
206 ao_data
.format
= AF_FORMAT_U8
;
209 esd_fmt
|= ESD_BITS16
;
210 ao_data
.format
= AF_FORMAT_S16_NE
;
211 bytes_per_sample
*= 2;
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
);
222 esd_latency
= ((channels
== 1 ? 2 : 1) * ESD_DEFAULT_RATE
*
223 (ESD_BUF_SIZE
+ 64 * (4.0f
/ bytes_per_sample
))
225 esd_latency
+= ESD_BUF_SIZE
* 2;
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
));
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
);
250 getsockopt(esd_play_fd
, SOL_SOCKET
, SO_SNDBUF
, &sbuf
, &len
);
252 getsockopt(esd_play_fd
, SOL_SOCKET
, SO_RCVBUF
, &rbuf
, &len
);
253 dprintf("esd: send/receive socket buffer space %d/%d bytes\n",
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
;
272 static void uninit(int immed
)
274 if (esd_play_fd
>= 0) {
275 esd_close(esd_play_fd
);
280 esd_free_server_info(esd_svinfo
);
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
)
303 /* round down buffersize to a multiple of ESD_BUF_SIZE bytes */
304 len
= len
/ ESD_BUF_SIZE
* ESD_BUF_SIZE
;
308 #define SINGLE_WRITE 0
310 nwritten
= write(esd_play_fd
, data
, len
);
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
);
319 if ( errno
!= EAGAIN
)
320 dprintf("esd play: write failed: %s\n", strerror(errno
));
322 } else if ( n
!= ESD_BUF_SIZE
) {
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
);
338 dprintf("esd play: blocked / %lu\n", esd_samples_written
);
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)
380 /* throw away data buffered in the esd connection */
381 if (ioctl(esd_play_fd
, I_FLUSH
, FLUSHW
))
388 * return: how many bytes can be played without blocking
390 static int get_space(void)
392 struct timeval tmout
;
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");
410 FD_SET(esd_play_fd
, &wfds
);
414 if (select(esd_play_fd
+ 1, NULL
, &wfds
, NULL
, &tmout
) != 1)
417 if (!FD_ISSET(esd_play_fd
, &wfds
))
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
);
432 * return: delay in seconds between first and last sample in buffer
434 static float get_delay(void)
437 double buffered_samples_time
;
440 if (!esd_play_start
.tv_sec
)
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;
457 dprintf("esd: get_delay %f\n", buffered_samples_time
- play_time
);
458 return buffered_samples_time
- play_time
;