VirtualBox

source: vbox/trunk/src/VBox/RDP/client-1.8.3/rdpsnd.c@ 69046

Last change on this file since 69046 was 55123, checked in by vboxsync, 10 years ago

rdesktop 1.8.3 modified for VBox

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.6 KB
Line 
1/* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Sound Channel Process Functions
4 Copyright 2006-2010 Pierre Ossman <ossman@cendio.se> for Cendio AB
5 Copyright 2009-2011 Peter Astrand <astrand@cendio.se> for Cendio AB
6 Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 2003-2008
7 Copyright (C) GuoJunBo <guojunbo@ict.ac.cn> 2003
8
9 This program is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
21*/
22
23/*
24 * Oracle GPL Disclaimer: For the avoidance of doubt, except that if any license choice
25 * other than GPL or LGPL is available it will apply instead, Oracle elects to use only
26 * the General Public License version 2 (GPLv2) at this time for any software where
27 * a choice of GPL license versions is made available with the language indicating
28 * that GPLv2 or any later version may be used, or where a choice of which version
29 * of the GPL is applied is otherwise unspecified.
30 */
31
32#include <assert.h>
33
34#include "rdesktop.h"
35#include "rdpsnd.h"
36#include "rdpsnd_dsp.h"
37
38#define RDPSND_CLOSE 1
39#define RDPSND_WRITE 2
40#define RDPSND_SET_VOLUME 3
41#define RDPSND_UNKNOWN4 4
42#define RDPSND_COMPLETION 5
43#define RDPSND_PING 6
44#define RDPSND_NEGOTIATE 7
45
46#define RDPSND_REC_NEGOTIATE 39
47#define RDPSND_REC_START 40
48#define RDPSND_REC_STOP 41
49#define RDPSND_REC_DATA 42
50#define RDPSND_REC_SET_VOLUME 43
51
52/* Special flag for RDPSND recording extension,
53 not defined in MS specs.
54
55 See doc/rdpsnd-rec.txt for more information.
56*/
57#define RDPSND_FLAG_RECORD 0x00800000
58
59#define MAX_FORMATS 10
60#define MAX_QUEUE 50
61
62extern RD_BOOL g_rdpsnd;
63
64static VCHANNEL *rdpsnd_channel;
65static VCHANNEL *rdpsnddbg_channel;
66static struct audio_driver *drivers = NULL;
67struct audio_driver *current_driver = NULL;
68
69static RD_BOOL rdpsnd_negotiated;
70static RD_BOOL rdpsnd_rec_negotiated;
71
72static RD_BOOL device_open;
73static RD_BOOL rec_device_open;
74
75static RD_WAVEFORMATEX formats[MAX_FORMATS];
76static unsigned int format_count;
77static unsigned int current_format;
78
79static RD_WAVEFORMATEX rec_formats[MAX_FORMATS];
80static unsigned int rec_format_count;
81static unsigned int rec_current_format;
82
83unsigned int queue_hi, queue_lo, queue_pending;
84struct audio_packet packet_queue[MAX_QUEUE];
85
86static char record_buffer[8192];
87static uint32 record_buffer_size;
88
89static uint8 packet_opcode;
90static struct stream packet;
91
92void (*wave_out_play) (void);
93
94static void rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index);
95static void rdpsnd_queue_init(void);
96static void rdpsnd_queue_clear(void);
97static void rdpsnd_queue_complete_pending(void);
98static long rdpsnd_queue_next_completion(void);
99
100static STREAM
101rdpsnd_init_packet(uint16 type, uint16 size)
102{
103 STREAM s;
104
105 s = channel_init(rdpsnd_channel, size + 4);
106 out_uint16_le(s, type);
107 out_uint16_le(s, size);
108 return s;
109}
110
111static void
112rdpsnd_send(STREAM s)
113{
114 channel_send(s, rdpsnd_channel);
115}
116
117static void
118rdpsnd_send_completion(uint16 tick, uint8 packet_index)
119{
120 STREAM s;
121
122 s = rdpsnd_init_packet(RDPSND_COMPLETION, 4);
123 out_uint16_le(s, tick);
124 out_uint8(s, packet_index);
125 out_uint8(s, 0);
126 s_mark_end(s);
127 rdpsnd_send(s);
128
129 DEBUG_SOUND(("RDPSND: -> RDPSND_COMPLETION(tick: %u, index: %u)\n",
130 (unsigned) tick, (unsigned) packet_index));
131}
132
133static void
134rdpsnd_flush_record(void)
135{
136 STREAM s;
137 unsigned int chunk_size;
138 char *data;
139
140 if (record_buffer_size == 0)
141 return;
142
143 assert(record_buffer_size <= sizeof(record_buffer));
144
145 data = record_buffer;
146
147 /*
148 * Microsoft's RDP server keeps dropping chunks, so we need to
149 * transmit everything inside one channel fragment or we risk
150 * making the rdpsnd server go out of sync with the byte stream.
151 */
152 while (record_buffer_size)
153 {
154 if (record_buffer_size < 1596)
155 chunk_size = record_buffer_size;
156 else
157 chunk_size = 1596;
158
159 s = rdpsnd_init_packet(RDPSND_REC_DATA, chunk_size);
160 out_uint8p(s, data, chunk_size);
161
162 s_mark_end(s);
163 rdpsnd_send(s);
164
165 data = data + chunk_size;
166 record_buffer_size -= chunk_size;
167
168 DEBUG_SOUND(("RDPSND: -> RDPSND_REC_DATA(length: %u)\n", (unsigned) chunk_size));
169 }
170
171 record_buffer_size = 0;
172}
173
174static void
175rdpsnd_clear_record(void)
176{
177 /*
178 * Silently drop everything we have in the record buffer as
179 * we've somehow gotten a reset in regard to the server.
180 */
181 record_buffer_size = 0;
182}
183
184void
185rdpsnd_record(const void *data, unsigned int size)
186{
187 uint32 remain, chunk;
188
189 assert(rec_device_open);
190
191 while (size)
192 {
193 remain = sizeof(record_buffer) - record_buffer_size;
194
195 if (size >= remain)
196 chunk = remain;
197 else
198 chunk = size;
199
200 memcpy(record_buffer + record_buffer_size, data, chunk);
201
202#ifdef B_ENDIAN
203 if (current_driver->need_byteswap_on_be)
204 rdpsnd_dsp_swapbytes(record_buffer + record_buffer_size,
205 chunk, &rec_formats[rec_current_format]);
206#endif
207
208 record_buffer_size += chunk;
209
210 data = (const char *) data + chunk;
211 size -= chunk;
212
213 if (record_buffer_size == sizeof(record_buffer))
214 rdpsnd_flush_record();
215 }
216}
217
218static RD_BOOL
219rdpsnd_auto_select(void)
220{
221 static RD_BOOL failed = False;
222
223 if (!failed)
224 {
225 current_driver = drivers;
226 while (current_driver != NULL)
227 {
228 DEBUG(("trying %s...\n", current_driver->name));
229 if (current_driver->wave_out_open())
230 {
231 DEBUG(("selected %s\n", current_driver->name));
232 current_driver->wave_out_close();
233 return True;
234 }
235 current_driver = current_driver->next;
236 }
237
238 warning("no working audio-driver found\n");
239 failed = True;
240 current_driver = NULL;
241 }
242
243 return False;
244}
245
246static void
247rdpsnd_process_negotiate(STREAM in)
248{
249 uint16 in_format_count, i;
250 uint8 pad;
251 uint16 version;
252 RD_WAVEFORMATEX *format;
253 STREAM out;
254 RD_BOOL device_available = False;
255 int readcnt;
256 int discardcnt;
257
258 in_uint8s(in, 14); /* initial bytes not valid from server */
259 in_uint16_le(in, in_format_count);
260 in_uint8(in, pad);
261 in_uint16_le(in, version);
262 in_uint8s(in, 1); /* padding */
263
264 DEBUG_SOUND(("RDPSND: RDPSND_NEGOTIATE(formats: %d, pad: 0x%02x, version: %x)\n",
265 (int) in_format_count, (unsigned) pad, (unsigned) version));
266
267 if (rdpsnd_negotiated)
268 {
269 error("RDPSND: Extra RDPSND_NEGOTIATE in the middle of a session\n");
270 /* Do a complete reset of the sound state */
271 rdpsnd_reset_state();
272 }
273
274 if (!current_driver && g_rdpsnd)
275 device_available = rdpsnd_auto_select();
276
277 if (current_driver && !device_available && current_driver->wave_out_open())
278 {
279 current_driver->wave_out_close();
280 device_available = True;
281 }
282
283 format_count = 0;
284 if (s_check_rem(in, 18 * in_format_count))
285 {
286 for (i = 0; i < in_format_count; i++)
287 {
288 format = &formats[format_count];
289 in_uint16_le(in, format->wFormatTag);
290 in_uint16_le(in, format->nChannels);
291 in_uint32_le(in, format->nSamplesPerSec);
292 in_uint32_le(in, format->nAvgBytesPerSec);
293 in_uint16_le(in, format->nBlockAlign);
294 in_uint16_le(in, format->wBitsPerSample);
295 in_uint16_le(in, format->cbSize);
296
297 /* read in the buffer of unknown use */
298 readcnt = format->cbSize;
299 discardcnt = 0;
300 if (format->cbSize > MAX_CBSIZE)
301 {
302 fprintf(stderr, "cbSize too large for buffer: %d\n",
303 format->cbSize);
304 readcnt = MAX_CBSIZE;
305 discardcnt = format->cbSize - MAX_CBSIZE;
306 }
307 in_uint8a(in, format->cb, readcnt);
308 in_uint8s(in, discardcnt);
309
310 if (current_driver && current_driver->wave_out_format_supported(format))
311 {
312 format_count++;
313 if (format_count == MAX_FORMATS)
314 break;
315 }
316 }
317 }
318
319 out = rdpsnd_init_packet(RDPSND_NEGOTIATE | 0x200, 20 + 18 * format_count);
320
321 uint32 flags = TSSNDCAPS_VOLUME;
322
323 /* if sound is enabled, set snd caps to alive to enable
324 transmision of audio from server */
325 if (g_rdpsnd)
326 {
327 flags |= TSSNDCAPS_ALIVE;
328 flags |= RDPSND_FLAG_RECORD;
329 }
330 out_uint32_le(out, flags); /* TSSNDCAPS flags */
331
332 out_uint32(out, 0xffffffff); /* volume */
333 out_uint32(out, 0); /* pitch */
334 out_uint16(out, 0); /* UDP port */
335
336 out_uint16_le(out, format_count);
337 out_uint8(out, 0); /* padding */
338 out_uint16_le(out, 2); /* version */
339 out_uint8(out, 0); /* padding */
340
341 for (i = 0; i < format_count; i++)
342 {
343 format = &formats[i];
344 out_uint16_le(out, format->wFormatTag);
345 out_uint16_le(out, format->nChannels);
346 out_uint32_le(out, format->nSamplesPerSec);
347 out_uint32_le(out, format->nAvgBytesPerSec);
348 out_uint16_le(out, format->nBlockAlign);
349 out_uint16_le(out, format->wBitsPerSample);
350 out_uint16(out, 0); /* cbSize */
351 }
352
353 s_mark_end(out);
354
355 DEBUG_SOUND(("RDPSND: -> RDPSND_NEGOTIATE(formats: %d)\n", (int) format_count));
356
357 rdpsnd_send(out);
358
359 rdpsnd_negotiated = True;
360}
361
362static void
363rdpsnd_process_ping(STREAM in)
364{
365 uint16 tick;
366 STREAM out;
367
368 in_uint16_le(in, tick);
369
370 DEBUG_SOUND(("RDPSND: RDPSND_PING(tick: 0x%04x)\n", (unsigned) tick));
371
372 out = rdpsnd_init_packet(RDPSND_PING | 0x2300, 4);
373 out_uint16_le(out, tick);
374 out_uint16_le(out, 0);
375 s_mark_end(out);
376 rdpsnd_send(out);
377
378 DEBUG_SOUND(("RDPSND: -> (tick: 0x%04x)\n", (unsigned) tick));
379}
380
381static void
382rdpsnd_process_rec_negotiate(STREAM in)
383{
384 uint16 in_format_count, i;
385 uint16 version;
386 RD_WAVEFORMATEX *format;
387 STREAM out;
388 RD_BOOL device_available = False;
389 int readcnt;
390 int discardcnt;
391
392 in_uint8s(in, 8); /* initial bytes not valid from server */
393 in_uint16_le(in, in_format_count);
394 in_uint16_le(in, version);
395
396 DEBUG_SOUND(("RDPSND: RDPSND_REC_NEGOTIATE(formats: %d, version: %x)\n",
397 (int) in_format_count, (unsigned) version));
398
399 if (rdpsnd_rec_negotiated)
400 {
401 error("RDPSND: Extra RDPSND_REC_NEGOTIATE in the middle of a session\n");
402 /* Do a complete reset of the sound state */
403 rdpsnd_reset_state();
404 }
405
406 if (!current_driver)
407 device_available = rdpsnd_auto_select();
408
409 if (current_driver && !device_available && current_driver->wave_in_open
410 && current_driver->wave_in_open())
411 {
412 current_driver->wave_in_close();
413 device_available = True;
414 }
415
416 rec_format_count = 0;
417 if (s_check_rem(in, 18 * in_format_count))
418 {
419 for (i = 0; i < in_format_count; i++)
420 {
421 format = &rec_formats[rec_format_count];
422 in_uint16_le(in, format->wFormatTag);
423 in_uint16_le(in, format->nChannels);
424 in_uint32_le(in, format->nSamplesPerSec);
425 in_uint32_le(in, format->nAvgBytesPerSec);
426 in_uint16_le(in, format->nBlockAlign);
427 in_uint16_le(in, format->wBitsPerSample);
428 in_uint16_le(in, format->cbSize);
429
430 /* read in the buffer of unknown use */
431 readcnt = format->cbSize;
432 discardcnt = 0;
433 if (format->cbSize > MAX_CBSIZE)
434 {
435 fprintf(stderr, "cbSize too large for buffer: %d\n",
436 format->cbSize);
437 readcnt = MAX_CBSIZE;
438 discardcnt = format->cbSize - MAX_CBSIZE;
439 }
440 in_uint8a(in, format->cb, readcnt);
441 in_uint8s(in, discardcnt);
442
443 if (current_driver && current_driver->wave_in_format_supported
444 && current_driver->wave_in_format_supported(format))
445 {
446 rec_format_count++;
447 if (rec_format_count == MAX_FORMATS)
448 break;
449 }
450 }
451 }
452
453 out = rdpsnd_init_packet(RDPSND_REC_NEGOTIATE, 12 + 18 * rec_format_count);
454 out_uint32_le(out, 0x00000000); /* flags */
455 out_uint32_le(out, 0xffffffff); /* volume */
456 out_uint16_le(out, rec_format_count);
457 out_uint16_le(out, 1); /* version */
458
459 for (i = 0; i < rec_format_count; i++)
460 {
461 format = &rec_formats[i];
462 out_uint16_le(out, format->wFormatTag);
463 out_uint16_le(out, format->nChannels);
464 out_uint32_le(out, format->nSamplesPerSec);
465 out_uint32_le(out, format->nAvgBytesPerSec);
466 out_uint16_le(out, format->nBlockAlign);
467 out_uint16_le(out, format->wBitsPerSample);
468 out_uint16(out, 0); /* cbSize */
469 }
470
471 s_mark_end(out);
472
473 DEBUG_SOUND(("RDPSND: -> RDPSND_REC_NEGOTIATE(formats: %d)\n", (int) rec_format_count));
474
475 rdpsnd_send(out);
476
477 rdpsnd_rec_negotiated = True;
478}
479
480static void
481rdpsnd_process_packet(uint8 opcode, STREAM s)
482{
483 uint16 vol_left, vol_right;
484 static uint16 tick, format;
485 static uint8 packet_index;
486
487 switch (opcode)
488 {
489 case RDPSND_WRITE:
490 in_uint16_le(s, tick);
491 in_uint16_le(s, format);
492 in_uint8(s, packet_index);
493 in_uint8s(s, 3);
494 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));
495
496 if (format >= MAX_FORMATS)
497 {
498 error("RDPSND: Invalid format index\n");
499 break;
500 }
501
502 if (!device_open || (format != current_format))
503 {
504 /*
505 * If we haven't selected a device by now, then either
506 * we've failed to find a working device, or the server
507 * is sending bogus RDPSND_WRITE.
508 */
509 if (!current_driver)
510 {
511 rdpsnd_send_completion(tick, packet_index);
512 break;
513 }
514 if (!device_open && !current_driver->wave_out_open())
515 {
516 rdpsnd_send_completion(tick, packet_index);
517 break;
518 }
519 if (!current_driver->wave_out_set_format(&formats[format]))
520 {
521 rdpsnd_send_completion(tick, packet_index);
522 current_driver->wave_out_close();
523 device_open = False;
524 break;
525 }
526 device_open = True;
527 current_format = format;
528 }
529
530 rdpsnd_queue_write(rdpsnd_dsp_process
531 (s->p, s->end - s->p, current_driver,
532 &formats[current_format]), tick, packet_index);
533 return;
534 break;
535 case RDPSND_CLOSE:
536 DEBUG_SOUND(("RDPSND: RDPSND_CLOSE()\n"));
537 if (device_open)
538 current_driver->wave_out_close();
539 device_open = False;
540 break;
541 case RDPSND_NEGOTIATE:
542 rdpsnd_process_negotiate(s);
543 break;
544 case RDPSND_PING:
545 rdpsnd_process_ping(s);
546 break;
547 case RDPSND_SET_VOLUME:
548 in_uint16_le(s, vol_left);
549 in_uint16_le(s, vol_right);
550 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));
551 if (device_open)
552 current_driver->wave_out_volume(vol_left, vol_right);
553 break;
554 case RDPSND_REC_NEGOTIATE:
555 rdpsnd_process_rec_negotiate(s);
556 break;
557 case RDPSND_REC_START:
558 in_uint16_le(s, format);
559 DEBUG_SOUND(("RDPSND: RDPSND_REC_START(format: %u)\n", (unsigned) format));
560
561 if (format >= MAX_FORMATS)
562 {
563 error("RDPSND: Invalid format index\n");
564 break;
565 }
566
567 if (rec_device_open)
568 {
569 error("RDPSND: Multiple RDPSND_REC_START\n");
570 break;
571 }
572
573 if (!current_driver->wave_in_open())
574 break;
575
576 if (!current_driver->wave_in_set_format(&rec_formats[format]))
577 {
578 error("RDPSND: Device not accepting format\n");
579 current_driver->wave_in_close();
580 break;
581 }
582 rec_current_format = format;
583 rec_device_open = True;
584 break;
585 case RDPSND_REC_STOP:
586 DEBUG_SOUND(("RDPSND: RDPSND_REC_STOP()\n"));
587 rdpsnd_flush_record();
588 if (rec_device_open)
589 current_driver->wave_in_close();
590 rec_device_open = False;
591 break;
592 case RDPSND_REC_SET_VOLUME:
593 in_uint16_le(s, vol_left);
594 in_uint16_le(s, vol_right);
595 DEBUG_SOUND(("RDPSND: RDPSND_REC_VOLUME(left: 0x%04x (%u %%), right: 0x%04x (%u %%))\n", (unsigned) vol_left, (unsigned) vol_left / 655, (unsigned) vol_right, (unsigned) vol_right / 655));
596 if (rec_device_open)
597 current_driver->wave_in_volume(vol_left, vol_right);
598 break;
599 default:
600 unimpl("RDPSND packet type %x\n", opcode);
601 break;
602 }
603}
604
605static void
606rdpsnd_process(STREAM s)
607{
608 uint16 len;
609
610 while (!s_check_end(s))
611 {
612 /* New packet */
613 if (packet.size == 0)
614 {
615 if ((s->end - s->p) < 4)
616 {
617 error("RDPSND: Split at packet header. Things will go south from here...\n");
618 return;
619 }
620 in_uint8(s, packet_opcode);
621 in_uint8s(s, 1); /* Padding */
622 in_uint16_le(s, len);
623
624 DEBUG_SOUND(("RDPSND: == Opcode %x Length: %d ==\n",
625 (int) packet_opcode, (int) len));
626
627 packet.p = packet.data;
628 packet.end = packet.data + len;
629 packet.size = len;
630 }
631 else
632 {
633 len = MIN(s->end - s->p, packet.end - packet.p);
634
635 /* Microsoft's server is so broken it's not even funny... */
636 if (packet_opcode == RDPSND_WRITE)
637 {
638 if ((packet.p - packet.data) < 12)
639 len = MIN(len, 12 - (packet.p - packet.data));
640 else if ((packet.p - packet.data) == 12)
641 {
642 DEBUG_SOUND(("RDPSND: Eating 4 bytes of %d bytes...\n",
643 len));
644 in_uint8s(s, 4);
645 len -= 4;
646 }
647 }
648
649 in_uint8a(s, packet.p, len);
650 packet.p += len;
651 }
652
653 /* Packet fully assembled */
654 if (packet.p == packet.end)
655 {
656 packet.p = packet.data;
657 rdpsnd_process_packet(packet_opcode, &packet);
658 packet.size = 0;
659 }
660 }
661}
662
663static RD_BOOL
664rdpsnddbg_line_handler(const char *line, void *data)
665{
666#ifdef WITH_DEBUG_SOUND
667 fprintf(stderr, "SNDDBG: %s\n", line);
668#endif
669 return True;
670}
671
672static void
673rdpsnddbg_process(STREAM s)
674{
675 unsigned int pkglen;
676 static char *rest = NULL;
677 char *buf;
678
679 pkglen = s->end - s->p;
680 /* str_handle_lines requires null terminated strings */
681 buf = (char *) xmalloc(pkglen + 1);
682 STRNCPY(buf, (char *) s->p, pkglen + 1);
683
684 str_handle_lines(buf, &rest, rdpsnddbg_line_handler, NULL);
685
686 xfree(buf);
687}
688
689static void
690rdpsnd_register_drivers(char *options)
691{
692 struct audio_driver **reg;
693
694 /* The order of registrations define the probe-order
695 when opening the device for the first time */
696 reg = &drivers;
697#if defined(RDPSND_ALSA)
698 *reg = alsa_register(options);
699 assert(*reg);
700 reg = &((*reg)->next);
701#endif
702#if defined(RDPSND_SUN)
703 *reg = sun_register(options);
704 assert(*reg);
705 reg = &((*reg)->next);
706#endif
707#if defined(RDPSND_OSS)
708 *reg = oss_register(options);
709 assert(*reg);
710 reg = &((*reg)->next);
711#endif
712#if defined(RDPSND_SGI)
713 *reg = sgi_register(options);
714 assert(*reg);
715 reg = &((*reg)->next);
716#endif
717#if defined(RDPSND_LIBAO)
718 *reg = libao_register(options);
719 assert(*reg);
720 reg = &((*reg)->next);
721#endif
722 *reg = NULL;
723}
724
725RD_BOOL
726rdpsnd_init(char *optarg)
727{
728 struct audio_driver *pos;
729 char *driver = NULL, *options = NULL;
730
731 drivers = NULL;
732
733 packet.data = (uint8 *) xmalloc(65536);
734 packet.p = packet.end = packet.data;
735 packet.size = 0;
736
737 rdpsnd_channel =
738 channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
739 rdpsnd_process);
740
741 rdpsnddbg_channel =
742 channel_register("snddbg", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
743 rdpsnddbg_process);
744
745 if ((rdpsnd_channel == NULL) || (rdpsnddbg_channel == NULL))
746 {
747 error("channel_register\n");
748 return False;
749 }
750
751 rdpsnd_queue_init();
752
753 if (optarg != NULL && strlen(optarg) > 0)
754 {
755 driver = options = optarg;
756
757 while (*options != '\0' && *options != ':')
758 options++;
759
760 if (*options == ':')
761 {
762 *options = '\0';
763 options++;
764 }
765
766 if (*options == '\0')
767 options = NULL;
768 }
769
770 rdpsnd_register_drivers(options);
771
772 if (!driver)
773 return True;
774
775 pos = drivers;
776 while (pos != NULL)
777 {
778 if (!strcmp(pos->name, driver))
779 {
780 DEBUG(("selected %s\n", pos->name));
781 current_driver = pos;
782 return True;
783 }
784 pos = pos->next;
785 }
786 return False;
787}
788
789void
790rdpsnd_reset_state(void)
791{
792 if (device_open)
793 current_driver->wave_out_close();
794 device_open = False;
795 rdpsnd_queue_clear();
796 rdpsnd_negotiated = False;
797
798 if (rec_device_open)
799 current_driver->wave_in_close();
800 rec_device_open = False;
801 rdpsnd_clear_record();
802 rdpsnd_rec_negotiated = False;
803}
804
805
806void
807rdpsnd_show_help(void)
808{
809 struct audio_driver *pos;
810
811 rdpsnd_register_drivers(NULL);
812
813 pos = drivers;
814 while (pos != NULL)
815 {
816 fprintf(stderr, " %s:\t%s\n", pos->name, pos->description);
817 pos = pos->next;
818 }
819}
820
821void
822rdpsnd_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
823{
824 long next_pending;
825
826 if (device_open || rec_device_open)
827 current_driver->add_fds(n, rfds, wfds, tv);
828
829 next_pending = rdpsnd_queue_next_completion();
830 if (next_pending >= 0)
831 {
832 long cur_timeout;
833
834 cur_timeout = tv->tv_sec * 1000000 + tv->tv_usec;
835 if (cur_timeout > next_pending)
836 {
837 tv->tv_sec = next_pending / 1000000;
838 tv->tv_usec = next_pending % 1000000;
839 }
840 }
841}
842
843void
844rdpsnd_check_fds(fd_set * rfds, fd_set * wfds)
845{
846 rdpsnd_queue_complete_pending();
847
848 if (device_open || rec_device_open)
849 current_driver->check_fds(rfds, wfds);
850}
851
852static void
853rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)
854{
855 struct audio_packet *packet = &packet_queue[queue_hi];
856 unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
857
858 if (next_hi == queue_pending)
859 {
860 error("No space to queue audio packet\n");
861 return;
862 }
863
864 queue_hi = next_hi;
865
866 packet->s = *s;
867 packet->tick = tick;
868 packet->index = index;
869
870 gettimeofday(&packet->arrive_tv, NULL);
871}
872
873struct audio_packet *
874rdpsnd_queue_current_packet(void)
875{
876 return &packet_queue[queue_lo];
877}
878
879RD_BOOL
880rdpsnd_queue_empty(void)
881{
882 return (queue_lo == queue_hi);
883}
884
885static void
886rdpsnd_queue_init(void)
887{
888 queue_pending = queue_lo = queue_hi = 0;
889}
890
891static void
892rdpsnd_queue_clear(void)
893{
894 struct audio_packet *packet;
895
896 /* Go through everything, not just the pending packets */
897 while (queue_pending != queue_hi)
898 {
899 packet = &packet_queue[queue_pending];
900 xfree(packet->s.data);
901 queue_pending = (queue_pending + 1) % MAX_QUEUE;
902 }
903
904 /* Reset everything back to the initial state */
905 queue_pending = queue_lo = queue_hi = 0;
906}
907
908void
909rdpsnd_queue_next(unsigned long completed_in_us)
910{
911 struct audio_packet *packet;
912
913 assert(!rdpsnd_queue_empty());
914
915 packet = &packet_queue[queue_lo];
916
917 gettimeofday(&packet->completion_tv, NULL);
918
919 packet->completion_tv.tv_usec += completed_in_us;
920 packet->completion_tv.tv_sec += packet->completion_tv.tv_usec / 1000000;
921 packet->completion_tv.tv_usec %= 1000000;
922
923 queue_lo = (queue_lo + 1) % MAX_QUEUE;
924
925 rdpsnd_queue_complete_pending();
926}
927
928int
929rdpsnd_queue_next_tick(void)
930{
931 if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
932 {
933 return packet_queue[(queue_lo + 1) % MAX_QUEUE].tick;
934 }
935 else
936 {
937 return (packet_queue[queue_lo].tick + 65535) % 65536;
938 }
939}
940
941static void
942rdpsnd_queue_complete_pending(void)
943{
944 struct timeval now;
945 long elapsed;
946 struct audio_packet *packet;
947
948 gettimeofday(&now, NULL);
949
950 while (queue_pending != queue_lo)
951 {
952 packet = &packet_queue[queue_pending];
953
954 if (now.tv_sec < packet->completion_tv.tv_sec)
955 break;
956
957 if ((now.tv_sec == packet->completion_tv.tv_sec) &&
958 (now.tv_usec < packet->completion_tv.tv_usec))
959 break;
960
961 elapsed = (packet->completion_tv.tv_sec - packet->arrive_tv.tv_sec) * 1000000 +
962 (packet->completion_tv.tv_usec - packet->arrive_tv.tv_usec);
963 elapsed /= 1000;
964
965 xfree(packet->s.data);
966 rdpsnd_send_completion((packet->tick + elapsed) % 65536, packet->index);
967 queue_pending = (queue_pending + 1) % MAX_QUEUE;
968 }
969}
970
971static long
972rdpsnd_queue_next_completion(void)
973{
974 struct audio_packet *packet;
975 long remaining;
976 struct timeval now;
977
978 if (queue_pending == queue_lo)
979 return -1;
980
981 gettimeofday(&now, NULL);
982
983 packet = &packet_queue[queue_pending];
984
985 remaining = (packet->completion_tv.tv_sec - now.tv_sec) * 1000000 +
986 (packet->completion_tv.tv_usec - now.tv_usec);
987
988 if (remaining < 0)
989 return 0;
990
991 return remaining;
992}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette