/[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

Contents of /sourceforge.net/trunk/rdesktop/rdpsnd_sun.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 504 - (show annotations)
Sun Oct 19 11:59:41 2003 UTC (20 years, 7 months ago) by stargo
File MIME type: text/plain
File size: 6154 byte(s)
Make sure that g_dsp_busy is initialized to False

1 /*
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 #include <sys/audioio.h>
29 #include <stropts.h>
30
31 #define MAX_QUEUE 10
32
33 int g_dsp_fd;
34 BOOL g_dsp_busy = False;
35 static BOOL reopened;
36 static BOOL swapaudio;
37 static short samplewidth;
38
39 static struct audio_packet
40 {
41 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 char *dsp_dev = getenv("AUDIODEV");
51
52 if (dsp_dev == NULL)
53 {
54 dsp_dev = "/dev/audio";
55 }
56
57 if ((g_dsp_fd = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1)
58 {
59 perror(dsp_dev);
60 return False;
61 }
62
63 /* Non-blocking so that user interface is responsive */
64 fcntl(g_dsp_fd, F_SETFL, fcntl(g_dsp_fd, F_GETFL) | O_NONBLOCK);
65
66 queue_lo = queue_hi = 0;
67 reopened = True;
68
69 return True;
70 }
71
72 void
73 wave_out_close(void)
74 {
75 /* Ack all remaining packets */
76 while (queue_lo != queue_hi)
77 {
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 ioctl(g_dsp_fd, I_FLUSH, FLUSHW);
85 close(g_dsp_fd);
86 }
87
88 BOOL
89 wave_out_format_supported(WAVEFORMATEX * pwfx)
90 {
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 wave_out_set_format(WAVEFORMATEX * pwfx)
103 {
104 audio_info_t info;
105 int test = 1;
106
107 ioctl(g_dsp_fd, AUDIO_DRAIN, 0);
108 swapaudio = False;
109 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 /* Do we need to swap the 16bit values? (Are we BigEndian) */
120 swapaudio = !(*(uint8 *) (&test));
121 }
122
123 samplewidth = pwfx->wBitsPerSample / 8;
124
125 if (pwfx->nChannels == 1)
126 {
127 info.play.channels = AUDIO_CHANNELS_MONO;
128 }
129 else if (pwfx->nChannels == 2)
130 {
131 info.play.channels = AUDIO_CHANNELS_STEREO;
132 samplewidth *= 2;
133 }
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 reopened = True;
141
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 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 if (volume / AUDIO_MID_BALANCE != 0)
168 {
169 balance =
170 AUDIO_MID_BALANCE - (left / (volume / AUDIO_MID_BALANCE)) +
171 (right / (volume / AUDIO_MID_BALANCE));
172 }
173 else
174 {
175 balance = AUDIO_MID_BALANCE;
176 }
177
178 info.play.gain = volume / (65536 / AUDIO_MAX_GAIN);
179 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 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
200 queue_hi = next_hi;
201
202 packet->s = *s;
203 packet->tick = tick;
204 packet->index = index;
205 packet->s.p += 4;
206
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 static uint32 samplecnt = 0;
226 static uint32 numsamples;
227
228 while (1)
229 {
230 if (reopened)
231 {
232 /* Device was just (re)openend */
233 samplecnt = 0;
234 swapped = False;
235 sentcompletion = True;
236 reopened = False;
237 }
238
239 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 /* Swap the current packet, but only once */
249 if (swapaudio && !swapped)
250 {
251 for (i = 0; i < out->end - out->p; i += 2)
252 {
253 swap = *(out->p + i);
254 *(out->p + i) = *(out->p + i + 1);
255 *(out->p + i + 1) = swap;
256 }
257 swapped = True;
258 }
259
260 if (sentcompletion)
261 {
262 sentcompletion = False;
263 numsamples = (out->end - out->p) / samplewidth;
264 }
265
266 len = 0;
267
268 if (out->end != out->p)
269 {
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
289 /* Ack the packet, if we have played at least 70% */
290 if (info.play.samples >= samplecnt + ((numsamples * 7) / 10))
291 {
292 samplecnt += numsamples;
293 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