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"
56 #define ESD_RESAMPLES 0
60 #define dprintf(...) printf(__VA_ARGS__)
62 #define dprintf(...) /**/
66 #define ESD_CLIENT_NAME "MPlayer"
67 #define ESD_MAX_DELAY (1.0f) /* max amount of data buffered in esd (#sec) */
69 static const ao_info_t info
=
71 "EsounD audio output",
73 "Juergen Keil <jk@tools.de>",
79 static int esd_fd
= -1;
80 static int esd_play_fd
= -1;
81 static esd_server_info_t
*esd_svinfo
;
82 static int esd_latency
;
83 static int esd_bytes_per_sample
;
84 static unsigned long esd_samples_written
;
85 static struct timeval esd_play_start
;
86 extern float audio_delay
;
89 * to set/get/query special features/parameters
91 static int control(int cmd
, void *arg
)
93 esd_player_info_t
*esd_pi
;
96 static time_t vol_cache_time
;
97 static ao_control_vol_t vol_cache
;
100 case AOCONTROL_GET_VOLUME
:
102 if (now
== vol_cache_time
) {
103 *(ao_control_vol_t
*)arg
= vol_cache
;
107 dprintf("esd: get vol\n");
108 if ((esd_i
= esd_get_all_info(esd_fd
)) == NULL
)
109 return CONTROL_ERROR
;
111 for (esd_pi
= esd_i
->player_list
; esd_pi
!= NULL
; esd_pi
= esd_pi
->next
)
112 if (strcmp(esd_pi
->name
, ESD_CLIENT_NAME
) == 0)
115 if (esd_pi
!= NULL
) {
116 ao_control_vol_t
*vol
= (ao_control_vol_t
*)arg
;
117 vol
->left
= esd_pi
->left_vol_scale
* 100 / ESD_VOLUME_BASE
;
118 vol
->right
= esd_pi
->right_vol_scale
* 100 / ESD_VOLUME_BASE
;
121 vol_cache_time
= now
;
123 esd_free_all_info(esd_i
);
127 case AOCONTROL_SET_VOLUME
:
128 dprintf("esd: set vol\n");
129 if ((esd_i
= esd_get_all_info(esd_fd
)) == NULL
)
130 return CONTROL_ERROR
;
132 for (esd_pi
= esd_i
->player_list
; esd_pi
!= NULL
; esd_pi
= esd_pi
->next
)
133 if (strcmp(esd_pi
->name
, ESD_CLIENT_NAME
) == 0)
136 if (esd_pi
!= NULL
) {
137 ao_control_vol_t
*vol
= (ao_control_vol_t
*)arg
;
138 esd_set_stream_pan(esd_fd
, esd_pi
->source_id
,
139 vol
->left
* ESD_VOLUME_BASE
/ 100,
140 vol
->right
* ESD_VOLUME_BASE
/ 100);
143 time(&vol_cache_time
);
145 esd_free_all_info(esd_i
);
149 return CONTROL_UNKNOWN
;
155 * open & setup audio device
156 * return: 1=success 0=fail
158 static int init(int rate_hz
, int channels
, int format
, int flags
)
160 esd_format_t esd_fmt
;
161 int bytes_per_sample
;
163 char *server
= ao_subdevice
; /* NULL for localhost */
164 float lag_seconds
, lag_net
, lag_serv
;
165 struct timeval proto_start
, proto_end
;
168 esd_fd
= esd_open_sound(server
);
170 mp_tmsg(MSGT_AO
, MSGL_ERR
, "[AO ESD] esd_open_sound failed: %s\n",
175 /* get server info, and measure network latency */
176 gettimeofday(&proto_start
, NULL
);
177 esd_svinfo
= esd_get_server_info(esd_fd
);
179 gettimeofday(&proto_end
, NULL
);
180 lag_net
= (proto_end
.tv_sec
- proto_start
.tv_sec
) +
181 (proto_end
.tv_usec
- proto_start
.tv_usec
) / 1000000.0;
182 lag_net
/= 2.0; /* round trip -> one way */
184 lag_net
= 0.0; /* no network lag */
188 mp_msg(MSGT_AO, MSGL_INFO, "AO: [esd] server info:\n");
189 esd_print_server_info(esd_svinfo);
194 esd_fmt
= ESD_STREAM
| ESD_PLAY
;
197 /* let the esd daemon convert sample rate */
199 /* let mplayer's audio filter convert the sample rate */
200 if (esd_svinfo
!= NULL
)
201 rate_hz
= esd_svinfo
->rate
;
203 ao_data
.samplerate
= rate_hz
;
205 /* EsounD can play mono or stereo */
209 ao_data
.channels
= bytes_per_sample
= 1;
212 esd_fmt
|= ESD_STEREO
;
213 ao_data
.channels
= bytes_per_sample
= 2;
217 /* EsounD can play 8bit unsigned and 16bit signed native */
221 esd_fmt
|= ESD_BITS8
;
222 ao_data
.format
= AF_FORMAT_U8
;
225 esd_fmt
|= ESD_BITS16
;
226 ao_data
.format
= AF_FORMAT_S16_NE
;
227 bytes_per_sample
*= 2;
231 /* modify audio_delay depending on esd_latency
232 * latency is number of samples @ 44.1khz stereo 16 bit
233 * adjust according to rate_hz & bytes_per_sample
235 #ifdef CONFIG_ESD_LATENCY
236 esd_latency
= esd_get_latency(esd_fd
);
238 esd_latency
= ((channels
== 1 ? 2 : 1) * ESD_DEFAULT_RATE
*
239 (ESD_BUF_SIZE
+ 64 * (4.0f
/ bytes_per_sample
))
241 esd_latency
+= ESD_BUF_SIZE
* 2;
243 if(esd_latency
> 0) {
244 lag_serv
= (esd_latency
* 4.0f
) / (bytes_per_sample
* rate_hz
);
245 lag_seconds
= lag_net
+ lag_serv
;
246 audio_delay
+= lag_seconds
;
247 mp_tmsg(MSGT_AO
, MSGL_INFO
,"[AO ESD] latency: [server: %0.2fs, net: %0.2fs] (adjust %0.2fs)\n",
248 lag_serv
, lag_net
, lag_seconds
);
251 esd_play_fd
= esd_play_stream_fallback(esd_fmt
, rate_hz
,
252 server
, ESD_CLIENT_NAME
);
253 if (esd_play_fd
< 0) {
254 mp_tmsg(MSGT_AO
, MSGL_ERR
, "[AO ESD] failed to open ESD playback stream: %s\n", strerror(errno
));
258 /* enable non-blocking i/o on the socket connection to the esd server */
259 if ((fl
= fcntl(esd_play_fd
, F_GETFL
)) >= 0)
260 fcntl(esd_play_fd
, F_SETFL
, O_NDELAY
|fl
);
266 getsockopt(esd_play_fd
, SOL_SOCKET
, SO_SNDBUF
, &sbuf
, &len
);
268 getsockopt(esd_play_fd
, SOL_SOCKET
, SO_RCVBUF
, &rbuf
, &len
);
269 dprintf("esd: send/receive socket buffer space %d/%d bytes\n",
274 ao_data
.bps
= bytes_per_sample
* rate_hz
;
275 ao_data
.outburst
= ao_data
.bps
> 100000 ? 4*ESD_BUF_SIZE
: 2*ESD_BUF_SIZE
;
277 esd_play_start
.tv_sec
= 0;
278 esd_samples_written
= 0;
279 esd_bytes_per_sample
= bytes_per_sample
;
288 static void uninit(int immed
)
290 if (esd_play_fd
>= 0) {
291 esd_close(esd_play_fd
);
296 esd_free_server_info(esd_svinfo
);
308 * plays 'len' bytes of 'data'
309 * it should round it down to outburst*n
310 * return: number of bytes played
312 static int play(void* data
, int len
, int flags
)
319 /* round down buffersize to a multiple of ESD_BUF_SIZE bytes */
320 len
= len
/ ESD_BUF_SIZE
* ESD_BUF_SIZE
;
324 #define SINGLE_WRITE 0
326 nwritten
= write(esd_play_fd
, data
, len
);
328 for (offs
= 0, nwritten
=0; offs
+ ESD_BUF_SIZE
<= len
; offs
+= ESD_BUF_SIZE
) {
330 * note: we're writing to a non-blocking socket here.
331 * A partial write means, that the socket buffer is full.
333 n
= write(esd_play_fd
, (char*)data
+ offs
, ESD_BUF_SIZE
);
335 if ( errno
!= EAGAIN
)
336 dprintf("esd play: write failed: %s\n", strerror(errno
));
338 } else if ( n
!= ESD_BUF_SIZE
) {
347 if (!esd_play_start
.tv_sec
)
348 gettimeofday(&esd_play_start
, NULL
);
349 nsamples
= nwritten
/ esd_bytes_per_sample
;
350 esd_samples_written
+= nsamples
;
352 dprintf("esd play: %d %lu\n", nsamples
, esd_samples_written
);
354 dprintf("esd play: blocked / %lu\n", esd_samples_written
);
362 * stop playing, keep buffers (for pause)
364 static void audio_pause(void)
367 * not possible with esd. the esd daemom will continue playing
368 * buffered data (not more than ESD_MAX_DELAY seconds of samples)
374 * resume playing, after audio_pause()
376 static void audio_resume(void)
379 * not possible with esd.
381 * Let's hope the pause was long enough that the esd ran out of
382 * buffered data; we restart our time based delay computation
383 * for an audio resume.
385 esd_play_start
.tv_sec
= 0;
386 esd_samples_written
= 0;
391 * stop playing and empty buffers (for seeking/pause)
393 static void reset(void)
396 /* throw away data buffered in the esd connection */
397 if (ioctl(esd_play_fd
, I_FLUSH
, FLUSHW
))
404 * return: how many bytes can be played without blocking
406 static int get_space(void)
408 struct timeval tmout
;
414 * Don't buffer too much data in the esd daemon.
416 * If we send too much, esd will block in write()s to the sound
417 * device, and the consequence is a huge slow down for things like
418 * esd_get_all_info().
420 if ((current_delay
= get_delay()) >= ESD_MAX_DELAY
) {
421 dprintf("esd get_space: too much data buffered\n");
426 FD_SET(esd_play_fd
, &wfds
);
430 if (select(esd_play_fd
+ 1, NULL
, &wfds
, NULL
, &tmout
) != 1)
433 if (!FD_ISSET(esd_play_fd
, &wfds
))
436 /* try to fill 50% of the remaining "free" buffer space */
437 space
= (ESD_MAX_DELAY
- current_delay
) * ao_data
.bps
* 0.5f
;
439 /* round up to next multiple of ESD_BUF_SIZE */
440 space
= (space
+ ESD_BUF_SIZE
-1) / ESD_BUF_SIZE
* ESD_BUF_SIZE
;
442 dprintf("esd get_space: %d\n", space
);
448 * return: delay in seconds between first and last sample in buffer
450 static float get_delay(void)
453 double buffered_samples_time
;
456 if (!esd_play_start
.tv_sec
)
459 buffered_samples_time
= (float)esd_samples_written
/ ao_data
.samplerate
;
460 gettimeofday(&now
, NULL
);
461 play_time
= now
.tv_sec
- esd_play_start
.tv_sec
;
462 play_time
+= (now
.tv_usec
- esd_play_start
.tv_usec
) / 1000000.;
464 /* dprintf("esd delay: %f %f\n", play_time, buffered_samples_time); */
466 if (play_time
> buffered_samples_time
) {
467 dprintf("esd: underflow\n");
468 esd_play_start
.tv_sec
= 0;
469 esd_samples_written
= 0;
473 dprintf("esd: get_delay %f\n", buffered_samples_time
- play_time
);
474 return buffered_samples_time
- play_time
;