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
= 0., lag_serv
;
165 struct timeval proto_start
, proto_end
;
167 global_ao
->no_persistent_volume
= true;
170 esd_fd
= esd_open_sound(server
);
172 mp_tmsg(MSGT_AO
, MSGL_ERR
, "[AO ESD] esd_open_sound failed: %s\n",
177 /* get server info, and measure network latency */
178 gettimeofday(&proto_start
, NULL
);
179 esd_svinfo
= esd_get_server_info(esd_fd
);
181 gettimeofday(&proto_end
, NULL
);
182 lag_net
= (proto_end
.tv_sec
- proto_start
.tv_sec
) +
183 (proto_end
.tv_usec
- proto_start
.tv_usec
) / 1000000.0;
184 lag_net
/= 2.0; /* round trip -> one way */
186 lag_net
= 0.0; /* no network lag */
190 mp_msg(MSGT_AO, MSGL_INFO, "AO: [esd] server info:\n");
191 esd_print_server_info(esd_svinfo);
196 esd_fmt
= ESD_STREAM
| ESD_PLAY
;
199 /* let the esd daemon convert sample rate */
201 /* let mplayer's audio filter convert the sample rate */
202 if (esd_svinfo
!= NULL
)
203 rate_hz
= esd_svinfo
->rate
;
205 ao_data
.samplerate
= rate_hz
;
207 /* EsounD can play mono or stereo */
211 ao_data
.channels
= bytes_per_sample
= 1;
214 esd_fmt
|= ESD_STEREO
;
215 ao_data
.channels
= bytes_per_sample
= 2;
219 /* EsounD can play 8bit unsigned and 16bit signed native */
223 esd_fmt
|= ESD_BITS8
;
224 ao_data
.format
= AF_FORMAT_U8
;
227 esd_fmt
|= ESD_BITS16
;
228 ao_data
.format
= AF_FORMAT_S16_NE
;
229 bytes_per_sample
*= 2;
233 /* modify audio_delay depending on esd_latency
234 * latency is number of samples @ 44.1khz stereo 16 bit
235 * adjust according to rate_hz & bytes_per_sample
237 #ifdef CONFIG_ESD_LATENCY
238 esd_latency
= esd_get_latency(esd_fd
);
240 esd_latency
= ((channels
== 1 ? 2 : 1) * ESD_DEFAULT_RATE
*
241 (ESD_BUF_SIZE
+ 64 * (4.0f
/ bytes_per_sample
))
243 esd_latency
+= ESD_BUF_SIZE
* 2;
245 if(esd_latency
> 0) {
246 lag_serv
= (esd_latency
* 4.0f
) / (bytes_per_sample
* rate_hz
);
247 lag_seconds
= lag_net
+ lag_serv
;
248 audio_delay
+= lag_seconds
;
249 mp_tmsg(MSGT_AO
, MSGL_INFO
,"[AO ESD] latency: [server: %0.2fs, net: %0.2fs] (adjust %0.2fs)\n",
250 lag_serv
, lag_net
, lag_seconds
);
253 esd_play_fd
= esd_play_stream_fallback(esd_fmt
, rate_hz
,
254 server
, ESD_CLIENT_NAME
);
255 if (esd_play_fd
< 0) {
256 mp_tmsg(MSGT_AO
, MSGL_ERR
, "[AO ESD] failed to open ESD playback stream: %s\n", strerror(errno
));
260 /* enable non-blocking i/o on the socket connection to the esd server */
261 if ((fl
= fcntl(esd_play_fd
, F_GETFL
)) >= 0)
262 fcntl(esd_play_fd
, F_SETFL
, O_NDELAY
|fl
);
268 getsockopt(esd_play_fd
, SOL_SOCKET
, SO_SNDBUF
, &sbuf
, &len
);
270 getsockopt(esd_play_fd
, SOL_SOCKET
, SO_RCVBUF
, &rbuf
, &len
);
271 dprintf("esd: send/receive socket buffer space %d/%d bytes\n",
276 ao_data
.bps
= bytes_per_sample
* rate_hz
;
277 ao_data
.outburst
= ao_data
.bps
> 100000 ? 4*ESD_BUF_SIZE
: 2*ESD_BUF_SIZE
;
279 esd_play_start
.tv_sec
= 0;
280 esd_samples_written
= 0;
281 esd_bytes_per_sample
= bytes_per_sample
;
290 static void uninit(int immed
)
292 if (esd_play_fd
>= 0) {
293 esd_close(esd_play_fd
);
298 esd_free_server_info(esd_svinfo
);
310 * plays 'len' bytes of 'data'
311 * it should round it down to outburst*n
312 * return: number of bytes played
314 static int play(void* data
, int len
, int flags
)
321 /* round down buffersize to a multiple of ESD_BUF_SIZE bytes */
322 len
= len
/ ESD_BUF_SIZE
* ESD_BUF_SIZE
;
326 #define SINGLE_WRITE 0
328 nwritten
= write(esd_play_fd
, data
, len
);
330 for (offs
= 0, nwritten
=0; offs
+ ESD_BUF_SIZE
<= len
; offs
+= ESD_BUF_SIZE
) {
332 * note: we're writing to a non-blocking socket here.
333 * A partial write means, that the socket buffer is full.
335 n
= write(esd_play_fd
, (char*)data
+ offs
, ESD_BUF_SIZE
);
337 if ( errno
!= EAGAIN
)
338 dprintf("esd play: write failed: %s\n", strerror(errno
));
340 } else if ( n
!= ESD_BUF_SIZE
) {
349 if (!esd_play_start
.tv_sec
)
350 gettimeofday(&esd_play_start
, NULL
);
351 nsamples
= nwritten
/ esd_bytes_per_sample
;
352 esd_samples_written
+= nsamples
;
354 dprintf("esd play: %d %lu\n", nsamples
, esd_samples_written
);
356 dprintf("esd play: blocked / %lu\n", esd_samples_written
);
364 * stop playing, keep buffers (for pause)
366 static void audio_pause(void)
369 * not possible with esd. the esd daemom will continue playing
370 * buffered data (not more than ESD_MAX_DELAY seconds of samples)
376 * resume playing, after audio_pause()
378 static void audio_resume(void)
381 * not possible with esd.
383 * Let's hope the pause was long enough that the esd ran out of
384 * buffered data; we restart our time based delay computation
385 * for an audio resume.
387 esd_play_start
.tv_sec
= 0;
388 esd_samples_written
= 0;
393 * stop playing and empty buffers (for seeking/pause)
395 static void reset(void)
398 /* throw away data buffered in the esd connection */
399 if (ioctl(esd_play_fd
, I_FLUSH
, FLUSHW
))
406 * return: how many bytes can be played without blocking
408 static int get_space(void)
410 struct timeval tmout
;
416 * Don't buffer too much data in the esd daemon.
418 * If we send too much, esd will block in write()s to the sound
419 * device, and the consequence is a huge slow down for things like
420 * esd_get_all_info().
422 if ((current_delay
= get_delay()) >= ESD_MAX_DELAY
) {
423 dprintf("esd get_space: too much data buffered\n");
428 FD_SET(esd_play_fd
, &wfds
);
432 if (select(esd_play_fd
+ 1, NULL
, &wfds
, NULL
, &tmout
) != 1)
435 if (!FD_ISSET(esd_play_fd
, &wfds
))
438 /* try to fill 50% of the remaining "free" buffer space */
439 space
= (ESD_MAX_DELAY
- current_delay
) * ao_data
.bps
* 0.5f
;
441 /* round up to next multiple of ESD_BUF_SIZE */
442 space
= (space
+ ESD_BUF_SIZE
-1) / ESD_BUF_SIZE
* ESD_BUF_SIZE
;
444 dprintf("esd get_space: %d\n", space
);
450 * return: delay in seconds between first and last sample in buffer
452 static float get_delay(void)
455 double buffered_samples_time
;
458 if (!esd_play_start
.tv_sec
)
461 buffered_samples_time
= (float)esd_samples_written
/ ao_data
.samplerate
;
462 gettimeofday(&now
, NULL
);
463 play_time
= now
.tv_sec
- esd_play_start
.tv_sec
;
464 play_time
+= (now
.tv_usec
- esd_play_start
.tv_usec
) / 1000000.;
466 /* dprintf("esd delay: %f %f\n", play_time, buffered_samples_time); */
468 if (play_time
> buffered_samples_time
) {
469 dprintf("esd: underflow\n");
470 esd_play_start
.tv_sec
= 0;
471 esd_samples_written
= 0;
475 dprintf("esd: get_delay %f\n", buffered_samples_time
- play_time
);
476 return buffered_samples_time
- play_time
;