VirtualBox

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

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

rdesktop 1.8.3 unmodified

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