/[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 499 by astrand, Wed Oct 15 14:01:32 2003 UTC revision 1342 by ossman_, Wed Dec 6 13:29:42 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    static uint8 packet_opcode;
54    static struct stream packet;
55    
56  STREAM  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
64  rdpsnd_init_packet(uint16 type, uint16 size)  rdpsnd_init_packet(uint16 type, uint16 size)
65  {  {
66          STREAM s;          STREAM s;
# Line 49  rdpsnd_init_packet(uint16 type, uint16 s Line 71  rdpsnd_init_packet(uint16 type, uint16 s
71          return s;          return s;
72  }  }
73    
74  void  static void
75  rdpsnd_send(STREAM s)  rdpsnd_send(STREAM s)
76  {  {
77  #ifdef RDPSND_DEBUG  #ifdef RDPSND_DEBUG
# Line 60  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;
89    
90          s = rdpsnd_init_packet(RDPSND_COMPLETION, 4);          s = rdpsnd_init_packet(RDPSND_COMPLETION, 4);
91          out_uint16_le(s, tick + 50);          out_uint16_le(s, tick);
92          out_uint8(s, packet_index);          out_uint8(s, packet_index);
93          out_uint8(s, 0);          out_uint8(s, 0);
94          s_mark_end(s);          s_mark_end(s);
95          rdpsnd_send(s);          rdpsnd_send(s);
96  }  }
97    
98  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 (wave_out_open())          if (current_driver->wave_out_open())
117          {          {
118                  wave_out_close();                  current_driver->wave_out_close();
119                  device_available = True;                  device_available = True;
120          }          }
121    
# Line 120  rdpsnd_process_negotiate(STREAM in) Line 146  rdpsnd_process_negotiate(STREAM in)
146                          in_uint8a(in, format->cb, readcnt);                          in_uint8a(in, format->cb, readcnt);
147                          in_uint8s(in, discardcnt);                          in_uint8s(in, discardcnt);
148    
149                          if (device_available && wave_out_format_supported(format))                          if (device_available && current_driver->wave_out_format_supported(format))
150                          {                          {
151                                  format_count++;                                  format_count++;
152                                  if (format_count == MAX_FORMATS)                                  if (format_count == MAX_FORMATS)
# Line 136  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 156  rdpsnd_process_negotiate(STREAM in) Line 182  rdpsnd_process_negotiate(STREAM in)
182          rdpsnd_send(out);          rdpsnd_send(out);
183  }  }
184    
185  void  static void
186  rdpsnd_process_unknown6(STREAM in)  rdpsnd_process_ping(STREAM in)
187  {  {
188          uint16 unknown1, unknown2;          uint16 tick;
189          STREAM out;          STREAM out;
190    
191          /* in_uint8s(in, 4); unknown */          in_uint16_le(in, tick);
192          in_uint16_le(in, unknown1);  
193          in_uint16_le(in, unknown2);          out = rdpsnd_init_packet(RDPSND_PING | 0x2300, 4);
194            out_uint16_le(out, tick);
195          out = rdpsnd_init_packet(RDPSND_UNKNOWN6 | 0x2300, 4);          out_uint16_le(out, 0);
         out_uint16_le(out, unknown1);  
         out_uint16_le(out, unknown2);  
196          s_mark_end(out);          s_mark_end(out);
197          rdpsnd_send(out);          rdpsnd_send(out);
198  }  }
199    
200  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;  
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 && !wave_out_open())  
221                          {                          {
222                                  rdpsnd_send_completion(tick, packet_index);                                  error("RDPSND: Invalid format index\n");
223                                  return;                                  break;
224                          }                          }
225                          if (!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                                  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;  
                 }  
   
                 wave_out_write(s, 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);  
                         awaiting_data_packet = True;  
248                          break;                          break;
249                  case RDPSND_CLOSE:                  case RDPSND_CLOSE:
250                          wave_out_close();                          current_driver->wave_out_close();
251                          device_open = False;                          device_open = False;
252                          break;                          break;
253                  case RDPSND_NEGOTIATE:                  case RDPSND_NEGOTIATE:
254                          rdpsnd_process_negotiate(s);                          rdpsnd_process_negotiate(s);
255                          break;                          break;
256                  case RDPSND_UNKNOWN6:                  case RDPSND_PING:
257                          rdpsnd_process_unknown6(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);
                                 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    static void
272    rdpsnd_process(STREAM s)
273    {
274            uint16 len;
275    
276            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                            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    static BOOL
325    rdpsnd_auto_open(void)
326    {
327            static BOOL failed = False;
328    
329            if (!failed)
330            {
331                    struct audio_driver *auto_driver = current_driver;
332    
333                    current_driver = drivers;
334                    while (current_driver != NULL)
335                    {
336                            DEBUG(("trying %s...\n", current_driver->name));
337                            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                    }
345    
346                    warning("no working audio-driver found\n");
347                    failed = True;
348                    current_driver = auto_driver;
349            }
350    
351            return False;
352    }
353    
354    static void
355    rdpsnd_register_drivers(char *options)
356    {
357            struct audio_driver **reg;
358    
359            /* The order of registrations define the probe-order
360               when opening the device for the first time */
361            reg = &drivers;
362    #if defined(RDPSND_ALSA)
363            *reg = alsa_register(options);
364            assert(*reg);
365            reg = &((*reg)->next);
366    #endif
367    #if defined(RDPSND_SUN)
368            *reg = sun_register(options);
369            assert(*reg);
370            reg = &((*reg)->next);
371    #endif
372    #if defined(RDPSND_OSS)
373            *reg = oss_register(options);
374            assert(*reg);
375            reg = &((*reg)->next);
376    #endif
377    #if defined(RDPSND_SGI)
378            *reg = sgi_register(options);
379            assert(*reg);
380            reg = &((*reg)->next);
381    #endif
382    #if defined(RDPSND_LIBAO)
383            *reg = libao_register(options);
384            assert(*reg);
385            reg = &((*reg)->next);
386    #endif
387            *reg = NULL;
388    }
389    
390  BOOL  BOOL
391  rdpsnd_init(void)  rdpsnd_init(char *optarg)
392  {  {
393            static struct audio_driver auto_driver;
394            struct audio_driver *pos;
395            char *driver = NULL, *options = NULL;
396    
397            drivers = NULL;
398    
399            packet.data = xmalloc(65536);
400            packet.p = packet.end = packet.data;
401            packet.size = 0;
402    
403          rdpsnd_channel =          rdpsnd_channel =
404                  channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,                  channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
405                                   rdpsnd_process);                                   rdpsnd_process);
406          return (rdpsnd_channel != NULL);  
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);
433    
434            if (!driver)
435            {
436                    auto_driver.wave_out_open = &rdpsnd_auto_open;
437                    current_driver = &auto_driver;
438                    return True;
439            }
440    
441            pos = drivers;
442            while (pos != NULL)
443            {
444                    if (!strcmp(pos->name, driver))
445                    {
446                            DEBUG(("selected %s\n", pos->name));
447                            current_driver = pos;
448                            return True;
449                    }
450                    pos = pos->next;
451            }
452            return False;
453    }
454    
455    void
456    rdpsnd_show_help(void)
457    {
458            struct audio_driver *pos;
459    
460            rdpsnd_register_drivers(NULL);
461    
462            pos = drivers;
463            while (pos != NULL)
464            {
465                    fprintf(stderr, "                     %s:\t%s\n", pos->name, pos->description);
466                    pos = pos->next;
467            }
468    }
469    
470    void
471    rdpsnd_play(void)
472    {
473            current_driver->wave_out_play();
474    }
475    
476    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)
512    {
513            struct audio_packet *packet = &packet_queue[queue_hi];
514            unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
515    
516            if (next_hi == queue_pending)
517            {
518                    error("No space to queue audio packet\n");
519                    return;
520            }
521    
522            queue_hi = next_hi;
523    
524            packet->s = *s;
525            packet->tick = tick;
526            packet->index = index;
527    
528            gettimeofday(&packet->arrive_tv, NULL);
529    
530            if (!g_dsp_busy)
531                    current_driver->wave_out_play();
532    }
533    
534    struct audio_packet *
535    rdpsnd_queue_current_packet(void)
536    {
537            return &packet_queue[queue_lo];
538    }
539    
540    BOOL
541    rdpsnd_queue_empty(void)
542    {
543            return (queue_lo == queue_hi);
544    }
545    
546    static void
547    rdpsnd_queue_init(void)
548    {
549            queue_pending = queue_lo = queue_hi = 0;
550    }
551    
552    void
553    rdpsnd_queue_next(unsigned long completed_in_us)
554    {
555            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;
568    
569            rdpsnd_queue_complete_pending();
570    }
571    
572    int
573    rdpsnd_queue_next_tick(void)
574    {
575            if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
576            {
577                    return packet_queue[(queue_lo + 1) % MAX_QUEUE].tick;
578            }
579            else
580            {
581                    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.499  
changed lines
  Added in v.1342

  ViewVC Help
Powered by ViewVC 1.1.26