2 * EsounD audio output driver for MPlayer
4 * copyright (c) 2002 Juergen Keil <jk@tools.de>
6 * This file is part of MPlayer.
8 * MPlayer is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * MPlayer is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * TODO / known problems:
25 * - does not work well when the esd daemon has autostandby disabled
26 * (workaround: run esd with option "-as 2" - fortunatelly this is
28 * - plays noise on a linux 2.4.4 kernel with a SB16PCI card, when using
29 * a local tcp connection to the esd daemon; there is no noise when using
30 * a unix domain socket connection.
31 * (there are EIO errors reported by the sound card driver, so this is
32 * most likely a linux sound card driver problem)
35 #include <sys/types.h>
37 #include <sys/socket.h>
50 #include "audio_out.h"
51 #include "audio_out_internal.h"
52 #include "libaf/af_format.h"
57 #define ESD_RESAMPLES 0
61 #define dprintf(...) printf(__VA_ARGS__)
63 #define dprintf(...) /**/
67 #define ESD_CLIENT_NAME "MPlayer"
68 #define ESD_MAX_DELAY (1.0f) /* max amount of data buffered in esd (#sec) */
70 static const ao_info_t info
=
72 "EsounD audio output",
74 "Juergen Keil <jk@tools.de>",
80 static int esd_fd
= -1;
81 static int esd_play_fd
= -1;
82 static esd_server_info_t
*esd_svinfo
;
83 static int esd_latency
;
84 static int esd_bytes_per_sample
;
85 static unsigned long esd_samples_written
;
86 static struct timeval esd_play_start
;
87 extern float audio_delay
;
90 * to set/get/query special features/parameters
92 static int control(int cmd
, void *arg
)
94 esd_player_info_t
*esd_pi
;
97 static time_t vol_cache_time
;
98 static ao_control_vol_t vol_cache
;
101 case AOCONTROL_GET_VOLUME
:
103 if (now
== vol_cache_time
) {
104 *(ao_control_vol_t
*)arg
= vol_cache
;
108 dprintf("esd: get vol\n");
109 if ((esd_i
= esd_get_all_info(esd_fd
)) == NULL
)
110 return CONTROL_ERROR
;
112 for (esd_pi
= esd_i
->player_list
; esd_pi
!= NULL
; esd_pi
= esd_pi
->next
)
113 if (strcmp(esd_pi
->name
, ESD_CLIENT_NAME
) == 0)
116 if (esd_pi
!= NULL
) {
117 ao_control_vol_t
*vol
= (ao_control_vol_t
*)arg
;
118 vol
->left
= esd_pi
->left_vol_scale
* 100 / ESD_VOLUME_BASE
;
119 vol
->right
= esd_pi
->right_vol_scale
* 100 / ESD_VOLUME_BASE
;
122 vol_cache_time
= now
;
124 esd_free_all_info(esd_i
);
128 case AOCONTROL_SET_VOLUME
:
129 dprintf("esd: set vol\n");
130 if ((esd_i
= esd_get_all_info(esd_fd
)) == NULL
)
131 return CONTROL_ERROR
;
133 for (esd_pi
= esd_i
->player_list
; esd_pi
!= NULL
; esd_pi
= esd_pi
->next
)
134 if (strcmp(esd_pi
->name
, ESD_CLIENT_NAME
) == 0)
137 if (esd_pi
!= NULL
) {
138 ao_control_vol_t
*vol
= (ao_control_vol_t
*)arg
;
139 esd_set_stream_pan(esd_fd
, esd_pi
->source_id
,
140 vol
->left
* ESD_VOLUME_BASE
/ 100,
141 vol
->right
* ESD_VOLUME_BASE
/ 100);
144 time(&vol_cache_time
);
146 esd_free_all_info(esd_i
);
150 return CONTROL_UNKNOWN
;
156 * open & setup audio device
157 * return: 1=success 0=fail
159 static int init(int rate_hz
, int channels
, int format
, int flags
)
161 esd_format_t esd_fmt
;
162 int bytes_per_sample
;
164 char *server
= ao_subdevice
; /* NULL for localhost */
165 float lag_seconds
, lag_net
, lag_serv
;
166 struct timeval proto_start
, proto_end
;
169 esd_fd
= esd_open_sound(server
);
171 mp_tmsg(MSGT_AO
, MSGL_ERR
, "[AO ESD] esd_open_sound failed: %s\n",
176 /* get server info, and measure network latency */
177 gettimeofday(&proto_start
, NULL
);
178 esd_svinfo
= esd_get_server_info(esd_fd
);
180 gettimeofday(&proto_end
, NULL
);
181 lag_net
= (proto_end
.tv_sec
- proto_start
.tv_sec
) +
182 (proto_end
.tv_usec
- proto_start
.tv_usec
) / 1000000.0;
183 lag_net
/= 2.0; /* round trip -> one way */
185 lag_net
= 0.0; /* no network lag */
189 mp_msg(MSGT_AO, MSGL_INFO, "AO: [esd] server info:\n");
190 esd_print_server_info(esd_svinfo);
195 esd_fmt
= ESD_STREAM
| ESD_PLAY
;
198 /* let the esd daemon convert sample rate */
200 /* let mplayer's audio filter convert the sample rate */
201 if (esd_svinfo
!= NULL
)
202 rate_hz
= esd_svinfo
->rate
;
204 ao_data
.samplerate
= rate_hz
;
206 /* EsounD can play mono or stereo */
210 ao_data
.channels
= bytes_per_sample
= 1;
213 esd_fmt
|= ESD_STEREO
;
214 ao_data
.channels
= bytes_per_sample
= 2;
218 /* EsounD can play 8bit unsigned and 16bit signed native */
222 esd_fmt
|= ESD_BITS8
;
223 ao_data
.format
= AF_FORMAT_U8
;
226 esd_fmt
|= ESD_BITS16
;
227 ao_data
.format
= AF_FORMAT_S16_NE
;
228 bytes_per_sample
*= 2;
232 /* modify audio_delay depending on esd_latency
233 * latency is number of samples @ 44.1khz stereo 16 bit
234 * adjust according to rate_hz & bytes_per_sample
236 #ifdef CONFIG_ESD_LATENCY
237 esd_latency
= esd_get_latency(esd_fd
);
239 esd_latency
= ((channels
== 1 ? 2 : 1) * ESD_DEFAULT_RATE
*
240 (ESD_BUF_SIZE
+ 64 * (4.0f
/ bytes_per_sample
))
242 esd_latency
+= ESD_BUF_SIZE
* 2;
244 if(esd_latency
> 0) {
245 lag_serv
= (esd_latency
* 4.0f
) / (bytes_per_sample
* rate_hz
);
246 lag_seconds
= lag_net
+ lag_serv
;
247 audio_delay
+= lag_seconds
;
248 mp_tmsg(MSGT_AO
, MSGL_INFO
,"[AO ESD] latency: [server: %0.2fs, net: %0.2fs] (adjust %0.2fs)\n",
249 lag_serv
, lag_net
, lag_seconds
);
252 esd_play_fd
= esd_play_stream_fallback(esd_fmt
, rate_hz
,
253 server
, ESD_CLIENT_NAME
);
254 if (esd_play_fd
< 0) {
255 mp_tmsg(MSGT_AO
, MSGL_ERR
, "[AO ESD] failed to open ESD playback stream: %s\n", strerror(errno
));
259 /* enable non-blocking i/o on the socket connection to the esd server */
260 if ((fl
= fcntl(esd_play_fd
, F_GETFL
)) >= 0)
261 fcntl(esd_play_fd
, F_SETFL
, O_NDELAY
|fl
);
267 getsockopt(esd_play_fd
, SOL_SOCKET
, SO_SNDBUF
, &sbuf
, &len
);
269 getsockopt(esd_play_fd
, SOL_SOCKET
, SO_RCVBUF
, &rbuf
, &len
);
270 dprintf("esd: send/receive socket buffer space %d/%d bytes\n",
275 ao_data
.bps
= bytes_per_sample
* rate_hz
;
276 ao_data
.outburst
= ao_data
.bps
> 100000 ? 4*ESD_BUF_SIZE
: 2*ESD_BUF_SIZE
;
278 esd_play_start
.tv_sec
= 0;
279 esd_samples_written
= 0;
280 esd_bytes_per_sample
= bytes_per_sample
;
289 static void uninit(int immed
)
291 if (esd_play_fd
>= 0) {
292 esd_close(esd_play_fd
);
297 esd_free_server_info(esd_svinfo
);
309 * plays 'len' bytes of 'data'
310 * it should round it down to outburst*n
311 * return: number of bytes played
313 static int play(void* data
, int len
, int flags
)
320 /* round down buffersize to a multiple of ESD_BUF_SIZE bytes */
321 len
= len
/ ESD_BUF_SIZE
* ESD_BUF_SIZE
;
325 #define SINGLE_WRITE 0
327 nwritten
= write(esd_play_fd
, data
, len
);
329 for (offs
= 0, nwritten
=0; offs
+ ESD_BUF_SIZE
<= len
; offs
+= ESD_BUF_SIZE
) {
331 * note: we're writing to a non-blocking socket here.
332 * A partial write means, that the socket buffer is full.
334 n
= write(esd_play_fd
, (char*)data
+ offs
, ESD_BUF_SIZE
);
336 if ( errno
!= EAGAIN
)
337 dprintf("esd play: write failed: %s\n", strerror(errno
));
339 } else if ( n
!= ESD_BUF_SIZE
) {
348 if (!esd_play_start
.tv_sec
)
349 gettimeofday(&esd_play_start
, NULL
);
350 nsamples
= nwritten
/ esd_bytes_per_sample
;
351 esd_samples_written
+= nsamples
;
353 dprintf("esd play: %d %lu\n", nsamples
, esd_samples_written
);
355 dprintf("esd play: blocked / %lu\n", esd_samples_written
);
363 * stop playing, keep buffers (for pause)
365 static void audio_pause(void)
368 * not possible with esd. the esd daemom will continue playing
369 * buffered data (not more than ESD_MAX_DELAY seconds of samples)
375 * resume playing, after audio_pause()
377 static void audio_resume(void)
380 * not possible with esd.
382 * Let's hope the pause was long enough that the esd ran out of
383 * buffered data; we restart our time based delay computation
384 * for an audio resume.
386 esd_play_start
.tv_sec
= 0;
387 esd_samples_written
= 0;
392 * stop playing and empty buffers (for seeking/pause)
394 static void reset(void)
397 /* throw away data buffered in the esd connection */
398 if (ioctl(esd_play_fd
, I_FLUSH
, FLUSHW
))
405 * return: how many bytes can be played without blocking
407 static int get_space(void)
409 struct timeval tmout
;
415 * Don't buffer too much data in the esd daemon.
417 * If we send too much, esd will block in write()s to the sound
418 * device, and the consequence is a huge slow down for things like
419 * esd_get_all_info().
421 if ((current_delay
= get_delay()) >= ESD_MAX_DELAY
) {
422 dprintf("esd get_space: too much data buffered\n");
427 FD_SET(esd_play_fd
, &wfds
);
431 if (select(esd_play_fd
+ 1, NULL
, &wfds
, NULL
, &tmout
) != 1)
434 if (!FD_ISSET(esd_play_fd
, &wfds
))
437 /* try to fill 50% of the remaining "free" buffer space */
438 space
= (ESD_MAX_DELAY
- current_delay
) * ao_data
.bps
* 0.5f
;
440 /* round up to next multiple of ESD_BUF_SIZE */
441 space
= (space
+ ESD_BUF_SIZE
-1) / ESD_BUF_SIZE
* ESD_BUF_SIZE
;
443 dprintf("esd get_space: %d\n", space
);
449 * return: delay in seconds between first and last sample in buffer
451 static float get_delay(void)
454 double buffered_samples_time
;
457 if (!esd_play_start
.tv_sec
)
460 buffered_samples_time
= (float)esd_samples_written
/ ao_data
.samplerate
;
461 gettimeofday(&now
, NULL
);
462 play_time
= now
.tv_sec
- esd_play_start
.tv_sec
;
463 play_time
+= (now
.tv_usec
- esd_play_start
.tv_usec
) / 1000000.;
465 /* dprintf("esd delay: %f %f\n", play_time, buffered_samples_time); */
467 if (play_time
> buffered_samples_time
) {
468 dprintf("esd: underflow\n");
469 esd_play_start
.tv_sec
= 0;
470 esd_samples_written
= 0;
474 dprintf("esd: get_delay %f\n", buffered_samples_time
- play_time
);
475 return buffered_samples_time
- play_time
;