/[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 1359 by ossman_, Tue Jan 2 16:30:06 2007 UTC
# 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 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    
60    static 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 int record_buffer_size;
68    
69  static uint8 packet_opcode;  static uint8 packet_opcode;
70  static struct stream packet;  static struct stream packet;
71    
# Line 91  rdpsnd_send_completion(uint16 tick, uint Line 109  rdpsnd_send_completion(uint16 tick, uint
109                       (unsigned) tick, (unsigned) packet_index));                       (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  static BOOL
182  rdpsnd_auto_select(void)  rdpsnd_auto_select(void)
# Line 187  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 236  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            WAVEFORMATEX *format;
330            STREAM out;
331            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 (device_available && current_driver->wave_in_format_supported(format))
380                            {
381                                    rec_format_count++;
382                                    if (rec_format_count == MAX_FORMATS)
383                                            break;
384                            }
385                    }
386            }
387    
388            out = rdpsnd_init_packet(RDPSND_REC_NEGOTIATE, 12 + 18 * rec_format_count);
389            out_uint32_le(out, 0x00000000); /* flags */
390            out_uint32_le(out, 0xffffffff); /* volume */
391            out_uint16_le(out, rec_format_count);
392            out_uint16_le(out, 1);  /* version */
393    
394            for (i = 0; i < rec_format_count; i++)
395            {
396                    format = &rec_formats[i];
397                    out_uint16_le(out, format->wFormatTag);
398                    out_uint16_le(out, format->nChannels);
399                    out_uint32_le(out, format->nSamplesPerSec);
400                    out_uint32_le(out, format->nAvgBytesPerSec);
401                    out_uint16_le(out, format->nBlockAlign);
402                    out_uint16_le(out, format->wBitsPerSample);
403                    out_uint16(out, 0);     /* cbSize */
404            }
405    
406            s_mark_end(out);
407    
408            DEBUG_SOUND(("RDPSND: -> RDPSND_REC_NEGOTIATE(formats: %d)\n", (int) rec_format_count));
409    
410            rdpsnd_send(out);
411    }
412    
413    static void
414  rdpsnd_process_packet(uint8 opcode, STREAM s)  rdpsnd_process_packet(uint8 opcode, STREAM s)
415  {  {
416          uint16 vol_left, vol_right;          uint16 vol_left, vol_right;
# Line 309  rdpsnd_process_packet(uint8 opcode, STRE Line 484  rdpsnd_process_packet(uint8 opcode, STRE
484                          if (device_open)                          if (device_open)
485                                  current_driver->wave_out_volume(vol_left, vol_right);                                  current_driver->wave_out_volume(vol_left, vol_right);
486                          break;                          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                                    error("RDPSND: Device not accepting format\n");
512                                    current_driver->wave_in_close();
513                                    break;
514                            }
515                            rec_device_open = True;
516                            break;
517                    case RDPSND_REC_STOP:
518                            DEBUG_SOUND(("RDPSND: RDPSND_REC_STOP()\n"));
519                            rdpsnd_flush_record();
520                            if (rec_device_open)
521                                    current_driver->wave_in_close();
522                            rec_device_open = False;
523                            break;
524                    case RDPSND_REC_SET_VOLUME:
525                            in_uint16_le(s, vol_left);
526                            in_uint16_le(s, vol_right);
527                            DEBUG_SOUND(("RDPSND: RDPSND_REC_VOLUME(left: 0x%04x (%u %%), right: 0x%04x (%u %%))\n", (unsigned) vol_left, (unsigned) vol_left / 655, (unsigned) vol_right, (unsigned) vol_right / 655));
528                            if (rec_device_open)
529                                    current_driver->wave_in_volume(vol_left, vol_right);
530                            break;
531                  default:                  default:
532                          unimpl("RDPSND packet type %x\n", opcode);                          unimpl("RDPSND packet type %x\n", opcode);
533                          break;                          break;
# Line 373  rdpsnd_process(STREAM s) Line 592  rdpsnd_process(STREAM s)
592          }          }
593  }  }
594    
595    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    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  static void  static void
622  rdpsnd_register_drivers(char *options)  rdpsnd_register_drivers(char *options)
623  {  {
# Line 425  rdpsnd_init(char *optarg) Line 670  rdpsnd_init(char *optarg)
670                  channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,                  channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
671                                   rdpsnd_process);                                   rdpsnd_process);
672    
673          if (rdpsnd_channel == NULL)          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");                  error("channel_register\n");
680                  return False;                  return False;
# Line 489  rdpsnd_add_fds(int *n, fd_set * rfds, fd Line 738  rdpsnd_add_fds(int *n, fd_set * rfds, fd
738  {  {
739          long next_pending;          long next_pending;
740    
741          if (device_open)          if (device_open || rec_device_open)
742                  current_driver->add_fds(n, rfds, wfds, tv);                  current_driver->add_fds(n, rfds, wfds, tv);
743    
744          next_pending = rdpsnd_queue_next_completion();          next_pending = rdpsnd_queue_next_completion();
# Line 511  rdpsnd_check_fds(fd_set * rfds, fd_set * Line 760  rdpsnd_check_fds(fd_set * rfds, fd_set *
760  {  {
761          rdpsnd_queue_complete_pending();          rdpsnd_queue_complete_pending();
762    
763          if (device_open)          if (device_open || rec_device_open)
764                  current_driver->check_fds(rfds, wfds);                  current_driver->check_fds(rfds, wfds);
765  }  }
766    

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

  ViewVC Help
Powered by ViewVC 1.1.26