/[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 509 - (show annotations)
Wed Oct 22 12:16:03 2003 UTC (20 years, 7 months ago) by stargo
File MIME type: text/plain
File size: 4288 byte(s)
Mixer fallback for broken sound-drivers

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/ioctl.h>
27 #include <sys/soundcard.h>
28
29 #define MAX_QUEUE 10
30
31 int g_dsp_fd;
32 BOOL g_dsp_busy = False;
33
34 static struct audio_packet
35 {
36 struct stream s;
37 uint16 tick;
38 uint8 index;
39 } packet_queue[MAX_QUEUE];
40 static unsigned int queue_hi, queue_lo;
41
42 BOOL
43 wave_out_open(void)
44 {
45 char *dsp_dev = "/dev/dsp";
46
47 if ((g_dsp_fd = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1)
48 {
49 perror(dsp_dev);
50 return False;
51 }
52
53 /* Non-blocking so that user interface is responsive */
54 fcntl(g_dsp_fd, F_SETFL, fcntl(g_dsp_fd, F_GETFL) | O_NONBLOCK);
55 return True;
56 }
57
58 void
59 wave_out_close(void)
60 {
61 close(g_dsp_fd);
62 }
63
64 BOOL
65 wave_out_format_supported(WAVEFORMATEX * pwfx)
66 {
67 if (pwfx->wFormatTag != WAVE_FORMAT_PCM)
68 return False;
69 if ((pwfx->nChannels != 1) && (pwfx->nChannels != 2))
70 return False;
71 if ((pwfx->wBitsPerSample != 8) && (pwfx->wBitsPerSample != 16))
72 return False;
73
74 return True;
75 }
76
77 BOOL
78 wave_out_set_format(WAVEFORMATEX * pwfx)
79 {
80 int speed, channels, format;
81
82 ioctl(g_dsp_fd, SNDCTL_DSP_RESET, NULL);
83 ioctl(g_dsp_fd, SNDCTL_DSP_SYNC, NULL);
84
85 if (pwfx->wBitsPerSample == 8)
86 format = AFMT_U8;
87 else if (pwfx->wBitsPerSample == 16)
88 format = AFMT_S16_LE;
89
90 if (ioctl(g_dsp_fd, SNDCTL_DSP_SETFMT, &format) == -1)
91 {
92 perror("SNDCTL_DSP_SETFMT");
93 close(g_dsp_fd);
94 return False;
95 }
96
97 channels = pwfx->nChannels;
98 if (ioctl(g_dsp_fd, SNDCTL_DSP_CHANNELS, &channels) == -1)
99 {
100 perror("SNDCTL_DSP_CHANNELS");
101 close(g_dsp_fd);
102 return False;
103 }
104
105 speed = pwfx->nSamplesPerSec;
106 if (ioctl(g_dsp_fd, SNDCTL_DSP_SPEED, &speed) == -1)
107 {
108 perror("SNDCTL_DSP_SPEED");
109 close(g_dsp_fd);
110 return False;
111 }
112
113 return True;
114 }
115
116 void
117 wave_out_volume(uint16 left, uint16 right)
118 {
119 static BOOL use_dev_mixer = False;
120 uint32 volume;
121 int fd_mix = -1;
122
123 volume = left / (65536 / 100);
124 volume |= right / (65536 / 100) << 8;
125
126 if (use_dev_mixer)
127 {
128 if ((fd_mix = open( "/dev/mixer", O_RDWR|O_NONBLOCK )) == -1 )
129 {
130 perror("open /dev/mixer");
131 return;
132 }
133
134 if (ioctl(fd_mix, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
135 {
136 perror("MIXER_WRITE(SOUND_MIXER_PCM)");
137 return;
138 }
139
140 close(fd_mix);
141 }
142
143 if (ioctl(g_dsp_fd, MIXER_WRITE(SOUND_MIXER_PCM), &volume) == -1)
144 {
145 perror("MIXER_WRITE(SOUND_MIXER_PCM)");
146 use_dev_mixer = True;
147 return;
148 }
149 }
150
151 void
152 wave_out_write(STREAM s, uint16 tick, uint8 index)
153 {
154 struct audio_packet *packet = &packet_queue[queue_hi];
155 unsigned int next_hi = (queue_hi + 1) % MAX_QUEUE;
156
157 if (next_hi == queue_lo)
158 {
159 error("No space to queue audio packet\n");
160 return;
161 }
162
163 queue_hi = next_hi;
164
165 packet->s = *s;
166 packet->tick = tick;
167 packet->index = index;
168 packet->s.p += 4;
169
170 /* we steal the data buffer from s, give it a new one */
171 s->data = malloc(s->size);
172
173 if (!g_dsp_busy)
174 wave_out_play();
175 }
176
177 void
178 wave_out_play(void)
179 {
180 struct audio_packet *packet;
181 ssize_t len;
182 STREAM out;
183
184 while (1)
185 {
186 if (queue_lo == queue_hi)
187 {
188 g_dsp_busy = 0;
189 return;
190 }
191
192 packet = &packet_queue[queue_lo];
193 out = &packet->s;
194
195 len = write(g_dsp_fd, out->p, out->end - out->p);
196 if (len == -1)
197 {
198 if (errno != EWOULDBLOCK)
199 perror("write audio");
200 g_dsp_busy = 1;
201 return;
202 }
203
204 out->p += len;
205 if (out->p == out->end)
206 {
207 rdpsnd_send_completion(packet->tick, packet->index);
208 free(out->data);
209 queue_lo = (queue_lo + 1) % MAX_QUEUE;
210 }
211 }
212
213 }

  ViewVC Help
Powered by ViewVC 1.1.26