/[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 474 by matthewc, Tue Sep 30 09:11:08 2003 UTC revision 1339 by ossman_, Wed Dec 6 13:01:45 2006 UTC
# Line 1  Line 1 
1  /*  /* -*- 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 (C) Matthew Chapman 2003
# Line 19  Line 19 
19     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20  */  */
21    
22    #include <assert.h>
23    
24  #include "rdesktop.h"  #include "rdesktop.h"
25    #include "rdpsnd.h"
26    #include "rdpsnd_dsp.h"
27    
28  #define RDPSND_CLOSE            1  #define RDPSND_CLOSE            1
29  #define RDPSND_WRITE            2  #define RDPSND_WRITE            2
30  #define RDPSND_SET_VOLUME       3  #define RDPSND_SET_VOLUME       3
31  #define RDPSND_UNKNOWN4         4  #define RDPSND_UNKNOWN4         4
32  #define RDPSND_COMPLETION       5  #define RDPSND_COMPLETION       5
33  #define RDPSND_UNKNOWN6         6  #define RDPSND_PING                     6
34  #define RDPSND_NEGOTIATE        7  #define RDPSND_NEGOTIATE        7
35    
36  #define MAX_FORMATS             10  #define MAX_FORMATS             10
37    #define MAX_QUEUE               10
38    
39    BOOL g_dsp_busy = False;
40    int g_dsp_fd;
41    
42  static VCHANNEL *rdpsnd_channel;  static VCHANNEL *rdpsnd_channel;
43    static struct audio_driver *drivers = NULL;
44    struct audio_driver *current_driver = NULL;
45    
46  static BOOL device_open;  static BOOL device_open;
47  static WAVEFORMATEX formats[MAX_FORMATS];  static WAVEFORMATEX formats[MAX_FORMATS];
48  static unsigned int format_count;  static unsigned int format_count;
49  static unsigned int current_format;  static unsigned int current_format;
50    unsigned int queue_hi, queue_lo, queue_pending;
51    struct audio_packet packet_queue[MAX_QUEUE];
52    
53    void (*wave_out_play) (void);
54    
55  STREAM  static void rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index);
56    static void rdpsnd_queue_init(void);
57    static void rdpsnd_queue_complete_pending(void);
58    static long rdpsnd_queue_next_completion(void);
59    
60    static STREAM
61  rdpsnd_init_packet(uint16 type, uint16 size)  rdpsnd_init_packet(uint16 type, uint16 size)
62  {  {
63          STREAM s;          STREAM s;
64    
65          s = channel_init(rdpsnd_channel, size+4);          s = channel_init(rdpsnd_channel, size + 4);
66          out_uint16_le(s, type);          out_uint16_le(s, type);
67          out_uint16_le(s, size);          out_uint16_le(s, size);
68          return s;          return s;
69  }  }
70    
71  void  static void
72  rdpsnd_send(STREAM s)  rdpsnd_send(STREAM s)
73  {  {
74  #ifdef RDPSND_DEBUG  #ifdef RDPSND_DEBUG
75          printf("RDPSND send:\n");          printf("RDPSND send:\n");
76          hexdump(s->channel_hdr+8, s->end-s->channel_hdr-8);          hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);
77  #endif  #endif
78    
79          channel_send(s, rdpsnd_channel);          channel_send(s, rdpsnd_channel);
80  }  }
81    
82  void rdpsnd_send_completion(uint16 tick, uint8 packet_index)  static void
83    rdpsnd_send_completion(uint16 tick, uint8 packet_index)
84  {  {
85          STREAM s;          STREAM s;
86    
87          s = rdpsnd_init_packet(RDPSND_COMPLETION, 4);          s = rdpsnd_init_packet(RDPSND_COMPLETION, 4);
88          out_uint16_le(s, tick+50);          out_uint16_le(s, tick);
89          out_uint8(s, packet_index);          out_uint8(s, packet_index);
90          out_uint8(s, 0);          out_uint8(s, 0);
91          s_mark_end(s);          s_mark_end(s);
92          rdpsnd_send(s);          rdpsnd_send(s);
93  }  }
94    
95  void  static void
96  rdpsnd_process_negotiate(STREAM in)  rdpsnd_process_negotiate(STREAM in)
97  {  {
98          unsigned int in_format_count, i;          unsigned int in_format_count, i;
99          WAVEFORMATEX *format;          WAVEFORMATEX *format;
100          STREAM out;          STREAM out;
101            BOOL device_available = False;
102            int readcnt;
103            int discardcnt;
104    
105          in_uint8s(in, 14);      /* flags, volume, pitch, UDP port */          in_uint8s(in, 14);      /* flags, volume, pitch, UDP port */
106          in_uint16_le(in, in_format_count);          in_uint16_le(in, in_format_count);
107          in_uint8s(in, 4);       /* pad, status, pad */          in_uint8s(in, 4);       /* pad, status, pad */
108    
109            if (current_driver->wave_out_open())
110            {
111                    current_driver->wave_out_close();
112                    device_available = True;
113            }
114    
115          format_count = 0;          format_count = 0;
116          if (s_check_rem(in, 18*in_format_count))          if (s_check_rem(in, 18 * in_format_count))
117          {          {
118                  for (i = 0; i < in_format_count; i++)                  for (i = 0; i < in_format_count; i++)
119                  {                  {
# Line 97  rdpsnd_process_negotiate(STREAM in) Line 126  rdpsnd_process_negotiate(STREAM in)
126                          in_uint16_le(in, format->wBitsPerSample);                          in_uint16_le(in, format->wBitsPerSample);
127                          in_uint16_le(in, format->cbSize);                          in_uint16_le(in, format->cbSize);
128    
129                          if (wave_out_format_supported(format))                          /* read in the buffer of unknown use */
130                            readcnt = format->cbSize;
131                            discardcnt = 0;
132                            if (format->cbSize > MAX_CBSIZE)
133                            {
134                                    fprintf(stderr, "cbSize too large for buffer: %d\n",
135                                            format->cbSize);
136                                    readcnt = MAX_CBSIZE;
137                                    discardcnt = format->cbSize - MAX_CBSIZE;
138                            }
139                            in_uint8a(in, format->cb, readcnt);
140                            in_uint8s(in, discardcnt);
141    
142                            if (device_available && current_driver->wave_out_format_supported(format))
143                          {                          {
144                                  format_count++;                                  format_count++;
145                                  if (format_count == MAX_FORMATS)                                  if (format_count == MAX_FORMATS)
# Line 106  rdpsnd_process_negotiate(STREAM in) Line 148  rdpsnd_process_negotiate(STREAM in)
148                  }                  }
149          }          }
150    
151          out = rdpsnd_init_packet(RDPSND_NEGOTIATE | 0x200, 20 + 18*format_count);          out = rdpsnd_init_packet(RDPSND_NEGOTIATE | 0x200, 20 + 18 * format_count);
152          out_uint32_le(out, 3);          /* flags */          out_uint32_le(out, 3);  /* flags */
153          out_uint32(out, 0xffffffff);    /* volume */          out_uint32(out, 0xffffffff);    /* volume */
154          out_uint32(out, 0);             /* pitch */          out_uint32(out, 0);     /* pitch */
155          out_uint16(out, 0);             /* UDP port */          out_uint16(out, 0);     /* UDP port */
156    
157          out_uint16_le(out, format_count);          out_uint16_le(out, format_count);
158          out_uint8(out, 0x95);           /* pad? */          out_uint8(out, 0x95);   /* pad? */
159          out_uint16_le(out, 2);          /* status */          out_uint16_le(out, 2);  /* status */
160          out_uint8(out, 0x77);           /* pad? */          out_uint8(out, 0x77);   /* pad? */
161    
162          for (i = 0; i < format_count; i++)          for (i = 0; i < format_count; i++)
163          {          {
# Line 126  rdpsnd_process_negotiate(STREAM in) Line 168  rdpsnd_process_negotiate(STREAM in)
168                  out_uint32_le(out, format->nAvgBytesPerSec);                  out_uint32_le(out, format->nAvgBytesPerSec);
169                  out_uint16_le(out, format->nBlockAlign);                  out_uint16_le(out, format->nBlockAlign);
170                  out_uint16_le(out, format->wBitsPerSample);                  out_uint16_le(out, format->wBitsPerSample);
171                  out_uint16(out, 0); /* cbSize */                  out_uint16(out, 0);     /* cbSize */
172          }          }
173    
174          s_mark_end(out);          s_mark_end(out);
175          rdpsnd_send(out);          rdpsnd_send(out);
176  }  }
177    
178  void  static void
179  rdpsnd_process_unknown6(STREAM in)  rdpsnd_process_ping(STREAM in)
180  {  {
181          uint16 unknown1, unknown2;          uint16 tick;
182          STREAM out;          STREAM out;
183    
184          /* in_uint8s(in, 4); unknown */          in_uint16_le(in, tick);
185          in_uint16_le(in, unknown1);  
186          in_uint16_le(in, unknown2);          out = rdpsnd_init_packet(RDPSND_PING | 0x2300, 4);
187            out_uint16_le(out, tick);
188          out = rdpsnd_init_packet(RDPSND_UNKNOWN6 | 0x2300, 4);          out_uint16_le(out, 0);
         out_uint16_le(out, unknown1);  
         out_uint16_le(out, unknown2);  
189          s_mark_end(out);          s_mark_end(out);
190          rdpsnd_send(out);          rdpsnd_send(out);
191  }  }
192    
193  void  static void
194  rdpsnd_process(STREAM s)  rdpsnd_process(STREAM s)
195  {  {
196          uint8 type;          uint8 type;
197          uint16 datalen;          uint16 datalen;
198            uint32 volume;
199          static uint16 tick, format;          static uint16 tick, format;
200          static uint8 packet_index;          static uint8 packet_index;
201          static BOOL awaiting_data_packet;          static BOOL awaiting_data_packet;
202            static unsigned char missing_bytes[4] = { 0, 0, 0, 0 };
203    
204  #ifdef RDPSND_DEBUG  #ifdef RDPSND_DEBUG
205          printf("RDPSND recv:\n");          printf("RDPSND recv:\n");
206          hexdump(s->p, s->end-s->p);          hexdump(s->p, s->end - s->p);
207  #endif  #endif
208    
209          if (awaiting_data_packet)          if (awaiting_data_packet)
# Line 174  rdpsnd_process(STREAM s) Line 216  rdpsnd_process(STREAM s)
216    
217                  if (!device_open || (format != current_format))                  if (!device_open || (format != current_format))
218                  {                  {
219                          if (!device_open && !wave_out_open())                          if (!device_open && !current_driver->wave_out_open())
220                          {                          {
221                                  rdpsnd_send_completion(tick, packet_index);                                  rdpsnd_send_completion(tick, packet_index);
222                                  return;                                  return;
223                          }                          }
224                          if (!wave_out_set_format(&formats[format]))                          if (!current_driver->wave_out_set_format(&formats[format]))
225                          {                          {
226                                  rdpsnd_send_completion(tick, packet_index);                                  rdpsnd_send_completion(tick, packet_index);
227                                  wave_out_close();                                  current_driver->wave_out_close();
228                                  device_open = False;                                  device_open = False;
229                                  return;                                  return;
230                          }                          }
# Line 190  rdpsnd_process(STREAM s) Line 232  rdpsnd_process(STREAM s)
232                          current_format = format;                          current_format = format;
233                  }                  }
234    
235                  wave_out_write(s, tick, packet_index);                  /* Insert the 4 missing bytes retrieved from last RDPSND_WRITE */
236                    memcpy(s->data, missing_bytes, 4);
237    
238                    rdpsnd_queue_write(rdpsnd_dsp_process
239                                       (s, current_driver, &formats[current_format]), tick,
240                                       packet_index);
241                  awaiting_data_packet = False;                  awaiting_data_packet = False;
242                  return;                  return;
243          }          }
244    
245          in_uint8(s, type);          in_uint8(s, type);
246          in_uint8s(s, 1); /* unknown? */          in_uint8s(s, 1);        /* unknown? */
247          in_uint16_le(s, datalen);          in_uint16_le(s, datalen);
248    
249          switch (type)          switch (type)
250          {          {
251          case RDPSND_WRITE:                  case RDPSND_WRITE:
252                  in_uint16_le(s, tick);                          in_uint16_le(s, tick);
253                  in_uint16_le(s, format);                          in_uint16_le(s, format);
254                  in_uint8(s, packet_index);                          in_uint8(s, packet_index);
255                  awaiting_data_packet = True;                          /* Here are our lost bytes, but why? */
256                  break;                          memcpy(missing_bytes, s->end - 4, 4);
257          case RDPSND_CLOSE:                          awaiting_data_packet = True;
258                  wave_out_close();                          break;
259                  device_open = False;                  case RDPSND_CLOSE:
260                  break;                          current_driver->wave_out_close();
261          case RDPSND_NEGOTIATE:                          device_open = False;
262                  rdpsnd_process_negotiate(s);                          break;
263                  break;                  case RDPSND_NEGOTIATE:
264          case RDPSND_UNKNOWN6:                          rdpsnd_process_negotiate(s);
265                  rdpsnd_process_unknown6(s);                          break;
266                  break;                  case RDPSND_PING:
267          case RDPSND_SET_VOLUME:                          rdpsnd_process_ping(s);
268                  /* uint32 volume */                          break;
269                  break;                  case RDPSND_SET_VOLUME:
270          default:                          in_uint32(s, volume);
271                  unimpl("RDPSND packet type %d\n", type);                          if (device_open)
272                  break;                          {
273                                    current_driver->wave_out_volume((volume & 0xffff),
274                                                                    (volume & 0xffff0000) >> 16);
275                            }
276                            break;
277                    default:
278                            unimpl("RDPSND packet type %d\n", type);
279                            break;
280            }
281    }
282    
283    static BOOL
284    rdpsnd_auto_open(void)
285    {
286            static BOOL failed = False;
287    
288            if (!failed)
289            {
290                    struct audio_driver *auto_driver = current_driver;
291    
292                    current_driver = drivers;
293                    while (current_driver != NULL)
294                    {
295                            DEBUG(("trying %s...\n", current_driver->name));
296                            if (current_driver->wave_out_open())
297                            {
298                                    DEBUG(("selected %s\n", current_driver->name));
299                                    return True;
300                            }
301                            g_dsp_fd = 0;
302                            current_driver = current_driver->next;
303                    }
304    
305                    warning("no working audio-driver found\n");
306                    failed = True;
307                    current_driver = auto_driver;
308          }          }
309    
310            return False;
311    }
312    
313    static void
314    rdpsnd_register_drivers(char *options)
315    {
316            struct audio_driver **reg;
317    
318            /* The order of registrations define the probe-order
319               when opening the device for the first time */
320            reg = &drivers;
321    #if defined(RDPSND_ALSA)
322            *reg = alsa_register(options);
323            assert(*reg);
324            reg = &((*reg)->next);
325    #endif
326    #if defined(RDPSND_SUN)
327            *reg = sun_register(options);
328            assert(*reg);
329            reg = &((*reg)->next);
330    #endif
331    #if defined(RDPSND_OSS)
332            *reg = oss_register(options);
333            assert(*reg);
334            reg = &((*reg)->next);
335    #endif
336    #if defined(RDPSND_SGI)
337            *reg = sgi_register(options);
338            assert(*reg);
339            reg = &((*reg)->next);
340    #endif
341    #if defined(RDPSND_LIBAO)
342            *reg = libao_register(options);
343            assert(*reg);
344            reg = &((*reg)->next);
345    #endif
346            *reg = NULL;
347  }  }
348    
349  BOOL  BOOL
350  rdpsnd_init(void)  rdpsnd_init(char *optarg)
351  {  {
352            static struct audio_driver auto_driver;
353            struct audio_driver *pos;
354            char *driver = NULL, *options = NULL;
355    
356            drivers = NULL;
357    
358          rdpsnd_channel =          rdpsnd_channel =
359                  channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,                  channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
360                                   rdpsnd_process);                                   rdpsnd_process);
361          return (rdpsnd_channel != NULL);  
362            if (rdpsnd_channel == NULL)
363            {
364                    error("channel_register\n");
365                    return False;
366            }
367    
368            rdpsnd_queue_init();
369    
370            if (optarg != NULL && strlen(optarg) > 0)
371            {
372                    driver = options = optarg;
373    
374                    while (*options != '\0' && *options != ':')
375                            options++;
376    
377                    if (*options == ':')
378                    {
379                            *options = '\0';
380                            options++;
381                    }
382    
383                    if (*options == '\0')
384                            options = NULL;
385            }
386    
387            rdpsnd_register_drivers(options);
388    
389            if (!driver)
390            {
391                    auto_driver.wave_out_open = &rdpsnd_auto_open;
392                    current_driver = &auto_driver;
393                    return True;
394            }
395    
396            pos = drivers;
397            while (pos != NULL)
398            {
399                    if (!strcmp(pos->name, driver))
400                    {
401                            DEBUG(("selected %s\n", pos->name));
402                            current_driver = pos;
403                            return True;
404                    }
405                    pos = pos->next;
406            }
407            return False;
408    }
409    
410    void
411    rdpsnd_show_help(void)
412    {
413            struct audio_driver *pos;
414    
415            rdpsnd_register_drivers(NULL);
416    
417            pos = drivers;
418            while (pos != NULL)
419            {
420                    fprintf(stderr, "                     %s:\t%s\n", pos->name, pos->description);
421                    pos = pos->next;
422            }
423    }
424    
425    void
426    rdpsnd_play(void)
427    {
428            current_driver->wave_out_play();
429    }
430    
431    void
432    rdpsnd_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
433    {
434            long next_pending;
435    
436            if (g_dsp_busy)
437            {
438                    FD_SET(g_dsp_fd, wfds);
439                    *n = (g_dsp_fd > *n) ? g_dsp_fd : *n;
440            }
441    
442            next_pending = rdpsnd_queue_next_completion();
443            if (next_pending >= 0)
444            {
445                    long cur_timeout;
446    
447                    cur_timeout = tv->tv_sec * 1000000 + tv->tv_usec;
448                    if (cur_timeout > next_pending)
449                    {
450                            tv->tv_sec = next_pending / 1000000;
451                            tv->tv_usec = next_pending % 1000000;
452                    }
453            }
454    }
455    
456    void
457    rdpsnd_check_fds(fd_set * rfds, fd_set * wfds)
458    {
459            rdpsnd_queue_complete_pending();
460    
461            if (g_dsp_busy && FD_ISSET(g_dsp_fd, wfds))
462                    rdpsnd_play();
463    }
464    
465    static void
466    rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)
467    {
468            struct audio_packet *packet = &packet_queue[queue_hi];
469            unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
470    
471            if (next_hi == queue_pending)
472            {
473                    error("No space to queue audio packet\n");
474                    return;
475            }
476    
477            queue_hi = next_hi;
478    
479            packet->s = *s;
480            packet->tick = tick;
481            packet->index = index;
482    
483            gettimeofday(&packet->arrive_tv, NULL);
484    
485            if (!g_dsp_busy)
486                    current_driver->wave_out_play();
487    }
488    
489    struct audio_packet *
490    rdpsnd_queue_current_packet(void)
491    {
492            return &packet_queue[queue_lo];
493    }
494    
495    BOOL
496    rdpsnd_queue_empty(void)
497    {
498            return (queue_lo == queue_hi);
499    }
500    
501    static void
502    rdpsnd_queue_init(void)
503    {
504            queue_pending = queue_lo = queue_hi = 0;
505    }
506    
507    void
508    rdpsnd_queue_next(unsigned long completed_in_us)
509    {
510            struct audio_packet *packet;
511    
512            assert(!rdpsnd_queue_empty());
513    
514            packet = &packet_queue[queue_lo];
515    
516            gettimeofday(&packet->completion_tv, NULL);
517    
518            packet->completion_tv.tv_usec += completed_in_us;
519            packet->completion_tv.tv_sec += packet->completion_tv.tv_usec / 1000000;
520            packet->completion_tv.tv_usec %= 1000000;
521    
522            queue_lo = (queue_lo + 1) % MAX_QUEUE;
523    
524            rdpsnd_queue_complete_pending();
525    }
526    
527    int
528    rdpsnd_queue_next_tick(void)
529    {
530            if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
531            {
532                    return packet_queue[(queue_lo + 1) % MAX_QUEUE].tick;
533            }
534            else
535            {
536                    return (packet_queue[queue_lo].tick + 65535) % 65536;
537            }
538    }
539    
540    static void
541    rdpsnd_queue_complete_pending(void)
542    {
543            struct timeval now;
544            long elapsed;
545            struct audio_packet *packet;
546    
547            gettimeofday(&now, NULL);
548    
549            while (queue_pending != queue_lo)
550            {
551                    packet = &packet_queue[queue_pending];
552    
553                    if (now.tv_sec < packet->completion_tv.tv_sec)
554                            break;
555    
556                    if ((now.tv_sec == packet->completion_tv.tv_sec) &&
557                        (now.tv_usec < packet->completion_tv.tv_usec))
558                            break;
559    
560                    elapsed = (packet->completion_tv.tv_sec - packet->arrive_tv.tv_sec) * 1000000 +
561                            (packet->completion_tv.tv_usec - packet->arrive_tv.tv_usec);
562                    elapsed /= 1000;
563    
564                    xfree(packet->s.data);
565                    rdpsnd_send_completion((packet->tick + elapsed) % 65536, packet->index);
566                    queue_pending = (queue_pending + 1) % MAX_QUEUE;
567            }
568    }
569    
570    static long
571    rdpsnd_queue_next_completion(void)
572    {
573            struct audio_packet *packet;
574            long remaining;
575            struct timeval now;
576    
577            if (queue_pending == queue_lo)
578                    return -1;
579    
580            gettimeofday(&now, NULL);
581    
582            packet = &packet_queue[queue_pending];
583    
584            remaining = (packet->completion_tv.tv_sec - now.tv_sec) * 1000000 +
585                    (packet->completion_tv.tv_usec - now.tv_usec);
586    
587            if (remaining < 0)
588                    return 0;
589    
590            return remaining;
591  }  }

Legend:
Removed from v.474  
changed lines
  Added in v.1339

  ViewVC Help
Powered by ViewVC 1.1.26