/[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 1274 by stargo, Sun Oct 1 11:00:03 2006 UTC revision 1341 by ossman_, Wed Dec 6 13:18:36 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  void (*wave_out_play) (void);  void (*wave_out_play) (void);
54    
55    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  static STREAM
61  rdpsnd_init_packet(uint16 type, uint16 size)  rdpsnd_init_packet(uint16 type, uint16 size)
62  {  {
# Line 72  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;
# Line 88  rdpsnd_send_completion(uint16 tick, uint Line 95  rdpsnd_send_completion(uint16 tick, uint
95  static 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 (current_driver->wave_out_open())          if (current_driver->wave_out_open())
114          {          {
# Line 148  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 169  rdpsnd_process_negotiate(STREAM in) Line 180  rdpsnd_process_negotiate(STREAM in)
180  }  }
181    
182  static void  static void
183  rdpsnd_process_servertick(STREAM in)  rdpsnd_process_ping(STREAM in)
184  {  {
185          uint16 tick1, tick2;          uint16 tick;
186          STREAM out;          STREAM out;
187    
188          /* in_uint8s(in, 4); unknown */          in_uint16_le(in, tick);
189          in_uint16_le(in, tick1);  
190          in_uint16_le(in, tick2);          out = rdpsnd_init_packet(RDPSND_PING | 0x2300, 4);
191            out_uint16_le(out, tick);
192          out = rdpsnd_init_packet(RDPSND_SERVERTICK | 0x2300, 4);          out_uint16_le(out, 0);
         out_uint16_le(out, tick1);  
         out_uint16_le(out, tick2);  
193          s_mark_end(out);          s_mark_end(out);
194          rdpsnd_send(out);          rdpsnd_send(out);
195  }  }
# Line 190  rdpsnd_process(STREAM s) Line 199  rdpsnd_process(STREAM s)
199  {  {
200          uint8 type;          uint8 type;
201          uint16 datalen;          uint16 datalen;
202          uint32 volume;          uint16 vol_left, vol_right;
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;
# Line 230  rdpsnd_process(STREAM s) Line 239  rdpsnd_process(STREAM s)
239                  /* Insert the 4 missing bytes retrieved from last RDPSND_WRITE */                  /* Insert the 4 missing bytes retrieved from last RDPSND_WRITE */
240                  memcpy(s->data, missing_bytes, 4);                  memcpy(s->data, missing_bytes, 4);
241    
242                  current_driver->                  rdpsnd_queue_write(rdpsnd_dsp_process
243                          wave_out_write(rdpsnd_dsp_process                                     (s, current_driver, &formats[current_format]), tick,
244                                         (s, current_driver, &formats[current_format]), tick,                                     packet_index);
                                        packet_index);  
245                  awaiting_data_packet = False;                  awaiting_data_packet = False;
246                  return;                  return;
247          }          }
# Line 259  rdpsnd_process(STREAM s) Line 267  rdpsnd_process(STREAM s)
267                  case RDPSND_NEGOTIATE:                  case RDPSND_NEGOTIATE:
268                          rdpsnd_process_negotiate(s);                          rdpsnd_process_negotiate(s);
269                          break;                          break;
270                  case RDPSND_SERVERTICK:                  case RDPSND_PING:
271                          rdpsnd_process_servertick(s);                          rdpsnd_process_ping(s);
272                          break;                          break;
273                  case RDPSND_SET_VOLUME:                  case RDPSND_SET_VOLUME:
274                          in_uint32(s, volume);                          in_uint16_le(s, vol_left);
275                            in_uint16_le(s, vol_right);
276                          if (device_open)                          if (device_open)
277                          {                                  current_driver->wave_out_volume(vol_left, vol_right);
                                 current_driver->wave_out_volume((volume & 0xffff),  
                                                                 (volume & 0xffff0000) >> 16);  
                         }  
278                          break;                          break;
279                  default:                  default:
280                          unimpl("RDPSND packet type %d\n", type);                          unimpl("RDPSND packet type %d\n", type);
# Line 316  rdpsnd_register_drivers(char *options) Line 322  rdpsnd_register_drivers(char *options)
322          reg = &drivers;          reg = &drivers;
323  #if defined(RDPSND_ALSA)  #if defined(RDPSND_ALSA)
324          *reg = alsa_register(options);          *reg = alsa_register(options);
325            assert(*reg);
326          reg = &((*reg)->next);          reg = &((*reg)->next);
327  #endif  #endif
328  #if defined(RDPSND_SUN)  #if defined(RDPSND_SUN)
329          *reg = sun_register(options);          *reg = sun_register(options);
330            assert(*reg);
331          reg = &((*reg)->next);          reg = &((*reg)->next);
332  #endif  #endif
333  #if defined(RDPSND_OSS)  #if defined(RDPSND_OSS)
334          *reg = oss_register(options);          *reg = oss_register(options);
335            assert(*reg);
336          reg = &((*reg)->next);          reg = &((*reg)->next);
337  #endif  #endif
338  #if defined(RDPSND_SGI)  #if defined(RDPSND_SGI)
339          *reg = sgi_register(options);          *reg = sgi_register(options);
340            assert(*reg);
341          reg = &((*reg)->next);          reg = &((*reg)->next);
342  #endif  #endif
343  #if defined(RDPSND_LIBAO)  #if defined(RDPSND_LIBAO)
344          *reg = libao_register(options);          *reg = libao_register(options);
345            assert(*reg);
346          reg = &((*reg)->next);          reg = &((*reg)->next);
347  #endif  #endif
348            *reg = NULL;
349  }  }
350    
351  BOOL  BOOL
# Line 355  rdpsnd_init(char *optarg) Line 367  rdpsnd_init(char *optarg)
367                  return False;                  return False;
368          }          }
369    
370            rdpsnd_queue_init();
371    
372          if (optarg != NULL && strlen(optarg) > 0)          if (optarg != NULL && strlen(optarg) > 0)
373          {          {
374                  driver = options = optarg;                  driver = options = optarg;
# Line 416  rdpsnd_play(void) Line 430  rdpsnd_play(void)
430          current_driver->wave_out_play();          current_driver->wave_out_play();
431  }  }
432    
433  inline void  void
434    rdpsnd_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
435    {
436            long next_pending;
437    
438            if (g_dsp_busy)
439            {
440                    FD_SET(g_dsp_fd, wfds);
441                    *n = (g_dsp_fd > *n) ? g_dsp_fd : *n;
442            }
443    
444            next_pending = rdpsnd_queue_next_completion();
445            if (next_pending >= 0)
446            {
447                    long cur_timeout;
448    
449                    cur_timeout = tv->tv_sec * 1000000 + tv->tv_usec;
450                    if (cur_timeout > next_pending)
451                    {
452                            tv->tv_sec = next_pending / 1000000;
453                            tv->tv_usec = next_pending % 1000000;
454                    }
455            }
456    }
457    
458    void
459    rdpsnd_check_fds(fd_set * rfds, fd_set * wfds)
460    {
461            rdpsnd_queue_complete_pending();
462    
463            if (g_dsp_busy && FD_ISSET(g_dsp_fd, wfds))
464                    rdpsnd_play();
465    }
466    
467    static void
468  rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)  rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)
469  {  {
470          struct audio_packet *packet = &packet_queue[queue_hi];          struct audio_packet *packet = &packet_queue[queue_hi];
471          unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;          unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
472    
473          if (next_hi == queue_lo)          if (next_hi == queue_pending)
474          {          {
475                  error("No space to queue audio packet\n");                  error("No space to queue audio packet\n");
476                  return;                  return;
# Line 434  rdpsnd_queue_write(STREAM s, uint16 tick Line 482  rdpsnd_queue_write(STREAM s, uint16 tick
482          packet->tick = tick;          packet->tick = tick;
483          packet->index = index;          packet->index = index;
484    
485            gettimeofday(&packet->arrive_tv, NULL);
486    
487          if (!g_dsp_busy)          if (!g_dsp_busy)
488                  current_driver->wave_out_play();                  current_driver->wave_out_play();
489  }  }
490    
491  inline struct audio_packet *  struct audio_packet *
492  rdpsnd_queue_current_packet(void)  rdpsnd_queue_current_packet(void)
493  {  {
494          return &packet_queue[queue_lo];          return &packet_queue[queue_lo];
495  }  }
496    
497  inline BOOL  BOOL
498  rdpsnd_queue_empty(void)  rdpsnd_queue_empty(void)
499  {  {
500          return (queue_lo == queue_hi);          return (queue_lo == queue_hi);
501  }  }
502    
503  inline void  static void
504  rdpsnd_queue_init(void)  rdpsnd_queue_init(void)
505  {  {
506          queue_lo = queue_hi = 0;          queue_pending = queue_lo = queue_hi = 0;
507  }  }
508    
509  inline void  void
510  rdpsnd_queue_next(void)  rdpsnd_queue_next(unsigned long completed_in_us)
511  {  {
512          xfree(packet_queue[queue_lo].s.data);          struct audio_packet *packet;
513    
514            assert(!rdpsnd_queue_empty());
515    
516            packet = &packet_queue[queue_lo];
517    
518            gettimeofday(&packet->completion_tv, NULL);
519    
520            packet->completion_tv.tv_usec += completed_in_us;
521            packet->completion_tv.tv_sec += packet->completion_tv.tv_usec / 1000000;
522            packet->completion_tv.tv_usec %= 1000000;
523    
524          queue_lo = (queue_lo + 1) % MAX_QUEUE;          queue_lo = (queue_lo + 1) % MAX_QUEUE;
525    
526            rdpsnd_queue_complete_pending();
527  }  }
528    
529  inline int  int
530  rdpsnd_queue_next_tick(void)  rdpsnd_queue_next_tick(void)
531  {  {
532          if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)          if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
# Line 475  rdpsnd_queue_next_tick(void) Line 538  rdpsnd_queue_next_tick(void)
538                  return (packet_queue[queue_lo].tick + 65535) % 65536;                  return (packet_queue[queue_lo].tick + 65535) % 65536;
539          }          }
540  }  }
541    
542    static void
543    rdpsnd_queue_complete_pending(void)
544    {
545            struct timeval now;
546            long elapsed;
547            struct audio_packet *packet;
548    
549            gettimeofday(&now, NULL);
550    
551            while (queue_pending != queue_lo)
552            {
553                    packet = &packet_queue[queue_pending];
554    
555                    if (now.tv_sec < packet->completion_tv.tv_sec)
556                            break;
557    
558                    if ((now.tv_sec == packet->completion_tv.tv_sec) &&
559                        (now.tv_usec < packet->completion_tv.tv_usec))
560                            break;
561    
562                    elapsed = (packet->completion_tv.tv_sec - packet->arrive_tv.tv_sec) * 1000000 +
563                            (packet->completion_tv.tv_usec - packet->arrive_tv.tv_usec);
564                    elapsed /= 1000;
565    
566                    xfree(packet->s.data);
567                    rdpsnd_send_completion((packet->tick + elapsed) % 65536, packet->index);
568                    queue_pending = (queue_pending + 1) % MAX_QUEUE;
569            }
570    }
571    
572    static long
573    rdpsnd_queue_next_completion(void)
574    {
575            struct audio_packet *packet;
576            long remaining;
577            struct timeval now;
578    
579            if (queue_pending == queue_lo)
580                    return -1;
581    
582            gettimeofday(&now, NULL);
583    
584            packet = &packet_queue[queue_pending];
585    
586            remaining = (packet->completion_tv.tv_sec - now.tv_sec) * 1000000 +
587                    (packet->completion_tv.tv_usec - now.tv_usec);
588    
589            if (remaining < 0)
590                    return 0;
591    
592            return remaining;
593    }

Legend:
Removed from v.1274  
changed lines
  Added in v.1341

  ViewVC Help
Powered by ViewVC 1.1.26