/[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 1411 - (hide annotations)
Mon Jun 18 08:31:27 2007 UTC (16 years, 11 months ago) by ossman_
Original Path: sourceforge.net/trunk/rdesktop/rdpsnd.c
File MIME type: text/plain
File size: 20568 byte(s)
None of the drivers requires it to be open to determine supported formats,
so let's not require it. This allows the device to be busy when rdesktop starts
but can be used later when it becomes free.

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_ 1411 if (current_driver && current_driver->wave_in_format_supported(format))
380 ossman_ 1359 {
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 jsorg71 1372 static RD_BOOL
596 ossman_ 1359 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 jsorg71 1382 buf = (char *) xmalloc(pkglen + 1);
614 ossman_ 1359 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 jsorg71 1372 RD_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 jsorg71 1382 packet.data = (uint8 *) xmalloc(65536);
666 ossman_ 1342 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 jsorg71 1372 RD_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