34 |
|
|
35 |
#define DEFAULTDEVICE "/dev/audio" |
#define DEFAULTDEVICE "/dev/audio" |
36 |
|
|
37 |
|
static int dsp_fd = -1; |
38 |
|
static BOOL dsp_busy; |
39 |
|
|
40 |
static BOOL g_reopened; |
static BOOL g_reopened; |
41 |
static short g_samplewidth; |
static short g_samplewidth; |
42 |
static char *dsp_dev; |
static char *dsp_dev; |
43 |
|
|
44 |
|
void sun_play(void); |
45 |
|
|
46 |
|
void |
47 |
|
sun_add_fds(int *n, fd_set * rfds, fd_set * wfds, struct timeval *tv) |
48 |
|
{ |
49 |
|
if (dsp_fd == -1) |
50 |
|
return; |
51 |
|
|
52 |
|
if (rdpsnd_queue_empty()) |
53 |
|
return; |
54 |
|
|
55 |
|
FD_SET(dsp_fd, wfds); |
56 |
|
if (dsp_fd > *n) |
57 |
|
*n = dsp_fd; |
58 |
|
} |
59 |
|
|
60 |
|
void |
61 |
|
sun_check_fds(fd_set * rfds, fd_set * wfds) |
62 |
|
{ |
63 |
|
if (FD_ISSET(dsp_fd, wfds)) |
64 |
|
sun_play(); |
65 |
|
} |
66 |
|
|
67 |
BOOL |
BOOL |
68 |
sun_open(void) |
sun_open(void) |
69 |
{ |
{ |
70 |
if ((g_dsp_fd = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1) |
if ((dsp_fd = open(dsp_dev, O_WRONLY | O_NONBLOCK)) == -1) |
71 |
{ |
{ |
72 |
perror(dsp_dev); |
perror(dsp_dev); |
73 |
return False; |
return False; |
74 |
} |
} |
75 |
|
|
76 |
/* Non-blocking so that user interface is responsive */ |
/* Non-blocking so that user interface is responsive */ |
77 |
fcntl(g_dsp_fd, F_SETFL, fcntl(g_dsp_fd, F_GETFL) | O_NONBLOCK); |
fcntl(dsp_fd, F_SETFL, fcntl(dsp_fd, F_GETFL) | O_NONBLOCK); |
78 |
|
|
79 |
g_reopened = True; |
g_reopened = True; |
80 |
|
|
86 |
{ |
{ |
87 |
/* Ack all remaining packets */ |
/* Ack all remaining packets */ |
88 |
while (!rdpsnd_queue_empty()) |
while (!rdpsnd_queue_empty()) |
89 |
{ |
rdpsnd_queue_next(0); |
|
rdpsnd_send_completion(rdpsnd_queue_current_packet()->tick, |
|
|
rdpsnd_queue_current_packet()->index); |
|
|
rdpsnd_queue_next(); |
|
|
} |
|
90 |
|
|
91 |
#if defined I_FLUSH && defined FLUSHW |
#if defined I_FLUSH && defined FLUSHW |
92 |
/* Flush the audiobuffer */ |
/* Flush the audiobuffer */ |
93 |
ioctl(g_dsp_fd, I_FLUSH, FLUSHW); |
ioctl(dsp_fd, I_FLUSH, FLUSHW); |
94 |
#endif |
#endif |
95 |
#if defined AUDIO_FLUSH |
#if defined AUDIO_FLUSH |
96 |
ioctl(g_dsp_fd, AUDIO_FLUSH, NULL); |
ioctl(dsp_fd, AUDIO_FLUSH, NULL); |
97 |
#endif |
#endif |
98 |
close(g_dsp_fd); |
close(dsp_fd); |
99 |
|
dsp_fd = -1; |
100 |
} |
} |
101 |
|
|
102 |
BOOL |
BOOL |
117 |
{ |
{ |
118 |
audio_info_t info; |
audio_info_t info; |
119 |
|
|
120 |
ioctl(g_dsp_fd, AUDIO_DRAIN, 0); |
ioctl(dsp_fd, AUDIO_DRAIN, 0); |
121 |
AUDIO_INITINFO(&info); |
AUDIO_INITINFO(&info); |
122 |
|
|
123 |
|
|
149 |
info.play.error = 0; |
info.play.error = 0; |
150 |
g_reopened = True; |
g_reopened = True; |
151 |
|
|
152 |
if (ioctl(g_dsp_fd, AUDIO_SETINFO, &info) == -1) |
if (ioctl(dsp_fd, AUDIO_SETINFO, &info) == -1) |
153 |
{ |
{ |
154 |
perror("AUDIO_SETINFO"); |
perror("AUDIO_SETINFO"); |
155 |
close(g_dsp_fd); |
sun_close(); |
156 |
return False; |
return False; |
157 |
} |
} |
158 |
|
|
184 |
info.play.gain = volume / (65536 / AUDIO_MAX_GAIN); |
info.play.gain = volume / (65536 / AUDIO_MAX_GAIN); |
185 |
info.play.balance = balance; |
info.play.balance = balance; |
186 |
|
|
187 |
if (ioctl(g_dsp_fd, AUDIO_SETINFO, &info) == -1) |
if (ioctl(dsp_fd, AUDIO_SETINFO, &info) == -1) |
188 |
{ |
{ |
189 |
perror("AUDIO_SETINFO"); |
perror("AUDIO_SETINFO"); |
190 |
return; |
return; |
214 |
} |
} |
215 |
|
|
216 |
if (rdpsnd_queue_empty()) |
if (rdpsnd_queue_empty()) |
|
{ |
|
|
g_dsp_busy = 0; |
|
217 |
return; |
return; |
|
} |
|
218 |
|
|
219 |
packet = rdpsnd_queue_current_packet(); |
packet = rdpsnd_queue_current_packet(); |
220 |
out = &packet->s; |
out = &packet->s; |
229 |
|
|
230 |
if (out->end != out->p) |
if (out->end != out->p) |
231 |
{ |
{ |
232 |
len = write(g_dsp_fd, out->p, out->end - out->p); |
len = write(dsp_fd, out->p, out->end - out->p); |
233 |
if (len == -1) |
if (len == -1) |
234 |
{ |
{ |
235 |
if (errno != EWOULDBLOCK) |
if (errno != EWOULDBLOCK) |
236 |
perror("write audio"); |
perror("write audio"); |
|
g_dsp_busy = 1; |
|
237 |
return; |
return; |
238 |
} |
} |
239 |
} |
} |
241 |
out->p += len; |
out->p += len; |
242 |
if (out->p == out->end) |
if (out->p == out->end) |
243 |
{ |
{ |
244 |
if (ioctl(g_dsp_fd, AUDIO_GETINFO, &info) == -1) |
if (ioctl(dsp_fd, AUDIO_GETINFO, &info) == -1) |
245 |
{ |
{ |
246 |
perror("AUDIO_GETINFO"); |
perror("AUDIO_GETINFO"); |
247 |
return; |
return; |
258 |
} |
} |
259 |
else |
else |
260 |
{ |
{ |
|
g_dsp_busy = 1; |
|
261 |
return; |
return; |
262 |
} |
} |
263 |
} |
} |
264 |
} |
} |
265 |
} |
} |
266 |
|
|
267 |
|
static struct audio_driver sun_driver = { |
268 |
|
.name = "sun", |
269 |
|
.description = "SUN/BSD output driver, default device: " DEFAULTDEVICE " or $AUDIODEV", |
270 |
|
|
271 |
|
.add_fds = sun_add_fds, |
272 |
|
.check_fds = sun_check_fds, |
273 |
|
|
274 |
|
.wave_out_open = sun_open, |
275 |
|
.wave_out_close = sun_close, |
276 |
|
.wave_out_format_supported = sun_format_supported, |
277 |
|
.wave_out_set_format = sun_set_format, |
278 |
|
.wave_out_volume = sun_volume, |
279 |
|
|
280 |
|
.need_byteswap_on_be = 1, |
281 |
|
.need_resampling = 0, |
282 |
|
}; |
283 |
|
|
284 |
struct audio_driver * |
struct audio_driver * |
285 |
sun_register(char *options) |
sun_register(char *options) |
286 |
{ |
{ |
|
static struct audio_driver sun_driver; |
|
|
|
|
|
sun_driver.wave_out_open = sun_open; |
|
|
sun_driver.wave_out_close = sun_close; |
|
|
sun_driver.wave_out_format_supported = sun_format_supported; |
|
|
sun_driver.wave_out_set_format = sun_set_format; |
|
|
sun_driver.wave_out_volume = sun_volume; |
|
|
sun_driver.wave_out_play = sun_play; |
|
|
sun_driver.name = xstrdup("sun"); |
|
|
sun_driver.description = |
|
|
xstrdup("SUN/BSD output driver, default device: " DEFAULTDEVICE " or $AUDIODEV"); |
|
|
sun_driver.need_byteswap_on_be = 1; |
|
|
sun_driver.need_resampling = 0; |
|
|
sun_driver.next = NULL; |
|
|
|
|
287 |
if (options) |
if (options) |
288 |
{ |
{ |
289 |
dsp_dev = xstrdup(options); |
dsp_dev = xstrdup(options); |