/[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 1255 - (hide annotations)
Sun Sep 17 11:04:50 2006 UTC (17 years, 8 months ago) by stargo
Original Path: sourceforge.net/trunk/rdesktop/rdpsnd.c
File MIME type: text/plain
File size: 9452 byte(s)
allow multiple sound-drivers to be compiled in simultaneously and
make the runtime selectable

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

  ViewVC Help
Powered by ViewVC 1.1.26