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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 491 - (show annotations)
Mon Oct 13 16:09:45 2003 UTC (20 years, 7 months ago) by stargo
Original Path: sourceforge.net/trunk/rdesktop/rdpsnd.c
File MIME type: text/plain
File size: 5616 byte(s)
Volume control for OSS & SUN
Ignore first 4 bytes of audio-packet (clicking noise)

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

  ViewVC Help
Powered by ViewVC 1.1.26