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
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.
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.
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.
24 #define RDPSND_CLOSE 1
25 #define RDPSND_WRITE 2
26 #define RDPSND_SET_VOLUME 3
27 #define RDPSND_UNKNOWN4 4
28 #define RDPSND_COMPLETION 5
29 #define RDPSND_SERVERTICK 6
30 #define RDPSND_NEGOTIATE 7
33 rdpsnd_init_packet(RDPCLIENT
* This
, uint16 type
, uint16 size
)
37 s
= channel_init(This
, This
->rdpsnd
.channel
, size
+ 4);
38 out_uint16_le(s
, type
);
39 out_uint16_le(s
, size
);
44 rdpsnd_send(RDPCLIENT
* This
, STREAM s
)
47 printf("RDPSND send:\n");
48 hexdump(s
->channel_hdr
+ 8, s
->end
- s
->channel_hdr
- 8);
51 channel_send(This
, s
, This
->rdpsnd
.channel
);
55 rdpsnd_send_completion(RDPCLIENT
* This
, uint16 tick
, uint8 packet_index
)
59 s
= rdpsnd_init_packet(This
, RDPSND_COMPLETION
, 4);
60 out_uint16_le(s
, tick
+ 50);
61 out_uint8(s
, packet_index
);
68 rdpsnd_process_negotiate(RDPCLIENT
* This
, STREAM in
)
70 unsigned int in_format_count
, i
;
73 BOOL device_available
= False
;
77 in_uint8s(in
, 14); /* flags, volume, pitch, UDP port */
78 in_uint16_le(in
, in_format_count
);
79 in_uint8s(in
, 4); /* pad, status, pad */
84 device_available
= True
;
87 This
->rdpsnd
.format_count
= 0;
88 if (s_check_rem(in
, 18 * in_format_count
))
90 for (i
= 0; i
< in_format_count
; i
++)
92 format
= &This
->rdpsnd
.formats
[This
->rdpsnd
.format_count
];
93 in_uint16_le(in
, format
->wFormatTag
);
94 in_uint16_le(in
, format
->nChannels
);
95 in_uint32_le(in
, format
->nSamplesPerSec
);
96 in_uint32_le(in
, format
->nAvgBytesPerSec
);
97 in_uint16_le(in
, format
->nBlockAlign
);
98 in_uint16_le(in
, format
->wBitsPerSample
);
99 in_uint16_le(in
, format
->cbSize
);
101 /* read in the buffer of unknown use */
102 readcnt
= format
->cbSize
;
104 if (format
->cbSize
> MAX_CBSIZE
)
106 fprintf(stderr
, "cbSize too large for buffer: %d\n",
108 readcnt
= MAX_CBSIZE
;
109 discardcnt
= format
->cbSize
- MAX_CBSIZE
;
111 in_uint8a(in
, format
->cb
, readcnt
);
112 in_uint8s(in
, discardcnt
);
114 if (device_available
&& wave_out_format_supported(format
))
116 This
->rdpsnd
.format_count
++;
117 if (This
->rdpsnd
.format_count
== MAX_FORMATS
)
123 out
= rdpsnd_init_packet(This
, RDPSND_NEGOTIATE
| 0x200, 20 + 18 * This
->rdpsnd
.format_count
);
124 out_uint32_le(out
, 3); /* flags */
125 out_uint32(out
, 0xffffffff); /* volume */
126 out_uint32(out
, 0); /* pitch */
127 out_uint16(out
, 0); /* UDP port */
129 out_uint16_le(out
, This
->rdpsnd
.format_count
);
130 out_uint8(out
, 0x95); /* pad? */
131 out_uint16_le(out
, 2); /* status */
132 out_uint8(out
, 0x77); /* pad? */
134 for (i
= 0; i
< This
->rdpsnd
.format_count
; i
++)
136 format
= &This
->rdpsnd
.formats
[i
];
137 out_uint16_le(out
, format
->wFormatTag
);
138 out_uint16_le(out
, format
->nChannels
);
139 out_uint32_le(out
, format
->nSamplesPerSec
);
140 out_uint32_le(out
, format
->nAvgBytesPerSec
);
141 out_uint16_le(out
, format
->nBlockAlign
);
142 out_uint16_le(out
, format
->wBitsPerSample
);
143 out_uint16(out
, 0); /* cbSize */
147 rdpsnd_send(This
, out
);
151 rdpsnd_process_servertick(RDPCLIENT
* This
, STREAM in
)
156 /* in_uint8s(in, 4); unknown */
157 in_uint16_le(in
, tick1
);
158 in_uint16_le(in
, tick2
);
160 out
= rdpsnd_init_packet(This
, RDPSND_SERVERTICK
| 0x2300, 4);
161 out_uint16_le(out
, tick1
);
162 out_uint16_le(out
, tick2
);
164 rdpsnd_send(This
, out
);
168 rdpsnd_process(RDPCLIENT
* This
, STREAM s
)
173 static uint16 tick
, format
;
174 static uint8 packet_index
;
175 static BOOL awaiting_data_packet
;
178 printf("RDPSND recv:\n");
179 hexdump(s
->p
, s
->end
- s
->p
);
182 if (awaiting_data_packet
)
184 if (format
>= MAX_FORMATS
)
186 error("RDPSND: Invalid format index\n");
190 if (!This
->rdpsnd
.device_open
|| (format
!= This
->rdpsnd
.current_format
))
192 if (!This
->rdpsnd
.device_open
&& !wave_out_open())
194 rdpsnd_send_completion(This
, tick
, packet_index
);
197 if (!wave_out_set_format(&This
->rdpsnd
.formats
[format
]))
199 rdpsnd_send_completion(This
, tick
, packet_index
);
201 This
->rdpsnd
.device_open
= False
;
204 This
->rdpsnd
.device_open
= True
;
205 This
->rdpsnd
.current_format
= format
;
208 wave_out_write(s
, tick
, packet_index
);
209 awaiting_data_packet
= False
;
214 in_uint8s(s
, 1); /* unknown? */
215 in_uint16_le(s
, datalen
);
220 in_uint16_le(s
, tick
);
221 in_uint16_le(s
, format
);
222 in_uint8(s
, packet_index
);
223 awaiting_data_packet
= True
;
227 This
->rdpsnd
.device_open
= False
;
229 case RDPSND_NEGOTIATE
:
230 rdpsnd_process_negotiate(This
, s
);
232 case RDPSND_SERVERTICK
:
233 rdpsnd_process_servertick(This
, s
);
235 case RDPSND_SET_VOLUME
:
236 in_uint32(s
, volume
);
237 if (This
->rdpsnd
.device_open
)
239 wave_out_volume((volume
& 0xffff), (volume
& 0xffff0000) >> 16);
243 unimpl("RDPSND packet type %d\n", type
);
249 rdpsnd_init(RDPCLIENT
* This
)
251 This
->rdpsnd
.channel
=
252 channel_register(This
, "rdpsnd", CHANNEL_OPTION_INITIALIZED
| CHANNEL_OPTION_ENCRYPT_RDP
,
254 return (This
->rdpsnd
.channel
!= NULL
);