/[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

Diff of /sourceforge.net/rdesktop/trunk/rdpsnd.c

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

revision 1265 by stargo, Sun Sep 17 20:06:37 2006 UTC revision 1359 by ossman_, Tue Jan 2 16:30:06 2007 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 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
5     Copyright (C) Matthew Chapman 2003     Copyright (C) Matthew Chapman 2003
6     Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003     Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003
7    
# 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"  #include "rdpsnd.h"
27  #include "rdpsnd_dsp.h"  #include "rdpsnd_dsp.h"
# Line 28  Line 31 
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_SERVERTICK       6  #define RDPSND_PING                     6
35  #define RDPSND_NEGOTIATE        7  #define RDPSND_NEGOTIATE        7
36    
37  #define MAX_FORMATS             10  #define RDPSND_REC_NEGOTIATE    39
38  #define MAX_QUEUE               10  #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  BOOL g_dsp_busy = False;  #define RDPSND_FLAG_RECORD              0x00800000
44  int g_dsp_fd;  
45    #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;  static struct audio_driver *drivers = NULL;
51  struct audio_driver *current_driver = NULL;  struct audio_driver *current_driver = NULL;
52    
53  static BOOL device_open;  static BOOL device_open;
54    static BOOL rec_device_open;
55    
56  static WAVEFORMATEX formats[MAX_FORMATS];  static 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  unsigned int queue_hi, queue_lo;  
60    static WAVEFORMATEX rec_formats[MAX_FORMATS];
61    static unsigned int rec_format_count;
62    
63    unsigned int queue_hi, queue_lo, queue_pending;
64  struct audio_packet packet_queue[MAX_QUEUE];  struct audio_packet packet_queue[MAX_QUEUE];
65    
66    static char record_buffer[8192];
67    static int record_buffer_size;
68    
69    static uint8 packet_opcode;
70    static struct stream packet;
71    
72  void (*wave_out_play) (void);  void (*wave_out_play) (void);
73    
74    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  static STREAM  static STREAM
80  rdpsnd_init_packet(uint16 type, uint16 size)  rdpsnd_init_packet(uint16 type, uint16 size)
81  {  {
# Line 64  rdpsnd_init_packet(uint16 type, uint16 s Line 90  rdpsnd_init_packet(uint16 type, uint16 s
90  static void  static void
91  rdpsnd_send(STREAM s)  rdpsnd_send(STREAM s)
92  {  {
 #ifdef RDPSND_DEBUG  
         printf("RDPSND send:\n");  
         hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);  
 #endif  
   
93          channel_send(s, rdpsnd_channel);          channel_send(s, rdpsnd_channel);
94  }  }
95    
96  void  static void
97  rdpsnd_send_completion(uint16 tick, uint8 packet_index)  rdpsnd_send_completion(uint16 tick, uint8 packet_index)
98  {  {
99          STREAM s;          STREAM s;
# Line 83  rdpsnd_send_completion(uint16 tick, uint Line 104  rdpsnd_send_completion(uint16 tick, uint
104          out_uint8(s, 0);          out_uint8(s, 0);
105          s_mark_end(s);          s_mark_end(s);
106          rdpsnd_send(s);          rdpsnd_send(s);
107    
108            DEBUG_SOUND(("RDPSND: -> RDPSND_COMPLETION(tick: %u, index: %u)\n",
109                         (unsigned) tick, (unsigned) packet_index));
110    }
111    
112    static void
113    rdpsnd_flush_record(void)
114    {
115            STREAM s;
116            unsigned int chunk_size;
117            char *data;
118    
119            if (record_buffer_size == 0)
120                    return;
121    
122            assert(record_buffer_size <= sizeof(record_buffer));
123    
124            data = record_buffer;
125    
126            /*
127             * Microsoft's RDP server keeps dropping chunks, so we need to
128             * transmit everything inside one channel fragment or we risk
129             * making the rdpsnd server go out of sync with the byte stream.
130             */
131            while (record_buffer_size)
132            {
133                    if (record_buffer_size < 1596)
134                            chunk_size = record_buffer_size;
135                    else
136                            chunk_size = 1596;
137    
138                    s = rdpsnd_init_packet(RDPSND_REC_DATA, chunk_size);
139                    out_uint8p(s, data, chunk_size);
140    
141                    s_mark_end(s);
142                    rdpsnd_send(s);
143    
144                    data = data + chunk_size;
145                    record_buffer_size -= chunk_size;
146    
147                    DEBUG_SOUND(("RDPSND: -> RDPSND_REC_DATA(length: %u)\n", (unsigned) chunk_size));
148            }
149    
150            record_buffer_size = 0;
151    }
152    
153    void
154    rdpsnd_record(const void *data, unsigned int size)
155    {
156            int remain;
157    
158            assert(rec_device_open);
159    
160            while (size)
161            {
162                    remain = sizeof(record_buffer) - record_buffer_size;
163    
164                    if (size >= remain)
165                    {
166                            memcpy(record_buffer + record_buffer_size, data, remain);
167                            record_buffer_size += remain;
168                            rdpsnd_flush_record();
169                            data = (const char *) data + remain;
170                            size -= remain;
171                    }
172                    else
173                    {
174                            memcpy(record_buffer + record_buffer_size, data, size);
175                            record_buffer_size += size;
176                            size = 0;
177                    }
178            }
179    }
180    
181    static BOOL
182    rdpsnd_auto_select(void)
183    {
184            static BOOL failed = False;
185    
186            if (!failed)
187            {
188                    current_driver = drivers;
189                    while (current_driver != NULL)
190                    {
191                            DEBUG(("trying %s...\n", current_driver->name));
192                            if (current_driver->wave_out_open())
193                            {
194                                    DEBUG(("selected %s\n", current_driver->name));
195                                    current_driver->wave_out_close();
196                                    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  static void  static void
210  rdpsnd_process_negotiate(STREAM in)  rdpsnd_process_negotiate(STREAM in)
211  {  {
212          unsigned int in_format_count, i;          uint16 in_format_count, i;
213            uint8 pad;
214            uint16 version;
215          WAVEFORMATEX *format;          WAVEFORMATEX *format;
216          STREAM out;          STREAM out;
217          BOOL device_available = False;          BOOL device_available = False;
218          int readcnt;          int readcnt;
219          int discardcnt;          int discardcnt;
220    
221          in_uint8s(in, 14);      /* flags, volume, pitch, UDP port */          in_uint8s(in, 14);      /* initial bytes not valid from server */
222          in_uint16_le(in, in_format_count);          in_uint16_le(in, in_format_count);
223          in_uint8s(in, 4);       /* pad, status, pad */          in_uint8(in, pad);
224            in_uint16_le(in, version);
225            in_uint8s(in, 1);       /* padding */
226    
227            DEBUG_SOUND(("RDPSND: RDPSND_NEGOTIATE(formats: %d, pad: 0x%02x, version: %x)\n",
228                         (int) in_format_count, (unsigned) pad, (unsigned) version));
229    
230          if (current_driver->wave_out_open())          if (!current_driver)
231                    device_available = rdpsnd_auto_select();
232    
233            if (current_driver && !device_available && current_driver->wave_out_open())
234          {          {
235                  current_driver->wave_out_close();                  current_driver->wave_out_close();
236                  device_available = True;                  device_available = True;
# Line 142  rdpsnd_process_negotiate(STREAM in) Line 273  rdpsnd_process_negotiate(STREAM in)
273          }          }
274    
275          out = rdpsnd_init_packet(RDPSND_NEGOTIATE | 0x200, 20 + 18 * format_count);          out = rdpsnd_init_packet(RDPSND_NEGOTIATE | 0x200, 20 + 18 * format_count);
276          out_uint32_le(out, 3);  /* flags */          out_uint32_le(out, 0x00800003); /* flags */
277          out_uint32(out, 0xffffffff);    /* volume */          out_uint32(out, 0xffffffff);    /* volume */
278          out_uint32(out, 0);     /* pitch */          out_uint32(out, 0);     /* pitch */
279          out_uint16(out, 0);     /* UDP port */          out_uint16(out, 0);     /* UDP port */
280    
281          out_uint16_le(out, format_count);          out_uint16_le(out, format_count);
282          out_uint8(out, 0x95);   /* pad? */          out_uint8(out, 0);      /* padding */
283          out_uint16_le(out, 2);  /* status */          out_uint16_le(out, 2);  /* version */
284          out_uint8(out, 0x77);   /* pad? */          out_uint8(out, 0);      /* padding */
285    
286          for (i = 0; i < format_count; i++)          for (i = 0; i < format_count; i++)
287          {          {
# Line 165  rdpsnd_process_negotiate(STREAM in) Line 296  rdpsnd_process_negotiate(STREAM in)
296          }          }
297    
298          s_mark_end(out);          s_mark_end(out);
299    
300            DEBUG_SOUND(("RDPSND: -> RDPSND_NEGOTIATE(formats: %d)\n", (int) format_count));
301    
302          rdpsnd_send(out);          rdpsnd_send(out);
303  }  }
304    
305  static void  static void
306  rdpsnd_process_servertick(STREAM in)  rdpsnd_process_ping(STREAM in)
307  {  {
308          uint16 tick1, tick2;          uint16 tick;
309          STREAM out;          STREAM out;
310    
311          /* in_uint8s(in, 4); unknown */          in_uint16_le(in, tick);
312          in_uint16_le(in, tick1);  
313          in_uint16_le(in, tick2);          DEBUG_SOUND(("RDPSND: RDPSND_PING(tick: 0x%04x)\n", (unsigned) tick));
314    
315          out = rdpsnd_init_packet(RDPSND_SERVERTICK | 0x2300, 4);          out = rdpsnd_init_packet(RDPSND_PING | 0x2300, 4);
316          out_uint16_le(out, tick1);          out_uint16_le(out, tick);
317          out_uint16_le(out, tick2);          out_uint16_le(out, 0);
318          s_mark_end(out);          s_mark_end(out);
319          rdpsnd_send(out);          rdpsnd_send(out);
320    
321            DEBUG_SOUND(("RDPSND: -> (tick: 0x%04x)\n", (unsigned) tick));
322  }  }
323    
324  static void  static void
325  rdpsnd_process(STREAM s)  rdpsnd_process_rec_negotiate(STREAM in)
326  {  {
327          uint8 type;          uint16 in_format_count, i;
328          uint16 datalen;          uint16 version;
329          uint32 volume;          WAVEFORMATEX *format;
330          static uint16 tick, format;          STREAM out;
331          static uint8 packet_index;          BOOL device_available = False;
332          static BOOL awaiting_data_packet;          int readcnt;
333          static unsigned char missing_bytes[4] = { 0, 0, 0, 0 };          int discardcnt;
334    
335  #ifdef RDPSND_DEBUG          in_uint8s(in, 8);       /* initial bytes not valid from server */
336          printf("RDPSND recv:\n");          in_uint16_le(in, in_format_count);
337          hexdump(s->p, s->end - s->p);          in_uint16_le(in, version);
 #endif  
338    
339          if (awaiting_data_packet)          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                  if (format >= MAX_FORMATS)                  current_driver->wave_in_close();
349                  {                  device_available = True;
350                          error("RDPSND: Invalid format index\n");          }
                         return;  
                 }  
351    
352                  if (!device_open || (format != current_format))          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                          if (!device_open && !current_driver->wave_out_open())                          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                                  rdpsnd_send_completion(tick, packet_index);                                  fprintf(stderr, "cbSize too large for buffer: %d\n",
372                                  return;                                          format->cbSize);
373                                    readcnt = MAX_CBSIZE;
374                                    discardcnt = format->cbSize - MAX_CBSIZE;
375                          }                          }
376                          if (!current_driver->wave_out_set_format(&formats[format]))                          in_uint8a(in, format->cb, readcnt);
377                            in_uint8s(in, discardcnt);
378    
379                            if (device_available && current_driver->wave_in_format_supported(format))
380                          {                          {
381                                  rdpsnd_send_completion(tick, packet_index);                                  rec_format_count++;
382                                  current_driver->wave_out_close();                                  if (rec_format_count == MAX_FORMATS)
383                                  device_open = False;                                          break;
                                 return;  
384                          }                          }
                         device_open = True;  
                         current_format = format;  
385                  }                  }
386            }
387    
388                  /* Insert the 4 missing bytes retrieved from last RDPSND_WRITE */          out = rdpsnd_init_packet(RDPSND_REC_NEGOTIATE, 12 + 18 * rec_format_count);
389                  memcpy(s->data, missing_bytes, 4);          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                  current_driver->          for (i = 0; i < rec_format_count; i++)
395                          wave_out_write(rdpsnd_dsp_process          {
396                                         (s, current_driver, &formats[current_format]), tick,                  format = &rec_formats[i];
397                                         packet_index);                  out_uint16_le(out, format->wFormatTag);
398                  awaiting_data_packet = False;                  out_uint16_le(out, format->nChannels);
399                  return;                  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          in_uint8(s, type);          s_mark_end(out);
407          in_uint8s(s, 1);        /* unknown? */  
408          in_uint16_le(s, datalen);          DEBUG_SOUND(("RDPSND: -> RDPSND_REC_NEGOTIATE(formats: %d)\n", (int) rec_format_count));
409    
410            rdpsnd_send(out);
411    }
412    
413    static void
414    rdpsnd_process_packet(uint8 opcode, STREAM s)
415    {
416            uint16 vol_left, vol_right;
417            static uint16 tick, format;
418            static uint8 packet_index;
419    
420          switch (type)          switch (opcode)
421          {          {
422                  case RDPSND_WRITE:                  case RDPSND_WRITE:
423                          in_uint16_le(s, tick);                          in_uint16_le(s, tick);
424                          in_uint16_le(s, format);                          in_uint16_le(s, format);
425                          in_uint8(s, packet_index);                          in_uint8(s, packet_index);
426                          /* Here are our lost bytes, but why? */                          in_uint8s(s, 3);
427                          memcpy(missing_bytes, s->end - 4, 4);                          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                          awaiting_data_packet = True;  
429                            if (format >= MAX_FORMATS)
430                            {
431                                    error("RDPSND: Invalid format index\n");
432                                    break;
433                            }
434    
435                            if (!device_open || (format != current_format))
436                            {
437                                    /*
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                                    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                            }
462    
463                            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                          break;                          break;
468                  case RDPSND_CLOSE:                  case RDPSND_CLOSE:
469                          current_driver->wave_out_close();                          DEBUG_SOUND(("RDPSND: RDPSND_CLOSE()\n"));
470                            if (device_open)
471                                    current_driver->wave_out_close();
472                          device_open = False;                          device_open = False;
473                          break;                          break;
474                  case RDPSND_NEGOTIATE:                  case RDPSND_NEGOTIATE:
475                          rdpsnd_process_negotiate(s);                          rdpsnd_process_negotiate(s);
476                          break;                          break;
477                  case RDPSND_SERVERTICK:                  case RDPSND_PING:
478                          rdpsnd_process_servertick(s);                          rdpsnd_process_ping(s);
479                          break;                          break;
480                  case RDPSND_SET_VOLUME:                  case RDPSND_SET_VOLUME:
481                          in_uint32(s, volume);                          in_uint16_le(s, vol_left);
482                            in_uint16_le(s, vol_right);
483                            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                          if (device_open)                          if (device_open)
485                                    current_driver->wave_out_volume(vol_left, vol_right);
486                            break;
487                    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                                  current_driver->wave_out_volume((volume & 0xffff),                                  error("RDPSND: Device not accepting format\n");
512                                                                  (volume & 0xffff0000) >> 16);                                  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;                          break;
531                  default:                  default:
532                          unimpl("RDPSND packet type %d\n", type);                          unimpl("RDPSND packet type %x\n", opcode);
533                          break;                          break;
534          }          }
535  }  }
536    
537  BOOL  static void
538  rdpsnd_init(void)  rdpsnd_process(STREAM s)
539  {  {
540          rdpsnd_channel =          uint16 len;
                 channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,  
                                  rdpsnd_process);  
   
         return (rdpsnd_channel != NULL);  
 }  
541    
542  BOOL          while (!s_check_end(s))
 rdpsnd_auto_open(void)  
 {  
         current_driver = drivers;  
         while (current_driver != NULL)  
543          {          {
544                  DEBUG(("trying %s...\n", current_driver->name));                  /* New packet */
545                  if (current_driver->wave_out_open())                  if (packet.size == 0)
546                  {                  {
547                          DEBUG(("selected %s\n", current_driver->name));                          if ((s->end - s->p) < 4)
548                          return True;                          {
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                            DEBUG_SOUND(("RDPSND: == Opcode %x Length: %d ==\n",
557                                         (int) packet_opcode, (int) len));
558    
559                            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                                            DEBUG_SOUND(("RDPSND: Eating 4 bytes of %d bytes...\n",
575                                                         len));
576                                            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                  }                  }
                 g_dsp_fd = 0;  
                 current_driver = current_driver->next;  
592          }          }
593    }
594    
595          warning("no working audio-driver found\n");  static BOOL
596    rdpsnddbg_line_handler(const char *line, void *data)
597    {
598    #ifdef WITH_DEBUG_SOUND
599            fprintf(stderr, "SNDDBG: %s\n", line);
600    #endif
601            return True;
602    }
603    
604          return False;  static void
605    rdpsnddbg_process(STREAM s)
606    {
607            unsigned int pkglen;
608            static char *rest = NULL;
609            char *buf;
610    
611            pkglen = s->end - s->p;
612            /* str_handle_lines requires null terminated strings */
613            buf = xmalloc(pkglen + 1);
614            STRNCPY(buf, (char *) s->p, pkglen + 1);
615    
616            str_handle_lines(buf, &rest, rdpsnddbg_line_handler, NULL);
617    
618            xfree(buf);
619  }  }
620    
621  void  static void
622  rdpsnd_register_drivers(char *options)  rdpsnd_register_drivers(char *options)
623  {  {
624          struct audio_driver **reg;          struct audio_driver **reg;
# Line 317  rdpsnd_register_drivers(char *options) Line 628  rdpsnd_register_drivers(char *options)
628          reg = &drivers;          reg = &drivers;
629  #if defined(RDPSND_ALSA)  #if defined(RDPSND_ALSA)
630          *reg = alsa_register(options);          *reg = alsa_register(options);
631            assert(*reg);
632          reg = &((*reg)->next);          reg = &((*reg)->next);
633  #endif  #endif
634  #if defined(RDPSND_SUN)  #if defined(RDPSND_SUN)
635          *reg = sun_register(options);          *reg = sun_register(options);
636            assert(*reg);
637          reg = &((*reg)->next);          reg = &((*reg)->next);
638  #endif  #endif
639  #if defined(RDPSND_OSS)  #if defined(RDPSND_OSS)
640          *reg = oss_register(options);          *reg = oss_register(options);
641            assert(*reg);
642          reg = &((*reg)->next);          reg = &((*reg)->next);
643  #endif  #endif
644  #if defined(RDPSND_SGI)  #if defined(RDPSND_SGI)
645          *reg = sgi_register(options);          *reg = sgi_register(options);
646            assert(*reg);
647          reg = &((*reg)->next);          reg = &((*reg)->next);
648  #endif  #endif
649  #if defined(RDPSND_LIBAO)  #if defined(RDPSND_LIBAO)
650          *reg = libao_register(options);          *reg = libao_register(options);
651            assert(*reg);
652          reg = &((*reg)->next);          reg = &((*reg)->next);
653  #endif  #endif
654            *reg = NULL;
655  }  }
656    
657  BOOL  BOOL
658  rdpsnd_select_driver(char *driver, char *options)  rdpsnd_init(char *optarg)
659  {  {
         static struct audio_driver auto_driver;  
660          struct audio_driver *pos;          struct audio_driver *pos;
661            char *driver = NULL, *options = NULL;
662    
663          drivers = NULL;          drivers = NULL;
664    
665            packet.data = xmalloc(65536);
666            packet.p = packet.end = packet.data;
667            packet.size = 0;
668    
669            rdpsnd_channel =
670                    channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
671                                     rdpsnd_process);
672    
673            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            {
679                    error("channel_register\n");
680                    return False;
681            }
682    
683            rdpsnd_queue_init();
684    
685            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          rdpsnd_register_drivers(options);          rdpsnd_register_drivers(options);
703    
704          if (!driver)          if (!driver)
         {  
                 auto_driver.wave_out_open = &rdpsnd_auto_open;  
                 current_driver = &auto_driver;  
705                  return True;                  return True;
         }  
706    
707          pos = drivers;          pos = drivers;
708          while (pos != NULL)          while (pos != NULL)
# Line 382  rdpsnd_show_help(void) Line 733  rdpsnd_show_help(void)
733          }          }
734  }  }
735    
736  inline void  void
737  rdpsnd_play(void)  rdpsnd_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
738  {  {
739          current_driver->wave_out_play();          long next_pending;
740    
741            if (device_open || rec_device_open)
742                    current_driver->add_fds(n, rfds, wfds, tv);
743    
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  void
759    rdpsnd_check_fds(fd_set * rfds, fd_set * wfds)
760    {
761            rdpsnd_queue_complete_pending();
762    
763            if (device_open || rec_device_open)
764                    current_driver->check_fds(rfds, wfds);
765    }
766    
767    static void
768  rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)  rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)
769  {  {
770          struct audio_packet *packet = &packet_queue[queue_hi];          struct audio_packet *packet = &packet_queue[queue_hi];
771          unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;          unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
772    
773          if (next_hi == queue_lo)          if (next_hi == queue_pending)
774          {          {
775                  error("No space to queue audio packet\n");                  error("No space to queue audio packet\n");
776                  return;                  return;
# Line 406  rdpsnd_queue_write(STREAM s, uint16 tick Line 782  rdpsnd_queue_write(STREAM s, uint16 tick
782          packet->tick = tick;          packet->tick = tick;
783          packet->index = index;          packet->index = index;
784    
785          if (!g_dsp_busy)          gettimeofday(&packet->arrive_tv, NULL);
                 current_driver->wave_out_play();  
786  }  }
787    
788  inline struct audio_packet *  struct audio_packet *
789  rdpsnd_queue_current_packet(void)  rdpsnd_queue_current_packet(void)
790  {  {
791          return &packet_queue[queue_lo];          return &packet_queue[queue_lo];
792  }  }
793    
794  inline BOOL  BOOL
795  rdpsnd_queue_empty(void)  rdpsnd_queue_empty(void)
796  {  {
797          return (queue_lo == queue_hi);          return (queue_lo == queue_hi);
798  }  }
799    
800  inline void  static void
801  rdpsnd_queue_init(void)  rdpsnd_queue_init(void)
802  {  {
803          queue_lo = queue_hi = 0;          queue_pending = queue_lo = queue_hi = 0;
804  }  }
805    
806  inline void  void
807  rdpsnd_queue_next(void)  rdpsnd_queue_next(unsigned long completed_in_us)
808  {  {
809          xfree(packet_queue[queue_lo].s.data);          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          queue_lo = (queue_lo + 1) % MAX_QUEUE;          queue_lo = (queue_lo + 1) % MAX_QUEUE;
822    
823            rdpsnd_queue_complete_pending();
824  }  }
825    
826  inline int  int
827  rdpsnd_queue_next_tick(void)  rdpsnd_queue_next_tick(void)
828  {  {
829          if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)          if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
# Line 447  rdpsnd_queue_next_tick(void) Line 835  rdpsnd_queue_next_tick(void)
835                  return (packet_queue[queue_lo].tick + 65535) % 65536;                  return (packet_queue[queue_lo].tick + 65535) % 65536;
836          }          }
837  }  }
838    
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                    elapsed /= 1000;
862    
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    }

Legend:
Removed from v.1265  
changed lines
  Added in v.1359

  ViewVC Help
Powered by ViewVC 1.1.26