VirtualBox

source: vbox/trunk/src/VBox/RDP/client-1.8.4/rdpsnd.c@ 77807

Last change on this file since 77807 was 76779, checked in by vboxsync, 6 years ago

RDP: add client-1.8.4.
bugref:9356: Update rdesktop-vrdp to 1.8.4
client-1.8.4 is a Subversion copy of 1.8.3 with the upstream 1.8.3 to 1.8.4
patch applied and a couple of fixes and changes after review, namely:

  • Stopped disabling the new pointer data format for our build, as this is no

longer needed.

  • Adjusted some snprintf buffers to make GCC happy.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 22.9 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 struct stream packet = *in;
368
369 if (!s_check_rem(in, 4))
370 {
371 rdp_protocol_error("rdpsnd_process_training(), consume of training data from stream would overrun", &packet);
372 }
373
374 in_uint16_le(in, tick);
375
376 DEBUG_SOUND(("RDPSND: RDPSND_PING(tick: 0x%04x)\n", (unsigned) tick));
377
378 out = rdpsnd_init_packet(RDPSND_PING | 0x2300, 4);
379 out_uint16_le(out, tick);
380 out_uint16_le(out, 0);
381 s_mark_end(out);
382 rdpsnd_send(out);
383
384 DEBUG_SOUND(("RDPSND: -> (tick: 0x%04x)\n", (unsigned) tick));
385}
386
387static void
388rdpsnd_process_rec_negotiate(STREAM in)
389{
390 uint16 in_format_count, i;
391 uint16 version;
392 RD_WAVEFORMATEX *format;
393 STREAM out;
394 RD_BOOL device_available = False;
395 int readcnt;
396 int discardcnt;
397
398 in_uint8s(in, 8); /* initial bytes not valid from server */
399 in_uint16_le(in, in_format_count);
400 in_uint16_le(in, version);
401
402 DEBUG_SOUND(("RDPSND: RDPSND_REC_NEGOTIATE(formats: %d, version: %x)\n",
403 (int) in_format_count, (unsigned) version));
404
405 if (rdpsnd_rec_negotiated)
406 {
407 error("RDPSND: Extra RDPSND_REC_NEGOTIATE in the middle of a session\n");
408 /* Do a complete reset of the sound state */
409 rdpsnd_reset_state();
410 }
411
412 if (!current_driver)
413 device_available = rdpsnd_auto_select();
414
415 if (current_driver && !device_available && current_driver->wave_in_open
416 && current_driver->wave_in_open())
417 {
418 current_driver->wave_in_close();
419 device_available = True;
420 }
421
422 rec_format_count = 0;
423 if (s_check_rem(in, 18 * in_format_count))
424 {
425 for (i = 0; i < in_format_count; i++)
426 {
427 format = &rec_formats[rec_format_count];
428 in_uint16_le(in, format->wFormatTag);
429 in_uint16_le(in, format->nChannels);
430 in_uint32_le(in, format->nSamplesPerSec);
431 in_uint32_le(in, format->nAvgBytesPerSec);
432 in_uint16_le(in, format->nBlockAlign);
433 in_uint16_le(in, format->wBitsPerSample);
434 in_uint16_le(in, format->cbSize);
435
436 /* read in the buffer of unknown use */
437 readcnt = format->cbSize;
438 discardcnt = 0;
439 if (format->cbSize > MAX_CBSIZE)
440 {
441 fprintf(stderr, "cbSize too large for buffer: %d\n",
442 format->cbSize);
443 readcnt = MAX_CBSIZE;
444 discardcnt = format->cbSize - MAX_CBSIZE;
445 }
446 in_uint8a(in, format->cb, readcnt);
447 in_uint8s(in, discardcnt);
448
449 if (current_driver && current_driver->wave_in_format_supported
450 && current_driver->wave_in_format_supported(format))
451 {
452 rec_format_count++;
453 if (rec_format_count == MAX_FORMATS)
454 break;
455 }
456 }
457 }
458
459 out = rdpsnd_init_packet(RDPSND_REC_NEGOTIATE, 12 + 18 * rec_format_count);
460 out_uint32_le(out, 0x00000000); /* flags */
461 out_uint32_le(out, 0xffffffff); /* volume */
462 out_uint16_le(out, rec_format_count);
463 out_uint16_le(out, 1); /* version */
464
465 for (i = 0; i < rec_format_count; i++)
466 {
467 format = &rec_formats[i];
468 out_uint16_le(out, format->wFormatTag);
469 out_uint16_le(out, format->nChannels);
470 out_uint32_le(out, format->nSamplesPerSec);
471 out_uint32_le(out, format->nAvgBytesPerSec);
472 out_uint16_le(out, format->nBlockAlign);
473 out_uint16_le(out, format->wBitsPerSample);
474 out_uint16(out, 0); /* cbSize */
475 }
476
477 s_mark_end(out);
478
479 DEBUG_SOUND(("RDPSND: -> RDPSND_REC_NEGOTIATE(formats: %d)\n", (int) rec_format_count));
480
481 rdpsnd_send(out);
482
483 rdpsnd_rec_negotiated = True;
484}
485
486static void
487rdpsnd_process_packet(uint8 opcode, STREAM s)
488{
489 uint16 vol_left, vol_right;
490 static uint16 tick, format;
491 static uint8 packet_index;
492
493 switch (opcode)
494 {
495 case RDPSND_WRITE:
496 in_uint16_le(s, tick);
497 in_uint16_le(s, format);
498 in_uint8(s, packet_index);
499 in_uint8s(s, 3);
500 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));
501
502 if (format >= MAX_FORMATS)
503 {
504 error("RDPSND: Invalid format index\n");
505 break;
506 }
507
508 if (!device_open || (format != current_format))
509 {
510 /*
511 * If we haven't selected a device by now, then either
512 * we've failed to find a working device, or the server
513 * is sending bogus RDPSND_WRITE.
514 */
515 if (!current_driver)
516 {
517 rdpsnd_send_completion(tick, packet_index);
518 break;
519 }
520 if (!device_open && !current_driver->wave_out_open())
521 {
522 rdpsnd_send_completion(tick, packet_index);
523 break;
524 }
525 if (!current_driver->wave_out_set_format(&formats[format]))
526 {
527 rdpsnd_send_completion(tick, packet_index);
528 current_driver->wave_out_close();
529 device_open = False;
530 break;
531 }
532 device_open = True;
533 current_format = format;
534 }
535
536 rdpsnd_queue_write(rdpsnd_dsp_process
537 (s->p, s->end - s->p, current_driver,
538 &formats[current_format]), tick, packet_index);
539 return;
540 break;
541 case RDPSND_CLOSE:
542 DEBUG_SOUND(("RDPSND: RDPSND_CLOSE()\n"));
543 if (device_open)
544 current_driver->wave_out_close();
545 device_open = False;
546 break;
547 case RDPSND_NEGOTIATE:
548 rdpsnd_process_negotiate(s);
549 break;
550 case RDPSND_PING:
551 rdpsnd_process_ping(s);
552 break;
553 case RDPSND_SET_VOLUME:
554 in_uint16_le(s, vol_left);
555 in_uint16_le(s, vol_right);
556 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));
557 if (device_open)
558 current_driver->wave_out_volume(vol_left, vol_right);
559 break;
560 case RDPSND_REC_NEGOTIATE:
561 rdpsnd_process_rec_negotiate(s);
562 break;
563 case RDPSND_REC_START:
564 in_uint16_le(s, format);
565 DEBUG_SOUND(("RDPSND: RDPSND_REC_START(format: %u)\n", (unsigned) format));
566
567 if (format >= MAX_FORMATS)
568 {
569 error("RDPSND: Invalid format index\n");
570 break;
571 }
572
573 if (rec_device_open)
574 {
575 error("RDPSND: Multiple RDPSND_REC_START\n");
576 break;
577 }
578
579 if (!current_driver->wave_in_open())
580 break;
581
582 if (!current_driver->wave_in_set_format(&rec_formats[format]))
583 {
584 error("RDPSND: Device not accepting format\n");
585 current_driver->wave_in_close();
586 break;
587 }
588 rec_current_format = format;
589 rec_device_open = True;
590 break;
591 case RDPSND_REC_STOP:
592 DEBUG_SOUND(("RDPSND: RDPSND_REC_STOP()\n"));
593 rdpsnd_flush_record();
594 if (rec_device_open)
595 current_driver->wave_in_close();
596 rec_device_open = False;
597 break;
598 case RDPSND_REC_SET_VOLUME:
599 in_uint16_le(s, vol_left);
600 in_uint16_le(s, vol_right);
601 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));
602 if (rec_device_open)
603 current_driver->wave_in_volume(vol_left, vol_right);
604 break;
605 default:
606 unimpl("RDPSND packet type %x\n", opcode);
607 break;
608 }
609}
610
611static void
612rdpsnd_process(STREAM s)
613{
614 uint16 len;
615
616 while (!s_check_end(s))
617 {
618 /* New packet */
619 if (packet.size == 0)
620 {
621 if ((s->end - s->p) < 4)
622 {
623 error("RDPSND: Split at packet header. Things will go south from here...\n");
624 return;
625 }
626 in_uint8(s, packet_opcode);
627 in_uint8s(s, 1); /* Padding */
628 in_uint16_le(s, len);
629
630 DEBUG_SOUND(("RDPSND: == Opcode %x Length: %d ==\n",
631 (int) packet_opcode, (int) len));
632
633 packet.p = packet.data;
634 packet.end = packet.data + len;
635 packet.size = len;
636 }
637 else
638 {
639 len = MIN(s->end - s->p, packet.end - packet.p);
640
641 /* Microsoft's server is so broken it's not even funny... */
642 if (packet_opcode == RDPSND_WRITE)
643 {
644 if ((packet.p - packet.data) < 12)
645 len = MIN(len, 12 - (packet.p - packet.data));
646 else if ((packet.p - packet.data) == 12)
647 {
648 DEBUG_SOUND(("RDPSND: Eating 4 bytes of %d bytes...\n",
649 len));
650 in_uint8s(s, 4);
651 len -= 4;
652 }
653 }
654
655 in_uint8a(s, packet.p, len);
656 packet.p += len;
657 }
658
659 /* Packet fully assembled */
660 if (packet.p == packet.end)
661 {
662 packet.p = packet.data;
663 rdpsnd_process_packet(packet_opcode, &packet);
664 packet.size = 0;
665 }
666 }
667}
668
669static RD_BOOL
670rdpsnddbg_line_handler(const char *line, void *data)
671{
672#ifdef WITH_DEBUG_SOUND
673 fprintf(stderr, "SNDDBG: %s\n", line);
674#endif
675 return True;
676}
677
678static void
679rdpsnddbg_process(STREAM s)
680{
681 unsigned int pkglen;
682 static char *rest = NULL;
683 char *buf;
684
685 if (!s_check(s))
686 {
687 rdp_protocol_error("rdpsnddbg_process(), stream is in unstable state", s);
688 }
689
690 pkglen = s->end - s->p;
691 /* str_handle_lines requires null terminated strings */
692 buf = (char *) xmalloc(pkglen + 1);
693 STRNCPY(buf, (char *) s->p, pkglen + 1);
694
695 str_handle_lines(buf, &rest, rdpsnddbg_line_handler, NULL);
696
697 xfree(buf);
698}
699
700static void
701rdpsnd_register_drivers(char *options)
702{
703 struct audio_driver **reg;
704
705 /* The order of registrations define the probe-order
706 when opening the device for the first time */
707 reg = &drivers;
708#if defined(RDPSND_ALSA)
709 *reg = alsa_register(options);
710 assert(*reg);
711 reg = &((*reg)->next);
712#endif
713#if defined(RDPSND_SUN)
714 *reg = sun_register(options);
715 assert(*reg);
716 reg = &((*reg)->next);
717#endif
718#if defined(RDPSND_OSS)
719 *reg = oss_register(options);
720 assert(*reg);
721 reg = &((*reg)->next);
722#endif
723#if defined(RDPSND_SGI)
724 *reg = sgi_register(options);
725 assert(*reg);
726 reg = &((*reg)->next);
727#endif
728#if defined(RDPSND_LIBAO)
729 *reg = libao_register(options);
730 assert(*reg);
731 reg = &((*reg)->next);
732#endif
733 *reg = NULL;
734}
735
736RD_BOOL
737rdpsnd_init(char *optarg)
738{
739 struct audio_driver *pos;
740 char *driver = NULL, *options = NULL;
741
742 drivers = NULL;
743
744 packet.data = (uint8 *) xmalloc(65536);
745 packet.p = packet.end = packet.data;
746 packet.size = 0;
747
748 rdpsnd_channel =
749 channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
750 rdpsnd_process);
751
752 rdpsnddbg_channel =
753 channel_register("snddbg", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
754 rdpsnddbg_process);
755
756 if ((rdpsnd_channel == NULL) || (rdpsnddbg_channel == NULL))
757 {
758 error("channel_register\n");
759 return False;
760 }
761
762 rdpsnd_queue_init();
763
764 if (optarg != NULL && strlen(optarg) > 0)
765 {
766 driver = options = optarg;
767
768 while (*options != '\0' && *options != ':')
769 options++;
770
771 if (*options == ':')
772 {
773 *options = '\0';
774 options++;
775 }
776
777 if (*options == '\0')
778 options = NULL;
779 }
780
781 rdpsnd_register_drivers(options);
782
783 if (!driver)
784 return True;
785
786 pos = drivers;
787 while (pos != NULL)
788 {
789 if (!strcmp(pos->name, driver))
790 {
791 DEBUG(("selected %s\n", pos->name));
792 current_driver = pos;
793 return True;
794 }
795 pos = pos->next;
796 }
797 return False;
798}
799
800void
801rdpsnd_reset_state(void)
802{
803 if (device_open)
804 current_driver->wave_out_close();
805 device_open = False;
806 rdpsnd_queue_clear();
807 rdpsnd_negotiated = False;
808
809 if (rec_device_open)
810 current_driver->wave_in_close();
811 rec_device_open = False;
812 rdpsnd_clear_record();
813 rdpsnd_rec_negotiated = False;
814}
815
816
817void
818rdpsnd_show_help(void)
819{
820 struct audio_driver *pos;
821
822 rdpsnd_register_drivers(NULL);
823
824 pos = drivers;
825 while (pos != NULL)
826 {
827 fprintf(stderr, " %s:\t%s\n", pos->name, pos->description);
828 pos = pos->next;
829 }
830}
831
832void
833rdpsnd_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
834{
835 long next_pending;
836
837 if (device_open || rec_device_open)
838 current_driver->add_fds(n, rfds, wfds, tv);
839
840 next_pending = rdpsnd_queue_next_completion();
841 if (next_pending >= 0)
842 {
843 long cur_timeout;
844
845 cur_timeout = tv->tv_sec * 1000000 + tv->tv_usec;
846 if (cur_timeout > next_pending)
847 {
848 tv->tv_sec = next_pending / 1000000;
849 tv->tv_usec = next_pending % 1000000;
850 }
851 }
852}
853
854void
855rdpsnd_check_fds(fd_set * rfds, fd_set * wfds)
856{
857 rdpsnd_queue_complete_pending();
858
859 if (device_open || rec_device_open)
860 current_driver->check_fds(rfds, wfds);
861}
862
863static void
864rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)
865{
866 struct audio_packet *packet = &packet_queue[queue_hi];
867 unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
868
869 if (next_hi == queue_pending)
870 {
871 error("No space to queue audio packet\n");
872 return;
873 }
874
875 queue_hi = next_hi;
876
877 packet->s = *s;
878 packet->tick = tick;
879 packet->index = index;
880
881 gettimeofday(&packet->arrive_tv, NULL);
882}
883
884struct audio_packet *
885rdpsnd_queue_current_packet(void)
886{
887 return &packet_queue[queue_lo];
888}
889
890RD_BOOL
891rdpsnd_queue_empty(void)
892{
893 return (queue_lo == queue_hi);
894}
895
896static void
897rdpsnd_queue_init(void)
898{
899 queue_pending = queue_lo = queue_hi = 0;
900}
901
902static void
903rdpsnd_queue_clear(void)
904{
905 struct audio_packet *packet;
906
907 /* Go through everything, not just the pending packets */
908 while (queue_pending != queue_hi)
909 {
910 packet = &packet_queue[queue_pending];
911 xfree(packet->s.data);
912 queue_pending = (queue_pending + 1) % MAX_QUEUE;
913 }
914
915 /* Reset everything back to the initial state */
916 queue_pending = queue_lo = queue_hi = 0;
917}
918
919void
920rdpsnd_queue_next(unsigned long completed_in_us)
921{
922 struct audio_packet *packet;
923
924 assert(!rdpsnd_queue_empty());
925
926 packet = &packet_queue[queue_lo];
927
928 gettimeofday(&packet->completion_tv, NULL);
929
930 packet->completion_tv.tv_usec += completed_in_us;
931 packet->completion_tv.tv_sec += packet->completion_tv.tv_usec / 1000000;
932 packet->completion_tv.tv_usec %= 1000000;
933
934 queue_lo = (queue_lo + 1) % MAX_QUEUE;
935
936 rdpsnd_queue_complete_pending();
937}
938
939int
940rdpsnd_queue_next_tick(void)
941{
942 if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
943 {
944 return packet_queue[(queue_lo + 1) % MAX_QUEUE].tick;
945 }
946 else
947 {
948 return (packet_queue[queue_lo].tick + 65535) % 65536;
949 }
950}
951
952static void
953rdpsnd_queue_complete_pending(void)
954{
955 struct timeval now;
956 long elapsed;
957 struct audio_packet *packet;
958
959 gettimeofday(&now, NULL);
960
961 while (queue_pending != queue_lo)
962 {
963 packet = &packet_queue[queue_pending];
964
965 if (now.tv_sec < packet->completion_tv.tv_sec)
966 break;
967
968 if ((now.tv_sec == packet->completion_tv.tv_sec) &&
969 (now.tv_usec < packet->completion_tv.tv_usec))
970 break;
971
972 elapsed = (packet->completion_tv.tv_sec - packet->arrive_tv.tv_sec) * 1000000 +
973 (packet->completion_tv.tv_usec - packet->arrive_tv.tv_usec);
974 elapsed /= 1000;
975
976 xfree(packet->s.data);
977 rdpsnd_send_completion((packet->tick + elapsed) % 65536, packet->index);
978 queue_pending = (queue_pending + 1) % MAX_QUEUE;
979 }
980}
981
982static long
983rdpsnd_queue_next_completion(void)
984{
985 struct audio_packet *packet;
986 long remaining;
987 struct timeval now;
988
989 if (queue_pending == queue_lo)
990 return -1;
991
992 gettimeofday(&now, NULL);
993
994 packet = &packet_queue[queue_pending];
995
996 remaining = (packet->completion_tv.tv_sec - now.tv_sec) * 1000000 +
997 (packet->completion_tv.tv_usec - now.tv_usec);
998
999 if (remaining < 0)
1000 return 0;
1001
1002 return remaining;
1003}
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