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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1256 - (show annotations)
Sun Sep 17 11:42:22 2006 UTC (17 years, 7 months ago) by stargo
File MIME type: text/plain
File size: 9431 byte(s)
fix SunCC errors/warnings and configure-variable-usage (LIBS/LDFLAGS)

1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Sound Channel Process Functions
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 "rdpsnd.h"
24
25 #define RDPSND_CLOSE 1
26 #define RDPSND_WRITE 2
27 #define RDPSND_SET_VOLUME 3
28 #define RDPSND_UNKNOWN4 4
29 #define RDPSND_COMPLETION 5
30 #define RDPSND_SERVERTICK 6
31 #define RDPSND_NEGOTIATE 7
32
33 #define MAX_FORMATS 10
34 #define MAX_QUEUE 10
35
36 BOOL g_dsp_busy = False;
37 int g_dsp_fd;
38
39 static VCHANNEL *rdpsnd_channel;
40 static struct audio_driver *drivers = NULL;
41 struct audio_driver *current_driver = NULL;
42
43 static BOOL device_open;
44 static WAVEFORMATEX formats[MAX_FORMATS];
45 static unsigned int format_count;
46 static unsigned int current_format;
47 unsigned int queue_hi, queue_lo;
48 struct audio_packet packet_queue[MAX_QUEUE];
49
50 void (*wave_out_play) (void);
51
52 static STREAM
53 rdpsnd_init_packet(uint16 type, uint16 size)
54 {
55 STREAM s;
56
57 s = channel_init(rdpsnd_channel, size + 4);
58 out_uint16_le(s, type);
59 out_uint16_le(s, size);
60 return s;
61 }
62
63 static void
64 rdpsnd_send(STREAM s)
65 {
66 #ifdef RDPSND_DEBUG
67 printf("RDPSND send:\n");
68 hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);
69 #endif
70
71 channel_send(s, rdpsnd_channel);
72 }
73
74 void
75 rdpsnd_send_completion(uint16 tick, uint8 packet_index)
76 {
77 STREAM s;
78
79 s = rdpsnd_init_packet(RDPSND_COMPLETION, 4);
80 out_uint16_le(s, tick);
81 out_uint8(s, packet_index);
82 out_uint8(s, 0);
83 s_mark_end(s);
84 rdpsnd_send(s);
85 }
86
87 static void
88 rdpsnd_process_negotiate(STREAM in)
89 {
90 unsigned int in_format_count, i;
91 WAVEFORMATEX *format;
92 STREAM out;
93 BOOL device_available = False;
94 int readcnt;
95 int discardcnt;
96
97 in_uint8s(in, 14); /* flags, volume, pitch, UDP port */
98 in_uint16_le(in, in_format_count);
99 in_uint8s(in, 4); /* pad, status, pad */
100
101 if (current_driver->wave_out_open())
102 {
103 current_driver->wave_out_close();
104 device_available = True;
105 }
106
107 format_count = 0;
108 if (s_check_rem(in, 18 * in_format_count))
109 {
110 for (i = 0; i < in_format_count; i++)
111 {
112 format = &formats[format_count];
113 in_uint16_le(in, format->wFormatTag);
114 in_uint16_le(in, format->nChannels);
115 in_uint32_le(in, format->nSamplesPerSec);
116 in_uint32_le(in, format->nAvgBytesPerSec);
117 in_uint16_le(in, format->nBlockAlign);
118 in_uint16_le(in, format->wBitsPerSample);
119 in_uint16_le(in, format->cbSize);
120
121 /* read in the buffer of unknown use */
122 readcnt = format->cbSize;
123 discardcnt = 0;
124 if (format->cbSize > MAX_CBSIZE)
125 {
126 fprintf(stderr, "cbSize too large for buffer: %d\n",
127 format->cbSize);
128 readcnt = MAX_CBSIZE;
129 discardcnt = format->cbSize - MAX_CBSIZE;
130 }
131 in_uint8a(in, format->cb, readcnt);
132 in_uint8s(in, discardcnt);
133
134 if (device_available && current_driver->wave_out_format_supported(format))
135 {
136 format_count++;
137 if (format_count == MAX_FORMATS)
138 break;
139 }
140 }
141 }
142
143 out = rdpsnd_init_packet(RDPSND_NEGOTIATE | 0x200, 20 + 18 * format_count);
144 out_uint32_le(out, 3); /* flags */
145 out_uint32(out, 0xffffffff); /* volume */
146 out_uint32(out, 0); /* pitch */
147 out_uint16(out, 0); /* UDP port */
148
149 out_uint16_le(out, format_count);
150 out_uint8(out, 0x95); /* pad? */
151 out_uint16_le(out, 2); /* status */
152 out_uint8(out, 0x77); /* pad? */
153
154 for (i = 0; i < format_count; i++)
155 {
156 format = &formats[i];
157 out_uint16_le(out, format->wFormatTag);
158 out_uint16_le(out, format->nChannels);
159 out_uint32_le(out, format->nSamplesPerSec);
160 out_uint32_le(out, format->nAvgBytesPerSec);
161 out_uint16_le(out, format->nBlockAlign);
162 out_uint16_le(out, format->wBitsPerSample);
163 out_uint16(out, 0); /* cbSize */
164 }
165
166 s_mark_end(out);
167 rdpsnd_send(out);
168 }
169
170 static void
171 rdpsnd_process_servertick(STREAM in)
172 {
173 uint16 tick1, tick2;
174 STREAM out;
175
176 /* in_uint8s(in, 4); unknown */
177 in_uint16_le(in, tick1);
178 in_uint16_le(in, tick2);
179
180 out = rdpsnd_init_packet(RDPSND_SERVERTICK | 0x2300, 4);
181 out_uint16_le(out, tick1);
182 out_uint16_le(out, tick2);
183 s_mark_end(out);
184 rdpsnd_send(out);
185 }
186
187 static void
188 rdpsnd_process(STREAM s)
189 {
190 uint8 type;
191 uint16 datalen;
192 uint32 volume;
193 static uint16 tick, format;
194 static uint8 packet_index;
195 static BOOL awaiting_data_packet;
196
197 #ifdef RDPSND_DEBUG
198 printf("RDPSND recv:\n");
199 hexdump(s->p, s->end - s->p);
200 #endif
201
202 if (awaiting_data_packet)
203 {
204 if (format >= MAX_FORMATS)
205 {
206 error("RDPSND: Invalid format index\n");
207 return;
208 }
209
210 if (!device_open || (format != current_format))
211 {
212 if (!device_open && !current_driver->wave_out_open())
213 {
214 rdpsnd_send_completion(tick, packet_index);
215 return;
216 }
217 if (!current_driver->wave_out_set_format(&formats[format]))
218 {
219 rdpsnd_send_completion(tick, packet_index);
220 current_driver->wave_out_close();
221 device_open = False;
222 return;
223 }
224 device_open = True;
225 current_format = format;
226 }
227
228 current_driver->wave_out_write(s, tick, packet_index);
229 awaiting_data_packet = False;
230 return;
231 }
232
233 in_uint8(s, type);
234 in_uint8s(s, 1); /* unknown? */
235 in_uint16_le(s, datalen);
236
237 switch (type)
238 {
239 case RDPSND_WRITE:
240 in_uint16_le(s, tick);
241 in_uint16_le(s, format);
242 in_uint8(s, packet_index);
243 awaiting_data_packet = True;
244 break;
245 case RDPSND_CLOSE:
246 current_driver->wave_out_close();
247 device_open = False;
248 break;
249 case RDPSND_NEGOTIATE:
250 rdpsnd_process_negotiate(s);
251 break;
252 case RDPSND_SERVERTICK:
253 rdpsnd_process_servertick(s);
254 break;
255 case RDPSND_SET_VOLUME:
256 in_uint32(s, volume);
257 if (device_open)
258 {
259 current_driver->wave_out_volume((volume & 0xffff),
260 (volume & 0xffff0000) >> 16);
261 }
262 break;
263 default:
264 unimpl("RDPSND packet type %d\n", type);
265 break;
266 }
267 }
268
269 BOOL
270 rdpsnd_init(void)
271 {
272 rdpsnd_channel =
273 channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
274 rdpsnd_process);
275
276 return (rdpsnd_channel != NULL);
277 }
278
279 BOOL
280 rdpsnd_auto_open(void)
281 {
282 current_driver = drivers;
283 while (current_driver != NULL)
284 {
285 DEBUG(("trying %s...\n", current_driver->name));
286 if (current_driver->wave_out_open())
287 {
288 DEBUG(("selected %s\n", current_driver->name));
289 return True;
290 }
291 g_dsp_fd = 0;
292 current_driver = current_driver->next;
293 }
294
295 warning("no working audio-driver found\n");
296
297 return False;
298 }
299
300 void
301 rdpsnd_register_drivers(char *options)
302 {
303 struct audio_driver **reg;
304
305 /* The order of registrations define the probe-order
306 when opening the device for the first time */
307 reg = &drivers;
308 #if defined(RDPSND_ALSA)
309 *reg = alsa_register(options);
310 reg = &((*reg)->next);
311 #endif
312 #if defined(RDPSND_OSS)
313 *reg = oss_register(options);
314 reg = &((*reg)->next);
315 #endif
316 #if defined(RDPSND_SUN)
317 *reg = sun_register(options);
318 reg = &((*reg)->next);
319 #endif
320 #if defined(RDPSND_SGI)
321 *reg = sgi_register(options);
322 reg = &((*reg)->next);
323 #endif
324 #if defined(RDPSND_LIBAO)
325 *reg = libao_register(options);
326 reg = &((*reg)->next);
327 #endif
328 }
329
330 BOOL
331 rdpsnd_select_driver(char *driver, char *options)
332 {
333 static struct audio_driver auto_driver;
334 struct audio_driver *pos;
335
336 drivers = NULL;
337 rdpsnd_register_drivers(options);
338
339 if (!driver)
340 {
341 auto_driver.wave_out_open = &rdpsnd_auto_open;
342 current_driver = &auto_driver;
343 return True;
344 }
345
346 pos = drivers;
347 while (pos != NULL)
348 {
349 if (!strcmp(pos->name, driver))
350 {
351 DEBUG(("selected %s\n", pos->name));
352 current_driver = pos;
353 return True;
354 }
355 pos = pos->next;
356 }
357 return False;
358 }
359
360 void
361 rdpsnd_show_help(void)
362 {
363 struct audio_driver *pos;
364
365 rdpsnd_register_drivers(NULL);
366
367 pos = drivers;
368 while (pos != NULL)
369 {
370 fprintf(stderr, " %s:\t%s\n", pos->name, pos->description);
371 pos = pos->next;
372 }
373 }
374
375 inline void
376 rdpsnd_play(void)
377 {
378 current_driver->wave_out_play();
379 }
380
381 void
382 rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)
383 {
384 struct audio_packet *packet = &packet_queue[queue_hi];
385 unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
386
387 if (next_hi == queue_lo)
388 {
389 error("No space to queue audio packet\n");
390 return;
391 }
392
393 queue_hi = next_hi;
394
395 packet->s = *s;
396 packet->tick = tick;
397 packet->index = index;
398 packet->s.p += 4;
399
400 /* we steal the data buffer from s, give it a new one */
401 s->data = malloc(s->size);
402
403 if (!g_dsp_busy)
404 current_driver->wave_out_play();
405 }
406
407 inline struct audio_packet *
408 rdpsnd_queue_current_packet(void)
409 {
410 return &packet_queue[queue_lo];
411 }
412
413 inline BOOL
414 rdpsnd_queue_empty(void)
415 {
416 return (queue_lo == queue_hi);
417 }
418
419 inline void
420 rdpsnd_queue_init(void)
421 {
422 queue_lo = queue_hi = 0;
423 }
424
425 inline void
426 rdpsnd_queue_next(void)
427 {
428 free(packet_queue[queue_lo].s.data);
429 queue_lo = (queue_lo + 1) % MAX_QUEUE;
430 }
431
432 inline int
433 rdpsnd_queue_next_tick(void)
434 {
435 if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
436 {
437 return packet_queue[(queue_lo + 1) % MAX_QUEUE].tick;
438 }
439 else
440 {
441 return (packet_queue[queue_lo].tick + 65535) % 65536;
442 }
443 }

  ViewVC Help
Powered by ViewVC 1.1.26