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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

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    
41 matthewc 474 static BOOL device_open;
42     static WAVEFORMATEX formats[MAX_FORMATS];
43     static unsigned int format_count;
44     static unsigned int current_format;
45 stargo 1254 static unsigned int queue_hi, queue_lo;
46     static struct audio_packet packet_queue[MAX_QUEUE];
47 matthewc 474
48 astrand 665 static STREAM
49 matthewc 474 rdpsnd_init_packet(uint16 type, uint16 size)
50     {
51     STREAM s;
52    
53 astrand 499 s = channel_init(rdpsnd_channel, size + 4);
54 matthewc 474 out_uint16_le(s, type);
55     out_uint16_le(s, size);
56     return s;
57     }
58    
59 astrand 665 static void
60 matthewc 474 rdpsnd_send(STREAM s)
61     {
62     #ifdef RDPSND_DEBUG
63     printf("RDPSND send:\n");
64 astrand 499 hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);
65 matthewc 474 #endif
66    
67     channel_send(s, rdpsnd_channel);
68     }
69    
70 astrand 499 void
71     rdpsnd_send_completion(uint16 tick, uint8 packet_index)
72 matthewc 474 {
73     STREAM s;
74    
75     s = rdpsnd_init_packet(RDPSND_COMPLETION, 4);
76 stargo 1254 out_uint16_le(s, tick);
77 matthewc 474 out_uint8(s, packet_index);
78     out_uint8(s, 0);
79     s_mark_end(s);
80     rdpsnd_send(s);
81     }
82    
83 astrand 665 static void
84 matthewc 474 rdpsnd_process_negotiate(STREAM in)
85     {
86     unsigned int in_format_count, i;
87     WAVEFORMATEX *format;
88     STREAM out;
89 stargo 491 BOOL device_available = False;
90 stargo 493 int readcnt;
91     int discardcnt;
92 matthewc 474
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 stargo 491 if (wave_out_open())
98     {
99     wave_out_close();
100     device_available = True;
101     }
102    
103 matthewc 474 format_count = 0;
104 astrand 499 if (s_check_rem(in, 18 * in_format_count))
105 matthewc 474 {
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 stargo 492 /* read in the buffer of unknown use */
118 stargo 493 readcnt = format->cbSize;
119     discardcnt = 0;
120 stargo 492 if (format->cbSize > MAX_CBSIZE)
121     {
122 astrand 499 fprintf(stderr, "cbSize too large for buffer: %d\n",
123     format->cbSize);
124 stargo 492 readcnt = MAX_CBSIZE;
125     discardcnt = format->cbSize - MAX_CBSIZE;
126     }
127     in_uint8a(in, format->cb, readcnt);
128     in_uint8s(in, discardcnt);
129    
130 stargo 491 if (device_available && wave_out_format_supported(format))
131 matthewc 474 {
132     format_count++;
133     if (format_count == MAX_FORMATS)
134     break;
135     }
136     }
137     }
138    
139 astrand 499 out = rdpsnd_init_packet(RDPSND_NEGOTIATE | 0x200, 20 + 18 * format_count);
140     out_uint32_le(out, 3); /* flags */
141 matthewc 474 out_uint32(out, 0xffffffff); /* volume */
142 astrand 499 out_uint32(out, 0); /* pitch */
143     out_uint16(out, 0); /* UDP port */
144 matthewc 474
145     out_uint16_le(out, format_count);
146 astrand 499 out_uint8(out, 0x95); /* pad? */
147     out_uint16_le(out, 2); /* status */
148     out_uint8(out, 0x77); /* pad? */
149 matthewc 474
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 astrand 499 out_uint16(out, 0); /* cbSize */
160 matthewc 474 }
161    
162     s_mark_end(out);
163     rdpsnd_send(out);
164     }
165    
166 astrand 665 static void
167 stargo 1044 rdpsnd_process_servertick(STREAM in)
168 matthewc 474 {
169 stargo 1044 uint16 tick1, tick2;
170 matthewc 474 STREAM out;
171    
172     /* in_uint8s(in, 4); unknown */
173 stargo 1044 in_uint16_le(in, tick1);
174     in_uint16_le(in, tick2);
175 matthewc 474
176 stargo 1044 out = rdpsnd_init_packet(RDPSND_SERVERTICK | 0x2300, 4);
177     out_uint16_le(out, tick1);
178     out_uint16_le(out, tick2);
179 matthewc 474 s_mark_end(out);
180     rdpsnd_send(out);
181     }
182    
183 astrand 665 static void
184 matthewc 432 rdpsnd_process(STREAM s)
185     {
186 matthewc 474 uint8 type;
187     uint16 datalen;
188 stargo 491 uint32 volume;
189 matthewc 474 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 astrand 499 hexdump(s->p, s->end - s->p);
196 matthewc 474 #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 stargo 1254 rdpsnd_queue_write(s, tick, packet_index);
225 matthewc 474 awaiting_data_packet = False;
226     return;
227     }
228    
229     in_uint8(s, type);
230 astrand 499 in_uint8s(s, 1); /* unknown? */
231 matthewc 474 in_uint16_le(s, datalen);
232    
233     switch (type)
234     {
235 astrand 499 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 stargo 1044 case RDPSND_SERVERTICK:
249     rdpsnd_process_servertick(s);
250 astrand 499 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 matthewc 474 }
262 matthewc 432 }
263    
264     BOOL
265     rdpsnd_init(void)
266     {
267 astrand 435 rdpsnd_channel =
268     channel_register("rdpsnd", CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP,
269     rdpsnd_process);
270 stargo 1254
271 matthewc 432 return (rdpsnd_channel != NULL);
272     }
273 stargo 1254
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