/[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 1302 - (show annotations)
Thu Oct 26 09:47:17 2006 UTC (17 years, 7 months ago) by ossman_
Original Path: sourceforge.net/trunk/rdesktop/rdpsnd.c
File MIME type: text/plain
File size: 12580 byte(s)
Rewrite the queue management a bit so that blocks are not completed until
they have finished playing. This also makes the queue system mandatory for
all backends.

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_SERVERTICK 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_servertick(STREAM in)
180 {
181 uint16 tick1, tick2;
182 STREAM out;
183
184 /* in_uint8s(in, 4); unknown */
185 in_uint16_le(in, tick1);
186 in_uint16_le(in, tick2);
187
188 out = rdpsnd_init_packet(RDPSND_SERVERTICK | 0x2300, 4);
189 out_uint16_le(out, tick1);
190 out_uint16_le(out, tick2);
191 s_mark_end(out);
192 rdpsnd_send(out);
193 }
194
195 static void
196 rdpsnd_process(STREAM s)
197 {
198 uint8 type;
199 uint16 datalen;
200 uint32 volume;
201 static uint16 tick, format;
202 static uint8 packet_index;
203 static BOOL awaiting_data_packet;
204 static unsigned char missing_bytes[4] = { 0, 0, 0, 0 };
205
206 #ifdef RDPSND_DEBUG
207 printf("RDPSND recv:\n");
208 hexdump(s->p, s->end - s->p);
209 #endif
210
211 if (awaiting_data_packet)
212 {
213 if (format >= MAX_FORMATS)
214 {
215 error("RDPSND: Invalid format index\n");
216 return;
217 }
218
219 if (!device_open || (format != current_format))
220 {
221 if (!device_open && !current_driver->wave_out_open())
222 {
223 rdpsnd_send_completion(tick, packet_index);
224 return;
225 }
226 if (!current_driver->wave_out_set_format(&formats[format]))
227 {
228 rdpsnd_send_completion(tick, packet_index);
229 current_driver->wave_out_close();
230 device_open = False;
231 return;
232 }
233 device_open = True;
234 current_format = format;
235 }
236
237 /* Insert the 4 missing bytes retrieved from last RDPSND_WRITE */
238 memcpy(s->data, missing_bytes, 4);
239
240 rdpsnd_queue_write(rdpsnd_dsp_process
241 (s, current_driver, &formats[current_format]), tick,
242 packet_index);
243 awaiting_data_packet = False;
244 return;
245 }
246
247 in_uint8(s, type);
248 in_uint8s(s, 1); /* unknown? */
249 in_uint16_le(s, datalen);
250
251 switch (type)
252 {
253 case RDPSND_WRITE:
254 in_uint16_le(s, tick);
255 in_uint16_le(s, format);
256 in_uint8(s, packet_index);
257 /* Here are our lost bytes, but why? */
258 memcpy(missing_bytes, s->end - 4, 4);
259 awaiting_data_packet = True;
260 break;
261 case RDPSND_CLOSE:
262 current_driver->wave_out_close();
263 device_open = False;
264 break;
265 case RDPSND_NEGOTIATE:
266 rdpsnd_process_negotiate(s);
267 break;
268 case RDPSND_SERVERTICK:
269 rdpsnd_process_servertick(s);
270 break;
271 case RDPSND_SET_VOLUME:
272 in_uint32(s, volume);
273 if (device_open)
274 {
275 current_driver->wave_out_volume((volume & 0xffff),
276 (volume & 0xffff0000) >> 16);
277 }
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 }
349
350 BOOL
351 rdpsnd_init(char *optarg)
352 {
353 static struct audio_driver auto_driver;
354 struct audio_driver *pos;
355 char *driver = NULL, *options = NULL;
356
357 drivers = NULL;
358
359 rdpsnd_channel =
360 channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
361 rdpsnd_process);
362
363 if (rdpsnd_channel == NULL)
364 {
365 error("channel_register\n");
366 return False;
367 }
368
369 rdpsnd_queue_init();
370
371 if (optarg != NULL && strlen(optarg) > 0)
372 {
373 driver = options = optarg;
374
375 while (*options != '\0' && *options != ':')
376 options++;
377
378 if (*options == ':')
379 {
380 *options = '\0';
381 options++;
382 }
383
384 if (*options == '\0')
385 options = NULL;
386 }
387
388 rdpsnd_register_drivers(options);
389
390 if (!driver)
391 {
392 auto_driver.wave_out_open = &rdpsnd_auto_open;
393 current_driver = &auto_driver;
394 return True;
395 }
396
397 pos = drivers;
398 while (pos != NULL)
399 {
400 if (!strcmp(pos->name, driver))
401 {
402 DEBUG(("selected %s\n", pos->name));
403 current_driver = pos;
404 return True;
405 }
406 pos = pos->next;
407 }
408 return False;
409 }
410
411 void
412 rdpsnd_show_help(void)
413 {
414 struct audio_driver *pos;
415
416 rdpsnd_register_drivers(NULL);
417
418 pos = drivers;
419 while (pos != NULL)
420 {
421 fprintf(stderr, " %s:\t%s\n", pos->name, pos->description);
422 pos = pos->next;
423 }
424 }
425
426 void
427 rdpsnd_play(void)
428 {
429 current_driver->wave_out_play();
430 }
431
432 void
433 rdpsnd_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
434 {
435 long next_pending;
436
437 if (g_dsp_busy)
438 {
439 FD_SET(g_dsp_fd, wfds);
440 *n = (g_dsp_fd > *n) ? g_dsp_fd : *n;
441 }
442
443 next_pending = rdpsnd_queue_next_completion();
444 if (next_pending >= 0)
445 {
446 long cur_timeout;
447
448 cur_timeout = tv->tv_sec * 1000000 + tv->tv_usec;
449 if (cur_timeout > next_pending)
450 {
451 tv->tv_sec = next_pending / 1000000;
452 tv->tv_usec = next_pending % 1000000;
453 }
454 }
455 }
456
457 void
458 rdpsnd_check_fds(fd_set * rfds, fd_set * wfds)
459 {
460 rdpsnd_queue_complete_pending();
461
462 if (g_dsp_busy && FD_ISSET(g_dsp_fd, wfds))
463 rdpsnd_play();
464 }
465
466 static void
467 rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)
468 {
469 struct audio_packet *packet = &packet_queue[queue_hi];
470 unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
471
472 if (next_hi == queue_pending)
473 {
474 error("No space to queue audio packet\n");
475 return;
476 }
477
478 queue_hi = next_hi;
479
480 packet->s = *s;
481 packet->tick = tick;
482 packet->index = index;
483
484 gettimeofday(&packet->arrive_tv, NULL);
485
486 if (!g_dsp_busy)
487 current_driver->wave_out_play();
488 }
489
490 struct audio_packet *
491 rdpsnd_queue_current_packet(void)
492 {
493 return &packet_queue[queue_lo];
494 }
495
496 BOOL
497 rdpsnd_queue_empty(void)
498 {
499 return (queue_lo == queue_hi);
500 }
501
502 static void
503 rdpsnd_queue_init(void)
504 {
505 queue_pending = queue_lo = queue_hi = 0;
506 }
507
508 void
509 rdpsnd_queue_next(unsigned long completed_in_us)
510 {
511 struct audio_packet *packet;
512
513 assert(!rdpsnd_queue_empty());
514
515 packet = &packet_queue[queue_lo];
516
517 gettimeofday(&packet->completion_tv, NULL);
518
519 packet->completion_tv.tv_usec += completed_in_us;
520 packet->completion_tv.tv_sec += packet->completion_tv.tv_usec / 1000000;
521 packet->completion_tv.tv_usec %= 1000000;
522
523 queue_lo = (queue_lo + 1) % MAX_QUEUE;
524
525 rdpsnd_queue_complete_pending();
526 }
527
528 int
529 rdpsnd_queue_next_tick(void)
530 {
531 if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
532 {
533 return packet_queue[(queue_lo + 1) % MAX_QUEUE].tick;
534 }
535 else
536 {
537 return (packet_queue[queue_lo].tick + 65535) % 65536;
538 }
539 }
540
541 static void
542 rdpsnd_queue_complete_pending(void)
543 {
544 struct timeval now;
545 long elapsed;
546 struct audio_packet *packet;
547
548 gettimeofday(&now, NULL);
549
550 while (queue_pending != queue_lo)
551 {
552 packet = &packet_queue[queue_pending];
553
554 if (now.tv_sec < packet->completion_tv.tv_sec)
555 break;
556
557 if ((now.tv_sec == packet->completion_tv.tv_sec) &&
558 (now.tv_usec < packet->completion_tv.tv_usec))
559 break;
560
561 elapsed = (packet->completion_tv.tv_sec - packet->arrive_tv.tv_sec) * 1000000 +
562 (packet->completion_tv.tv_usec - packet->arrive_tv.tv_usec);
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