/[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 1340 by ossman_, Wed Dec 6 13:11:35 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;
# Line 49  rdpsnd_init_packet(uint16 type, uint16 s Line 68  rdpsnd_init_packet(uint16 type, uint16 s
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
# Line 60  rdpsnd_send(STREAM s) Line 79  rdpsnd_send(STREAM s)
79          channel_send(s, rdpsnd_channel);          channel_send(s, rdpsnd_channel);
80  }  }
81    
82  void  static void
83  rdpsnd_send_completion(uint16 tick, uint8 packet_index)  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;          uint16 in_format_count, i;
99            uint8 pad;
100            uint16 version;
101          WAVEFORMATEX *format;          WAVEFORMATEX *format;
102          STREAM out;          STREAM out;
103          BOOL device_available = False;          BOOL device_available = False;
104          int readcnt;          int readcnt;
105          int discardcnt;          int discardcnt;
106    
107          in_uint8s(in, 14);      /* flags, volume, pitch, UDP port */          in_uint8s(in, 14);      /* initial bytes not valid from server */
108          in_uint16_le(in, in_format_count);          in_uint16_le(in, in_format_count);
109          in_uint8s(in, 4);       /* pad, status, pad */          in_uint8(in, pad);
110            in_uint16_le(in, version);
111            in_uint8s(in, 1);       /* padding */
112    
113          if (wave_out_open())          if (current_driver->wave_out_open())
114          {          {
115                  wave_out_close();                  current_driver->wave_out_close();
116                  device_available = True;                  device_available = True;
117          }          }
118    
# Line 120  rdpsnd_process_negotiate(STREAM in) Line 143  rdpsnd_process_negotiate(STREAM in)
143                          in_uint8a(in, format->cb, readcnt);                          in_uint8a(in, format->cb, readcnt);
144                          in_uint8s(in, discardcnt);                          in_uint8s(in, discardcnt);
145    
146                          if (device_available && wave_out_format_supported(format))                          if (device_available && current_driver->wave_out_format_supported(format))
147                          {                          {
148                                  format_count++;                                  format_count++;
149                                  if (format_count == MAX_FORMATS)                                  if (format_count == MAX_FORMATS)
# Line 136  rdpsnd_process_negotiate(STREAM in) Line 159  rdpsnd_process_negotiate(STREAM in)
159          out_uint16(out, 0);     /* UDP port */          out_uint16(out, 0);     /* UDP port */
160    
161          out_uint16_le(out, format_count);          out_uint16_le(out, format_count);
162          out_uint8(out, 0x95);   /* pad? */          out_uint8(out, 0);      /* padding */
163          out_uint16_le(out, 2);  /* status */          out_uint16_le(out, 2);  /* version */
164          out_uint8(out, 0x77);   /* pad? */          out_uint8(out, 0);      /* padding */
165    
166          for (i = 0; i < format_count; i++)          for (i = 0; i < format_count; i++)
167          {          {
# Line 156  rdpsnd_process_negotiate(STREAM in) Line 179  rdpsnd_process_negotiate(STREAM in)
179          rdpsnd_send(out);          rdpsnd_send(out);
180  }  }
181    
182  void  static void
183  rdpsnd_process_unknown6(STREAM in)  rdpsnd_process_ping(STREAM in)
184  {  {
185          uint16 unknown1, unknown2;          uint16 tick;
186          STREAM out;          STREAM out;
187    
188          /* in_uint8s(in, 4); unknown */          in_uint16_le(in, tick);
189          in_uint16_le(in, unknown1);  
190          in_uint16_le(in, unknown2);          out = rdpsnd_init_packet(RDPSND_PING | 0x2300, 4);
191            out_uint16_le(out, tick);
192          out = rdpsnd_init_packet(RDPSND_UNKNOWN6 | 0x2300, 4);          out_uint16_le(out, 0);
         out_uint16_le(out, unknown1);  
         out_uint16_le(out, unknown2);  
193          s_mark_end(out);          s_mark_end(out);
194          rdpsnd_send(out);          rdpsnd_send(out);
195  }  }
196    
197  void  static void
198  rdpsnd_process(STREAM s)  rdpsnd_process(STREAM s)
199  {  {
200          uint8 type;          uint8 type;
# Line 182  rdpsnd_process(STREAM s) Line 203  rdpsnd_process(STREAM s)
203          static uint16 tick, format;          static uint16 tick, format;
204          static uint8 packet_index;          static uint8 packet_index;
205          static BOOL awaiting_data_packet;          static BOOL awaiting_data_packet;
206            static unsigned char missing_bytes[4] = { 0, 0, 0, 0 };
207    
208  #ifdef RDPSND_DEBUG  #ifdef RDPSND_DEBUG
209          printf("RDPSND recv:\n");          printf("RDPSND recv:\n");
# Line 198  rdpsnd_process(STREAM s) Line 220  rdpsnd_process(STREAM s)
220    
221                  if (!device_open || (format != current_format))                  if (!device_open || (format != current_format))
222                  {                  {
223                          if (!device_open && !wave_out_open())                          if (!device_open && !current_driver->wave_out_open())
224                          {                          {
225                                  rdpsnd_send_completion(tick, packet_index);                                  rdpsnd_send_completion(tick, packet_index);
226                                  return;                                  return;
227                          }                          }
228                          if (!wave_out_set_format(&formats[format]))                          if (!current_driver->wave_out_set_format(&formats[format]))
229                          {                          {
230                                  rdpsnd_send_completion(tick, packet_index);                                  rdpsnd_send_completion(tick, packet_index);
231                                  wave_out_close();                                  current_driver->wave_out_close();
232                                  device_open = False;                                  device_open = False;
233                                  return;                                  return;
234                          }                          }
# Line 214  rdpsnd_process(STREAM s) Line 236  rdpsnd_process(STREAM s)
236                          current_format = format;                          current_format = format;
237                  }                  }
238    
239                  wave_out_write(s, tick, packet_index);                  /* Insert the 4 missing bytes retrieved from last RDPSND_WRITE */
240                    memcpy(s->data, missing_bytes, 4);
241    
242                    rdpsnd_queue_write(rdpsnd_dsp_process
243                                       (s, current_driver, &formats[current_format]), tick,
244                                       packet_index);
245                  awaiting_data_packet = False;                  awaiting_data_packet = False;
246                  return;                  return;
247          }          }
# Line 229  rdpsnd_process(STREAM s) Line 256  rdpsnd_process(STREAM s)
256                          in_uint16_le(s, tick);                          in_uint16_le(s, tick);
257                          in_uint16_le(s, format);                          in_uint16_le(s, format);
258                          in_uint8(s, packet_index);                          in_uint8(s, packet_index);
259                            /* Here are our lost bytes, but why? */
260                            memcpy(missing_bytes, s->end - 4, 4);
261                          awaiting_data_packet = True;                          awaiting_data_packet = True;
262                          break;                          break;
263                  case RDPSND_CLOSE:                  case RDPSND_CLOSE:
264                          wave_out_close();                          current_driver->wave_out_close();
265                          device_open = False;                          device_open = False;
266                          break;                          break;
267                  case RDPSND_NEGOTIATE:                  case RDPSND_NEGOTIATE:
268                          rdpsnd_process_negotiate(s);                          rdpsnd_process_negotiate(s);
269                          break;                          break;
270                  case RDPSND_UNKNOWN6:                  case RDPSND_PING:
271                          rdpsnd_process_unknown6(s);                          rdpsnd_process_ping(s);
272                          break;                          break;
273                  case RDPSND_SET_VOLUME:                  case RDPSND_SET_VOLUME:
274                          in_uint32(s, volume);                          in_uint32(s, volume);
275                          if (device_open)                          if (device_open)
276                          {                          {
277                                  wave_out_volume((volume & 0xffff), (volume & 0xffff0000) >> 16);                                  current_driver->wave_out_volume((volume & 0xffff),
278                                                                    (volume & 0xffff0000) >> 16);
279                          }                          }
280                          break;                          break;
281                  default:                  default:
# Line 254  rdpsnd_process(STREAM s) Line 284  rdpsnd_process(STREAM s)
284          }          }
285  }  }
286    
287    static BOOL
288    rdpsnd_auto_open(void)
289    {
290            static BOOL failed = False;
291    
292            if (!failed)
293            {
294                    struct audio_driver *auto_driver = current_driver;
295    
296                    current_driver = drivers;
297                    while (current_driver != NULL)
298                    {
299                            DEBUG(("trying %s...\n", current_driver->name));
300                            if (current_driver->wave_out_open())
301                            {
302                                    DEBUG(("selected %s\n", current_driver->name));
303                                    return True;
304                            }
305                            g_dsp_fd = 0;
306                            current_driver = current_driver->next;
307                    }
308    
309                    warning("no working audio-driver found\n");
310                    failed = True;
311                    current_driver = auto_driver;
312            }
313    
314            return False;
315    }
316    
317    static void
318    rdpsnd_register_drivers(char *options)
319    {
320            struct audio_driver **reg;
321    
322            /* The order of registrations define the probe-order
323               when opening the device for the first time */
324            reg = &drivers;
325    #if defined(RDPSND_ALSA)
326            *reg = alsa_register(options);
327            assert(*reg);
328            reg = &((*reg)->next);
329    #endif
330    #if defined(RDPSND_SUN)
331            *reg = sun_register(options);
332            assert(*reg);
333            reg = &((*reg)->next);
334    #endif
335    #if defined(RDPSND_OSS)
336            *reg = oss_register(options);
337            assert(*reg);
338            reg = &((*reg)->next);
339    #endif
340    #if defined(RDPSND_SGI)
341            *reg = sgi_register(options);
342            assert(*reg);
343            reg = &((*reg)->next);
344    #endif
345    #if defined(RDPSND_LIBAO)
346            *reg = libao_register(options);
347            assert(*reg);
348            reg = &((*reg)->next);
349    #endif
350            *reg = NULL;
351    }
352    
353  BOOL  BOOL
354  rdpsnd_init(void)  rdpsnd_init(char *optarg)
355  {  {
356            static struct audio_driver auto_driver;
357            struct audio_driver *pos;
358            char *driver = NULL, *options = NULL;
359    
360            drivers = NULL;
361    
362          rdpsnd_channel =          rdpsnd_channel =
363                  channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,                  channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
364                                   rdpsnd_process);                                   rdpsnd_process);
365          return (rdpsnd_channel != NULL);  
366            if (rdpsnd_channel == NULL)
367            {
368                    error("channel_register\n");
369                    return False;
370            }
371    
372            rdpsnd_queue_init();
373    
374            if (optarg != NULL && strlen(optarg) > 0)
375            {
376                    driver = options = optarg;
377    
378                    while (*options != '\0' && *options != ':')
379                            options++;
380    
381                    if (*options == ':')
382                    {
383                            *options = '\0';
384                            options++;
385                    }
386    
387                    if (*options == '\0')
388                            options = NULL;
389            }
390    
391            rdpsnd_register_drivers(options);
392    
393            if (!driver)
394            {
395                    auto_driver.wave_out_open = &rdpsnd_auto_open;
396                    current_driver = &auto_driver;
397                    return True;
398            }
399    
400            pos = drivers;
401            while (pos != NULL)
402            {
403                    if (!strcmp(pos->name, driver))
404                    {
405                            DEBUG(("selected %s\n", pos->name));
406                            current_driver = pos;
407                            return True;
408                    }
409                    pos = pos->next;
410            }
411            return False;
412    }
413    
414    void
415    rdpsnd_show_help(void)
416    {
417            struct audio_driver *pos;
418    
419            rdpsnd_register_drivers(NULL);
420    
421            pos = drivers;
422            while (pos != NULL)
423            {
424                    fprintf(stderr, "                     %s:\t%s\n", pos->name, pos->description);
425                    pos = pos->next;
426            }
427    }
428    
429    void
430    rdpsnd_play(void)
431    {
432            current_driver->wave_out_play();
433    }
434    
435    void
436    rdpsnd_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
437    {
438            long next_pending;
439    
440            if (g_dsp_busy)
441            {
442                    FD_SET(g_dsp_fd, wfds);
443                    *n = (g_dsp_fd > *n) ? g_dsp_fd : *n;
444            }
445    
446            next_pending = rdpsnd_queue_next_completion();
447            if (next_pending >= 0)
448            {
449                    long cur_timeout;
450    
451                    cur_timeout = tv->tv_sec * 1000000 + tv->tv_usec;
452                    if (cur_timeout > next_pending)
453                    {
454                            tv->tv_sec = next_pending / 1000000;
455                            tv->tv_usec = next_pending % 1000000;
456                    }
457            }
458    }
459    
460    void
461    rdpsnd_check_fds(fd_set * rfds, fd_set * wfds)
462    {
463            rdpsnd_queue_complete_pending();
464    
465            if (g_dsp_busy && FD_ISSET(g_dsp_fd, wfds))
466                    rdpsnd_play();
467    }
468    
469    static void
470    rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)
471    {
472            struct audio_packet *packet = &packet_queue[queue_hi];
473            unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
474    
475            if (next_hi == queue_pending)
476            {
477                    error("No space to queue audio packet\n");
478                    return;
479            }
480    
481            queue_hi = next_hi;
482    
483            packet->s = *s;
484            packet->tick = tick;
485            packet->index = index;
486    
487            gettimeofday(&packet->arrive_tv, NULL);
488    
489            if (!g_dsp_busy)
490                    current_driver->wave_out_play();
491    }
492    
493    struct audio_packet *
494    rdpsnd_queue_current_packet(void)
495    {
496            return &packet_queue[queue_lo];
497    }
498    
499    BOOL
500    rdpsnd_queue_empty(void)
501    {
502            return (queue_lo == queue_hi);
503    }
504    
505    static void
506    rdpsnd_queue_init(void)
507    {
508            queue_pending = queue_lo = queue_hi = 0;
509    }
510    
511    void
512    rdpsnd_queue_next(unsigned long completed_in_us)
513    {
514            struct audio_packet *packet;
515    
516            assert(!rdpsnd_queue_empty());
517    
518            packet = &packet_queue[queue_lo];
519    
520            gettimeofday(&packet->completion_tv, NULL);
521    
522            packet->completion_tv.tv_usec += completed_in_us;
523            packet->completion_tv.tv_sec += packet->completion_tv.tv_usec / 1000000;
524            packet->completion_tv.tv_usec %= 1000000;
525    
526            queue_lo = (queue_lo + 1) % MAX_QUEUE;
527    
528            rdpsnd_queue_complete_pending();
529    }
530    
531    int
532    rdpsnd_queue_next_tick(void)
533    {
534            if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
535            {
536                    return packet_queue[(queue_lo + 1) % MAX_QUEUE].tick;
537            }
538            else
539            {
540                    return (packet_queue[queue_lo].tick + 65535) % 65536;
541            }
542    }
543    
544    static void
545    rdpsnd_queue_complete_pending(void)
546    {
547            struct timeval now;
548            long elapsed;
549            struct audio_packet *packet;
550    
551            gettimeofday(&now, NULL);
552    
553            while (queue_pending != queue_lo)
554            {
555                    packet = &packet_queue[queue_pending];
556    
557                    if (now.tv_sec < packet->completion_tv.tv_sec)
558                            break;
559    
560                    if ((now.tv_sec == packet->completion_tv.tv_sec) &&
561                        (now.tv_usec < packet->completion_tv.tv_usec))
562                            break;
563    
564                    elapsed = (packet->completion_tv.tv_sec - packet->arrive_tv.tv_sec) * 1000000 +
565                            (packet->completion_tv.tv_usec - packet->arrive_tv.tv_usec);
566                    elapsed /= 1000;
567    
568                    xfree(packet->s.data);
569                    rdpsnd_send_completion((packet->tick + elapsed) % 65536, packet->index);
570                    queue_pending = (queue_pending + 1) % MAX_QUEUE;
571            }
572    }
573    
574    static long
575    rdpsnd_queue_next_completion(void)
576    {
577            struct audio_packet *packet;
578            long remaining;
579            struct timeval now;
580    
581            if (queue_pending == queue_lo)
582                    return -1;
583    
584            gettimeofday(&now, NULL);
585    
586            packet = &packet_queue[queue_pending];
587    
588            remaining = (packet->completion_tv.tv_sec - now.tv_sec) * 1000000 +
589                    (packet->completion_tv.tv_usec - now.tv_usec);
590    
591            if (remaining < 0)
592                    return 0;
593    
594            return remaining;
595  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26