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.5 by cebix, 2000-07-13T13:47:06Z vs.
Revision 1.8 by cebix, 2001-07-05T21:24:45Z

# 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-2000 Christian Bauer
4 > *  Basilisk II (C) 1997-2001 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 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, &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   #ifdef ENABLE_ESD
173 <        printf("Using ESD audio output\n");
143 <
144 <        // ESD audio format
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;
175 #else
176        ErrorAlert("Basilisk II has been compiled with ESD support disabled.");
177        return false;
234   #endif
235   }
236  
237 < void AudioInit(void)
237 > static bool open_audio(void)
238   {
239 <        char str[256];
240 <
241 <        // Init audio status (defaults) and feature flags
242 <        set_audio_status_format();
243 <        AudioStatus.mixer = 0;
244 <        AudioStatus.num_sources = 0;
189 <        audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut;
190 <
191 <        // Sound disabled in prefs? Then do nothing
192 <        if (PrefsFindBool("nosound"))
193 <                return;
239 > #ifdef ENABLE_ESD
240 >        // If ESPEAKER is set, the user probably wants to use ESD, so try that first
241 >        if (getenv("ESPEAKER"))
242 >                if (open_esd())
243 >                        goto dev_opened;
244 > #endif
245  
246          // Try to open /dev/dsp
247 <        audio_fd = open(DSP_NAME, O_WRONLY);
248 <        if (audio_fd < 0) {
247 >        if (open_dsp())
248 >                goto dev_opened;
249 >
250   #ifdef ENABLE_ESD
251 <                if (!audio_init_esd())
252 <                        return;
253 < #else
254 <                sprintf(str, GetString(STR_NO_AUDIO_DEV_WARN), DSP_NAME, strerror(errno));
203 <                WarningAlert(str);
204 <                return;
251 >        // Hm, /dev/dsp failed so we try ESD again if ESPEAKER wasn't set
252 >        if (!getenv("ESPEAKER"))
253 >                if (open_esd())
254 >                        goto dev_opened;
255   #endif
206        } else
207                if (!audio_init_dsp())
208                        return;
256  
257 <        // Try to open /dev/mixer
258 <        mixer_fd = open("/dev/mixer", O_RDWR);
259 <        if (mixer_fd < 0)
213 <                printf("WARNING: Cannot open /dev/mixer (%s)", strerror(errno));
257 >        // No audio device succeeded
258 >        WarningAlert(GetString(STR_NO_AUDIO_WARN));
259 >        return false;
260  
261 <        // Init semaphore
262 <        if (sem_init(&audio_irq_done_sem, 0, 0) < 0)
263 <                return;
264 <        sem_inited = true;
261 >        // Device opened, set AudioStatus
262 > dev_opened:
263 >        sound_buffer_size = (audio_sample_sizes[audio_sample_size_index] >> 3) * audio_channel_counts[audio_channel_count_index] * audio_frames_per_block;
264 >        set_audio_status_format();
265  
266          // Start streaming thread
267          pthread_attr_init(&stream_thread_attr);
# Line 228 | Line 274 | void AudioInit(void)
274                  pthread_attr_setschedparam(&stream_thread_attr, &fifo_param);
275          }
276   #endif
277 +        stream_thread_cancel = false;
278          stream_thread_active = (pthread_create(&stream_thread, &stream_thread_attr, stream_func, NULL) == 0);
279  
280 <        // Everything OK
280 >        // Everything went fine
281          audio_open = true;
282 +        return true;
283 + }
284 +
285 + void AudioInit(void)
286 + {
287 +        char str[256];
288 +
289 +        // Init audio status (reasonable defaults) and feature flags
290 +        AudioStatus.sample_rate = 44100 << 16;
291 +        AudioStatus.sample_size = 16;
292 +        AudioStatus.channels = 2;
293 +        AudioStatus.mixer = 0;
294 +        AudioStatus.num_sources = 0;
295 +        audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut;
296 +
297 +        // Sound disabled in prefs? Then do nothing
298 +        if (PrefsFindBool("nosound"))
299 +                return;
300 +
301 +        // Init semaphore
302 +        if (sem_init(&audio_irq_done_sem, 0, 0) < 0)
303 +                return;
304 +        sem_inited = true;
305 +
306 +        // Try to open /dev/mixer
307 +        mixer_fd = open("/dev/mixer", O_RDWR);
308 +        if (mixer_fd < 0)
309 +                printf("WARNING: Cannot open /dev/mixer (%s)", strerror(errno));
310 +
311 +        // Open and initialize audio device
312 +        open_audio();
313   }
314  
315  
# Line 239 | Line 317 | void AudioInit(void)
317   *  Deinitialization
318   */
319  
320 < void AudioExit(void)
320 > static void close_audio(void)
321   {
322          // Stop stream and delete semaphore
323          if (stream_thread_active) {
# Line 250 | Line 328 | void AudioExit(void)
328                  pthread_join(stream_thread, NULL);
329                  stream_thread_active = false;
330          }
253        if (sem_inited)
254                sem_destroy(&audio_irq_done_sem);
331  
332 <        // Close /dev/dsp
333 <        if (audio_fd > 0)
332 >        // Close /dev/dsp or ESD socket
333 >        if (audio_fd >= 0) {
334                  close(audio_fd);
335 +                audio_fd = -1;
336 +        }
337 +
338 +        audio_open = false;
339 + }
340 +
341 + void AudioExit(void)
342 + {
343 +        if (sem_inited) {
344 +                sem_destroy(&audio_irq_done_sem);
345 +                sem_inited = false;
346 +        }
347  
348          // Close /dev/mixer
349 <        if (mixer_fd > 0)
349 >        if (mixer_fd >= 0) {
350                  close(mixer_fd);
351 +                mixer_fd = -1;
352 +        }
353   }
354  
355  
# Line 372 | Line 462 | void AudioInterrupt(void)
462  
463   /*
464   *  Set sampling parameters
465 < *  "index" is an index into the audio_sample_rates[] etc. arrays
465 > *  "index" is an index into the audio_sample_rates[] etc. vectors
466   *  It is guaranteed that AudioStatus.num_sources == 0
467   */
468  
469 < void audio_set_sample_rate(int index)
469 > bool audio_set_sample_rate(int index)
470   {
471 +        close_audio();
472 +        audio_sample_rate_index = index;
473 +        return open_audio();
474   }
475  
476 < void audio_set_sample_size(int index)
476 > bool audio_set_sample_size(int index)
477   {
478 +        close_audio();
479 +        audio_sample_size_index = index;
480 +        return open_audio();
481   }
482  
483 < void audio_set_channels(int index)
483 > bool audio_set_channels(int index)
484   {
485 +        close_audio();
486 +        audio_channel_count_index = index;
487 +        return open_audio();
488   }
489  
490  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines