/[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 491 by stargo, Mon Oct 13 16:09:45 2003 UTC revision 1265 by stargo, Sun Sep 17 20:06:37 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 20  Line 20 
20  */  */
21    
22  #include "rdesktop.h"  #include "rdesktop.h"
23    #include "rdpsnd.h"
24    #include "rdpsnd_dsp.h"
25    
26  #define RDPSND_CLOSE            1  #define RDPSND_CLOSE            1
27  #define RDPSND_WRITE            2  #define RDPSND_WRITE            2
28  #define RDPSND_SET_VOLUME       3  #define RDPSND_SET_VOLUME       3
29  #define RDPSND_UNKNOWN4         4  #define RDPSND_UNKNOWN4         4
30  #define RDPSND_COMPLETION       5  #define RDPSND_COMPLETION       5
31  #define RDPSND_UNKNOWN6         6  #define RDPSND_SERVERTICK       6
32  #define RDPSND_NEGOTIATE        7  #define RDPSND_NEGOTIATE        7
33    
34  #define MAX_FORMATS             10  #define MAX_FORMATS             10
35    #define MAX_QUEUE               10
36    
37    BOOL g_dsp_busy = False;
38    int g_dsp_fd;
39    
40  static VCHANNEL *rdpsnd_channel;  static VCHANNEL *rdpsnd_channel;
41    static struct audio_driver *drivers = NULL;
42    struct audio_driver *current_driver = NULL;
43    
44  static BOOL device_open;  static BOOL device_open;
45  static WAVEFORMATEX formats[MAX_FORMATS];  static WAVEFORMATEX formats[MAX_FORMATS];
46  static unsigned int format_count;  static unsigned int format_count;
47  static unsigned int current_format;  static unsigned int current_format;
48    unsigned int queue_hi, queue_lo;
49    struct audio_packet packet_queue[MAX_QUEUE];
50    
51    void (*wave_out_play) (void);
52    
53  STREAM  static STREAM
54  rdpsnd_init_packet(uint16 type, uint16 size)  rdpsnd_init_packet(uint16 type, uint16 size)
55  {  {
56          STREAM s;          STREAM s;
57    
58          s = channel_init(rdpsnd_channel, size+4);          s = channel_init(rdpsnd_channel, size + 4);
59          out_uint16_le(s, type);          out_uint16_le(s, type);
60          out_uint16_le(s, size);          out_uint16_le(s, size);
61          return s;          return s;
62  }  }
63    
64  void  static void
65  rdpsnd_send(STREAM s)  rdpsnd_send(STREAM s)
66  {  {
67  #ifdef RDPSND_DEBUG  #ifdef RDPSND_DEBUG
68          printf("RDPSND send:\n");          printf("RDPSND send:\n");
69          hexdump(s->channel_hdr+8, s->end-s->channel_hdr-8);          hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);
70  #endif  #endif
71    
72          channel_send(s, rdpsnd_channel);          channel_send(s, rdpsnd_channel);
73  }  }
74    
75  void rdpsnd_send_completion(uint16 tick, uint8 packet_index)  void
76    rdpsnd_send_completion(uint16 tick, uint8 packet_index)
77  {  {
78          STREAM s;          STREAM s;
79    
80          s = rdpsnd_init_packet(RDPSND_COMPLETION, 4);          s = rdpsnd_init_packet(RDPSND_COMPLETION, 4);
81          out_uint16_le(s, tick+50);          out_uint16_le(s, tick);
82          out_uint8(s, packet_index);          out_uint8(s, packet_index);
83          out_uint8(s, 0);          out_uint8(s, 0);
84          s_mark_end(s);          s_mark_end(s);
85          rdpsnd_send(s);          rdpsnd_send(s);
86  }  }
87    
88  void  static void
89  rdpsnd_process_negotiate(STREAM in)  rdpsnd_process_negotiate(STREAM in)
90  {  {
91          unsigned int in_format_count, i;          unsigned int in_format_count, i;
92          WAVEFORMATEX *format;          WAVEFORMATEX *format;
93          STREAM out;          STREAM out;
94          BOOL device_available = False;          BOOL device_available = False;
95            int readcnt;
96            int discardcnt;
97    
98          in_uint8s(in, 14);      /* flags, volume, pitch, UDP port */          in_uint8s(in, 14);      /* flags, volume, pitch, UDP port */
99          in_uint16_le(in, in_format_count);          in_uint16_le(in, in_format_count);
100          in_uint8s(in, 4);       /* pad, status, pad */          in_uint8s(in, 4);       /* pad, status, pad */
101    
102          if (wave_out_open())          if (current_driver->wave_out_open())
103          {          {
104                  wave_out_close();                  current_driver->wave_out_close();
105                  device_available = True;                  device_available = True;
106          }          }
107    
108          format_count = 0;          format_count = 0;
109          if (s_check_rem(in, 18*in_format_count))          if (s_check_rem(in, 18 * in_format_count))
110          {          {
111                  for (i = 0; i < in_format_count; i++)                  for (i = 0; i < in_format_count; i++)
112                  {                  {
# Line 104  rdpsnd_process_negotiate(STREAM in) Line 119  rdpsnd_process_negotiate(STREAM in)
119                          in_uint16_le(in, format->wBitsPerSample);                          in_uint16_le(in, format->wBitsPerSample);
120                          in_uint16_le(in, format->cbSize);                          in_uint16_le(in, format->cbSize);
121    
122                          if (device_available && wave_out_format_supported(format))                          /* read in the buffer of unknown use */
123                            readcnt = format->cbSize;
124                            discardcnt = 0;
125                            if (format->cbSize > MAX_CBSIZE)
126                            {
127                                    fprintf(stderr, "cbSize too large for buffer: %d\n",
128                                            format->cbSize);
129                                    readcnt = MAX_CBSIZE;
130                                    discardcnt = format->cbSize - MAX_CBSIZE;
131                            }
132                            in_uint8a(in, format->cb, readcnt);
133                            in_uint8s(in, discardcnt);
134    
135                            if (device_available && current_driver->wave_out_format_supported(format))
136                          {                          {
137                                  format_count++;                                  format_count++;
138                                  if (format_count == MAX_FORMATS)                                  if (format_count == MAX_FORMATS)
# Line 113  rdpsnd_process_negotiate(STREAM in) Line 141  rdpsnd_process_negotiate(STREAM in)
141                  }                  }
142          }          }
143    
144          out = rdpsnd_init_packet(RDPSND_NEGOTIATE | 0x200, 20 + 18*format_count);          out = rdpsnd_init_packet(RDPSND_NEGOTIATE | 0x200, 20 + 18 * format_count);
145          out_uint32_le(out, 3);          /* flags */          out_uint32_le(out, 3);  /* flags */
146          out_uint32(out, 0xffffffff);    /* volume */          out_uint32(out, 0xffffffff);    /* volume */
147          out_uint32(out, 0);             /* pitch */          out_uint32(out, 0);     /* pitch */
148          out_uint16(out, 0);             /* UDP port */          out_uint16(out, 0);     /* UDP port */
149    
150          out_uint16_le(out, format_count);          out_uint16_le(out, format_count);
151          out_uint8(out, 0x95);           /* pad? */          out_uint8(out, 0x95);   /* pad? */
152          out_uint16_le(out, 2);          /* status */          out_uint16_le(out, 2);  /* status */
153          out_uint8(out, 0x77);           /* pad? */          out_uint8(out, 0x77);   /* pad? */
154    
155          for (i = 0; i < format_count; i++)          for (i = 0; i < format_count; i++)
156          {          {
# Line 133  rdpsnd_process_negotiate(STREAM in) Line 161  rdpsnd_process_negotiate(STREAM in)
161                  out_uint32_le(out, format->nAvgBytesPerSec);                  out_uint32_le(out, format->nAvgBytesPerSec);
162                  out_uint16_le(out, format->nBlockAlign);                  out_uint16_le(out, format->nBlockAlign);
163                  out_uint16_le(out, format->wBitsPerSample);                  out_uint16_le(out, format->wBitsPerSample);
164                  out_uint16(out, 0); /* cbSize */                  out_uint16(out, 0);     /* cbSize */
165          }          }
166    
167          s_mark_end(out);          s_mark_end(out);
168          rdpsnd_send(out);          rdpsnd_send(out);
169  }  }
170    
171  void  static void
172  rdpsnd_process_unknown6(STREAM in)  rdpsnd_process_servertick(STREAM in)
173  {  {
174          uint16 unknown1, unknown2;          uint16 tick1, tick2;
175          STREAM out;          STREAM out;
176    
177          /* in_uint8s(in, 4); unknown */          /* in_uint8s(in, 4); unknown */
178          in_uint16_le(in, unknown1);          in_uint16_le(in, tick1);
179          in_uint16_le(in, unknown2);          in_uint16_le(in, tick2);
180    
181          out = rdpsnd_init_packet(RDPSND_UNKNOWN6 | 0x2300, 4);          out = rdpsnd_init_packet(RDPSND_SERVERTICK | 0x2300, 4);
182          out_uint16_le(out, unknown1);          out_uint16_le(out, tick1);
183          out_uint16_le(out, unknown2);          out_uint16_le(out, tick2);
184          s_mark_end(out);          s_mark_end(out);
185          rdpsnd_send(out);          rdpsnd_send(out);
186  }  }
187    
188  void  static void
189  rdpsnd_process(STREAM s)  rdpsnd_process(STREAM s)
190  {  {
191          uint8 type;          uint8 type;
# Line 166  rdpsnd_process(STREAM s) Line 194  rdpsnd_process(STREAM s)
194          static uint16 tick, format;          static uint16 tick, format;
195          static uint8 packet_index;          static uint8 packet_index;
196          static BOOL awaiting_data_packet;          static BOOL awaiting_data_packet;
197            static unsigned char missing_bytes[4] = { 0, 0, 0, 0 };
198    
199  #ifdef RDPSND_DEBUG  #ifdef RDPSND_DEBUG
200          printf("RDPSND recv:\n");          printf("RDPSND recv:\n");
201          hexdump(s->p, s->end-s->p);          hexdump(s->p, s->end - s->p);
202  #endif  #endif
203    
204          if (awaiting_data_packet)          if (awaiting_data_packet)
# Line 182  rdpsnd_process(STREAM s) Line 211  rdpsnd_process(STREAM s)
211    
212                  if (!device_open || (format != current_format))                  if (!device_open || (format != current_format))
213                  {                  {
214                          if (!device_open && !wave_out_open())                          if (!device_open && !current_driver->wave_out_open())
215                          {                          {
216                                  rdpsnd_send_completion(tick, packet_index);                                  rdpsnd_send_completion(tick, packet_index);
217                                  return;                                  return;
218                          }                          }
219                          if (!wave_out_set_format(&formats[format]))                          if (!current_driver->wave_out_set_format(&formats[format]))
220                          {                          {
221                                  rdpsnd_send_completion(tick, packet_index);                                  rdpsnd_send_completion(tick, packet_index);
222                                  wave_out_close();                                  current_driver->wave_out_close();
223                                  device_open = False;                                  device_open = False;
224                                  return;                                  return;
225                          }                          }
# Line 198  rdpsnd_process(STREAM s) Line 227  rdpsnd_process(STREAM s)
227                          current_format = format;                          current_format = format;
228                  }                  }
229    
230                  wave_out_write(s, tick, packet_index);                  /* Insert the 4 missing bytes retrieved from last RDPSND_WRITE */
231                    memcpy(s->data, missing_bytes, 4);
232    
233                    current_driver->
234                            wave_out_write(rdpsnd_dsp_process
235                                           (s, current_driver, &formats[current_format]), tick,
236                                           packet_index);
237                  awaiting_data_packet = False;                  awaiting_data_packet = False;
238                  return;                  return;
239          }          }
240    
241          in_uint8(s, type);          in_uint8(s, type);
242          in_uint8s(s, 1); /* unknown? */          in_uint8s(s, 1);        /* unknown? */
243          in_uint16_le(s, datalen);          in_uint16_le(s, datalen);
244    
245          switch (type)          switch (type)
246          {          {
247          case RDPSND_WRITE:                  case RDPSND_WRITE:
248                  in_uint16_le(s, tick);                          in_uint16_le(s, tick);
249                  in_uint16_le(s, format);                          in_uint16_le(s, format);
250                  in_uint8(s, packet_index);                          in_uint8(s, packet_index);
251                  awaiting_data_packet = True;                          /* Here are our lost bytes, but why? */
252                  break;                          memcpy(missing_bytes, s->end - 4, 4);
253          case RDPSND_CLOSE:                          awaiting_data_packet = True;
254                  wave_out_close();                          break;
255                  device_open = False;                  case RDPSND_CLOSE:
256                  break;                          current_driver->wave_out_close();
257          case RDPSND_NEGOTIATE:                          device_open = False;
258                  rdpsnd_process_negotiate(s);                          break;
259                  break;                  case RDPSND_NEGOTIATE:
260          case RDPSND_UNKNOWN6:                          rdpsnd_process_negotiate(s);
261                  rdpsnd_process_unknown6(s);                          break;
262                  break;                  case RDPSND_SERVERTICK:
263          case RDPSND_SET_VOLUME:                          rdpsnd_process_servertick(s);
264                  in_uint32(s, volume);                          break;
265                  if ( device_open )                  case RDPSND_SET_VOLUME:
266                  {                          in_uint32(s, volume);
267                          wave_out_volume((volume & 0xffff), (volume & 0xffff0000) >> 16);                          if (device_open)
268                  }                          {
269                  break;                                  current_driver->wave_out_volume((volume & 0xffff),
270          default:                                                                  (volume & 0xffff0000) >> 16);
271                  unimpl("RDPSND packet type %d\n", type);                          }
272                  break;                          break;
273                    default:
274                            unimpl("RDPSND packet type %d\n", type);
275                            break;
276          }          }
277  }  }
278    
# Line 244  rdpsnd_init(void) Line 282  rdpsnd_init(void)
282          rdpsnd_channel =          rdpsnd_channel =
283                  channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,                  channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
284                                   rdpsnd_process);                                   rdpsnd_process);
285    
286          return (rdpsnd_channel != NULL);          return (rdpsnd_channel != NULL);
287  }  }
288    
289    BOOL
290    rdpsnd_auto_open(void)
291    {
292            current_driver = drivers;
293            while (current_driver != NULL)
294            {
295                    DEBUG(("trying %s...\n", current_driver->name));
296                    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            }
304    
305            warning("no working audio-driver found\n");
306    
307            return False;
308    }
309    
310    void
311    rdpsnd_register_drivers(char *options)
312    {
313            struct audio_driver **reg;
314    
315            /* The order of registrations define the probe-order
316               when opening the device for the first time */
317            reg = &drivers;
318    #if defined(RDPSND_ALSA)
319            *reg = alsa_register(options);
320            reg = &((*reg)->next);
321    #endif
322    #if defined(RDPSND_SUN)
323            *reg = sun_register(options);
324            reg = &((*reg)->next);
325    #endif
326    #if defined(RDPSND_OSS)
327            *reg = oss_register(options);
328            reg = &((*reg)->next);
329    #endif
330    #if defined(RDPSND_SGI)
331            *reg = sgi_register(options);
332            reg = &((*reg)->next);
333    #endif
334    #if defined(RDPSND_LIBAO)
335            *reg = libao_register(options);
336            reg = &((*reg)->next);
337    #endif
338    }
339    
340    BOOL
341    rdpsnd_select_driver(char *driver, char *options)
342    {
343            static struct audio_driver auto_driver;
344            struct audio_driver *pos;
345    
346            drivers = NULL;
347            rdpsnd_register_drivers(options);
348    
349            if (!driver)
350            {
351                    auto_driver.wave_out_open = &rdpsnd_auto_open;
352                    current_driver = &auto_driver;
353                    return True;
354            }
355    
356            pos = drivers;
357            while (pos != NULL)
358            {
359                    if (!strcmp(pos->name, driver))
360                    {
361                            DEBUG(("selected %s\n", pos->name));
362                            current_driver = pos;
363                            return True;
364                    }
365                    pos = pos->next;
366            }
367            return False;
368    }
369    
370    void
371    rdpsnd_show_help(void)
372    {
373            struct audio_driver *pos;
374    
375            rdpsnd_register_drivers(NULL);
376    
377            pos = drivers;
378            while (pos != NULL)
379            {
380                    fprintf(stderr, "                     %s:\t%s\n", pos->name, pos->description);
381                    pos = pos->next;
382            }
383    }
384    
385    inline void
386    rdpsnd_play(void)
387    {
388            current_driver->wave_out_play();
389    }
390    
391    void
392    rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)
393    {
394            struct audio_packet *packet = &packet_queue[queue_hi];
395            unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
396    
397            if (next_hi == queue_lo)
398            {
399                    error("No space to queue audio packet\n");
400                    return;
401            }
402    
403            queue_hi = next_hi;
404    
405            packet->s = *s;
406            packet->tick = tick;
407            packet->index = index;
408    
409            if (!g_dsp_busy)
410                    current_driver->wave_out_play();
411    }
412    
413    inline struct audio_packet *
414    rdpsnd_queue_current_packet(void)
415    {
416            return &packet_queue[queue_lo];
417    }
418    
419    inline BOOL
420    rdpsnd_queue_empty(void)
421    {
422            return (queue_lo == queue_hi);
423    }
424    
425    inline void
426    rdpsnd_queue_init(void)
427    {
428            queue_lo = queue_hi = 0;
429    }
430    
431    inline void
432    rdpsnd_queue_next(void)
433    {
434            xfree(packet_queue[queue_lo].s.data);
435            queue_lo = (queue_lo + 1) % MAX_QUEUE;
436    }
437    
438    inline int
439    rdpsnd_queue_next_tick(void)
440    {
441            if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
442            {
443                    return packet_queue[(queue_lo + 1) % MAX_QUEUE].tick;
444            }
445            else
446            {
447                    return (packet_queue[queue_lo].tick + 65535) % 65536;
448            }
449    }

Legend:
Removed from v.491  
changed lines
  Added in v.1265

  ViewVC Help
Powered by ViewVC 1.1.26