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.11 by gbeauche, 2001-07-15T05:40:12Z

# 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, &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   #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;
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];
243 <
244 <        // Init audio status (defaults) and feature flags
245 <        set_audio_status_format();
246 <        AudioStatus.mixer = 0;
247 <        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;
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 <        audio_fd = open(DSP_NAME, O_WRONLY);
251 <        if (audio_fd < 0) {
250 >        if (open_dsp())
251 >                goto dev_opened;
252 >
253   #ifdef ENABLE_ESD
254 <                if (!audio_init_esd())
255 <                        return;
256 < #else
257 <                sprintf(str, GetString(STR_NO_AUDIO_DEV_WARN), DSP_NAME, strerror(errno));
203 <                WarningAlert(str);
204 <                return;
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
206        } else
207                if (!audio_init_dsp())
208                        return;
259  
260 <        // Try to open /dev/mixer
261 <        mixer_fd = open("/dev/mixer", O_RDWR);
262 <        if (mixer_fd < 0)
213 <                printf("WARNING: Cannot open /dev/mixer (%s)", strerror(errno));
260 >        // No audio device succeeded
261 >        WarningAlert(GetString(STR_NO_AUDIO_WARN));
262 >        return false;
263  
264 <        // Init semaphore
265 <        if (sem_init(&audio_irq_done_sem, 0, 0) < 0)
266 <                return;
267 <        sem_inited = true;
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          pthread_attr_init(&stream_thread_attr);
# Line 228 | Line 277 | void AudioInit(void)
277                  pthread_attr_setschedparam(&stream_thread_attr, &fifo_param);
278          }
279   #endif
280 +        stream_thread_cancel = false;
281          stream_thread_active = (pthread_create(&stream_thread, &stream_thread_attr, stream_func, NULL) == 0);
282  
283 <        // Everything OK
283 >        // Everything went fine
284          audio_open = true;
285 +        return true;
286 + }
287 +
288 + void AudioInit(void)
289 + {
290 +        // Init audio status (reasonable defaults) and feature flags
291 +        AudioStatus.sample_rate = 44100 << 16;
292 +        AudioStatus.sample_size = 16;
293 +        AudioStatus.channels = 2;
294 +        AudioStatus.mixer = 0;
295 +        AudioStatus.num_sources = 0;
296 +        audio_component_flags = cmpWantsRegisterMessage | kStereoOut | k16BitOut;
297 +
298 +        // Sound disabled in prefs? Then do nothing
299 +        if (PrefsFindBool("nosound"))
300 +                return;
301 +
302 +        // Init semaphore
303 +        if (sem_init(&audio_irq_done_sem, 0, 0) < 0)
304 +                return;
305 +        sem_inited = true;
306 +
307 +        // Try to open /dev/mixer
308 +        mixer_fd = open("/dev/mixer", O_RDWR);
309 +        if (mixer_fd < 0)
310 +                printf("WARNING: Cannot open /dev/mixer (%s)", strerror(errno));
311 +
312 +        // Open and initialize audio device
313 +        open_audio();
314   }
315  
316  
# Line 239 | Line 318 | void AudioInit(void)
318   *  Deinitialization
319   */
320  
321 < void AudioExit(void)
321 > static void close_audio(void)
322   {
323          // Stop stream and delete semaphore
324          if (stream_thread_active) {
# Line 250 | Line 329 | void AudioExit(void)
329                  pthread_join(stream_thread, NULL);
330                  stream_thread_active = false;
331          }
253        if (sem_inited)
254                sem_destroy(&audio_irq_done_sem);
332  
333 <        // Close /dev/dsp
334 <        if (audio_fd > 0)
333 >        // Close /dev/dsp or ESD socket
334 >        if (audio_fd >= 0) {
335                  close(audio_fd);
336 +                audio_fd = -1;
337 +        }
338 +
339 +        audio_open = false;
340 + }
341 +
342 + void AudioExit(void)
343 + {
344 +        // Close audio device
345 +        close_audio();
346 +
347 +        // Delete semaphore
348 +        if (sem_inited) {
349 +                sem_destroy(&audio_irq_done_sem);
350 +                sem_inited = false;
351 +        }
352  
353          // Close /dev/mixer
354 <        if (mixer_fd > 0)
354 >        if (mixer_fd >= 0) {
355                  close(mixer_fd);
356 +                mixer_fd = -1;
357 +        }
358   }
359  
360  
# Line 287 | Line 382 | void audio_exit_stream()
382   *  Streaming function
383   */
384  
290 static uint32 apple_stream_info;        // Mac address of SoundComponentData struct describing next buffer
291
385   static void *stream_func(void *arg)
386   {
387          int16 *silent_buffer = new int16[sound_buffer_size / 2];
# Line 372 | Line 465 | void AudioInterrupt(void)
465  
466   /*
467   *  Set sampling parameters
468 < *  "index" is an index into the audio_sample_rates[] etc. arrays
468 > *  "index" is an index into the audio_sample_rates[] etc. vectors
469   *  It is guaranteed that AudioStatus.num_sources == 0
470   */
471  
472 < void audio_set_sample_rate(int index)
472 > bool audio_set_sample_rate(int index)
473   {
474 +        close_audio();
475 +        audio_sample_rate_index = index;
476 +        return open_audio();
477   }
478  
479 < void audio_set_sample_size(int index)
479 > bool audio_set_sample_size(int index)
480   {
481 +        close_audio();
482 +        audio_sample_size_index = index;
483 +        return open_audio();
484   }
485  
486 < void audio_set_channels(int index)
486 > bool audio_set_channels(int index)
487   {
488 +        close_audio();
489 +        audio_channel_count_index = index;
490 +        return open_audio();
491   }
492  
493  

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines