VirtualBox

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

最後變更 在這個檔案從9902是 9902,由 vboxsync 提交於 16 年 前

Added rdesktop 1.6.0.

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

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