ReactOS 0.4.15-dev-7934-g1dc8d80
rdpsnd_sun.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 - Sun
4 Copyright (C) Matthew Chapman 2003
5 Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003
6 Copyright (C) Michael Gernoth mike@zerfleddert.de 2003
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 <unistd.h>
25#include <fcntl.h>
26#include <errno.h>
27#include <sys/ioctl.h>
28#include <sys/audioio.h>
29
30#if (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
31#include <stropts.h>
32#endif
33
34#define MAX_QUEUE 10
35
36int This->dsp_;
37BOOL This->dsp_bu = False;
40static short g_samplewidth;
41
42static struct audio_packet
43{
44 struct stream s;
48static unsigned int queue_hi, queue_lo;
49
50BOOL
52{
53 char *dsp_dev = getenv("AUDIODEV");
54
55 if (dsp_dev == NULL)
56 {
57 dsp_dev = xstrdup("/dev/audio");
58 }
59
60 if ((This->dsp_ = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1)
61 {
62 perror(dsp_dev);
63 return False;
64 }
65
66 /* Non-blocking so that user interface is responsive */
67 fcntl(This->dsp_, F_SETFL, fcntl(This->dsp_, F_GETFL) | O_NONBLOCK);
68
69 queue_lo = queue_hi = 0;
71
72 return True;
73}
74
75void
77{
78 /* Ack all remaining packets */
79 while (queue_lo != queue_hi)
80 {
83 queue_lo = (queue_lo + 1) % MAX_QUEUE;
84 }
85
86#if defined I_FLUSH && defined FLUSHW
87 /* Flush the audiobuffer */
88 ioctl(This->dsp_, I_FLUSH, FLUSHW);
89#endif
90#if defined AUDIO_FLUSH
91 ioctl(This->dsp_, AUDIO_FLUSH, NULL);
92#endif
93 close(This->dsp_);
94}
95
96BOOL
98{
99 if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
100 return False;
101 if ((pwfx->nChannels != 1) && (pwfx->nChannels != 2))
102 return False;
103 if ((pwfx->wBitsPerSample != 8) && (pwfx->wBitsPerSample != 16))
104 return False;
105
106 return True;
107}
108
109BOOL
111{
112 audio_info_t info;
113
114 ioctl(This->dsp_, AUDIO_DRAIN, 0);
116 AUDIO_INITINFO(&info);
117
118
119 if (pwfx->wBitsPerSample == 8)
120 {
121 info.play.encoding = AUDIO_ENCODING_LINEAR8;
122 }
123 else if (pwfx->wBitsPerSample == 16)
124 {
125 info.play.encoding = AUDIO_ENCODING_LINEAR;
126 /* Do we need to swap the 16bit values? (Are we BigEndian) */
127#ifdef B_ENDIAN
128 g_swapaudio = 1;
129#else
130 g_swapaudio = 0;
131#endif
132 }
133
134 g_samplewidth = pwfx->wBitsPerSample / 8;
135
136 if (pwfx->nChannels == 1)
137 {
138 info.play.channels = 1;
139 }
140 else if (pwfx->nChannels == 2)
141 {
142 info.play.channels = 2;
143 g_samplewidth *= 2;
144 }
145
146 info.play.sample_rate = pwfx->nSamplesPerSec;
147 info.play.precision = pwfx->wBitsPerSample;
148 info.play.samples = 0;
149 info.play.eof = 0;
150 info.play.error = 0;
152
153 if (ioctl(This->dsp_, AUDIO_SETINFO, &info) == -1)
154 {
155 perror("AUDIO_SETINFO");
156 close(This->dsp_);
157 return False;
158 }
159
160 return True;
161}
162
163void
165{
166 audio_info_t info;
167 uint balance;
168 uint volume;
169
170 AUDIO_INITINFO(&info);
171
172 volume = (left > right) ? left : right;
173
174 if (volume / AUDIO_MID_BALANCE != 0)
175 {
176 balance =
177 AUDIO_MID_BALANCE - (left / (volume / AUDIO_MID_BALANCE)) +
178 (right / (volume / AUDIO_MID_BALANCE));
179 }
180 else
181 {
182 balance = AUDIO_MID_BALANCE;
183 }
184
185 info.play.gain = volume / (65536 / AUDIO_MAX_GAIN);
186 info.play.balance = balance;
187
188 if (ioctl(This->dsp_, AUDIO_SETINFO, &info) == -1)
189 {
190 perror("AUDIO_SETINFO");
191 return;
192 }
193}
194
195void
197{
199 unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
200
201 if (next_hi == queue_lo)
202 {
203 error("No space to queue audio packet\n");
204 return;
205 }
206
207 queue_hi = next_hi;
208
209 packet->s = *s;
210 packet->tick = tick;
211 packet->index = index;
212 packet->s.p += 4;
213
214 /* we steal the data buffer from s, give it a new one */
215 s->data = malloc(s->size);
216
217 if (!This->dsp_bu)
219}
220
221void
223{
224 struct audio_packet *packet;
225 audio_info_t info;
226 ssize_t len;
227 unsigned int i;
228 uint8 swap;
229 STREAM out;
230 static BOOL swapped = False;
231 static BOOL sentcompletion = True;
232 static uint32 samplecnt = 0;
233 static uint32 numsamples;
234
235 while (1)
236 {
237 if (g_reopened)
238 {
239 /* Device was just (re)openend */
240 samplecnt = 0;
241 swapped = False;
242 sentcompletion = True;
244 }
245
246 if (queue_lo == queue_hi)
247 {
248 This->dsp_bu = 0;
249 return;
250 }
251
253 out = &packet->s;
254
255 /* Swap the current packet, but only once */
256 if (g_swapaudio && !swapped)
257 {
258 for (i = 0; i < out->end - out->p; i += 2)
259 {
260 swap = *(out->p + i);
261 *(out->p + i) = *(out->p + i + 1);
262 *(out->p + i + 1) = swap;
263 }
264 swapped = True;
265 }
266
267 if (sentcompletion)
268 {
269 sentcompletion = False;
270 numsamples = (out->end - out->p) / g_samplewidth;
271 }
272
273 len = 0;
274
275 if (out->end != out->p)
276 {
277 len = write(This->dsp_, out->p, out->end - out->p);
278 if (len == -1)
279 {
280 if (errno != EWOULDBLOCK)
281 perror("write audio");
282 This->dsp_bu = 1;
283 return;
284 }
285 }
286
287 out->p += len;
288 if (out->p == out->end)
289 {
290 if (ioctl(This->dsp_, AUDIO_GETINFO, &info) == -1)
291 {
292 perror("AUDIO_GETINFO");
293 return;
294 }
295
296 /* Ack the packet, if we have played at least 70% */
297 if (info.play.samples >= samplecnt + ((numsamples * 7) / 10))
298 {
299 samplecnt += numsamples;
300 rdpsnd_send_completion(packet->tick, packet->index);
301 free(out->data);
302 queue_lo = (queue_lo + 1) % MAX_QUEUE;
303 swapped = False;
304 sentcompletion = True;
305 }
306 else
307 {
308 This->dsp_bu = 1;
309 return;
310 }
311 }
312 }
313}
#define O_WRONLY
Definition: acwin.h:111
#define open
Definition: acwin.h:95
#define close
Definition: acwin.h:98
#define write
Definition: acwin.h:97
#define WAVE_FORMAT_PCM
Definition: constants.h:425
char * xstrdup(const char *s)
Definition: uimain.c:768
unsigned short uint16
Definition: types.h:30
unsigned int uint32
Definition: types.h:32
#define False
Definition: types.h:25
#define True
Definition: types.h:24
unsigned char uint8
Definition: types.h:28
#define index(s, c)
Definition: various.h:29
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define NULL
Definition: types.h:112
UINT32 uint
Definition: types.h:83
#define EWOULDBLOCK
Definition: errno.h:42
unsigned int BOOL
Definition: ntddk_ex.h:94
GLdouble s
Definition: gl.h:2039
GLuint index
Definition: glext.h:6031
GLdouble GLdouble right
Definition: glext.h:10859
GLint left
Definition: glext.h:7726
GLenum GLsizei len
Definition: glext.h:6722
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
_CRTIMP void __cdecl perror(_In_opt_z_ const char *_ErrMsg)
_Check_return_ char *__cdecl getenv(_In_z_ const char *_VarName)
#define error(str)
Definition: mkdosfs.c:1605
#define O_NONBLOCK
Definition: port.h:158
#define swap(a, b)
Definition: qsort.c:63
void rdpsnd_send_completion(RDPCLIENT *This, uint16 tick, uint8 packet_index)
Definition: rdpsnd.c:55
static unsigned int queue_lo
Definition: rdpsnd_sun.c:48
BOOL wave_out_open(void)
Definition: rdpsnd_sun.c:51
static short g_samplewidth
Definition: rdpsnd_sun.c:40
BOOL wave_out_format_supported(WAVEFORMATEX *pwfx)
Definition: rdpsnd_sun.c:97
void wave_out_write(STREAM s, uint16 tick, uint8 index)
Definition: rdpsnd_sun.c:196
static BOOL g_reopened
Definition: rdpsnd_sun.c:38
BOOL wave_out_set_format(WAVEFORMATEX *pwfx)
Definition: rdpsnd_sun.c:110
void wave_out_close(void)
Definition: rdpsnd_sun.c:76
void wave_out_volume(uint16 left, uint16 right)
Definition: rdpsnd_sun.c:164
void wave_out_play(void)
Definition: rdpsnd_sun.c:222
static unsigned int queue_hi
Definition: rdpsnd_sun.c:48
#define MAX_QUEUE
Definition: rdpsnd_sun.c:34
static BOOL g_swapaudio
Definition: rdpsnd_sun.c:39
static struct audio_packet packet_queue[MAX_QUEUE]
static FILE * out
Definition: regtests2xml.c:44
int ssize_t
Definition: rosdhcp.h:48
#define errno
Definition: errno.h:18
WORD wBitsPerSample
Definition: audioclient.idl:45
DWORD nSamplesPerSec
Definition: audioclient.idl:42
Definition: dhcpd.h:135
Definition: parse.h:23
#define ioctl
Definition: wintirpc.h:60