/[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 1256 - (show annotations)
Sun Sep 17 11:42:22 2006 UTC (17 years, 7 months ago) by stargo
File MIME type: text/plain
File size: 6370 byte(s)
fix SunCC errors/warnings and configure-variable-usage (LIBS/LDFLAGS)

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

  ViewVC Help
Powered by ViewVC 1.1.26