/[rdesktop]/jpeg/rdesktop/trunk/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 /jpeg/rdesktop/trunk/rdpsnd_oss.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 532 - (hide annotations)
Wed Oct 29 14:14:46 2003 UTC (20 years, 6 months ago) by astrand
Original Path: sourceforge.net/trunk/rdesktop/rdpsnd_oss.c
File MIME type: text/plain
File size: 5031 byte(s)
Indent fixes

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     char *dsp_dev = "/dev/dsp";
49    
50 astrand 499 if ((g_dsp_fd = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1)
51 matthewc 475 {
52     perror(dsp_dev);
53     return False;
54     }
55    
56     /* Non-blocking so that user interface is responsive */
57 astrand 499 fcntl(g_dsp_fd, F_SETFL, fcntl(g_dsp_fd, F_GETFL) | O_NONBLOCK);
58 matthewc 475 return True;
59     }
60    
61     void
62     wave_out_close(void)
63     {
64     close(g_dsp_fd);
65     }
66    
67     BOOL
68 astrand 499 wave_out_format_supported(WAVEFORMATEX * pwfx)
69 matthewc 475 {
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 astrand 499 wave_out_set_format(WAVEFORMATEX * pwfx)
82 matthewc 475 {
83 stargo 510 int channels, format;
84 matthewc 475
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 stargo 510 g_samplewidth = pwfx->wBitsPerSample / 8;
94    
95 matthewc 475 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 stargo 510 if (channels == 2)
111 matthewc 475 {
112 stargo 510 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 matthewc 475 perror("SNDCTL_DSP_SPEED");
119     close(g_dsp_fd);
120     return False;
121     }
122    
123     return True;
124     }
125    
126     void
127 stargo 491 wave_out_volume(uint16 left, uint16 right)
128     {
129 stargo 509 static BOOL use_dev_mixer = False;
130 stargo 491 uint32 volume;
131 stargo 509 int fd_mix = -1;
132 stargo 491
133 astrand 499 volume = left / (65536 / 100);
134     volume |= right / (65536 / 100) << 8;
135 stargo 509
136     if (use_dev_mixer)
137     {
138 astrand 532 if ((fd_mix = open("/dev/mixer", O_RDWR | O_NONBLOCK)) == -1)
139 stargo 509 {
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 stargo 491 if (ioctl(g_dsp_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
154     {
155     perror("MIXER_WRITE(SOUND_MIXER_PCM)");
156 stargo 509 use_dev_mixer = True;
157 stargo 491 return;
158     }
159     }
160    
161     void
162 matthewc 475 wave_out_write(STREAM s, uint16 tick, uint8 index)
163     {
164 matthewc 476 struct audio_packet *packet = &packet_queue[queue_hi];
165     unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
166 matthewc 475
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 stargo 491 packet->s.p += 4;
179 matthewc 475
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 stargo 510 static long startedat_us;
194     static long startedat_s;
195     static BOOL started = False;
196     struct timeval tv;
197 matthewc 475
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 stargo 510 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 astrand 499 len = write(g_dsp_fd, out->p, out->end - out->p);
218 matthewc 475 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 stargo 510 long long duration;
230     long elapsed;
231 astrand 532
232 stargo 510 gettimeofday(&tv, NULL);
233 astrand 532 duration = (out->size * (1000000 / (g_samplewidth * g_snd_rate)));
234     elapsed = (tv.tv_sec - startedat_s) * 1000000 + (tv.tv_usec - startedat_us);
235 stargo 510
236 astrand 532 if (elapsed >= (duration * 7) / 10)
237 stargo 510 {
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 matthewc 475 }
249     }
250     }

  ViewVC Help
Powered by ViewVC 1.1.26