1 |
|
/* |
2 |
|
* audio_oss_esd.cpp - Audio support, implementation for OSS and ESD (Linux and FreeBSD) |
3 |
|
* |
4 |
< |
* Basilisk II (C) 1997-2001 Christian Bauer |
4 |
> |
* Basilisk II (C) 1997-2002 Christian Bauer |
5 |
|
* |
6 |
|
* This program is free software; you can redistribute it and/or modify |
7 |
|
* it under the terms of the GNU General Public License as published by |
54 |
|
static int audio_sample_size_index = 0; |
55 |
|
static int audio_channel_count_index = 0; |
56 |
|
|
57 |
– |
// Constants |
58 |
– |
#define DSP_NAME "/dev/dsp" |
59 |
– |
|
57 |
|
// Global variables |
58 |
< |
static int audio_fd = -1; // fd of /dev/dsp or ESD |
59 |
< |
static int mixer_fd = -1; // fd of /dev/mixer |
58 |
> |
static bool is_dsp_audio = false; // Flag: is DSP audio |
59 |
> |
static int audio_fd = -1; // fd of dsp or ESD |
60 |
> |
static int mixer_fd = -1; // fd of mixer |
61 |
|
static sem_t audio_irq_done_sem; // Signal from interrupt to streaming thread: data block read |
62 |
|
static bool sem_inited = false; // Flag: audio_irq_done_sem initialized |
63 |
|
static int sound_buffer_size; // Size of sound buffer in bytes |
84 |
|
AudioStatus.channels = audio_channel_counts[audio_channel_count_index]; |
85 |
|
} |
86 |
|
|
87 |
< |
// Init using /dev/dsp, returns false on error |
87 |
> |
// Init using the dsp device, returns false on error |
88 |
|
static bool open_dsp(void) |
89 |
|
{ |
90 |
< |
// Open /dev/dsp |
91 |
< |
audio_fd = open(DSP_NAME, O_WRONLY); |
90 |
> |
// Open the device |
91 |
> |
const char *dsp = PrefsFindString("dsp"); |
92 |
> |
audio_fd = open(dsp, O_WRONLY); |
93 |
|
if (audio_fd < 0) { |
94 |
< |
fprintf(stderr, "WARNING: Cannot open %s (%s)\n", DSP_NAME, strerror(errno)); |
94 |
> |
fprintf(stderr, "WARNING: Cannot open %s (%s)\n", dsp, strerror(errno)); |
95 |
|
return false; |
96 |
|
} |
97 |
|
|
98 |
< |
printf("Using " DSP_NAME " audio output\n"); |
98 |
> |
printf("Using %s audio output\n", dsp); |
99 |
> |
is_dsp_audio = true; |
100 |
|
|
101 |
|
// Get supported sample formats |
102 |
|
if (audio_sample_sizes.empty()) { |
213 |
|
|
214 |
|
// The reason we do this here is that we don't want to add sample |
215 |
|
// rates etc. unless the ESD server connection could be opened |
216 |
< |
// (if ESD fails, /dev/dsp might be tried next) |
216 |
> |
// (if ESD fails, dsp might be tried next) |
217 |
|
audio_sample_rates.push_back(11025 << 16); |
218 |
|
audio_sample_rates.push_back(22050 << 16); |
219 |
|
audio_sample_rates.push_back(44100 << 16); |
246 |
|
goto dev_opened; |
247 |
|
#endif |
248 |
|
|
249 |
< |
// Try to open /dev/dsp |
249 |
> |
// Try to open dsp |
250 |
|
if (open_dsp()) |
251 |
|
goto dev_opened; |
252 |
|
|
253 |
|
#ifdef ENABLE_ESD |
254 |
< |
// Hm, /dev/dsp failed so we try ESD again if ESPEAKER wasn't set |
254 |
> |
// Hm, dsp failed so we try ESD again if ESPEAKER wasn't set |
255 |
|
if (!getenv("ESPEAKER")) |
256 |
|
if (open_esd()) |
257 |
|
goto dev_opened; |
267 |
|
set_audio_status_format(); |
268 |
|
|
269 |
|
// Start streaming thread |
270 |
< |
pthread_attr_init(&stream_thread_attr); |
271 |
< |
#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) |
272 |
< |
if (geteuid() == 0) { |
273 |
< |
pthread_attr_setinheritsched(&stream_thread_attr, PTHREAD_EXPLICIT_SCHED); |
274 |
< |
pthread_attr_setschedpolicy(&stream_thread_attr, SCHED_FIFO); |
275 |
< |
struct sched_param fifo_param; |
276 |
< |
fifo_param.sched_priority = (sched_get_priority_min(SCHED_FIFO) + sched_get_priority_max(SCHED_FIFO)) / 2; |
277 |
< |
pthread_attr_setschedparam(&stream_thread_attr, &fifo_param); |
278 |
< |
} |
279 |
< |
#endif |
280 |
< |
stream_thread_cancel = false; |
270 |
> |
Set_pthread_attr(&stream_thread_attr, 0); |
271 |
|
stream_thread_active = (pthread_create(&stream_thread, &stream_thread_attr, stream_func, NULL) == 0); |
272 |
|
|
273 |
|
// Everything went fine |
294 |
|
return; |
295 |
|
sem_inited = true; |
296 |
|
|
297 |
< |
// Try to open /dev/mixer |
298 |
< |
mixer_fd = open("/dev/mixer", O_RDWR); |
297 |
> |
// Try to open the mixer device |
298 |
> |
const char *mixer = PrefsFindString("mixer"); |
299 |
> |
mixer_fd = open(mixer, O_RDWR); |
300 |
|
if (mixer_fd < 0) |
301 |
< |
printf("WARNING: Cannot open /dev/mixer (%s)", strerror(errno)); |
301 |
> |
printf("WARNING: Cannot open %s (%s)\n", mixer, strerror(errno)); |
302 |
|
|
303 |
|
// Open and initialize audio device |
304 |
|
open_audio(); |
321 |
|
stream_thread_active = false; |
322 |
|
} |
323 |
|
|
324 |
< |
// Close /dev/dsp or ESD socket |
324 |
> |
// Close dsp or ESD socket |
325 |
|
if (audio_fd >= 0) { |
326 |
|
close(audio_fd); |
327 |
|
audio_fd = -1; |
332 |
|
|
333 |
|
void AudioExit(void) |
334 |
|
{ |
335 |
+ |
// Stop the device immediately. Otherwise, close() sends |
336 |
+ |
// SNDCTL_DSP_SYNC, which may hang |
337 |
+ |
if (is_dsp_audio) |
338 |
+ |
ioctl(audio_fd, SNDCTL_DSP_RESET, 0); |
339 |
+ |
|
340 |
|
// Close audio device |
341 |
|
close_audio(); |
342 |
|
|
346 |
|
sem_inited = false; |
347 |
|
} |
348 |
|
|
349 |
< |
// Close /dev/mixer |
349 |
> |
// Close mixer device |
350 |
|
if (mixer_fd >= 0) { |
351 |
|
close(mixer_fd); |
352 |
|
mixer_fd = -1; |