ReactOS  0.4.12-dev-918-g6c6e7b8
rdpsnd.c
Go to the documentation of this file.
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 along
18  with this program; if not, write to the Free Software Foundation, Inc.,
19  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21 
22 #include "rdesktop.h"
23 
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
31 
32 static STREAM
34 {
35  STREAM s;
36 
37  s = channel_init(This, This->rdpsnd.channel, size + 4);
40  return s;
41 }
42 
43 static void
45 {
46 #ifdef RDPSND_DEBUG
47  printf("RDPSND send:\n");
48  hexdump(s->channel_hdr + 8, s->end - s->channel_hdr - 8);
49 #endif
50 
51  channel_send(This, s, This->rdpsnd.channel);
52 }
53 
54 void
56 {
57  STREAM s;
58 
60  out_uint16_le(s, tick + 50);
61  out_uint8(s, packet_index);
62  out_uint8(s, 0);
63  s_mark_end(s);
64  rdpsnd_send(This, s);
65 }
66 
67 static void
69 {
70  unsigned int in_format_count, i;
72  STREAM out;
73  BOOL device_available = False;
74  int readcnt;
75  int discardcnt;
76 
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 */
80 
81  if (wave_out_open())
82  {
84  device_available = True;
85  }
86 
87  This->rdpsnd.format_count = 0;
88  if (s_check_rem(in, 18 * in_format_count))
89  {
90  for (i = 0; i < in_format_count; i++)
91  {
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);
100 
101  /* read in the buffer of unknown use */
102  readcnt = format->cbSize;
103  discardcnt = 0;
104  if (format->cbSize > MAX_CBSIZE)
105  {
106  fprintf(stderr, "cbSize too large for buffer: %d\n",
107  format->cbSize);
108  readcnt = MAX_CBSIZE;
109  discardcnt = format->cbSize - MAX_CBSIZE;
110  }
111  in_uint8a(in, format->cb, readcnt);
112  in_uint8s(in, discardcnt);
113 
114  if (device_available && wave_out_format_supported(format))
115  {
116  This->rdpsnd.format_count++;
117  if (This->rdpsnd.format_count == MAX_FORMATS)
118  break;
119  }
120  }
121  }
122 
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 */
128 
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? */
133 
134  for (i = 0; i < This->rdpsnd.format_count; i++)
135  {
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 */
144  }
145 
146  s_mark_end(out);
147  rdpsnd_send(This, out);
148 }
149 
150 static void
152 {
153  uint16 tick1, tick2;
154  STREAM out;
155 
156  /* in_uint8s(in, 4); unknown */
157  in_uint16_le(in, tick1);
158  in_uint16_le(in, tick2);
159 
161  out_uint16_le(out, tick1);
162  out_uint16_le(out, tick2);
163  s_mark_end(out);
164  rdpsnd_send(This, out);
165 }
166 
167 static void
169 {
170  uint8 type;
171  uint16 datalen;
172  uint32 volume;
173  static uint16 tick, format;
174  static uint8 packet_index;
175  static BOOL awaiting_data_packet;
176 
177 #ifdef RDPSND_DEBUG
178  printf("RDPSND recv:\n");
179  hexdump(s->p, s->end - s->p);
180 #endif
181 
182  if (awaiting_data_packet)
183  {
184  if (format >= MAX_FORMATS)
185  {
186  error("RDPSND: Invalid format index\n");
187  return;
188  }
189 
190  if (!This->rdpsnd.device_open || (format != This->rdpsnd.current_format))
191  {
192  if (!This->rdpsnd.device_open && !wave_out_open())
193  {
194  rdpsnd_send_completion(This, tick, packet_index);
195  return;
196  }
197  if (!wave_out_set_format(&This->rdpsnd.formats[format]))
198  {
199  rdpsnd_send_completion(This, tick, packet_index);
200  wave_out_close();
201  This->rdpsnd.device_open = False;
202  return;
203  }
204  This->rdpsnd.device_open = True;
205  This->rdpsnd.current_format = format;
206  }
207 
208  wave_out_write(s, tick, packet_index);
209  awaiting_data_packet = False;
210  return;
211  }
212 
213  in_uint8(s, type);
214  in_uint8s(s, 1); /* unknown? */
216 
217  switch (type)
218  {
219  case RDPSND_WRITE:
220  in_uint16_le(s, tick);
222  in_uint8(s, packet_index);
223  awaiting_data_packet = True;
224  break;
225  case RDPSND_CLOSE:
226  wave_out_close();
227  This->rdpsnd.device_open = False;
228  break;
229  case RDPSND_NEGOTIATE:
231  break;
232  case RDPSND_SERVERTICK:
234  break;
235  case RDPSND_SET_VOLUME:
236  in_uint32(s, volume);
237  if (This->rdpsnd.device_open)
238  {
239  wave_out_volume((volume & 0xffff), (volume & 0xffff0000) >> 16);
240  }
241  break;
242  default:
243  unimpl("RDPSND packet type %d\n", type);
244  break;
245  }
246 }
247 
248 BOOL
250 {
251  This->rdpsnd.channel =
254  return (This->rdpsnd.channel != NULL);
255 }
#define RDPSND_COMPLETION
Definition: rdpsnd.c:28
#define out_uint16_le(s, v)
Definition: parse.h:58
void wave_out_close(void)
Definition: rdpsnd_libao.c:80
#define error(str)
Definition: mkdosfs.c:1605
#define RDPSND_CLOSE
Definition: rdpsnd.c:24
unsigned int uint32
Definition: types.h:32
static void rdpsnd_send(RDPCLIENT *This, STREAM s)
Definition: rdpsnd.c:44
void wave_out_volume(uint16 left, uint16 right)
Definition: rdpsnd_libao.c:142
#define out_uint32_le(s, v)
Definition: parse.h:59
#define s_check_rem(s, n)
Definition: parse.h:43
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
#define out_uint16(s, v)
Definition: parse.h:84
int const JOCTET unsigned int datalen
Definition: jpeglib.h:1027
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: gl.h:1546
BOOL rdpsnd_init(RDPCLIENT *This)
Definition: rdpsnd.c:249
VCHANNEL * channel_register(char *name, uint32 flags, void(*callback)(STREAM))
Definition: channels.c:46
#define out_uint8(s, v)
Definition: parse.h:92
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define MAX_CBSIZE
Definition: types.h:173
#define CHANNEL_OPTION_INITIALIZED
Definition: constants.h:431
unsigned int BOOL
Definition: ntddk_ex.h:94
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
static void rdpsnd_process_servertick(RDPCLIENT *This, STREAM in)
Definition: rdpsnd.c:151
static void rdpsnd_process_negotiate(RDPCLIENT *This, STREAM in)
Definition: rdpsnd.c:68
static void rdpsnd_process(RDPCLIENT *This, STREAM s)
Definition: rdpsnd.c:168
smooth NULL
Definition: ftsmooth.c:416
#define MAX_FORMATS
#define in_uint8s(s, n)
Definition: parse.h:91
void wave_out_write(STREAM s, uint16 tick, uint8 index)
Definition: rdpsnd_libao.c:148
BOOL wave_out_open(void)
Definition: rdpsnd_libao.c:51
BOOL wave_out_format_supported(WAVEFORMATEX *pwfx)
Definition: rdpsnd_libao.c:97
#define True
Definition: types.h:24
#define False
Definition: types.h:25
GLsizeiptr size
Definition: glext.h:5919
static FILE * out
Definition: regtests2xml.c:44
#define RDPSND_NEGOTIATE
Definition: rdpsnd.c:30
unsigned char uint8
Definition: types.h:28
#define in_uint32(s, v)
Definition: parse.h:83
Definition: parse.h:22
static STREAM rdpsnd_init_packet(RDPCLIENT *This, uint16 type, uint16 size)
Definition: rdpsnd.c:33
GLdouble s
Definition: gl.h:2039
#define in_uint8a(s, v, n)
Definition: parse.h:90
void hexdump(unsigned char *p, unsigned int len)
Definition: shimdbg.c:234
void rdpsnd_send_completion(RDPCLIENT *This, uint16 tick, uint8 packet_index)
Definition: rdpsnd.c:55
GLuint in
Definition: glext.h:9616
#define RDPSND_SERVERTICK
Definition: rdpsnd.c:29
unsigned short uint16
Definition: types.h:30
#define in_uint8(s, v)
Definition: parse.h:88
BOOL wave_out_set_format(WAVEFORMATEX *pwfx)
Definition: rdpsnd_libao.c:114
FILE * stderr
#define out_uint32(s, v)
Definition: parse.h:85
void unimpl(char *format,...)
Definition: uimain.c:801
#define s_mark_end(s)
Definition: parse.h:41
#define in_uint32_le(s, v)
Definition: parse.h:56
#define RDPSND_SET_VOLUME
Definition: rdpsnd.c:26
#define RDPSND_WRITE
Definition: rdpsnd.c:25
void channel_send(STREAM s, VCHANNEL *channel)
Definition: channels.c:79
#define in_uint16_le(s, v)
Definition: parse.h:55
#define printf
Definition: config.h:203
#define CHANNEL_OPTION_ENCRYPT_RDP
Definition: constants.h:432
STREAM channel_init(VCHANNEL *channel, uint32 length)
Definition: channels.c:69