/[rdesktop]/jpeg/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

Diff of /jpeg/rdesktop/trunk/rdpsnd.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.963  
changed lines
  Added in v.1475

  ViewVC Help
Powered by ViewVC 1.1.26