/[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 801 - (hide annotations)
Tue Nov 23 13:29:12 2004 UTC (19 years, 6 months ago) by astrand
File MIME type: text/plain
File size: 6228 byte(s)
Indent fixes

1 jsorg71 778 /*
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     #include "rdesktop.h"
23     #include <unistd.h>
24     #include <fcntl.h>
25     #include <errno.h>
26 stargo 510 #include <sys/time.h>
27 matthewc 475 #include <sys/ioctl.h>
28     #include <sys/soundcard.h>
29    
30     #define MAX_QUEUE 10
31    
32     int g_dsp_fd;
33 stargo 504 BOOL g_dsp_busy = False;
34 stargo 510 static int g_snd_rate;
35     static short g_samplewidth;
36 stargo 761 static BOOL g_driver_broken = False;
37 matthewc 475
38 astrand 499 static struct audio_packet
39     {
40 matthewc 475 struct stream s;
41     uint16 tick;
42     uint8 index;
43     } packet_queue[MAX_QUEUE];
44     static unsigned int queue_hi, queue_lo;
45    
46     BOOL
47     wave_out_open(void)
48     {
49 stargo 751 char *dsp_dev = getenv("AUDIODEV");
50 matthewc 475
51 stargo 751 if (dsp_dev == NULL)
52     {
53 stargo 794 dsp_dev = strdup("/dev/dsp");
54 stargo 751 }
55    
56 astrand 499 if ((g_dsp_fd = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1)
57 matthewc 475 {
58     perror(dsp_dev);
59     return False;
60     }
61    
62     /* Non-blocking so that user interface is responsive */
63 astrand 499 fcntl(g_dsp_fd, F_SETFL, fcntl(g_dsp_fd, F_GETFL) | O_NONBLOCK);
64 matthewc 475 return True;
65     }
66    
67     void
68     wave_out_close(void)
69     {
70     close(g_dsp_fd);
71     }
72    
73     BOOL
74 astrand 499 wave_out_format_supported(WAVEFORMATEX * pwfx)
75 matthewc 475 {
76     if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
77     return False;
78     if ((pwfx->nChannels != 1) && (pwfx->nChannels != 2))
79     return False;
80     if ((pwfx->wBitsPerSample != 8) && (pwfx->wBitsPerSample != 16))
81     return False;
82    
83     return True;
84     }
85    
86     BOOL
87 astrand 499 wave_out_set_format(WAVEFORMATEX * pwfx)
88 matthewc 475 {
89 stargo 761 int stereo, format, fragments;
90 matthewc 475
91     ioctl(g_dsp_fd, SNDCTL_DSP_RESET, NULL);
92     ioctl(g_dsp_fd, SNDCTL_DSP_SYNC, NULL);
93    
94     if (pwfx->wBitsPerSample == 8)
95     format = AFMT_U8;
96     else if (pwfx->wBitsPerSample == 16)
97     format = AFMT_S16_LE;
98    
99 stargo 510 g_samplewidth = pwfx->wBitsPerSample / 8;
100    
101 matthewc 475 if (ioctl(g_dsp_fd, SNDCTL_DSP_SETFMT, &format) == -1)
102     {
103     perror("SNDCTL_DSP_SETFMT");
104     close(g_dsp_fd);
105     return False;
106     }
107    
108 stargo 760 if (pwfx->nChannels == 2)
109 matthewc 475 {
110 stargo 760 stereo = 1;
111     g_samplewidth *= 2;
112     }
113     else
114     {
115     stereo = 0;
116     }
117    
118     if (ioctl(g_dsp_fd, SNDCTL_DSP_STEREO, &stereo) == -1)
119     {
120 matthewc 475 perror("SNDCTL_DSP_CHANNELS");
121     close(g_dsp_fd);
122     return False;
123     }
124    
125 stargo 510 g_snd_rate = pwfx->nSamplesPerSec;
126     if (ioctl(g_dsp_fd, SNDCTL_DSP_SPEED, &g_snd_rate) == -1)
127     {
128 matthewc 475 perror("SNDCTL_DSP_SPEED");
129     close(g_dsp_fd);
130     return False;
131     }
132    
133 stargo 761 /* try to get 7 fragments of 2^12 bytes size */
134     fragments = (7 << 16) + 12;
135     ioctl(g_dsp_fd, SNDCTL_DSP_SETFRAGMENT, &fragments);
136    
137     if (!g_driver_broken)
138     {
139     audio_buf_info info;
140    
141 astrand 801 memset(&info, 0, sizeof(info));
142 stargo 761 if (ioctl(g_dsp_fd, SNDCTL_DSP_GETOSPACE, &info) == -1)
143     {
144     perror("SNDCTL_DSP_GETOSPACE");
145     close(g_dsp_fd);
146     return False;
147     }
148    
149     if (info.fragments == 0 || info.fragstotal == 0 || info.fragsize == 0)
150     {
151     fprintf(stderr,
152     "Broken OSS-driver detected: fragments: %d, fragstotal: %d, fragsize: %d\n",
153     info.fragments, info.fragstotal, info.fragsize);
154     g_driver_broken = True;
155     }
156     }
157    
158 matthewc 475 return True;
159     }
160    
161     void
162 stargo 491 wave_out_volume(uint16 left, uint16 right)
163     {
164 stargo 509 static BOOL use_dev_mixer = False;
165 stargo 491 uint32 volume;
166 stargo 509 int fd_mix = -1;
167 stargo 491
168 astrand 499 volume = left / (65536 / 100);
169     volume |= right / (65536 / 100) << 8;
170 stargo 509
171     if (use_dev_mixer)
172     {
173 astrand 532 if ((fd_mix = open("/dev/mixer", O_RDWR | O_NONBLOCK)) == -1)
174 stargo 509 {
175     perror("open /dev/mixer");
176     return;
177     }
178    
179     if (ioctl(fd_mix, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
180     {
181     perror("MIXER_WRITE(SOUND_MIXER_PCM)");
182     return;
183     }
184    
185     close(fd_mix);
186     }
187    
188 stargo 491 if (ioctl(g_dsp_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
189     {
190     perror("MIXER_WRITE(SOUND_MIXER_PCM)");
191 stargo 509 use_dev_mixer = True;
192 stargo 491 return;
193     }
194     }
195    
196     void
197 matthewc 475 wave_out_write(STREAM s, uint16 tick, uint8 index)
198     {
199 matthewc 476 struct audio_packet *packet = &packet_queue[queue_hi];
200     unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
201 matthewc 475
202     if (next_hi == queue_lo)
203     {
204     error("No space to queue audio packet\n");
205     return;
206     }
207    
208     queue_hi = next_hi;
209    
210     packet->s = *s;
211     packet->tick = tick;
212     packet->index = index;
213 stargo 491 packet->s.p += 4;
214 matthewc 475
215     /* we steal the data buffer from s, give it a new one */
216 jsorg71 778 s->data = (uint8 *) malloc(s->size);
217 matthewc 475
218     if (!g_dsp_busy)
219     wave_out_play();
220     }
221    
222     void
223     wave_out_play(void)
224     {
225     struct audio_packet *packet;
226     ssize_t len;
227     STREAM out;
228 stargo 510 static long startedat_us;
229     static long startedat_s;
230     static BOOL started = False;
231     struct timeval tv;
232 stargo 761 audio_buf_info info;
233 matthewc 475
234     while (1)
235     {
236     if (queue_lo == queue_hi)
237     {
238     g_dsp_busy = 0;
239     return;
240     }
241    
242     packet = &packet_queue[queue_lo];
243     out = &packet->s;
244    
245 stargo 510 if (!started)
246     {
247     gettimeofday(&tv, NULL);
248     startedat_us = tv.tv_usec;
249     startedat_s = tv.tv_sec;
250     started = True;
251     }
252    
253 stargo 761 len = out->end - out->p;
254    
255     if (!g_driver_broken)
256     {
257 astrand 801 memset(&info, 0, sizeof(info));
258 stargo 761 if (ioctl(g_dsp_fd, SNDCTL_DSP_GETOSPACE, &info) == -1)
259     {
260     perror("SNDCTL_DSP_GETOSPACE");
261     return;
262     }
263    
264     if (info.fragments == 0)
265     {
266     g_dsp_busy = 1;
267     return;
268     }
269    
270     if (info.fragments * info.fragsize < len
271     && info.fragments * info.fragsize > 0)
272     {
273     len = info.fragments * info.fragsize;
274     }
275     }
276    
277    
278     len = write(g_dsp_fd, out->p, len);
279 matthewc 475 if (len == -1)
280     {
281     if (errno != EWOULDBLOCK)
282     perror("write audio");
283     g_dsp_busy = 1;
284     return;
285     }
286    
287     out->p += len;
288     if (out->p == out->end)
289     {
290 stargo 510 long long duration;
291     long elapsed;
292 astrand 532
293 stargo 510 gettimeofday(&tv, NULL);
294 astrand 532 duration = (out->size * (1000000 / (g_samplewidth * g_snd_rate)));
295     elapsed = (tv.tv_sec - startedat_s) * 1000000 + (tv.tv_usec - startedat_us);
296 stargo 510
297 stargo 753 if (elapsed >= (duration * 85) / 100)
298 stargo 510 {
299     rdpsnd_send_completion(packet->tick, packet->index);
300     free(out->data);
301     queue_lo = (queue_lo + 1) % MAX_QUEUE;
302     started = False;
303     }
304     else
305     {
306     g_dsp_busy = 1;
307     return;
308     }
309 matthewc 475 }
310     }
311     }

  ViewVC Help
Powered by ViewVC 1.1.26