/[rdesktop]/sourceforge.net/trunk/rdesktop/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 /sourceforge.net/trunk/rdesktop/rdpsnd_oss.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1345 - (hide annotations)
Thu Dec 7 11:54:29 2006 UTC (17 years, 6 months ago) by ossman_
File MIME type: text/plain
File size: 6681 byte(s)
Restructure driver registration structures a bit so it is easier to add
new fields (and also reduce some memory usage/leaks).

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 stargo 1247 static int snd_rate;
47     static short samplewidth;
48 stargo 1255 static char *dsp_dev;
49 ossman_ 1302 static BOOL in_esddsp;
50 matthewc 475
51 ossman_ 1345 /* This is a just a forward declaration */
52     static struct audio_driver oss_driver;
53    
54 ossman_ 1302 static BOOL
55     detect_esddsp(void)
56     {
57     struct stat s;
58     char *preload;
59    
60     if (fstat(g_dsp_fd, &s) == -1)
61     return False;
62    
63     if (S_ISCHR(s.st_mode) || S_ISBLK(s.st_mode))
64     return False;
65    
66     preload = getenv("LD_PRELOAD");
67     if (preload == NULL)
68     return False;
69    
70     if (strstr(preload, "esddsp") == NULL)
71     return False;
72    
73     return True;
74     }
75    
76 matthewc 475 BOOL
77 stargo 1255 oss_open(void)
78 matthewc 475 {
79 stargo 1247 if ((g_dsp_fd = open(dsp_dev, O_WRONLY)) == -1)
80 matthewc 475 {
81     perror(dsp_dev);
82     return False;
83     }
84    
85 ossman_ 1302 in_esddsp = detect_esddsp();
86    
87 matthewc 475 return True;
88     }
89    
90     void
91 stargo 1255 oss_close(void)
92 matthewc 475 {
93     close(g_dsp_fd);
94 astrand 1318 g_dsp_busy = 0;
95 matthewc 475 }
96    
97     BOOL
98 stargo 1255 oss_format_supported(WAVEFORMATEX * pwfx)
99 matthewc 475 {
100     if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
101     return False;
102     if ((pwfx->nChannels != 1) && (pwfx->nChannels != 2))
103     return False;
104     if ((pwfx->wBitsPerSample != 8) && (pwfx->wBitsPerSample != 16))
105     return False;
106    
107     return True;
108     }
109    
110     BOOL
111 stargo 1255 oss_set_format(WAVEFORMATEX * pwfx)
112 matthewc 475 {
113 stargo 761 int stereo, format, fragments;
114 stargo 1247 static BOOL driver_broken = False;
115 matthewc 475
116     ioctl(g_dsp_fd, SNDCTL_DSP_RESET, NULL);
117     ioctl(g_dsp_fd, SNDCTL_DSP_SYNC, NULL);
118    
119     if (pwfx->wBitsPerSample == 8)
120     format = AFMT_U8;
121     else if (pwfx->wBitsPerSample == 16)
122     format = AFMT_S16_LE;
123    
124 stargo 1247 samplewidth = pwfx->wBitsPerSample / 8;
125 stargo 510
126 matthewc 475 if (ioctl(g_dsp_fd, SNDCTL_DSP_SETFMT, &format) == -1)
127     {
128     perror("SNDCTL_DSP_SETFMT");
129 astrand 1318 oss_close();
130 matthewc 475 return False;
131     }
132    
133 stargo 760 if (pwfx->nChannels == 2)
134 matthewc 475 {
135 stargo 760 stereo = 1;
136 stargo 1247 samplewidth *= 2;
137 stargo 760 }
138     else
139     {
140     stereo = 0;
141     }
142    
143     if (ioctl(g_dsp_fd, SNDCTL_DSP_STEREO, &stereo) == -1)
144     {
145 matthewc 475 perror("SNDCTL_DSP_CHANNELS");
146 astrand 1318 oss_close();
147 matthewc 475 return False;
148     }
149    
150 stargo 1286 oss_driver.need_resampling = 0;
151 stargo 1247 snd_rate = pwfx->nSamplesPerSec;
152     if (ioctl(g_dsp_fd, SNDCTL_DSP_SPEED, &snd_rate) == -1)
153 stargo 510 {
154 stargo 1286 int rates[] = { 44100, 48000, 0 };
155     int *prates = rates;
156    
157     while (*prates != 0)
158     {
159     if ((pwfx->nSamplesPerSec != *prates)
160     && (ioctl(g_dsp_fd, SNDCTL_DSP_SPEED, prates) != -1))
161     {
162     oss_driver.need_resampling = 1;
163     snd_rate = *prates;
164     if (rdpsnd_dsp_resample_set
165     (snd_rate, pwfx->wBitsPerSample, pwfx->nChannels) == False)
166     {
167     error("rdpsnd_dsp_resample_set failed");
168 astrand 1318 oss_close();
169 stargo 1286 return False;
170     }
171    
172     break;
173     }
174     prates++;
175     }
176    
177     if (*prates == 0)
178     {
179     perror("SNDCTL_DSP_SPEED");
180 astrand 1318 oss_close();
181 stargo 1286 return False;
182     }
183 matthewc 475 }
184    
185 stargo 1247 /* try to get 12 fragments of 2^12 bytes size */
186     fragments = (12 << 16) + 12;
187 stargo 761 ioctl(g_dsp_fd, SNDCTL_DSP_SETFRAGMENT, &fragments);
188    
189 stargo 1247 if (!driver_broken)
190 stargo 761 {
191     audio_buf_info info;
192    
193 astrand 801 memset(&info, 0, sizeof(info));
194 stargo 761 if (ioctl(g_dsp_fd, SNDCTL_DSP_GETOSPACE, &info) == -1)
195     {
196     perror("SNDCTL_DSP_GETOSPACE");
197 astrand 1318 oss_close();
198 stargo 761 return False;
199     }
200    
201     if (info.fragments == 0 || info.fragstotal == 0 || info.fragsize == 0)
202     {
203     fprintf(stderr,
204     "Broken OSS-driver detected: fragments: %d, fragstotal: %d, fragsize: %d\n",
205     info.fragments, info.fragstotal, info.fragsize);
206 stargo 1247 driver_broken = True;
207 stargo 761 }
208     }
209    
210 matthewc 475 return True;
211     }
212    
213     void
214 stargo 1255 oss_volume(uint16 left, uint16 right)
215 stargo 491 {
216     uint32 volume;
217    
218 astrand 499 volume = left / (65536 / 100);
219     volume |= right / (65536 / 100) << 8;
220 stargo 509
221 stargo 491 if (ioctl(g_dsp_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
222     {
223 stargo 1275 warning("hardware volume control unavailable, falling back to software volume control!\n");
224 stargo 1269 oss_driver.wave_out_volume = rdpsnd_dsp_softvol_set;
225 stargo 1275 rdpsnd_dsp_softvol_set(left, right);
226 stargo 491 return;
227     }
228     }
229    
230     void
231 stargo 1255 oss_play(void)
232 matthewc 475 {
233     struct audio_packet *packet;
234     ssize_t len;
235     STREAM out;
236    
237 stargo 1254 if (rdpsnd_queue_empty())
238 matthewc 475 {
239 stargo 1247 g_dsp_busy = 0;
240     return;
241     }
242 matthewc 475
243 stargo 1254 packet = rdpsnd_queue_current_packet();
244 stargo 1247 out = &packet->s;
245 matthewc 475
246 stargo 1247 len = out->end - out->p;
247 stargo 761
248 stargo 1247 len = write(g_dsp_fd, out->p, (len > MAX_LEN) ? MAX_LEN : len);
249     if (len == -1)
250     {
251     if (errno != EWOULDBLOCK)
252     perror("write audio");
253     g_dsp_busy = 1;
254     return;
255     }
256 stargo 761
257 stargo 1247 out->p += len;
258 ossman_ 1302
259 stargo 1247 if (out->p == out->end)
260     {
261 ossman_ 1302 int delay_bytes;
262     unsigned long delay_us;
263     audio_buf_info info;
264 stargo 761
265 ossman_ 1302 if (in_esddsp)
266 matthewc 475 {
267 ossman_ 1302 /* EsounD has no way of querying buffer status, so we have to
268     * go with a fixed size. */
269     delay_bytes = out->size;
270 stargo 1247 }
271     else
272     {
273 ossman_ 1302 #ifdef SNDCTL_DSP_GETODELAY
274     delay_bytes = 0;
275     if (ioctl(g_dsp_fd, SNDCTL_DSP_GETODELAY, &delay_bytes) == -1)
276     delay_bytes = -1;
277     #else
278     delay_bytes = -1;
279     #endif
280    
281     if (delay_bytes == -1)
282     {
283     if (ioctl(g_dsp_fd, SNDCTL_DSP_GETOSPACE, &info) != -1)
284     delay_bytes = info.fragstotal * info.fragsize - info.bytes;
285     else
286     delay_bytes = out->size;
287     }
288 matthewc 475 }
289 ossman_ 1302
290     delay_us = delay_bytes * (1000000 / (samplewidth * snd_rate));
291     rdpsnd_queue_next(delay_us);
292 matthewc 475 }
293 ossman_ 1302 else
294     {
295     g_dsp_busy = 1;
296     }
297    
298 stargo 1247 return;
299 matthewc 475 }
300 stargo 1255
301 ossman_ 1345 static struct audio_driver oss_driver = {
302     .name = "oss",
303     .description = "OSS output driver, default device: " DEFAULTDEVICE " or $AUDIODEV",
304    
305     .wave_out_open = oss_open,
306     .wave_out_close = oss_close,
307     .wave_out_format_supported = oss_format_supported,
308     .wave_out_set_format = oss_set_format,
309     .wave_out_volume = oss_volume,
310     .wave_out_play = oss_play,
311    
312     .need_byteswap_on_be = 0,
313     .need_resampling = 0,
314     };
315    
316 stargo 1255 struct audio_driver *
317     oss_register(char *options)
318     {
319     if (options)
320     {
321     dsp_dev = xstrdup(options);
322     }
323     else
324     {
325     dsp_dev = getenv("AUDIODEV");
326    
327     if (dsp_dev == NULL)
328     {
329     dsp_dev = xstrdup(DEFAULTDEVICE);
330     }
331     }
332    
333     return &oss_driver;
334     }

  ViewVC Help
Powered by ViewVC 1.1.26