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

  ViewVC Help
Powered by ViewVC 1.1.26