/[rdesktop]/sourceforge.net/trunk/rdesktop/rdpsnd_oss.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_oss.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 760 - (show annotations)
Fri Sep 3 18:04:48 2004 UTC (19 years, 9 months ago) by stargo
File MIME type: text/plain
File size: 5106 byte(s)
fix for esddsp, which does not implement the SNDCTL_DSP_CHANNELS ioctl

1 /*
2 rdesktop: A Remote Desktop Protocol client.
3 Sound Channel Process Functions - Open Sound System
4 Copyright (C) Matthew Chapman 2003
5 Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "rdesktop.h"
23 #include <unistd.h>
24 #include <fcntl.h>
25 #include <errno.h>
26 #include <sys/time.h>
27 #include <sys/ioctl.h>
28 #include <sys/soundcard.h>
29
30 #define MAX_QUEUE 10
31
32 int g_dsp_fd;
33 BOOL g_dsp_busy = False;
34 static int g_snd_rate;
35 static short g_samplewidth;
36
37 static struct audio_packet
38 {
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 = getenv("AUDIODEV");
49
50 if (dsp_dev == NULL)
51 {
52 dsp_dev = "/dev/dsp";
53 }
54
55 if ((g_dsp_fd = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1)
56 {
57 perror(dsp_dev);
58 return False;
59 }
60
61 /* Non-blocking so that user interface is responsive */
62 fcntl(g_dsp_fd, F_SETFL, fcntl(g_dsp_fd, F_GETFL) | O_NONBLOCK);
63 return True;
64 }
65
66 void
67 wave_out_close(void)
68 {
69 close(g_dsp_fd);
70 }
71
72 BOOL
73 wave_out_format_supported(WAVEFORMATEX * pwfx)
74 {
75 if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
76 return False;
77 if ((pwfx->nChannels != 1) && (pwfx->nChannels != 2))
78 return False;
79 if ((pwfx->wBitsPerSample != 8) && (pwfx->wBitsPerSample != 16))
80 return False;
81
82 return True;
83 }
84
85 BOOL
86 wave_out_set_format(WAVEFORMATEX * pwfx)
87 {
88 int stereo, format;
89
90 ioctl(g_dsp_fd, SNDCTL_DSP_RESET, NULL);
91 ioctl(g_dsp_fd, SNDCTL_DSP_SYNC, NULL);
92
93 if (pwfx->wBitsPerSample == 8)
94 format = AFMT_U8;
95 else if (pwfx->wBitsPerSample == 16)
96 format = AFMT_S16_LE;
97
98 g_samplewidth = pwfx->wBitsPerSample / 8;
99
100 if (ioctl(g_dsp_fd, SNDCTL_DSP_SETFMT, &format) == -1)
101 {
102 perror("SNDCTL_DSP_SETFMT");
103 close(g_dsp_fd);
104 return False;
105 }
106
107 if (pwfx->nChannels == 2)
108 {
109 stereo = 1;
110 g_samplewidth *= 2;
111 }
112 else
113 {
114 stereo = 0;
115 }
116
117 if (ioctl(g_dsp_fd, SNDCTL_DSP_STEREO, &stereo) == -1)
118 {
119 perror("SNDCTL_DSP_CHANNELS");
120 close(g_dsp_fd);
121 return False;
122 }
123
124 g_snd_rate = pwfx->nSamplesPerSec;
125 if (ioctl(g_dsp_fd, SNDCTL_DSP_SPEED, &g_snd_rate) == -1)
126 {
127 perror("SNDCTL_DSP_SPEED");
128 close(g_dsp_fd);
129 return False;
130 }
131
132 return True;
133 }
134
135 void
136 wave_out_volume(uint16 left, uint16 right)
137 {
138 static BOOL use_dev_mixer = False;
139 uint32 volume;
140 int fd_mix = -1;
141
142 volume = left / (65536 / 100);
143 volume |= right / (65536 / 100) << 8;
144
145 if (use_dev_mixer)
146 {
147 if ((fd_mix = open("/dev/mixer", O_RDWR | O_NONBLOCK)) == -1)
148 {
149 perror("open /dev/mixer");
150 return;
151 }
152
153 if (ioctl(fd_mix, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
154 {
155 perror("MIXER_WRITE(SOUND_MIXER_PCM)");
156 return;
157 }
158
159 close(fd_mix);
160 }
161
162 if (ioctl(g_dsp_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
163 {
164 perror("MIXER_WRITE(SOUND_MIXER_PCM)");
165 use_dev_mixer = True;
166 return;
167 }
168 }
169
170 void
171 wave_out_write(STREAM s, uint16 tick, uint8 index)
172 {
173 struct audio_packet *packet = &packet_queue[queue_hi];
174 unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
175
176 if (next_hi == queue_lo)
177 {
178 error("No space to queue audio packet\n");
179 return;
180 }
181
182 queue_hi = next_hi;
183
184 packet->s = *s;
185 packet->tick = tick;
186 packet->index = index;
187 packet->s.p += 4;
188
189 /* we steal the data buffer from s, give it a new one */
190 s->data = malloc(s->size);
191
192 if (!g_dsp_busy)
193 wave_out_play();
194 }
195
196 void
197 wave_out_play(void)
198 {
199 struct audio_packet *packet;
200 ssize_t len;
201 STREAM out;
202 static long startedat_us;
203 static long startedat_s;
204 static BOOL started = False;
205 struct timeval tv;
206
207 while (1)
208 {
209 if (queue_lo == queue_hi)
210 {
211 g_dsp_busy = 0;
212 return;
213 }
214
215 packet = &packet_queue[queue_lo];
216 out = &packet->s;
217
218 if (!started)
219 {
220 gettimeofday(&tv, NULL);
221 startedat_us = tv.tv_usec;
222 startedat_s = tv.tv_sec;
223 started = True;
224 }
225
226 len = write(g_dsp_fd, out->p, out->end - out->p);
227 if (len == -1)
228 {
229 if (errno != EWOULDBLOCK)
230 perror("write audio");
231 g_dsp_busy = 1;
232 return;
233 }
234
235 out->p += len;
236 if (out->p == out->end)
237 {
238 long long duration;
239 long elapsed;
240
241 gettimeofday(&tv, NULL);
242 duration = (out->size * (1000000 / (g_samplewidth * g_snd_rate)));
243 elapsed = (tv.tv_sec - startedat_s) * 1000000 + (tv.tv_usec - startedat_us);
244
245 if (elapsed >= (duration * 85) / 100)
246 {
247 rdpsnd_send_completion(packet->tick, packet->index);
248 free(out->data);
249 queue_lo = (queue_lo + 1) % MAX_QUEUE;
250 started = False;
251 }
252 else
253 {
254 g_dsp_busy = 1;
255 return;
256 }
257 }
258 }
259 }

  ViewVC Help
Powered by ViewVC 1.1.26