/[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 760 - (hide 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 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 760 int stereo, 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 stargo 760 if (pwfx->nChannels == 2)
108 matthewc 475 {
109 stargo 760 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 matthewc 475 perror("SNDCTL_DSP_CHANNELS");
120     close(g_dsp_fd);
121     return False;
122     }
123    
124 stargo 510 g_snd_rate = pwfx->nSamplesPerSec;
125     if (ioctl(g_dsp_fd, SNDCTL_DSP_SPEED, &g_snd_rate) == -1)
126     {
127 matthewc 475 perror("SNDCTL_DSP_SPEED");
128     close(g_dsp_fd);
129     return False;
130     }
131    
132     return True;
133     }
134    
135     void
136 stargo 491 wave_out_volume(uint16 left, uint16 right)
137     {
138 stargo 509 static BOOL use_dev_mixer = False;
139 stargo 491 uint32 volume;
140 stargo 509 int fd_mix = -1;
141 stargo 491
142 astrand 499 volume = left / (65536 / 100);
143     volume |= right / (65536 / 100) << 8;
144 stargo 509
145     if (use_dev_mixer)
146     {
147 astrand 532 if ((fd_mix = open("/dev/mixer", O_RDWR | O_NONBLOCK)) == -1)
148 stargo 509 {
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 stargo 491 if (ioctl(g_dsp_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
163     {
164     perror("MIXER_WRITE(SOUND_MIXER_PCM)");
165 stargo 509 use_dev_mixer = True;
166 stargo 491 return;
167     }
168     }
169    
170     void
171 matthewc 475 wave_out_write(STREAM s, uint16 tick, uint8 index)
172     {
173 matthewc 476 struct audio_packet *packet = &packet_queue[queue_hi];
174     unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
175 matthewc 475
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 stargo 491 packet->s.p += 4;
188 matthewc 475
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 stargo 510 static long startedat_us;
203     static long startedat_s;
204     static BOOL started = False;
205     struct timeval tv;
206 matthewc 475
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 stargo 510 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 astrand 499 len = write(g_dsp_fd, out->p, out->end - out->p);
227 matthewc 475 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 stargo 510 long long duration;
239     long elapsed;
240 astrand 532
241 stargo 510 gettimeofday(&tv, NULL);
242 astrand 532 duration = (out->size * (1000000 / (g_samplewidth * g_snd_rate)));
243     elapsed = (tv.tv_sec - startedat_s) * 1000000 + (tv.tv_usec - startedat_us);
244 stargo 510
245 stargo 753 if (elapsed >= (duration * 85) / 100)
246 stargo 510 {
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 matthewc 475 }
258     }
259     }

  ViewVC Help
Powered by ViewVC 1.1.26