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

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

  ViewVC Help
Powered by ViewVC 1.1.26