/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1343 - (hide annotations)
Wed Dec 6 13:55:34 2006 UTC (17 years, 5 months ago) by ossman_
Original Path: sourceforge.net/trunk/rdesktop/rdpsnd.c
File MIME type: text/plain
File size: 14310 byte(s)
Add more sensible debug output from rdpsnd.

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

  ViewVC Help
Powered by ViewVC 1.1.26