ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/Unix/audio_oss_esd.cpp
(Generate patch)

Comparing BasiliskII/src/Unix/audio_oss_esd.cpp (file contents):
Revision 1.3 by cebix, 1999-11-03T10:56:22Z vs.
Revision 1.14 by gbeauche, 2002-10-03T15:47:59Z

# Line 1 | Line 1
1   /*
2   *  audio_oss_esd.cpp - Audio support, implementation for OSS and ESD (Linux and FreeBSD)
3   *
4 < *  Basilisk II (C) 1997-1999 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
# Line 31 | Line 31
31   #endif
32  
33   #ifdef __FreeBSD__
34 < #include <machine/soundcard.h>
34 > #include <sys/soundcard.h>
35   #endif
36  
37   #include "cpu_emulation.h"
# Line 41 | Line 41
41   #include "audio.h"
42   #include "audio_defs.h"
43  
44 < #if ENABLE_ESD
44 > #ifdef ENABLE_ESD
45   #include <esd.h>
46   #endif
47  
# Line 49 | Line 49
49   #include "debug.h"
50  
51  
52 < // Supported sample rates, sizes and channels (defaults)
53 < int audio_num_sample_rates = 1;
54 < uint32 audio_sample_rates[] = {44100 << 16};
55 < int audio_num_sample_sizes = 1;
56 < uint16 audio_sample_sizes[] = {16};
57 < int audio_num_channel_counts = 1;
58 < uint16 audio_channel_counts[] = {2};
52 > // The currently selected audio parameters (indices in audio_sample_rates[] etc. vectors)
53 > static int audio_sample_rate_index = 0;
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"
# Line 84 | Line 81 | static void *stream_func(void *arg);
81   // Set AudioStatus to reflect current audio stream format
82   static void set_audio_status_format(void)
83   {
84 <        AudioStatus.sample_rate = audio_sample_rates[0];
85 <        AudioStatus.sample_size = audio_sample_sizes[0];
86 <        AudioStatus.channels = audio_channel_counts[0];
84 >        AudioStatus.sample_rate = audio_sample_rates[audio_sample_rate_index];
85 >        AudioStatus.sample_size = audio_sample_sizes[audio_sample_size_index];
86 >        AudioStatus.channels = audio_channel_counts[audio_channel_count_index];
87   }
88  
89   // Init using /dev/dsp, returns false on error
90 < bool audio_init_dsp(void)
90 > static bool open_dsp(void)
91   {
92 +        // Open /dev/dsp
93 +        audio_fd = open(DSP_NAME, O_WRONLY);
94 +        if (audio_fd < 0) {
95 +                fprintf(stderr, "WARNING: Cannot open %s (%s)\n", DSP_NAME, strerror(errno));
96 +                return false;
97 +        }
98 +
99          printf("Using " DSP_NAME " audio output\n");
100  
101          // Get supported sample formats
102 <        unsigned long format;
103 <        ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &format);
104 <        if ((format & (AFMT_U8 | AFMT_S16_BE | AFMT_S16_LE)) == 0) {
105 <                WarningAlert(GetString(STR_AUDIO_FORMAT_WARN));
106 <                close(audio_fd);
107 <                audio_fd = -1;
108 <                return false;
109 <        }
110 <        if (format & (AFMT_S16_BE | AFMT_S16_LE)) {
111 <                audio_sample_sizes[0] = 16;
112 <                silence_byte = 0;
113 <        } else {
114 <                audio_sample_sizes[0] = 8;
115 <                silence_byte = 0x80;
102 >        if (audio_sample_sizes.empty()) {
103 >                unsigned long format;
104 >                ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &format);
105 >                if (format & AFMT_U8)
106 >                        audio_sample_sizes.push_back(8);
107 >                if (format & (AFMT_S16_BE | AFMT_S16_LE))
108 >                        audio_sample_sizes.push_back(16);
109 >
110 >                int stereo = 0;
111 >                if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo) == 0 && stereo == 0)
112 >                        audio_channel_counts.push_back(1);
113 >                stereo = 1;
114 >                if (ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo) == 0 && stereo == 1)
115 >                        audio_channel_counts.push_back(2);
116 >
117 >                if (audio_sample_sizes.empty() || audio_channel_counts.empty()) {
118 >                        WarningAlert(GetString(STR_AUDIO_FORMAT_WARN));
119 >                        close(audio_fd);
120 >                        audio_fd = -1;
121 >                        return false;
122 >                }
123 >
124 >                audio_sample_rates.push_back(11025 << 16);
125 >                audio_sample_rates.push_back(22050 << 16);
126 >                int rate = 44100;
127 >                ioctl(audio_fd, SNDCTL_DSP_SPEED, &rate);
128 >                if (rate > 22050)
129 >                        audio_sample_rates.push_back(rate << 16);
130 >
131 >                // Default to highest supported values
132 >                audio_sample_rate_index = audio_sample_rates.size() - 1;
133 >                audio_sample_size_index = audio_sample_sizes.size() - 1;
134 >                audio_channel_count_index = audio_channel_counts.size() - 1;
135          }
113        if (!(format & AFMT_S16_BE))
114                little_endian = true;
136  
137          // Set DSP parameters
138 <        format = audio_sample_sizes[0] == 8 ? AFMT_U8 : (little_endian ? AFMT_S16_LE : AFMT_S16_BE);
138 >        unsigned long format;
139 >        if (audio_sample_sizes[audio_sample_size_index] == 8) {
140 >                format = AFMT_U8;
141 >                little_endian = false;
142 >                silence_byte = 0x80;
143 >        } else {
144 >                unsigned long sup_format;
145 >                ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &sup_format);
146 >                if (sup_format & AFMT_S16_BE) {
147 >                        little_endian = false;
148 >                        format = AFMT_S16_BE;
149 >                } else {
150 >                        little_endian = true;
151 >                        format = AFMT_S16_LE;
152 >                }
153 >                silence_byte = 0;
154 >        }
155          ioctl(audio_fd, SNDCTL_DSP_SETFMT, &format);
156          int frag = 0x0004000c;          // Block size: 4096 frames
157          ioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &frag);
158 <        int stereo = (audio_channel_counts[0] == 2);
158 >        int stereo = (audio_channel_counts[audio_channel_count_index] == 2);
159          ioctl(audio_fd, SNDCTL_DSP_STEREO, &stereo);
160 <        int rate = audio_sample_rates[0] >> 16;
160 >        int rate = audio_sample_rates[audio_sample_rate_index] >> 16;
161          ioctl(audio_fd, SNDCTL_DSP_SPEED, &rate);
125        audio_sample_rates[0] = rate << 16;
126
127        // Set AudioStatus again because we now know more about the sound
128        // system's capabilities
129        set_audio_status_format();
162  
163          // Get sound buffer size
164          ioctl(audio_fd, SNDCTL_DSP_GETBLKSIZE, &audio_frames_per_block);
165          D(bug("DSP_GETBLKSIZE %d\n", audio_frames_per_block));
134        sound_buffer_size = (AudioStatus.sample_size >> 3) * AudioStatus.channels * audio_frames_per_block;
166          return true;
167   }
168  
169   // Init using ESD, returns false on error
170 < bool audio_init_esd(void)
170 > static bool open_esd(void)
171   {
172 < #if ENABLE_ESD
173 <        printf("Using ESD audio output\n");
143 <
144 <        // ESD audio format
172 > #ifdef ENABLE_ESD
173 >        int rate;
174          esd_format_t format = ESD_STREAM | ESD_PLAY;
175 <        if (AudioStatus.sample_size == 8)
176 <                format |= ESD_BITS8;
177 <        else
178 <                format |= ESD_BITS16;
179 <        if (AudioStatus.channels == 1)
180 <                format |= ESD_MONO;
181 <        else
182 <                format |= ESD_STEREO;
175 >
176 >        if (audio_sample_sizes.empty()) {
177 >
178 >                // Default values
179 >                rate = 44100;
180 >                format |= (ESD_BITS16 | ESD_STEREO);
181 >
182 >        } else {
183 >
184 >                rate = audio_sample_rates[audio_sample_rate_index] >> 16;
185 >                if (audio_sample_sizes[audio_sample_size_index] == 8)
186 >                        format |= ESD_BITS8;
187 >                else
188 >                        format |= ESD_BITS16;
189 >                if (audio_channel_counts[audio_channel_count_index] == 1)
190 >                        format |= ESD_MONO;
191 >                else
192 >                        format |= ESD_STEREO;
193 >        }
194  
195   #if WORDS_BIGENDIAN
196          little_endian = false;
# Line 160 | Line 200 | bool audio_init_esd(void)
200          silence_byte = 0;       // Is this correct for 8-bit mode?
201  
202          // Open connection to ESD server
203 <        audio_fd = esd_play_stream(format, AudioStatus.sample_rate >> 16, NULL, NULL);
203 >        audio_fd = esd_play_stream(format, rate, NULL, NULL);
204          if (audio_fd < 0) {
205 <                char str[256];
166 <                sprintf(str, GetString(STR_NO_ESD_WARN), strerror(errno));
167 <                WarningAlert(str);
205 >                fprintf(stderr, "WARNING: Cannot open ESD connection\n");
206                  return false;
207          }
208  
209 +        printf("Using ESD audio output\n");
210 +
211 +        // ESD supports a variety of twisted little audio formats, all different
212 +        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)
217 +                audio_sample_rates.push_back(11025 << 16);
218 +                audio_sample_rates.push_back(22050 << 16);
219 +                audio_sample_rates.push_back(44100 << 16);
220 +                audio_sample_sizes.push_back(8);
221 +                audio_sample_sizes.push_back(16);
222 +                audio_channel_counts.push_back(1);
223 +                audio_channel_counts.push_back(2);
224 +
225 +                // Default to highest supported values
226 +                audio_sample_rate_index = audio_sample_rates.size() - 1;
227 +                audio_sample_size_index = audio_sample_sizes.size() - 1;
228 +                audio_channel_count_index = audio_channel_counts.size() - 1;
229 +        }
230 +
231          // Sound buffer size = 4096 frames
232          audio_frames_per_block = 4096;
173        sound_buffer_size = (AudioStatus.sample_size >> 3) * AudioStatus.channels * audio_frames_per_block;
233          return true;
234   #else
235 <        ErrorAlert("Basilisk II has been compiled with ESD support disabled.");
235 >        // ESD is not enabled, shut up the compiler
236          return false;
237   #endif
238   }
239  
240 < void AudioInit(void)
240 > static bool open_audio(void)
241   {
242 <        char str[256];
242 > #ifdef ENABLE_ESD
243 >        // If ESPEAKER is set, the user probably wants to use ESD, so try that first
244 >        if (getenv("ESPEAKER"))
245 >                if (open_esd())
246 >                        goto dev_opened;
247 > #endif
248 >
249 >        // Try to open /dev/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
255 >        if (!getenv("ESPEAKER"))
256 >                if (open_esd())
257 >                        goto dev_opened;
258 > #endif
259 >
260 >        // No audio device succeeded
261 >        WarningAlert(GetString(STR_NO_AUDIO_WARN));
262 >        return false;
263  
264 <        // Init audio status (defaults) and feature flags
264 >        // Device opened, set AudioStatus
265 > dev_opened:
266 >        sound_buffer_size = (audio_sample_sizes[audio_sample_size_index] >> 3) * audio_channel_counts[audio_channel_count_index] * audio_frames_per_block;
267          set_audio_status_format();
268 +
269 +        // Start streaming thread
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
274 +        audio_open = true;
275 +        return true;
276 + }
277 +
278 + void AudioInit(void)
279 + {
280 +        // Init audio status (reasonable defaults) and feature flags
281 +        AudioStatus.sample_rate = 44100 << 16;
282 +        AudioStatus.sample_size = 16;
283 +        AudioStatus.channels = 2;
284          AudioStatus.mixer = 0;
285          AudioStatus.num_sources = 0;
286          audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut;
# Line 192 | Line 289 | void AudioInit(void)
289          if (PrefsFindBool("nosound"))
290                  return;
291  
292 <        // Try to open /dev/dsp
293 <        audio_fd = open(DSP_NAME, O_WRONLY);
197 <        if (audio_fd < 0) {
198 < #if ENABLE_ESD
199 <                if (!audio_init_esd())
200 <                        return;
201 < #else
202 <                sprintf(str, GetString(STR_NO_AUDIO_DEV_WARN), DSP_NAME, strerror(errno));
203 <                WarningAlert(str);
292 >        // Init semaphore
293 >        if (sem_init(&audio_irq_done_sem, 0, 0) < 0)
294                  return;
295 < #endif
206 <        } else
207 <                if (!audio_init_dsp())
208 <                        return;
295 >        sem_inited = true;
296  
297          // Try to open /dev/mixer
298          mixer_fd = open("/dev/mixer", O_RDWR);
299          if (mixer_fd < 0)
300                  printf("WARNING: Cannot open /dev/mixer (%s)", strerror(errno));
301  
302 <        // Init semaphore
303 <        if (sem_init(&audio_irq_done_sem, 0, 0) < 0)
217 <                return;
218 <        sem_inited = true;
219 <
220 <        // Start streaming thread
221 <        pthread_attr_init(&stream_thread_attr);
222 < #if defined(_POSIX_THREAD_PRIORITY_SCHEDULING)
223 <        if (geteuid() == 0) {
224 <                pthread_attr_setinheritsched(&stream_thread_attr, PTHREAD_EXPLICIT_SCHED);
225 <                pthread_attr_setschedpolicy(&stream_thread_attr, SCHED_FIFO);
226 <                struct sched_param fifo_param;
227 <                fifo_param.sched_priority = (sched_get_priority_min(SCHED_FIFO) + sched_get_priority_max(SCHED_FIFO)) / 2;
228 <                pthread_attr_setschedparam(&stream_thread_attr, &fifo_param);
229 <        }
230 < #endif
231 <        stream_thread_active = (pthread_create(&stream_thread, &stream_thread_attr, stream_func, NULL) == 0);
232 <
233 <        // Everything OK
234 <        audio_open = true;
302 >        // Open and initialize audio device
303 >        open_audio();
304   }
305  
306  
# Line 239 | Line 308 | void AudioInit(void)
308   *  Deinitialization
309   */
310  
311 < void AudioExit(void)
311 > static void close_audio(void)
312   {
313          // Stop stream and delete semaphore
314          if (stream_thread_active) {
# Line 250 | Line 319 | void AudioExit(void)
319                  pthread_join(stream_thread, NULL);
320                  stream_thread_active = false;
321          }
253        if (sem_inited)
254                sem_destroy(&audio_irq_done_sem);
322  
323 <        // Close /dev/dsp
324 <        if (audio_fd > 0)
323 >        // Close /dev/dsp or ESD socket
324 >        if (audio_fd >= 0) {
325                  close(audio_fd);
326 +                audio_fd = -1;
327 +        }
328 +
329 +        audio_open = false;
330 + }
331 +
332 + void AudioExit(void)
333 + {
334 +        // Close audio device
335 +        close_audio();
336 +
337 +        // Delete semaphore
338 +        if (sem_inited) {
339 +                sem_destroy(&audio_irq_done_sem);
340 +                sem_inited = false;
341 +        }
342  
343          // Close /dev/mixer
344 <        if (mixer_fd > 0)
344 >        if (mixer_fd >= 0) {
345                  close(mixer_fd);
346 +                mixer_fd = -1;
347 +        }
348   }
349  
350  
# Line 287 | Line 372 | void audio_exit_stream()
372   *  Streaming function
373   */
374  
290 static uint32 apple_stream_info;        // Mac address of SoundComponentData struct describing next buffer
291
375   static void *stream_func(void *arg)
376   {
377          int16 *silent_buffer = new int16[sound_buffer_size / 2];
# Line 372 | Line 455 | void AudioInterrupt(void)
455  
456   /*
457   *  Set sampling parameters
458 < *  "index" is an index into the audio_sample_rates[] etc. arrays
458 > *  "index" is an index into the audio_sample_rates[] etc. vectors
459   *  It is guaranteed that AudioStatus.num_sources == 0
460   */
461  
462 < void audio_set_sample_rate(int index)
462 > bool audio_set_sample_rate(int index)
463   {
464 +        close_audio();
465 +        audio_sample_rate_index = index;
466 +        return open_audio();
467   }
468  
469 < void audio_set_sample_size(int index)
469 > bool audio_set_sample_size(int index)
470   {
471 +        close_audio();
472 +        audio_sample_size_index = index;
473 +        return open_audio();
474   }
475  
476 < void audio_set_channels(int index)
476 > bool audio_set_channels(int index)
477   {
478 +        close_audio();
479 +        audio_channel_count_index = index;
480 +        return open_audio();
481   }
482  
483  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines