/[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 532 - (show annotations)
Wed Oct 29 14:14:46 2003 UTC (20 years, 7 months ago) by astrand
File MIME type: text/plain
File size: 5031 byte(s)
Indent 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 = "/dev/dsp";
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 /* Non-blocking so that user interface is responsive */
57 fcntl(g_dsp_fd, F_SETFL, fcntl(g_dsp_fd, F_GETFL) | O_NONBLOCK);
58 return True;
59 }
60
61 void
62 wave_out_close(void)
63 {
64 close(g_dsp_fd);
65 }
66
67 BOOL
68 wave_out_format_supported(WAVEFORMATEX * pwfx)
69 {
70 if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
71 return False;
72 if ((pwfx->nChannels != 1) && (pwfx->nChannels != 2))
73 return False;
74 if ((pwfx->wBitsPerSample != 8) && (pwfx->wBitsPerSample != 16))
75 return False;
76
77 return True;
78 }
79
80 BOOL
81 wave_out_set_format(WAVEFORMATEX * pwfx)
82 {
83 int channels, format;
84
85 ioctl(g_dsp_fd, SNDCTL_DSP_RESET, NULL);
86 ioctl(g_dsp_fd, SNDCTL_DSP_SYNC, NULL);
87
88 if (pwfx->wBitsPerSample == 8)
89 format = AFMT_U8;
90 else if (pwfx->wBitsPerSample == 16)
91 format = AFMT_S16_LE;
92
93 g_samplewidth = pwfx->wBitsPerSample / 8;
94
95 if (ioctl(g_dsp_fd, SNDCTL_DSP_SETFMT, &format) == -1)
96 {
97 perror("SNDCTL_DSP_SETFMT");
98 close(g_dsp_fd);
99 return False;
100 }
101
102 channels = pwfx->nChannels;
103 if (ioctl(g_dsp_fd, SNDCTL_DSP_CHANNELS, &channels) == -1)
104 {
105 perror("SNDCTL_DSP_CHANNELS");
106 close(g_dsp_fd);
107 return False;
108 }
109
110 if (channels == 2)
111 {
112 g_samplewidth *= 2;
113 }
114
115 g_snd_rate = pwfx->nSamplesPerSec;
116 if (ioctl(g_dsp_fd, SNDCTL_DSP_SPEED, &g_snd_rate) == -1)
117 {
118 perror("SNDCTL_DSP_SPEED");
119 close(g_dsp_fd);
120 return False;
121 }
122
123 return True;
124 }
125
126 void
127 wave_out_volume(uint16 left, uint16 right)
128 {
129 static BOOL use_dev_mixer = False;
130 uint32 volume;
131 int fd_mix = -1;
132
133 volume = left / (65536 / 100);
134 volume |= right / (65536 / 100) << 8;
135
136 if (use_dev_mixer)
137 {
138 if ((fd_mix = open("/dev/mixer", O_RDWR | O_NONBLOCK)) == -1)
139 {
140 perror("open /dev/mixer");
141 return;
142 }
143
144 if (ioctl(fd_mix, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
145 {
146 perror("MIXER_WRITE(SOUND_MIXER_PCM)");
147 return;
148 }
149
150 close(fd_mix);
151 }
152
153 if (ioctl(g_dsp_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
154 {
155 perror("MIXER_WRITE(SOUND_MIXER_PCM)");
156 use_dev_mixer = True;
157 return;
158 }
159 }
160
161 void
162 wave_out_write(STREAM s, uint16 tick, uint8 index)
163 {
164 struct audio_packet *packet = &packet_queue[queue_hi];
165 unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
166
167 if (next_hi == queue_lo)
168 {
169 error("No space to queue audio packet\n");
170 return;
171 }
172
173 queue_hi = next_hi;
174
175 packet->s = *s;
176 packet->tick = tick;
177 packet->index = index;
178 packet->s.p += 4;
179
180 /* we steal the data buffer from s, give it a new one */
181 s->data = malloc(s->size);
182
183 if (!g_dsp_busy)
184 wave_out_play();
185 }
186
187 void
188 wave_out_play(void)
189 {
190 struct audio_packet *packet;
191 ssize_t len;
192 STREAM out;
193 static long startedat_us;
194 static long startedat_s;
195 static BOOL started = False;
196 struct timeval tv;
197
198 while (1)
199 {
200 if (queue_lo == queue_hi)
201 {
202 g_dsp_busy = 0;
203 return;
204 }
205
206 packet = &packet_queue[queue_lo];
207 out = &packet->s;
208
209 if (!started)
210 {
211 gettimeofday(&tv, NULL);
212 startedat_us = tv.tv_usec;
213 startedat_s = tv.tv_sec;
214 started = True;
215 }
216
217 len = write(g_dsp_fd, out->p, out->end - out->p);
218 if (len == -1)
219 {
220 if (errno != EWOULDBLOCK)
221 perror("write audio");
222 g_dsp_busy = 1;
223 return;
224 }
225
226 out->p += len;
227 if (out->p == out->end)
228 {
229 long long duration;
230 long elapsed;
231
232 gettimeofday(&tv, NULL);
233 duration = (out->size * (1000000 / (g_samplewidth * g_snd_rate)));
234 elapsed = (tv.tv_sec - startedat_s) * 1000000 + (tv.tv_usec - startedat_us);
235
236 if (elapsed >= (duration * 7) / 10)
237 {
238 rdpsnd_send_completion(packet->tick, packet->index);
239 free(out->data);
240 queue_lo = (queue_lo + 1) % MAX_QUEUE;
241 started = False;
242 }
243 else
244 {
245 g_dsp_busy = 1;
246 return;
247 }
248 }
249 }
250 }

  ViewVC Help
Powered by ViewVC 1.1.26