/[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 1359 - (hide annotations)
Tue Jan 2 16:30:06 2007 UTC (17 years, 4 months ago) by ossman_
Original Path: sourceforge.net/trunk/rdesktop/rdpsnd.c
File MIME type: text/plain
File size: 20498 byte(s)
Add experimental extension to the RDPSND protocol that allows recording.

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 ossman_ 1359 #define RDPSND_REC_NEGOTIATE 39
38     #define RDPSND_REC_START 40
39     #define RDPSND_REC_STOP 41
40     #define RDPSND_REC_DATA 42
41     #define RDPSND_REC_SET_VOLUME 43
42    
43     #define RDPSND_FLAG_RECORD 0x00800000
44    
45 matthewc 474 #define MAX_FORMATS 10
46 ossman_ 1359 #define MAX_QUEUE 50
47 matthewc 474
48 matthewc 432 static VCHANNEL *rdpsnd_channel;
49 ossman_ 1359 static VCHANNEL *rdpsnddbg_channel;
50 stargo 1255 static struct audio_driver *drivers = NULL;
51 stargo 1256 struct audio_driver *current_driver = NULL;
52 matthewc 432
53 matthewc 474 static BOOL device_open;
54 ossman_ 1359 static BOOL rec_device_open;
55    
56 matthewc 474 static WAVEFORMATEX formats[MAX_FORMATS];
57     static unsigned int format_count;
58     static unsigned int current_format;
59 ossman_ 1359
60     static WAVEFORMATEX rec_formats[MAX_FORMATS];
61     static unsigned int rec_format_count;
62    
63 ossman_ 1302 unsigned int queue_hi, queue_lo, queue_pending;
64 stargo 1256 struct audio_packet packet_queue[MAX_QUEUE];
65 matthewc 474
66 ossman_ 1359 static char record_buffer[8192];
67     static int record_buffer_size;
68    
69 ossman_ 1342 static uint8 packet_opcode;
70     static struct stream packet;
71    
72 stargo 1255 void (*wave_out_play) (void);
73    
74 ossman_ 1302 static void rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index);
75     static void rdpsnd_queue_init(void);
76     static void rdpsnd_queue_complete_pending(void);
77     static long rdpsnd_queue_next_completion(void);
78    
79 astrand 665 static STREAM
80 matthewc 474 rdpsnd_init_packet(uint16 type, uint16 size)
81     {
82     STREAM s;
83    
84 astrand 499 s = channel_init(rdpsnd_channel, size + 4);
85 matthewc 474 out_uint16_le(s, type);
86     out_uint16_le(s, size);
87     return s;
88     }
89    
90 astrand 665 static void
91 matthewc 474 rdpsnd_send(STREAM s)
92     {
93     channel_send(s, rdpsnd_channel);
94     }
95    
96 ossman_ 1302 static void
97 astrand 499 rdpsnd_send_completion(uint16 tick, uint8 packet_index)
98 matthewc 474 {
99     STREAM s;
100    
101     s = rdpsnd_init_packet(RDPSND_COMPLETION, 4);
102 stargo 1254 out_uint16_le(s, tick);
103 matthewc 474 out_uint8(s, packet_index);
104     out_uint8(s, 0);
105     s_mark_end(s);
106     rdpsnd_send(s);
107 ossman_ 1343
108     DEBUG_SOUND(("RDPSND: -> RDPSND_COMPLETION(tick: %u, index: %u)\n",
109     (unsigned) tick, (unsigned) packet_index));
110 matthewc 474 }
111    
112 ossman_ 1359 static void
113     rdpsnd_flush_record(void)
114     {
115     STREAM s;
116     unsigned int chunk_size;
117     char *data;
118 ossman_ 1346
119 ossman_ 1359 if (record_buffer_size == 0)
120     return;
121    
122     assert(record_buffer_size <= sizeof(record_buffer));
123    
124     data = record_buffer;
125    
126     /*
127     * Microsoft's RDP server keeps dropping chunks, so we need to
128     * transmit everything inside one channel fragment or we risk
129     * making the rdpsnd server go out of sync with the byte stream.
130     */
131     while (record_buffer_size)
132     {
133     if (record_buffer_size < 1596)
134     chunk_size = record_buffer_size;
135     else
136     chunk_size = 1596;
137    
138     s = rdpsnd_init_packet(RDPSND_REC_DATA, chunk_size);
139     out_uint8p(s, data, chunk_size);
140    
141     s_mark_end(s);
142     rdpsnd_send(s);
143    
144     data = data + chunk_size;
145     record_buffer_size -= chunk_size;
146    
147     DEBUG_SOUND(("RDPSND: -> RDPSND_REC_DATA(length: %u)\n", (unsigned) chunk_size));
148     }
149    
150     record_buffer_size = 0;
151     }
152    
153     void
154     rdpsnd_record(const void *data, unsigned int size)
155     {
156     int remain;
157    
158     assert(rec_device_open);
159    
160     while (size)
161     {
162     remain = sizeof(record_buffer) - record_buffer_size;
163    
164     if (size >= remain)
165     {
166     memcpy(record_buffer + record_buffer_size, data, remain);
167     record_buffer_size += remain;
168     rdpsnd_flush_record();
169     data = (const char *) data + remain;
170     size -= remain;
171     }
172     else
173     {
174     memcpy(record_buffer + record_buffer_size, data, size);
175     record_buffer_size += size;
176     size = 0;
177     }
178     }
179     }
180    
181 ossman_ 1346 static BOOL
182     rdpsnd_auto_select(void)
183     {
184     static BOOL failed = False;
185    
186     if (!failed)
187     {
188     current_driver = drivers;
189     while (current_driver != NULL)
190     {
191     DEBUG(("trying %s...\n", current_driver->name));
192     if (current_driver->wave_out_open())
193     {
194     DEBUG(("selected %s\n", current_driver->name));
195 stargo 1350 current_driver->wave_out_close();
196 ossman_ 1346 return True;
197     }
198     current_driver = current_driver->next;
199     }
200    
201     warning("no working audio-driver found\n");
202     failed = True;
203     current_driver = NULL;
204     }
205    
206     return False;
207     }
208    
209 astrand 665 static void
210 matthewc 474 rdpsnd_process_negotiate(STREAM in)
211     {
212 ossman_ 1340 uint16 in_format_count, i;
213     uint8 pad;
214     uint16 version;
215 matthewc 474 WAVEFORMATEX *format;
216     STREAM out;
217 stargo 491 BOOL device_available = False;
218 stargo 493 int readcnt;
219     int discardcnt;
220 matthewc 474
221 ossman_ 1340 in_uint8s(in, 14); /* initial bytes not valid from server */
222 matthewc 474 in_uint16_le(in, in_format_count);
223 ossman_ 1340 in_uint8(in, pad);
224     in_uint16_le(in, version);
225     in_uint8s(in, 1); /* padding */
226 matthewc 474
227 ossman_ 1344 DEBUG_SOUND(("RDPSND: RDPSND_NEGOTIATE(formats: %d, pad: 0x%02x, version: %x)\n",
228     (int) in_format_count, (unsigned) pad, (unsigned) version));
229 ossman_ 1343
230 ossman_ 1346 if (!current_driver)
231 stargo 1353 device_available = rdpsnd_auto_select();
232 ossman_ 1346
233 stargo 1353 if (current_driver && !device_available && current_driver->wave_out_open())
234 stargo 491 {
235 stargo 1353 current_driver->wave_out_close();
236 stargo 491 device_available = True;
237     }
238    
239 matthewc 474 format_count = 0;
240 astrand 499 if (s_check_rem(in, 18 * in_format_count))
241 matthewc 474 {
242     for (i = 0; i < in_format_count; i++)
243     {
244     format = &formats[format_count];
245     in_uint16_le(in, format->wFormatTag);
246     in_uint16_le(in, format->nChannels);
247     in_uint32_le(in, format->nSamplesPerSec);
248     in_uint32_le(in, format->nAvgBytesPerSec);
249     in_uint16_le(in, format->nBlockAlign);
250     in_uint16_le(in, format->wBitsPerSample);
251     in_uint16_le(in, format->cbSize);
252    
253 stargo 492 /* read in the buffer of unknown use */
254 stargo 493 readcnt = format->cbSize;
255     discardcnt = 0;
256 stargo 492 if (format->cbSize > MAX_CBSIZE)
257     {
258 astrand 499 fprintf(stderr, "cbSize too large for buffer: %d\n",
259     format->cbSize);
260 stargo 492 readcnt = MAX_CBSIZE;
261     discardcnt = format->cbSize - MAX_CBSIZE;
262     }
263     in_uint8a(in, format->cb, readcnt);
264     in_uint8s(in, discardcnt);
265    
266 stargo 1255 if (device_available && current_driver->wave_out_format_supported(format))
267 matthewc 474 {
268     format_count++;
269     if (format_count == MAX_FORMATS)
270     break;
271     }
272     }
273     }
274    
275 astrand 499 out = rdpsnd_init_packet(RDPSND_NEGOTIATE | 0x200, 20 + 18 * format_count);
276 ossman_ 1359 out_uint32_le(out, 0x00800003); /* flags */
277 matthewc 474 out_uint32(out, 0xffffffff); /* volume */
278 astrand 499 out_uint32(out, 0); /* pitch */
279     out_uint16(out, 0); /* UDP port */
280 matthewc 474
281     out_uint16_le(out, format_count);
282 ossman_ 1340 out_uint8(out, 0); /* padding */
283     out_uint16_le(out, 2); /* version */
284     out_uint8(out, 0); /* padding */
285 matthewc 474
286     for (i = 0; i < format_count; i++)
287     {
288     format = &formats[i];
289     out_uint16_le(out, format->wFormatTag);
290     out_uint16_le(out, format->nChannels);
291     out_uint32_le(out, format->nSamplesPerSec);
292     out_uint32_le(out, format->nAvgBytesPerSec);
293     out_uint16_le(out, format->nBlockAlign);
294     out_uint16_le(out, format->wBitsPerSample);
295 astrand 499 out_uint16(out, 0); /* cbSize */
296 matthewc 474 }
297    
298     s_mark_end(out);
299 ossman_ 1343
300     DEBUG_SOUND(("RDPSND: -> RDPSND_NEGOTIATE(formats: %d)\n", (int) format_count));
301    
302 matthewc 474 rdpsnd_send(out);
303     }
304    
305 astrand 665 static void
306 ossman_ 1339 rdpsnd_process_ping(STREAM in)
307 matthewc 474 {
308 ossman_ 1339 uint16 tick;
309 matthewc 474 STREAM out;
310    
311 ossman_ 1339 in_uint16_le(in, tick);
312 matthewc 474
313 ossman_ 1343 DEBUG_SOUND(("RDPSND: RDPSND_PING(tick: 0x%04x)\n", (unsigned) tick));
314    
315 ossman_ 1339 out = rdpsnd_init_packet(RDPSND_PING | 0x2300, 4);
316     out_uint16_le(out, tick);
317     out_uint16_le(out, 0);
318 matthewc 474 s_mark_end(out);
319     rdpsnd_send(out);
320 ossman_ 1343
321     DEBUG_SOUND(("RDPSND: -> (tick: 0x%04x)\n", (unsigned) tick));
322 matthewc 474 }
323    
324 astrand 665 static void
325 ossman_ 1359 rdpsnd_process_rec_negotiate(STREAM in)
326     {
327     uint16 in_format_count, i;
328     uint16 version;
329     WAVEFORMATEX *format;
330     STREAM out;
331     BOOL device_available = False;
332     int readcnt;
333     int discardcnt;
334    
335     in_uint8s(in, 8); /* initial bytes not valid from server */
336     in_uint16_le(in, in_format_count);
337     in_uint16_le(in, version);
338    
339     DEBUG_SOUND(("RDPSND: RDPSND_REC_NEGOTIATE(formats: %d, version: %x)\n",
340     (int) in_format_count, (unsigned) version));
341    
342     if (!current_driver)
343     device_available = rdpsnd_auto_select();
344    
345     if (current_driver && !device_available && current_driver->wave_in_open
346     && current_driver->wave_in_open())
347     {
348     current_driver->wave_in_close();
349     device_available = True;
350     }
351    
352     rec_format_count = 0;
353     if (s_check_rem(in, 18 * in_format_count))
354     {
355     for (i = 0; i < in_format_count; i++)
356     {
357     format = &rec_formats[rec_format_count];
358     in_uint16_le(in, format->wFormatTag);
359     in_uint16_le(in, format->nChannels);
360     in_uint32_le(in, format->nSamplesPerSec);
361     in_uint32_le(in, format->nAvgBytesPerSec);
362     in_uint16_le(in, format->nBlockAlign);
363     in_uint16_le(in, format->wBitsPerSample);
364     in_uint16_le(in, format->cbSize);
365    
366     /* read in the buffer of unknown use */
367     readcnt = format->cbSize;
368     discardcnt = 0;
369     if (format->cbSize > MAX_CBSIZE)
370     {
371     fprintf(stderr, "cbSize too large for buffer: %d\n",
372     format->cbSize);
373     readcnt = MAX_CBSIZE;
374     discardcnt = format->cbSize - MAX_CBSIZE;
375     }
376     in_uint8a(in, format->cb, readcnt);
377     in_uint8s(in, discardcnt);
378    
379     if (device_available && current_driver->wave_in_format_supported(format))
380     {
381     rec_format_count++;
382     if (rec_format_count == MAX_FORMATS)
383     break;
384     }
385     }
386     }
387    
388     out = rdpsnd_init_packet(RDPSND_REC_NEGOTIATE, 12 + 18 * rec_format_count);
389     out_uint32_le(out, 0x00000000); /* flags */
390     out_uint32_le(out, 0xffffffff); /* volume */
391     out_uint16_le(out, rec_format_count);
392     out_uint16_le(out, 1); /* version */
393    
394     for (i = 0; i < rec_format_count; i++)
395     {
396     format = &rec_formats[i];
397     out_uint16_le(out, format->wFormatTag);
398     out_uint16_le(out, format->nChannels);
399     out_uint32_le(out, format->nSamplesPerSec);
400     out_uint32_le(out, format->nAvgBytesPerSec);
401     out_uint16_le(out, format->nBlockAlign);
402     out_uint16_le(out, format->wBitsPerSample);
403     out_uint16(out, 0); /* cbSize */
404     }
405    
406     s_mark_end(out);
407    
408     DEBUG_SOUND(("RDPSND: -> RDPSND_REC_NEGOTIATE(formats: %d)\n", (int) rec_format_count));
409    
410     rdpsnd_send(out);
411     }
412    
413     static void
414 ossman_ 1342 rdpsnd_process_packet(uint8 opcode, STREAM s)
415 matthewc 432 {
416 ossman_ 1341 uint16 vol_left, vol_right;
417 matthewc 474 static uint16 tick, format;
418     static uint8 packet_index;
419    
420 ossman_ 1342 switch (opcode)
421 matthewc 474 {
422 ossman_ 1342 case RDPSND_WRITE:
423     in_uint16_le(s, tick);
424     in_uint16_le(s, format);
425     in_uint8(s, packet_index);
426     in_uint8s(s, 3);
427 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));
428 matthewc 474
429 ossman_ 1342 if (format >= MAX_FORMATS)
430 matthewc 474 {
431 ossman_ 1342 error("RDPSND: Invalid format index\n");
432     break;
433 matthewc 474 }
434 ossman_ 1342
435     if (!device_open || (format != current_format))
436 matthewc 474 {
437 ossman_ 1346 /*
438     * If we haven't selected a device by now, then either
439     * we've failed to find a working device, or the server
440     * is sending bogus RDPSND_WRITE.
441     */
442     if (!current_driver)
443     {
444     rdpsnd_send_completion(tick, packet_index);
445     break;
446     }
447 ossman_ 1342 if (!device_open && !current_driver->wave_out_open())
448     {
449     rdpsnd_send_completion(tick, packet_index);
450     break;
451     }
452     if (!current_driver->wave_out_set_format(&formats[format]))
453     {
454     rdpsnd_send_completion(tick, packet_index);
455     current_driver->wave_out_close();
456     device_open = False;
457     break;
458     }
459     device_open = True;
460     current_format = format;
461 matthewc 474 }
462    
463 ossman_ 1342 rdpsnd_queue_write(rdpsnd_dsp_process
464     (s->p, s->end - s->p, current_driver,
465     &formats[current_format]), tick, packet_index);
466     return;
467 astrand 499 break;
468     case RDPSND_CLOSE:
469 ossman_ 1343 DEBUG_SOUND(("RDPSND: RDPSND_CLOSE()\n"));
470 ossman_ 1346 if (device_open)
471     current_driver->wave_out_close();
472 astrand 499 device_open = False;
473     break;
474     case RDPSND_NEGOTIATE:
475     rdpsnd_process_negotiate(s);
476     break;
477 ossman_ 1339 case RDPSND_PING:
478     rdpsnd_process_ping(s);
479 astrand 499 break;
480     case RDPSND_SET_VOLUME:
481 ossman_ 1341 in_uint16_le(s, vol_left);
482     in_uint16_le(s, vol_right);
483 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));
484 astrand 499 if (device_open)
485 ossman_ 1341 current_driver->wave_out_volume(vol_left, vol_right);
486 astrand 499 break;
487 ossman_ 1359 case RDPSND_REC_NEGOTIATE:
488     rdpsnd_process_rec_negotiate(s);
489     break;
490     case RDPSND_REC_START:
491     in_uint16_le(s, format);
492     DEBUG_SOUND(("RDPSND: RDPSND_REC_START(format: %u)\n", (unsigned) format));
493    
494     if (format >= MAX_FORMATS)
495     {
496     error("RDPSND: Invalid format index\n");
497     break;
498     }
499    
500     if (rec_device_open)
501     {
502     error("RDPSND: Multiple RDPSND_REC_START\n");
503     break;
504     }
505    
506     if (!current_driver->wave_in_open())
507     break;
508    
509     if (!current_driver->wave_in_set_format(&rec_formats[format]))
510     {
511     error("RDPSND: Device not accepting format\n");
512     current_driver->wave_in_close();
513     break;
514     }
515     rec_device_open = True;
516     break;
517     case RDPSND_REC_STOP:
518     DEBUG_SOUND(("RDPSND: RDPSND_REC_STOP()\n"));
519     rdpsnd_flush_record();
520     if (rec_device_open)
521     current_driver->wave_in_close();
522     rec_device_open = False;
523     break;
524     case RDPSND_REC_SET_VOLUME:
525     in_uint16_le(s, vol_left);
526     in_uint16_le(s, vol_right);
527     DEBUG_SOUND(("RDPSND: RDPSND_REC_VOLUME(left: 0x%04x (%u %%), right: 0x%04x (%u %%))\n", (unsigned) vol_left, (unsigned) vol_left / 655, (unsigned) vol_right, (unsigned) vol_right / 655));
528     if (rec_device_open)
529     current_driver->wave_in_volume(vol_left, vol_right);
530     break;
531 astrand 499 default:
532 ossman_ 1342 unimpl("RDPSND packet type %x\n", opcode);
533 astrand 499 break;
534 matthewc 474 }
535 matthewc 432 }
536    
537 ossman_ 1342 static void
538     rdpsnd_process(STREAM s)
539     {
540     uint16 len;
541    
542     while (!s_check_end(s))
543     {
544     /* New packet */
545     if (packet.size == 0)
546     {
547     if ((s->end - s->p) < 4)
548     {
549     error("RDPSND: Split at packet header. Things will go south from here...\n");
550     return;
551     }
552     in_uint8(s, packet_opcode);
553     in_uint8s(s, 1); /* Padding */
554     in_uint16_le(s, len);
555    
556 ossman_ 1343 DEBUG_SOUND(("RDPSND: == Opcode %x Length: %d ==\n",
557     (int) packet_opcode, (int) len));
558    
559 ossman_ 1342 packet.p = packet.data;
560     packet.end = packet.data + len;
561     packet.size = len;
562     }
563     else
564     {
565     len = MIN(s->end - s->p, packet.end - packet.p);
566    
567     /* Microsoft's server is so broken it's not even funny... */
568     if (packet_opcode == RDPSND_WRITE)
569     {
570     if ((packet.p - packet.data) < 12)
571     len = MIN(len, 12 - (packet.p - packet.data));
572     else if ((packet.p - packet.data) == 12)
573     {
574 ossman_ 1343 DEBUG_SOUND(("RDPSND: Eating 4 bytes of %d bytes...\n",
575     len));
576 ossman_ 1342 in_uint8s(s, 4);
577     len -= 4;
578     }
579     }
580    
581     in_uint8a(s, packet.p, len);
582     packet.p += len;
583     }
584    
585     /* Packet fully assembled */
586     if (packet.p == packet.end)
587     {
588     packet.p = packet.data;
589     rdpsnd_process_packet(packet_opcode, &packet);
590     packet.size = 0;
591     }
592     }
593     }
594    
595 ossman_ 1359 static BOOL
596     rdpsnddbg_line_handler(const char *line, void *data)
597     {
598     #ifdef WITH_DEBUG_SOUND
599     fprintf(stderr, "SNDDBG: %s\n", line);
600     #endif
601     return True;
602     }
603    
604 stargo 1274 static void
605 ossman_ 1359 rdpsnddbg_process(STREAM s)
606     {
607     unsigned int pkglen;
608     static char *rest = NULL;
609     char *buf;
610    
611     pkglen = s->end - s->p;
612     /* str_handle_lines requires null terminated strings */
613     buf = xmalloc(pkglen + 1);
614     STRNCPY(buf, (char *) s->p, pkglen + 1);
615    
616     str_handle_lines(buf, &rest, rdpsnddbg_line_handler, NULL);
617    
618     xfree(buf);
619     }
620    
621     static void
622 stargo 1255 rdpsnd_register_drivers(char *options)
623     {
624     struct audio_driver **reg;
625    
626     /* The order of registrations define the probe-order
627     when opening the device for the first time */
628     reg = &drivers;
629     #if defined(RDPSND_ALSA)
630     *reg = alsa_register(options);
631 ossman_ 1298 assert(*reg);
632 stargo 1255 reg = &((*reg)->next);
633     #endif
634 stargo 1264 #if defined(RDPSND_SUN)
635     *reg = sun_register(options);
636 ossman_ 1298 assert(*reg);
637 stargo 1264 reg = &((*reg)->next);
638     #endif
639 stargo 1255 #if defined(RDPSND_OSS)
640     *reg = oss_register(options);
641 ossman_ 1298 assert(*reg);
642 stargo 1255 reg = &((*reg)->next);
643     #endif
644     #if defined(RDPSND_SGI)
645     *reg = sgi_register(options);
646 ossman_ 1298 assert(*reg);
647 stargo 1255 reg = &((*reg)->next);
648     #endif
649     #if defined(RDPSND_LIBAO)
650     *reg = libao_register(options);
651 ossman_ 1302 assert(*reg);
652 stargo 1255 reg = &((*reg)->next);
653     #endif
654 stargo 1332 *reg = NULL;
655 stargo 1255 }
656    
657     BOOL
658 stargo 1272 rdpsnd_init(char *optarg)
659 stargo 1255 {
660     struct audio_driver *pos;
661 stargo 1272 char *driver = NULL, *options = NULL;
662 stargo 1255
663     drivers = NULL;
664 stargo 1272
665 ossman_ 1342 packet.data = xmalloc(65536);
666     packet.p = packet.end = packet.data;
667     packet.size = 0;
668    
669 stargo 1272 rdpsnd_channel =
670     channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
671     rdpsnd_process);
672    
673 ossman_ 1359 rdpsnddbg_channel =
674     channel_register("snddbg", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
675     rdpsnddbg_process);
676    
677     if ((rdpsnd_channel == NULL) || (rdpsnddbg_channel == NULL))
678 stargo 1272 {
679     error("channel_register\n");
680     return False;
681     }
682    
683 ossman_ 1302 rdpsnd_queue_init();
684    
685 stargo 1272 if (optarg != NULL && strlen(optarg) > 0)
686     {
687     driver = options = optarg;
688    
689     while (*options != '\0' && *options != ':')
690     options++;
691    
692     if (*options == ':')
693     {
694     *options = '\0';
695     options++;
696     }
697    
698     if (*options == '\0')
699     options = NULL;
700     }
701    
702 stargo 1255 rdpsnd_register_drivers(options);
703    
704     if (!driver)
705     return True;
706    
707     pos = drivers;
708     while (pos != NULL)
709     {
710     if (!strcmp(pos->name, driver))
711     {
712     DEBUG(("selected %s\n", pos->name));
713     current_driver = pos;
714     return True;
715     }
716     pos = pos->next;
717     }
718     return False;
719     }
720    
721     void
722     rdpsnd_show_help(void)
723     {
724     struct audio_driver *pos;
725    
726     rdpsnd_register_drivers(NULL);
727    
728     pos = drivers;
729     while (pos != NULL)
730     {
731     fprintf(stderr, " %s:\t%s\n", pos->name, pos->description);
732     pos = pos->next;
733     }
734     }
735    
736 stargo 1273 void
737 ossman_ 1302 rdpsnd_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
738     {
739     long next_pending;
740    
741 ossman_ 1359 if (device_open || rec_device_open)
742 ossman_ 1346 current_driver->add_fds(n, rfds, wfds, tv);
743 ossman_ 1302
744     next_pending = rdpsnd_queue_next_completion();
745     if (next_pending >= 0)
746     {
747     long cur_timeout;
748    
749     cur_timeout = tv->tv_sec * 1000000 + tv->tv_usec;
750     if (cur_timeout > next_pending)
751     {
752     tv->tv_sec = next_pending / 1000000;
753     tv->tv_usec = next_pending % 1000000;
754     }
755     }
756     }
757    
758     void
759     rdpsnd_check_fds(fd_set * rfds, fd_set * wfds)
760     {
761     rdpsnd_queue_complete_pending();
762    
763 ossman_ 1359 if (device_open || rec_device_open)
764 ossman_ 1346 current_driver->check_fds(rfds, wfds);
765 ossman_ 1302 }
766    
767     static void
768 stargo 1254 rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)
769     {
770     struct audio_packet *packet = &packet_queue[queue_hi];
771     unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
772    
773 ossman_ 1302 if (next_hi == queue_pending)
774 stargo 1254 {
775     error("No space to queue audio packet\n");
776     return;
777     }
778    
779     queue_hi = next_hi;
780    
781     packet->s = *s;
782     packet->tick = tick;
783     packet->index = index;
784    
785 ossman_ 1302 gettimeofday(&packet->arrive_tv, NULL);
786 stargo 1254 }
787    
788 ossman_ 1299 struct audio_packet *
789 stargo 1254 rdpsnd_queue_current_packet(void)
790     {
791     return &packet_queue[queue_lo];
792     }
793    
794 ossman_ 1299 BOOL
795 stargo 1254 rdpsnd_queue_empty(void)
796     {
797     return (queue_lo == queue_hi);
798     }
799    
800 ossman_ 1302 static void
801 stargo 1254 rdpsnd_queue_init(void)
802     {
803 ossman_ 1302 queue_pending = queue_lo = queue_hi = 0;
804 stargo 1254 }
805    
806 ossman_ 1299 void
807 ossman_ 1302 rdpsnd_queue_next(unsigned long completed_in_us)
808 stargo 1254 {
809 ossman_ 1302 struct audio_packet *packet;
810    
811     assert(!rdpsnd_queue_empty());
812    
813     packet = &packet_queue[queue_lo];
814    
815     gettimeofday(&packet->completion_tv, NULL);
816    
817     packet->completion_tv.tv_usec += completed_in_us;
818     packet->completion_tv.tv_sec += packet->completion_tv.tv_usec / 1000000;
819     packet->completion_tv.tv_usec %= 1000000;
820    
821 stargo 1254 queue_lo = (queue_lo + 1) % MAX_QUEUE;
822 ossman_ 1302
823     rdpsnd_queue_complete_pending();
824 stargo 1254 }
825    
826 ossman_ 1299 int
827 stargo 1254 rdpsnd_queue_next_tick(void)
828     {
829     if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
830     {
831     return packet_queue[(queue_lo + 1) % MAX_QUEUE].tick;
832     }
833     else
834     {
835     return (packet_queue[queue_lo].tick + 65535) % 65536;
836     }
837     }
838 ossman_ 1302
839     static void
840     rdpsnd_queue_complete_pending(void)
841     {
842     struct timeval now;
843     long elapsed;
844     struct audio_packet *packet;
845    
846     gettimeofday(&now, NULL);
847    
848     while (queue_pending != queue_lo)
849     {
850     packet = &packet_queue[queue_pending];
851    
852     if (now.tv_sec < packet->completion_tv.tv_sec)
853     break;
854    
855     if ((now.tv_sec == packet->completion_tv.tv_sec) &&
856     (now.tv_usec < packet->completion_tv.tv_usec))
857     break;
858    
859     elapsed = (packet->completion_tv.tv_sec - packet->arrive_tv.tv_sec) * 1000000 +
860     (packet->completion_tv.tv_usec - packet->arrive_tv.tv_usec);
861 ossman_ 1337 elapsed /= 1000;
862 ossman_ 1302
863     xfree(packet->s.data);
864     rdpsnd_send_completion((packet->tick + elapsed) % 65536, packet->index);
865     queue_pending = (queue_pending + 1) % MAX_QUEUE;
866     }
867     }
868    
869     static long
870     rdpsnd_queue_next_completion(void)
871     {
872     struct audio_packet *packet;
873     long remaining;
874     struct timeval now;
875    
876     if (queue_pending == queue_lo)
877     return -1;
878    
879     gettimeofday(&now, NULL);
880    
881     packet = &packet_queue[queue_pending];
882    
883     remaining = (packet->completion_tv.tv_sec - now.tv_sec) * 1000000 +
884     (packet->completion_tv.tv_usec - now.tv_usec);
885    
886     if (remaining < 0)
887     return 0;
888    
889     return remaining;
890     }

  ViewVC Help
Powered by ViewVC 1.1.26