/[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 1265 by stargo, Sun Sep 17 20:06:37 2006 UTC revision 1342 by ossman_, Wed Dec 6 13:29:42 2006 UTC
# 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"  #include "rdpsnd.h"
26  #include "rdpsnd_dsp.h"  #include "rdpsnd_dsp.h"
# Line 28  Line 30 
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_SERVERTICK       6  #define RDPSND_PING                     6
34  #define RDPSND_NEGOTIATE        7  #define RDPSND_NEGOTIATE        7
35    
36  #define MAX_FORMATS             10  #define MAX_FORMATS             10
# Line 45  static BOOL device_open; Line 47  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;  unsigned int queue_hi, queue_lo, queue_pending;
51  struct audio_packet packet_queue[MAX_QUEUE];  struct audio_packet packet_queue[MAX_QUEUE];
52    
53    static uint8 packet_opcode;
54    static struct stream packet;
55    
56  void (*wave_out_play) (void);  void (*wave_out_play) (void);
57    
58    static void rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index);
59    static void rdpsnd_queue_init(void);
60    static void rdpsnd_queue_complete_pending(void);
61    static long rdpsnd_queue_next_completion(void);
62    
63  static STREAM  static STREAM
64  rdpsnd_init_packet(uint16 type, uint16 size)  rdpsnd_init_packet(uint16 type, uint16 size)
65  {  {
# Line 72  rdpsnd_send(STREAM s) Line 82  rdpsnd_send(STREAM s)
82          channel_send(s, rdpsnd_channel);          channel_send(s, rdpsnd_channel);
83  }  }
84    
85  void  static void
86  rdpsnd_send_completion(uint16 tick, uint8 packet_index)  rdpsnd_send_completion(uint16 tick, uint8 packet_index)
87  {  {
88          STREAM s;          STREAM s;
# Line 88  rdpsnd_send_completion(uint16 tick, uint Line 98  rdpsnd_send_completion(uint16 tick, uint
98  static void  static void
99  rdpsnd_process_negotiate(STREAM in)  rdpsnd_process_negotiate(STREAM in)
100  {  {
101          unsigned int in_format_count, i;          uint16 in_format_count, i;
102            uint8 pad;
103            uint16 version;
104          WAVEFORMATEX *format;          WAVEFORMATEX *format;
105          STREAM out;          STREAM out;
106          BOOL device_available = False;          BOOL device_available = False;
107          int readcnt;          int readcnt;
108          int discardcnt;          int discardcnt;
109    
110          in_uint8s(in, 14);      /* flags, volume, pitch, UDP port */          in_uint8s(in, 14);      /* initial bytes not valid from server */
111          in_uint16_le(in, in_format_count);          in_uint16_le(in, in_format_count);
112          in_uint8s(in, 4);       /* pad, status, pad */          in_uint8(in, pad);
113            in_uint16_le(in, version);
114            in_uint8s(in, 1);       /* padding */
115    
116          if (current_driver->wave_out_open())          if (current_driver->wave_out_open())
117          {          {
# Line 148  rdpsnd_process_negotiate(STREAM in) Line 162  rdpsnd_process_negotiate(STREAM in)
162          out_uint16(out, 0);     /* UDP port */          out_uint16(out, 0);     /* UDP port */
163    
164          out_uint16_le(out, format_count);          out_uint16_le(out, format_count);
165          out_uint8(out, 0x95);   /* pad? */          out_uint8(out, 0);      /* padding */
166          out_uint16_le(out, 2);  /* status */          out_uint16_le(out, 2);  /* version */
167          out_uint8(out, 0x77);   /* pad? */          out_uint8(out, 0);      /* padding */
168    
169          for (i = 0; i < format_count; i++)          for (i = 0; i < format_count; i++)
170          {          {
# Line 169  rdpsnd_process_negotiate(STREAM in) Line 183  rdpsnd_process_negotiate(STREAM in)
183  }  }
184    
185  static void  static void
186  rdpsnd_process_servertick(STREAM in)  rdpsnd_process_ping(STREAM in)
187  {  {
188          uint16 tick1, tick2;          uint16 tick;
189          STREAM out;          STREAM out;
190    
191          /* in_uint8s(in, 4); unknown */          in_uint16_le(in, tick);
192          in_uint16_le(in, tick1);  
193          in_uint16_le(in, tick2);          out = rdpsnd_init_packet(RDPSND_PING | 0x2300, 4);
194            out_uint16_le(out, tick);
195          out = rdpsnd_init_packet(RDPSND_SERVERTICK | 0x2300, 4);          out_uint16_le(out, 0);
         out_uint16_le(out, tick1);  
         out_uint16_le(out, tick2);  
196          s_mark_end(out);          s_mark_end(out);
197          rdpsnd_send(out);          rdpsnd_send(out);
198  }  }
199    
200  static void  static void
201  rdpsnd_process(STREAM s)  rdpsnd_process_packet(uint8 opcode, STREAM s)
202  {  {
203          uint8 type;          uint16 vol_left, vol_right;
         uint16 datalen;  
         uint32 volume;  
204          static uint16 tick, format;          static uint16 tick, format;
205          static uint8 packet_index;          static uint8 packet_index;
         static BOOL awaiting_data_packet;  
         static unsigned char missing_bytes[4] = { 0, 0, 0, 0 };  
206    
207  #ifdef RDPSND_DEBUG  #ifdef RDPSND_DEBUG
208          printf("RDPSND recv:\n");          printf("RDPSND recv:\n");
209          hexdump(s->p, s->end - s->p);          hexdump(s->p, s->end - s->p);
210  #endif  #endif
211    
212          if (awaiting_data_packet)          switch (opcode)
213          {          {
214                  if (format >= MAX_FORMATS)                  case RDPSND_WRITE:
215                  {                          in_uint16_le(s, tick);
216                          error("RDPSND: Invalid format index\n");                          in_uint16_le(s, format);
217                          return;                          in_uint8(s, packet_index);
218                  }                          in_uint8s(s, 3);
219    
220                  if (!device_open || (format != current_format))                          if (format >= MAX_FORMATS)
                 {  
                         if (!device_open && !current_driver->wave_out_open())  
221                          {                          {
222                                  rdpsnd_send_completion(tick, packet_index);                                  error("RDPSND: Invalid format index\n");
223                                  return;                                  break;
224                          }                          }
225                          if (!current_driver->wave_out_set_format(&formats[format]))  
226                            if (!device_open || (format != current_format))
227                          {                          {
228                                  rdpsnd_send_completion(tick, packet_index);                                  if (!device_open && !current_driver->wave_out_open())
229                                  current_driver->wave_out_close();                                  {
230                                  device_open = False;                                          rdpsnd_send_completion(tick, packet_index);
231                                  return;                                          break;
232                                    }
233                                    if (!current_driver->wave_out_set_format(&formats[format]))
234                                    {
235                                            rdpsnd_send_completion(tick, packet_index);
236                                            current_driver->wave_out_close();
237                                            device_open = False;
238                                            break;
239                                    }
240                                    device_open = True;
241                                    current_format = format;
242                          }                          }
                         device_open = True;  
                         current_format = format;  
                 }  
   
                 /* Insert the 4 missing bytes retrieved from last RDPSND_WRITE */  
                 memcpy(s->data, missing_bytes, 4);  
   
                 current_driver->  
                         wave_out_write(rdpsnd_dsp_process  
                                        (s, current_driver, &formats[current_format]), tick,  
                                        packet_index);  
                 awaiting_data_packet = False;  
                 return;  
         }  
   
         in_uint8(s, type);  
         in_uint8s(s, 1);        /* unknown? */  
         in_uint16_le(s, datalen);  
243    
244          switch (type)                          rdpsnd_queue_write(rdpsnd_dsp_process
245          {                                             (s->p, s->end - s->p, current_driver,
246                  case RDPSND_WRITE:                                              &formats[current_format]), tick, packet_index);
247                          in_uint16_le(s, tick);                          return;
                         in_uint16_le(s, format);  
                         in_uint8(s, packet_index);  
                         /* Here are our lost bytes, but why? */  
                         memcpy(missing_bytes, s->end - 4, 4);  
                         awaiting_data_packet = True;  
248                          break;                          break;
249                  case RDPSND_CLOSE:                  case RDPSND_CLOSE:
250                          current_driver->wave_out_close();                          current_driver->wave_out_close();
# Line 259  rdpsnd_process(STREAM s) Line 253  rdpsnd_process(STREAM s)
253                  case RDPSND_NEGOTIATE:                  case RDPSND_NEGOTIATE:
254                          rdpsnd_process_negotiate(s);                          rdpsnd_process_negotiate(s);
255                          break;                          break;
256                  case RDPSND_SERVERTICK:                  case RDPSND_PING:
257                          rdpsnd_process_servertick(s);                          rdpsnd_process_ping(s);
258                          break;                          break;
259                  case RDPSND_SET_VOLUME:                  case RDPSND_SET_VOLUME:
260                          in_uint32(s, volume);                          in_uint16_le(s, vol_left);
261                            in_uint16_le(s, vol_right);
262                          if (device_open)                          if (device_open)
263                          {                                  current_driver->wave_out_volume(vol_left, vol_right);
                                 current_driver->wave_out_volume((volume & 0xffff),  
                                                                 (volume & 0xffff0000) >> 16);  
                         }  
264                          break;                          break;
265                  default:                  default:
266                          unimpl("RDPSND packet type %d\n", type);                          unimpl("RDPSND packet type %x\n", opcode);
267                          break;                          break;
268          }          }
269  }  }
270    
271  BOOL  static void
272  rdpsnd_init(void)  rdpsnd_process(STREAM s)
273  {  {
274          rdpsnd_channel =          uint16 len;
275                  channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,  
276                                   rdpsnd_process);          while (!s_check_end(s))
277            {
278                    /* New packet */
279                    if (packet.size == 0)
280                    {
281                            if ((s->end - s->p) < 4)
282                            {
283                                    error("RDPSND: Split at packet header. Things will go south from here...\n");
284                                    return;
285                            }
286                            in_uint8(s, packet_opcode);
287                            in_uint8s(s, 1);        /* Padding */
288                            in_uint16_le(s, len);
289    
290                            packet.p = packet.data;
291                            packet.end = packet.data + len;
292                            packet.size = len;
293                    }
294                    else
295                    {
296                            len = MIN(s->end - s->p, packet.end - packet.p);
297    
298                            /* Microsoft's server is so broken it's not even funny... */
299                            if (packet_opcode == RDPSND_WRITE)
300                            {
301                                    if ((packet.p - packet.data) < 12)
302                                            len = MIN(len, 12 - (packet.p - packet.data));
303                                    else if ((packet.p - packet.data) == 12)
304                                    {
305                                            in_uint8s(s, 4);
306                                            len -= 4;
307                                    }
308                            }
309    
310          return (rdpsnd_channel != NULL);                          in_uint8a(s, packet.p, len);
311                            packet.p += len;
312                    }
313    
314                    /* Packet fully assembled */
315                    if (packet.p == packet.end)
316                    {
317                            packet.p = packet.data;
318                            rdpsnd_process_packet(packet_opcode, &packet);
319                            packet.size = 0;
320                    }
321            }
322  }  }
323    
324  BOOL  static BOOL
325  rdpsnd_auto_open(void)  rdpsnd_auto_open(void)
326  {  {
327          current_driver = drivers;          static BOOL failed = False;
328          while (current_driver != NULL)  
329            if (!failed)
330          {          {
331                  DEBUG(("trying %s...\n", current_driver->name));                  struct audio_driver *auto_driver = current_driver;
332                  if (current_driver->wave_out_open())  
333                    current_driver = drivers;
334                    while (current_driver != NULL)
335                  {                  {
336                          DEBUG(("selected %s\n", current_driver->name));                          DEBUG(("trying %s...\n", current_driver->name));
337                          return True;                          if (current_driver->wave_out_open())
338                            {
339                                    DEBUG(("selected %s\n", current_driver->name));
340                                    return True;
341                            }
342                            g_dsp_fd = 0;
343                            current_driver = current_driver->next;
344                  }                  }
                 g_dsp_fd = 0;  
                 current_driver = current_driver->next;  
         }  
345    
346          warning("no working audio-driver found\n");                  warning("no working audio-driver found\n");
347                    failed = True;
348                    current_driver = auto_driver;
349            }
350    
351          return False;          return False;
352  }  }
353    
354  void  static void
355  rdpsnd_register_drivers(char *options)  rdpsnd_register_drivers(char *options)
356  {  {
357          struct audio_driver **reg;          struct audio_driver **reg;
# Line 317  rdpsnd_register_drivers(char *options) Line 361  rdpsnd_register_drivers(char *options)
361          reg = &drivers;          reg = &drivers;
362  #if defined(RDPSND_ALSA)  #if defined(RDPSND_ALSA)
363          *reg = alsa_register(options);          *reg = alsa_register(options);
364            assert(*reg);
365          reg = &((*reg)->next);          reg = &((*reg)->next);
366  #endif  #endif
367  #if defined(RDPSND_SUN)  #if defined(RDPSND_SUN)
368          *reg = sun_register(options);          *reg = sun_register(options);
369            assert(*reg);
370          reg = &((*reg)->next);          reg = &((*reg)->next);
371  #endif  #endif
372  #if defined(RDPSND_OSS)  #if defined(RDPSND_OSS)
373          *reg = oss_register(options);          *reg = oss_register(options);
374            assert(*reg);
375          reg = &((*reg)->next);          reg = &((*reg)->next);
376  #endif  #endif
377  #if defined(RDPSND_SGI)  #if defined(RDPSND_SGI)
378          *reg = sgi_register(options);          *reg = sgi_register(options);
379            assert(*reg);
380          reg = &((*reg)->next);          reg = &((*reg)->next);
381  #endif  #endif
382  #if defined(RDPSND_LIBAO)  #if defined(RDPSND_LIBAO)
383          *reg = libao_register(options);          *reg = libao_register(options);
384            assert(*reg);
385          reg = &((*reg)->next);          reg = &((*reg)->next);
386  #endif  #endif
387            *reg = NULL;
388  }  }
389    
390  BOOL  BOOL
391  rdpsnd_select_driver(char *driver, char *options)  rdpsnd_init(char *optarg)
392  {  {
393          static struct audio_driver auto_driver;          static struct audio_driver auto_driver;
394          struct audio_driver *pos;          struct audio_driver *pos;
395            char *driver = NULL, *options = NULL;
396    
397          drivers = NULL;          drivers = NULL;
398    
399            packet.data = xmalloc(65536);
400            packet.p = packet.end = packet.data;
401            packet.size = 0;
402    
403            rdpsnd_channel =
404                    channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
405                                     rdpsnd_process);
406    
407            if (rdpsnd_channel == NULL)
408            {
409                    error("channel_register\n");
410                    return False;
411            }
412    
413            rdpsnd_queue_init();
414    
415            if (optarg != NULL && strlen(optarg) > 0)
416            {
417                    driver = options = optarg;
418    
419                    while (*options != '\0' && *options != ':')
420                            options++;
421    
422                    if (*options == ':')
423                    {
424                            *options = '\0';
425                            options++;
426                    }
427    
428                    if (*options == '\0')
429                            options = NULL;
430            }
431    
432          rdpsnd_register_drivers(options);          rdpsnd_register_drivers(options);
433    
434          if (!driver)          if (!driver)
# Line 382  rdpsnd_show_help(void) Line 467  rdpsnd_show_help(void)
467          }          }
468  }  }
469    
470  inline void  void
471  rdpsnd_play(void)  rdpsnd_play(void)
472  {  {
473          current_driver->wave_out_play();          current_driver->wave_out_play();
474  }  }
475    
476  void  void
477    rdpsnd_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
478    {
479            long next_pending;
480    
481            if (g_dsp_busy)
482            {
483                    FD_SET(g_dsp_fd, wfds);
484                    *n = (g_dsp_fd > *n) ? g_dsp_fd : *n;
485            }
486    
487            next_pending = rdpsnd_queue_next_completion();
488            if (next_pending >= 0)
489            {
490                    long cur_timeout;
491    
492                    cur_timeout = tv->tv_sec * 1000000 + tv->tv_usec;
493                    if (cur_timeout > next_pending)
494                    {
495                            tv->tv_sec = next_pending / 1000000;
496                            tv->tv_usec = next_pending % 1000000;
497                    }
498            }
499    }
500    
501    void
502    rdpsnd_check_fds(fd_set * rfds, fd_set * wfds)
503    {
504            rdpsnd_queue_complete_pending();
505    
506            if (g_dsp_busy && FD_ISSET(g_dsp_fd, wfds))
507                    rdpsnd_play();
508    }
509    
510    static void
511  rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)  rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)
512  {  {
513          struct audio_packet *packet = &packet_queue[queue_hi];          struct audio_packet *packet = &packet_queue[queue_hi];
514          unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;          unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
515    
516          if (next_hi == queue_lo)          if (next_hi == queue_pending)
517          {          {
518                  error("No space to queue audio packet\n");                  error("No space to queue audio packet\n");
519                  return;                  return;
# Line 406  rdpsnd_queue_write(STREAM s, uint16 tick Line 525  rdpsnd_queue_write(STREAM s, uint16 tick
525          packet->tick = tick;          packet->tick = tick;
526          packet->index = index;          packet->index = index;
527    
528            gettimeofday(&packet->arrive_tv, NULL);
529    
530          if (!g_dsp_busy)          if (!g_dsp_busy)
531                  current_driver->wave_out_play();                  current_driver->wave_out_play();
532  }  }
533    
534  inline struct audio_packet *  struct audio_packet *
535  rdpsnd_queue_current_packet(void)  rdpsnd_queue_current_packet(void)
536  {  {
537          return &packet_queue[queue_lo];          return &packet_queue[queue_lo];
538  }  }
539    
540  inline BOOL  BOOL
541  rdpsnd_queue_empty(void)  rdpsnd_queue_empty(void)
542  {  {
543          return (queue_lo == queue_hi);          return (queue_lo == queue_hi);
544  }  }
545    
546  inline void  static void
547  rdpsnd_queue_init(void)  rdpsnd_queue_init(void)
548  {  {
549          queue_lo = queue_hi = 0;          queue_pending = queue_lo = queue_hi = 0;
550  }  }
551    
552  inline void  void
553  rdpsnd_queue_next(void)  rdpsnd_queue_next(unsigned long completed_in_us)
554  {  {
555          xfree(packet_queue[queue_lo].s.data);          struct audio_packet *packet;
556    
557            assert(!rdpsnd_queue_empty());
558    
559            packet = &packet_queue[queue_lo];
560    
561            gettimeofday(&packet->completion_tv, NULL);
562    
563            packet->completion_tv.tv_usec += completed_in_us;
564            packet->completion_tv.tv_sec += packet->completion_tv.tv_usec / 1000000;
565            packet->completion_tv.tv_usec %= 1000000;
566    
567          queue_lo = (queue_lo + 1) % MAX_QUEUE;          queue_lo = (queue_lo + 1) % MAX_QUEUE;
568    
569            rdpsnd_queue_complete_pending();
570  }  }
571    
572  inline int  int
573  rdpsnd_queue_next_tick(void)  rdpsnd_queue_next_tick(void)
574  {  {
575          if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)          if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
# Line 447  rdpsnd_queue_next_tick(void) Line 581  rdpsnd_queue_next_tick(void)
581                  return (packet_queue[queue_lo].tick + 65535) % 65536;                  return (packet_queue[queue_lo].tick + 65535) % 65536;
582          }          }
583  }  }
584    
585    static void
586    rdpsnd_queue_complete_pending(void)
587    {
588            struct timeval now;
589            long elapsed;
590            struct audio_packet *packet;
591    
592            gettimeofday(&now, NULL);
593    
594            while (queue_pending != queue_lo)
595            {
596                    packet = &packet_queue[queue_pending];
597    
598                    if (now.tv_sec < packet->completion_tv.tv_sec)
599                            break;
600    
601                    if ((now.tv_sec == packet->completion_tv.tv_sec) &&
602                        (now.tv_usec < packet->completion_tv.tv_usec))
603                            break;
604    
605                    elapsed = (packet->completion_tv.tv_sec - packet->arrive_tv.tv_sec) * 1000000 +
606                            (packet->completion_tv.tv_usec - packet->arrive_tv.tv_usec);
607                    elapsed /= 1000;
608    
609                    xfree(packet->s.data);
610                    rdpsnd_send_completion((packet->tick + elapsed) % 65536, packet->index);
611                    queue_pending = (queue_pending + 1) % MAX_QUEUE;
612            }
613    }
614    
615    static long
616    rdpsnd_queue_next_completion(void)
617    {
618            struct audio_packet *packet;
619            long remaining;
620            struct timeval now;
621    
622            if (queue_pending == queue_lo)
623                    return -1;
624    
625            gettimeofday(&now, NULL);
626    
627            packet = &packet_queue[queue_pending];
628    
629            remaining = (packet->completion_tv.tv_sec - now.tv_sec) * 1000000 +
630                    (packet->completion_tv.tv_usec - now.tv_usec);
631    
632            if (remaining < 0)
633                    return 0;
634    
635            return remaining;
636    }

Legend:
Removed from v.1265  
changed lines
  Added in v.1342

  ViewVC Help
Powered by ViewVC 1.1.26