Mercurial > mplayer.hg
annotate libao2/ao_esd.c @ 32041:d03d69f64929
Move mplPBFade extern declaration to gmplayer.h, which is better suited.
author | diego |
---|---|
date | Thu, 09 Sep 2010 17:15:16 +0000 |
parents | 0f1b5b68af32 |
children | b8cc88eef14e |
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 | |
28362
f0a0d87b7c56
1) HAVE_SYS_ASOUNDLIB_H/HAVE_ALSA_ASOUNDLIB_H are defined/undefined,
diego
parents:
27502
diff
changeset
|
57 #define ESD_RESAMPLES 0 |
f0a0d87b7c56
1) HAVE_SYS_ASOUNDLIB_H/HAVE_ALSA_ASOUNDLIB_H are defined/undefined,
diego
parents:
27502
diff
changeset
|
58 #define ESD_DEBUG 0 |
8572 | 59 |
60 #if ESD_DEBUG | |
61 #define dprintf(...) printf(__VA_ARGS__) | |
62 #else | |
63 #define dprintf(...) /**/ | |
64 #endif | |
65 | |
66 | |
67 #define ESD_CLIENT_NAME "MPlayer" | |
68 #define ESD_MAX_DELAY (1.0f) /* max amount of data buffered in esd (#sec) */ | |
69 | |
28823 | 70 static const ao_info_t info = |
8572 | 71 { |
72 "EsounD audio output", | |
73 "esd", | |
74 "Juergen Keil <jk@tools.de>", | |
75 "" | |
76 }; | |
77 | |
78 LIBAO_EXTERN(esd) | |
79 | |
80 static int esd_fd = -1; | |
81 static int esd_play_fd = -1; | |
82 static esd_server_info_t *esd_svinfo; | |
83 static int esd_latency; | |
84 static int esd_bytes_per_sample; | |
85 static unsigned long esd_samples_written; | |
86 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
|
87 extern float audio_delay; |
8572 | 88 |
89 /* | |
90 * to set/get/query special features/parameters | |
91 */ | |
9633
12b1790038b0
64bit libao2 fix by Jens Axboe <mplayer-dev@kernel.dk>
alex
parents:
8623
diff
changeset
|
92 static int control(int cmd, void *arg) |
8572 | 93 { |
94 esd_player_info_t *esd_pi; | |
95 esd_info_t *esd_i; | |
96 time_t now; | |
97 static time_t vol_cache_time; | |
98 static ao_control_vol_t vol_cache; | |
99 | |
100 switch (cmd) { | |
101 case AOCONTROL_GET_VOLUME: | |
102 time(&now); | |
103 if (now == vol_cache_time) { | |
104 *(ao_control_vol_t *)arg = vol_cache; | |
105 return CONTROL_OK; | |
106 } | |
107 | |
108 dprintf("esd: get vol\n"); | |
109 if ((esd_i = esd_get_all_info(esd_fd)) == NULL) | |
110 return CONTROL_ERROR; | |
111 | |
112 for (esd_pi = esd_i->player_list; esd_pi != NULL; esd_pi = esd_pi->next) | |
113 if (strcmp(esd_pi->name, ESD_CLIENT_NAME) == 0) | |
114 break; | |
115 | |
116 if (esd_pi != NULL) { | |
117 ao_control_vol_t *vol = (ao_control_vol_t *)arg; | |
118 vol->left = esd_pi->left_vol_scale * 100 / ESD_VOLUME_BASE; | |
119 vol->right = esd_pi->right_vol_scale * 100 / ESD_VOLUME_BASE; | |
120 | |
121 vol_cache = *vol; | |
122 vol_cache_time = now; | |
123 } | |
124 esd_free_all_info(esd_i); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28823
diff
changeset
|
125 |
8572 | 126 return CONTROL_OK; |
127 | |
128 case AOCONTROL_SET_VOLUME: | |
129 dprintf("esd: set vol\n"); | |
130 if ((esd_i = esd_get_all_info(esd_fd)) == NULL) | |
131 return CONTROL_ERROR; | |
132 | |
133 for (esd_pi = esd_i->player_list; esd_pi != NULL; esd_pi = esd_pi->next) | |
134 if (strcmp(esd_pi->name, ESD_CLIENT_NAME) == 0) | |
135 break; | |
136 | |
137 if (esd_pi != NULL) { | |
138 ao_control_vol_t *vol = (ao_control_vol_t *)arg; | |
139 esd_set_stream_pan(esd_fd, esd_pi->source_id, | |
140 vol->left * ESD_VOLUME_BASE / 100, | |
141 vol->right * ESD_VOLUME_BASE / 100); | |
142 | |
143 vol_cache = *vol; | |
144 time(&vol_cache_time); | |
145 } | |
146 esd_free_all_info(esd_i); | |
147 return CONTROL_OK; | |
148 | |
149 default: | |
150 return CONTROL_UNKNOWN; | |
151 } | |
152 } | |
153 | |
154 | |
155 /* | |
156 * open & setup audio device | |
157 * return: 1=success 0=fail | |
158 */ | |
159 static int init(int rate_hz, int channels, int format, int flags) | |
160 { | |
161 esd_format_t esd_fmt; | |
162 int bytes_per_sample; | |
163 int fl; | |
10213
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
164 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
|
165 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
|
166 struct timeval proto_start, proto_end; |
8572 | 167 |
168 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
|
169 esd_fd = esd_open_sound(server); |
8572 | 170 if (esd_fd < 0) { |
13383
c1955840883d
mp_msg transition of unmaintained audio output drivers.
ivo
parents:
12145
diff
changeset
|
171 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ESD_CantOpenSound, |
8572 | 172 strerror(errno)); |
173 return 0; | |
174 } | |
175 | |
10213
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
176 /* 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
|
177 gettimeofday(&proto_start, NULL); |
8572 | 178 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
|
179 if(server) { |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
180 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
|
181 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
|
182 (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
|
183 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
|
184 } else |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
185 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
|
186 |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
187 /* |
8572 | 188 if (esd_svinfo) { |
189 mp_msg(MSGT_AO, MSGL_INFO, "AO: [esd] server info:\n"); | |
190 esd_print_server_info(esd_svinfo); | |
191 } | |
10213
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
192 */ |
8572 | 193 } |
194 | |
195 esd_fmt = ESD_STREAM | ESD_PLAY; | |
196 | |
197 #if ESD_RESAMPLES | |
198 /* let the esd daemon convert sample rate */ | |
199 #else | |
200 /* let mplayer's audio filter convert the sample rate */ | |
201 if (esd_svinfo != NULL) | |
202 rate_hz = esd_svinfo->rate; | |
203 #endif | |
204 ao_data.samplerate = rate_hz; | |
205 | |
206 /* EsounD can play mono or stereo */ | |
207 switch (channels) { | |
208 case 1: | |
209 esd_fmt |= ESD_MONO; | |
210 ao_data.channels = bytes_per_sample = 1; | |
211 break; | |
212 default: | |
213 esd_fmt |= ESD_STEREO; | |
214 ao_data.channels = bytes_per_sample = 2; | |
215 break; | |
216 } | |
217 | |
218 /* EsounD can play 8bit unsigned and 16bit signed native */ | |
219 switch (format) { | |
14245 | 220 case AF_FORMAT_S8: |
221 case AF_FORMAT_U8: | |
8572 | 222 esd_fmt |= ESD_BITS8; |
14245 | 223 ao_data.format = AF_FORMAT_U8; |
8572 | 224 break; |
225 default: | |
226 esd_fmt |= ESD_BITS16; | |
14245 | 227 ao_data.format = AF_FORMAT_S16_NE; |
8572 | 228 bytes_per_sample *= 2; |
229 break; | |
230 } | |
231 | |
10213
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
232 /* 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
|
233 * 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
|
234 * 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
|
235 */ |
27387
eb7bdbd98210
Rename some audio-output-related preprocessor directives.
diego
parents:
18976
diff
changeset
|
236 #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
|
237 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
|
238 #else |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28823
diff
changeset
|
239 esd_latency = ((channels == 1 ? 2 : 1) * ESD_DEFAULT_RATE * |
10213
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
240 (ESD_BUF_SIZE + 64 * (4.0f / bytes_per_sample)) |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28823
diff
changeset
|
241 ) / rate_hz; |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28823
diff
changeset
|
242 esd_latency += ESD_BUF_SIZE * 2; |
10213
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
243 #endif |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
244 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
|
245 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
|
246 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
|
247 audio_delay += lag_seconds; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28823
diff
changeset
|
248 mp_msg(MSGT_AO, MSGL_INFO,MSGTR_AO_ESD_LatencyInfo, |
13383
c1955840883d
mp_msg transition of unmaintained audio output drivers.
ivo
parents:
12145
diff
changeset
|
249 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
|
250 } |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28823
diff
changeset
|
251 |
8572 | 252 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
|
253 server, ESD_CLIENT_NAME); |
8572 | 254 if (esd_play_fd < 0) { |
13383
c1955840883d
mp_msg transition of unmaintained audio output drivers.
ivo
parents:
12145
diff
changeset
|
255 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ESD_CantOpenPBStream, strerror(errno)); |
8572 | 256 return 0; |
257 } | |
258 | |
259 /* enable non-blocking i/o on the socket connection to the esd server */ | |
260 if ((fl = fcntl(esd_play_fd, F_GETFL)) >= 0) | |
261 fcntl(esd_play_fd, F_SETFL, O_NDELAY|fl); | |
262 | |
263 #if ESD_DEBUG | |
264 { | |
265 int sbuf, rbuf, len; | |
266 len = sizeof(sbuf); | |
267 getsockopt(esd_play_fd, SOL_SOCKET, SO_SNDBUF, &sbuf, &len); | |
268 len = sizeof(rbuf); | |
269 getsockopt(esd_play_fd, SOL_SOCKET, SO_RCVBUF, &rbuf, &len); | |
270 dprintf("esd: send/receive socket buffer space %d/%d bytes\n", | |
271 sbuf, rbuf); | |
272 } | |
273 #endif | |
274 | |
275 ao_data.bps = bytes_per_sample * rate_hz; | |
276 ao_data.outburst = ao_data.bps > 100000 ? 4*ESD_BUF_SIZE : 2*ESD_BUF_SIZE; | |
277 | |
278 esd_play_start.tv_sec = 0; | |
279 esd_samples_written = 0; | |
280 esd_bytes_per_sample = bytes_per_sample; | |
281 | |
282 return 1; | |
283 } | |
284 | |
285 | |
286 /* | |
287 * close audio device | |
288 */ | |
12145 | 289 static void uninit(int immed) |
8572 | 290 { |
291 if (esd_play_fd >= 0) { | |
292 esd_close(esd_play_fd); | |
293 esd_play_fd = -1; | |
294 } | |
295 | |
296 if (esd_svinfo) { | |
297 esd_free_server_info(esd_svinfo); | |
298 esd_svinfo = NULL; | |
299 } | |
300 | |
301 if (esd_fd >= 0) { | |
302 esd_close(esd_fd); | |
303 esd_fd = -1; | |
304 } | |
305 } | |
306 | |
307 | |
308 /* | |
309 * plays 'len' bytes of 'data' | |
310 * it should round it down to outburst*n | |
311 * return: number of bytes played | |
312 */ | |
313 static int play(void* data, int len, int flags) | |
314 { | |
315 int offs; | |
316 int nwritten; | |
317 int nsamples; | |
18976
6a08d0dabca8
Remove unused variables, patch by Stefan Huehner, stefan ##at## huehner org.
diego
parents:
17566
diff
changeset
|
318 int n; |
8572 | 319 |
320 /* round down buffersize to a multiple of ESD_BUF_SIZE bytes */ | |
321 len = len / ESD_BUF_SIZE * ESD_BUF_SIZE; | |
322 if (len <= 0) | |
323 return 0; | |
324 | |
325 #define SINGLE_WRITE 0 | |
326 #if SINGLE_WRITE | |
327 nwritten = write(esd_play_fd, data, len); | |
328 #else | |
11619
179138947307
This patch contains bugfixes for the esd audio output driver that I
attila
parents:
10213
diff
changeset
|
329 for (offs = 0, nwritten=0; offs + ESD_BUF_SIZE <= len; offs += ESD_BUF_SIZE) { |
8572 | 330 /* |
331 * note: we're writing to a non-blocking socket here. | |
332 * A partial write means, that the socket buffer is full. | |
333 */ | |
11619
179138947307
This patch contains bugfixes for the esd audio output driver that I
attila
parents:
10213
diff
changeset
|
334 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
|
335 if ( n < 0 ) { |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28823
diff
changeset
|
336 if ( errno != EAGAIN ) |
8572 | 337 dprintf("esd play: write failed: %s\n", strerror(errno)); |
338 break; | |
11619
179138947307
This patch contains bugfixes for the esd audio output driver that I
attila
parents:
10213
diff
changeset
|
339 } else if ( n != ESD_BUF_SIZE ) { |
179138947307
This patch contains bugfixes for the esd audio output driver that I
attila
parents:
10213
diff
changeset
|
340 nwritten += n; |
179138947307
This patch contains bugfixes for the esd audio output driver that I
attila
parents:
10213
diff
changeset
|
341 break; |
8572 | 342 } else |
343 nwritten += n; | |
344 } | |
11619
179138947307
This patch contains bugfixes for the esd audio output driver that I
attila
parents:
10213
diff
changeset
|
345 #endif |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28823
diff
changeset
|
346 |
8572 | 347 if (nwritten > 0) { |
348 if (!esd_play_start.tv_sec) | |
349 gettimeofday(&esd_play_start, NULL); | |
350 nsamples = nwritten / esd_bytes_per_sample; | |
351 esd_samples_written += nsamples; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28823
diff
changeset
|
352 |
8572 | 353 dprintf("esd play: %d %lu\n", nsamples, esd_samples_written); |
354 } else { | |
355 dprintf("esd play: blocked / %lu\n", esd_samples_written); | |
356 } | |
357 | |
358 return nwritten; | |
359 } | |
360 | |
361 | |
362 /* | |
363 * stop playing, keep buffers (for pause) | |
364 */ | |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
14479
diff
changeset
|
365 static void audio_pause(void) |
8572 | 366 { |
367 /* | |
368 * not possible with esd. the esd daemom will continue playing | |
369 * buffered data (not more than ESD_MAX_DELAY seconds of samples) | |
370 */ | |
371 } | |
372 | |
373 | |
374 /* | |
375 * resume playing, after audio_pause() | |
376 */ | |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
14479
diff
changeset
|
377 static void audio_resume(void) |
8572 | 378 { |
379 /* | |
380 * not possible with esd. | |
381 * | |
382 * Let's hope the pause was long enough that the esd ran out of | |
383 * buffered data; we restart our time based delay computation | |
384 * for an audio resume. | |
385 */ | |
386 esd_play_start.tv_sec = 0; | |
387 esd_samples_written = 0; | |
388 } | |
389 | |
390 | |
391 /* | |
392 * stop playing and empty buffers (for seeking/pause) | |
393 */ | |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
14479
diff
changeset
|
394 static void reset(void) |
8572 | 395 { |
396 #ifdef __svr4__ | |
397 /* throw away data buffered in the esd connection */ | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28823
diff
changeset
|
398 if (ioctl(esd_play_fd, I_FLUSH, FLUSHW)) |
8572 | 399 perror("I_FLUSH"); |
400 #endif | |
401 } | |
402 | |
403 | |
404 /* | |
405 * return: how many bytes can be played without blocking | |
406 */ | |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
14479
diff
changeset
|
407 static int get_space(void) |
8572 | 408 { |
409 struct timeval tmout; | |
410 fd_set wfds; | |
411 float current_delay; | |
412 int space; | |
413 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28823
diff
changeset
|
414 /* |
8572 | 415 * Don't buffer too much data in the esd daemon. |
416 * | |
417 * If we send too much, esd will block in write()s to the sound | |
418 * device, and the consequence is a huge slow down for things like | |
419 * esd_get_all_info(). | |
420 */ | |
421 if ((current_delay = get_delay()) >= ESD_MAX_DELAY) { | |
422 dprintf("esd get_space: too much data buffered\n"); | |
423 return 0; | |
424 } | |
425 | |
426 FD_ZERO(&wfds); | |
427 FD_SET(esd_play_fd, &wfds); | |
428 tmout.tv_sec = 0; | |
429 tmout.tv_usec = 0; | |
430 | |
431 if (select(esd_play_fd + 1, NULL, &wfds, NULL, &tmout) != 1) | |
432 return 0; | |
433 | |
434 if (!FD_ISSET(esd_play_fd, &wfds)) | |
435 return 0; | |
436 | |
437 /* try to fill 50% of the remaining "free" buffer space */ | |
438 space = (ESD_MAX_DELAY - current_delay) * ao_data.bps * 0.5f; | |
439 | |
440 /* round up to next multiple of ESD_BUF_SIZE */ | |
441 space = (space + ESD_BUF_SIZE-1) / ESD_BUF_SIZE * ESD_BUF_SIZE; | |
442 | |
443 dprintf("esd get_space: %d\n", space); | |
444 return space; | |
445 } | |
446 | |
447 | |
448 /* | |
449 * return: delay in seconds between first and last sample in buffer | |
450 */ | |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
14479
diff
changeset
|
451 static float get_delay(void) |
8572 | 452 { |
453 struct timeval now; | |
454 double buffered_samples_time; | |
455 double play_time; | |
456 | |
457 if (!esd_play_start.tv_sec) | |
458 return 0; | |
459 | |
460 buffered_samples_time = (float)esd_samples_written / ao_data.samplerate; | |
461 gettimeofday(&now, NULL); | |
462 play_time = now.tv_sec - esd_play_start.tv_sec; | |
463 play_time += (now.tv_usec - esd_play_start.tv_usec) / 1000000.; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28823
diff
changeset
|
464 |
8572 | 465 /* dprintf("esd delay: %f %f\n", play_time, buffered_samples_time); */ |
466 | |
467 if (play_time > buffered_samples_time) { | |
468 dprintf("esd: underflow\n"); | |
469 esd_play_start.tv_sec = 0; | |
470 esd_samples_written = 0; | |
471 return 0; | |
472 } | |
473 | |
474 dprintf("esd: get_delay %f\n", buffered_samples_time - play_time); | |
475 return buffered_samples_time - play_time; | |
476 } |