/[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 1353 by stargo, Sun Dec 24 15:22:15 2006 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 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB     Copyright 2006-2008 Pierre Ossman <ossman@cendio.se> for Cendio AB
5     Copyright (C) Matthew Chapman 2003     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 34  Line 34 
34  #define RDPSND_PING                     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               10  #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    static unsigned int rec_current_format;
63    
64  unsigned int queue_hi, queue_lo, queue_pending;  unsigned int queue_hi, queue_lo, queue_pending;
65  struct audio_packet packet_queue[MAX_QUEUE];  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;  static uint8 packet_opcode;
71  static struct stream packet;  static struct stream packet;
72    
# Line 91  rdpsnd_send_completion(uint16 tick, uint Line 110  rdpsnd_send_completion(uint16 tick, uint
110                       (unsigned) tick, (unsigned) packet_index));                       (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  static BOOL                  if (record_buffer_size == sizeof(record_buffer))
184                            rdpsnd_flush_record();
185            }
186    }
187    
188    static RD_BOOL
189  rdpsnd_auto_select(void)  rdpsnd_auto_select(void)
190  {  {
191          static BOOL failed = False;          static RD_BOOL failed = False;
192    
193          if (!failed)          if (!failed)
194          {          {
# Line 126  rdpsnd_process_negotiate(STREAM in) Line 219  rdpsnd_process_negotiate(STREAM in)
219          uint16 in_format_count, i;          uint16 in_format_count, i;
220          uint8 pad;          uint8 pad;
221          uint16 version;          uint16 version;
222          WAVEFORMATEX *format;          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    
# Line 177  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 && current_driver->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 187  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 */
# Line 236  rdpsnd_process_ping(STREAM in) Line 329  rdpsnd_process_ping(STREAM in)
329  }  }
330    
331  static void  static void
332    rdpsnd_process_rec_negotiate(STREAM in)
333    {
334            uint16 in_format_count, i;
335            uint16 version;
336            RD_WAVEFORMATEX *format;
337            STREAM out;
338            RD_BOOL device_available = False;
339            int readcnt;
340            int discardcnt;
341    
342            in_uint8s(in, 8);       /* initial bytes not valid from server */
343            in_uint16_le(in, in_format_count);
344            in_uint16_le(in, version);
345    
346            DEBUG_SOUND(("RDPSND: RDPSND_REC_NEGOTIATE(formats: %d, version: %x)\n",
347                         (int) in_format_count, (unsigned) version));
348    
349            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                    current_driver->wave_in_close();
356                    device_available = True;
357            }
358    
359            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                            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                                    fprintf(stderr, "cbSize too large for buffer: %d\n",
379                                            format->cbSize);
380                                    readcnt = MAX_CBSIZE;
381                                    discardcnt = format->cbSize - MAX_CBSIZE;
382                            }
383                            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                                    rec_format_count++;
390                                    if (rec_format_count == MAX_FORMATS)
391                                            break;
392                            }
393                    }
394            }
395    
396            out = rdpsnd_init_packet(RDPSND_REC_NEGOTIATE, 12 + 18 * rec_format_count);
397            out_uint32_le(out, 0x00000000); /* flags */
398            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            s_mark_end(out);
415    
416            DEBUG_SOUND(("RDPSND: -> RDPSND_REC_NEGOTIATE(formats: %d)\n", (int) rec_format_count));
417    
418            rdpsnd_send(out);
419    }
420    
421    static void
422  rdpsnd_process_packet(uint8 opcode, STREAM s)  rdpsnd_process_packet(uint8 opcode, STREAM s)
423  {  {
424          uint16 vol_left, vol_right;          uint16 vol_left, vol_right;
# Line 309  rdpsnd_process_packet(uint8 opcode, STRE Line 492  rdpsnd_process_packet(uint8 opcode, STRE
492                          if (device_open)                          if (device_open)
493                                  current_driver->wave_out_volume(vol_left, vol_right);                                  current_driver->wave_out_volume(vol_left, vol_right);
494                          break;                          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                                    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;
540                  default:                  default:
541                          unimpl("RDPSND packet type %x\n", opcode);                          unimpl("RDPSND packet type %x\n", opcode);
542                          break;                          break;
# Line 373  rdpsnd_process(STREAM s) Line 601  rdpsnd_process(STREAM s)
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  static void
631  rdpsnd_register_drivers(char *options)  rdpsnd_register_drivers(char *options)
632  {  {
# Line 409  rdpsnd_register_drivers(char *options) Line 663  rdpsnd_register_drivers(char *options)
663          *reg = NULL;          *reg = NULL;
664  }  }
665    
666  BOOL  RD_BOOL
667  rdpsnd_init(char *optarg)  rdpsnd_init(char *optarg)
668  {  {
669          struct audio_driver *pos;          struct audio_driver *pos;
# Line 417  rdpsnd_init(char *optarg) Line 671  rdpsnd_init(char *optarg)
671    
672          drivers = NULL;          drivers = NULL;
673    
674          packet.data = xmalloc(65536);          packet.data = (uint8 *) xmalloc(65536);
675          packet.p = packet.end = packet.data;          packet.p = packet.end = packet.data;
676          packet.size = 0;          packet.size = 0;
677    
# Line 425  rdpsnd_init(char *optarg) Line 679  rdpsnd_init(char *optarg)
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    
682          if (rdpsnd_channel == NULL)          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");                  error("channel_register\n");
689                  return False;                  return False;
# Line 489  rdpsnd_add_fds(int *n, fd_set * rfds, fd Line 747  rdpsnd_add_fds(int *n, fd_set * rfds, fd
747  {  {
748          long next_pending;          long next_pending;
749    
750          if (device_open)          if (device_open || rec_device_open)
751                  current_driver->add_fds(n, rfds, wfds, tv);                  current_driver->add_fds(n, rfds, wfds, tv);
752    
753          next_pending = rdpsnd_queue_next_completion();          next_pending = rdpsnd_queue_next_completion();
# Line 511  rdpsnd_check_fds(fd_set * rfds, fd_set * Line 769  rdpsnd_check_fds(fd_set * rfds, fd_set *
769  {  {
770          rdpsnd_queue_complete_pending();          rdpsnd_queue_complete_pending();
771    
772          if (device_open)          if (device_open || rec_device_open)
773                  current_driver->check_fds(rfds, wfds);                  current_driver->check_fds(rfds, wfds);
774  }  }
775    
# Line 542  rdpsnd_queue_current_packet(void) Line 800  rdpsnd_queue_current_packet(void)
800          return &packet_queue[queue_lo];          return &packet_queue[queue_lo];
801  }  }
802    
803  BOOL  RD_BOOL
804  rdpsnd_queue_empty(void)  rdpsnd_queue_empty(void)
805  {  {
806          return (queue_lo == queue_hi);          return (queue_lo == queue_hi);

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

  ViewVC Help
Powered by ViewVC 1.1.26