/[rdesktop]/sourceforge.net/rdesktop/trunk/rdpsnd.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /sourceforge.net/rdesktop/trunk/rdpsnd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1350 - (show annotations)
Sun Dec 24 13:48:50 2006 UTC (17 years, 4 months ago) by stargo
Original Path: sourceforge.net/trunk/rdesktop/rdpsnd.c
File MIME type: text/plain
File size: 14243 byte(s)
fix double open of sound device. should at least allow oss, libao, sun and
sgi drivers to be selected again, when they only allow one open of the
device.

1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Sound Channel Process Functions
4 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
5 Copyright (C) Matthew Chapman 2003
6 Copyright (C) GuoJunBo guojunbo@ict.ac.cn 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 MAX_FORMATS 10
38 #define MAX_QUEUE 10
39
40 static VCHANNEL *rdpsnd_channel;
41 static struct audio_driver *drivers = NULL;
42 struct audio_driver *current_driver = NULL;
43
44 static BOOL device_open;
45 static WAVEFORMATEX formats[MAX_FORMATS];
46 static unsigned int format_count;
47 static unsigned int current_format;
48 unsigned int queue_hi, queue_lo, queue_pending;
49 struct audio_packet packet_queue[MAX_QUEUE];
50
51 static uint8 packet_opcode;
52 static struct stream packet;
53
54 void (*wave_out_play) (void);
55
56 static void rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index);
57 static void rdpsnd_queue_init(void);
58 static void rdpsnd_queue_complete_pending(void);
59 static long rdpsnd_queue_next_completion(void);
60
61 static STREAM
62 rdpsnd_init_packet(uint16 type, uint16 size)
63 {
64 STREAM s;
65
66 s = channel_init(rdpsnd_channel, size + 4);
67 out_uint16_le(s, type);
68 out_uint16_le(s, size);
69 return s;
70 }
71
72 static void
73 rdpsnd_send(STREAM s)
74 {
75 channel_send(s, rdpsnd_channel);
76 }
77
78 static void
79 rdpsnd_send_completion(uint16 tick, uint8 packet_index)
80 {
81 STREAM s;
82
83 s = rdpsnd_init_packet(RDPSND_COMPLETION, 4);
84 out_uint16_le(s, tick);
85 out_uint8(s, packet_index);
86 out_uint8(s, 0);
87 s_mark_end(s);
88 rdpsnd_send(s);
89
90 DEBUG_SOUND(("RDPSND: -> RDPSND_COMPLETION(tick: %u, index: %u)\n",
91 (unsigned) tick, (unsigned) packet_index));
92 }
93
94
95 static BOOL
96 rdpsnd_auto_select(void)
97 {
98 static BOOL failed = False;
99
100 if (!failed)
101 {
102 current_driver = drivers;
103 while (current_driver != NULL)
104 {
105 DEBUG(("trying %s...\n", current_driver->name));
106 if (current_driver->wave_out_open())
107 {
108 DEBUG(("selected %s\n", current_driver->name));
109 current_driver->wave_out_close();
110 return True;
111 }
112 current_driver = current_driver->next;
113 }
114
115 warning("no working audio-driver found\n");
116 failed = True;
117 current_driver = NULL;
118 }
119
120 return False;
121 }
122
123 static void
124 rdpsnd_process_negotiate(STREAM in)
125 {
126 uint16 in_format_count, i;
127 uint8 pad;
128 uint16 version;
129 WAVEFORMATEX *format;
130 STREAM out;
131 BOOL device_available = False;
132 int readcnt;
133 int discardcnt;
134
135 in_uint8s(in, 14); /* initial bytes not valid from server */
136 in_uint16_le(in, in_format_count);
137 in_uint8(in, pad);
138 in_uint16_le(in, version);
139 in_uint8s(in, 1); /* padding */
140
141 DEBUG_SOUND(("RDPSND: RDPSND_NEGOTIATE(formats: %d, pad: 0x%02x, version: %x)\n",
142 (int) in_format_count, (unsigned) pad, (unsigned) version));
143
144 if (!current_driver)
145 rdpsnd_auto_select();
146
147 if (current_driver)
148 {
149 device_available = True;
150 }
151
152 format_count = 0;
153 if (s_check_rem(in, 18 * in_format_count))
154 {
155 for (i = 0; i < in_format_count; i++)
156 {
157 format = &formats[format_count];
158 in_uint16_le(in, format->wFormatTag);
159 in_uint16_le(in, format->nChannels);
160 in_uint32_le(in, format->nSamplesPerSec);
161 in_uint32_le(in, format->nAvgBytesPerSec);
162 in_uint16_le(in, format->nBlockAlign);
163 in_uint16_le(in, format->wBitsPerSample);
164 in_uint16_le(in, format->cbSize);
165
166 /* read in the buffer of unknown use */
167 readcnt = format->cbSize;
168 discardcnt = 0;
169 if (format->cbSize > MAX_CBSIZE)
170 {
171 fprintf(stderr, "cbSize too large for buffer: %d\n",
172 format->cbSize);
173 readcnt = MAX_CBSIZE;
174 discardcnt = format->cbSize - MAX_CBSIZE;
175 }
176 in_uint8a(in, format->cb, readcnt);
177 in_uint8s(in, discardcnt);
178
179 if (device_available && current_driver->wave_out_format_supported(format))
180 {
181 format_count++;
182 if (format_count == MAX_FORMATS)
183 break;
184 }
185 }
186 }
187
188 out = rdpsnd_init_packet(RDPSND_NEGOTIATE | 0x200, 20 + 18 * format_count);
189 out_uint32_le(out, 3); /* flags */
190 out_uint32(out, 0xffffffff); /* volume */
191 out_uint32(out, 0); /* pitch */
192 out_uint16(out, 0); /* UDP port */
193
194 out_uint16_le(out, format_count);
195 out_uint8(out, 0); /* padding */
196 out_uint16_le(out, 2); /* version */
197 out_uint8(out, 0); /* padding */
198
199 for (i = 0; i < format_count; i++)
200 {
201 format = &formats[i];
202 out_uint16_le(out, format->wFormatTag);
203 out_uint16_le(out, format->nChannels);
204 out_uint32_le(out, format->nSamplesPerSec);
205 out_uint32_le(out, format->nAvgBytesPerSec);
206 out_uint16_le(out, format->nBlockAlign);
207 out_uint16_le(out, format->wBitsPerSample);
208 out_uint16(out, 0); /* cbSize */
209 }
210
211 s_mark_end(out);
212
213 DEBUG_SOUND(("RDPSND: -> RDPSND_NEGOTIATE(formats: %d)\n", (int) format_count));
214
215 rdpsnd_send(out);
216 }
217
218 static void
219 rdpsnd_process_ping(STREAM in)
220 {
221 uint16 tick;
222 STREAM out;
223
224 in_uint16_le(in, tick);
225
226 DEBUG_SOUND(("RDPSND: RDPSND_PING(tick: 0x%04x)\n", (unsigned) tick));
227
228 out = rdpsnd_init_packet(RDPSND_PING | 0x2300, 4);
229 out_uint16_le(out, tick);
230 out_uint16_le(out, 0);
231 s_mark_end(out);
232 rdpsnd_send(out);
233
234 DEBUG_SOUND(("RDPSND: -> (tick: 0x%04x)\n", (unsigned) tick));
235 }
236
237 static void
238 rdpsnd_process_packet(uint8 opcode, STREAM s)
239 {
240 uint16 vol_left, vol_right;
241 static uint16 tick, format;
242 static uint8 packet_index;
243
244 switch (opcode)
245 {
246 case RDPSND_WRITE:
247 in_uint16_le(s, tick);
248 in_uint16_le(s, format);
249 in_uint8(s, packet_index);
250 in_uint8s(s, 3);
251 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));
252
253 if (format >= MAX_FORMATS)
254 {
255 error("RDPSND: Invalid format index\n");
256 break;
257 }
258
259 if (!device_open || (format != current_format))
260 {
261 /*
262 * If we haven't selected a device by now, then either
263 * we've failed to find a working device, or the server
264 * is sending bogus RDPSND_WRITE.
265 */
266 if (!current_driver)
267 {
268 rdpsnd_send_completion(tick, packet_index);
269 break;
270 }
271 if (!device_open && !current_driver->wave_out_open())
272 {
273 rdpsnd_send_completion(tick, packet_index);
274 break;
275 }
276 if (!current_driver->wave_out_set_format(&formats[format]))
277 {
278 rdpsnd_send_completion(tick, packet_index);
279 current_driver->wave_out_close();
280 device_open = False;
281 break;
282 }
283 device_open = True;
284 current_format = format;
285 }
286
287 rdpsnd_queue_write(rdpsnd_dsp_process
288 (s->p, s->end - s->p, current_driver,
289 &formats[current_format]), tick, packet_index);
290 return;
291 break;
292 case RDPSND_CLOSE:
293 DEBUG_SOUND(("RDPSND: RDPSND_CLOSE()\n"));
294 if (device_open)
295 current_driver->wave_out_close();
296 device_open = False;
297 break;
298 case RDPSND_NEGOTIATE:
299 rdpsnd_process_negotiate(s);
300 break;
301 case RDPSND_PING:
302 rdpsnd_process_ping(s);
303 break;
304 case RDPSND_SET_VOLUME:
305 in_uint16_le(s, vol_left);
306 in_uint16_le(s, vol_right);
307 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));
308 if (device_open)
309 current_driver->wave_out_volume(vol_left, vol_right);
310 break;
311 default:
312 unimpl("RDPSND packet type %x\n", opcode);
313 break;
314 }
315 }
316
317 static void
318 rdpsnd_process(STREAM s)
319 {
320 uint16 len;
321
322 while (!s_check_end(s))
323 {
324 /* New packet */
325 if (packet.size == 0)
326 {
327 if ((s->end - s->p) < 4)
328 {
329 error("RDPSND: Split at packet header. Things will go south from here...\n");
330 return;
331 }
332 in_uint8(s, packet_opcode);
333 in_uint8s(s, 1); /* Padding */
334 in_uint16_le(s, len);
335
336 DEBUG_SOUND(("RDPSND: == Opcode %x Length: %d ==\n",
337 (int) packet_opcode, (int) len));
338
339 packet.p = packet.data;
340 packet.end = packet.data + len;
341 packet.size = len;
342 }
343 else
344 {
345 len = MIN(s->end - s->p, packet.end - packet.p);
346
347 /* Microsoft's server is so broken it's not even funny... */
348 if (packet_opcode == RDPSND_WRITE)
349 {
350 if ((packet.p - packet.data) < 12)
351 len = MIN(len, 12 - (packet.p - packet.data));
352 else if ((packet.p - packet.data) == 12)
353 {
354 DEBUG_SOUND(("RDPSND: Eating 4 bytes of %d bytes...\n",
355 len));
356 in_uint8s(s, 4);
357 len -= 4;
358 }
359 }
360
361 in_uint8a(s, packet.p, len);
362 packet.p += len;
363 }
364
365 /* Packet fully assembled */
366 if (packet.p == packet.end)
367 {
368 packet.p = packet.data;
369 rdpsnd_process_packet(packet_opcode, &packet);
370 packet.size = 0;
371 }
372 }
373 }
374
375 static void
376 rdpsnd_register_drivers(char *options)
377 {
378 struct audio_driver **reg;
379
380 /* The order of registrations define the probe-order
381 when opening the device for the first time */
382 reg = &drivers;
383 #if defined(RDPSND_ALSA)
384 *reg = alsa_register(options);
385 assert(*reg);
386 reg = &((*reg)->next);
387 #endif
388 #if defined(RDPSND_SUN)
389 *reg = sun_register(options);
390 assert(*reg);
391 reg = &((*reg)->next);
392 #endif
393 #if defined(RDPSND_OSS)
394 *reg = oss_register(options);
395 assert(*reg);
396 reg = &((*reg)->next);
397 #endif
398 #if defined(RDPSND_SGI)
399 *reg = sgi_register(options);
400 assert(*reg);
401 reg = &((*reg)->next);
402 #endif
403 #if defined(RDPSND_LIBAO)
404 *reg = libao_register(options);
405 assert(*reg);
406 reg = &((*reg)->next);
407 #endif
408 *reg = NULL;
409 }
410
411 BOOL
412 rdpsnd_init(char *optarg)
413 {
414 struct audio_driver *pos;
415 char *driver = NULL, *options = NULL;
416
417 drivers = NULL;
418
419 packet.data = xmalloc(65536);
420 packet.p = packet.end = packet.data;
421 packet.size = 0;
422
423 rdpsnd_channel =
424 channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
425 rdpsnd_process);
426
427 if (rdpsnd_channel == NULL)
428 {
429 error("channel_register\n");
430 return False;
431 }
432
433 rdpsnd_queue_init();
434
435 if (optarg != NULL && strlen(optarg) > 0)
436 {
437 driver = options = optarg;
438
439 while (*options != '\0' && *options != ':')
440 options++;
441
442 if (*options == ':')
443 {
444 *options = '\0';
445 options++;
446 }
447
448 if (*options == '\0')
449 options = NULL;
450 }
451
452 rdpsnd_register_drivers(options);
453
454 if (!driver)
455 return True;
456
457 pos = drivers;
458 while (pos != NULL)
459 {
460 if (!strcmp(pos->name, driver))
461 {
462 DEBUG(("selected %s\n", pos->name));
463 current_driver = pos;
464 return True;
465 }
466 pos = pos->next;
467 }
468 return False;
469 }
470
471 void
472 rdpsnd_show_help(void)
473 {
474 struct audio_driver *pos;
475
476 rdpsnd_register_drivers(NULL);
477
478 pos = drivers;
479 while (pos != NULL)
480 {
481 fprintf(stderr, " %s:\t%s\n", pos->name, pos->description);
482 pos = pos->next;
483 }
484 }
485
486 void
487 rdpsnd_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
488 {
489 long next_pending;
490
491 if (device_open)
492 current_driver->add_fds(n, rfds, wfds, tv);
493
494 next_pending = rdpsnd_queue_next_completion();
495 if (next_pending >= 0)
496 {
497 long cur_timeout;
498
499 cur_timeout = tv->tv_sec * 1000000 + tv->tv_usec;
500 if (cur_timeout > next_pending)
501 {
502 tv->tv_sec = next_pending / 1000000;
503 tv->tv_usec = next_pending % 1000000;
504 }
505 }
506 }
507
508 void
509 rdpsnd_check_fds(fd_set * rfds, fd_set * wfds)
510 {
511 rdpsnd_queue_complete_pending();
512
513 if (device_open)
514 current_driver->check_fds(rfds, wfds);
515 }
516
517 static void
518 rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)
519 {
520 struct audio_packet *packet = &packet_queue[queue_hi];
521 unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
522
523 if (next_hi == queue_pending)
524 {
525 error("No space to queue audio packet\n");
526 return;
527 }
528
529 queue_hi = next_hi;
530
531 packet->s = *s;
532 packet->tick = tick;
533 packet->index = index;
534
535 gettimeofday(&packet->arrive_tv, NULL);
536 }
537
538 struct audio_packet *
539 rdpsnd_queue_current_packet(void)
540 {
541 return &packet_queue[queue_lo];
542 }
543
544 BOOL
545 rdpsnd_queue_empty(void)
546 {
547 return (queue_lo == queue_hi);
548 }
549
550 static void
551 rdpsnd_queue_init(void)
552 {
553 queue_pending = queue_lo = queue_hi = 0;
554 }
555
556 void
557 rdpsnd_queue_next(unsigned long completed_in_us)
558 {
559 struct audio_packet *packet;
560
561 assert(!rdpsnd_queue_empty());
562
563 packet = &packet_queue[queue_lo];
564
565 gettimeofday(&packet->completion_tv, NULL);
566
567 packet->completion_tv.tv_usec += completed_in_us;
568 packet->completion_tv.tv_sec += packet->completion_tv.tv_usec / 1000000;
569 packet->completion_tv.tv_usec %= 1000000;
570
571 queue_lo = (queue_lo + 1) % MAX_QUEUE;
572
573 rdpsnd_queue_complete_pending();
574 }
575
576 int
577 rdpsnd_queue_next_tick(void)
578 {
579 if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
580 {
581 return packet_queue[(queue_lo + 1) % MAX_QUEUE].tick;
582 }
583 else
584 {
585 return (packet_queue[queue_lo].tick + 65535) % 65536;
586 }
587 }
588
589 static void
590 rdpsnd_queue_complete_pending(void)
591 {
592 struct timeval now;
593 long elapsed;
594 struct audio_packet *packet;
595
596 gettimeofday(&now, NULL);
597
598 while (queue_pending != queue_lo)
599 {
600 packet = &packet_queue[queue_pending];
601
602 if (now.tv_sec < packet->completion_tv.tv_sec)
603 break;
604
605 if ((now.tv_sec == packet->completion_tv.tv_sec) &&
606 (now.tv_usec < packet->completion_tv.tv_usec))
607 break;
608
609 elapsed = (packet->completion_tv.tv_sec - packet->arrive_tv.tv_sec) * 1000000 +
610 (packet->completion_tv.tv_usec - packet->arrive_tv.tv_usec);
611 elapsed /= 1000;
612
613 xfree(packet->s.data);
614 rdpsnd_send_completion((packet->tick + elapsed) % 65536, packet->index);
615 queue_pending = (queue_pending + 1) % MAX_QUEUE;
616 }
617 }
618
619 static long
620 rdpsnd_queue_next_completion(void)
621 {
622 struct audio_packet *packet;
623 long remaining;
624 struct timeval now;
625
626 if (queue_pending == queue_lo)
627 return -1;
628
629 gettimeofday(&now, NULL);
630
631 packet = &packet_queue[queue_pending];
632
633 remaining = (packet->completion_tv.tv_sec - now.tv_sec) * 1000000 +
634 (packet->completion_tv.tv_usec - now.tv_usec);
635
636 if (remaining < 0)
637 return 0;
638
639 return remaining;
640 }

  ViewVC Help
Powered by ViewVC 1.1.26