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;