/[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 1299 - (show annotations)
Thu Oct 19 11:28:53 2006 UTC (17 years, 7 months ago) by ossman_
Original Path: sourceforge.net/trunk/rdesktop/rdpsnd.c
File MIME type: text/plain
File size: 10210 byte(s)
Inline functions with external linkage is a gcc-ism and not kosher under C99.

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 <assert.h>
23
24 #include "rdesktop.h"
25 #include "rdpsnd.h"
26 #include "rdpsnd_dsp.h"
27
28 #define RDPSND_CLOSE 1
29 #define RDPSND_WRITE 2
30 #define RDPSND_SET_VOLUME 3
31 #define RDPSND_UNKNOWN4 4
32 #define RDPSND_COMPLETION 5
33 #define RDPSND_SERVERTICK 6
34 #define RDPSND_NEGOTIATE 7
35
36 #define MAX_FORMATS 10
37 #define MAX_QUEUE 10
38
39 BOOL g_dsp_busy = False;
40 int g_dsp_fd;
41
42 static VCHANNEL *rdpsnd_channel;
43 static struct audio_driver *drivers = NULL;
44 struct audio_driver *current_driver = NULL;
45
46 static BOOL device_open;
47 static WAVEFORMATEX formats[MAX_FORMATS];
48 static unsigned int format_count;
49 static unsigned int current_format;
50 unsigned int queue_hi, queue_lo;
51 struct audio_packet packet_queue[MAX_QUEUE];
52
53 void (*wave_out_play) (void);
54
55 static STREAM
56 rdpsnd_init_packet(uint16 type, uint16 size)
57 {
58 STREAM s;
59
60 s = channel_init(rdpsnd_channel, size + 4);
61 out_uint16_le(s, type);
62 out_uint16_le(s, size);
63 return s;
64 }
65
66 static void
67 rdpsnd_send(STREAM s)
68 {
69 #ifdef RDPSND_DEBUG
70 printf("RDPSND send:\n");
71 hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);
72 #endif
73
74 channel_send(s, rdpsnd_channel);
75 }
76
77 void
78 rdpsnd_send_completion(uint16 tick, uint8 packet_index)
79 {
80 STREAM s;
81
82 s = rdpsnd_init_packet(RDPSND_COMPLETION, 4);
83 out_uint16_le(s, tick);
84 out_uint8(s, packet_index);
85 out_uint8(s, 0);
86 s_mark_end(s);
87 rdpsnd_send(s);
88 }
89
90 static void
91 rdpsnd_process_negotiate(STREAM in)
92 {
93 unsigned int in_format_count, i;
94 WAVEFORMATEX *format;
95 STREAM out;
96 BOOL device_available = False;
97 int readcnt;
98 int discardcnt;
99
100 in_uint8s(in, 14); /* flags, volume, pitch, UDP port */
101 in_uint16_le(in, in_format_count);
102 in_uint8s(in, 4); /* pad, status, pad */
103
104 if (current_driver->wave_out_open())
105 {
106 current_driver->wave_out_close();
107 device_available = True;
108 }
109
110 format_count = 0;
111 if (s_check_rem(in, 18 * in_format_count))
112 {
113 for (i = 0; i < in_format_count; i++)
114 {
115 format = &formats[format_count];
116 in_uint16_le(in, format->wFormatTag);
117 in_uint16_le(in, format->nChannels);
118 in_uint32_le(in, format->nSamplesPerSec);
119 in_uint32_le(in, format->nAvgBytesPerSec);
120 in_uint16_le(in, format->nBlockAlign);
121 in_uint16_le(in, format->wBitsPerSample);
122 in_uint16_le(in, format->cbSize);
123
124 /* read in the buffer of unknown use */
125 readcnt = format->cbSize;
126 discardcnt = 0;
127 if (format->cbSize > MAX_CBSIZE)
128 {
129 fprintf(stderr, "cbSize too large for buffer: %d\n",
130 format->cbSize);
131 readcnt = MAX_CBSIZE;
132 discardcnt = format->cbSize - MAX_CBSIZE;
133 }
134 in_uint8a(in, format->cb, readcnt);
135 in_uint8s(in, discardcnt);
136
137 if (device_available && current_driver->wave_out_format_supported(format))
138 {
139 format_count++;
140 if (format_count == MAX_FORMATS)
141 break;
142 }
143 }
144 }
145
146 out = rdpsnd_init_packet(RDPSND_NEGOTIATE | 0x200, 20 + 18 * format_count);
147 out_uint32_le(out, 3); /* flags */
148 out_uint32(out, 0xffffffff); /* volume */
149 out_uint32(out, 0); /* pitch */
150 out_uint16(out, 0); /* UDP port */
151
152 out_uint16_le(out, format_count);
153 out_uint8(out, 0x95); /* pad? */
154 out_uint16_le(out, 2); /* status */
155 out_uint8(out, 0x77); /* pad? */
156
157 for (i = 0; i < format_count; i++)
158 {
159 format = &formats[i];
160 out_uint16_le(out, format->wFormatTag);
161 out_uint16_le(out, format->nChannels);
162 out_uint32_le(out, format->nSamplesPerSec);
163 out_uint32_le(out, format->nAvgBytesPerSec);
164 out_uint16_le(out, format->nBlockAlign);
165 out_uint16_le(out, format->wBitsPerSample);
166 out_uint16(out, 0); /* cbSize */
167 }
168
169 s_mark_end(out);
170 rdpsnd_send(out);
171 }
172
173 static void
174 rdpsnd_process_servertick(STREAM in)
175 {
176 uint16 tick1, tick2;
177 STREAM out;
178
179 /* in_uint8s(in, 4); unknown */
180 in_uint16_le(in, tick1);
181 in_uint16_le(in, tick2);
182
183 out = rdpsnd_init_packet(RDPSND_SERVERTICK | 0x2300, 4);
184 out_uint16_le(out, tick1);
185 out_uint16_le(out, tick2);
186 s_mark_end(out);
187 rdpsnd_send(out);
188 }
189
190 static void
191 rdpsnd_process(STREAM s)
192 {
193 uint8 type;
194 uint16 datalen;
195 uint32 volume;
196 static uint16 tick, format;
197 static uint8 packet_index;
198 static BOOL awaiting_data_packet;
199 static unsigned char missing_bytes[4] = { 0, 0, 0, 0 };
200
201 #ifdef RDPSND_DEBUG
202 printf("RDPSND recv:\n");
203 hexdump(s->p, s->end - s->p);
204 #endif
205
206 if (awaiting_data_packet)
207 {
208 if (format >= MAX_FORMATS)
209 {
210 error("RDPSND: Invalid format index\n");
211 return;
212 }
213
214 if (!device_open || (format != current_format))
215 {
216 if (!device_open && !current_driver->wave_out_open())
217 {
218 rdpsnd_send_completion(tick, packet_index);
219 return;
220 }
221 if (!current_driver->wave_out_set_format(&formats[format]))
222 {
223 rdpsnd_send_completion(tick, packet_index);
224 current_driver->wave_out_close();
225 device_open = False;
226 return;
227 }
228 device_open = True;
229 current_format = format;
230 }
231
232 /* Insert the 4 missing bytes retrieved from last RDPSND_WRITE */
233 memcpy(s->data, missing_bytes, 4);
234
235 current_driver->
236 wave_out_write(rdpsnd_dsp_process
237 (s, current_driver, &formats[current_format]), tick,
238 packet_index);
239 awaiting_data_packet = False;
240 return;
241 }
242
243 in_uint8(s, type);
244 in_uint8s(s, 1); /* unknown? */
245 in_uint16_le(s, datalen);
246
247 switch (type)
248 {
249 case RDPSND_WRITE:
250 in_uint16_le(s, tick);
251 in_uint16_le(s, format);
252 in_uint8(s, packet_index);
253 /* Here are our lost bytes, but why? */
254 memcpy(missing_bytes, s->end - 4, 4);
255 awaiting_data_packet = True;
256 break;
257 case RDPSND_CLOSE:
258 current_driver->wave_out_close();
259 device_open = False;
260 break;
261 case RDPSND_NEGOTIATE:
262 rdpsnd_process_negotiate(s);
263 break;
264 case RDPSND_SERVERTICK:
265 rdpsnd_process_servertick(s);
266 break;
267 case RDPSND_SET_VOLUME:
268 in_uint32(s, volume);
269 if (device_open)
270 {
271 current_driver->wave_out_volume((volume & 0xffff),
272 (volume & 0xffff0000) >> 16);
273 }
274 break;
275 default:
276 unimpl("RDPSND packet type %d\n", type);
277 break;
278 }
279 }
280
281 static BOOL
282 rdpsnd_auto_open(void)
283 {
284 static BOOL failed = False;
285
286 if (!failed)
287 {
288 struct audio_driver *auto_driver = current_driver;
289
290 current_driver = drivers;
291 while (current_driver != NULL)
292 {
293 DEBUG(("trying %s...\n", current_driver->name));
294 if (current_driver->wave_out_open())
295 {
296 DEBUG(("selected %s\n", current_driver->name));
297 return True;
298 }
299 g_dsp_fd = 0;
300 current_driver = current_driver->next;
301 }
302
303 warning("no working audio-driver found\n");
304 failed = True;
305 current_driver = auto_driver;
306 }
307
308 return False;
309 }
310
311 static void
312 rdpsnd_register_drivers(char *options)
313 {
314 struct audio_driver **reg;
315
316 /* The order of registrations define the probe-order
317 when opening the device for the first time */
318 reg = &drivers;
319 #if defined(RDPSND_ALSA)
320 *reg = alsa_register(options);
321 assert(*reg);
322 reg = &((*reg)->next);
323 #endif
324 #if defined(RDPSND_SUN)
325 *reg = sun_register(options);
326 assert(*reg);
327 reg = &((*reg)->next);
328 #endif
329 #if defined(RDPSND_OSS)
330 *reg = oss_register(options);
331 assert(*reg);
332 reg = &((*reg)->next);
333 #endif
334 #if defined(RDPSND_SGI)
335 *reg = sgi_register(options);
336 assert(*reg);
337 reg = &((*reg)->next);
338 #endif
339 #if defined(RDPSND_LIBAO)
340 *reg = libao_register(options);
341 assert(*reg);
342 reg = &((*reg)->next);
343 #endif
344 }
345
346 BOOL
347 rdpsnd_init(char *optarg)
348 {
349 static struct audio_driver auto_driver;
350 struct audio_driver *pos;
351 char *driver = NULL, *options = NULL;
352
353 drivers = NULL;
354
355 rdpsnd_channel =
356 channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
357 rdpsnd_process);
358
359 if (rdpsnd_channel == NULL)
360 {
361 error("channel_register\n");
362 return False;
363 }
364
365 if (optarg != NULL && strlen(optarg) > 0)
366 {
367 driver = options = optarg;
368
369 while (*options != '\0' && *options != ':')
370 options++;
371
372 if (*options == ':')
373 {
374 *options = '\0';
375 options++;
376 }
377
378 if (*options == '\0')
379 options = NULL;
380 }
381
382 rdpsnd_register_drivers(options);
383
384 if (!driver)
385 {
386 auto_driver.wave_out_open = &rdpsnd_auto_open;
387 current_driver = &auto_driver;
388 return True;
389 }
390
391 pos = drivers;
392 while (pos != NULL)
393 {
394 if (!strcmp(pos->name, driver))
395 {
396 DEBUG(("selected %s\n", pos->name));
397 current_driver = pos;
398 return True;
399 }
400 pos = pos->next;
401 }
402 return False;
403 }
404
405 void
406 rdpsnd_show_help(void)
407 {
408 struct audio_driver *pos;
409
410 rdpsnd_register_drivers(NULL);
411
412 pos = drivers;
413 while (pos != NULL)
414 {
415 fprintf(stderr, " %s:\t%s\n", pos->name, pos->description);
416 pos = pos->next;
417 }
418 }
419
420 void
421 rdpsnd_play(void)
422 {
423 current_driver->wave_out_play();
424 }
425
426 void
427 rdpsnd_queue_write(STREAM s, uint16 tick, uint8 index)
428 {
429 struct audio_packet *packet = &packet_queue[queue_hi];
430 unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
431
432 if (next_hi == queue_lo)
433 {
434 error("No space to queue audio packet\n");
435 return;
436 }
437
438 queue_hi = next_hi;
439
440 packet->s = *s;
441 packet->tick = tick;
442 packet->index = index;
443
444 if (!g_dsp_busy)
445 current_driver->wave_out_play();
446 }
447
448 struct audio_packet *
449 rdpsnd_queue_current_packet(void)
450 {
451 return &packet_queue[queue_lo];
452 }
453
454 BOOL
455 rdpsnd_queue_empty(void)
456 {
457 return (queue_lo == queue_hi);
458 }
459
460 void
461 rdpsnd_queue_init(void)
462 {
463 queue_lo = queue_hi = 0;
464 }
465
466 void
467 rdpsnd_queue_next(void)
468 {
469 xfree(packet_queue[queue_lo].s.data);
470 queue_lo = (queue_lo + 1) % MAX_QUEUE;
471 }
472
473 int
474 rdpsnd_queue_next_tick(void)
475 {
476 if (((queue_lo + 1) % MAX_QUEUE) != queue_hi)
477 {
478 return packet_queue[(queue_lo + 1) % MAX_QUEUE].tick;
479 }
480 else
481 {
482 return (packet_queue[queue_lo].tick + 65535) % 65536;
483 }
484 }

  ViewVC Help
Powered by ViewVC 1.1.26