/[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 1302 - (show annotations)
Thu Oct 26 09:47:17 2006 UTC (17 years, 7 months ago) by ossman_
File MIME type: text/plain
File size: 5790 byte(s)
Rewrite the queue management a bit so that blocks are not completed until
they have finished playing. This also makes the queue system mandatory for
all backends.

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

  ViewVC Help
Powered by ViewVC 1.1.26