Mercurial > mplayer.hg
annotate libao2/ao_esd.c @ 27975:806c541d03dd
Do not draw in window if our image has not yet been adjusted to the new window size.
Fixes some cases of borders not being black in fullscreen when fullscreen image
is scaled down.
author | reimar |
---|---|
date | Sun, 23 Nov 2008 20:39:15 +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 } |