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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1254 - (show annotations)
Sun Sep 17 10:32:18 2006 UTC (17 years, 8 months ago) by stargo
File MIME type: text/plain
File size: 7338 byte(s)
unify queue-handling in rdpsnd.c (remove private copies from all
drivers)

1 /* -*- c-basic-offset: 8 -*-
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 #include "rdpsnd.h"
24
25 #define RDPSND_CLOSE 1
26 #define RDPSND_WRITE 2
27 #define RDPSND_SET_VOLUME 3
28 #define RDPSND_UNKNOWN4 4
29 #define RDPSND_COMPLETION 5
30 #define RDPSND_SERVERTICK 6
31 #define RDPSND_NEGOTIATE 7
32
33 #define MAX_FORMATS 10
34 #define MAX_QUEUE 10
35
36 BOOL g_dsp_busy = False;
37 int g_dsp_fd;
38
39 static VCHANNEL *rdpsnd_channel;
40
41 static BOOL device_open;
42 static WAVEFORMATEX formats[MAX_FORMATS];
43 static unsigned int format_count;
44 static unsigned int current_format;
45 static unsigned int queue_hi, queue_lo;
46 static struct audio_packet packet_queue[MAX_QUEUE];
47
48 static STREAM
49 rdpsnd_init_packet(uint16 type, uint16 size)
50 {
51 STREAM s;
52
53 s = channel_init(rdpsnd_channel, size + 4);
54 out_uint16_le(s, type);
55 out_uint16_le(s, size);
56 return s;
57 }
58
59 static void
60 rdpsnd_send(STREAM s)
61 {
62 #ifdef RDPSND_DEBUG
63 printf("RDPSND send:\n");
64 hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);
65 #endif
66
67 channel_send(s, rdpsnd_channel);
68 }
69
70 void
71 rdpsnd_send_completion(uint16 tick, uint8 packet_index)
72 {
73 STREAM s;
74
75 s = rdpsnd_init_packet(RDPSND_COMPLETION, 4);
76 out_uint16_le(s, tick);
77 out_uint8(s, packet_index);
78 out_uint8(s, 0);
79 s_mark_end(s);
80 rdpsnd_send(s);
81 }
82
83 static void
84 rdpsnd_process_negotiate(STREAM in)
85 {
86 unsigned int in_format_count, i;
87 WAVEFORMATEX *format;
88 STREAM out;
89 BOOL device_available = False;
90 int readcnt;
91 int discardcnt;
92
93 in_uint8s(in, 14); /* flags, volume, pitch, UDP port */
94 in_uint16_le(in, in_format_count);
95 in_uint8s(in, 4); /* pad, status, pad */
96
97 if (wave_out_open())
98 {
99 wave_out_close();
100 device_available = True;
101 }
102
103 format_count = 0;
104 if (s_check_rem(in, 18 * in_format_count))
105 {
106 for (i = 0; i < in_format_count; i++)
107 {
108 format = &formats[format_count];
109 in_uint16_le(in, format->wFormatTag);
110 in_uint16_le(in, format->nChannels);
111 in_uint32_le(in, format->nSamplesPerSec);
112 in_uint32_le(in, format->nAvgBytesPerSec);
113 in_uint16_le(in, format->nBlockAlign);
114 in_uint16_le(in, format->wBitsPerSample);
115 in_uint16_le(in, format->cbSize);
116
117 /* read in the buffer of unknown use */
118 readcnt = format->cbSize;
119 discardcnt = 0;
120 if (format->cbSize > MAX_CBSIZE)
121 {
122 fprintf(stderr, "cbSize too large for buffer: %d\n",
123 format->cbSize);
124 readcnt = MAX_CBSIZE;
125 discardcnt = format->cbSize - MAX_CBSIZE;
126 }
127 in_uint8a(in, format->cb, readcnt);
128 in_uint8s(in, discardcnt);
129
130 if (device_available && wave_out_format_supported(format))
131 {
132 format_count++;
133 if (format_count == MAX_FORMATS)
134 break;
135 }
136 }
137 }
138
139 out = rdpsnd_init_packet(RDPSND_NEGOTIATE | 0x200, 20 + 18 * format_count);
140 out_uint32_le(out, 3); /* flags */
141 out_uint32(out, 0xffffffff); /* volume */
142 out_uint32(out, 0); /* pitch */
143 out_uint16(out, 0); /* UDP port */
144
145 out_uint16_le(out, format_count);
146 out_uint8(out, 0x95); /* pad? */
147 out_uint16_le(out, 2); /* status */
148 out_uint8(out, 0x77); /* pad? */
149
150 for (i = 0; i < format_count; i++)
151 {
152 format = &formats[i];
153 out_uint16_le(out, format->wFormatTag);
154 out_uint16_le(out, format->nChannels);
155 out_uint32_le(out, format->nSamplesPerSec);
156 out_uint32_le(out, format->nAvgBytesPerSec);
157 out_uint16_le(out, format->nBlockAlign);
158 out_uint16_le(out, format->wBitsPerSample);
159 out_uint16(out, 0); /* cbSize */
160 }
161
162 s_mark_end(out);
163 rdpsnd_send(out);
164 }
165
166 static void
167 rdpsnd_process_servertick(STREAM in)
168 {
169 uint16 tick1, tick2;
170 STREAM out;
171
172 /* in_uint8s(in, 4); unknown */
173 in_uint16_le(in, tick1);
174 in_uint16_le(in, tick2);
175
176 out = rdpsnd_init_packet(RDPSND_SERVERTICK | 0x2300, 4);
177 out_uint16_le(out, tick1);
178 out_uint16_le(out, tick2);
179 s_mark_end(out);
180 rdpsnd_send(out);
181 }
182
183 static void
184 rdpsnd_process(STREAM s)
185 {
186 uint8 type;
187 uint16 datalen;
188 uint32 volume;
189 static uint16 tick, format;
190 static uint8 packet_index;
191 static BOOL awaiting_data_packet;
192
193 #ifdef RDPSND_DEBUG
194 printf("RDPSND recv:\n");
195 hexdump(s->p, s->end - s->p);
196 #endif
197
198 if (awaiting_data_packet)
199 {
200 if (format >= MAX_FORMATS)
201 {
202 error("RDPSND: Invalid format index\n");
203 return;
204 }
205
206 if (!device_open || (format != current_format))
207 {
208 if (!device_open && !wave_out_open())
209 {
210 rdpsnd_send_completion(tick, packet_index);
211 return;
212 }
213 if (!wave_out_set_format(&formats[format]))
214 {
215 rdpsnd_send_completion(tick, packet_index);
216 wave_out_close();
217 device_open = False;
218 return;
219 }
220 device_open = True;
221 current_format = format;
222 }
223
224 rdpsnd_queue_write(s, tick, packet_index);
225 awaiting_data_packet = False;
226 return;
227 }
228
229 in_uint8(s, type);
230 in_uint8s(s, 1); /* unknown? */
231 in_uint16_le(s, datalen);
232
233 switch (type)
234 {
235 case RDPSND_WRITE:
236 in_uint16_le(s, tick);
237 in_uint16_le(s, format);
238 in_uint8(s, packet_index);
239 awaiting_data_packet = True;
240 break;
241 case RDPSND_CLOSE:
242 wave_out_close();
243 device_open = False;
244 break;
245 case RDPSND_NEGOTIATE:
246 rdpsnd_process_negotiate(s);
247 break;
248 case RDPSND_SERVERTICK:
249 rdpsnd_process_servertick(s);
250 break;
251 case RDPSND_SET_VOLUME:
252 in_uint32(s, volume);
253 if (device_open)
254 {
255 wave_out_volume((volume & 0xffff), (volume & 0xffff0000) >> 16);
256 }
257 break;
258 default:
259 unimpl("RDPSND packet type %d\n", type);
260 break;
261 }
262 }
263
264 BOOL
265 rdpsnd_init(void)
266 {
267 rdpsnd_channel =
268 channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
269 rdpsnd_process);
270
271 return (rdpsnd_channel != NULL);
272 }
273
274 void
275 rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)
276 {
277 struct audio_packet *packet = &packet_queue[queue_hi];
278 unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
279
280 if (next_hi == queue_lo)
281 {
282 error("No space to queue audio packet\n");
283 return;
284 }
285
286 queue_hi = next_hi;
287
288 packet->s = *s;
289 packet->tick = tick;
290 packet->index = index;
291 packet->s.p += 4;
292
293 /* we steal the data buffer from s, give it a new one */
294 s->data = malloc(s->size);
295
296 if (!g_dsp_busy)
297 wave_out_play();
298 }
299
300 inline struct audio_packet *
301 rdpsnd_queue_current_packet(void)
302 {
303 return &packet_queue[queue_lo];
304 }
305
306 inline BOOL
307 rdpsnd_queue_empty(void)
308 {
309 return (queue_lo == queue_hi);
310 }
311
312 inline void
313 rdpsnd_queue_init(void)
314 {
315 queue_lo = queue_hi = 0;
316 }
317
318 inline void
319 rdpsnd_queue_next(void)
320 {
321 free(packet_queue[queue_lo].s.data);
322 queue_lo = (queue_lo + 1) % MAX_QUEUE;
323 }
324
325 inline int
326 rdpsnd_queue_next_tick(void)
327 {
328 if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
329 {
330 return packet_queue[(queue_lo + 1) % MAX_QUEUE].tick;
331 }
332 else
333 {
334 return (packet_queue[queue_lo].tick + 65535) % 65536;
335 }
336 }

  ViewVC Help
Powered by ViewVC 1.1.26