/[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

Annotation of /sourceforge.net/rdesktop/trunk/rdpsnd.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 493 - (hide annotations)
Tue Oct 14 07:53:10 2003 UTC (20 years, 7 months ago) by stargo
Original Path: sourceforge.net/trunk/rdesktop/rdpsnd.c
File MIME type: text/plain
File size: 6000 byte(s)
fix gccism

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     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 rdpsnd_send_completion(uint16 tick, uint8 packet_index)
64     {
65     STREAM s;
66    
67     s = rdpsnd_init_packet(RDPSND_COMPLETION, 4);
68     out_uint16_le(s, tick+50);
69     out_uint8(s, packet_index);
70     out_uint8(s, 0);
71     s_mark_end(s);
72     rdpsnd_send(s);
73     }
74    
75     void
76     rdpsnd_process_negotiate(STREAM in)
77     {
78     unsigned int in_format_count, i;
79     WAVEFORMATEX *format;
80     STREAM out;
81 stargo 491 BOOL device_available = False;
82 stargo 493 int readcnt;
83     int discardcnt;
84 matthewc 474
85     in_uint8s(in, 14); /* flags, volume, pitch, UDP port */
86     in_uint16_le(in, in_format_count);
87     in_uint8s(in, 4); /* pad, status, pad */
88    
89 stargo 491 if (wave_out_open())
90     {
91     wave_out_close();
92     device_available = True;
93     }
94    
95 matthewc 474 format_count = 0;
96     if (s_check_rem(in, 18*in_format_count))
97     {
98     for (i = 0; i < in_format_count; i++)
99     {
100     format = &formats[format_count];
101     in_uint16_le(in, format->wFormatTag);
102     in_uint16_le(in, format->nChannels);
103     in_uint32_le(in, format->nSamplesPerSec);
104     in_uint32_le(in, format->nAvgBytesPerSec);
105     in_uint16_le(in, format->nBlockAlign);
106     in_uint16_le(in, format->wBitsPerSample);
107     in_uint16_le(in, format->cbSize);
108    
109 stargo 492 /* read in the buffer of unknown use */
110 stargo 493 readcnt = format->cbSize;
111     discardcnt = 0;
112 stargo 492 if (format->cbSize > MAX_CBSIZE)
113     {
114     fprintf(stderr, "cbSize too large for buffer: %d\n", format->cbSize);
115     readcnt = MAX_CBSIZE;
116     discardcnt = format->cbSize - MAX_CBSIZE;
117     }
118     in_uint8a(in, format->cb, readcnt);
119     in_uint8s(in, discardcnt);
120    
121 stargo 491 if (device_available && wave_out_format_supported(format))
122 matthewc 474 {
123     format_count++;
124     if (format_count == MAX_FORMATS)
125     break;
126     }
127     }
128     }
129    
130     out = rdpsnd_init_packet(RDPSND_NEGOTIATE | 0x200, 20 + 18*format_count);
131     out_uint32_le(out, 3); /* flags */
132     out_uint32(out, 0xffffffff); /* volume */
133     out_uint32(out, 0); /* pitch */
134     out_uint16(out, 0); /* UDP port */
135    
136     out_uint16_le(out, format_count);
137     out_uint8(out, 0x95); /* pad? */
138     out_uint16_le(out, 2); /* status */
139     out_uint8(out, 0x77); /* pad? */
140    
141     for (i = 0; i < format_count; i++)
142     {
143     format = &formats[i];
144     out_uint16_le(out, format->wFormatTag);
145     out_uint16_le(out, format->nChannels);
146     out_uint32_le(out, format->nSamplesPerSec);
147     out_uint32_le(out, format->nAvgBytesPerSec);
148     out_uint16_le(out, format->nBlockAlign);
149     out_uint16_le(out, format->wBitsPerSample);
150     out_uint16(out, 0); /* cbSize */
151     }
152    
153     s_mark_end(out);
154     rdpsnd_send(out);
155     }
156    
157     void
158     rdpsnd_process_unknown6(STREAM in)
159     {
160     uint16 unknown1, unknown2;
161     STREAM out;
162    
163     /* in_uint8s(in, 4); unknown */
164     in_uint16_le(in, unknown1);
165     in_uint16_le(in, unknown2);
166    
167     out = rdpsnd_init_packet(RDPSND_UNKNOWN6 | 0x2300, 4);
168     out_uint16_le(out, unknown1);
169     out_uint16_le(out, unknown2);
170     s_mark_end(out);
171     rdpsnd_send(out);
172     }
173    
174     void
175 matthewc 432 rdpsnd_process(STREAM s)
176     {
177 matthewc 474 uint8 type;
178     uint16 datalen;
179 stargo 491 uint32 volume;
180 matthewc 474 static uint16 tick, format;
181     static uint8 packet_index;
182     static BOOL awaiting_data_packet;
183    
184     #ifdef RDPSND_DEBUG
185     printf("RDPSND recv:\n");
186     hexdump(s->p, s->end-s->p);
187     #endif
188    
189     if (awaiting_data_packet)
190     {
191     if (format >= MAX_FORMATS)
192     {
193     error("RDPSND: Invalid format index\n");
194     return;
195     }
196    
197     if (!device_open || (format != current_format))
198     {
199     if (!device_open && !wave_out_open())
200     {
201     rdpsnd_send_completion(tick, packet_index);
202     return;
203     }
204     if (!wave_out_set_format(&formats[format]))
205     {
206     rdpsnd_send_completion(tick, packet_index);
207     wave_out_close();
208     device_open = False;
209     return;
210     }
211     device_open = True;
212     current_format = format;
213     }
214    
215     wave_out_write(s, tick, packet_index);
216     awaiting_data_packet = False;
217     return;
218     }
219    
220     in_uint8(s, type);
221     in_uint8s(s, 1); /* unknown? */
222     in_uint16_le(s, datalen);
223    
224     switch (type)
225     {
226     case RDPSND_WRITE:
227     in_uint16_le(s, tick);
228     in_uint16_le(s, format);
229     in_uint8(s, packet_index);
230     awaiting_data_packet = True;
231     break;
232     case RDPSND_CLOSE:
233     wave_out_close();
234     device_open = False;
235     break;
236     case RDPSND_NEGOTIATE:
237     rdpsnd_process_negotiate(s);
238     break;
239     case RDPSND_UNKNOWN6:
240     rdpsnd_process_unknown6(s);
241     break;
242     case RDPSND_SET_VOLUME:
243 stargo 491 in_uint32(s, volume);
244     if ( device_open )
245     {
246     wave_out_volume((volume & 0xffff), (volume & 0xffff0000) >> 16);
247     }
248 matthewc 474 break;
249     default:
250     unimpl("RDPSND packet type %d\n", type);
251     break;
252     }
253 matthewc 432 }
254    
255     BOOL
256     rdpsnd_init(void)
257     {
258 astrand 435 rdpsnd_channel =
259     channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
260     rdpsnd_process);
261 matthewc 432 return (rdpsnd_channel != NULL);
262     }

  ViewVC Help
Powered by ViewVC 1.1.26