/[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 1340 by ossman_, Wed Dec 6 13:11:35 2006 UTC revision 1372 by jsorg71, Mon Jan 8 04:47: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 (C) Matthew Chapman 2003     Copyright 2006-2007 Pierre Ossman <ossman@cendio.se> for Cendio AB
5       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 33  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 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);  static void rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index);
# Line 71  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    
# Line 90  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 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  static void
# Line 98  rdpsnd_process_negotiate(STREAM in) Line 212  rdpsnd_process_negotiate(STREAM in)
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 110  rdpsnd_process_negotiate(STREAM in) Line 224  rdpsnd_process_negotiate(STREAM in)
224          in_uint16_le(in, version);          in_uint16_le(in, version);
225          in_uint8s(in, 1);       /* padding */          in_uint8s(in, 1);       /* padding */
226    
227          if (current_driver->wave_out_open())          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)
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 153  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 176  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    
# Line 187  rdpsnd_process_ping(STREAM in) Line 310  rdpsnd_process_ping(STREAM in)
310    
311          in_uint16_le(in, tick);          in_uint16_le(in, tick);
312    
313            DEBUG_SOUND(("RDPSND: RDPSND_PING(tick: 0x%04x)\n", (unsigned) tick));
314    
315          out = rdpsnd_init_packet(RDPSND_PING | 0x2300, 4);          out = rdpsnd_init_packet(RDPSND_PING | 0x2300, 4);
316          out_uint16_le(out, tick);          out_uint16_le(out, tick);
317          out_uint16_le(out, 0);          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;          RD_WAVEFORMATEX *format;
330          static uint16 tick, format;          STREAM out;
331          static uint8 packet_index;          RD_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                  rdpsnd_queue_write(rdpsnd_dsp_process          for (i = 0; i < rec_format_count; i++)
395                                     (s, current_driver, &formats[current_format]), tick,          {
396                                     packet_index);                  format = &rec_formats[i];
397                  awaiting_data_packet = False;                  out_uint16_le(out, format->wFormatTag);
398                  return;                  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          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          switch (type)          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 (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:
# Line 271  rdpsnd_process(STREAM s) Line 478  rdpsnd_process(STREAM s)
478                          rdpsnd_process_ping(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                                  current_driver->wave_out_volume((volume & 0xffff),                                  error("RDPSND: Multiple RDPSND_REC_START\n");
503                                                                  (volume & 0xffff0000) >> 16);                                  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;                          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  static BOOL  static void
538  rdpsnd_auto_open(void)  rdpsnd_process(STREAM s)
539  {  {
540          static BOOL failed = False;          uint16 len;
541    
542          if (!failed)          while (!s_check_end(s))
543          {          {
544                  struct audio_driver *auto_driver = current_driver;                  /* New packet */
545                    if (packet.size == 0)
                 current_driver = drivers;  
                 while (current_driver != NULL)  
546                  {                  {
547                          DEBUG(("trying %s...\n", current_driver->name));                          if ((s->end - s->p) < 4)
                         if (current_driver->wave_out_open())  
548                          {                          {
549                                  DEBUG(("selected %s\n", current_driver->name));                                  error("RDPSND: Split at packet header. Things will go south from here...\n");
550                                  return True;                                  return;
551                          }                          }
552                          g_dsp_fd = 0;                          in_uint8(s, packet_opcode);
553                          current_driver = current_driver->next;                          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                  warning("no working audio-driver found\n");                          /* Microsoft's server is so broken it's not even funny... */
568                  failed = True;                          if (packet_opcode == RDPSND_WRITE)
569                  current_driver = auto_driver;                          {
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                    }
592          }          }
593    }
594    
595          return False;  static RD_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
# Line 350  rdpsnd_register_drivers(char *options) Line 654  rdpsnd_register_drivers(char *options)
654          *reg = NULL;          *reg = NULL;
655  }  }
656    
657  BOOL  RD_BOOL
658  rdpsnd_init(char *optarg)  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;          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 =          rdpsnd_channel =
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 391  rdpsnd_init(char *optarg) Line 702  rdpsnd_init(char *optarg)
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 427  rdpsnd_show_help(void) Line 734  rdpsnd_show_help(void)
734  }  }
735    
736  void  void
 rdpsnd_play(void)  
 {  
         current_driver->wave_out_play();  
 }  
   
 void  
737  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)
738  {  {
739          long next_pending;          long next_pending;
740    
741          if (g_dsp_busy)          if (device_open || rec_device_open)
742          {                  current_driver->add_fds(n, rfds, wfds, tv);
                 FD_SET(g_dsp_fd, wfds);  
                 *n = (g_dsp_fd > *n) ? g_dsp_fd : *n;  
         }  
743    
744          next_pending = rdpsnd_queue_next_completion();          next_pending = rdpsnd_queue_next_completion();
745          if (next_pending >= 0)          if (next_pending >= 0)
# Line 462  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 (g_dsp_busy && FD_ISSET(g_dsp_fd, wfds))          if (device_open || rec_device_open)
764                  rdpsnd_play();                  current_driver->check_fds(rfds, wfds);
765  }  }
766    
767  static void  static void
# Line 485  rdpsnd_queue_write(STREAM s, uint16 tick Line 783  rdpsnd_queue_write(STREAM s, uint16 tick
783          packet->index = index;          packet->index = index;
784    
785          gettimeofday(&packet->arrive_tv, NULL);          gettimeofday(&packet->arrive_tv, NULL);
   
         if (!g_dsp_busy)  
                 current_driver->wave_out_play();  
786  }  }
787    
788  struct audio_packet *  struct audio_packet *
# Line 496  rdpsnd_queue_current_packet(void) Line 791  rdpsnd_queue_current_packet(void)
791          return &packet_queue[queue_lo];          return &packet_queue[queue_lo];
792  }  }
793    
794  BOOL  RD_BOOL
795  rdpsnd_queue_empty(void)  rdpsnd_queue_empty(void)
796  {  {
797          return (queue_lo == queue_hi);          return (queue_lo == queue_hi);

Legend:
Removed from v.1340  
changed lines
  Added in v.1372

  ViewVC Help
Powered by ViewVC 1.1.26