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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1273 - (show annotations)
Sun Oct 1 10:56:39 2006 UTC (17 years, 7 months ago) by stargo
Original Path: sourceforge.net/trunk/rdesktop/rdpsnd.c
File MIME type: text/plain
File size: 10153 byte(s)
let 'make proto' generate correct prototypes for rdpsnd

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

  ViewVC Help
Powered by ViewVC 1.1.26