/[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

Annotation of /sourceforge.net/trunk/rdesktop/rdpsnd_oss.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 751 - (hide annotations)
Fri Aug 13 09:43:31 2004 UTC (19 years, 9 months ago) by stargo
File MIME type: text/plain
File size: 5092 byte(s)
add $AUDIODEV support to oss-driver

1 matthewc 475 /*
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 stargo 510 #include <sys/time.h>
27 matthewc 475 #include <sys/ioctl.h>
28     #include <sys/soundcard.h>
29    
30     #define MAX_QUEUE 10
31    
32     int g_dsp_fd;
33 stargo 504 BOOL g_dsp_busy = False;
34 stargo 510 static int g_snd_rate;
35     static short g_samplewidth;
36 matthewc 475
37 astrand 499 static struct audio_packet
38     {
39 matthewc 475 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 stargo 751 char *dsp_dev = getenv("AUDIODEV");
49 matthewc 475
50 stargo 751 if (dsp_dev == NULL)
51     {
52     dsp_dev = "/dev/dsp";
53     }
54    
55 astrand 499 if ((g_dsp_fd = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1)
56 matthewc 475 {
57     perror(dsp_dev);
58     return False;
59     }
60    
61     /* Non-blocking so that user interface is responsive */
62 astrand 499 fcntl(g_dsp_fd, F_SETFL, fcntl(g_dsp_fd, F_GETFL) | O_NONBLOCK);
63 matthewc 475 return True;
64     }
65    
66     void
67     wave_out_close(void)
68     {
69     close(g_dsp_fd);
70     }
71    
72     BOOL
73 astrand 499 wave_out_format_supported(WAVEFORMATEX * pwfx)
74 matthewc 475 {
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 astrand 499 wave_out_set_format(WAVEFORMATEX * pwfx)
87 matthewc 475 {
88 stargo 510 int channels, format;
89 matthewc 475
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 stargo 510 g_samplewidth = pwfx->wBitsPerSample / 8;
99    
100 matthewc 475 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 stargo 510 if (channels == 2)
116 matthewc 475 {
117 stargo 510 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 matthewc 475 perror("SNDCTL_DSP_SPEED");
124     close(g_dsp_fd);
125     return False;
126     }
127    
128     return True;
129     }
130    
131     void
132 stargo 491 wave_out_volume(uint16 left, uint16 right)
133     {
134 stargo 509 static BOOL use_dev_mixer = False;
135 stargo 491 uint32 volume;
136 stargo 509 int fd_mix = -1;
137 stargo 491
138 astrand 499 volume = left / (65536 / 100);
139     volume |= right / (65536 / 100) << 8;
140 stargo 509
141     if (use_dev_mixer)
142     {
143 astrand 532 if ((fd_mix = open("/dev/mixer", O_RDWR | O_NONBLOCK)) == -1)
144 stargo 509 {
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 stargo 491 if (ioctl(g_dsp_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
159     {
160     perror("MIXER_WRITE(SOUND_MIXER_PCM)");
161 stargo 509 use_dev_mixer = True;
162 stargo 491 return;
163     }
164     }
165    
166     void
167 matthewc 475 wave_out_write(STREAM s, uint16 tick, uint8 index)
168     {
169 matthewc 476 struct audio_packet *packet = &packet_queue[queue_hi];
170     unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
171 matthewc 475
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 stargo 491 packet->s.p += 4;
184 matthewc 475
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 stargo 510 static long startedat_us;
199     static long startedat_s;
200     static BOOL started = False;
201     struct timeval tv;
202 matthewc 475
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 stargo 510 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 astrand 499 len = write(g_dsp_fd, out->p, out->end - out->p);
223 matthewc 475 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 stargo 510 long long duration;
235     long elapsed;
236 astrand 532
237 stargo 510 gettimeofday(&tv, NULL);
238 astrand 532 duration = (out->size * (1000000 / (g_samplewidth * g_snd_rate)));
239     elapsed = (tv.tv_sec - startedat_s) * 1000000 + (tv.tv_usec - startedat_us);
240 stargo 510
241 astrand 532 if (elapsed >= (duration * 7) / 10)
242 stargo 510 {
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 matthewc 475 }
254     }
255     }

  ViewVC Help
Powered by ViewVC 1.1.26