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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1341 - (show annotations)
Wed Dec 6 13:18:36 2006 UTC (17 years, 5 months ago) by ossman_
Original Path: sourceforge.net/trunk/rdesktop/rdpsnd.c
File MIME type: text/plain
File size: 12584 byte(s)
Properly split volume channels for RDPSND_SET_VOLUME.

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 uint16 in_format_count, i;
99 uint8 pad;
100 uint16 version;
101 WAVEFORMATEX *format;
102 STREAM out;
103 BOOL device_available = False;
104 int readcnt;
105 int discardcnt;
106
107 in_uint8s(in, 14); /* initial bytes not valid from server */
108 in_uint16_le(in, in_format_count);
109 in_uint8(in, pad);
110 in_uint16_le(in, version);
111 in_uint8s(in, 1); /* padding */
112
113 if (current_driver->wave_out_open())
114 {
115 current_driver->wave_out_close();
116 device_available = True;
117 }
118
119 format_count = 0;
120 if (s_check_rem(in, 18 * in_format_count))
121 {
122 for (i = 0; i < in_format_count; i++)
123 {
124 format = &formats[format_count];
125 in_uint16_le(in, format->wFormatTag);
126 in_uint16_le(in, format->nChannels);
127 in_uint32_le(in, format->nSamplesPerSec);
128 in_uint32_le(in, format->nAvgBytesPerSec);
129 in_uint16_le(in, format->nBlockAlign);
130 in_uint16_le(in, format->wBitsPerSample);
131 in_uint16_le(in, format->cbSize);
132
133 /* read in the buffer of unknown use */
134 readcnt = format->cbSize;
135 discardcnt = 0;
136 if (format->cbSize > MAX_CBSIZE)
137 {
138 fprintf(stderr, "cbSize too large for buffer: %d\n",
139 format->cbSize);
140 readcnt = MAX_CBSIZE;
141 discardcnt = format->cbSize - MAX_CBSIZE;
142 }
143 in_uint8a(in, format->cb, readcnt);
144 in_uint8s(in, discardcnt);
145
146 if (device_available && current_driver->wave_out_format_supported(format))
147 {
148 format_count++;
149 if (format_count == MAX_FORMATS)
150 break;
151 }
152 }
153 }
154
155 out = rdpsnd_init_packet(RDPSND_NEGOTIATE | 0x200, 20 + 18 * format_count);
156 out_uint32_le(out, 3); /* flags */
157 out_uint32(out, 0xffffffff); /* volume */
158 out_uint32(out, 0); /* pitch */
159 out_uint16(out, 0); /* UDP port */
160
161 out_uint16_le(out, format_count);
162 out_uint8(out, 0); /* padding */
163 out_uint16_le(out, 2); /* version */
164 out_uint8(out, 0); /* padding */
165
166 for (i = 0; i < format_count; i++)
167 {
168 format = &formats[i];
169 out_uint16_le(out, format->wFormatTag);
170 out_uint16_le(out, format->nChannels);
171 out_uint32_le(out, format->nSamplesPerSec);
172 out_uint32_le(out, format->nAvgBytesPerSec);
173 out_uint16_le(out, format->nBlockAlign);
174 out_uint16_le(out, format->wBitsPerSample);
175 out_uint16(out, 0); /* cbSize */
176 }
177
178 s_mark_end(out);
179 rdpsnd_send(out);
180 }
181
182 static void
183 rdpsnd_process_ping(STREAM in)
184 {
185 uint16 tick;
186 STREAM out;
187
188 in_uint16_le(in, tick);
189
190 out = rdpsnd_init_packet(RDPSND_PING | 0x2300, 4);
191 out_uint16_le(out, tick);
192 out_uint16_le(out, 0);
193 s_mark_end(out);
194 rdpsnd_send(out);
195 }
196
197 static void
198 rdpsnd_process(STREAM s)
199 {
200 uint8 type;
201 uint16 datalen;
202 uint16 vol_left, vol_right;
203 static uint16 tick, format;
204 static uint8 packet_index;
205 static BOOL awaiting_data_packet;
206 static unsigned char missing_bytes[4] = { 0, 0, 0, 0 };
207
208 #ifdef RDPSND_DEBUG
209 printf("RDPSND recv:\n");
210 hexdump(s->p, s->end - s->p);
211 #endif
212
213 if (awaiting_data_packet)
214 {
215 if (format >= MAX_FORMATS)
216 {
217 error("RDPSND: Invalid format index\n");
218 return;
219 }
220
221 if (!device_open || (format != current_format))
222 {
223 if (!device_open && !current_driver->wave_out_open())
224 {
225 rdpsnd_send_completion(tick, packet_index);
226 return;
227 }
228 if (!current_driver->wave_out_set_format(&formats[format]))
229 {
230 rdpsnd_send_completion(tick, packet_index);
231 current_driver->wave_out_close();
232 device_open = False;
233 return;
234 }
235 device_open = True;
236 current_format = format;
237 }
238
239 /* Insert the 4 missing bytes retrieved from last RDPSND_WRITE */
240 memcpy(s->data, missing_bytes, 4);
241
242 rdpsnd_queue_write(rdpsnd_dsp_process
243 (s, current_driver, &formats[current_format]), tick,
244 packet_index);
245 awaiting_data_packet = False;
246 return;
247 }
248
249 in_uint8(s, type);
250 in_uint8s(s, 1); /* unknown? */
251 in_uint16_le(s, datalen);
252
253 switch (type)
254 {
255 case RDPSND_WRITE:
256 in_uint16_le(s, tick);
257 in_uint16_le(s, format);
258 in_uint8(s, packet_index);
259 /* Here are our lost bytes, but why? */
260 memcpy(missing_bytes, s->end - 4, 4);
261 awaiting_data_packet = True;
262 break;
263 case RDPSND_CLOSE:
264 current_driver->wave_out_close();
265 device_open = False;
266 break;
267 case RDPSND_NEGOTIATE:
268 rdpsnd_process_negotiate(s);
269 break;
270 case RDPSND_PING:
271 rdpsnd_process_ping(s);
272 break;
273 case RDPSND_SET_VOLUME:
274 in_uint16_le(s, vol_left);
275 in_uint16_le(s, vol_right);
276 if (device_open)
277 current_driver->wave_out_volume(vol_left, vol_right);
278 break;
279 default:
280 unimpl("RDPSND packet type %d\n", type);
281 break;
282 }
283 }
284
285 static BOOL
286 rdpsnd_auto_open(void)
287 {
288 static BOOL failed = False;
289
290 if (!failed)
291 {
292 struct audio_driver *auto_driver = current_driver;
293
294 current_driver = drivers;
295 while (current_driver != NULL)
296 {
297 DEBUG(("trying %s...\n", current_driver->name));
298 if (current_driver->wave_out_open())
299 {
300 DEBUG(("selected %s\n", current_driver->name));
301 return True;
302 }
303 g_dsp_fd = 0;
304 current_driver = current_driver->next;
305 }
306
307 warning("no working audio-driver found\n");
308 failed = True;
309 current_driver = auto_driver;
310 }
311
312 return False;
313 }
314
315 static void
316 rdpsnd_register_drivers(char *options)
317 {
318 struct audio_driver **reg;
319
320 /* The order of registrations define the probe-order
321 when opening the device for the first time */
322 reg = &drivers;
323 #if defined(RDPSND_ALSA)
324 *reg = alsa_register(options);
325 assert(*reg);
326 reg = &((*reg)->next);
327 #endif
328 #if defined(RDPSND_SUN)
329 *reg = sun_register(options);
330 assert(*reg);
331 reg = &((*reg)->next);
332 #endif
333 #if defined(RDPSND_OSS)
334 *reg = oss_register(options);
335 assert(*reg);
336 reg = &((*reg)->next);
337 #endif
338 #if defined(RDPSND_SGI)
339 *reg = sgi_register(options);
340 assert(*reg);
341 reg = &((*reg)->next);
342 #endif
343 #if defined(RDPSND_LIBAO)
344 *reg = libao_register(options);
345 assert(*reg);
346 reg = &((*reg)->next);
347 #endif
348 *reg = NULL;
349 }
350
351 BOOL
352 rdpsnd_init(char *optarg)
353 {
354 static struct audio_driver auto_driver;
355 struct audio_driver *pos;
356 char *driver = NULL, *options = NULL;
357
358 drivers = NULL;
359
360 rdpsnd_channel =
361 channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
362 rdpsnd_process);
363
364 if (rdpsnd_channel == NULL)
365 {
366 error("channel_register\n");
367 return False;
368 }
369
370 rdpsnd_queue_init();
371
372 if (optarg != NULL && strlen(optarg) > 0)
373 {
374 driver = options = optarg;
375
376 while (*options != '\0' && *options != ':')
377 options++;
378
379 if (*options == ':')
380 {
381 *options = '\0';
382 options++;
383 }
384
385 if (*options == '\0')
386 options = NULL;
387 }
388
389 rdpsnd_register_drivers(options);
390
391 if (!driver)
392 {
393 auto_driver.wave_out_open = &rdpsnd_auto_open;
394 current_driver = &auto_driver;
395 return True;
396 }
397
398 pos = drivers;
399 while (pos != NULL)
400 {
401 if (!strcmp(pos->name, driver))
402 {
403 DEBUG(("selected %s\n", pos->name));
404 current_driver = pos;
405 return True;
406 }
407 pos = pos->next;
408 }
409 return False;
410 }
411
412 void
413 rdpsnd_show_help(void)
414 {
415 struct audio_driver *pos;
416
417 rdpsnd_register_drivers(NULL);
418
419 pos = drivers;
420 while (pos != NULL)
421 {
422 fprintf(stderr, " %s:\t%s\n", pos->name, pos->description);
423 pos = pos->next;
424 }
425 }
426
427 void
428 rdpsnd_play(void)
429 {
430 current_driver->wave_out_play();
431 }
432
433 void
434 rdpsnd_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
435 {
436 long next_pending;
437
438 if (g_dsp_busy)
439 {
440 FD_SET(g_dsp_fd, wfds);
441 *n = (g_dsp_fd > *n) ? g_dsp_fd : *n;
442 }
443
444 next_pending = rdpsnd_queue_next_completion();
445 if (next_pending >= 0)
446 {
447 long cur_timeout;
448
449 cur_timeout = tv->tv_sec * 1000000 + tv->tv_usec;
450 if (cur_timeout > next_pending)
451 {
452 tv->tv_sec = next_pending / 1000000;
453 tv->tv_usec = next_pending % 1000000;
454 }
455 }
456 }
457
458 void
459 rdpsnd_check_fds(fd_set * rfds, fd_set * wfds)
460 {
461 rdpsnd_queue_complete_pending();
462
463 if (g_dsp_busy && FD_ISSET(g_dsp_fd, wfds))
464 rdpsnd_play();
465 }
466
467 static void
468 rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)
469 {
470 struct audio_packet *packet = &packet_queue[queue_hi];
471 unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
472
473 if (next_hi == queue_pending)
474 {
475 error("No space to queue audio packet\n");
476 return;
477 }
478
479 queue_hi = next_hi;
480
481 packet->s = *s;
482 packet->tick = tick;
483 packet->index = index;
484
485 gettimeofday(&packet->arrive_tv, NULL);
486
487 if (!g_dsp_busy)
488 current_driver->wave_out_play();
489 }
490
491 struct audio_packet *
492 rdpsnd_queue_current_packet(void)
493 {
494 return &packet_queue[queue_lo];
495 }
496
497 BOOL
498 rdpsnd_queue_empty(void)
499 {
500 return (queue_lo == queue_hi);
501 }
502
503 static void
504 rdpsnd_queue_init(void)
505 {
506 queue_pending = queue_lo = queue_hi = 0;
507 }
508
509 void
510 rdpsnd_queue_next(unsigned long completed_in_us)
511 {
512 struct audio_packet *packet;
513
514 assert(!rdpsnd_queue_empty());
515
516 packet = &packet_queue[queue_lo];
517
518 gettimeofday(&packet->completion_tv, NULL);
519
520 packet->completion_tv.tv_usec += completed_in_us;
521 packet->completion_tv.tv_sec += packet->completion_tv.tv_usec / 1000000;
522 packet->completion_tv.tv_usec %= 1000000;
523
524 queue_lo = (queue_lo + 1) % MAX_QUEUE;
525
526 rdpsnd_queue_complete_pending();
527 }
528
529 int
530 rdpsnd_queue_next_tick(void)
531 {
532 if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
533 {
534 return packet_queue[(queue_lo + 1) % MAX_QUEUE].tick;
535 }
536 else
537 {
538 return (packet_queue[queue_lo].tick + 65535) % 65536;
539 }
540 }
541
542 static void
543 rdpsnd_queue_complete_pending(void)
544 {
545 struct timeval now;
546 long elapsed;
547 struct audio_packet *packet;
548
549 gettimeofday(&now, NULL);
550
551 while (queue_pending != queue_lo)
552 {
553 packet = &packet_queue[queue_pending];
554
555 if (now.tv_sec < packet->completion_tv.tv_sec)
556 break;
557
558 if ((now.tv_sec == packet->completion_tv.tv_sec) &&
559 (now.tv_usec < packet->completion_tv.tv_usec))
560 break;
561
562 elapsed = (packet->completion_tv.tv_sec - packet->arrive_tv.tv_sec) * 1000000 +
563 (packet->completion_tv.tv_usec - packet->arrive_tv.tv_usec);
564 elapsed /= 1000;
565
566 xfree(packet->s.data);
567 rdpsnd_send_completion((packet->tick + elapsed) % 65536, packet->index);
568 queue_pending = (queue_pending + 1) % MAX_QUEUE;
569 }
570 }
571
572 static long
573 rdpsnd_queue_next_completion(void)
574 {
575 struct audio_packet *packet;
576 long remaining;
577 struct timeval now;
578
579 if (queue_pending == queue_lo)
580 return -1;
581
582 gettimeofday(&now, NULL);
583
584 packet = &packet_queue[queue_pending];
585
586 remaining = (packet->completion_tv.tv_sec - now.tv_sec) * 1000000 +
587 (packet->completion_tv.tv_usec - now.tv_usec);
588
589 if (remaining < 0)
590 return 0;
591
592 return remaining;
593 }

  ViewVC Help
Powered by ViewVC 1.1.26