/[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 1353 - (hide annotations)
Sun Dec 24 15:22:15 2006 UTC (17 years, 4 months ago) by stargo
Original Path: sourceforge.net/trunk/rdesktop/rdpsnd.c
File MIME type: text/plain
File size: 14354 byte(s)
fix device_available which I broke in a previous commit

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

  ViewVC Help
Powered by ViewVC 1.1.26