/[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 1345 - (show annotations)
Thu Dec 7 11:54:29 2006 UTC (17 years, 5 months ago) by ossman_
File MIME type: text/plain
File size: 5534 byte(s)
Restructure driver registration structures a bit so it is easier to add
new fields (and also reduce some memory usage/leaks).

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

  ViewVC Help
Powered by ViewVC 1.1.26