/[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 1427 - (hide annotations)
Fri Jan 18 15:11:57 2008 UTC (16 years, 4 months ago) by ossman_
Original Path: sourceforge.net/trunk/rdesktop/rdpsnd.c
File MIME type: text/plain
File size: 20619 byte(s)
Check that the sound backend supports wave_in_format_supported before
calling it.

1 astrand 963 /* -*- c-basic-offset: 8 -*-
2 matthewc 474 rdesktop: A Remote Desktop Protocol client.
3     Sound Channel Process Functions
4 jsorg71 1365 Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
5     Copyright (C) Matthew Chapman 2003-2007
6 matthewc 474 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 jsorg71 1372 static RD_BOOL device_open;
54     static RD_BOOL rec_device_open;
55 ossman_ 1359
56 jsorg71 1364 static RD_WAVEFORMATEX formats[MAX_FORMATS];
57 matthewc 474 static unsigned int format_count;
58     static unsigned int current_format;
59 ossman_ 1359
60 jsorg71 1364 static RD_WAVEFORMATEX rec_formats[MAX_FORMATS];
61 ossman_ 1359 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 jsorg71 1382 static uint32 record_buffer_size;
68 ossman_ 1359
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 jsorg71 1382 uint32 remain;
157 ossman_ 1359
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 jsorg71 1372 static RD_BOOL
182 ossman_ 1346 rdpsnd_auto_select(void)
183     {
184 jsorg71 1372 static RD_BOOL failed = False;
185 ossman_ 1346
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 jsorg71 1364 RD_WAVEFORMATEX *format;
216 matthewc 474 STREAM out;
217 jsorg71 1372 RD_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 ossman_ 1411 if (current_driver && 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 jsorg71 1364 RD_WAVEFORMATEX *format;
330 ossman_ 1359 STREAM out;
331 jsorg71 1372 RD_BOOL device_available = False;
332 ossman_ 1359 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 ossman_ 1427 if (current_driver && current_driver->wave_in_format_supported
380     && current_driver->wave_in_format_supported(format))
381 ossman_ 1359 {
382     rec_format_count++;
383     if (rec_format_count == MAX_FORMATS)
384     break;
385     }
386     }
387     }
388    
389     out = rdpsnd_init_packet(RDPSND_REC_NEGOTIATE, 12 + 18 * rec_format_count);
390     out_uint32_le(out, 0x00000000); /* flags */
391     out_uint32_le(out, 0xffffffff); /* volume */
392     out_uint16_le(out, rec_format_count);
393     out_uint16_le(out, 1); /* version */
394    
395     for (i = 0; i < rec_format_count; i++)
396     {
397     format = &rec_formats[i];
398     out_uint16_le(out, format->wFormatTag);
399     out_uint16_le(out, format->nChannels);
400     out_uint32_le(out, format->nSamplesPerSec);
401     out_uint32_le(out, format->nAvgBytesPerSec);
402     out_uint16_le(out, format->nBlockAlign);
403     out_uint16_le(out, format->wBitsPerSample);
404     out_uint16(out, 0); /* cbSize */
405     }
406    
407     s_mark_end(out);
408    
409     DEBUG_SOUND(("RDPSND: -> RDPSND_REC_NEGOTIATE(formats: %d)\n", (int) rec_format_count));
410    
411     rdpsnd_send(out);
412     }
413    
414     static void
415 ossman_ 1342 rdpsnd_process_packet(uint8 opcode, STREAM s)
416 matthewc 432 {
417 ossman_ 1341 uint16 vol_left, vol_right;
418 matthewc 474 static uint16 tick, format;
419     static uint8 packet_index;
420    
421 ossman_ 1342 switch (opcode)
422 matthewc 474 {
423 ossman_ 1342 case RDPSND_WRITE:
424     in_uint16_le(s, tick);
425     in_uint16_le(s, format);
426     in_uint8(s, packet_index);
427     in_uint8s(s, 3);
428 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));
429 matthewc 474
430 ossman_ 1342 if (format >= MAX_FORMATS)
431 matthewc 474 {
432 ossman_ 1342 error("RDPSND: Invalid format index\n");
433     break;
434 matthewc 474 }
435 ossman_ 1342
436     if (!device_open || (format != current_format))
437 matthewc 474 {
438 ossman_ 1346 /*
439     * If we haven't selected a device by now, then either
440     * we've failed to find a working device, or the server
441     * is sending bogus RDPSND_WRITE.
442     */
443     if (!current_driver)
444     {
445     rdpsnd_send_completion(tick, packet_index);
446     break;
447     }
448 ossman_ 1342 if (!device_open && !current_driver->wave_out_open())
449     {
450     rdpsnd_send_completion(tick, packet_index);
451     break;
452     }
453     if (!current_driver->wave_out_set_format(&formats[format]))
454     {
455     rdpsnd_send_completion(tick, packet_index);
456     current_driver->wave_out_close();
457     device_open = False;
458     break;
459     }
460     device_open = True;
461     current_format = format;
462 matthewc 474 }
463    
464 ossman_ 1342 rdpsnd_queue_write(rdpsnd_dsp_process
465     (s->p, s->end - s->p, current_driver,
466     &formats[current_format]), tick, packet_index);
467     return;
468 astrand 499 break;
469     case RDPSND_CLOSE:
470 ossman_ 1343 DEBUG_SOUND(("RDPSND: RDPSND_CLOSE()\n"));
471 ossman_ 1346 if (device_open)
472     current_driver->wave_out_close();
473 astrand 499 device_open = False;
474     break;
475     case RDPSND_NEGOTIATE:
476     rdpsnd_process_negotiate(s);
477     break;
478 ossman_ 1339 case RDPSND_PING:
479     rdpsnd_process_ping(s);
480 astrand 499 break;
481     case RDPSND_SET_VOLUME:
482 ossman_ 1341 in_uint16_le(s, vol_left);
483     in_uint16_le(s, vol_right);
484 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));
485 astrand 499 if (device_open)
486 ossman_ 1341 current_driver->wave_out_volume(vol_left, vol_right);
487 astrand 499 break;
488 ossman_ 1359 case RDPSND_REC_NEGOTIATE:
489     rdpsnd_process_rec_negotiate(s);
490     break;
491     case RDPSND_REC_START:
492     in_uint16_le(s, format);
493     DEBUG_SOUND(("RDPSND: RDPSND_REC_START(format: %u)\n", (unsigned) format));
494    
495     if (format >= MAX_FORMATS)
496     {
497     error("RDPSND: Invalid format index\n");
498     break;
499     }
500    
501     if (rec_device_open)
502     {
503     error("RDPSND: Multiple RDPSND_REC_START\n");
504     break;
505     }
506    
507     if (!current_driver->wave_in_open())
508     break;
509    
510     if (!current_driver->wave_in_set_format(&rec_formats[format]))
511     {
512     error("RDPSND: Device not accepting format\n");
513     current_driver->wave_in_close();
514     break;
515     }
516     rec_device_open = True;
517     break;
518     case RDPSND_REC_STOP:
519     DEBUG_SOUND(("RDPSND: RDPSND_REC_STOP()\n"));
520     rdpsnd_flush_record();
521     if (rec_device_open)
522     current_driver->wave_in_close();
523     rec_device_open = False;
524     break;
525     case RDPSND_REC_SET_VOLUME:
526     in_uint16_le(s, vol_left);
527     in_uint16_le(s, vol_right);
528     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));
529     if (rec_device_open)
530     current_driver->wave_in_volume(vol_left, vol_right);
531     break;
532 astrand 499 default:
533 ossman_ 1342 unimpl("RDPSND packet type %x\n", opcode);
534 astrand 499 break;
535 matthewc 474 }
536 matthewc 432 }
537    
538 ossman_ 1342 static void
539     rdpsnd_process(STREAM s)
540     {
541     uint16 len;
542    
543     while (!s_check_end(s))
544     {
545     /* New packet */
546     if (packet.size == 0)
547     {
548     if ((s->end - s->p) < 4)
549     {
550     error("RDPSND: Split at packet header. Things will go south from here...\n");
551     return;
552     }
553     in_uint8(s, packet_opcode);
554     in_uint8s(s, 1); /* Padding */
555     in_uint16_le(s, len);
556    
557 ossman_ 1343 DEBUG_SOUND(("RDPSND: == Opcode %x Length: %d ==\n",
558     (int) packet_opcode, (int) len));
559    
560 ossman_ 1342 packet.p = packet.data;
561     packet.end = packet.data + len;
562     packet.size = len;
563     }
564     else
565     {
566     len = MIN(s->end - s->p, packet.end - packet.p);
567    
568     /* Microsoft's server is so broken it's not even funny... */
569     if (packet_opcode == RDPSND_WRITE)
570     {
571     if ((packet.p - packet.data) < 12)
572     len = MIN(len, 12 - (packet.p - packet.data));
573     else if ((packet.p - packet.data) == 12)
574     {
575 ossman_ 1343 DEBUG_SOUND(("RDPSND: Eating 4 bytes of %d bytes...\n",
576     len));
577 ossman_ 1342 in_uint8s(s, 4);
578     len -= 4;
579     }
580     }
581    
582     in_uint8a(s, packet.p, len);
583     packet.p += len;
584     }
585    
586     /* Packet fully assembled */
587     if (packet.p == packet.end)
588     {
589     packet.p = packet.data;
590     rdpsnd_process_packet(packet_opcode, &packet);
591     packet.size = 0;
592     }
593     }
594     }
595    
596 jsorg71 1372 static RD_BOOL
597 ossman_ 1359 rdpsnddbg_line_handler(const char *line, void *data)
598     {
599     #ifdef WITH_DEBUG_SOUND
600     fprintf(stderr, "SNDDBG: %s\n", line);
601     #endif
602     return True;
603     }
604    
605 stargo 1274 static void
606 ossman_ 1359 rdpsnddbg_process(STREAM s)
607     {
608     unsigned int pkglen;
609     static char *rest = NULL;
610     char *buf;
611    
612     pkglen = s->end - s->p;
613     /* str_handle_lines requires null terminated strings */
614 jsorg71 1382 buf = (char *) xmalloc(pkglen + 1);
615 ossman_ 1359 STRNCPY(buf, (char *) s->p, pkglen + 1);
616    
617     str_handle_lines(buf, &rest, rdpsnddbg_line_handler, NULL);
618    
619     xfree(buf);
620     }
621    
622     static void
623 stargo 1255 rdpsnd_register_drivers(char *options)
624     {
625     struct audio_driver **reg;
626    
627     /* The order of registrations define the probe-order
628     when opening the device for the first time */
629     reg = &drivers;
630     #if defined(RDPSND_ALSA)
631     *reg = alsa_register(options);
632 ossman_ 1298 assert(*reg);
633 stargo 1255 reg = &((*reg)->next);
634     #endif
635 stargo 1264 #if defined(RDPSND_SUN)
636     *reg = sun_register(options);
637 ossman_ 1298 assert(*reg);
638 stargo 1264 reg = &((*reg)->next);
639     #endif
640 stargo 1255 #if defined(RDPSND_OSS)
641     *reg = oss_register(options);
642 ossman_ 1298 assert(*reg);
643 stargo 1255 reg = &((*reg)->next);
644     #endif
645     #if defined(RDPSND_SGI)
646     *reg = sgi_register(options);
647 ossman_ 1298 assert(*reg);
648 stargo 1255 reg = &((*reg)->next);
649     #endif
650     #if defined(RDPSND_LIBAO)
651     *reg = libao_register(options);
652 ossman_ 1302 assert(*reg);
653 stargo 1255 reg = &((*reg)->next);
654     #endif
655 stargo 1332 *reg = NULL;
656 stargo 1255 }
657    
658 jsorg71 1372 RD_BOOL
659 stargo 1272 rdpsnd_init(char *optarg)
660 stargo 1255 {
661     struct audio_driver *pos;
662 stargo 1272 char *driver = NULL, *options = NULL;
663 stargo 1255
664     drivers = NULL;
665 stargo 1272
666 jsorg71 1382 packet.data = (uint8 *) xmalloc(65536);
667 ossman_ 1342 packet.p = packet.end = packet.data;
668     packet.size = 0;
669    
670 stargo 1272 rdpsnd_channel =
671     channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
672     rdpsnd_process);
673    
674 ossman_ 1359 rdpsnddbg_channel =
675     channel_register("snddbg", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
676     rdpsnddbg_process);
677    
678     if ((rdpsnd_channel == NULL) || (rdpsnddbg_channel == NULL))
679 stargo 1272 {
680     error("channel_register\n");
681     return False;
682     }
683    
684 ossman_ 1302 rdpsnd_queue_init();
685    
686 stargo 1272 if (optarg != NULL && strlen(optarg) > 0)
687     {
688     driver = options = optarg;
689    
690     while (*options != '\0' && *options != ':')
691     options++;
692    
693     if (*options == ':')
694     {
695     *options = '\0';
696     options++;
697     }
698    
699     if (*options == '\0')
700     options = NULL;
701     }
702    
703 stargo 1255 rdpsnd_register_drivers(options);
704    
705     if (!driver)
706     return True;
707    
708     pos = drivers;
709     while (pos != NULL)
710     {
711     if (!strcmp(pos->name, driver))
712     {
713     DEBUG(("selected %s\n", pos->name));
714     current_driver = pos;
715     return True;
716     }
717     pos = pos->next;
718     }
719     return False;
720     }
721    
722     void
723     rdpsnd_show_help(void)
724     {
725     struct audio_driver *pos;
726    
727     rdpsnd_register_drivers(NULL);
728    
729     pos = drivers;
730     while (pos != NULL)
731     {
732     fprintf(stderr, " %s:\t%s\n", pos->name, pos->description);
733     pos = pos->next;
734     }
735     }
736    
737 stargo 1273 void
738 ossman_ 1302 rdpsnd_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
739     {
740     long next_pending;
741    
742 ossman_ 1359 if (device_open || rec_device_open)
743 ossman_ 1346 current_driver->add_fds(n, rfds, wfds, tv);
744 ossman_ 1302
745     next_pending = rdpsnd_queue_next_completion();
746     if (next_pending >= 0)
747     {
748     long cur_timeout;
749    
750     cur_timeout = tv->tv_sec * 1000000 + tv->tv_usec;
751     if (cur_timeout > next_pending)
752     {
753     tv->tv_sec = next_pending / 1000000;
754     tv->tv_usec = next_pending % 1000000;
755     }
756     }
757     }
758    
759     void
760     rdpsnd_check_fds(fd_set * rfds, fd_set * wfds)
761     {
762     rdpsnd_queue_complete_pending();
763    
764 ossman_ 1359 if (device_open || rec_device_open)
765 ossman_ 1346 current_driver->check_fds(rfds, wfds);
766 ossman_ 1302 }
767    
768     static void
769 stargo 1254 rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)
770     {
771     struct audio_packet *packet = &packet_queue[queue_hi];
772     unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
773    
774 ossman_ 1302 if (next_hi == queue_pending)
775 stargo 1254 {
776     error("No space to queue audio packet\n");
777     return;
778     }
779    
780     queue_hi = next_hi;
781    
782     packet->s = *s;
783     packet->tick = tick;
784     packet->index = index;
785    
786 ossman_ 1302 gettimeofday(&packet->arrive_tv, NULL);
787 stargo 1254 }
788    
789 ossman_ 1299 struct audio_packet *
790 stargo 1254 rdpsnd_queue_current_packet(void)
791     {
792     return &packet_queue[queue_lo];
793     }
794    
795 jsorg71 1372 RD_BOOL
796 stargo 1254 rdpsnd_queue_empty(void)
797     {
798     return (queue_lo == queue_hi);
799     }
800    
801 ossman_ 1302 static void
802 stargo 1254 rdpsnd_queue_init(void)
803     {
804 ossman_ 1302 queue_pending = queue_lo = queue_hi = 0;
805 stargo 1254 }
806    
807 ossman_ 1299 void
808 ossman_ 1302 rdpsnd_queue_next(unsigned long completed_in_us)
809 stargo 1254 {
810 ossman_ 1302 struct audio_packet *packet;
811    
812     assert(!rdpsnd_queue_empty());
813    
814     packet = &packet_queue[queue_lo];
815    
816     gettimeofday(&packet->completion_tv, NULL);
817    
818     packet->completion_tv.tv_usec += completed_in_us;
819     packet->completion_tv.tv_sec += packet->completion_tv.tv_usec / 1000000;
820     packet->completion_tv.tv_usec %= 1000000;
821    
822 stargo 1254 queue_lo = (queue_lo + 1) % MAX_QUEUE;
823 ossman_ 1302
824     rdpsnd_queue_complete_pending();
825 stargo 1254 }
826    
827 ossman_ 1299 int
828 stargo 1254 rdpsnd_queue_next_tick(void)
829     {
830     if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
831     {
832     return packet_queue[(queue_lo + 1) % MAX_QUEUE].tick;
833     }
834     else
835     {
836     return (packet_queue[queue_lo].tick + 65535) % 65536;
837     }
838     }
839 ossman_ 1302
840     static void
841     rdpsnd_queue_complete_pending(void)
842     {
843     struct timeval now;
844     long elapsed;
845     struct audio_packet *packet;
846    
847     gettimeofday(&now, NULL);
848    
849     while (queue_pending != queue_lo)
850     {
851     packet = &packet_queue[queue_pending];
852    
853     if (now.tv_sec < packet->completion_tv.tv_sec)
854     break;
855    
856     if ((now.tv_sec == packet->completion_tv.tv_sec) &&
857     (now.tv_usec < packet->completion_tv.tv_usec))
858     break;
859    
860     elapsed = (packet->completion_tv.tv_sec - packet->arrive_tv.tv_sec) * 1000000 +
861     (packet->completion_tv.tv_usec - packet->arrive_tv.tv_usec);
862 ossman_ 1337 elapsed /= 1000;
863 ossman_ 1302
864     xfree(packet->s.data);
865     rdpsnd_send_completion((packet->tick + elapsed) % 65536, packet->index);
866     queue_pending = (queue_pending + 1) % MAX_QUEUE;
867     }
868     }
869    
870     static long
871     rdpsnd_queue_next_completion(void)
872     {
873     struct audio_packet *packet;
874     long remaining;
875     struct timeval now;
876    
877     if (queue_pending == queue_lo)
878     return -1;
879    
880     gettimeofday(&now, NULL);
881    
882     packet = &packet_queue[queue_pending];
883    
884     remaining = (packet->completion_tv.tv_sec - now.tv_sec) * 1000000 +
885     (packet->completion_tv.tv_usec - now.tv_usec);
886    
887     if (remaining < 0)
888     return 0;
889    
890     return remaining;
891     }

  ViewVC Help
Powered by ViewVC 1.1.26