/[rdesktop]/jpeg/rdesktop/trunk/rdpsnd_oss.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /jpeg/rdesktop/trunk/rdpsnd_oss.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1351 - (hide annotations)
Sun Dec 24 13:53:23 2006 UTC (17 years, 4 months ago) by stargo
Original Path: sourceforge.net/trunk/rdesktop/rdpsnd_oss.c
File MIME type: text/plain
File size: 7130 byte(s)
Make code compile with C89 compilers again

1 astrand 963 /* -*- c-basic-offset: 8 -*-
2 matthewc 475 rdesktop: A Remote Desktop Protocol client.
3     Sound Channel Process Functions - Open Sound System
4     Copyright (C) Matthew Chapman 2003
5     Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003
6    
7     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11    
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     GNU General Public License for more details.
16    
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20     */
21    
22 astrand 1227 /*
23     This is a workaround for Esound bug 312665.
24     FIXME: Remove this when Esound is fixed.
25     */
26     #ifdef _FILE_OFFSET_BITS
27     #undef _FILE_OFFSET_BITS
28     #endif
29    
30 matthewc 475 #include "rdesktop.h"
31 stargo 1254 #include "rdpsnd.h"
32 stargo 1269 #include "rdpsnd_dsp.h"
33 matthewc 475 #include <unistd.h>
34     #include <fcntl.h>
35     #include <errno.h>
36 ossman_ 1302 #include <unistd.h>
37 stargo 510 #include <sys/time.h>
38 matthewc 475 #include <sys/ioctl.h>
39     #include <sys/soundcard.h>
40 ossman_ 1302 #include <sys/types.h>
41     #include <sys/stat.h>
42 matthewc 475
43 stargo 1254 #define DEFAULTDEVICE "/dev/dsp"
44 stargo 1247 #define MAX_LEN 512
45 matthewc 475
46 ossman_ 1346 static int dsp_fd = -1;
47     static BOOL dsp_busy;
48    
49 stargo 1247 static int snd_rate;
50     static short samplewidth;
51 stargo 1255 static char *dsp_dev;
52 ossman_ 1302 static BOOL in_esddsp;
53 matthewc 475
54 ossman_ 1345 /* This is a just a forward declaration */
55     static struct audio_driver oss_driver;
56    
57 ossman_ 1346 void oss_play(void);
58    
59     void
60     oss_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
61     {
62     if (dsp_fd == -1)
63     return;
64    
65     if (rdpsnd_queue_empty())
66     return;
67    
68     FD_SET(dsp_fd, wfds);
69     if (dsp_fd > *n)
70     *n = dsp_fd;
71     }
72    
73     void
74     oss_check_fds(fd_set * rfds, fd_set * wfds)
75     {
76     if (FD_ISSET(dsp_fd, wfds))
77     oss_play();
78     }
79    
80 ossman_ 1302 static BOOL
81     detect_esddsp(void)
82     {
83     struct stat s;
84     char *preload;
85    
86 ossman_ 1346 if (fstat(dsp_fd, &s) == -1)
87 ossman_ 1302 return False;
88    
89     if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode))
90     return False;
91    
92     preload = getenv("LD_PRELOAD");
93     if (preload == NULL)
94     return False;
95    
96     if (strstr(preload, "esddsp") == NULL)
97     return False;
98    
99     return True;
100     }
101    
102 matthewc 475 BOOL
103 stargo 1255 oss_open(void)
104 matthewc 475 {
105 ossman_ 1346 if ((dsp_fd = open(dsp_dev, O_WRONLY)) == -1)
106 matthewc 475 {
107     perror(dsp_dev);
108     return False;
109     }
110    
111 ossman_ 1302 in_esddsp = detect_esddsp();
112    
113 matthewc 475 return True;
114     }
115    
116     void
117 stargo 1255 oss_close(void)
118 matthewc 475 {
119 ossman_ 1346 close(dsp_fd);
120     dsp_fd = -1;
121     dsp_busy = False;
122 matthewc 475 }
123    
124     BOOL
125 stargo 1255 oss_format_supported(WAVEFORMATEX * pwfx)
126 matthewc 475 {
127     if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
128     return False;
129     if ((pwfx->nChannels != 1) && (pwfx->nChannels != 2))
130     return False;
131     if ((pwfx->wBitsPerSample != 8) && (pwfx->wBitsPerSample != 16))
132     return False;
133    
134     return True;
135     }
136    
137     BOOL
138 stargo 1255 oss_set_format(WAVEFORMATEX * pwfx)
139 matthewc 475 {
140 stargo 761 int stereo, format, fragments;
141 stargo 1247 static BOOL driver_broken = False;
142 matthewc 475
143 ossman_ 1346 ioctl(dsp_fd, SNDCTL_DSP_RESET, NULL);
144     ioctl(dsp_fd, SNDCTL_DSP_SYNC, NULL);
145 matthewc 475
146     if (pwfx->wBitsPerSample == 8)
147     format = AFMT_U8;
148     else if (pwfx->wBitsPerSample == 16)
149     format = AFMT_S16_LE;
150    
151 stargo 1247 samplewidth = pwfx->wBitsPerSample / 8;
152 stargo 510
153 ossman_ 1346 if (ioctl(dsp_fd, SNDCTL_DSP_SETFMT, &format) == -1)
154 matthewc 475 {
155     perror("SNDCTL_DSP_SETFMT");
156 astrand 1318 oss_close();
157 matthewc 475 return False;
158     }
159    
160 stargo 760 if (pwfx->nChannels == 2)
161 matthewc 475 {
162 stargo 760 stereo = 1;
163 stargo 1247 samplewidth *= 2;
164 stargo 760 }
165     else
166     {
167     stereo = 0;
168     }
169    
170 ossman_ 1346 if (ioctl(dsp_fd, SNDCTL_DSP_STEREO, &stereo) == -1)
171 stargo 760 {
172 matthewc 475 perror("SNDCTL_DSP_CHANNELS");
173 astrand 1318 oss_close();
174 matthewc 475 return False;
175     }
176    
177 stargo 1286 oss_driver.need_resampling = 0;
178 stargo 1247 snd_rate = pwfx->nSamplesPerSec;
179 ossman_ 1346 if (ioctl(dsp_fd, SNDCTL_DSP_SPEED, &snd_rate) == -1)
180 stargo 510 {
181 stargo 1286 int rates[] = { 44100, 48000, 0 };
182     int *prates = rates;
183    
184     while (*prates != 0)
185     {
186     if ((pwfx->nSamplesPerSec != *prates)
187 ossman_ 1346 && (ioctl(dsp_fd, SNDCTL_DSP_SPEED, prates) != -1))
188 stargo 1286 {
189     oss_driver.need_resampling = 1;
190     snd_rate = *prates;
191     if (rdpsnd_dsp_resample_set
192     (snd_rate, pwfx->wBitsPerSample, pwfx->nChannels) == False)
193     {
194     error("rdpsnd_dsp_resample_set failed");
195 astrand 1318 oss_close();
196 stargo 1286 return False;
197     }
198    
199     break;
200     }
201     prates++;
202     }
203    
204     if (*prates == 0)
205     {
206     perror("SNDCTL_DSP_SPEED");
207 astrand 1318 oss_close();
208 stargo 1286 return False;
209     }
210 matthewc 475 }
211    
212 stargo 1247 /* try to get 12 fragments of 2^12 bytes size */
213     fragments = (12 << 16) + 12;
214 ossman_ 1346 ioctl(dsp_fd, SNDCTL_DSP_SETFRAGMENT, &fragments);
215 stargo 761
216 stargo 1247 if (!driver_broken)
217 stargo 761 {
218     audio_buf_info info;
219    
220 astrand 801 memset(&info, 0, sizeof(info));
221 ossman_ 1346 if (ioctl(dsp_fd, SNDCTL_DSP_GETOSPACE, &info) == -1)
222 stargo 761 {
223     perror("SNDCTL_DSP_GETOSPACE");
224 astrand 1318 oss_close();
225 stargo 761 return False;
226     }
227    
228     if (info.fragments == 0 || info.fragstotal == 0 || info.fragsize == 0)
229     {
230     fprintf(stderr,
231     "Broken OSS-driver detected: fragments: %d, fragstotal: %d, fragsize: %d\n",
232     info.fragments, info.fragstotal, info.fragsize);
233 stargo 1247 driver_broken = True;
234 stargo 761 }
235     }
236    
237 matthewc 475 return True;
238     }
239    
240     void
241 stargo 1255 oss_volume(uint16 left, uint16 right)
242 stargo 491 {
243     uint32 volume;
244    
245 astrand 499 volume = left / (65536 / 100);
246     volume |= right / (65536 / 100) << 8;
247 stargo 509
248 ossman_ 1346 if (ioctl(dsp_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
249 stargo 491 {
250 stargo 1275 warning("hardware volume control unavailable, falling back to software volume control!\n");
251 stargo 1269 oss_driver.wave_out_volume = rdpsnd_dsp_softvol_set;
252 stargo 1275 rdpsnd_dsp_softvol_set(left, right);
253 stargo 491 return;
254     }
255     }
256    
257     void
258 stargo 1255 oss_play(void)
259 matthewc 475 {
260     struct audio_packet *packet;
261     ssize_t len;
262     STREAM out;
263    
264 ossman_ 1346 /* We shouldn't be called if the queue is empty, but still */
265 stargo 1254 if (rdpsnd_queue_empty())
266 stargo 1247 return;
267 matthewc 475
268 stargo 1254 packet = rdpsnd_queue_current_packet();
269 stargo 1247 out = &packet->s;
270 matthewc 475
271 stargo 1247 len = out->end - out->p;
272 stargo 761
273 ossman_ 1346 len = write(dsp_fd, out->p, (len > MAX_LEN) ? MAX_LEN : len);
274 stargo 1247 if (len == -1)
275     {
276     if (errno != EWOULDBLOCK)
277     perror("write audio");
278     return;
279     }
280 stargo 761
281 stargo 1247 out->p += len;
282 ossman_ 1302
283 stargo 1247 if (out->p == out->end)
284     {
285 ossman_ 1302 int delay_bytes;
286     unsigned long delay_us;
287     audio_buf_info info;
288 stargo 761
289 ossman_ 1302 if (in_esddsp)
290 matthewc 475 {
291 ossman_ 1302 /* EsounD has no way of querying buffer status, so we have to
292     * go with a fixed size. */
293     delay_bytes = out->size;
294 stargo 1247 }
295     else
296     {
297 ossman_ 1302 #ifdef SNDCTL_DSP_GETODELAY
298     delay_bytes = 0;
299 ossman_ 1346 if (ioctl(dsp_fd, SNDCTL_DSP_GETODELAY, &delay_bytes) == -1)
300 ossman_ 1302 delay_bytes = -1;
301     #else
302     delay_bytes = -1;
303     #endif
304    
305     if (delay_bytes == -1)
306     {
307 ossman_ 1346 if (ioctl(dsp_fd, SNDCTL_DSP_GETOSPACE, &info) != -1)
308 ossman_ 1302 delay_bytes = info.fragstotal * info.fragsize - info.bytes;
309     else
310     delay_bytes = out->size;
311     }
312 matthewc 475 }
313 ossman_ 1302
314     delay_us = delay_bytes * (1000000 / (samplewidth * snd_rate));
315     rdpsnd_queue_next(delay_us);
316 matthewc 475 }
317     }
318 stargo 1255
319 stargo 1351 struct audio_driver *
320     oss_register(char *options)
321     {
322     oss_driver.name = xstrdup("oss");
323     oss_driver.description =
324     xstrdup("OSS output driver, default device: " DEFAULTDEVICE " or $AUDIODEV");
325 ossman_ 1345
326 stargo 1351 oss_driver.add_fds = oss_add_fds;
327     oss_driver.check_fds = oss_check_fds;
328 ossman_ 1346
329 stargo 1351 oss_driver.wave_out_open = oss_open;
330     oss_driver.wave_out_close = oss_close;
331     oss_driver.wave_out_format_supported = oss_format_supported;
332     oss_driver.wave_out_set_format = oss_set_format;
333     oss_driver.wave_out_volume = oss_volume;
334 ossman_ 1345
335 stargo 1351 oss_driver.need_byteswap_on_be = 0;
336     oss_driver.need_resampling = 0;
337 ossman_ 1345
338 stargo 1255 if (options)
339     {
340     dsp_dev = xstrdup(options);
341     }
342     else
343     {
344     dsp_dev = getenv("AUDIODEV");
345    
346     if (dsp_dev == NULL)
347     {
348     dsp_dev = xstrdup(DEFAULTDEVICE);
349     }
350     }
351    
352     return &oss_driver;
353     }

  ViewVC Help
Powered by ViewVC 1.1.26