/[rdesktop]/sourceforge.net/trunk/rdesktop/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/trunk/rdesktop/rdpsnd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1339 - (show annotations)
Wed Dec 6 13:01:45 2006 UTC (17 years, 6 months ago) by ossman_
File MIME type: text/plain
File size: 12512 byte(s)
Change servertick to ping according to new information.

1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 Sound Channel Process Functions
4 Copyright (C) Matthew Chapman 2003
5 Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include <assert.h>
23
24 #include "rdesktop.h"
25 #include "rdpsnd.h"
26 #include "rdpsnd_dsp.h"
27
28 #define RDPSND_CLOSE 1
29 #define RDPSND_WRITE 2
30 #define RDPSND_SET_VOLUME 3
31 #define RDPSND_UNKNOWN4 4
32 #define RDPSND_COMPLETION 5
33 #define RDPSND_PING 6
34 #define RDPSND_NEGOTIATE 7
35
36 #define MAX_FORMATS 10
37 #define MAX_QUEUE 10
38
39 BOOL g_dsp_busy = False;
40 int g_dsp_fd;
41
42 static VCHANNEL *rdpsnd_channel;
43 static struct audio_driver *drivers = NULL;
44 struct audio_driver *current_driver = NULL;
45
46 static BOOL device_open;
47 static WAVEFORMATEX formats[MAX_FORMATS];
48 static unsigned int format_count;
49 static unsigned int current_format;
50 unsigned int queue_hi, queue_lo, queue_pending;
51 struct audio_packet packet_queue[MAX_QUEUE];
52
53 void (*wave_out_play) (void);
54
55 static void rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index);
56 static void rdpsnd_queue_init(void);
57 static void rdpsnd_queue_complete_pending(void);
58 static long rdpsnd_queue_next_completion(void);
59
60 static STREAM
61 rdpsnd_init_packet(uint16 type, uint16 size)
62 {
63 STREAM s;
64
65 s = channel_init(rdpsnd_channel, size + 4);
66 out_uint16_le(s, type);
67 out_uint16_le(s, size);
68 return s;
69 }
70
71 static void
72 rdpsnd_send(STREAM s)
73 {
74 #ifdef RDPSND_DEBUG
75 printf("RDPSND send:\n");
76 hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);
77 #endif
78
79 channel_send(s, rdpsnd_channel);
80 }
81
82 static void
83 rdpsnd_send_completion(uint16 tick, uint8 packet_index)
84 {
85 STREAM s;
86
87 s = rdpsnd_init_packet(RDPSND_COMPLETION, 4);
88 out_uint16_le(s, tick);
89 out_uint8(s, packet_index);
90 out_uint8(s, 0);
91 s_mark_end(s);
92 rdpsnd_send(s);
93 }
94
95 static void
96 rdpsnd_process_negotiate(STREAM in)
97 {
98 unsigned int in_format_count, i;
99 WAVEFORMATEX *format;
100 STREAM out;
101 BOOL device_available = False;
102 int readcnt;
103 int discardcnt;
104
105 in_uint8s(in, 14); /* flags, volume, pitch, UDP port */
106 in_uint16_le(in, in_format_count);
107 in_uint8s(in, 4); /* pad, status, pad */
108
109 if (current_driver->wave_out_open())
110 {
111 current_driver->wave_out_close();
112 device_available = True;
113 }
114
115 format_count = 0;
116 if (s_check_rem(in, 18 * in_format_count))
117 {
118 for (i = 0; i < in_format_count; i++)
119 {
120 format = &formats[format_count];
121 in_uint16_le(in, format->wFormatTag);
122 in_uint16_le(in, format->nChannels);
123 in_uint32_le(in, format->nSamplesPerSec);
124 in_uint32_le(in, format->nAvgBytesPerSec);
125 in_uint16_le(in, format->nBlockAlign);
126 in_uint16_le(in, format->wBitsPerSample);
127 in_uint16_le(in, format->cbSize);
128
129 /* read in the buffer of unknown use */
130 readcnt = format->cbSize;
131 discardcnt = 0;
132 if (format->cbSize > MAX_CBSIZE)
133 {
134 fprintf(stderr, "cbSize too large for buffer: %d\n",
135 format->cbSize);
136 readcnt = MAX_CBSIZE;
137 discardcnt = format->cbSize - MAX_CBSIZE;
138 }
139 in_uint8a(in, format->cb, readcnt);
140 in_uint8s(in, discardcnt);
141
142 if (device_available && current_driver->wave_out_format_supported(format))
143 {
144 format_count++;
145 if (format_count == MAX_FORMATS)
146 break;
147 }
148 }
149 }
150
151 out = rdpsnd_init_packet(RDPSND_NEGOTIATE | 0x200, 20 + 18 * format_count);
152 out_uint32_le(out, 3); /* flags */
153 out_uint32(out, 0xffffffff); /* volume */
154 out_uint32(out, 0); /* pitch */
155 out_uint16(out, 0); /* UDP port */
156
157 out_uint16_le(out, format_count);
158 out_uint8(out, 0x95); /* pad? */
159 out_uint16_le(out, 2); /* status */
160 out_uint8(out, 0x77); /* pad? */
161
162 for (i = 0; i < format_count; i++)
163 {
164 format = &formats[i];
165 out_uint16_le(out, format->wFormatTag);
166 out_uint16_le(out, format->nChannels);
167 out_uint32_le(out, format->nSamplesPerSec);
168 out_uint32_le(out, format->nAvgBytesPerSec);
169 out_uint16_le(out, format->nBlockAlign);
170 out_uint16_le(out, format->wBitsPerSample);
171 out_uint16(out, 0); /* cbSize */
172 }
173
174 s_mark_end(out);
175 rdpsnd_send(out);
176 }
177
178 static void
179 rdpsnd_process_ping(STREAM in)
180 {
181 uint16 tick;
182 STREAM out;
183
184 in_uint16_le(in, tick);
185
186 out = rdpsnd_init_packet(RDPSND_PING | 0x2300, 4);
187 out_uint16_le(out, tick);
188 out_uint16_le(out, 0);
189 s_mark_end(out);
190 rdpsnd_send(out);
191 }
192
193 static void
194 rdpsnd_process(STREAM s)
195 {
196 uint8 type;
197 uint16 datalen;
198 uint32 volume;
199 static uint16 tick, format;
200 static uint8 packet_index;
201 static BOOL awaiting_data_packet;
202 static unsigned char missing_bytes[4] = { 0, 0, 0, 0 };
203
204 #ifdef RDPSND_DEBUG
205 printf("RDPSND recv:\n");
206 hexdump(s->p, s->end - s->p);
207 #endif
208
209 if (awaiting_data_packet)
210 {
211 if (format >= MAX_FORMATS)
212 {
213 error("RDPSND: Invalid format index\n");
214 return;
215 }
216
217 if (!device_open || (format != current_format))
218 {
219 if (!device_open && !current_driver->wave_out_open())
220 {
221 rdpsnd_send_completion(tick, packet_index);
222 return;
223 }
224 if (!current_driver->wave_out_set_format(&formats[format]))
225 {
226 rdpsnd_send_completion(tick, packet_index);
227 current_driver->wave_out_close();
228 device_open = False;
229 return;
230 }
231 device_open = True;
232 current_format = format;
233 }
234
235 /* Insert the 4 missing bytes retrieved from last RDPSND_WRITE */
236 memcpy(s->data, missing_bytes, 4);
237
238 rdpsnd_queue_write(rdpsnd_dsp_process
239 (s, current_driver, &formats[current_format]), tick,
240 packet_index);
241 awaiting_data_packet = False;
242 return;
243 }
244
245 in_uint8(s, type);
246 in_uint8s(s, 1); /* unknown? */
247 in_uint16_le(s, datalen);
248
249 switch (type)
250 {
251 case RDPSND_WRITE:
252 in_uint16_le(s, tick);
253 in_uint16_le(s, format);
254 in_uint8(s, packet_index);
255 /* Here are our lost bytes, but why? */
256 memcpy(missing_bytes, s->end - 4, 4);
257 awaiting_data_packet = True;
258 break;
259 case RDPSND_CLOSE:
260 current_driver->wave_out_close();
261 device_open = False;
262 break;
263 case RDPSND_NEGOTIATE:
264 rdpsnd_process_negotiate(s);
265 break;
266 case RDPSND_PING:
267 rdpsnd_process_ping(s);
268 break;
269 case RDPSND_SET_VOLUME:
270 in_uint32(s, volume);
271 if (device_open)
272 {
273 current_driver->wave_out_volume((volume & 0xffff),
274 (volume & 0xffff0000) >> 16);
275 }
276 break;
277 default:
278 unimpl("RDPSND packet type %d\n", type);
279 break;
280 }
281 }
282
283 static BOOL
284 rdpsnd_auto_open(void)
285 {
286 static BOOL failed = False;
287
288 if (!failed)
289 {
290 struct audio_driver *auto_driver = current_driver;
291
292 current_driver = drivers;
293 while (current_driver != NULL)
294 {
295 DEBUG(("trying %s...\n", current_driver->name));
296 if (current_driver->wave_out_open())
297 {
298 DEBUG(("selected %s\n", current_driver->name));
299 return True;
300 }
301 g_dsp_fd = 0;
302 current_driver = current_driver->next;
303 }
304
305 warning("no working audio-driver found\n");
306 failed = True;
307 current_driver = auto_driver;
308 }
309
310 return False;
311 }
312
313 static void
314 rdpsnd_register_drivers(char *options)
315 {
316 struct audio_driver **reg;
317
318 /* The order of registrations define the probe-order
319 when opening the device for the first time */
320 reg = &drivers;
321 #if defined(RDPSND_ALSA)
322 *reg = alsa_register(options);
323 assert(*reg);
324 reg = &((*reg)->next);
325 #endif
326 #if defined(RDPSND_SUN)
327 *reg = sun_register(options);
328 assert(*reg);
329 reg = &((*reg)->next);
330 #endif
331 #if defined(RDPSND_OSS)
332 *reg = oss_register(options);
333 assert(*reg);
334 reg = &((*reg)->next);
335 #endif
336 #if defined(RDPSND_SGI)
337 *reg = sgi_register(options);
338 assert(*reg);
339 reg = &((*reg)->next);
340 #endif
341 #if defined(RDPSND_LIBAO)
342 *reg = libao_register(options);
343 assert(*reg);
344 reg = &((*reg)->next);
345 #endif
346 *reg = NULL;
347 }
348
349 BOOL
350 rdpsnd_init(char *optarg)
351 {
352 static struct audio_driver auto_driver;
353 struct audio_driver *pos;
354 char *driver = NULL, *options = NULL;
355
356 drivers = NULL;
357
358 rdpsnd_channel =
359 channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
360 rdpsnd_process);
361
362 if (rdpsnd_channel == NULL)
363 {
364 error("channel_register\n");
365 return False;
366 }
367
368 rdpsnd_queue_init();
369
370 if (optarg != NULL && strlen(optarg) > 0)
371 {
372 driver = options = optarg;
373
374 while (*options != '\0' && *options != ':')
375 options++;
376
377 if (*options == ':')
378 {
379 *options = '\0';
380 options++;
381 }
382
383 if (*options == '\0')
384 options = NULL;
385 }
386
387 rdpsnd_register_drivers(options);
388
389 if (!driver)
390 {
391 auto_driver.wave_out_open = &rdpsnd_auto_open;
392 current_driver = &auto_driver;
393 return True;
394 }
395
396 pos = drivers;
397 while (pos != NULL)
398 {
399 if (!strcmp(pos->name, driver))
400 {
401 DEBUG(("selected %s\n", pos->name));
402 current_driver = pos;
403 return True;
404 }
405 pos = pos->next;
406 }
407 return False;
408 }
409
410 void
411 rdpsnd_show_help(void)
412 {
413 struct audio_driver *pos;
414
415 rdpsnd_register_drivers(NULL);
416
417 pos = drivers;
418 while (pos != NULL)
419 {
420 fprintf(stderr, " %s:\t%s\n", pos->name, pos->description);
421 pos = pos->next;
422 }
423 }
424
425 void
426 rdpsnd_play(void)
427 {
428 current_driver->wave_out_play();
429 }
430
431 void
432 rdpsnd_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
433 {
434 long next_pending;
435
436 if (g_dsp_busy)
437 {
438 FD_SET(g_dsp_fd, wfds);
439 *n = (g_dsp_fd > *n) ? g_dsp_fd : *n;
440 }
441
442 next_pending = rdpsnd_queue_next_completion();
443 if (next_pending >= 0)
444 {
445 long cur_timeout;
446
447 cur_timeout = tv->tv_sec * 1000000 + tv->tv_usec;
448 if (cur_timeout > next_pending)
449 {
450 tv->tv_sec = next_pending / 1000000;
451 tv->tv_usec = next_pending % 1000000;
452 }
453 }
454 }
455
456 void
457 rdpsnd_check_fds(fd_set * rfds, fd_set * wfds)
458 {
459 rdpsnd_queue_complete_pending();
460
461 if (g_dsp_busy && FD_ISSET(g_dsp_fd, wfds))
462 rdpsnd_play();
463 }
464
465 static void
466 rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)
467 {
468 struct audio_packet *packet = &packet_queue[queue_hi];
469 unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
470
471 if (next_hi == queue_pending)
472 {
473 error("No space to queue audio packet\n");
474 return;
475 }
476
477 queue_hi = next_hi;
478
479 packet->s = *s;
480 packet->tick = tick;
481 packet->index = index;
482
483 gettimeofday(&packet->arrive_tv, NULL);
484
485 if (!g_dsp_busy)
486 current_driver->wave_out_play();
487 }
488
489 struct audio_packet *
490 rdpsnd_queue_current_packet(void)
491 {
492 return &packet_queue[queue_lo];
493 }
494
495 BOOL
496 rdpsnd_queue_empty(void)
497 {
498 return (queue_lo == queue_hi);
499 }
500
501 static void
502 rdpsnd_queue_init(void)
503 {
504 queue_pending = queue_lo = queue_hi = 0;
505 }
506
507 void
508 rdpsnd_queue_next(unsigned long completed_in_us)
509 {
510 struct audio_packet *packet;
511
512 assert(!rdpsnd_queue_empty());
513
514 packet = &packet_queue[queue_lo];
515
516 gettimeofday(&packet->completion_tv, NULL);
517
518 packet->completion_tv.tv_usec += completed_in_us;
519 packet->completion_tv.tv_sec += packet->completion_tv.tv_usec / 1000000;
520 packet->completion_tv.tv_usec %= 1000000;
521
522 queue_lo = (queue_lo + 1) % MAX_QUEUE;
523
524 rdpsnd_queue_complete_pending();
525 }
526
527 int
528 rdpsnd_queue_next_tick(void)
529 {
530 if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
531 {
532 return packet_queue[(queue_lo + 1) % MAX_QUEUE].tick;
533 }
534 else
535 {
536 return (packet_queue[queue_lo].tick + 65535) % 65536;
537 }
538 }
539
540 static void
541 rdpsnd_queue_complete_pending(void)
542 {
543 struct timeval now;
544 long elapsed;
545 struct audio_packet *packet;
546
547 gettimeofday(&now, NULL);
548
549 while (queue_pending != queue_lo)
550 {
551 packet = &packet_queue[queue_pending];
552
553 if (now.tv_sec < packet->completion_tv.tv_sec)
554 break;
555
556 if ((now.tv_sec == packet->completion_tv.tv_sec) &&
557 (now.tv_usec < packet->completion_tv.tv_usec))
558 break;
559
560 elapsed = (packet->completion_tv.tv_sec - packet->arrive_tv.tv_sec) * 1000000 +
561 (packet->completion_tv.tv_usec - packet->arrive_tv.tv_usec);
562 elapsed /= 1000;
563
564 xfree(packet->s.data);
565 rdpsnd_send_completion((packet->tick + elapsed) % 65536, packet->index);
566 queue_pending = (queue_pending + 1) % MAX_QUEUE;
567 }
568 }
569
570 static long
571 rdpsnd_queue_next_completion(void)
572 {
573 struct audio_packet *packet;
574 long remaining;
575 struct timeval now;
576
577 if (queue_pending == queue_lo)
578 return -1;
579
580 gettimeofday(&now, NULL);
581
582 packet = &packet_queue[queue_pending];
583
584 remaining = (packet->completion_tv.tv_sec - now.tv_sec) * 1000000 +
585 (packet->completion_tv.tv_usec - now.tv_usec);
586
587 if (remaining < 0)
588 return 0;
589
590 return remaining;
591 }

  ViewVC Help
Powered by ViewVC 1.1.26