/[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 559 - (show annotations)
Thu Dec 11 12:25:38 2003 UTC (20 years, 5 months ago) by stargo
File MIME type: text/plain
File size: 6166 byte(s)
Removed timezone stuff, due to too much portability problems...
Will solve this later
Portability "fix" for rdpsnd_sun.c on openbsd

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

  ViewVC Help
Powered by ViewVC 1.1.26