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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1353 - (show annotations)
Sun Dec 24 15:22:15 2006 UTC (17 years, 5 months ago) by stargo
Original Path: sourceforge.net/trunk/rdesktop/rdpsnd.c
File MIME type: text/plain
File size: 14354 byte(s)
fix device_available which I broke in a previous commit

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

  ViewVC Help
Powered by ViewVC 1.1.26