Mercurial > mplayer.hg
annotate libao2/ao_esd.c @ 28066:ccffc23bf229
sync w/r28096
author | gpoirier |
---|---|
date | Fri, 05 Dec 2008 21:46:28 +0000 |
parents | 9a1da32ed7bf |
children | f0a0d87b7c56 |
rev | line source |
---|---|
8572 | 1 /* |
27502
9a1da32ed7bf
Replace casual GPL notice by proper license header.
diego
parents:
27387
diff
changeset
|
2 * EsounD audio output driver for MPlayer |
9a1da32ed7bf
Replace casual GPL notice by proper license header.
diego
parents:
27387
diff
changeset
|
3 * |
9a1da32ed7bf
Replace casual GPL notice by proper license header.
diego
parents:
27387
diff
changeset
|
4 * copyright (c) 2002 Juergen Keil <jk@tools.de> |
9a1da32ed7bf
Replace casual GPL notice by proper license header.
diego
parents:
27387
diff
changeset
|
5 * |
9a1da32ed7bf
Replace casual GPL notice by proper license header.
diego
parents:
27387
diff
changeset
|
6 * This file is part of MPlayer. |
9a1da32ed7bf
Replace casual GPL notice by proper license header.
diego
parents:
27387
diff
changeset
|
7 * |
9a1da32ed7bf
Replace casual GPL notice by proper license header.
diego
parents:
27387
diff
changeset
|
8 * MPlayer is free software; you can redistribute it and/or modify |
9a1da32ed7bf
Replace casual GPL notice by proper license header.
diego
parents:
27387
diff
changeset
|
9 * it under the terms of the GNU General Public License as published by |
9a1da32ed7bf
Replace casual GPL notice by proper license header.
diego
parents:
27387
diff
changeset
|
10 * the Free Software Foundation; either version 2 of the License, or |
9a1da32ed7bf
Replace casual GPL notice by proper license header.
diego
parents:
27387
diff
changeset
|
11 * (at your option) any later version. |
8572 | 12 * |
27502
9a1da32ed7bf
Replace casual GPL notice by proper license header.
diego
parents:
27387
diff
changeset
|
13 * MPlayer is distributed in the hope that it will be useful, |
9a1da32ed7bf
Replace casual GPL notice by proper license header.
diego
parents:
27387
diff
changeset
|
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
9a1da32ed7bf
Replace casual GPL notice by proper license header.
diego
parents:
27387
diff
changeset
|
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
9a1da32ed7bf
Replace casual GPL notice by proper license header.
diego
parents:
27387
diff
changeset
|
16 * GNU General Public License for more details. |
8572 | 17 * |
27502
9a1da32ed7bf
Replace casual GPL notice by proper license header.
diego
parents:
27387
diff
changeset
|
18 * You should have received a copy of the GNU General Public License along |
9a1da32ed7bf
Replace casual GPL notice by proper license header.
diego
parents:
27387
diff
changeset
|
19 * with MPlayer; if not, write to the Free Software Foundation, Inc., |
9a1da32ed7bf
Replace casual GPL notice by proper license header.
diego
parents:
27387
diff
changeset
|
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
9a1da32ed7bf
Replace casual GPL notice by proper license header.
diego
parents:
27387
diff
changeset
|
21 */ |
9a1da32ed7bf
Replace casual GPL notice by proper license header.
diego
parents:
27387
diff
changeset
|
22 |
9a1da32ed7bf
Replace casual GPL notice by proper license header.
diego
parents:
27387
diff
changeset
|
23 /* |
8572 | 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 | |
27 * the default) | |
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) | |
33 */ | |
34 | |
35 #include <sys/types.h> | |
36 #include <sys/time.h> | |
37 #include <sys/socket.h> | |
38 #include <stdio.h> | |
39 #include <string.h> | |
40 #include <unistd.h> | |
41 #include <errno.h> | |
42 #include <fcntl.h> | |
8623
440301fef3fe
Added/reordered #includes to silence warnings about "implicit declaration".
rathann
parents:
8572
diff
changeset
|
43 #include <time.h> |
8572 | 44 #ifdef __svr4__ |
45 #include <stropts.h> | |
46 #endif | |
47 #include <esd.h> | |
48 | |
14479 | 49 #include "config.h" |
8572 | 50 #include "audio_out.h" |
51 #include "audio_out_internal.h" | |
14245 | 52 #include "libaf/af_format.h" |
14123 | 53 #include "mp_msg.h" |
54 #include "help_mp.h" | |
8572 | 55 |
56 | |
57 #undef ESD_DEBUG | |
58 | |
59 #if ESD_DEBUG | |
60 #define dprintf(...) printf(__VA_ARGS__) | |
61 #else | |
62 #define dprintf(...) /**/ | |
63 #endif | |
64 | |
65 | |
66 #define ESD_CLIENT_NAME "MPlayer" | |
67 #define ESD_MAX_DELAY (1.0f) /* max amount of data buffered in esd (#sec) */ | |
68 | |
69 static ao_info_t info = | |
70 { | |
71 "EsounD audio output", | |
72 "esd", | |
73 "Juergen Keil <jk@tools.de>", | |
74 "" | |
75 }; | |
76 | |
77 LIBAO_EXTERN(esd) | |
78 | |
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; | |
10213
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
86 extern float audio_delay; |
8572 | 87 |
88 /* | |
89 * to set/get/query special features/parameters | |
90 */ | |
9633
12b1790038b0
64bit libao2 fix by Jens Axboe <mplayer-dev@kernel.dk>
alex
parents:
8623
diff
changeset
|
91 static int control(int cmd, void *arg) |
8572 | 92 { |
93 esd_player_info_t *esd_pi; | |
94 esd_info_t *esd_i; | |
95 time_t now; | |
96 static time_t vol_cache_time; | |
97 static ao_control_vol_t vol_cache; | |
98 | |
99 switch (cmd) { | |
100 case AOCONTROL_GET_VOLUME: | |
101 time(&now); | |
102 if (now == vol_cache_time) { | |
103 *(ao_control_vol_t *)arg = vol_cache; | |
104 return CONTROL_OK; | |
105 } | |
106 | |
107 dprintf("esd: get vol\n"); | |
108 if ((esd_i = esd_get_all_info(esd_fd)) == NULL) | |
109 return CONTROL_ERROR; | |
110 | |
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) | |
113 break; | |
114 | |
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; | |
119 | |
120 vol_cache = *vol; | |
121 vol_cache_time = now; | |
122 } | |
123 esd_free_all_info(esd_i); | |
124 | |
125 return CONTROL_OK; | |
126 | |
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; | |
131 | |
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) | |
134 break; | |
135 | |
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); | |
141 | |
142 vol_cache = *vol; | |
143 time(&vol_cache_time); | |
144 } | |
145 esd_free_all_info(esd_i); | |
146 return CONTROL_OK; | |
147 | |
148 default: | |
149 return CONTROL_UNKNOWN; | |
150 } | |
151 } | |
152 | |
153 | |
154 /* | |
155 * open & setup audio device | |
156 * return: 1=success 0=fail | |
157 */ | |
158 static int init(int rate_hz, int channels, int format, int flags) | |
159 { | |
160 esd_format_t esd_fmt; | |
161 int bytes_per_sample; | |
162 int fl; | |
10213
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
163 char *server = ao_subdevice; /* NULL for localhost */ |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
164 float lag_seconds, lag_net, lag_serv; |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
165 struct timeval proto_start, proto_end; |
8572 | 166 |
167 if (esd_fd < 0) { | |
10213
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
168 esd_fd = esd_open_sound(server); |
8572 | 169 if (esd_fd < 0) { |
13383
c1955840883d
mp_msg transition of unmaintained audio output drivers.
ivo
parents:
12145
diff
changeset
|
170 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ESD_CantOpenSound, |
8572 | 171 strerror(errno)); |
172 return 0; | |
173 } | |
174 | |
10213
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
175 /* get server info, and measure network latency */ |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
176 gettimeofday(&proto_start, NULL); |
8572 | 177 esd_svinfo = esd_get_server_info(esd_fd); |
10213
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
178 if(server) { |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
179 gettimeofday(&proto_end, NULL); |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
180 lag_net = (proto_end.tv_sec - proto_start.tv_sec) + |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
181 (proto_end.tv_usec - proto_start.tv_usec) / 1000000.0; |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
182 lag_net /= 2.0; /* round trip -> one way */ |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
183 } else |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
184 lag_net = 0.0; /* no network lag */ |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
185 |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
186 /* |
8572 | 187 if (esd_svinfo) { |
188 mp_msg(MSGT_AO, MSGL_INFO, "AO: [esd] server info:\n"); | |
189 esd_print_server_info(esd_svinfo); | |
190 } | |
10213
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
191 */ |
8572 | 192 } |
193 | |
194 esd_fmt = ESD_STREAM | ESD_PLAY; | |
195 | |
196 #if ESD_RESAMPLES | |
197 /* let the esd daemon convert sample rate */ | |
198 #else | |
199 /* let mplayer's audio filter convert the sample rate */ | |
200 if (esd_svinfo != NULL) | |
201 rate_hz = esd_svinfo->rate; | |
202 #endif | |
203 ao_data.samplerate = rate_hz; | |
204 | |
205 /* EsounD can play mono or stereo */ | |
206 switch (channels) { | |
207 case 1: | |
208 esd_fmt |= ESD_MONO; | |
209 ao_data.channels = bytes_per_sample = 1; | |
210 break; | |
211 default: | |
212 esd_fmt |= ESD_STEREO; | |
213 ao_data.channels = bytes_per_sample = 2; | |
214 break; | |
215 } | |
216 | |
217 /* EsounD can play 8bit unsigned and 16bit signed native */ | |
218 switch (format) { | |
14245 | 219 case AF_FORMAT_S8: |
220 case AF_FORMAT_U8: | |
8572 | 221 esd_fmt |= ESD_BITS8; |
14245 | 222 ao_data.format = AF_FORMAT_U8; |
8572 | 223 break; |
224 default: | |
225 esd_fmt |= ESD_BITS16; | |
14245 | 226 ao_data.format = AF_FORMAT_S16_NE; |
8572 | 227 bytes_per_sample *= 2; |
228 break; | |
229 } | |
230 | |
10213
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
231 /* modify audio_delay depending on esd_latency |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
232 * latency is number of samples @ 44.1khz stereo 16 bit |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
233 * adjust according to rate_hz & bytes_per_sample |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
234 */ |
27387
eb7bdbd98210
Rename some audio-output-related preprocessor directives.
diego
parents:
18976
diff
changeset
|
235 #ifdef CONFIG_ESD_LATENCY |
10213
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
236 esd_latency = esd_get_latency(esd_fd); |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
237 #else |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
238 esd_latency = ((channels == 1 ? 2 : 1) * ESD_DEFAULT_RATE * |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
239 (ESD_BUF_SIZE + 64 * (4.0f / bytes_per_sample)) |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
240 ) / rate_hz; |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
241 esd_latency += ESD_BUF_SIZE * 2; |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
242 #endif |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
243 if(esd_latency > 0) { |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
244 lag_serv = (esd_latency * 4.0f) / (bytes_per_sample * rate_hz); |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
245 lag_seconds = lag_net + lag_serv; |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
246 audio_delay += lag_seconds; |
13383
c1955840883d
mp_msg transition of unmaintained audio output drivers.
ivo
parents:
12145
diff
changeset
|
247 mp_msg(MSGT_AO, MSGL_INFO,MSGTR_AO_ESD_LatencyInfo, |
c1955840883d
mp_msg transition of unmaintained audio output drivers.
ivo
parents:
12145
diff
changeset
|
248 lag_serv, lag_net, lag_seconds); |
10213
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
249 } |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
250 |
8572 | 251 esd_play_fd = esd_play_stream_fallback(esd_fmt, rate_hz, |
10213
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
252 server, ESD_CLIENT_NAME); |
8572 | 253 if (esd_play_fd < 0) { |
13383
c1955840883d
mp_msg transition of unmaintained audio output drivers.
ivo
parents:
12145
diff
changeset
|
254 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ESD_CantOpenPBStream, strerror(errno)); |
8572 | 255 return 0; |
256 } | |
257 | |
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); | |
261 | |
262 #if ESD_DEBUG | |
263 { | |
264 int sbuf, rbuf, len; | |
265 len = sizeof(sbuf); | |
266 getsockopt(esd_play_fd, SOL_SOCKET, SO_SNDBUF, &sbuf, &len); | |
267 len = sizeof(rbuf); | |
268 getsockopt(esd_play_fd, SOL_SOCKET, SO_RCVBUF, &rbuf, &len); | |
269 dprintf("esd: send/receive socket buffer space %d/%d bytes\n", | |
270 sbuf, rbuf); | |
271 } | |
272 #endif | |
273 | |
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; | |
276 | |
277 esd_play_start.tv_sec = 0; | |
278 esd_samples_written = 0; | |
279 esd_bytes_per_sample = bytes_per_sample; | |
280 | |
281 return 1; | |
282 } | |
283 | |
284 | |
285 /* | |
286 * close audio device | |
287 */ | |
12145 | 288 static void uninit(int immed) |
8572 | 289 { |
290 if (esd_play_fd >= 0) { | |
291 esd_close(esd_play_fd); | |
292 esd_play_fd = -1; | |
293 } | |
294 | |
295 if (esd_svinfo) { | |
296 esd_free_server_info(esd_svinfo); | |
297 esd_svinfo = NULL; | |
298 } | |
299 | |
300 if (esd_fd >= 0) { | |
301 esd_close(esd_fd); | |
302 esd_fd = -1; | |
303 } | |
304 } | |
305 | |
306 | |
307 /* | |
308 * plays 'len' bytes of 'data' | |
309 * it should round it down to outburst*n | |
310 * return: number of bytes played | |
311 */ | |
312 static int play(void* data, int len, int flags) | |
313 { | |
314 int offs; | |
315 int nwritten; | |
316 int nsamples; | |
18976
6a08d0dabca8
Remove unused variables, patch by Stefan Huehner, stefan ##at## huehner org.
diego
parents:
17566
diff
changeset
|
317 int n; |
8572 | 318 |
319 /* round down buffersize to a multiple of ESD_BUF_SIZE bytes */ | |
320 len = len / ESD_BUF_SIZE * ESD_BUF_SIZE; | |
321 if (len <= 0) | |
322 return 0; | |
323 | |
324 #define SINGLE_WRITE 0 | |
325 #if SINGLE_WRITE | |
326 nwritten = write(esd_play_fd, data, len); | |
327 #else | |
11619
179138947307
This patch contains bugfixes for the esd audio output driver that I
attila
parents:
10213
diff
changeset
|
328 for (offs = 0, nwritten=0; offs + ESD_BUF_SIZE <= len; offs += ESD_BUF_SIZE) { |
8572 | 329 /* |
330 * note: we're writing to a non-blocking socket here. | |
331 * A partial write means, that the socket buffer is full. | |
332 */ | |
11619
179138947307
This patch contains bugfixes for the esd audio output driver that I
attila
parents:
10213
diff
changeset
|
333 n = write(esd_play_fd, (char*)data + offs, ESD_BUF_SIZE); |
179138947307
This patch contains bugfixes for the esd audio output driver that I
attila
parents:
10213
diff
changeset
|
334 if ( n < 0 ) { |
179138947307
This patch contains bugfixes for the esd audio output driver that I
attila
parents:
10213
diff
changeset
|
335 if ( errno != EAGAIN ) |
8572 | 336 dprintf("esd play: write failed: %s\n", strerror(errno)); |
337 break; | |
11619
179138947307
This patch contains bugfixes for the esd audio output driver that I
attila
parents:
10213
diff
changeset
|
338 } else if ( n != ESD_BUF_SIZE ) { |
179138947307
This patch contains bugfixes for the esd audio output driver that I
attila
parents:
10213
diff
changeset
|
339 nwritten += n; |
179138947307
This patch contains bugfixes for the esd audio output driver that I
attila
parents:
10213
diff
changeset
|
340 break; |
8572 | 341 } else |
342 nwritten += n; | |
343 } | |
11619
179138947307
This patch contains bugfixes for the esd audio output driver that I
attila
parents:
10213
diff
changeset
|
344 #endif |
179138947307
This patch contains bugfixes for the esd audio output driver that I
attila
parents:
10213
diff
changeset
|
345 |
8572 | 346 if (nwritten > 0) { |
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; | |
351 | |
352 dprintf("esd play: %d %lu\n", nsamples, esd_samples_written); | |
353 } else { | |
354 dprintf("esd play: blocked / %lu\n", esd_samples_written); | |
355 } | |
356 | |
357 return nwritten; | |
358 } | |
359 | |
360 | |
361 /* | |
362 * stop playing, keep buffers (for pause) | |
363 */ | |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
14479
diff
changeset
|
364 static void audio_pause(void) |
8572 | 365 { |
366 /* | |
367 * not possible with esd. the esd daemom will continue playing | |
368 * buffered data (not more than ESD_MAX_DELAY seconds of samples) | |
369 */ | |
370 } | |
371 | |
372 | |
373 /* | |
374 * resume playing, after audio_pause() | |
375 */ | |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
14479
diff
changeset
|
376 static void audio_resume(void) |
8572 | 377 { |
378 /* | |
379 * not possible with esd. | |
380 * | |
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. | |
384 */ | |
385 esd_play_start.tv_sec = 0; | |
386 esd_samples_written = 0; | |
387 } | |
388 | |
389 | |
390 /* | |
391 * stop playing and empty buffers (for seeking/pause) | |
392 */ | |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
14479
diff
changeset
|
393 static void reset(void) |
8572 | 394 { |
395 #ifdef __svr4__ | |
396 /* throw away data buffered in the esd connection */ | |
397 if (ioctl(esd_play_fd, I_FLUSH, FLUSHW)) | |
398 perror("I_FLUSH"); | |
399 #endif | |
400 } | |
401 | |
402 | |
403 /* | |
404 * return: how many bytes can be played without blocking | |
405 */ | |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
14479
diff
changeset
|
406 static int get_space(void) |
8572 | 407 { |
408 struct timeval tmout; | |
409 fd_set wfds; | |
410 float current_delay; | |
411 int space; | |
412 | |
413 /* | |
414 * Don't buffer too much data in the esd daemon. | |
415 * | |
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(). | |
419 */ | |
420 if ((current_delay = get_delay()) >= ESD_MAX_DELAY) { | |
421 dprintf("esd get_space: too much data buffered\n"); | |
422 return 0; | |
423 } | |
424 | |
425 FD_ZERO(&wfds); | |
426 FD_SET(esd_play_fd, &wfds); | |
427 tmout.tv_sec = 0; | |
428 tmout.tv_usec = 0; | |
429 | |
430 if (select(esd_play_fd + 1, NULL, &wfds, NULL, &tmout) != 1) | |
431 return 0; | |
432 | |
433 if (!FD_ISSET(esd_play_fd, &wfds)) | |
434 return 0; | |
435 | |
436 /* try to fill 50% of the remaining "free" buffer space */ | |
437 space = (ESD_MAX_DELAY - current_delay) * ao_data.bps * 0.5f; | |
438 | |
439 /* round up to next multiple of ESD_BUF_SIZE */ | |
440 space = (space + ESD_BUF_SIZE-1) / ESD_BUF_SIZE * ESD_BUF_SIZE; | |
441 | |
442 dprintf("esd get_space: %d\n", space); | |
443 return space; | |
444 } | |
445 | |
446 | |
447 /* | |
448 * return: delay in seconds between first and last sample in buffer | |
449 */ | |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
14479
diff
changeset
|
450 static float get_delay(void) |
8572 | 451 { |
452 struct timeval now; | |
453 double buffered_samples_time; | |
454 double play_time; | |
455 | |
456 if (!esd_play_start.tv_sec) | |
457 return 0; | |
458 | |
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.; | |
463 | |
464 /* dprintf("esd delay: %f %f\n", play_time, buffered_samples_time); */ | |
465 | |
466 if (play_time > buffered_samples_time) { | |
467 dprintf("esd: underflow\n"); | |
468 esd_play_start.tv_sec = 0; | |
469 esd_samples_written = 0; | |
470 return 0; | |
471 } | |
472 | |
473 dprintf("esd: get_delay %f\n", buffered_samples_time - play_time); | |
474 return buffered_samples_time - play_time; | |
475 } |