/[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 1254 - (show annotations)
Sun Sep 17 10:32:18 2006 UTC (17 years, 8 months ago) by stargo
File MIME type: text/plain
File size: 5275 byte(s)
unify queue-handling in rdpsnd.c (remove private copies from all
drivers)

1 /* -*- c-basic-offset: 8 -*-
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 /*
23 This is a workaround for Esound bug 312665.
24 FIXME: Remove this when Esound is fixed.
25 */
26 #ifdef _FILE_OFFSET_BITS
27 #undef _FILE_OFFSET_BITS
28 #endif
29
30 #include "rdesktop.h"
31 #include "rdpsnd.h"
32 #include <unistd.h>
33 #include <fcntl.h>
34 #include <errno.h>
35 #include <sys/time.h>
36 #include <sys/ioctl.h>
37 #include <sys/soundcard.h>
38
39 #define DEFAULTDEVICE "/dev/dsp"
40 #define MAX_LEN 512
41
42 static int snd_rate;
43 static short samplewidth;
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 = xstrdup(DEFAULTDEVICE);
53 }
54
55 if ((g_dsp_fd = open(dsp_dev, O_WRONLY)) == -1)
56 {
57 perror(dsp_dev);
58 return False;
59 }
60
61 return True;
62 }
63
64 void
65 wave_out_close(void)
66 {
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 int stereo, format, fragments;
87 static BOOL driver_broken = False;
88
89 ioctl(g_dsp_fd, SNDCTL_DSP_RESET, NULL);
90 ioctl(g_dsp_fd, SNDCTL_DSP_SYNC, NULL);
91
92 if (pwfx->wBitsPerSample == 8)
93 format = AFMT_U8;
94 else if (pwfx->wBitsPerSample == 16)
95 format = AFMT_S16_LE;
96
97 samplewidth = pwfx->wBitsPerSample / 8;
98
99 if (ioctl(g_dsp_fd, SNDCTL_DSP_SETFMT, &format) == -1)
100 {
101 perror("SNDCTL_DSP_SETFMT");
102 close(g_dsp_fd);
103 return False;
104 }
105
106 if (pwfx->nChannels == 2)
107 {
108 stereo = 1;
109 samplewidth *= 2;
110 }
111 else
112 {
113 stereo = 0;
114 }
115
116 if (ioctl(g_dsp_fd, SNDCTL_DSP_STEREO, &stereo) == -1)
117 {
118 perror("SNDCTL_DSP_CHANNELS");
119 close(g_dsp_fd);
120 return False;
121 }
122
123 snd_rate = pwfx->nSamplesPerSec;
124 if (ioctl(g_dsp_fd, SNDCTL_DSP_SPEED, &snd_rate) == -1)
125 {
126 perror("SNDCTL_DSP_SPEED");
127 close(g_dsp_fd);
128 return False;
129 }
130
131 /* try to get 12 fragments of 2^12 bytes size */
132 fragments = (12 << 16) + 12;
133 ioctl(g_dsp_fd, SNDCTL_DSP_SETFRAGMENT, &fragments);
134
135 if (!driver_broken)
136 {
137 audio_buf_info info;
138
139 memset(&info, 0, sizeof(info));
140 if (ioctl(g_dsp_fd, SNDCTL_DSP_GETOSPACE, &info) == -1)
141 {
142 perror("SNDCTL_DSP_GETOSPACE");
143 close(g_dsp_fd);
144 return False;
145 }
146
147 if (info.fragments == 0 || info.fragstotal == 0 || info.fragsize == 0)
148 {
149 fprintf(stderr,
150 "Broken OSS-driver detected: fragments: %d, fragstotal: %d, fragsize: %d\n",
151 info.fragments, info.fragstotal, info.fragsize);
152 driver_broken = True;
153 }
154 }
155
156 return True;
157 }
158
159 void
160 wave_out_volume(uint16 left, uint16 right)
161 {
162 static BOOL use_dev_mixer = False;
163 uint32 volume;
164 int fd_mix = -1;
165
166 volume = left / (65536 / 100);
167 volume |= right / (65536 / 100) << 8;
168
169 if (use_dev_mixer)
170 {
171 if ((fd_mix = open("/dev/mixer", O_RDWR | O_NONBLOCK)) == -1)
172 {
173 perror("open /dev/mixer");
174 return;
175 }
176
177 if (ioctl(fd_mix, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
178 {
179 perror("MIXER_WRITE(SOUND_MIXER_PCM)");
180 return;
181 }
182
183 close(fd_mix);
184 }
185
186 if (ioctl(g_dsp_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
187 {
188 perror("MIXER_WRITE(SOUND_MIXER_PCM)");
189 use_dev_mixer = True;
190 return;
191 }
192 }
193
194 void
195 wave_out_play(void)
196 {
197 struct audio_packet *packet;
198 ssize_t len;
199 STREAM out;
200 static long startedat_us;
201 static long startedat_s;
202 static BOOL started = False;
203 struct timeval tv;
204
205 if (rdpsnd_queue_empty())
206 {
207 g_dsp_busy = 0;
208 return;
209 }
210
211 packet = rdpsnd_queue_current_packet();
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 = out->end - out->p;
223
224 len = write(g_dsp_fd, out->p, (len > MAX_LEN) ? MAX_LEN : len);
225 if (len == -1)
226 {
227 if (errno != EWOULDBLOCK)
228 perror("write audio");
229 g_dsp_busy = 1;
230 return;
231 }
232
233 out->p += len;
234 if (out->p == out->end)
235 {
236 long long duration;
237 long elapsed;
238
239 gettimeofday(&tv, NULL);
240 duration = (out->size * (1000000 / (samplewidth * snd_rate)));
241 elapsed = (tv.tv_sec - startedat_s) * 1000000 + (tv.tv_usec - startedat_us);
242
243 if (elapsed >= (duration * 85) / 100)
244 {
245 /* We need to add 50 to tell windows that time has passed while
246 * playing this packet */
247 rdpsnd_send_completion(packet->tick + 50, packet->index);
248 rdpsnd_queue_next();
249 started = False;
250 }
251 else
252 {
253 g_dsp_busy = 1;
254 return;
255 }
256 }
257 g_dsp_busy = 1;
258 return;
259 }

  ViewVC Help
Powered by ViewVC 1.1.26