/[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 432 by matthewc, Tue Jul 1 09:31:25 2003 UTC revision 499 by astrand, Wed Oct 15 14:01:32 2003 UTC
# Line 1  Line 1 
1    /*
2       rdesktop: A Remote Desktop Protocol client.
3       Sound Channel Process Functions
4       Copyright (C) Matthew Chapman 2003
5       Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003
6    
7       This program is free software; you can redistribute it and/or modify
8       it under the terms of the GNU General Public License as published by
9       the Free Software Foundation; either version 2 of the License, or
10       (at your option) any later version.
11    
12       This program is distributed in the hope that it will be useful,
13       but WITHOUT ANY WARRANTY; without even the implied warranty of
14       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15       GNU General Public License for more details.
16    
17       You should have received a copy of the GNU General Public License
18       along with this program; if not, write to the Free Software
19       Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20    */
21    
22  #include "rdesktop.h"  #include "rdesktop.h"
23    
24    #define RDPSND_CLOSE            1
25    #define RDPSND_WRITE            2
26    #define RDPSND_SET_VOLUME       3
27    #define RDPSND_UNKNOWN4         4
28    #define RDPSND_COMPLETION       5
29    #define RDPSND_UNKNOWN6         6
30    #define RDPSND_NEGOTIATE        7
31    
32    #define MAX_FORMATS             10
33    
34  static VCHANNEL *rdpsnd_channel;  static VCHANNEL *rdpsnd_channel;
35    
36  static void  static BOOL device_open;
37    static WAVEFORMATEX formats[MAX_FORMATS];
38    static unsigned int format_count;
39    static unsigned int current_format;
40    
41    STREAM
42    rdpsnd_init_packet(uint16 type, uint16 size)
43    {
44            STREAM s;
45    
46            s = channel_init(rdpsnd_channel, size + 4);
47            out_uint16_le(s, type);
48            out_uint16_le(s, size);
49            return s;
50    }
51    
52    void
53    rdpsnd_send(STREAM s)
54    {
55    #ifdef RDPSND_DEBUG
56            printf("RDPSND send:\n");
57            hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);
58    #endif
59    
60            channel_send(s, rdpsnd_channel);
61    }
62    
63    void
64    rdpsnd_send_completion(uint16 tick, uint8 packet_index)
65    {
66            STREAM s;
67    
68            s = rdpsnd_init_packet(RDPSND_COMPLETION, 4);
69            out_uint16_le(s, tick + 50);
70            out_uint8(s, packet_index);
71            out_uint8(s, 0);
72            s_mark_end(s);
73            rdpsnd_send(s);
74    }
75    
76    void
77    rdpsnd_process_negotiate(STREAM in)
78    {
79            unsigned int in_format_count, i;
80            WAVEFORMATEX *format;
81            STREAM out;
82            BOOL device_available = False;
83            int readcnt;
84            int discardcnt;
85    
86            in_uint8s(in, 14);      /* flags, volume, pitch, UDP port */
87            in_uint16_le(in, in_format_count);
88            in_uint8s(in, 4);       /* pad, status, pad */
89    
90            if (wave_out_open())
91            {
92                    wave_out_close();
93                    device_available = True;
94            }
95    
96            format_count = 0;
97            if (s_check_rem(in, 18 * in_format_count))
98            {
99                    for (i = 0; i < in_format_count; i++)
100                    {
101                            format = &formats[format_count];
102                            in_uint16_le(in, format->wFormatTag);
103                            in_uint16_le(in, format->nChannels);
104                            in_uint32_le(in, format->nSamplesPerSec);
105                            in_uint32_le(in, format->nAvgBytesPerSec);
106                            in_uint16_le(in, format->nBlockAlign);
107                            in_uint16_le(in, format->wBitsPerSample);
108                            in_uint16_le(in, format->cbSize);
109    
110                            /* read in the buffer of unknown use */
111                            readcnt = format->cbSize;
112                            discardcnt = 0;
113                            if (format->cbSize > MAX_CBSIZE)
114                            {
115                                    fprintf(stderr, "cbSize too large for buffer: %d\n",
116                                            format->cbSize);
117                                    readcnt = MAX_CBSIZE;
118                                    discardcnt = format->cbSize - MAX_CBSIZE;
119                            }
120                            in_uint8a(in, format->cb, readcnt);
121                            in_uint8s(in, discardcnt);
122    
123                            if (device_available && wave_out_format_supported(format))
124                            {
125                                    format_count++;
126                                    if (format_count == MAX_FORMATS)
127                                            break;
128                            }
129                    }
130            }
131    
132            out = rdpsnd_init_packet(RDPSND_NEGOTIATE | 0x200, 20 + 18 * format_count);
133            out_uint32_le(out, 3);  /* flags */
134            out_uint32(out, 0xffffffff);    /* volume */
135            out_uint32(out, 0);     /* pitch */
136            out_uint16(out, 0);     /* UDP port */
137    
138            out_uint16_le(out, format_count);
139            out_uint8(out, 0x95);   /* pad? */
140            out_uint16_le(out, 2);  /* status */
141            out_uint8(out, 0x77);   /* pad? */
142    
143            for (i = 0; i < format_count; i++)
144            {
145                    format = &formats[i];
146                    out_uint16_le(out, format->wFormatTag);
147                    out_uint16_le(out, format->nChannels);
148                    out_uint32_le(out, format->nSamplesPerSec);
149                    out_uint32_le(out, format->nAvgBytesPerSec);
150                    out_uint16_le(out, format->nBlockAlign);
151                    out_uint16_le(out, format->wBitsPerSample);
152                    out_uint16(out, 0);     /* cbSize */
153            }
154    
155            s_mark_end(out);
156            rdpsnd_send(out);
157    }
158    
159    void
160    rdpsnd_process_unknown6(STREAM in)
161    {
162            uint16 unknown1, unknown2;
163            STREAM out;
164    
165            /* in_uint8s(in, 4); unknown */
166            in_uint16_le(in, unknown1);
167            in_uint16_le(in, unknown2);
168    
169            out = rdpsnd_init_packet(RDPSND_UNKNOWN6 | 0x2300, 4);
170            out_uint16_le(out, unknown1);
171            out_uint16_le(out, unknown2);
172            s_mark_end(out);
173            rdpsnd_send(out);
174    }
175    
176    void
177  rdpsnd_process(STREAM s)  rdpsnd_process(STREAM s)
178  {  {
179          printf("rdpsnd_process\n");          uint8 type;
180          hexdump(s->p, s->end-s->p);          uint16 datalen;
181            uint32 volume;
182            static uint16 tick, format;
183            static uint8 packet_index;
184            static BOOL awaiting_data_packet;
185    
186    #ifdef RDPSND_DEBUG
187            printf("RDPSND recv:\n");
188            hexdump(s->p, s->end - s->p);
189    #endif
190    
191            if (awaiting_data_packet)
192            {
193                    if (format >= MAX_FORMATS)
194                    {
195                            error("RDPSND: Invalid format index\n");
196                            return;
197                    }
198    
199                    if (!device_open || (format != current_format))
200                    {
201                            if (!device_open && !wave_out_open())
202                            {
203                                    rdpsnd_send_completion(tick, packet_index);
204                                    return;
205                            }
206                            if (!wave_out_set_format(&formats[format]))
207                            {
208                                    rdpsnd_send_completion(tick, packet_index);
209                                    wave_out_close();
210                                    device_open = False;
211                                    return;
212                            }
213                            device_open = True;
214                            current_format = format;
215                    }
216    
217                    wave_out_write(s, tick, packet_index);
218                    awaiting_data_packet = False;
219                    return;
220            }
221    
222            in_uint8(s, type);
223            in_uint8s(s, 1);        /* unknown? */
224            in_uint16_le(s, datalen);
225    
226            switch (type)
227            {
228                    case RDPSND_WRITE:
229                            in_uint16_le(s, tick);
230                            in_uint16_le(s, format);
231                            in_uint8(s, packet_index);
232                            awaiting_data_packet = True;
233                            break;
234                    case RDPSND_CLOSE:
235                            wave_out_close();
236                            device_open = False;
237                            break;
238                    case RDPSND_NEGOTIATE:
239                            rdpsnd_process_negotiate(s);
240                            break;
241                    case RDPSND_UNKNOWN6:
242                            rdpsnd_process_unknown6(s);
243                            break;
244                    case RDPSND_SET_VOLUME:
245                            in_uint32(s, volume);
246                            if (device_open)
247                            {
248                                    wave_out_volume((volume & 0xffff), (volume & 0xffff0000) >> 16);
249                            }
250                            break;
251                    default:
252                            unimpl("RDPSND packet type %d\n", type);
253                            break;
254            }
255  }  }
256    
257  BOOL  BOOL
258  rdpsnd_init(void)  rdpsnd_init(void)
259  {  {
260          rdpsnd_channel = channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP, rdpsnd_process);          rdpsnd_channel =
261                    channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
262                                     rdpsnd_process);
263          return (rdpsnd_channel != NULL);          return (rdpsnd_channel != NULL);
264  }  }

Legend:
Removed from v.432  
changed lines
  Added in v.499

  ViewVC Help
Powered by ViewVC 1.1.26