/[rdesktop]/jpeg/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

Annotation of /jpeg/rdesktop/trunk/rdpsnd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 665 - (hide annotations)
Sat Apr 17 07:24:22 2004 UTC (20 years, 1 month ago) by astrand
Original Path: sourceforge.net/trunk/rdesktop/rdpsnd.c
File MIME type: text/plain
File size: 6074 byte(s)
Made internal functions static.

1 matthewc 474 /*
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 matthewc 432 #include "rdesktop.h"
23    
24 matthewc 474 #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 matthewc 432 static VCHANNEL *rdpsnd_channel;
35    
36 matthewc 474 static BOOL device_open;
37     static WAVEFORMATEX formats[MAX_FORMATS];
38     static unsigned int format_count;
39     static unsigned int current_format;
40    
41 astrand 665 static STREAM
42 matthewc 474 rdpsnd_init_packet(uint16 type, uint16 size)
43     {
44     STREAM s;
45    
46 astrand 499 s = channel_init(rdpsnd_channel, size + 4);
47 matthewc 474 out_uint16_le(s, type);
48     out_uint16_le(s, size);
49     return s;
50     }
51    
52 astrand 665 static void
53 matthewc 474 rdpsnd_send(STREAM s)
54     {
55     #ifdef RDPSND_DEBUG
56     printf("RDPSND send:\n");
57 astrand 499 hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);
58 matthewc 474 #endif
59    
60     channel_send(s, rdpsnd_channel);
61     }
62    
63 astrand 499 void
64     rdpsnd_send_completion(uint16 tick, uint8 packet_index)
65 matthewc 474 {
66     STREAM s;
67    
68     s = rdpsnd_init_packet(RDPSND_COMPLETION, 4);
69 astrand 499 out_uint16_le(s, tick + 50);
70 matthewc 474 out_uint8(s, packet_index);
71     out_uint8(s, 0);
72     s_mark_end(s);
73     rdpsnd_send(s);
74     }
75    
76 astrand 665 static void
77 matthewc 474 rdpsnd_process_negotiate(STREAM in)
78     {
79     unsigned int in_format_count, i;
80     WAVEFORMATEX *format;
81     STREAM out;
82 stargo 491 BOOL device_available = False;
83 stargo 493 int readcnt;
84     int discardcnt;
85 matthewc 474
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 stargo 491 if (wave_out_open())
91     {
92     wave_out_close();
93     device_available = True;
94     }
95    
96 matthewc 474 format_count = 0;
97 astrand 499 if (s_check_rem(in, 18 * in_format_count))
98 matthewc 474 {
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 stargo 492 /* read in the buffer of unknown use */
111 stargo 493 readcnt = format->cbSize;
112     discardcnt = 0;
113 stargo 492 if (format->cbSize > MAX_CBSIZE)
114     {
115 astrand 499 fprintf(stderr, "cbSize too large for buffer: %d\n",
116     format->cbSize);
117 stargo 492 readcnt = MAX_CBSIZE;
118     discardcnt = format->cbSize - MAX_CBSIZE;
119     }
120     in_uint8a(in, format->cb, readcnt);
121     in_uint8s(in, discardcnt);
122    
123 stargo 491 if (device_available && wave_out_format_supported(format))
124 matthewc 474 {
125     format_count++;
126     if (format_count == MAX_FORMATS)
127     break;
128     }
129     }
130     }
131    
132 astrand 499 out = rdpsnd_init_packet(RDPSND_NEGOTIATE | 0x200, 20 + 18 * format_count);
133     out_uint32_le(out, 3); /* flags */
134 matthewc 474 out_uint32(out, 0xffffffff); /* volume */
135 astrand 499 out_uint32(out, 0); /* pitch */
136     out_uint16(out, 0); /* UDP port */
137 matthewc 474
138     out_uint16_le(out, format_count);
139 astrand 499 out_uint8(out, 0x95); /* pad? */
140     out_uint16_le(out, 2); /* status */
141     out_uint8(out, 0x77); /* pad? */
142 matthewc 474
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 astrand 499 out_uint16(out, 0); /* cbSize */
153 matthewc 474 }
154    
155     s_mark_end(out);
156     rdpsnd_send(out);
157     }
158    
159 astrand 665 static void
160 matthewc 474 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 astrand 665 static void
177 matthewc 432 rdpsnd_process(STREAM s)
178     {
179 matthewc 474 uint8 type;
180     uint16 datalen;
181 stargo 491 uint32 volume;
182 matthewc 474 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 astrand 499 hexdump(s->p, s->end - s->p);
189 matthewc 474 #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 astrand 499 in_uint8s(s, 1); /* unknown? */
224 matthewc 474 in_uint16_le(s, datalen);
225    
226     switch (type)
227     {
228 astrand 499 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 matthewc 474 }
255 matthewc 432 }
256    
257     BOOL
258     rdpsnd_init(void)
259     {
260 astrand 435 rdpsnd_channel =
261     channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
262     rdpsnd_process);
263 matthewc 432 return (rdpsnd_channel != NULL);
264     }

  ViewVC Help
Powered by ViewVC 1.1.26