/[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 778 - (hide annotations)
Sun Oct 3 20:19:51 2004 UTC (19 years, 8 months ago) by jsorg71
File MIME type: text/plain
File size: 6151 byte(s)
changes to compile with g++

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     dsp_dev = "/dev/dsp";
54     }
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     if (ioctl(g_dsp_fd, SNDCTL_DSP_GETOSPACE, &info) == -1)
142     {
143     perror("SNDCTL_DSP_GETOSPACE");
144     close(g_dsp_fd);
145     return False;
146     }
147    
148     if (info.fragments == 0 || info.fragstotal == 0 || info.fragsize == 0)
149     {
150     fprintf(stderr,
151     "Broken OSS-driver detected: fragments: %d, fragstotal: %d, fragsize: %d\n",
152     info.fragments, info.fragstotal, info.fragsize);
153     g_driver_broken = True;
154     }
155     }
156    
157 matthewc 475 return True;
158     }
159    
160     void
161 stargo 491 wave_out_volume(uint16 left, uint16 right)
162     {
163 stargo 509 static BOOL use_dev_mixer = False;
164 stargo 491 uint32 volume;
165 stargo 509 int fd_mix = -1;
166 stargo 491
167 astrand 499 volume = left / (65536 / 100);
168     volume |= right / (65536 / 100) << 8;
169 stargo 509
170     if (use_dev_mixer)
171     {
172 astrand 532 if ((fd_mix = open("/dev/mixer", O_RDWR | O_NONBLOCK)) == -1)
173 stargo 509 {
174     perror("open /dev/mixer");
175     return;
176     }
177    
178     if (ioctl(fd_mix, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
179     {
180     perror("MIXER_WRITE(SOUND_MIXER_PCM)");
181     return;
182     }
183    
184     close(fd_mix);
185     }
186    
187 stargo 491 if (ioctl(g_dsp_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
188     {
189     perror("MIXER_WRITE(SOUND_MIXER_PCM)");
190 stargo 509 use_dev_mixer = True;
191 stargo 491 return;
192     }
193     }
194    
195     void
196 matthewc 475 wave_out_write(STREAM s, uint16 tick, uint8 index)
197     {
198 matthewc 476 struct audio_packet *packet = &packet_queue[queue_hi];
199     unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
200 matthewc 475
201     if (next_hi == queue_lo)
202     {
203     error("No space to queue audio packet\n");
204     return;
205     }
206    
207     queue_hi = next_hi;
208    
209     packet->s = *s;
210     packet->tick = tick;
211     packet->index = index;
212 stargo 491 packet->s.p += 4;
213 matthewc 475
214     /* we steal the data buffer from s, give it a new one */
215 jsorg71 778 s->data = (uint8 *) malloc(s->size);
216 matthewc 475
217     if (!g_dsp_busy)
218     wave_out_play();
219     }
220    
221     void
222     wave_out_play(void)
223     {
224     struct audio_packet *packet;
225     ssize_t len;
226     STREAM out;
227 stargo 510 static long startedat_us;
228     static long startedat_s;
229     static BOOL started = False;
230     struct timeval tv;
231 stargo 761 audio_buf_info info;
232 matthewc 475
233     while (1)
234     {
235     if (queue_lo == queue_hi)
236     {
237     g_dsp_busy = 0;
238     return;
239     }
240    
241     packet = &packet_queue[queue_lo];
242     out = &packet->s;
243    
244 stargo 510 if (!started)
245     {
246     gettimeofday(&tv, NULL);
247     startedat_us = tv.tv_usec;
248     startedat_s = tv.tv_sec;
249     started = True;
250     }
251    
252 stargo 761 len = out->end - out->p;
253    
254     if (!g_driver_broken)
255     {
256     if (ioctl(g_dsp_fd, SNDCTL_DSP_GETOSPACE, &info) == -1)
257     {
258     perror("SNDCTL_DSP_GETOSPACE");
259     return;
260     }
261    
262     if (info.fragments == 0)
263     {
264     g_dsp_busy = 1;
265     return;
266     }
267    
268     if (info.fragments * info.fragsize < len
269     && info.fragments * info.fragsize > 0)
270     {
271     len = info.fragments * info.fragsize;
272     }
273     }
274    
275    
276     len = write(g_dsp_fd, out->p, len);
277 matthewc 475 if (len == -1)
278     {
279     if (errno != EWOULDBLOCK)
280     perror("write audio");
281     g_dsp_busy = 1;
282     return;
283     }
284    
285     out->p += len;
286     if (out->p == out->end)
287     {
288 stargo 510 long long duration;
289     long elapsed;
290 astrand 532
291 stargo 510 gettimeofday(&tv, NULL);
292 astrand 532 duration = (out->size * (1000000 / (g_samplewidth * g_snd_rate)));
293     elapsed = (tv.tv_sec - startedat_s) * 1000000 + (tv.tv_usec - startedat_us);
294 stargo 510
295 stargo 753 if (elapsed >= (duration * 85) / 100)
296 stargo 510 {
297     rdpsnd_send_completion(packet->tick, packet->index);
298     free(out->data);
299     queue_lo = (queue_lo + 1) % MAX_QUEUE;
300     started = False;
301     }
302     else
303     {
304     g_dsp_busy = 1;
305     return;
306     }
307 matthewc 475 }
308     }
309     }

  ViewVC Help
Powered by ViewVC 1.1.26