/[rdesktop]/sourceforge.net/trunk/rdesktop/rdpsnd_sun.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

Contents of /sourceforge.net/trunk/rdesktop/rdpsnd_sun.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1347 - (show annotations)
Thu Dec 7 16:41:58 2006 UTC (17 years, 5 months ago) by stargo
File MIME type: text/plain
File size: 5852 byte(s)
fix sun audio driver

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-2006
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
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 */
22
23 #include "rdesktop.h"
24 #include "rdpsnd.h"
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <errno.h>
28 #include <sys/ioctl.h>
29 #include <sys/audioio.h>
30
31 #if (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
32 #include <stropts.h>
33 #endif
34
35 #define DEFAULTDEVICE "/dev/audio"
36
37 static int dsp_fd = -1;
38 static BOOL dsp_busy;
39
40 static BOOL g_reopened;
41 static short g_samplewidth;
42 static char *dsp_dev;
43
44 void sun_play(void);
45
46 void
47 sun_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv)
48 {
49 if (dsp_fd == -1)
50 return;
51
52 if (rdpsnd_queue_empty())
53 return;
54
55 FD_SET(dsp_fd, wfds);
56 if (dsp_fd > *n)
57 *n = dsp_fd;
58 }
59
60 void
61 sun_check_fds(fd_set * rfds, fd_set * wfds)
62 {
63 if (FD_ISSET(dsp_fd, wfds))
64 sun_play();
65 }
66
67 BOOL
68 sun_open(void)
69 {
70 if ((dsp_fd = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1)
71 {
72 perror(dsp_dev);
73 return False;
74 }
75
76 /* Non-blocking so that user interface is responsive */
77 fcntl(dsp_fd, F_SETFL, fcntl(dsp_fd, F_GETFL) | O_NONBLOCK);
78
79 g_reopened = True;
80
81 return True;
82 }
83
84 void
85 sun_close(void)
86 {
87 /* Ack all remaining packets */
88 while (!rdpsnd_queue_empty())
89 rdpsnd_queue_next(0);
90
91 #if defined I_FLUSH && defined FLUSHW
92 /* Flush the audiobuffer */
93 ioctl(dsp_fd, I_FLUSH, FLUSHW);
94 #endif
95 #if defined AUDIO_FLUSH
96 ioctl(dsp_fd, AUDIO_FLUSH, NULL);
97 #endif
98 close(dsp_fd);
99 dsp_fd = -1;
100 }
101
102 BOOL
103 sun_format_supported(WAVEFORMATEX * pwfx)
104 {
105 if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
106 return False;
107 if ((pwfx->nChannels != 1) && (pwfx->nChannels != 2))
108 return False;
109 if ((pwfx->wBitsPerSample != 8) && (pwfx->wBitsPerSample != 16))
110 return False;
111
112 return True;
113 }
114
115 BOOL
116 sun_set_format(WAVEFORMATEX * pwfx)
117 {
118 audio_info_t info;
119
120 ioctl(dsp_fd, AUDIO_DRAIN, 0);
121 AUDIO_INITINFO(&info);
122
123
124 if (pwfx->wBitsPerSample == 8)
125 {
126 info.play.encoding = AUDIO_ENCODING_LINEAR8;
127 }
128 else if (pwfx->wBitsPerSample == 16)
129 {
130 info.play.encoding = AUDIO_ENCODING_LINEAR;
131 }
132
133 g_samplewidth = pwfx->wBitsPerSample / 8;
134
135 if (pwfx->nChannels == 1)
136 {
137 info.play.channels = 1;
138 }
139 else if (pwfx->nChannels == 2)
140 {
141 info.play.channels = 2;
142 g_samplewidth *= 2;
143 }
144
145 info.play.sample_rate = pwfx->nSamplesPerSec;
146 info.play.precision = pwfx->wBitsPerSample;
147 info.play.samples = 0;
148 info.play.eof = 0;
149 info.play.error = 0;
150 g_reopened = True;
151
152 if (ioctl(dsp_fd, AUDIO_SETINFO, &info) == -1)
153 {
154 perror("AUDIO_SETINFO");
155 sun_close();
156 return False;
157 }
158
159 return True;
160 }
161
162 void
163 sun_volume(uint16 left, uint16 right)
164 {
165 audio_info_t info;
166 uint balance;
167 uint volume;
168
169 AUDIO_INITINFO(&info);
170
171 volume = (left > right) ? left : right;
172
173 if (volume / AUDIO_MID_BALANCE != 0)
174 {
175 balance =
176 AUDIO_MID_BALANCE - (left / (volume / AUDIO_MID_BALANCE)) +
177 (right / (volume / AUDIO_MID_BALANCE));
178 }
179 else
180 {
181 balance = AUDIO_MID_BALANCE;
182 }
183
184 info.play.gain = volume / (65536 / AUDIO_MAX_GAIN);
185 info.play.balance = balance;
186
187 if (ioctl(dsp_fd, AUDIO_SETINFO, &info) == -1)
188 {
189 perror("AUDIO_SETINFO");
190 return;
191 }
192 }
193
194 void
195 sun_play(void)
196 {
197 struct audio_packet *packet;
198 audio_info_t info;
199 ssize_t len;
200 unsigned int i;
201 STREAM out;
202 static BOOL sentcompletion = True;
203 static uint32 samplecnt = 0;
204 static uint32 numsamples;
205
206 while (1)
207 {
208 if (g_reopened)
209 {
210 /* Device was just (re)openend */
211 samplecnt = 0;
212 sentcompletion = True;
213 g_reopened = False;
214 }
215
216 if (rdpsnd_queue_empty())
217 return;
218
219 packet = rdpsnd_queue_current_packet();
220 out = &packet->s;
221
222 if (sentcompletion)
223 {
224 sentcompletion = False;
225 numsamples = (out->end - out->p) / g_samplewidth;
226 }
227
228 len = 0;
229
230 if (out->end != out->p)
231 {
232 len = write(dsp_fd, out->p, out->end - out->p);
233 if (len == -1)
234 {
235 if (errno != EWOULDBLOCK)
236 perror("write audio");
237 return;
238 }
239 }
240
241 out->p += len;
242 if (out->p == out->end)
243 {
244 if (ioctl(dsp_fd, AUDIO_GETINFO, &info) == -1)
245 {
246 perror("AUDIO_GETINFO");
247 return;
248 }
249
250 /* Ack the packet, if we have played at least 70% */
251 if (info.play.samples >= samplecnt + ((numsamples * 7) / 10))
252 {
253 samplecnt += numsamples;
254 /* We need to add 50 to tell windows that time has passed while
255 * playing this packet */
256 rdpsnd_queue_next(50);
257 sentcompletion = True;
258 }
259 else
260 {
261 return;
262 }
263 }
264 }
265 }
266
267 static struct audio_driver sun_driver = {
268 .name = "sun",
269 .description = "SUN/BSD output driver, default device: " DEFAULTDEVICE " or $AUDIODEV",
270
271 .add_fds = sun_add_fds,
272 .check_fds = sun_check_fds,
273
274 .wave_out_open = sun_open,
275 .wave_out_close = sun_close,
276 .wave_out_format_supported = sun_format_supported,
277 .wave_out_set_format = sun_set_format,
278 .wave_out_volume = sun_volume,
279
280 .need_byteswap_on_be = 1,
281 .need_resampling = 0,
282 };
283
284 struct audio_driver *
285 sun_register(char *options)
286 {
287 if (options)
288 {
289 dsp_dev = xstrdup(options);
290 }
291 else
292 {
293 dsp_dev = getenv("AUDIODEV");
294
295 if (dsp_dev == NULL)
296 {
297 dsp_dev = xstrdup(DEFAULTDEVICE);
298 }
299 }
300
301 return &sun_driver;
302 }

  ViewVC Help
Powered by ViewVC 1.1.26