/[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 1344 by ossman_, Wed Dec 6 13:59:43 2006 UTC revision 1427 by ossman_, Fri Jan 18 15:11:57 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 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB     Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
5     Copyright (C) Matthew Chapman 2003     Copyright (C) Matthew Chapman 2003-2007
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 34  Line 34 
34  #define RDPSND_PING                     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    #define RDPSND_FLAG_RECORD              0x00800000
44    
45  BOOL g_dsp_busy = False;  #define MAX_FORMATS             10
46  int g_dsp_fd;  #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 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    
63  unsigned int queue_hi, queue_lo, queue_pending;  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 uint32 record_buffer_size;
68    
69  static uint8 packet_opcode;  static uint8 packet_opcode;
70  static struct stream packet;  static struct stream packet;
71    
# Line 95  rdpsnd_send_completion(uint16 tick, uint Line 110  rdpsnd_send_completion(uint16 tick, uint
110  }  }
111    
112  static void  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            uint32 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 RD_BOOL
182    rdpsnd_auto_select(void)
183    {
184            static RD_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
210  rdpsnd_process_negotiate(STREAM in)  rdpsnd_process_negotiate(STREAM in)
211  {  {
212          uint16 in_format_count, i;          uint16 in_format_count, i;
213          uint8 pad;          uint8 pad;
214          uint16 version;          uint16 version;
215          WAVEFORMATEX *format;          RD_WAVEFORMATEX *format;
216          STREAM out;          STREAM out;
217          BOOL device_available = False;          RD_BOOL device_available = False;
218          int readcnt;          int readcnt;
219          int discardcnt;          int discardcnt;
220    
# Line 115  rdpsnd_process_negotiate(STREAM in) Line 227  rdpsnd_process_negotiate(STREAM in)
227          DEBUG_SOUND(("RDPSND: RDPSND_NEGOTIATE(formats: %d, pad: 0x%02x, version: %x)\n",          DEBUG_SOUND(("RDPSND: RDPSND_NEGOTIATE(formats: %d, pad: 0x%02x, version: %x)\n",
228                       (int) in_format_count, (unsigned) pad, (unsigned) version));                       (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 148  rdpsnd_process_negotiate(STREAM in) Line 263  rdpsnd_process_negotiate(STREAM in)
263                          in_uint8a(in, format->cb, readcnt);                          in_uint8a(in, format->cb, readcnt);
264                          in_uint8s(in, discardcnt);                          in_uint8s(in, discardcnt);
265    
266                          if (device_available && current_driver->wave_out_format_supported(format))                          if (current_driver && current_driver->wave_out_format_supported(format))
267                          {                          {
268                                  format_count++;                                  format_count++;
269                                  if (format_count == MAX_FORMATS)                                  if (format_count == MAX_FORMATS)
# Line 158  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 */
# Line 207  rdpsnd_process_ping(STREAM in) Line 322  rdpsnd_process_ping(STREAM in)
322  }  }
323    
324  static void  static void
325    rdpsnd_process_rec_negotiate(STREAM in)
326    {
327            uint16 in_format_count, i;
328            uint16 version;
329            RD_WAVEFORMATEX *format;
330            STREAM out;
331            RD_BOOL device_available = False;
332            int readcnt;
333            int discardcnt;
334    
335            in_uint8s(in, 8);       /* initial bytes not valid from server */
336            in_uint16_le(in, in_format_count);
337            in_uint16_le(in, version);
338    
339            DEBUG_SOUND(("RDPSND: RDPSND_REC_NEGOTIATE(formats: %d, version: %x)\n",
340                         (int) in_format_count, (unsigned) version));
341    
342            if (!current_driver)
343                    device_available = rdpsnd_auto_select();
344    
345            if (current_driver && !device_available && current_driver->wave_in_open
346                && current_driver->wave_in_open())
347            {
348                    current_driver->wave_in_close();
349                    device_available = True;
350            }
351    
352            rec_format_count = 0;
353            if (s_check_rem(in, 18 * in_format_count))
354            {
355                    for (i = 0; i < in_format_count; i++)
356                    {
357                            format = &rec_formats[rec_format_count];
358                            in_uint16_le(in, format->wFormatTag);
359                            in_uint16_le(in, format->nChannels);
360                            in_uint32_le(in, format->nSamplesPerSec);
361                            in_uint32_le(in, format->nAvgBytesPerSec);
362                            in_uint16_le(in, format->nBlockAlign);
363                            in_uint16_le(in, format->wBitsPerSample);
364                            in_uint16_le(in, format->cbSize);
365    
366                            /* read in the buffer of unknown use */
367                            readcnt = format->cbSize;
368                            discardcnt = 0;
369                            if (format->cbSize > MAX_CBSIZE)
370                            {
371                                    fprintf(stderr, "cbSize too large for buffer: %d\n",
372                                            format->cbSize);
373                                    readcnt = MAX_CBSIZE;
374                                    discardcnt = format->cbSize - MAX_CBSIZE;
375                            }
376                            in_uint8a(in, format->cb, readcnt);
377                            in_uint8s(in, discardcnt);
378    
379                            if (current_driver && current_driver->wave_in_format_supported
380                                && current_driver->wave_in_format_supported(format))
381                            {
382                                    rec_format_count++;
383                                    if (rec_format_count == MAX_FORMATS)
384                                            break;
385                            }
386                    }
387            }
388    
389            out = rdpsnd_init_packet(RDPSND_REC_NEGOTIATE, 12 + 18 * rec_format_count);
390            out_uint32_le(out, 0x00000000); /* flags */
391            out_uint32_le(out, 0xffffffff); /* volume */
392            out_uint16_le(out, rec_format_count);
393            out_uint16_le(out, 1);  /* version */
394    
395            for (i = 0; i < rec_format_count; i++)
396            {
397                    format = &rec_formats[i];
398                    out_uint16_le(out, format->wFormatTag);
399                    out_uint16_le(out, format->nChannels);
400                    out_uint32_le(out, format->nSamplesPerSec);
401                    out_uint32_le(out, format->nAvgBytesPerSec);
402                    out_uint16_le(out, format->nBlockAlign);
403                    out_uint16_le(out, format->wBitsPerSample);
404                    out_uint16(out, 0);     /* cbSize */
405            }
406    
407            s_mark_end(out);
408    
409            DEBUG_SOUND(("RDPSND: -> RDPSND_REC_NEGOTIATE(formats: %d)\n", (int) rec_format_count));
410    
411            rdpsnd_send(out);
412    }
413    
414    static void
415  rdpsnd_process_packet(uint8 opcode, STREAM s)  rdpsnd_process_packet(uint8 opcode, STREAM s)
416  {  {
417          uint16 vol_left, vol_right;          uint16 vol_left, vol_right;
# Line 230  rdpsnd_process_packet(uint8 opcode, STRE Line 435  rdpsnd_process_packet(uint8 opcode, STRE
435    
436                          if (!device_open || (format != current_format))                          if (!device_open || (format != current_format))
437                          {                          {
438                                    /*
439                                     * If we haven't selected a device by now, then either
440                                     * we've failed to find a working device, or the server
441                                     * is sending bogus RDPSND_WRITE.
442                                     */
443                                    if (!current_driver)
444                                    {
445                                            rdpsnd_send_completion(tick, packet_index);
446                                            break;
447                                    }
448                                  if (!device_open && !current_driver->wave_out_open())                                  if (!device_open && !current_driver->wave_out_open())
449                                  {                                  {
450                                          rdpsnd_send_completion(tick, packet_index);                                          rdpsnd_send_completion(tick, packet_index);
# Line 253  rdpsnd_process_packet(uint8 opcode, STRE Line 468  rdpsnd_process_packet(uint8 opcode, STRE
468                          break;                          break;
469                  case RDPSND_CLOSE:                  case RDPSND_CLOSE:
470                          DEBUG_SOUND(("RDPSND: RDPSND_CLOSE()\n"));                          DEBUG_SOUND(("RDPSND: RDPSND_CLOSE()\n"));
471                          current_driver->wave_out_close();                          if (device_open)
472                                    current_driver->wave_out_close();
473                          device_open = False;                          device_open = False;
474                          break;                          break;
475                  case RDPSND_NEGOTIATE:                  case RDPSND_NEGOTIATE:
# Line 269  rdpsnd_process_packet(uint8 opcode, STRE Line 485  rdpsnd_process_packet(uint8 opcode, STRE
485                          if (device_open)                          if (device_open)
486                                  current_driver->wave_out_volume(vol_left, vol_right);                                  current_driver->wave_out_volume(vol_left, vol_right);
487                          break;                          break;
488                    case RDPSND_REC_NEGOTIATE:
489                            rdpsnd_process_rec_negotiate(s);
490                            break;
491                    case RDPSND_REC_START:
492                            in_uint16_le(s, format);
493                            DEBUG_SOUND(("RDPSND: RDPSND_REC_START(format: %u)\n", (unsigned) format));
494    
495                            if (format >= MAX_FORMATS)
496                            {
497                                    error("RDPSND: Invalid format index\n");
498                                    break;
499                            }
500    
501                            if (rec_device_open)
502                            {
503                                    error("RDPSND: Multiple RDPSND_REC_START\n");
504                                    break;
505                            }
506    
507                            if (!current_driver->wave_in_open())
508                                    break;
509    
510                            if (!current_driver->wave_in_set_format(&rec_formats[format]))
511                            {
512                                    error("RDPSND: Device not accepting format\n");
513                                    current_driver->wave_in_close();
514                                    break;
515                            }
516                            rec_device_open = True;
517                            break;
518                    case RDPSND_REC_STOP:
519                            DEBUG_SOUND(("RDPSND: RDPSND_REC_STOP()\n"));
520                            rdpsnd_flush_record();
521                            if (rec_device_open)
522                                    current_driver->wave_in_close();
523                            rec_device_open = False;
524                            break;
525                    case RDPSND_REC_SET_VOLUME:
526                            in_uint16_le(s, vol_left);
527                            in_uint16_le(s, vol_right);
528                            DEBUG_SOUND(("RDPSND: RDPSND_REC_VOLUME(left: 0x%04x (%u %%), right: 0x%04x (%u %%))\n", (unsigned) vol_left, (unsigned) vol_left / 655, (unsigned) vol_right, (unsigned) vol_right / 655));
529                            if (rec_device_open)
530                                    current_driver->wave_in_volume(vol_left, vol_right);
531                            break;
532                  default:                  default:
533                          unimpl("RDPSND packet type %x\n", opcode);                          unimpl("RDPSND packet type %x\n", opcode);
534                          break;                          break;
# Line 333  rdpsnd_process(STREAM s) Line 593  rdpsnd_process(STREAM s)
593          }          }
594  }  }
595    
596  static BOOL  static RD_BOOL
597  rdpsnd_auto_open(void)  rdpsnddbg_line_handler(const char *line, void *data)
598  {  {
599          static BOOL failed = False;  #ifdef WITH_DEBUG_SOUND
600            fprintf(stderr, "SNDDBG: %s\n", line);
601    #endif
602            return True;
603    }
604    
605          if (!failed)  static void
606          {  rdpsnddbg_process(STREAM s)
607                  struct audio_driver *auto_driver = current_driver;  {
608            unsigned int pkglen;
609            static char *rest = NULL;
610            char *buf;
611    
612                  current_driver = drivers;          pkglen = s->end - s->p;
613                  while (current_driver != NULL)          /* str_handle_lines requires null terminated strings */
614                  {          buf = (char *) xmalloc(pkglen + 1);
615                          DEBUG(("trying %s...\n", current_driver->name));          STRNCPY(buf, (char *) s->p, pkglen + 1);
                         if (current_driver->wave_out_open())  
                         {  
                                 DEBUG(("selected %s\n", current_driver->name));  
                                 return True;  
                         }  
                         g_dsp_fd = 0;  
                         current_driver = current_driver->next;  
                 }  
616    
617                  warning("no working audio-driver found\n");          str_handle_lines(buf, &rest, rdpsnddbg_line_handler, NULL);
                 failed = True;  
                 current_driver = auto_driver;  
         }  
618    
619          return False;          xfree(buf);
620  }  }
621    
622  static void  static void
# Line 399  rdpsnd_register_drivers(char *options) Line 655  rdpsnd_register_drivers(char *options)
655          *reg = NULL;          *reg = NULL;
656  }  }
657    
658  BOOL  RD_BOOL
659  rdpsnd_init(char *optarg)  rdpsnd_init(char *optarg)
660  {  {
         static struct audio_driver auto_driver;  
661          struct audio_driver *pos;          struct audio_driver *pos;
662          char *driver = NULL, *options = NULL;          char *driver = NULL, *options = NULL;
663    
664          drivers = NULL;          drivers = NULL;
665    
666          packet.data = xmalloc(65536);          packet.data = (uint8 *) xmalloc(65536);
667          packet.p = packet.end = packet.data;          packet.p = packet.end = packet.data;
668          packet.size = 0;          packet.size = 0;
669    
# Line 416  rdpsnd_init(char *optarg) Line 671  rdpsnd_init(char *optarg)
671                  channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,                  channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
672                                   rdpsnd_process);                                   rdpsnd_process);
673    
674          if (rdpsnd_channel == NULL)          rdpsnddbg_channel =
675                    channel_register("snddbg", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
676                                     rdpsnddbg_process);
677    
678            if ((rdpsnd_channel == NULL) || (rdpsnddbg_channel == NULL))
679          {          {
680                  error("channel_register\n");                  error("channel_register\n");
681                  return False;                  return False;
# Line 444  rdpsnd_init(char *optarg) Line 703  rdpsnd_init(char *optarg)
703          rdpsnd_register_drivers(options);          rdpsnd_register_drivers(options);
704    
705          if (!driver)          if (!driver)
         {  
                 auto_driver.wave_out_open = &rdpsnd_auto_open;  
                 current_driver = &auto_driver;  
706                  return True;                  return True;
         }  
707    
708          pos = drivers;          pos = drivers;
709          while (pos != NULL)          while (pos != NULL)
# Line 480  rdpsnd_show_help(void) Line 735  rdpsnd_show_help(void)
735  }  }
736    
737  void  void
 rdpsnd_play(void)  
 {  
         current_driver->wave_out_play();  
 }  
   
 void  
738  rdpsnd_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)  rdpsnd_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
739  {  {
740          long next_pending;          long next_pending;
741    
742          if (g_dsp_busy)          if (device_open || rec_device_open)
743          {                  current_driver->add_fds(n, rfds, wfds, tv);
                 FD_SET(g_dsp_fd, wfds);  
                 *n = (g_dsp_fd > *n) ? g_dsp_fd : *n;  
         }  
744    
745          next_pending = rdpsnd_queue_next_completion();          next_pending = rdpsnd_queue_next_completion();
746          if (next_pending >= 0)          if (next_pending >= 0)
# Line 515  rdpsnd_check_fds(fd_set * rfds, fd_set * Line 761  rdpsnd_check_fds(fd_set * rfds, fd_set *
761  {  {
762          rdpsnd_queue_complete_pending();          rdpsnd_queue_complete_pending();
763    
764          if (g_dsp_busy && FD_ISSET(g_dsp_fd, wfds))          if (device_open || rec_device_open)
765                  rdpsnd_play();                  current_driver->check_fds(rfds, wfds);
766  }  }
767    
768  static void  static void
# Line 538  rdpsnd_queue_write(STREAM s, uint16 tick Line 784  rdpsnd_queue_write(STREAM s, uint16 tick
784          packet->index = index;          packet->index = index;
785    
786          gettimeofday(&packet->arrive_tv, NULL);          gettimeofday(&packet->arrive_tv, NULL);
   
         if (!g_dsp_busy)  
                 current_driver->wave_out_play();  
787  }  }
788    
789  struct audio_packet *  struct audio_packet *
# Line 549  rdpsnd_queue_current_packet(void) Line 792  rdpsnd_queue_current_packet(void)
792          return &packet_queue[queue_lo];          return &packet_queue[queue_lo];
793  }  }
794    
795  BOOL  RD_BOOL
796  rdpsnd_queue_empty(void)  rdpsnd_queue_empty(void)
797  {  {
798          return (queue_lo == queue_hi);          return (queue_lo == queue_hi);

Legend:
Removed from v.1344  
changed lines
  Added in v.1427

  ViewVC Help
Powered by ViewVC 1.1.26