/[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 1298 - (hide annotations)
Thu Oct 19 11:27:40 2006 UTC (17 years, 7 months ago) by ossman_
Original Path: sourceforge.net/trunk/rdesktop/rdpsnd.c
File MIME type: text/plain
File size: 10252 byte(s)
Make sure we get valid return values from the sound backends.

1 astrand 963 /* -*- c-basic-offset: 8 -*-
2 matthewc 474 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 ossman_ 1298 #include <assert.h>
23    
24 matthewc 432 #include "rdesktop.h"
25 stargo 1254 #include "rdpsnd.h"
26 stargo 1258 #include "rdpsnd_dsp.h"
27 matthewc 432
28 matthewc 474 #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 stargo 1044 #define RDPSND_SERVERTICK 6
34 matthewc 474 #define RDPSND_NEGOTIATE 7
35    
36     #define MAX_FORMATS 10
37 stargo 1254 #define MAX_QUEUE 10
38 matthewc 474
39 stargo 1254 BOOL g_dsp_busy = False;
40     int g_dsp_fd;
41    
42 matthewc 432 static VCHANNEL *rdpsnd_channel;
43 stargo 1255 static struct audio_driver *drivers = NULL;
44 stargo 1256 struct audio_driver *current_driver = NULL;
45 matthewc 432
46 matthewc 474 static BOOL device_open;
47     static WAVEFORMATEX formats[MAX_FORMATS];
48     static unsigned int format_count;
49     static unsigned int current_format;
50 stargo 1256 unsigned int queue_hi, queue_lo;
51     struct audio_packet packet_queue[MAX_QUEUE];
52 matthewc 474
53 stargo 1255 void (*wave_out_play) (void);
54    
55 astrand 665 static STREAM
56 matthewc 474 rdpsnd_init_packet(uint16 type, uint16 size)
57     {
58     STREAM s;
59    
60 astrand 499 s = channel_init(rdpsnd_channel, size + 4);
61 matthewc 474 out_uint16_le(s, type);
62     out_uint16_le(s, size);
63     return s;
64     }
65    
66 astrand 665 static void
67 matthewc 474 rdpsnd_send(STREAM s)
68     {
69     #ifdef RDPSND_DEBUG
70     printf("RDPSND send:\n");
71 astrand 499 hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);
72 matthewc 474 #endif
73    
74     channel_send(s, rdpsnd_channel);
75     }
76    
77 astrand 499 void
78     rdpsnd_send_completion(uint16 tick, uint8 packet_index)
79 matthewc 474 {
80     STREAM s;
81    
82     s = rdpsnd_init_packet(RDPSND_COMPLETION, 4);
83 stargo 1254 out_uint16_le(s, tick);
84 matthewc 474 out_uint8(s, packet_index);
85     out_uint8(s, 0);
86     s_mark_end(s);
87     rdpsnd_send(s);
88     }
89    
90 astrand 665 static void
91 matthewc 474 rdpsnd_process_negotiate(STREAM in)
92     {
93     unsigned int in_format_count, i;
94     WAVEFORMATEX *format;
95     STREAM out;
96 stargo 491 BOOL device_available = False;
97 stargo 493 int readcnt;
98     int discardcnt;
99 matthewc 474
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 stargo 1255 if (current_driver->wave_out_open())
105 stargo 491 {
106 stargo 1255 current_driver->wave_out_close();
107 stargo 491 device_available = True;
108     }
109    
110 matthewc 474 format_count = 0;
111 astrand 499 if (s_check_rem(in, 18 * in_format_count))
112 matthewc 474 {
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 stargo 492 /* read in the buffer of unknown use */
125 stargo 493 readcnt = format->cbSize;
126     discardcnt = 0;
127 stargo 492 if (format->cbSize > MAX_CBSIZE)
128     {
129 astrand 499 fprintf(stderr, "cbSize too large for buffer: %d\n",
130     format->cbSize);
131 stargo 492 readcnt = MAX_CBSIZE;
132     discardcnt = format->cbSize - MAX_CBSIZE;
133     }
134     in_uint8a(in, format->cb, readcnt);
135     in_uint8s(in, discardcnt);
136    
137 stargo 1255 if (device_available && current_driver->wave_out_format_supported(format))
138 matthewc 474 {
139     format_count++;
140     if (format_count == MAX_FORMATS)
141     break;
142     }
143     }
144     }
145    
146 astrand 499 out = rdpsnd_init_packet(RDPSND_NEGOTIATE | 0x200, 20 + 18 * format_count);
147     out_uint32_le(out, 3); /* flags */
148 matthewc 474 out_uint32(out, 0xffffffff); /* volume */
149 astrand 499 out_uint32(out, 0); /* pitch */
150     out_uint16(out, 0); /* UDP port */
151 matthewc 474
152     out_uint16_le(out, format_count);
153 astrand 499 out_uint8(out, 0x95); /* pad? */
154     out_uint16_le(out, 2); /* status */
155     out_uint8(out, 0x77); /* pad? */
156 matthewc 474
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 astrand 499 out_uint16(out, 0); /* cbSize */
167 matthewc 474 }
168    
169     s_mark_end(out);
170     rdpsnd_send(out);
171     }
172    
173 astrand 665 static void
174 stargo 1044 rdpsnd_process_servertick(STREAM in)
175 matthewc 474 {
176 stargo 1044 uint16 tick1, tick2;
177 matthewc 474 STREAM out;
178    
179     /* in_uint8s(in, 4); unknown */
180 stargo 1044 in_uint16_le(in, tick1);
181     in_uint16_le(in, tick2);
182 matthewc 474
183 stargo 1044 out = rdpsnd_init_packet(RDPSND_SERVERTICK | 0x2300, 4);
184     out_uint16_le(out, tick1);
185     out_uint16_le(out, tick2);
186 matthewc 474 s_mark_end(out);
187     rdpsnd_send(out);
188     }
189    
190 astrand 665 static void
191 matthewc 432 rdpsnd_process(STREAM s)
192     {
193 matthewc 474 uint8 type;
194     uint16 datalen;
195 stargo 491 uint32 volume;
196 matthewc 474 static uint16 tick, format;
197     static uint8 packet_index;
198     static BOOL awaiting_data_packet;
199 stargo 1265 static unsigned char missing_bytes[4] = { 0, 0, 0, 0 };
200 matthewc 474
201     #ifdef RDPSND_DEBUG
202     printf("RDPSND recv:\n");
203 astrand 499 hexdump(s->p, s->end - s->p);
204 matthewc 474 #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 stargo 1255 if (!device_open && !current_driver->wave_out_open())
217 matthewc 474 {
218     rdpsnd_send_completion(tick, packet_index);
219     return;
220     }
221 stargo 1255 if (!current_driver->wave_out_set_format(&formats[format]))
222 matthewc 474 {
223     rdpsnd_send_completion(tick, packet_index);
224 stargo 1255 current_driver->wave_out_close();
225 matthewc 474 device_open = False;
226     return;
227     }
228     device_open = True;
229     current_format = format;
230     }
231    
232 stargo 1265 /* Insert the 4 missing bytes retrieved from last RDPSND_WRITE */
233     memcpy(s->data, missing_bytes, 4);
234    
235 stargo 1263 current_driver->
236     wave_out_write(rdpsnd_dsp_process
237     (s, current_driver, &formats[current_format]), tick,
238     packet_index);
239 matthewc 474 awaiting_data_packet = False;
240     return;
241     }
242    
243     in_uint8(s, type);
244 astrand 499 in_uint8s(s, 1); /* unknown? */
245 matthewc 474 in_uint16_le(s, datalen);
246    
247     switch (type)
248     {
249 astrand 499 case RDPSND_WRITE:
250     in_uint16_le(s, tick);
251     in_uint16_le(s, format);
252     in_uint8(s, packet_index);
253 stargo 1265 /* Here are our lost bytes, but why? */
254     memcpy(missing_bytes, s->end - 4, 4);
255 astrand 499 awaiting_data_packet = True;
256     break;
257     case RDPSND_CLOSE:
258 stargo 1255 current_driver->wave_out_close();
259 astrand 499 device_open = False;
260     break;
261     case RDPSND_NEGOTIATE:
262     rdpsnd_process_negotiate(s);
263     break;
264 stargo 1044 case RDPSND_SERVERTICK:
265     rdpsnd_process_servertick(s);
266 astrand 499 break;
267     case RDPSND_SET_VOLUME:
268     in_uint32(s, volume);
269     if (device_open)
270     {
271 stargo 1255 current_driver->wave_out_volume((volume & 0xffff),
272     (volume & 0xffff0000) >> 16);
273 astrand 499 }
274     break;
275     default:
276     unimpl("RDPSND packet type %d\n", type);
277     break;
278 matthewc 474 }
279 matthewc 432 }
280    
281 stargo 1274 static BOOL
282 stargo 1255 rdpsnd_auto_open(void)
283     {
284 stargo 1271 static BOOL failed = False;
285    
286     if (!failed)
287 stargo 1255 {
288 stargo 1271 struct audio_driver *auto_driver = current_driver;
289    
290     current_driver = drivers;
291     while (current_driver != NULL)
292 stargo 1255 {
293 stargo 1271 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 stargo 1255 }
302 stargo 1271
303     warning("no working audio-driver found\n");
304     failed = True;
305     current_driver = auto_driver;
306 stargo 1255 }
307    
308     return False;
309     }
310    
311 stargo 1274 static void
312 stargo 1255 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 ossman_ 1298 assert(*reg);
322 stargo 1255 reg = &((*reg)->next);
323     #endif
324 stargo 1264 #if defined(RDPSND_SUN)
325     *reg = sun_register(options);
326 ossman_ 1298 assert(*reg);
327 stargo 1264 reg = &((*reg)->next);
328     #endif
329 stargo 1255 #if defined(RDPSND_OSS)
330     *reg = oss_register(options);
331 ossman_ 1298 assert(*reg);
332 stargo 1255 reg = &((*reg)->next);
333     #endif
334     #if defined(RDPSND_SGI)
335     *reg = sgi_register(options);
336 ossman_ 1298 assert(*reg);
337 stargo 1255 reg = &((*reg)->next);
338     #endif
339     #if defined(RDPSND_LIBAO)
340     *reg = libao_register(options);
341 ossman_ 1298 assert(*reg);
342 stargo 1255 reg = &((*reg)->next);
343     #endif
344     }
345    
346     BOOL
347 stargo 1272 rdpsnd_init(char *optarg)
348 stargo 1255 {
349     static struct audio_driver auto_driver;
350     struct audio_driver *pos;
351 stargo 1272 char *driver = NULL, *options = NULL;
352 stargo 1255
353     drivers = NULL;
354 stargo 1272
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 stargo 1255 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 stargo 1273 void
421 stargo 1255 rdpsnd_play(void)
422     {
423     current_driver->wave_out_play();
424     }
425    
426 stargo 1273 inline void
427 stargo 1254 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 stargo 1255 current_driver->wave_out_play();
446 stargo 1254 }
447    
448     inline struct audio_packet *
449     rdpsnd_queue_current_packet(void)
450     {
451     return &packet_queue[queue_lo];
452     }
453    
454     inline BOOL
455     rdpsnd_queue_empty(void)
456     {
457     return (queue_lo == queue_hi);
458     }
459    
460     inline void
461     rdpsnd_queue_init(void)
462     {
463     queue_lo = queue_hi = 0;
464     }
465    
466     inline void
467     rdpsnd_queue_next(void)
468     {
469 stargo 1258 xfree(packet_queue[queue_lo].s.data);
470 stargo 1254 queue_lo = (queue_lo + 1) % MAX_QUEUE;
471     }
472    
473     inline 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