3 |
Sound Channel Process Functions - Open Sound System |
Sound Channel Process Functions - Open Sound System |
4 |
Copyright (C) Matthew Chapman 2003 |
Copyright (C) Matthew Chapman 2003 |
5 |
Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003 |
Copyright (C) GuoJunBo guojunbo@ict.ac.cn 2003 |
6 |
|
Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB |
7 |
|
|
8 |
This program is free software; you can redistribute it and/or modify |
This program is free software; you can redistribute it and/or modify |
9 |
it under the terms of the GNU General Public License as published by |
it under the terms of the GNU General Public License as published by |
45 |
#define MAX_LEN 512 |
#define MAX_LEN 512 |
46 |
|
|
47 |
static int dsp_fd = -1; |
static int dsp_fd = -1; |
48 |
static BOOL dsp_busy; |
static int dsp_mode; |
49 |
|
static int dsp_refs; |
50 |
|
|
51 |
|
static BOOL dsp_configured; |
52 |
|
|
53 |
|
static BOOL dsp_out; |
54 |
|
static BOOL dsp_in; |
55 |
|
|
56 |
|
static int stereo; |
57 |
|
static int format; |
58 |
static int snd_rate; |
static int snd_rate; |
59 |
static short samplewidth; |
static short samplewidth; |
60 |
static char *dsp_dev; |
static char *dsp_dev; |
64 |
static struct audio_driver oss_driver; |
static struct audio_driver oss_driver; |
65 |
|
|
66 |
void oss_play(void); |
void oss_play(void); |
67 |
|
void oss_record(void); |
68 |
|
|
69 |
void |
void |
70 |
oss_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv) |
oss_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv) |
72 |
if (dsp_fd == -1) |
if (dsp_fd == -1) |
73 |
return; |
return; |
74 |
|
|
75 |
if (rdpsnd_queue_empty()) |
if (dsp_out && !rdpsnd_queue_empty()) |
76 |
return; |
FD_SET(dsp_fd, wfds); |
77 |
|
if (dsp_in) |
78 |
FD_SET(dsp_fd, wfds); |
FD_SET(dsp_fd, rfds); |
79 |
if (dsp_fd > *n) |
if (dsp_fd > *n) |
80 |
*n = dsp_fd; |
*n = dsp_fd; |
81 |
} |
} |
85 |
{ |
{ |
86 |
if (FD_ISSET(dsp_fd, wfds)) |
if (FD_ISSET(dsp_fd, wfds)) |
87 |
oss_play(); |
oss_play(); |
88 |
|
if (FD_ISSET(dsp_fd, rfds)) |
89 |
|
oss_record(); |
90 |
} |
} |
91 |
|
|
92 |
static BOOL |
static BOOL |
112 |
} |
} |
113 |
|
|
114 |
BOOL |
BOOL |
115 |
oss_open(void) |
oss_open(int fallback) |
116 |
{ |
{ |
117 |
if ((dsp_fd = open(dsp_dev, O_WRONLY)) == -1) |
int caps; |
118 |
|
|
119 |
|
if (dsp_fd != -1) |
120 |
{ |
{ |
121 |
perror(dsp_dev); |
dsp_refs++; |
122 |
|
|
123 |
|
if (dsp_mode == O_RDWR) |
124 |
|
return True; |
125 |
|
|
126 |
|
if (dsp_mode == fallback) |
127 |
|
return True; |
128 |
|
|
129 |
|
dsp_refs--; |
130 |
return False; |
return False; |
131 |
} |
} |
132 |
|
|
133 |
|
dsp_configured = False; |
134 |
|
|
135 |
|
dsp_mode = O_RDWR; |
136 |
|
dsp_fd = open(dsp_dev, O_RDWR | O_NONBLOCK); |
137 |
|
if (dsp_fd != -1) |
138 |
|
{ |
139 |
|
ioctl(dsp_fd, SNDCTL_DSP_SETDUPLEX, 0); |
140 |
|
|
141 |
|
if ((ioctl(dsp_fd, SNDCTL_DSP_GETCAPS, &caps) < 0) || !(caps & DSP_CAP_DUPLEX)) |
142 |
|
{ |
143 |
|
close(dsp_fd); |
144 |
|
dsp_fd = -1; |
145 |
|
} |
146 |
|
} |
147 |
|
|
148 |
|
if (dsp_fd == -1) |
149 |
|
{ |
150 |
|
dsp_mode = fallback; |
151 |
|
|
152 |
|
dsp_fd = open(dsp_dev, dsp_mode | O_NONBLOCK); |
153 |
|
if (dsp_fd == -1) |
154 |
|
{ |
155 |
|
perror(dsp_dev); |
156 |
|
return False; |
157 |
|
} |
158 |
|
} |
159 |
|
|
160 |
|
dsp_refs++; |
161 |
|
|
162 |
in_esddsp = detect_esddsp(); |
in_esddsp = detect_esddsp(); |
163 |
|
|
164 |
return True; |
return True; |
167 |
void |
void |
168 |
oss_close(void) |
oss_close(void) |
169 |
{ |
{ |
170 |
|
dsp_refs--; |
171 |
|
|
172 |
|
if (dsp_refs != 0) |
173 |
|
return; |
174 |
|
|
175 |
close(dsp_fd); |
close(dsp_fd); |
176 |
dsp_fd = -1; |
dsp_fd = -1; |
177 |
dsp_busy = False; |
} |
178 |
|
|
179 |
|
BOOL |
180 |
|
oss_open_out(void) |
181 |
|
{ |
182 |
|
if (!oss_open(O_WRONLY)) |
183 |
|
return False; |
184 |
|
|
185 |
|
dsp_out = True; |
186 |
|
|
187 |
|
return True; |
188 |
|
} |
189 |
|
|
190 |
|
void |
191 |
|
oss_close_out(void) |
192 |
|
{ |
193 |
|
oss_close(); |
194 |
|
|
195 |
|
/* Ack all remaining packets */ |
196 |
|
while (!rdpsnd_queue_empty()) |
197 |
|
rdpsnd_queue_next(0); |
198 |
|
|
199 |
|
dsp_out = False; |
200 |
|
} |
201 |
|
|
202 |
|
BOOL |
203 |
|
oss_open_in(void) |
204 |
|
{ |
205 |
|
if (!oss_open(O_RDONLY)) |
206 |
|
return False; |
207 |
|
|
208 |
|
dsp_in = True; |
209 |
|
|
210 |
|
return True; |
211 |
|
} |
212 |
|
|
213 |
|
void |
214 |
|
oss_close_in(void) |
215 |
|
{ |
216 |
|
oss_close(); |
217 |
|
|
218 |
|
dsp_in = False; |
219 |
} |
} |
220 |
|
|
221 |
BOOL |
BOOL |
234 |
BOOL |
BOOL |
235 |
oss_set_format(WAVEFORMATEX * pwfx) |
oss_set_format(WAVEFORMATEX * pwfx) |
236 |
{ |
{ |
237 |
int stereo, format, fragments; |
int fragments; |
238 |
static BOOL driver_broken = False; |
static BOOL driver_broken = False; |
239 |
|
|
240 |
|
if (dsp_configured) |
241 |
|
{ |
242 |
|
if ((pwfx->wBitsPerSample == 8) && (format != AFMT_U8)) |
243 |
|
return False; |
244 |
|
if ((pwfx->wBitsPerSample == 16) && (format != AFMT_S16_LE)) |
245 |
|
return False; |
246 |
|
|
247 |
|
if ((pwfx->nChannels == 2) != !!stereo) |
248 |
|
return False; |
249 |
|
|
250 |
|
if (pwfx->nSamplesPerSec != snd_rate) |
251 |
|
return False; |
252 |
|
|
253 |
|
return True; |
254 |
|
} |
255 |
|
|
256 |
ioctl(dsp_fd, SNDCTL_DSP_RESET, NULL); |
ioctl(dsp_fd, SNDCTL_DSP_RESET, NULL); |
257 |
ioctl(dsp_fd, SNDCTL_DSP_SYNC, NULL); |
ioctl(dsp_fd, SNDCTL_DSP_SYNC, NULL); |
258 |
|
|
347 |
} |
} |
348 |
} |
} |
349 |
|
|
350 |
|
dsp_configured = True; |
351 |
|
|
352 |
return True; |
return True; |
353 |
} |
} |
354 |
|
|
431 |
} |
} |
432 |
} |
} |
433 |
|
|
434 |
|
void |
435 |
|
oss_record(void) |
436 |
|
{ |
437 |
|
char buffer[32768]; |
438 |
|
int len; |
439 |
|
|
440 |
|
len = read(dsp_fd, buffer, sizeof(buffer)); |
441 |
|
if (len == -1) |
442 |
|
{ |
443 |
|
if (errno != EWOULDBLOCK) |
444 |
|
perror("read audio"); |
445 |
|
return; |
446 |
|
} |
447 |
|
|
448 |
|
rdpsnd_record(buffer, len); |
449 |
|
} |
450 |
|
|
451 |
struct audio_driver * |
struct audio_driver * |
452 |
oss_register(char *options) |
oss_register(char *options) |
453 |
{ |
{ |
454 |
oss_driver.name = xstrdup("oss"); |
memset(&oss_driver, 0, sizeof(oss_driver)); |
455 |
|
|
456 |
|
oss_driver.name = "oss"; |
457 |
oss_driver.description = |
oss_driver.description = |
458 |
xstrdup("OSS output driver, default device: " DEFAULTDEVICE " or $AUDIODEV"); |
"OSS output driver, default device: " DEFAULTDEVICE " or $AUDIODEV"; |
459 |
|
|
460 |
oss_driver.add_fds = oss_add_fds; |
oss_driver.add_fds = oss_add_fds; |
461 |
oss_driver.check_fds = oss_check_fds; |
oss_driver.check_fds = oss_check_fds; |
462 |
|
|
463 |
oss_driver.wave_out_open = oss_open; |
oss_driver.wave_out_open = oss_open_out; |
464 |
oss_driver.wave_out_close = oss_close; |
oss_driver.wave_out_close = oss_close_out; |
465 |
oss_driver.wave_out_format_supported = oss_format_supported; |
oss_driver.wave_out_format_supported = oss_format_supported; |
466 |
oss_driver.wave_out_set_format = oss_set_format; |
oss_driver.wave_out_set_format = oss_set_format; |
467 |
oss_driver.wave_out_volume = oss_volume; |
oss_driver.wave_out_volume = oss_volume; |
468 |
|
|
469 |
|
oss_driver.wave_in_open = oss_open_in; |
470 |
|
oss_driver.wave_in_close = oss_close_in; |
471 |
|
oss_driver.wave_in_format_supported = oss_format_supported; |
472 |
|
oss_driver.wave_in_set_format = oss_set_format; |
473 |
|
oss_driver.wave_in_volume = NULL; /* FIXME */ |
474 |
|
|
475 |
oss_driver.need_byteswap_on_be = 0; |
oss_driver.need_byteswap_on_be = 0; |
476 |
oss_driver.need_resampling = 0; |
oss_driver.need_resampling = 0; |
477 |
|
|
485 |
|
|
486 |
if (dsp_dev == NULL) |
if (dsp_dev == NULL) |
487 |
{ |
{ |
488 |
dsp_dev = xstrdup(DEFAULTDEVICE); |
dsp_dev = DEFAULTDEVICE; |
489 |
} |
} |
490 |
} |
} |
491 |
|
|