/[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 476 - (show annotations)
Sat Oct 4 00:03:24 2003 UTC (20 years, 7 months ago) by matthewc
File MIME type: text/plain
File size: 4886 byte(s)
Add Sun audio support, fix a bug in the OSS driver.
(Michael Gernoth <michael@gernoth.net>)

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/audio.h>
29 #include <stropts.h>
30
31 #define MAX_QUEUE 10
32
33 int g_dsp_fd;
34 BOOL g_dsp_busy;
35 static BOOL swapaudio;
36 static short samplewidth;
37
38 static struct audio_packet {
39 struct stream s;
40 uint16 tick;
41 uint8 index;
42 } packet_queue[MAX_QUEUE];
43 static unsigned int queue_hi, queue_lo;
44
45 BOOL
46 wave_out_open(void)
47 {
48 char *dsp_dev = "/dev/audio";
49
50 if ((g_dsp_fd = open(dsp_dev, O_WRONLY|O_NONBLOCK)) == -1)
51 {
52 perror(dsp_dev);
53 return False;
54 }
55
56
57 /* Non-blocking so that user interface is responsive */
58 fcntl(g_dsp_fd, F_SETFL, fcntl(g_dsp_fd, F_GETFL)|O_NONBLOCK);
59 queue_lo = queue_hi = 0;
60 return True;
61 }
62
63 void
64 wave_out_close(void)
65 {
66 ioctl(g_dsp_fd,I_FLUSH,FLUSHW);
67 close(g_dsp_fd);
68 }
69
70 BOOL
71 wave_out_format_supported(WAVEFORMATEX *pwfx)
72 {
73 if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
74 return False;
75 if ((pwfx->nChannels != 1) && (pwfx->nChannels != 2))
76 return False;
77 if ((pwfx->wBitsPerSample != 8) && (pwfx->wBitsPerSample != 16))
78 return False;
79
80 return True;
81 }
82
83 BOOL
84 wave_out_set_format(WAVEFORMATEX *pwfx)
85 {
86 audio_info_t info;
87 int test = 1;
88
89 ioctl(g_dsp_fd, AUDIO_DRAIN, 0);
90 swapaudio = False;
91 AUDIO_INITINFO(&info);
92
93
94 if (pwfx->wBitsPerSample == 8)
95 {
96 info.play.encoding = AUDIO_ENCODING_LINEAR8;
97 samplewidth=1;
98 }
99 else if (pwfx->wBitsPerSample == 16)
100 {
101 info.play.encoding = AUDIO_ENCODING_LINEAR;
102 swapaudio = !(*(uint8 *) (&test));
103 samplewidth=2;
104 }
105
106 if (pwfx->nChannels == 1 )
107 {
108 info.play.channels = AUDIO_CHANNELS_MONO;
109 }
110 else if (pwfx->nChannels == 2 )
111 {
112 info.play.channels = AUDIO_CHANNELS_STEREO;
113 samplewidth*=2;
114 }
115
116 info.play.sample_rate = pwfx->nSamplesPerSec;
117 info.play.precision = pwfx->wBitsPerSample;
118 info.play.samples = 0;
119 info.play.eof = 0;
120 info.play.error = 0;
121
122 if (ioctl(g_dsp_fd, AUDIO_SETINFO, &info) == -1)
123 {
124 perror("AUDIO_SETINFO");
125 close(g_dsp_fd);
126 return False;
127 }
128
129 return True;
130 }
131
132 void
133 wave_out_write(STREAM s, uint16 tick, uint8 index)
134 {
135 struct audio_packet *packet = &packet_queue[queue_hi];
136 unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
137
138 if (next_hi == queue_lo)
139 {
140 error("No space to queue audio packet\n");
141 return;
142 }
143
144 queue_hi = next_hi;
145
146 packet->s = *s;
147 packet->tick = tick;
148 packet->index = index;
149
150 /* we steal the data buffer from s, give it a new one */
151 s->data = malloc(s->size);
152
153 if (!g_dsp_busy)
154 wave_out_play();
155 }
156
157 void
158 wave_out_play(void)
159 {
160 struct audio_packet *packet;
161 audio_info_t info;
162 ssize_t len;
163 unsigned int i;
164 uint8 swap;
165 STREAM out;
166 static BOOL swapped = False;
167 static BOOL sentcompletion = True;
168 static int samplecnt;
169 static int numsamples;
170
171 while (1)
172 {
173 if (queue_lo == queue_hi)
174 {
175 g_dsp_busy = 0;
176 return;
177 }
178
179 packet = &packet_queue[queue_lo];
180 out = &packet->s;
181
182 if ( swapaudio && ! swapped )
183 {
184 for ( i = 0; i < out->end - out->p; i+=2 )
185 {
186 swap = *(out->p + i);
187 *(out->p + i ) = *(out->p + i + 1);
188 *(out->p + i + 1) = swap;
189 swapped = True;
190 }
191 }
192
193 if ( sentcompletion )
194 {
195 if (ioctl(g_dsp_fd, AUDIO_GETINFO, &info) == -1)
196 {
197 perror("AUDIO_GETINFO");
198 return;
199 }
200 samplecnt=info.play.samples;
201 sentcompletion = False;
202 numsamples = (out->end-out->p)/samplewidth;
203 }
204
205 len=0;
206
207 if ( out->end - out->p != 0 )
208 {
209 len = write(g_dsp_fd, out->p, out->end - out->p);
210 if (len == -1)
211 {
212 if (errno != EWOULDBLOCK)
213 perror("write audio");
214 g_dsp_busy = 1;
215 return;
216 }
217 }
218
219 out->p += len;
220 if (out->p == out->end)
221 {
222 if (ioctl(g_dsp_fd, AUDIO_GETINFO, &info) == -1)
223 {
224 perror("AUDIO_GETINFO");
225 return;
226 }
227 if ( info.play.samples >= samplecnt+(numsamples)*0.9 )
228 {
229 rdpsnd_send_completion(packet->tick, packet->index);
230 free(out->data);
231 queue_lo = (queue_lo + 1) % MAX_QUEUE;
232 swapped = False;
233 sentcompletion = True;
234 }
235 else
236 {
237 g_dsp_busy = 1;
238 return;
239 }
240 }
241 }
242 }

  ViewVC Help
Powered by ViewVC 1.1.26