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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1428 - (hide annotations)
Tue Jan 22 10:42:55 2008 UTC (16 years, 4 months ago) by ossman_
File MIME type: text/plain
File size: 8011 byte(s)
Record support for Sun audio backend. Also do some general improvements and
get it more in line with the OSS backend.

1 astrand 963 /* -*- c-basic-offset: 8 -*-
2 matthewc 476 rdesktop: A Remote Desktop Protocol client.
3     Sound Channel Process Functions - Sun
4 jsorg71 1365 Copyright (C) Matthew Chapman 2003-2007
5 matthewc 476 Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003
6 jsorg71 1365 Copyright (C) Michael Gernoth mike@zerfleddert.de 2003-2007
7 ossman_ 1428 Copyright 2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
8 matthewc 476
9     This program is free software; you can redistribute it and/or modify
10     it under the terms of the GNU General Public License as published by
11     the Free Software Foundation; either version 2 of the License, or
12     (at your option) any later version.
13    
14     This program is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17     GNU General Public License for more details.
18    
19     You should have received a copy of the GNU General Public License
20     along with this program; if not, write to the Free Software
21     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22     */
23    
24     #include "rdesktop.h"
25 stargo 1254 #include "rdpsnd.h"
26 matthewc 476 #include <unistd.h>
27     #include <fcntl.h>
28     #include <errno.h>
29     #include <sys/ioctl.h>
30 matthewc 477 #include <sys/audioio.h>
31 matthewc 476
32 stargo 560 #if (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
33     #include <stropts.h>
34     #endif
35    
36 stargo 1254 #define DEFAULTDEVICE "/dev/audio"
37 ossman_ 1428 #define MAX_LEN 512
38 matthewc 476
39 ossman_ 1346 static int dsp_fd = -1;
40 ossman_ 1428 static int dsp_mode;
41     static int dsp_refs;
42 ossman_ 1346
43 ossman_ 1428 static RD_BOOL dsp_configured;
44     static RD_BOOL dsp_broken;
45    
46     static RD_BOOL dsp_out;
47     static RD_BOOL dsp_in;
48    
49     static int stereo;
50     static int format;
51     static uint32 snd_rate;
52     static short samplewidth;
53 stargo 1255 static char *dsp_dev;
54 matthewc 476
55 ossman_ 1428 static uint_t written_samples;
56    
57 stargo 1347 void sun_play(void);
58 ossman_ 1428 void sun_record(void);
59 ossman_ 1346
60     void
61     sun_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
62     {
63     if (dsp_fd == -1)
64     return;
65    
66 ossman_ 1428 if (dsp_out && !rdpsnd_queue_empty())
67     FD_SET(dsp_fd, wfds);
68     if (dsp_in)
69     FD_SET(dsp_fd, rfds);
70 ossman_ 1346 if (dsp_fd > *n)
71     *n = dsp_fd;
72     }
73    
74     void
75     sun_check_fds(fd_set * rfds, fd_set * wfds)
76     {
77     if (FD_ISSET(dsp_fd, wfds))
78     sun_play();
79 ossman_ 1428 if (FD_ISSET(dsp_fd, rfds))
80     sun_record();
81 ossman_ 1346 }
82    
83 jsorg71 1372 RD_BOOL
84 ossman_ 1428 sun_open(int mode)
85 matthewc 476 {
86 ossman_ 1428 audio_info_t info;
87    
88     if (dsp_fd != -1)
89 matthewc 476 {
90 ossman_ 1428 dsp_refs++;
91    
92     if (dsp_mode == O_RDWR)
93     return True;
94    
95     if (dsp_mode == mode)
96     return True;
97    
98     dsp_refs--;
99 matthewc 476 return False;
100     }
101    
102 ossman_ 1428 dsp_configured = False;
103     dsp_broken = False;
104 astrand 499
105 ossman_ 1428 written_samples = 0;
106 astrand 499
107 ossman_ 1428 dsp_mode = O_RDWR;
108     dsp_fd = open(dsp_dev, O_RDWR | O_NONBLOCK);
109     if (dsp_fd != -1)
110     {
111     AUDIO_INITINFO(&info);
112    
113     if ((ioctl(dsp_fd, AUDIO_GETINFO, &info) == -1)
114     || !(info.hw_features & AUDIO_HWFEATURE_DUPLEX))
115     {
116     close(dsp_fd);
117     dsp_fd = -1;
118     }
119     }
120    
121     if (dsp_fd == -1)
122     {
123     dsp_mode = mode;
124    
125     dsp_fd = open(dsp_dev, dsp_mode | O_NONBLOCK);
126     if (dsp_fd == -1)
127     {
128     perror(dsp_dev);
129     return False;
130     }
131     }
132    
133     dsp_refs++;
134    
135 matthewc 476 return True;
136     }
137    
138     void
139 stargo 1255 sun_close(void)
140 matthewc 476 {
141 ossman_ 1428 dsp_refs--;
142 matthewc 477
143 ossman_ 1428 if (dsp_refs != 0)
144     return;
145    
146     close(dsp_fd);
147     dsp_fd = -1;
148     }
149    
150     RD_BOOL
151     sun_open_out(void)
152     {
153     if (!sun_open(O_WRONLY))
154     return False;
155    
156     dsp_out = True;
157    
158     return True;
159     }
160    
161     void
162     sun_close_out(void)
163     {
164 stargo 538 #if defined I_FLUSH && defined FLUSHW
165 matthewc 477 /* Flush the audiobuffer */
166 ossman_ 1346 ioctl(dsp_fd, I_FLUSH, FLUSHW);
167 stargo 538 #endif
168 stargo 561 #if defined AUDIO_FLUSH
169 ossman_ 1346 ioctl(dsp_fd, AUDIO_FLUSH, NULL);
170 stargo 561 #endif
171 ossman_ 1428
172     sun_close();
173    
174     /* Ack all remaining packets */
175     while (!rdpsnd_queue_empty())
176     rdpsnd_queue_next(0);
177    
178     dsp_out = False;
179 matthewc 476 }
180    
181 jsorg71 1372 RD_BOOL
182 ossman_ 1428 sun_open_in(void)
183     {
184     if (!sun_open(O_RDONLY))
185     return False;
186    
187     dsp_in = True;
188    
189     return True;
190     }
191    
192     void
193     sun_close_in(void)
194     {
195     sun_close();
196    
197     dsp_in = False;
198     }
199    
200     RD_BOOL
201 jsorg71 1364 sun_format_supported(RD_WAVEFORMATEX * pwfx)
202 matthewc 476 {
203     if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
204     return False;
205     if ((pwfx->nChannels != 1) && (pwfx->nChannels != 2))
206     return False;
207     if ((pwfx->wBitsPerSample != 8) && (pwfx->wBitsPerSample != 16))
208     return False;
209    
210     return True;
211     }
212    
213 jsorg71 1372 RD_BOOL
214 jsorg71 1364 sun_set_format(RD_WAVEFORMATEX * pwfx)
215 matthewc 476 {
216     audio_info_t info;
217    
218 ossman_ 1346 ioctl(dsp_fd, AUDIO_DRAIN, 0);
219 matthewc 476 AUDIO_INITINFO(&info);
220    
221 ossman_ 1428 if (dsp_configured)
222     {
223     if ((pwfx->wBitsPerSample == 8) && (format != AUDIO_ENCODING_LINEAR8))
224     return False;
225     if ((pwfx->wBitsPerSample == 16) && (format != AUDIO_ENCODING_LINEAR))
226     return False;
227 matthewc 476
228 ossman_ 1428 if ((pwfx->nChannels == 2) != !!stereo)
229     return False;
230    
231     if (pwfx->nSamplesPerSec != snd_rate)
232     return False;
233    
234     return True;
235     }
236    
237 matthewc 476 if (pwfx->wBitsPerSample == 8)
238     {
239     info.play.encoding = AUDIO_ENCODING_LINEAR8;
240     }
241     else if (pwfx->wBitsPerSample == 16)
242     {
243     info.play.encoding = AUDIO_ENCODING_LINEAR;
244     }
245    
246 ossman_ 1428 samplewidth = pwfx->wBitsPerSample / 8;
247 stargo 491
248 astrand 499 if (pwfx->nChannels == 1)
249     {
250 matthewc 514 info.play.channels = 1;
251 matthewc 476 }
252 astrand 499 else if (pwfx->nChannels == 2)
253 matthewc 476 {
254 matthewc 514 info.play.channels = 2;
255 ossman_ 1428 samplewidth *= 2;
256 matthewc 476 }
257    
258 ossman_ 1428 snd_rate = pwfx->nSamplesPerSec;
259    
260 matthewc 476 info.play.sample_rate = pwfx->nSamplesPerSec;
261     info.play.precision = pwfx->wBitsPerSample;
262     info.play.samples = 0;
263     info.play.eof = 0;
264     info.play.error = 0;
265    
266 ossman_ 1428 info.record.sample_rate = info.play.sample_rate;
267     info.record.channels = info.play.channels;
268     info.record.precision = info.play.precision;
269     info.record.encoding = info.play.encoding;
270     info.record.samples = 0;
271     info.record.error = 0;
272    
273 ossman_ 1346 if (ioctl(dsp_fd, AUDIO_SETINFO, &info) == -1)
274 matthewc 476 {
275     perror("AUDIO_SETINFO");
276 ossman_ 1346 sun_close();
277 matthewc 476 return False;
278     }
279    
280 ossman_ 1428 dsp_configured = True;
281    
282 matthewc 476 return True;
283     }
284    
285     void
286 stargo 1255 sun_volume(uint16 left, uint16 right)
287 stargo 491 {
288     audio_info_t info;
289     uint balance;
290     uint volume;
291    
292 stargo 772 AUDIO_INITINFO(&info);
293 stargo 491
294     volume = (left > right) ? left : right;
295    
296 astrand 499 if (volume / AUDIO_MID_BALANCE != 0)
297 stargo 491 {
298 astrand 499 balance =
299     AUDIO_MID_BALANCE - (left / (volume / AUDIO_MID_BALANCE)) +
300     (right / (volume / AUDIO_MID_BALANCE));
301 stargo 491 }
302     else
303     {
304     balance = AUDIO_MID_BALANCE;
305     }
306    
307 astrand 499 info.play.gain = volume / (65536 / AUDIO_MAX_GAIN);
308 stargo 491 info.play.balance = balance;
309    
310 ossman_ 1346 if (ioctl(dsp_fd, AUDIO_SETINFO, &info) == -1)
311 stargo 491 {
312     perror("AUDIO_SETINFO");
313     return;
314     }
315     }
316    
317     void
318 stargo 1255 sun_play(void)
319 matthewc 476 {
320     struct audio_packet *packet;
321     ssize_t len;
322     STREAM out;
323    
324 ossman_ 1428 /* We shouldn't be called if the queue is empty, but still */
325     if (rdpsnd_queue_empty())
326     return;
327    
328     packet = rdpsnd_queue_current_packet();
329     out = &packet->s;
330    
331     len = out->end - out->p;
332    
333     len = write(dsp_fd, out->p, (len > MAX_LEN) ? MAX_LEN : len);
334     if (len == -1)
335 matthewc 476 {
336 ossman_ 1428 if (errno != EWOULDBLOCK)
337 matthewc 477 {
338 ossman_ 1428 if (!dsp_broken)
339     perror("RDPSND: write()");
340     dsp_broken = True;
341     rdpsnd_queue_next(0);
342 matthewc 477 }
343 ossman_ 1428 return;
344     }
345 matthewc 477
346 ossman_ 1428 written_samples += len / (samplewidth * (stereo ? 2 : 1));
347 matthewc 476
348 ossman_ 1428 dsp_broken = False;
349 matthewc 476
350 ossman_ 1428 out->p += len;
351 matthewc 476
352 ossman_ 1428 if (out->p == out->end)
353     {
354     audio_info_t info;
355     uint_t delay_samples;
356     unsigned long delay_us;
357 matthewc 476
358 ossman_ 1428 if (ioctl(dsp_fd, AUDIO_GETINFO, &info) != -1)
359     delay_samples = written_samples - info.play.samples;
360     else
361     delay_samples = out->size / (samplewidth * (stereo ? 2 : 1));
362 matthewc 476
363 ossman_ 1428 delay_us = delay_samples * (1000000 / snd_rate);
364     rdpsnd_queue_next(delay_us);
365     }
366     }
367 matthewc 477
368 ossman_ 1428 void
369     sun_record(void)
370     {
371     char buffer[32768];
372     int len;
373    
374     len = read(dsp_fd, buffer, sizeof(buffer));
375     if (len == -1)
376     {
377     if (errno != EWOULDBLOCK)
378     perror("read audio");
379     return;
380 matthewc 476 }
381 ossman_ 1428
382     rdpsnd_record(buffer, len);
383 matthewc 476 }
384 stargo 1255
385 stargo 1351 struct audio_driver *
386     sun_register(char *options)
387     {
388     static struct audio_driver sun_driver;
389 ossman_ 1345
390 ossman_ 1356 memset(&sun_driver, 0, sizeof(sun_driver));
391    
392     sun_driver.name = "sun";
393 stargo 1351 sun_driver.description =
394 ossman_ 1356 "SUN/BSD output driver, default device: " DEFAULTDEVICE " or $AUDIODEV";
395 ossman_ 1346
396 stargo 1351 sun_driver.add_fds = sun_add_fds;
397     sun_driver.check_fds = sun_check_fds;
398 ossman_ 1345
399 ossman_ 1428 sun_driver.wave_out_open = sun_open_out;
400     sun_driver.wave_out_close = sun_close_out;
401 stargo 1351 sun_driver.wave_out_format_supported = sun_format_supported;
402     sun_driver.wave_out_set_format = sun_set_format;
403     sun_driver.wave_out_volume = sun_volume;
404 ossman_ 1345
405 ossman_ 1428 sun_driver.wave_in_open = sun_open_in;
406     sun_driver.wave_in_close = sun_close_in;
407     sun_driver.wave_in_format_supported = sun_format_supported;
408     sun_driver.wave_in_set_format = sun_set_format;
409     sun_driver.wave_in_volume = NULL; /* FIXME */
410    
411 stargo 1351 sun_driver.need_byteswap_on_be = 1;
412     sun_driver.need_resampling = 0;
413    
414 stargo 1255 if (options)
415     {
416     dsp_dev = xstrdup(options);
417     }
418     else
419     {
420     dsp_dev = getenv("AUDIODEV");
421    
422     if (dsp_dev == NULL)
423     {
424 ossman_ 1356 dsp_dev = DEFAULTDEVICE;
425 stargo 1255 }
426     }
427    
428     return &sun_driver;
429     }

  ViewVC Help
Powered by ViewVC 1.1.26