Mercurial > mplayer.hg
annotate libao2/ao_esd.c @ 37149:a9ceb566a008
configure: add CONFIG_STARTCODE to prevent build failure
author | michael |
---|---|
date | Tue, 05 Aug 2014 11:12:59 +0000 |
parents | 6ec928ab8112 |
children |
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" | |
32055
b8cc88eef14e
Replace audio_delay extern declaration by proper mplayer.h #include.
diego
parents:
29263
diff
changeset
|
55 #include "mplayer.h" |
8572 | 56 |
57 | |
28362
f0a0d87b7c56
1) HAVE_SYS_ASOUNDLIB_H/HAVE_ALSA_ASOUNDLIB_H are defined/undefined,
diego
parents:
27502
diff
changeset
|
58 #define ESD_RESAMPLES 0 |
f0a0d87b7c56
1) HAVE_SYS_ASOUNDLIB_H/HAVE_ALSA_ASOUNDLIB_H are defined/undefined,
diego
parents:
27502
diff
changeset
|
59 #define ESD_DEBUG 0 |
8572 | 60 |
61 #if ESD_DEBUG | |
62 #define dprintf(...) printf(__VA_ARGS__) | |
63 #else | |
64 #define dprintf(...) /**/ | |
65 #endif | |
66 | |
67 | |
68 #define ESD_CLIENT_NAME "MPlayer" | |
69 #define ESD_MAX_DELAY (1.0f) /* max amount of data buffered in esd (#sec) */ | |
70 | |
28823 | 71 static const ao_info_t info = |
8572 | 72 { |
73 "EsounD audio output", | |
74 "esd", | |
75 "Juergen Keil <jk@tools.de>", | |
76 "" | |
77 }; | |
78 | |
79 LIBAO_EXTERN(esd) | |
80 | |
81 static int esd_fd = -1; | |
82 static int esd_play_fd = -1; | |
83 static esd_server_info_t *esd_svinfo; | |
84 static int esd_latency; | |
85 static int esd_bytes_per_sample; | |
86 static unsigned long esd_samples_written; | |
87 static struct timeval esd_play_start; | |
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 |
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 esd_fmt = ESD_STREAM | ESD_PLAY; | |
194 | |
195 #if ESD_RESAMPLES | |
196 /* let the esd daemon convert sample rate */ | |
197 #else | |
198 /* let mplayer's audio filter convert the sample rate */ | |
199 if (esd_svinfo != NULL) | |
200 rate_hz = esd_svinfo->rate; | |
201 #endif | |
202 ao_data.samplerate = rate_hz; | |
203 | |
204 /* EsounD can play mono or stereo */ | |
205 switch (channels) { | |
206 case 1: | |
207 esd_fmt |= ESD_MONO; | |
208 ao_data.channels = bytes_per_sample = 1; | |
209 break; | |
210 default: | |
211 esd_fmt |= ESD_STEREO; | |
212 ao_data.channels = bytes_per_sample = 2; | |
213 break; | |
214 } | |
215 | |
216 /* EsounD can play 8bit unsigned and 16bit signed native */ | |
217 switch (format) { | |
14245 | 218 case AF_FORMAT_S8: |
219 case AF_FORMAT_U8: | |
8572 | 220 esd_fmt |= ESD_BITS8; |
14245 | 221 ao_data.format = AF_FORMAT_U8; |
8572 | 222 break; |
223 default: | |
224 esd_fmt |= ESD_BITS16; | |
14245 | 225 ao_data.format = AF_FORMAT_S16_NE; |
8572 | 226 bytes_per_sample *= 2; |
227 break; | |
228 } | |
229 | |
10213
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
230 /* 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
|
231 * 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
|
232 * 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
|
233 */ |
27387
eb7bdbd98210
Rename some audio-output-related preprocessor directives.
diego
parents:
18976
diff
changeset
|
234 #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
|
235 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
|
236 #else |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28823
diff
changeset
|
237 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
|
238 (ESD_BUF_SIZE + 64 * (4.0f / bytes_per_sample)) |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28823
diff
changeset
|
239 ) / rate_hz; |
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28823
diff
changeset
|
240 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
|
241 #endif |
5e15ff3261ff
esd:server and esd latency support by Andrew Williams <andrew.s.williams@adelaide.edu.au>
alex
parents:
9633
diff
changeset
|
242 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
|
243 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
|
244 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
|
245 audio_delay += lag_seconds; |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28823
diff
changeset
|
246 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
|
247 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
|
248 } |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28823
diff
changeset
|
249 |
8572 | 250 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
|
251 server, ESD_CLIENT_NAME); |
8572 | 252 if (esd_play_fd < 0) { |
13383
c1955840883d
mp_msg transition of unmaintained audio output drivers.
ivo
parents:
12145
diff
changeset
|
253 mp_msg(MSGT_AO, MSGL_ERR, MSGTR_AO_ESD_CantOpenPBStream, strerror(errno)); |
8572 | 254 return 0; |
255 } | |
256 | |
257 /* enable non-blocking i/o on the socket connection to the esd server */ | |
258 if ((fl = fcntl(esd_play_fd, F_GETFL)) >= 0) | |
259 fcntl(esd_play_fd, F_SETFL, O_NDELAY|fl); | |
260 | |
261 #if ESD_DEBUG | |
262 { | |
263 int sbuf, rbuf, len; | |
264 len = sizeof(sbuf); | |
265 getsockopt(esd_play_fd, SOL_SOCKET, SO_SNDBUF, &sbuf, &len); | |
266 len = sizeof(rbuf); | |
267 getsockopt(esd_play_fd, SOL_SOCKET, SO_RCVBUF, &rbuf, &len); | |
268 dprintf("esd: send/receive socket buffer space %d/%d bytes\n", | |
269 sbuf, rbuf); | |
270 } | |
271 #endif | |
272 | |
273 ao_data.bps = bytes_per_sample * rate_hz; | |
274 ao_data.outburst = ao_data.bps > 100000 ? 4*ESD_BUF_SIZE : 2*ESD_BUF_SIZE; | |
275 | |
276 esd_play_start.tv_sec = 0; | |
277 esd_samples_written = 0; | |
278 esd_bytes_per_sample = bytes_per_sample; | |
279 | |
280 return 1; | |
281 } | |
282 | |
283 | |
284 /* | |
285 * close audio device | |
286 */ | |
12145 | 287 static void uninit(int immed) |
8572 | 288 { |
289 if (esd_play_fd >= 0) { | |
290 esd_close(esd_play_fd); | |
291 esd_play_fd = -1; | |
292 } | |
293 | |
294 if (esd_svinfo) { | |
295 esd_free_server_info(esd_svinfo); | |
296 esd_svinfo = NULL; | |
297 } | |
298 | |
299 if (esd_fd >= 0) { | |
300 esd_close(esd_fd); | |
301 esd_fd = -1; | |
302 } | |
303 } | |
304 | |
305 | |
306 /* | |
307 * plays 'len' bytes of 'data' | |
308 * it should round it down to outburst*n | |
309 * return: number of bytes played | |
310 */ | |
311 static int play(void* data, int len, int flags) | |
312 { | |
313 int offs; | |
314 int nwritten; | |
315 int nsamples; | |
18976
6a08d0dabca8
Remove unused variables, patch by Stefan Huehner, stefan ##at## huehner org.
diego
parents:
17566
diff
changeset
|
316 int n; |
8572 | 317 |
318 /* round down buffersize to a multiple of ESD_BUF_SIZE bytes */ | |
319 len = len / ESD_BUF_SIZE * ESD_BUF_SIZE; | |
320 if (len <= 0) | |
321 return 0; | |
322 | |
323 #define SINGLE_WRITE 0 | |
324 #if SINGLE_WRITE | |
325 nwritten = write(esd_play_fd, data, len); | |
326 #else | |
11619
179138947307
This patch contains bugfixes for the esd audio output driver that I
attila
parents:
10213
diff
changeset
|
327 for (offs = 0, nwritten=0; offs + ESD_BUF_SIZE <= len; offs += ESD_BUF_SIZE) { |
8572 | 328 /* |
329 * note: we're writing to a non-blocking socket here. | |
330 * A partial write means, that the socket buffer is full. | |
331 */ | |
11619
179138947307
This patch contains bugfixes for the esd audio output driver that I
attila
parents:
10213
diff
changeset
|
332 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
|
333 if ( n < 0 ) { |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28823
diff
changeset
|
334 if ( errno != EAGAIN ) |
8572 | 335 dprintf("esd play: write failed: %s\n", strerror(errno)); |
336 break; | |
11619
179138947307
This patch contains bugfixes for the esd audio output driver that I
attila
parents:
10213
diff
changeset
|
337 } else if ( n != ESD_BUF_SIZE ) { |
179138947307
This patch contains bugfixes for the esd audio output driver that I
attila
parents:
10213
diff
changeset
|
338 nwritten += n; |
179138947307
This patch contains bugfixes for the esd audio output driver that I
attila
parents:
10213
diff
changeset
|
339 break; |
8572 | 340 } else |
341 nwritten += n; | |
342 } | |
11619
179138947307
This patch contains bugfixes for the esd audio output driver that I
attila
parents:
10213
diff
changeset
|
343 #endif |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28823
diff
changeset
|
344 |
8572 | 345 if (nwritten > 0) { |
346 if (!esd_play_start.tv_sec) | |
347 gettimeofday(&esd_play_start, NULL); | |
348 nsamples = nwritten / esd_bytes_per_sample; | |
349 esd_samples_written += nsamples; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28823
diff
changeset
|
350 |
8572 | 351 dprintf("esd play: %d %lu\n", nsamples, esd_samples_written); |
352 } else { | |
353 dprintf("esd play: blocked / %lu\n", esd_samples_written); | |
354 } | |
355 | |
356 return nwritten; | |
357 } | |
358 | |
359 | |
360 /* | |
361 * stop playing, keep buffers (for pause) | |
362 */ | |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
14479
diff
changeset
|
363 static void audio_pause(void) |
8572 | 364 { |
365 /* | |
366 * not possible with esd. the esd daemom will continue playing | |
367 * buffered data (not more than ESD_MAX_DELAY seconds of samples) | |
368 */ | |
369 } | |
370 | |
371 | |
372 /* | |
373 * resume playing, after audio_pause() | |
374 */ | |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
14479
diff
changeset
|
375 static void audio_resume(void) |
8572 | 376 { |
377 /* | |
378 * not possible with esd. | |
379 * | |
380 * Let's hope the pause was long enough that the esd ran out of | |
381 * buffered data; we restart our time based delay computation | |
382 * for an audio resume. | |
383 */ | |
384 esd_play_start.tv_sec = 0; | |
385 esd_samples_written = 0; | |
386 } | |
387 | |
388 | |
389 /* | |
390 * stop playing and empty buffers (for seeking/pause) | |
391 */ | |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
14479
diff
changeset
|
392 static void reset(void) |
8572 | 393 { |
394 #ifdef __svr4__ | |
395 /* throw away data buffered in the esd connection */ | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28823
diff
changeset
|
396 if (ioctl(esd_play_fd, I_FLUSH, FLUSHW)) |
8572 | 397 perror("I_FLUSH"); |
398 #endif | |
399 } | |
400 | |
401 | |
402 /* | |
403 * return: how many bytes can be played without blocking | |
404 */ | |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
14479
diff
changeset
|
405 static int get_space(void) |
8572 | 406 { |
407 struct timeval tmout; | |
408 fd_set wfds; | |
409 float current_delay; | |
410 int space; | |
411 | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28823
diff
changeset
|
412 /* |
8572 | 413 * Don't buffer too much data in the esd daemon. |
414 * | |
415 * If we send too much, esd will block in write()s to the sound | |
416 * device, and the consequence is a huge slow down for things like | |
417 * esd_get_all_info(). | |
418 */ | |
419 if ((current_delay = get_delay()) >= ESD_MAX_DELAY) { | |
420 dprintf("esd get_space: too much data buffered\n"); | |
421 return 0; | |
422 } | |
423 | |
424 FD_ZERO(&wfds); | |
425 FD_SET(esd_play_fd, &wfds); | |
426 tmout.tv_sec = 0; | |
427 tmout.tv_usec = 0; | |
428 | |
429 if (select(esd_play_fd + 1, NULL, &wfds, NULL, &tmout) != 1) | |
430 return 0; | |
431 | |
432 if (!FD_ISSET(esd_play_fd, &wfds)) | |
433 return 0; | |
434 | |
435 /* try to fill 50% of the remaining "free" buffer space */ | |
436 space = (ESD_MAX_DELAY - current_delay) * ao_data.bps * 0.5f; | |
437 | |
438 /* round up to next multiple of ESD_BUF_SIZE */ | |
439 space = (space + ESD_BUF_SIZE-1) / ESD_BUF_SIZE * ESD_BUF_SIZE; | |
440 | |
441 dprintf("esd get_space: %d\n", space); | |
442 return space; | |
443 } | |
444 | |
445 | |
446 /* | |
447 * return: delay in seconds between first and last sample in buffer | |
448 */ | |
17566
f580a7755ac5
Patch by Stefan Huehner / stefan % huehner ! org \
rathann
parents:
14479
diff
changeset
|
449 static float get_delay(void) |
8572 | 450 { |
451 struct timeval now; | |
452 double buffered_samples_time; | |
453 double play_time; | |
454 | |
455 if (!esd_play_start.tv_sec) | |
456 return 0; | |
457 | |
458 buffered_samples_time = (float)esd_samples_written / ao_data.samplerate; | |
459 gettimeofday(&now, NULL); | |
460 play_time = now.tv_sec - esd_play_start.tv_sec; | |
461 play_time += (now.tv_usec - esd_play_start.tv_usec) / 1000000.; | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28823
diff
changeset
|
462 |
8572 | 463 /* dprintf("esd delay: %f %f\n", play_time, buffered_samples_time); */ |
464 | |
465 if (play_time > buffered_samples_time) { | |
466 dprintf("esd: underflow\n"); | |
467 esd_play_start.tv_sec = 0; | |
468 esd_samples_written = 0; | |
469 return 0; | |
470 } | |
471 | |
472 dprintf("esd: get_delay %f\n", buffered_samples_time - play_time); | |
473 return buffered_samples_time - play_time; | |
474 } |