/[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 1340 - (hide annotations)
Wed Dec 6 13:11:35 2006 UTC (17 years, 5 months ago) by ossman_
Original Path: sourceforge.net/trunk/rdesktop/rdpsnd.c
File MIME type: text/plain
File size: 12580 byte(s)
Update rdpsnd_negotiate() to new information.

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

  ViewVC Help
Powered by ViewVC 1.1.26