ReactOS  0.4.14-dev-376-gaedba84
rdpsnd_sgi.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 - SGI/IRIX
4  Copyright (C) Matthew Chapman 2003
5  Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003
6  Copyright (C) Jeremy Meng void.foo@gmail.com 2004, 2005
7 
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License along
19  with this program; if not, write to the Free Software Foundation, Inc.,
20  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22 
23 #include "rdesktop.h"
24 #include <errno.h>
25 #include <dmedia/audio.h>
26 
27 /* #define IRIX_DEBUG 1 */
28 
29 #define IRIX_MAX_VOL 65535
30 
31 #define MAX_QUEUE 10
32 
33 int This->dsp_;
34 ALconfig audioconfig;
35 ALport output_port;
36 
37 BOOL This->dsp_bu = False;
39 static int g_snd_rate;
40 static BOOL g_swapaudio;
41 static int width = AL_SAMPLE_16;
42 
46 
47 static struct audio_packet
48 {
49  struct stream s;
50  uint16 tick;
51  uint8 index;
53 static unsigned int queue_hi, queue_lo;
54 
55 BOOL
57 {
58  ALparamInfo pinfo;
59 
60 #if (defined(IRIX_DEBUG))
61  fprintf(stderr, "wave_out_open: begin\n");
62 #endif
63 
64  if (alGetParamInfo(AL_DEFAULT_OUTPUT, AL_GAIN, &pinfo) < 0)
65  {
66  fprintf(stderr, "wave_out_open: alGetParamInfo failed: %s\n",
67  alGetErrorString(oserror()));
68  }
69  min_volume = alFixedToDouble(pinfo.min.ll);
70  max_volume = alFixedToDouble(pinfo.max.ll);
72 #if (defined(IRIX_DEBUG))
73  fprintf(stderr, "wave_out_open: minvol = %lf, maxvol= %lf, range = %lf.\n",
75 #endif
76 
77  queue_lo = queue_hi = 0;
78 
79  audioconfig = alNewConfig();
80  if (audioconfig == (ALconfig) 0)
81  {
82  fprintf(stderr, "wave_out_open: alNewConfig failed: %s\n",
83  alGetErrorString(oserror()));
84  return False;
85  }
86 
87  output_port = alOpenPort("rdpsnd", "w", 0);
88  if (output_port == (ALport) 0)
89  {
90  fprintf(stderr, "wave_out_open: alOpenPort failed: %s\n",
91  alGetErrorString(oserror()));
92  return False;
93  }
94 
95 #if (defined(IRIX_DEBUG))
96  fprintf(stderr, "wave_out_open: returning\n");
97 #endif
98  return True;
99 }
100 
101 void
103 {
104  /* Ack all remaining packets */
105 #if (defined(IRIX_DEBUG))
106  fprintf(stderr, "wave_out_close: begin\n");
107 #endif
108 
109  while (queue_lo != queue_hi)
110  {
112  free(packet_queue[queue_lo].s.data);
113  queue_lo = (queue_lo + 1) % MAX_QUEUE;
114  }
115  alDiscardFrames(output_port, 0);
116 
117  alClosePort(output_port);
118  alFreeConfig(audioconfig);
119 #if (defined(IRIX_DEBUG))
120  fprintf(stderr, "wave_out_close: returning\n");
121 #endif
122 }
123 
124 BOOL
126 {
127  if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
128  return False;
129  if ((pwfx->nChannels != 1) && (pwfx->nChannels != 2))
130  return False;
131  if ((pwfx->wBitsPerSample != 8) && (pwfx->wBitsPerSample != 16))
132  return False;
133 
134  return True;
135 }
136 
137 BOOL
139 {
140  int channels;
141  int frameSize, channelCount;
142  ALpv params;
143 
144 #if (defined(IRIX_DEBUG))
145  fprintf(stderr, "wave_out_set_format: init...\n");
146 #endif
147 
148  g_swapaudio = False;
149  if (pwfx->wBitsPerSample == 8)
150  width = AL_SAMPLE_8;
151  else if (pwfx->wBitsPerSample == 16)
152  {
153  width = AL_SAMPLE_16;
154  /* Do we need to swap the 16bit values? (Are we BigEndian) */
155 #if (defined(B_ENDIAN))
156  g_swapaudio = 1;
157 #else
158  g_swapaudio = 0;
159 #endif
160  }
161 
162  /* Limited support to configure an opened audio port in IRIX. The
163  number of channels is a static setting and can not be changed after
164  a port is opened. So if the number of channels remains the same, we
165  can configure other settings; otherwise we have to reopen the audio
166  port, using same config. */
167 
168  channels = pwfx->nChannels;
169  g_snd_rate = pwfx->nSamplesPerSec;
170 
171  alSetSampFmt(audioconfig, AL_SAMPFMT_TWOSCOMP);
172  alSetWidth(audioconfig, width);
173  if (channels != alGetChannels(audioconfig))
174  {
175  alClosePort(output_port);
176  alSetChannels(audioconfig, channels);
177  output_port = alOpenPort("rdpsnd", "w", audioconfig);
178 
179  if (output_port == (ALport) 0)
180  {
181  fprintf(stderr, "wave_out_set_format: alOpenPort failed: %s\n",
182  alGetErrorString(oserror()));
183  return False;
184  }
185 
186  }
187 
188  resource = alGetResource(output_port);
189  maxFillable = alGetFillable(output_port);
190  channelCount = alGetChannels(audioconfig);
191  frameSize = alGetWidth(audioconfig);
192 
193  if (frameSize == 0 || channelCount == 0)
194  {
195  fprintf(stderr, "wave_out_set_format: bad frameSize or channelCount\n");
196  return False;
197  }
198  combinedFrameSize = frameSize * channelCount;
199 
200  params.param = AL_RATE;
201  params.value.ll = (long long) g_snd_rate << 32;
202 
203  if (alSetParams(resource, &params, 1) < 0)
204  {
205  fprintf(stderr, "wave_set_format: alSetParams failed: %s\n",
206  alGetErrorString(oserror()));
207  return False;
208  }
209  if (params.sizeOut < 0)
210  {
211  fprintf(stderr, "wave_set_format: invalid rate %d\n", g_snd_rate);
212  return False;
213  }
214 
215 #if (defined(IRIX_DEBUG))
216  fprintf(stderr, "wave_out_set_format: returning...\n");
217 #endif
218  return True;
219 }
220 
221 void
223 {
224  double gainleft, gainright;
225  ALpv pv[1];
226  ALfixed gain[8];
227 
228 #if (defined(IRIX_DEBUG))
229  fprintf(stderr, "wave_out_volume: begin\n");
230  fprintf(stderr, "left='%d', right='%d'\n", left, right);
231 #endif
232 
233  gainleft = (double) left / IRIX_MAX_VOL;
234  gainright = (double) right / IRIX_MAX_VOL;
235 
236  gain[0] = alDoubleToFixed(min_volume + gainleft * volume_range);
237  gain[1] = alDoubleToFixed(min_volume + gainright * volume_range);
238 
239  pv[0].param = AL_GAIN;
240  pv[0].value.ptr = gain;
241  pv[0].sizeIn = 8;
242  if (alSetParams(AL_DEFAULT_OUTPUT, pv, 1) < 0)
243  {
244  fprintf(stderr, "wave_out_volume: alSetParams failed: %s\n",
245  alGetErrorString(oserror()));
246  return;
247  }
248 
249 #if (defined(IRIX_DEBUG))
250  fprintf(stderr, "wave_out_volume: returning\n");
251 #endif
252 }
253 
254 void
256 {
258  unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
259 
260  if (next_hi == queue_lo)
261  {
262  fprintf(stderr, "No space to queue audio packet\n");
263  return;
264  }
265 
266  queue_hi = next_hi;
267 
268  packet->s = *s;
269  packet->tick = tick;
270  packet->index = index;
271  packet->s.p += 4;
272 
273  /* we steal the data buffer from s, give it a new one */
274  s->data = malloc(s->size);
275 
276  if (!This->dsp_bu)
277  wave_out_play();
278 }
279 
280 void
282 {
283  struct audio_packet *packet;
284  ssize_t len;
285  unsigned int i;
286  uint8 swap;
287  STREAM out;
288  static BOOL swapped = False;
289  int gf;
290 
291  while (1)
292  {
293  if (queue_lo == queue_hi)
294  {
295  This->dsp_bu = False;
296  return;
297  }
298 
300  out = &packet->s;
301 
302  /* Swap the current packet, but only once */
303  if (g_swapaudio && !swapped)
304  {
305  for (i = 0; i < out->end - out->p; i += 2)
306  {
307  swap = *(out->p + i);
308  *(out->p + i) = *(out->p + i + 1);
309  *(out->p + i + 1) = swap;
310  }
311  swapped = True;
312  }
313 
314  len = out->end - out->p;
315 
316  alWriteFrames(output_port, out->p, len / combinedFrameSize);
317 
318  out->p += len;
319  if (out->p == out->end)
320  {
321  gf = alGetFilled(output_port);
322  if (gf < (4 * maxFillable / 10))
323  {
324  rdpsnd_send_completion(packet->tick, packet->index);
325  free(out->data);
326  queue_lo = (queue_lo + 1) % MAX_QUEUE;
327  swapped = False;
328  }
329  else
330  {
331 #if (defined(IRIX_DEBUG))
332 /* fprintf(stderr,"Busy playing...\n"); */
333 #endif
334  This->dsp_bu = True;
335  usleep(10);
336  return;
337  }
338  }
339  }
340 }
GLint GLint GLsizei width
Definition: gl.h:1546
static BOOL g_swapaudio
Definition: rdpsnd_sgi.c:38
static int g_snd_rate
Definition: rdpsnd_sgi.c:39
#define swap(a, b)
Definition: qsort.c:63
double min_volume
Definition: rdpsnd_sgi.c:43
int combinedFrameSize
Definition: rdpsnd_sgi.c:45
UCHAR packet[_PAGE_SIZE]
Definition: serial.c:53
int usleep(unsigned int useconds)
#define free
Definition: debug_ros.c:5
double volume_range
Definition: rdpsnd_sgi.c:43
BOOL wave_out_format_supported(WAVEFORMATEX *pwfx)
Definition: rdpsnd_sgi.c:125
int This channels
Definition: rdpsnd_libao.c:37
int resource
Definition: rdpsnd_sgi.c:44
ALport output_port
Definition: rdpsnd_sgi.c:35
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
static struct audio_packet packet_queue[MAX_QUEUE]
#define WAVE_FORMAT_PCM
Definition: constants.h:425
GLenum const GLfloat * params
Definition: glext.h:5645
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,...)
double max_volume
Definition: rdpsnd_sgi.c:43
int maxFillable
Definition: rdpsnd_sgi.c:44
void wave_out_play(void)
Definition: rdpsnd_sgi.c:281
WORD wBitsPerSample
Definition: audioclient.idl:45
static const char mbstate_t *static wchar_t const char mbstate_t *static const wchar_t int *static double
Definition: string.c:80
GLuint index
Definition: glext.h:6031
DWORD nSamplesPerSec
Definition: audioclient.idl:42
Definition: dhcpd.h:135
#define True
Definition: types.h:24
#define False
Definition: types.h:25
#define IRIX_MAX_VOL
Definition: rdpsnd_sgi.c:29
void wave_out_close(void)
Definition: rdpsnd_sgi.c:102
static FILE * out
Definition: regtests2xml.c:44
GLint left
Definition: glext.h:7726
unsigned char uint8
Definition: types.h:28
GLdouble GLdouble right
Definition: glext.h:10859
#define MAX_QUEUE
Definition: rdpsnd_sgi.c:31
#define index(s, c)
Definition: various.h:29
Definition: parse.h:22
GLenum GLsizei len
Definition: glext.h:6722
int ssize_t
Definition: rosdhcp.h:48
GLdouble s
Definition: gl.h:2039
static unsigned int queue_lo
Definition: rdpsnd_sgi.c:53
BOOL wave_out_open(void)
Definition: rdpsnd_sgi.c:56
void rdpsnd_send_completion(RDPCLIENT *This, uint16 tick, uint8 packet_index)
Definition: rdpsnd.c:55
unsigned short uint16
Definition: types.h:30
#define long
Definition: qsort.c:33
void wave_out_volume(uint16 left, uint16 right)
Definition: rdpsnd_sgi.c:222
ALconfig audioconfig
Definition: rdpsnd_sgi.c:34
void wave_out_write(STREAM s, uint16 tick, uint8 index)
Definition: rdpsnd_sgi.c:255
FILE * stderr
#define malloc
Definition: debug_ros.c:4
BOOL wave_out_set_format(WAVEFORMATEX *pwfx)
Definition: rdpsnd_sgi.c:138
char data[MTU]
Definition: ipreceive.c:8
static unsigned int queue_hi
Definition: rdpsnd_sgi.c:53