/[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 510 - (hide annotations)
Thu Oct 23 11:11:31 2003 UTC (20 years, 6 months ago) by stargo
File MIME type: text/plain
File size: 6180 byte(s)
fix for oss-driver (too fast acks)
some g_ prefixes for globals

1 matthewc 476 /*
2     rdesktop: A Remote Desktop Protocol client.
3     Sound Channel Process Functions - Sun
4     Copyright (C) Matthew Chapman 2003
5     Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003
6     Copyright (C) Michael Gernoth mike@zerfleddert.de 2003
7    
8     This program is free software; you can redistribute it and/or modify
9     it under the terms of the GNU General Public License as published by
10     the Free Software Foundation; either version 2 of the License, or
11     (at your option) any later version.
12    
13     This program is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     GNU General Public License for more details.
17    
18     You should have received a copy of the GNU General Public License
19     along with this program; if not, write to the Free Software
20     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21     */
22    
23     #include "rdesktop.h"
24     #include <unistd.h>
25     #include <fcntl.h>
26     #include <errno.h>
27     #include <sys/ioctl.h>
28 matthewc 477 #include <sys/audioio.h>
29 matthewc 476 #include <stropts.h>
30    
31     #define MAX_QUEUE 10
32    
33     int g_dsp_fd;
34 stargo 504 BOOL g_dsp_busy = False;
35 stargo 510 static BOOL g_reopened;
36     static BOOL g_swapaudio;
37     static short g_samplewidth;
38 matthewc 476
39 astrand 499 static struct audio_packet
40     {
41 matthewc 476 struct stream s;
42     uint16 tick;
43     uint8 index;
44     } packet_queue[MAX_QUEUE];
45     static unsigned int queue_hi, queue_lo;
46    
47     BOOL
48     wave_out_open(void)
49     {
50 matthewc 477 char *dsp_dev = getenv("AUDIODEV");
51 matthewc 476
52 astrand 499 if (dsp_dev == NULL)
53 matthewc 477 {
54 astrand 499 dsp_dev = "/dev/audio";
55 matthewc 477 }
56    
57 astrand 499 if ((g_dsp_fd = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1)
58 matthewc 476 {
59     perror(dsp_dev);
60     return False;
61     }
62    
63     /* Non-blocking so that user interface is responsive */
64 astrand 499 fcntl(g_dsp_fd, F_SETFL, fcntl(g_dsp_fd, F_GETFL) | O_NONBLOCK);
65    
66 matthewc 476 queue_lo = queue_hi = 0;
67 stargo 510 g_reopened = True;
68 astrand 499
69 matthewc 476 return True;
70     }
71    
72     void
73     wave_out_close(void)
74     {
75 matthewc 477 /* Ack all remaining packets */
76 astrand 499 while (queue_lo != queue_hi)
77 matthewc 477 {
78     rdpsnd_send_completion(packet_queue[queue_lo].tick, packet_queue[queue_lo].index);
79     free(packet_queue[queue_lo].s.data);
80     queue_lo = (queue_lo + 1) % MAX_QUEUE;
81     }
82    
83     /* Flush the audiobuffer */
84 astrand 499 ioctl(g_dsp_fd, I_FLUSH, FLUSHW);
85 matthewc 476 close(g_dsp_fd);
86     }
87    
88     BOOL
89 astrand 499 wave_out_format_supported(WAVEFORMATEX * pwfx)
90 matthewc 476 {
91     if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
92     return False;
93     if ((pwfx->nChannels != 1) && (pwfx->nChannels != 2))
94     return False;
95     if ((pwfx->wBitsPerSample != 8) && (pwfx->wBitsPerSample != 16))
96     return False;
97    
98     return True;
99     }
100    
101     BOOL
102 astrand 499 wave_out_set_format(WAVEFORMATEX * pwfx)
103 matthewc 476 {
104     audio_info_t info;
105     int test = 1;
106    
107     ioctl(g_dsp_fd, AUDIO_DRAIN, 0);
108 stargo 510 g_swapaudio = False;
109 matthewc 476 AUDIO_INITINFO(&info);
110    
111    
112     if (pwfx->wBitsPerSample == 8)
113     {
114     info.play.encoding = AUDIO_ENCODING_LINEAR8;
115     }
116     else if (pwfx->wBitsPerSample == 16)
117     {
118     info.play.encoding = AUDIO_ENCODING_LINEAR;
119 matthewc 477 /* Do we need to swap the 16bit values? (Are we BigEndian) */
120 stargo 510 g_swapaudio = !(*(uint8 *) (&test));
121 matthewc 476 }
122    
123 stargo 510 g_samplewidth = pwfx->wBitsPerSample / 8;
124 stargo 491
125 astrand 499 if (pwfx->nChannels == 1)
126     {
127 matthewc 476 info.play.channels = AUDIO_CHANNELS_MONO;
128     }
129 astrand 499 else if (pwfx->nChannels == 2)
130 matthewc 476 {
131     info.play.channels = AUDIO_CHANNELS_STEREO;
132 stargo 510 g_samplewidth *= 2;
133 matthewc 476 }
134    
135     info.play.sample_rate = pwfx->nSamplesPerSec;
136     info.play.precision = pwfx->wBitsPerSample;
137     info.play.samples = 0;
138     info.play.eof = 0;
139     info.play.error = 0;
140 stargo 510 g_reopened = True;
141 matthewc 476
142     if (ioctl(g_dsp_fd, AUDIO_SETINFO, &info) == -1)
143     {
144     perror("AUDIO_SETINFO");
145     close(g_dsp_fd);
146     return False;
147     }
148    
149     return True;
150     }
151    
152     void
153 stargo 491 wave_out_volume(uint16 left, uint16 right)
154     {
155     audio_info_t info;
156     uint balance;
157     uint volume;
158    
159     if (ioctl(g_dsp_fd, AUDIO_GETINFO, &info) == -1)
160     {
161     perror("AUDIO_GETINFO");
162     return;
163     }
164    
165     volume = (left > right) ? left : right;
166    
167 astrand 499 if (volume / AUDIO_MID_BALANCE != 0)
168 stargo 491 {
169 astrand 499 balance =
170     AUDIO_MID_BALANCE - (left / (volume / AUDIO_MID_BALANCE)) +
171     (right / (volume / AUDIO_MID_BALANCE));
172 stargo 491 }
173     else
174     {
175     balance = AUDIO_MID_BALANCE;
176     }
177    
178 astrand 499 info.play.gain = volume / (65536 / AUDIO_MAX_GAIN);
179 stargo 491 info.play.balance = balance;
180    
181     if (ioctl(g_dsp_fd, AUDIO_SETINFO, &info) == -1)
182     {
183     perror("AUDIO_SETINFO");
184     return;
185     }
186     }
187    
188     void
189 matthewc 476 wave_out_write(STREAM s, uint16 tick, uint8 index)
190     {
191     struct audio_packet *packet = &packet_queue[queue_hi];
192     unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
193    
194     if (next_hi == queue_lo)
195     {
196     error("No space to queue audio packet\n");
197     return;
198     }
199 astrand 499
200 matthewc 476 queue_hi = next_hi;
201    
202     packet->s = *s;
203     packet->tick = tick;
204     packet->index = index;
205 stargo 491 packet->s.p += 4;
206 matthewc 476
207     /* we steal the data buffer from s, give it a new one */
208     s->data = malloc(s->size);
209    
210     if (!g_dsp_busy)
211     wave_out_play();
212     }
213    
214     void
215     wave_out_play(void)
216     {
217     struct audio_packet *packet;
218     audio_info_t info;
219     ssize_t len;
220     unsigned int i;
221     uint8 swap;
222     STREAM out;
223     static BOOL swapped = False;
224     static BOOL sentcompletion = True;
225 matthewc 477 static uint32 samplecnt = 0;
226     static uint32 numsamples;
227 matthewc 476
228     while (1)
229     {
230 stargo 510 if (g_reopened)
231 matthewc 477 {
232     /* Device was just (re)openend */
233     samplecnt = 0;
234     swapped = False;
235     sentcompletion = True;
236 stargo 510 g_reopened = False;
237 matthewc 477 }
238    
239 matthewc 476 if (queue_lo == queue_hi)
240     {
241     g_dsp_busy = 0;
242     return;
243     }
244    
245     packet = &packet_queue[queue_lo];
246     out = &packet->s;
247    
248 matthewc 477 /* Swap the current packet, but only once */
249 stargo 510 if (g_swapaudio && !swapped)
250 matthewc 476 {
251 astrand 499 for (i = 0; i < out->end - out->p; i += 2)
252 matthewc 476 {
253     swap = *(out->p + i);
254 stargo 491 *(out->p + i) = *(out->p + i + 1);
255 matthewc 476 *(out->p + i + 1) = swap;
256     }
257 stargo 491 swapped = True;
258 matthewc 476 }
259    
260 astrand 499 if (sentcompletion)
261 matthewc 476 {
262     sentcompletion = False;
263 stargo 510 numsamples = (out->end - out->p) / g_samplewidth;
264 matthewc 476 }
265    
266 astrand 499 len = 0;
267 matthewc 476
268 astrand 499 if (out->end != out->p)
269 matthewc 476 {
270     len = write(g_dsp_fd, out->p, out->end - out->p);
271     if (len == -1)
272     {
273     if (errno != EWOULDBLOCK)
274     perror("write audio");
275     g_dsp_busy = 1;
276     return;
277     }
278     }
279    
280     out->p += len;
281     if (out->p == out->end)
282     {
283     if (ioctl(g_dsp_fd, AUDIO_GETINFO, &info) == -1)
284     {
285     perror("AUDIO_GETINFO");
286     return;
287     }
288 matthewc 477
289     /* Ack the packet, if we have played at least 70% */
290 astrand 499 if (info.play.samples >= samplecnt + ((numsamples * 7) / 10))
291 matthewc 476 {
292 matthewc 477 samplecnt += numsamples;
293 matthewc 476 rdpsnd_send_completion(packet->tick, packet->index);
294     free(out->data);
295     queue_lo = (queue_lo + 1) % MAX_QUEUE;
296     swapped = False;
297     sentcompletion = True;
298     }
299     else
300     {
301     g_dsp_busy = 1;
302     return;
303     }
304     }
305     }
306     }

  ViewVC Help
Powered by ViewVC 1.1.26