VirtualBox

source: vbox/trunk/src/VBox/RDP/client/rdpsnd.c@ 51770

Last change on this file since 51770 was 37224, checked in by vboxsync, 13 years ago

RDP/client: fix OSE

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