/[rdesktop]/sourceforge.net/trunk/rdesktop/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/trunk/rdesktop/rdpsnd.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1332 by stargo, Mon Nov 6 23:05:39 2006 UTC revision 1343 by ossman_, Wed Dec 6 13:55:34 2006 UTC
# Line 1  Line 1 
1  /* -*- c-basic-offset: 8 -*-  /* -*- 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 30  Line 31 
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_SERVERTICK       6  #define RDPSND_PING                     6
35  #define RDPSND_NEGOTIATE        7  #define RDPSND_NEGOTIATE        7
36    
37  #define MAX_FORMATS             10  #define MAX_FORMATS             10
# Line 50  static unsigned int current_format; Line 51  static unsigned int current_format;
51  unsigned int queue_hi, queue_lo, queue_pending;  unsigned int queue_hi, queue_lo, queue_pending;
52  struct audio_packet packet_queue[MAX_QUEUE];  struct audio_packet packet_queue[MAX_QUEUE];
53    
54    static uint8 packet_opcode;
55    static struct stream packet;
56    
57  void (*wave_out_play) (void);  void (*wave_out_play) (void);
58    
59  static void rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index);  static void rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index);
# Line 71  rdpsnd_init_packet(uint16 type, uint16 s Line 75  rdpsnd_init_packet(uint16 type, uint16 s
75  static 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    
# Line 90  rdpsnd_send_completion(uint16 tick, uint Line 89  rdpsnd_send_completion(uint16 tick, uint
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  static 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;          BOOL device_available = False;
106          int readcnt;          int readcnt;
107          int discardcnt;          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, pad1: 0x%02x, version: %x)\n",
116                         (int) in_format_count, (unsigned) pad1, (unsigned) version));
117    
118          if (current_driver->wave_out_open())          if (current_driver->wave_out_open())
119          {          {
# Line 155  rdpsnd_process_negotiate(STREAM in) Line 164  rdpsnd_process_negotiate(STREAM in)
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 172  rdpsnd_process_negotiate(STREAM in) Line 181  rdpsnd_process_negotiate(STREAM in)
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  static void  static void
191  rdpsnd_process_servertick(STREAM in)  rdpsnd_process_ping(STREAM in)
192  {  {
193          uint16 tick1, tick2;          uint16 tick;
194          STREAM out;          STREAM out;
195    
196          /* in_uint8s(in, 4); unknown */          in_uint16_le(in, tick);
197          in_uint16_le(in, tick1);  
198          in_uint16_le(in, tick2);          DEBUG_SOUND(("RDPSND: RDPSND_PING(tick: 0x%04x)\n", (unsigned) tick));
199    
200          out = rdpsnd_init_packet(RDPSND_SERVERTICK | 0x2300, 4);          out = rdpsnd_init_packet(RDPSND_PING | 0x2300, 4);
201          out_uint16_le(out, tick1);          out_uint16_le(out, tick);
202          out_uint16_le(out, tick2);          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  static 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;  
         uint32 volume;  
213          static uint16 tick, format;          static uint16 tick, format;
214          static uint8 packet_index;          static uint8 packet_index;
         static BOOL awaiting_data_packet;  
         static unsigned char missing_bytes[4] = { 0, 0, 0, 0 };  
   
 #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                          return;                          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 (!device_open || (format != current_format))                          if (format >= MAX_FORMATS)
                 {  
                         if (!device_open && !current_driver->wave_out_open())  
226                          {                          {
227                                  rdpsnd_send_completion(tick, packet_index);                                  error("RDPSND: Invalid format index\n");
228                                  return;                                  break;
229                          }                          }
230                          if (!current_driver->wave_out_set_format(&formats[format]))  
231                            if (!device_open || (format != current_format))
232                          {                          {
233                                  rdpsnd_send_completion(tick, packet_index);                                  if (!device_open && !current_driver->wave_out_open())
234                                  current_driver->wave_out_close();                                  {
235                                  device_open = False;                                          rdpsnd_send_completion(tick, packet_index);
236                                  return;                                          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                          }                          }
                         device_open = True;  
                         current_format = format;  
                 }  
   
                 /* Insert the 4 missing bytes retrieved from last RDPSND_WRITE */  
                 memcpy(s->data, missing_bytes, 4);  
   
                 rdpsnd_queue_write(rdpsnd_dsp_process  
                                    (s, current_driver, &formats[current_format]), tick,  
                                    packet_index);  
                 awaiting_data_packet = False;  
                 return;  
         }  
   
         in_uint8(s, type);  
         in_uint8s(s, 1);        /* unknown? */  
         in_uint16_le(s, datalen);  
248    
249          switch (type)                          rdpsnd_queue_write(rdpsnd_dsp_process
250          {                                             (s->p, s->end - s->p, current_driver,
251                  case RDPSND_WRITE:                                              &formats[current_format]), tick, packet_index);
252                          in_uint16_le(s, tick);                          return;
                         in_uint16_le(s, format);  
                         in_uint8(s, packet_index);  
                         /* Here are our lost bytes, but why? */  
                         memcpy(missing_bytes, s->end - 4, 4);  
                         awaiting_data_packet = True;  
253                          break;                          break;
254                  case RDPSND_CLOSE:                  case RDPSND_CLOSE:
255                            DEBUG_SOUND(("RDPSND: RDPSND_CLOSE()\n"));
256                          current_driver->wave_out_close();                          current_driver->wave_out_close();
257                          device_open = False;                          device_open = False;
258                          break;                          break;
259                  case RDPSND_NEGOTIATE:                  case RDPSND_NEGOTIATE:
260                          rdpsnd_process_negotiate(s);                          rdpsnd_process_negotiate(s);
261                          break;                          break;
262                  case RDPSND_SERVERTICK:                  case RDPSND_PING:
263                          rdpsnd_process_servertick(s);                          rdpsnd_process_ping(s);
264                          break;                          break;
265                  case RDPSND_SET_VOLUME:                  case RDPSND_SET_VOLUME:
266                          in_uint32(s, volume);                          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)                          if (device_open)
270                          {                                  current_driver->wave_out_volume(vol_left, vol_right);
                                 current_driver->wave_out_volume((volume & 0xffff),  
                                                                 (volume & 0xffff0000) >> 16);  
                         }  
271                          break;                          break;
272                  default:                  default:
273                          unimpl("RDPSND packet type %d\n", type);                          unimpl("RDPSND packet type %x\n", opcode);
274                          break;                          break;
275          }          }
276  }  }
277    
278    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 ((s->end - s->p) < 4)
289                            {
290                                    error("RDPSND: Split at packet header. Things will go south from here...\n");
291                                    return;
292                            }
293                            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                                    if ((packet.p - packet.data) < 12)
312                                            len = MIN(len, 12 - (packet.p - packet.data));
313                                    else if ((packet.p - packet.data) == 12)
314                                    {
315                                            DEBUG_SOUND(("RDPSND: Eating 4 bytes of %d bytes...\n",
316                                                         len));
317                                            in_uint8s(s, 4);
318                                            len -= 4;
319                                    }
320                            }
321    
322                            in_uint8a(s, packet.p, len);
323                            packet.p += len;
324                    }
325    
326                    /* Packet fully assembled */
327                    if (packet.p == packet.end)
328                    {
329                            packet.p = packet.data;
330                            rdpsnd_process_packet(packet_opcode, &packet);
331                            packet.size = 0;
332                    }
333            }
334    }
335    
336  static BOOL  static BOOL
337  rdpsnd_auto_open(void)  rdpsnd_auto_open(void)
338  {  {
# Line 357  rdpsnd_init(char *optarg) Line 408  rdpsnd_init(char *optarg)
408    
409          drivers = NULL;          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);
# Line 561  rdpsnd_queue_complete_pending(void) Line 616  rdpsnd_queue_complete_pending(void)
616    
617                  elapsed = (packet->completion_tv.tv_sec - packet->arrive_tv.tv_sec) * 1000000 +                  elapsed = (packet->completion_tv.tv_sec - packet->arrive_tv.tv_sec) * 1000000 +
618                          (packet->completion_tv.tv_usec - packet->arrive_tv.tv_usec);                          (packet->completion_tv.tv_usec - packet->arrive_tv.tv_usec);
619                    elapsed /= 1000;
620    
621                  xfree(packet->s.data);                  xfree(packet->s.data);
622                  rdpsnd_send_completion((packet->tick + elapsed) % 65536, packet->index);                  rdpsnd_send_completion((packet->tick + elapsed) % 65536, packet->index);

Legend:
Removed from v.1332  
changed lines
  Added in v.1343

  ViewVC Help
Powered by ViewVC 1.1.26