/[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 1350 - (hide annotations)
Sun Dec 24 13:48:50 2006 UTC (17 years, 4 months ago) by stargo
Original Path: sourceforge.net/trunk/rdesktop/rdpsnd.c
File MIME type: text/plain
File size: 14243 byte(s)
fix double open of sound device. should at least allow oss, libao, sun and
sgi drivers to be selected again, when they only allow one open of the
device.

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

  ViewVC Help
Powered by ViewVC 1.1.26