/[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 1254 - (hide 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 astrand 963 /* -*- c-basic-offset: 8 -*-
2 matthewc 475 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 astrand 1227 /*
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 matthewc 475 #include "rdesktop.h"
31 stargo 1254 #include "rdpsnd.h"
32 matthewc 475 #include <unistd.h>
33     #include <fcntl.h>
34     #include <errno.h>
35 stargo 510 #include <sys/time.h>
36 matthewc 475 #include <sys/ioctl.h>
37     #include <sys/soundcard.h>
38    
39 stargo 1254 #define DEFAULTDEVICE "/dev/dsp"
40 stargo 1247 #define MAX_LEN 512
41 matthewc 475
42 stargo 1247 static int snd_rate;
43     static short samplewidth;
44 matthewc 475
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 stargo 1254 dsp_dev = xstrdup(DEFAULTDEVICE);
53 stargo 751 }
54    
55 stargo 1247 if ((g_dsp_fd = open(dsp_dev, O_WRONLY)) == -1)
56 matthewc 475 {
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 astrand 499 wave_out_format_supported(WAVEFORMATEX * pwfx)
72 matthewc 475 {
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 astrand 499 wave_out_set_format(WAVEFORMATEX * pwfx)
85 matthewc 475 {
86 stargo 761 int stereo, format, fragments;
87 stargo 1247 static BOOL driver_broken = False;
88 matthewc 475
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 stargo 1247 samplewidth = pwfx->wBitsPerSample / 8;
98 stargo 510
99 matthewc 475 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 stargo 760 if (pwfx->nChannels == 2)
107 matthewc 475 {
108 stargo 760 stereo = 1;
109 stargo 1247 samplewidth *= 2;
110 stargo 760 }
111     else
112     {
113     stereo = 0;
114     }
115    
116     if (ioctl(g_dsp_fd, SNDCTL_DSP_STEREO, &stereo) == -1)
117     {
118 matthewc 475 perror("SNDCTL_DSP_CHANNELS");
119     close(g_dsp_fd);
120     return False;
121     }
122    
123 stargo 1247 snd_rate = pwfx->nSamplesPerSec;
124     if (ioctl(g_dsp_fd, SNDCTL_DSP_SPEED, &snd_rate) == -1)
125 stargo 510 {
126 matthewc 475 perror("SNDCTL_DSP_SPEED");
127     close(g_dsp_fd);
128     return False;
129     }
130    
131 stargo 1247 /* try to get 12 fragments of 2^12 bytes size */
132     fragments = (12 << 16) + 12;
133 stargo 761 ioctl(g_dsp_fd, SNDCTL_DSP_SETFRAGMENT, &fragments);
134    
135 stargo 1247 if (!driver_broken)
136 stargo 761 {
137     audio_buf_info info;
138    
139 astrand 801 memset(&info, 0, sizeof(info));
140 stargo 761 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 stargo 1247 driver_broken = True;
153 stargo 761 }
154     }
155    
156 matthewc 475 return True;
157     }
158    
159     void
160 stargo 491 wave_out_volume(uint16 left, uint16 right)
161     {
162 stargo 509 static BOOL use_dev_mixer = False;
163 stargo 491 uint32 volume;
164 stargo 509 int fd_mix = -1;
165 stargo 491
166 astrand 499 volume = left / (65536 / 100);
167     volume |= right / (65536 / 100) << 8;
168 stargo 509
169     if (use_dev_mixer)
170     {
171 astrand 532 if ((fd_mix = open("/dev/mixer", O_RDWR | O_NONBLOCK)) == -1)
172 stargo 509 {
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 stargo 491 if (ioctl(g_dsp_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
187     {
188     perror("MIXER_WRITE(SOUND_MIXER_PCM)");
189 stargo 509 use_dev_mixer = True;
190 stargo 491 return;
191     }
192     }
193    
194     void
195 matthewc 475 wave_out_play(void)
196     {
197     struct audio_packet *packet;
198     ssize_t len;
199     STREAM out;
200 stargo 510 static long startedat_us;
201     static long startedat_s;
202     static BOOL started = False;
203     struct timeval tv;
204 matthewc 475
205 stargo 1254 if (rdpsnd_queue_empty())
206 matthewc 475 {
207 stargo 1247 g_dsp_busy = 0;
208     return;
209     }
210 matthewc 475
211 stargo 1254 packet = rdpsnd_queue_current_packet();
212 stargo 1247 out = &packet->s;
213 matthewc 475
214 stargo 1247 if (!started)
215     {
216     gettimeofday(&tv, NULL);
217     startedat_us = tv.tv_usec;
218     startedat_s = tv.tv_sec;
219     started = True;
220     }
221 stargo 510
222 stargo 1247 len = out->end - out->p;
223 stargo 761
224 stargo 1247 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 stargo 761
233 stargo 1247 out->p += len;
234     if (out->p == out->end)
235     {
236     long long duration;
237     long elapsed;
238 stargo 761
239 stargo 1247 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 stargo 761
243 stargo 1247 if (elapsed >= (duration * 85) / 100)
244 matthewc 475 {
245 stargo 1254 /* 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 stargo 1247 started = False;
250     }
251     else
252     {
253 matthewc 475 g_dsp_busy = 1;
254     return;
255     }
256     }
257 stargo 1247 g_dsp_busy = 1;
258     return;
259 matthewc 475 }

  ViewVC Help
Powered by ViewVC 1.1.26