/[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 1340 - (show annotations)
Wed Dec 6 13:11:35 2006 UTC (17 years, 5 months ago) by ossman_
File MIME type: text/plain
File size: 12580 byte(s)
Update rdpsnd_negotiate() to new information.

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

  ViewVC Help
Powered by ViewVC 1.1.26