/[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 753 - (show annotations)
Mon Aug 23 11:13:50 2004 UTC (19 years, 8 months ago) by stargo
File MIME type: text/plain
File size: 5094 byte(s)
oss sound fixes

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 channels, 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 channels = pwfx->nChannels;
108 if (ioctl(g_dsp_fd, SNDCTL_DSP_CHANNELS, &channels) == -1)
109 {
110 perror("SNDCTL_DSP_CHANNELS");
111 close(g_dsp_fd);
112 return False;
113 }
114
115 if (channels == 2)
116 {
117 g_samplewidth *= 2;
118 }
119
120 g_snd_rate = pwfx->nSamplesPerSec;
121 if (ioctl(g_dsp_fd, SNDCTL_DSP_SPEED, &g_snd_rate) == -1)
122 {
123 perror("SNDCTL_DSP_SPEED");
124 close(g_dsp_fd);
125 return False;
126 }
127
128 return True;
129 }
130
131 void
132 wave_out_volume(uint16 left, uint16 right)
133 {
134 static BOOL use_dev_mixer = False;
135 uint32 volume;
136 int fd_mix = -1;
137
138 volume = left / (65536 / 100);
139 volume |= right / (65536 / 100) << 8;
140
141 if (use_dev_mixer)
142 {
143 if ((fd_mix = open("/dev/mixer", O_RDWR | O_NONBLOCK)) == -1)
144 {
145 perror("open /dev/mixer");
146 return;
147 }
148
149 if (ioctl(fd_mix, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
150 {
151 perror("MIXER_WRITE(SOUND_MIXER_PCM)");
152 return;
153 }
154
155 close(fd_mix);
156 }
157
158 if (ioctl(g_dsp_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
159 {
160 perror("MIXER_WRITE(SOUND_MIXER_PCM)");
161 use_dev_mixer = True;
162 return;
163 }
164 }
165
166 void
167 wave_out_write(STREAM s, uint16 tick, uint8 index)
168 {
169 struct audio_packet *packet = &packet_queue[queue_hi];
170 unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
171
172 if (next_hi == queue_lo)
173 {
174 error("No space to queue audio packet\n");
175 return;
176 }
177
178 queue_hi = next_hi;
179
180 packet->s = *s;
181 packet->tick = tick;
182 packet->index = index;
183 packet->s.p += 4;
184
185 /* we steal the data buffer from s, give it a new one */
186 s->data = malloc(s->size);
187
188 if (!g_dsp_busy)
189 wave_out_play();
190 }
191
192 void
193 wave_out_play(void)
194 {
195 struct audio_packet *packet;
196 ssize_t len;
197 STREAM out;
198 static long startedat_us;
199 static long startedat_s;
200 static BOOL started = False;
201 struct timeval tv;
202
203 while (1)
204 {
205 if (queue_lo == queue_hi)
206 {
207 g_dsp_busy = 0;
208 return;
209 }
210
211 packet = &packet_queue[queue_lo];
212 out = &packet->s;
213
214 if (!started)
215 {
216 gettimeofday(&tv, NULL);
217 startedat_us = tv.tv_usec;
218 startedat_s = tv.tv_sec;
219 started = True;
220 }
221
222 len = write(g_dsp_fd, out->p, out->end - out->p);
223 if (len == -1)
224 {
225 if (errno != EWOULDBLOCK)
226 perror("write audio");
227 g_dsp_busy = 1;
228 return;
229 }
230
231 out->p += len;
232 if (out->p == out->end)
233 {
234 long long duration;
235 long elapsed;
236
237 gettimeofday(&tv, NULL);
238 duration = (out->size * (1000000 / (g_samplewidth * g_snd_rate)));
239 elapsed = (tv.tv_sec - startedat_s) * 1000000 + (tv.tv_usec - startedat_us);
240
241 if (elapsed >= (duration * 85) / 100)
242 {
243 rdpsnd_send_completion(packet->tick, packet->index);
244 free(out->data);
245 queue_lo = (queue_lo + 1) % MAX_QUEUE;
246 started = False;
247 }
248 else
249 {
250 g_dsp_busy = 1;
251 return;
252 }
253 }
254 }
255 }

  ViewVC Help
Powered by ViewVC 1.1.26