/[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 1346 - (show annotations)
Thu Dec 7 15:23:45 2006 UTC (17 years, 5 months ago) by ossman_
Original Path: sourceforge.net/trunk/rdesktop/rdpsnd.c
File MIME type: text/plain
File size: 14276 byte(s)
Abstract select() handling in rdpsnd so that backends can do their thing
more correctly.

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

  ViewVC Help
Powered by ViewVC 1.1.26