/[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 1263 by stargo, Sun Sep 17 18:08:51 2006 UTC revision 1339 by ossman_, Wed Dec 6 13:01:45 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 169  rdpsnd_process_negotiate(STREAM in) Line 176  rdpsnd_process_negotiate(STREAM in)
176  }  }
177    
178  static void  static void
179  rdpsnd_process_servertick(STREAM in)  rdpsnd_process_ping(STREAM in)
180  {  {
181          uint16 tick1, tick2;          uint16 tick;
182          STREAM out;          STREAM out;
183    
184          /* in_uint8s(in, 4); unknown */          in_uint16_le(in, tick);
185          in_uint16_le(in, tick1);  
186          in_uint16_le(in, tick2);          out = rdpsnd_init_packet(RDPSND_PING | 0x2300, 4);
187            out_uint16_le(out, tick);
188          out = rdpsnd_init_packet(RDPSND_SERVERTICK | 0x2300, 4);          out_uint16_le(out, 0);
         out_uint16_le(out, tick1);  
         out_uint16_le(out, tick2);  
189          s_mark_end(out);          s_mark_end(out);
190          rdpsnd_send(out);          rdpsnd_send(out);
191  }  }
# Line 194  rdpsnd_process(STREAM s) Line 199  rdpsnd_process(STREAM s)
199          static uint16 tick, format;          static uint16 tick, format;
200          static uint8 packet_index;          static uint8 packet_index;
201          static BOOL awaiting_data_packet;          static BOOL awaiting_data_packet;
202            static unsigned char missing_bytes[4] = { 0, 0, 0, 0 };
203    
204  #ifdef RDPSND_DEBUG  #ifdef RDPSND_DEBUG
205          printf("RDPSND recv:\n");          printf("RDPSND recv:\n");
# Line 226  rdpsnd_process(STREAM s) Line 232  rdpsnd_process(STREAM s)
232                          current_format = format;                          current_format = format;
233                  }                  }
234    
235                  current_driver->                  /* Insert the 4 missing bytes retrieved from last RDPSND_WRITE */
236                          wave_out_write(rdpsnd_dsp_process                  memcpy(s->data, missing_bytes, 4);
237                                         (s, current_driver, &formats[current_format]), tick,  
238                                         packet_index);                  rdpsnd_queue_write(rdpsnd_dsp_process
239                                       (s, current_driver, &formats[current_format]), tick,
240                                       packet_index);
241                  awaiting_data_packet = False;                  awaiting_data_packet = False;
242                  return;                  return;
243          }          }
# Line 244  rdpsnd_process(STREAM s) Line 252  rdpsnd_process(STREAM s)
252                          in_uint16_le(s, tick);                          in_uint16_le(s, tick);
253                          in_uint16_le(s, format);                          in_uint16_le(s, format);
254                          in_uint8(s, packet_index);                          in_uint8(s, packet_index);
255                            /* Here are our lost bytes, but why? */
256                            memcpy(missing_bytes, s->end - 4, 4);
257                          awaiting_data_packet = True;                          awaiting_data_packet = True;
258                          break;                          break;
259                  case RDPSND_CLOSE:                  case RDPSND_CLOSE:
# Line 253  rdpsnd_process(STREAM s) Line 263  rdpsnd_process(STREAM s)
263                  case RDPSND_NEGOTIATE:                  case RDPSND_NEGOTIATE:
264                          rdpsnd_process_negotiate(s);                          rdpsnd_process_negotiate(s);
265                          break;                          break;
266                  case RDPSND_SERVERTICK:                  case RDPSND_PING:
267                          rdpsnd_process_servertick(s);                          rdpsnd_process_ping(s);
268                          break;                          break;
269                  case RDPSND_SET_VOLUME:                  case RDPSND_SET_VOLUME:
270                          in_uint32(s, volume);                          in_uint32(s, volume);
# Line 270  rdpsnd_process(STREAM s) Line 280  rdpsnd_process(STREAM s)
280          }          }
281  }  }
282    
283  BOOL  static BOOL
 rdpsnd_init(void)  
 {  
         rdpsnd_channel =  
                 channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,  
                                  rdpsnd_process);  
   
         return (rdpsnd_channel != NULL);  
 }  
   
 BOOL  
284  rdpsnd_auto_open(void)  rdpsnd_auto_open(void)
285  {  {
286          current_driver = drivers;          static BOOL failed = False;
287          while (current_driver != NULL)  
288            if (!failed)
289          {          {
290                  DEBUG(("trying %s...\n", current_driver->name));                  struct audio_driver *auto_driver = current_driver;
291                  if (current_driver->wave_out_open())  
292                    current_driver = drivers;
293                    while (current_driver != NULL)
294                  {                  {
295                          DEBUG(("selected %s\n", current_driver->name));                          DEBUG(("trying %s...\n", current_driver->name));
296                          return True;                          if (current_driver->wave_out_open())
297                            {
298                                    DEBUG(("selected %s\n", current_driver->name));
299                                    return True;
300                            }
301                            g_dsp_fd = 0;
302                            current_driver = current_driver->next;
303                  }                  }
                 g_dsp_fd = 0;  
                 current_driver = current_driver->next;  
         }  
304    
305          warning("no working audio-driver found\n");                  warning("no working audio-driver found\n");
306                    failed = True;
307                    current_driver = auto_driver;
308            }
309    
310          return False;          return False;
311  }  }
312    
313  void  static void
314  rdpsnd_register_drivers(char *options)  rdpsnd_register_drivers(char *options)
315  {  {
316          struct audio_driver **reg;          struct audio_driver **reg;
# Line 311  rdpsnd_register_drivers(char *options) Line 320  rdpsnd_register_drivers(char *options)
320          reg = &drivers;          reg = &drivers;
321  #if defined(RDPSND_ALSA)  #if defined(RDPSND_ALSA)
322          *reg = alsa_register(options);          *reg = alsa_register(options);
323          reg = &((*reg)->next);          assert(*reg);
 #endif  
 #if defined(RDPSND_OSS)  
         *reg = oss_register(options);  
324          reg = &((*reg)->next);          reg = &((*reg)->next);
325  #endif  #endif
326  #if defined(RDPSND_SUN)  #if defined(RDPSND_SUN)
327          *reg = sun_register(options);          *reg = sun_register(options);
328            assert(*reg);
329            reg = &((*reg)->next);
330    #endif
331    #if defined(RDPSND_OSS)
332            *reg = oss_register(options);
333            assert(*reg);
334          reg = &((*reg)->next);          reg = &((*reg)->next);
335  #endif  #endif
336  #if defined(RDPSND_SGI)  #if defined(RDPSND_SGI)
337          *reg = sgi_register(options);          *reg = sgi_register(options);
338            assert(*reg);
339          reg = &((*reg)->next);          reg = &((*reg)->next);
340  #endif  #endif
341  #if defined(RDPSND_LIBAO)  #if defined(RDPSND_LIBAO)
342          *reg = libao_register(options);          *reg = libao_register(options);
343            assert(*reg);
344          reg = &((*reg)->next);          reg = &((*reg)->next);
345  #endif  #endif
346            *reg = NULL;
347  }  }
348    
349  BOOL  BOOL
350  rdpsnd_select_driver(char *driver, char *options)  rdpsnd_init(char *optarg)
351  {  {
352          static struct audio_driver auto_driver;          static struct audio_driver auto_driver;
353          struct audio_driver *pos;          struct audio_driver *pos;
354            char *driver = NULL, *options = NULL;
355    
356          drivers = NULL;          drivers = NULL;
357    
358            rdpsnd_channel =
359                    channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
360                                     rdpsnd_process);
361    
362            if (rdpsnd_channel == NULL)
363            {
364                    error("channel_register\n");
365                    return False;
366            }
367    
368            rdpsnd_queue_init();
369    
370            if (optarg != NULL && strlen(optarg) > 0)
371            {
372                    driver = options = optarg;
373    
374                    while (*options != '\0' && *options != ':')
375                            options++;
376    
377                    if (*options == ':')
378                    {
379                            *options = '\0';
380                            options++;
381                    }
382    
383                    if (*options == '\0')
384                            options = NULL;
385            }
386    
387          rdpsnd_register_drivers(options);          rdpsnd_register_drivers(options);
388    
389          if (!driver)          if (!driver)
# Line 376  rdpsnd_show_help(void) Line 422  rdpsnd_show_help(void)
422          }          }
423  }  }
424    
425  inline void  void
426  rdpsnd_play(void)  rdpsnd_play(void)
427  {  {
428          current_driver->wave_out_play();          current_driver->wave_out_play();
429  }  }
430    
431  void  void
432    rdpsnd_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
433    {
434            long next_pending;
435    
436            if (g_dsp_busy)
437            {
438                    FD_SET(g_dsp_fd, wfds);
439                    *n = (g_dsp_fd > *n) ? g_dsp_fd : *n;
440            }
441    
442            next_pending = rdpsnd_queue_next_completion();
443            if (next_pending >= 0)
444            {
445                    long cur_timeout;
446    
447                    cur_timeout = tv->tv_sec * 1000000 + tv->tv_usec;
448                    if (cur_timeout > next_pending)
449                    {
450                            tv->tv_sec = next_pending / 1000000;
451                            tv->tv_usec = next_pending % 1000000;
452                    }
453            }
454    }
455    
456    void
457    rdpsnd_check_fds(fd_set * rfds, fd_set * wfds)
458    {
459            rdpsnd_queue_complete_pending();
460    
461            if (g_dsp_busy && FD_ISSET(g_dsp_fd, wfds))
462                    rdpsnd_play();
463    }
464    
465    static void
466  rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)  rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)
467  {  {
468          struct audio_packet *packet = &packet_queue[queue_hi];          struct audio_packet *packet = &packet_queue[queue_hi];
469          unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;          unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
470    
471          if (next_hi == queue_lo)          if (next_hi == queue_pending)
472          {          {
473                  error("No space to queue audio packet\n");                  error("No space to queue audio packet\n");
474                  return;                  return;
# Line 400  rdpsnd_queue_write(STREAM s, uint16 tick Line 480  rdpsnd_queue_write(STREAM s, uint16 tick
480          packet->tick = tick;          packet->tick = tick;
481          packet->index = index;          packet->index = index;
482    
483            gettimeofday(&packet->arrive_tv, NULL);
484    
485          if (!g_dsp_busy)          if (!g_dsp_busy)
486                  current_driver->wave_out_play();                  current_driver->wave_out_play();
487  }  }
488    
489  inline struct audio_packet *  struct audio_packet *
490  rdpsnd_queue_current_packet(void)  rdpsnd_queue_current_packet(void)
491  {  {
492          return &packet_queue[queue_lo];          return &packet_queue[queue_lo];
493  }  }
494    
495  inline BOOL  BOOL
496  rdpsnd_queue_empty(void)  rdpsnd_queue_empty(void)
497  {  {
498          return (queue_lo == queue_hi);          return (queue_lo == queue_hi);
499  }  }
500    
501  inline void  static void
502  rdpsnd_queue_init(void)  rdpsnd_queue_init(void)
503  {  {
504          queue_lo = queue_hi = 0;          queue_pending = queue_lo = queue_hi = 0;
505  }  }
506    
507  inline void  void
508  rdpsnd_queue_next(void)  rdpsnd_queue_next(unsigned long completed_in_us)
509  {  {
510          xfree(packet_queue[queue_lo].s.data);          struct audio_packet *packet;
511    
512            assert(!rdpsnd_queue_empty());
513    
514            packet = &packet_queue[queue_lo];
515    
516            gettimeofday(&packet->completion_tv, NULL);
517    
518            packet->completion_tv.tv_usec += completed_in_us;
519            packet->completion_tv.tv_sec += packet->completion_tv.tv_usec / 1000000;
520            packet->completion_tv.tv_usec %= 1000000;
521    
522          queue_lo = (queue_lo + 1) % MAX_QUEUE;          queue_lo = (queue_lo + 1) % MAX_QUEUE;
523    
524            rdpsnd_queue_complete_pending();
525  }  }
526    
527  inline int  int
528  rdpsnd_queue_next_tick(void)  rdpsnd_queue_next_tick(void)
529  {  {
530          if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)          if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
# Line 441  rdpsnd_queue_next_tick(void) Line 536  rdpsnd_queue_next_tick(void)
536                  return (packet_queue[queue_lo].tick + 65535) % 65536;                  return (packet_queue[queue_lo].tick + 65535) % 65536;
537          }          }
538  }  }
539    
540    static void
541    rdpsnd_queue_complete_pending(void)
542    {
543            struct timeval now;
544            long elapsed;
545            struct audio_packet *packet;
546    
547            gettimeofday(&now, NULL);
548    
549            while (queue_pending != queue_lo)
550            {
551                    packet = &packet_queue[queue_pending];
552    
553                    if (now.tv_sec < packet->completion_tv.tv_sec)
554                            break;
555    
556                    if ((now.tv_sec == packet->completion_tv.tv_sec) &&
557                        (now.tv_usec < packet->completion_tv.tv_usec))
558                            break;
559    
560                    elapsed = (packet->completion_tv.tv_sec - packet->arrive_tv.tv_sec) * 1000000 +
561                            (packet->completion_tv.tv_usec - packet->arrive_tv.tv_usec);
562                    elapsed /= 1000;
563    
564                    xfree(packet->s.data);
565                    rdpsnd_send_completion((packet->tick + elapsed) % 65536, packet->index);
566                    queue_pending = (queue_pending + 1) % MAX_QUEUE;
567            }
568    }
569    
570    static long
571    rdpsnd_queue_next_completion(void)
572    {
573            struct audio_packet *packet;
574            long remaining;
575            struct timeval now;
576    
577            if (queue_pending == queue_lo)
578                    return -1;
579    
580            gettimeofday(&now, NULL);
581    
582            packet = &packet_queue[queue_pending];
583    
584            remaining = (packet->completion_tv.tv_sec - now.tv_sec) * 1000000 +
585                    (packet->completion_tv.tv_usec - now.tv_usec);
586    
587            if (remaining < 0)
588                    return 0;
589    
590            return remaining;
591    }

Legend:
Removed from v.1263  
changed lines
  Added in v.1339

  ViewVC Help
Powered by ViewVC 1.1.26