comparison src/audio/bsd/SDL_bsdaudio.c @ 1662:782fd950bd46 SDL-1.3

Revamp of the video system in progress - adding support for multiple displays, multiple windows, and a full video mode selection API. WARNING: None of the video drivers have been updated for the new API yet! The API is still under design and very fluid. The code is now run through a consistent indent format: indent -i4 -nut -nsc -br -ce The headers are being converted to automatically generate doxygen documentation.
author Sam Lantinga <slouken@libsdl.org>
date Sun, 28 May 2006 13:04:16 +0000
parents 95451df282c3
children 4da1ee79c9af
comparison
equal deleted inserted replaced
1661:281d3f4870e5 1662:782fd950bd46
65 #else 65 #else
66 #define OPEN_FLAGS (O_WRONLY|O_NONBLOCK) 66 #define OPEN_FLAGS (O_WRONLY|O_NONBLOCK)
67 #endif 67 #endif
68 68
69 /* Audio driver functions */ 69 /* Audio driver functions */
70 static void OBSD_WaitAudio(_THIS); 70 static void OBSD_WaitAudio (_THIS);
71 static int OBSD_OpenAudio(_THIS, SDL_AudioSpec *spec); 71 static int OBSD_OpenAudio (_THIS, SDL_AudioSpec * spec);
72 static void OBSD_PlayAudio(_THIS); 72 static void OBSD_PlayAudio (_THIS);
73 static Uint8 *OBSD_GetAudioBuf(_THIS); 73 static Uint8 *OBSD_GetAudioBuf (_THIS);
74 static void OBSD_CloseAudio(_THIS); 74 static void OBSD_CloseAudio (_THIS);
75 75
76 #ifdef DEBUG_AUDIO 76 #ifdef DEBUG_AUDIO
77 static void OBSD_Status(_THIS); 77 static void OBSD_Status (_THIS);
78 #endif 78 #endif
79 79
80 /* Audio driver bootstrap functions */ 80 /* Audio driver bootstrap functions */
81 81
82 static int 82 static int
83 Audio_Available(void) 83 Audio_Available (void)
84 { 84 {
85 int fd; 85 int fd;
86 int available; 86 int available;
87 87
88 available = 0; 88 available = 0;
89 fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0); 89 fd = SDL_OpenAudioPath (NULL, 0, OPEN_FLAGS, 0);
90 if(fd >= 0) { 90 if (fd >= 0) {
91 available = 1; 91 available = 1;
92 close(fd); 92 close (fd);
93 } 93 }
94 return(available); 94 return (available);
95 } 95 }
96 96
97 static void 97 static void
98 Audio_DeleteDevice(SDL_AudioDevice *device) 98 Audio_DeleteDevice (SDL_AudioDevice * device)
99 { 99 {
100 SDL_free(device->hidden); 100 SDL_free (device->hidden);
101 SDL_free(device); 101 SDL_free (device);
102 } 102 }
103 103
104 static SDL_AudioDevice 104 static SDL_AudioDevice *
105 *Audio_CreateDevice(int devindex) 105 Audio_CreateDevice (int devindex)
106 { 106 {
107 SDL_AudioDevice *this; 107 SDL_AudioDevice *this;
108 108
109 /* Initialize all variables that we clean on shutdown */ 109 /* Initialize all variables that we clean on shutdown */
110 this = (SDL_AudioDevice*)SDL_malloc(sizeof(SDL_AudioDevice)); 110 this = (SDL_AudioDevice *) SDL_malloc (sizeof (SDL_AudioDevice));
111 if(this) { 111 if (this) {
112 SDL_memset(this, 0, (sizeof *this)); 112 SDL_memset (this, 0, (sizeof *this));
113 this->hidden = 113 this->hidden = (struct SDL_PrivateAudioData *)
114 (struct SDL_PrivateAudioData*)SDL_malloc((sizeof *this->hidden)); 114 SDL_malloc ((sizeof *this->hidden));
115 } 115 }
116 if((this == NULL) || (this->hidden == NULL)) { 116 if ((this == NULL) || (this->hidden == NULL)) {
117 SDL_OutOfMemory(); 117 SDL_OutOfMemory ();
118 if(this) SDL_free(this); 118 if (this)
119 return(0); 119 SDL_free (this);
120 } 120 return (0);
121 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); 121 }
122 SDL_memset (this->hidden, 0, (sizeof *this->hidden));
122 audio_fd = -1; 123 audio_fd = -1;
123 124
124 /* Set the function pointers */ 125 /* Set the function pointers */
125 this->OpenAudio = OBSD_OpenAudio; 126 this->OpenAudio = OBSD_OpenAudio;
126 this->WaitAudio = OBSD_WaitAudio; 127 this->WaitAudio = OBSD_WaitAudio;
127 this->PlayAudio = OBSD_PlayAudio; 128 this->PlayAudio = OBSD_PlayAudio;
128 this->GetAudioBuf = OBSD_GetAudioBuf; 129 this->GetAudioBuf = OBSD_GetAudioBuf;
129 this->CloseAudio = OBSD_CloseAudio; 130 this->CloseAudio = OBSD_CloseAudio;
130 131
131 this->free = Audio_DeleteDevice; 132 this->free = Audio_DeleteDevice;
132 133
133 return this; 134 return this;
134 } 135 }
135 136
136 AudioBootStrap BSD_AUDIO_bootstrap = { 137 AudioBootStrap BSD_AUDIO_bootstrap = {
137 BSD_AUDIO_DRIVER_NAME, BSD_AUDIO_DRIVER_DESC, 138 BSD_AUDIO_DRIVER_NAME, BSD_AUDIO_DRIVER_DESC,
138 Audio_Available, Audio_CreateDevice 139 Audio_Available, Audio_CreateDevice
139 }; 140 };
140 141
141 /* This function waits until it is possible to write a full sound buffer */ 142 /* This function waits until it is possible to write a full sound buffer */
142 static void 143 static void
143 OBSD_WaitAudio(_THIS) 144 OBSD_WaitAudio (_THIS)
144 { 145 {
145 #ifndef USE_BLOCKING_WRITES /* Not necessary when using blocking writes */ 146 #ifndef USE_BLOCKING_WRITES /* Not necessary when using blocking writes */
146 /* See if we need to use timed audio synchronization */ 147 /* See if we need to use timed audio synchronization */
147 if ( frame_ticks ) { 148 if (frame_ticks) {
148 /* Use timer for general audio synchronization */ 149 /* Use timer for general audio synchronization */
149 Sint32 ticks; 150 Sint32 ticks;
150 151
151 ticks = ((Sint32)(next_frame - SDL_GetTicks()))-FUDGE_TICKS; 152 ticks = ((Sint32) (next_frame - SDL_GetTicks ())) - FUDGE_TICKS;
152 if ( ticks > 0 ) { 153 if (ticks > 0) {
153 SDL_Delay(ticks); 154 SDL_Delay (ticks);
154 } 155 }
155 } else { 156 } else {
156 /* Use select() for audio synchronization */ 157 /* Use select() for audio synchronization */
157 fd_set fdset; 158 fd_set fdset;
158 struct timeval timeout; 159 struct timeval timeout;
159 160
160 FD_ZERO(&fdset); 161 FD_ZERO (&fdset);
161 FD_SET(audio_fd, &fdset); 162 FD_SET (audio_fd, &fdset);
162 timeout.tv_sec = 10; 163 timeout.tv_sec = 10;
163 timeout.tv_usec = 0; 164 timeout.tv_usec = 0;
164 #ifdef DEBUG_AUDIO 165 #ifdef DEBUG_AUDIO
165 fprintf(stderr, "Waiting for audio to get ready\n"); 166 fprintf (stderr, "Waiting for audio to get ready\n");
166 #endif 167 #endif
167 if ( select(audio_fd+1, NULL, &fdset, NULL, &timeout) <= 0 ) { 168 if (select (audio_fd + 1, NULL, &fdset, NULL, &timeout) <= 0) {
168 const char *message = 169 const char *message =
169 "Audio timeout - buggy audio driver? (disabled)"; 170 "Audio timeout - buggy audio driver? (disabled)";
170 /* In general we should never print to the screen, 171 /* In general we should never print to the screen,
171 but in this case we have no other way of letting 172 but in this case we have no other way of letting
172 the user know what happened. 173 the user know what happened.
173 */ 174 */
174 fprintf(stderr, "SDL: %s\n", message); 175 fprintf (stderr, "SDL: %s\n", message);
175 this->enabled = 0; 176 this->enabled = 0;
176 /* Don't try to close - may hang */ 177 /* Don't try to close - may hang */
177 audio_fd = -1; 178 audio_fd = -1;
178 #ifdef DEBUG_AUDIO 179 #ifdef DEBUG_AUDIO
179 fprintf(stderr, "Done disabling audio\n"); 180 fprintf (stderr, "Done disabling audio\n");
180 #endif 181 #endif
181 } 182 }
182 #ifdef DEBUG_AUDIO 183 #ifdef DEBUG_AUDIO
183 fprintf(stderr, "Ready!\n"); 184 fprintf (stderr, "Ready!\n");
184 #endif 185 #endif
185 } 186 }
186 #endif /* !USE_BLOCKING_WRITES */ 187 #endif /* !USE_BLOCKING_WRITES */
187 } 188 }
188 189
189 static void 190 static void
190 OBSD_PlayAudio(_THIS) 191 OBSD_PlayAudio (_THIS)
191 { 192 {
192 int written, p=0; 193 int written, p = 0;
193 194
194 /* Write the audio data, checking for EAGAIN on broken audio drivers */ 195 /* Write the audio data, checking for EAGAIN on broken audio drivers */
195 do { 196 do {
196 written = write(audio_fd, &mixbuf[p], mixlen-p); 197 written = write (audio_fd, &mixbuf[p], mixlen - p);
197 if (written>0) 198 if (written > 0)
198 p += written; 199 p += written;
199 if (written == -1 && errno != 0 && errno != EAGAIN && errno != EINTR) 200 if (written == -1 && errno != 0 && errno != EAGAIN && errno != EINTR) {
200 { 201 /* Non recoverable error has occurred. It should be reported!!! */
201 /* Non recoverable error has occurred. It should be reported!!! */ 202 perror ("audio");
202 perror("audio"); 203 break;
203 break; 204 }
204 } 205
205 206 if (p < written
206 if ( p < written || ((written < 0) && ((errno == 0) || (errno == EAGAIN))) ) { 207 || ((written < 0) && ((errno == 0) || (errno == EAGAIN)))) {
207 SDL_Delay(1); /* Let a little CPU time go by */ 208 SDL_Delay (1); /* Let a little CPU time go by */
208 } 209 }
209 } while ( p < written ); 210 }
210 211 while (p < written);
211 /* If timer synchronization is enabled, set the next write frame */ 212
212 if ( frame_ticks ) { 213 /* If timer synchronization is enabled, set the next write frame */
213 next_frame += frame_ticks; 214 if (frame_ticks) {
214 } 215 next_frame += frame_ticks;
215 216 }
216 /* If we couldn't write, assume fatal error for now */ 217
217 if ( written < 0 ) { 218 /* If we couldn't write, assume fatal error for now */
218 this->enabled = 0; 219 if (written < 0) {
219 } 220 this->enabled = 0;
220 #ifdef DEBUG_AUDIO 221 }
221 fprintf(stderr, "Wrote %d bytes of audio data\n", written); 222 #ifdef DEBUG_AUDIO
222 #endif 223 fprintf (stderr, "Wrote %d bytes of audio data\n", written);
223 } 224 #endif
224 225 }
225 static Uint8 226
226 *OBSD_GetAudioBuf(_THIS) 227 static Uint8 *
227 { 228 OBSD_GetAudioBuf (_THIS)
228 return(mixbuf); 229 {
230 return (mixbuf);
229 } 231 }
230 232
231 static void 233 static void
232 OBSD_CloseAudio(_THIS) 234 OBSD_CloseAudio (_THIS)
233 { 235 {
234 if(mixbuf != NULL) { 236 if (mixbuf != NULL) {
235 SDL_FreeAudioMem(mixbuf); 237 SDL_FreeAudioMem (mixbuf);
236 mixbuf = NULL; 238 mixbuf = NULL;
237 } 239 }
238 if(audio_fd >= 0) { 240 if (audio_fd >= 0) {
239 close(audio_fd); 241 close (audio_fd);
240 audio_fd = -1; 242 audio_fd = -1;
241 } 243 }
242 } 244 }
243 245
244 #ifdef DEBUG_AUDIO 246 #ifdef DEBUG_AUDIO
245 void 247 void
246 OBSD_Status(_THIS) 248 OBSD_Status (_THIS)
247 { 249 {
248 audio_info_t info; 250 audio_info_t info;
249 251
250 if(ioctl(audio_fd, AUDIO_GETINFO, &info) < 0) { 252 if (ioctl (audio_fd, AUDIO_GETINFO, &info) < 0) {
251 fprintf(stderr,"AUDIO_GETINFO failed.\n"); 253 fprintf (stderr, "AUDIO_GETINFO failed.\n");
252 return; 254 return;
253 } 255 }
254 256
255 fprintf(stderr,"\n" 257 fprintf (stderr, "\n"
256 "[play/record info]\n" 258 "[play/record info]\n"
257 "buffer size : %d bytes\n" 259 "buffer size : %d bytes\n"
258 "sample rate : %i Hz\n" 260 "sample rate : %i Hz\n"
259 "channels : %i\n" 261 "channels : %i\n"
260 "precision : %i-bit\n" 262 "precision : %i-bit\n"
261 "encoding : 0x%x\n" 263 "encoding : 0x%x\n"
262 "seek : %i\n" 264 "seek : %i\n"
263 "sample count : %i\n" 265 "sample count : %i\n"
264 "EOF count : %i\n" 266 "EOF count : %i\n"
265 "paused : %s\n" 267 "paused : %s\n"
266 "error occured : %s\n" 268 "error occured : %s\n"
267 "waiting : %s\n" 269 "waiting : %s\n"
268 "active : %s\n" 270 "active : %s\n"
269 "", 271 "",
270 info.play.buffer_size, 272 info.
271 info.play.sample_rate, 273 play.
272 info.play.channels, 274 buffer_size,
273 info.play.precision, 275 info.
274 info.play.encoding, 276 play.
275 info.play.seek, 277 sample_rate,
276 info.play.samples, 278 info.
277 info.play.eof, 279 play.
278 info.play.pause ? "yes" : "no", 280 channels,
279 info.play.error ? "yes" : "no", 281 info.
280 info.play.waiting ? "yes" : "no", 282 play.
281 info.play.active ? "yes": "no"); 283 precision,
282 284 info.
283 fprintf(stderr,"\n" 285 play.
284 "[audio info]\n" 286 encoding,
285 "monitor_gain : %i\n" 287 info.
286 "hw block size : %d bytes\n" 288 play.
287 "hi watermark : %i\n" 289 seek,
288 "lo watermark : %i\n" 290 info.
289 "audio mode : %s\n" 291 play.
290 "", 292 samples,
291 info.monitor_gain, 293 info.
292 info.blocksize, 294 play.
293 info.hiwat, info.lowat, 295 eof,
294 (info.mode == AUMODE_PLAY) ? "PLAY" 296 info.
295 : (info.mode = AUMODE_RECORD) ? "RECORD" 297 play.
296 : (info.mode == AUMODE_PLAY_ALL ? "PLAY_ALL" 298 pause
297 : "?")); 299 ?
300 "yes"
301 :
302 "no",
303 info.
304 play.
305 error
306 ?
307 "yes"
308 :
309 "no",
310 info.
311 play.waiting ? "yes" : "no", info.play.active ? "yes" : "no");
312
313 fprintf (stderr, "\n"
314 "[audio info]\n"
315 "monitor_gain : %i\n"
316 "hw block size : %d bytes\n"
317 "hi watermark : %i\n"
318 "lo watermark : %i\n"
319 "audio mode : %s\n"
320 "",
321 info.monitor_gain,
322 info.blocksize,
323 info.hiwat, info.lowat,
324 (info.mode == AUMODE_PLAY) ? "PLAY"
325 : (info.mode = AUMODE_RECORD) ? "RECORD"
326 : (info.mode == AUMODE_PLAY_ALL ? "PLAY_ALL" : "?"));
298 } 327 }
299 #endif /* DEBUG_AUDIO */ 328 #endif /* DEBUG_AUDIO */
300 329
301 static int 330 static int
302 OBSD_OpenAudio(_THIS, SDL_AudioSpec *spec) 331 OBSD_OpenAudio (_THIS, SDL_AudioSpec * spec)
303 { 332 {
304 char audiodev[64]; 333 char audiodev[64];
305 Uint16 format; 334 Uint16 format;
306 audio_info_t info; 335 audio_info_t info;
307 336
308 AUDIO_INITINFO(&info); 337 AUDIO_INITINFO (&info);
309 338
310 /* Calculate the final parameters for this audio specification */ 339 /* Calculate the final parameters for this audio specification */
311 SDL_CalculateAudioSpec(spec); 340 SDL_CalculateAudioSpec (spec);
312 341
313 #ifdef USE_TIMER_SYNC 342 #ifdef USE_TIMER_SYNC
314 frame_ticks = 0.0; 343 frame_ticks = 0.0;
315 #endif 344 #endif
316 345
317 /* Open the audio device */ 346 /* Open the audio device */
318 audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0); 347 audio_fd = SDL_OpenAudioPath (audiodev, sizeof (audiodev), OPEN_FLAGS, 0);
319 if(audio_fd < 0) { 348 if (audio_fd < 0) {
320 SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); 349 SDL_SetError ("Couldn't open %s: %s", audiodev, strerror (errno));
321 return(-1); 350 return (-1);
322 } 351 }
323 352
324 /* Set to play mode */ 353 /* Set to play mode */
325 info.mode = AUMODE_PLAY; 354 info.mode = AUMODE_PLAY;
326 if(ioctl(audio_fd, AUDIO_SETINFO, &info) < 0) { 355 if (ioctl (audio_fd, AUDIO_SETINFO, &info) < 0) {
327 SDL_SetError("Couldn't put device into play mode"); 356 SDL_SetError ("Couldn't put device into play mode");
328 return(-1); 357 return (-1);
329 } 358 }
330 359
331 mixbuf = NULL; 360 mixbuf = NULL;
332 AUDIO_INITINFO(&info); 361 AUDIO_INITINFO (&info);
333 for (format = SDL_FirstAudioFormat(spec->format); 362 for (format = SDL_FirstAudioFormat (spec->format);
334 format; format = SDL_NextAudioFormat()) 363 format; format = SDL_NextAudioFormat ()) {
335 { 364 switch (format) {
336 switch(format) { 365 case AUDIO_U8:
337 case AUDIO_U8: 366 info.play.encoding = AUDIO_ENCODING_ULINEAR;
338 info.play.encoding = AUDIO_ENCODING_ULINEAR; 367 info.play.precision = 8;
339 info.play.precision = 8; 368 break;
340 break; 369 case AUDIO_S8:
341 case AUDIO_S8: 370 info.play.encoding = AUDIO_ENCODING_SLINEAR;
342 info.play.encoding = AUDIO_ENCODING_SLINEAR; 371 info.play.precision = 8;
343 info.play.precision = 8; 372 break;
344 break; 373 case AUDIO_S16LSB:
345 case AUDIO_S16LSB: 374 info.play.encoding = AUDIO_ENCODING_SLINEAR_LE;
346 info.play.encoding = AUDIO_ENCODING_SLINEAR_LE; 375 info.play.precision = 16;
347 info.play.precision = 16; 376 break;
348 break; 377 case AUDIO_S16MSB:
349 case AUDIO_S16MSB: 378 info.play.encoding = AUDIO_ENCODING_SLINEAR_BE;
350 info.play.encoding = AUDIO_ENCODING_SLINEAR_BE; 379 info.play.precision = 16;
351 info.play.precision = 16; 380 break;
352 break; 381 case AUDIO_U16LSB:
353 case AUDIO_U16LSB: 382 info.play.encoding = AUDIO_ENCODING_ULINEAR_LE;
354 info.play.encoding = AUDIO_ENCODING_ULINEAR_LE; 383 info.play.precision = 16;
355 info.play.precision = 16; 384 break;
356 break; 385 case AUDIO_U16MSB:
357 case AUDIO_U16MSB: 386 info.play.encoding = AUDIO_ENCODING_ULINEAR_BE;
358 info.play.encoding = AUDIO_ENCODING_ULINEAR_BE; 387 info.play.precision = 16;
359 info.play.precision = 16; 388 break;
360 break; 389 default:
361 default: 390 continue;
362 continue; 391 }
363 } 392 if (ioctl (audio_fd, AUDIO_SETINFO, &info) == 0)
364 if (ioctl(audio_fd, AUDIO_SETINFO, &info) == 0) 393 break;
365 break; 394 }
366 } 395
367 396 if (!format) {
368 if(!format) { 397 SDL_SetError ("No supported encoding for 0x%x", spec->format);
369 SDL_SetError("No supported encoding for 0x%x", spec->format); 398 return (-1);
370 return(-1);
371 } 399 }
372 400
373 spec->format = format; 401 spec->format = format;
374 402
375 AUDIO_INITINFO(&info); 403 AUDIO_INITINFO (&info);
376 info.play.channels = spec->channels; 404 info.play.channels = spec->channels;
377 if (ioctl(audio_fd, AUDIO_SETINFO, &info) == -1) 405 if (ioctl (audio_fd, AUDIO_SETINFO, &info) == -1)
378 spec->channels = 1; 406 spec->channels = 1;
379 AUDIO_INITINFO(&info); 407 AUDIO_INITINFO (&info);
380 info.play.sample_rate = spec->freq; 408 info.play.sample_rate = spec->freq;
381 info.blocksize = spec->size; 409 info.blocksize = spec->size;
382 info.hiwat = 5; 410 info.hiwat = 5;
383 info.lowat = 3; 411 info.lowat = 3;
384 (void)ioctl(audio_fd, AUDIO_SETINFO, &info); 412 (void) ioctl (audio_fd, AUDIO_SETINFO, &info);
385 (void)ioctl(audio_fd, AUDIO_GETINFO, &info); 413 (void) ioctl (audio_fd, AUDIO_GETINFO, &info);
386 spec->freq = info.play.sample_rate; 414 spec->freq = info.play.sample_rate;
387 /* Allocate mixing buffer */ 415 /* Allocate mixing buffer */
388 mixlen = spec->size; 416 mixlen = spec->size;
389 mixbuf = (Uint8*)SDL_AllocAudioMem(mixlen); 417 mixbuf = (Uint8 *) SDL_AllocAudioMem (mixlen);
390 if(mixbuf == NULL) { 418 if (mixbuf == NULL) {
391 return(-1); 419 return (-1);
392 } 420 }
393 SDL_memset(mixbuf, spec->silence, spec->size); 421 SDL_memset (mixbuf, spec->silence, spec->size);
394 422
395 /* Get the parent process id (we're the parent of the audio thread) */ 423 /* Get the parent process id (we're the parent of the audio thread) */
396 parent = getpid(); 424 parent = getpid ();
397 425
398 #ifdef DEBUG_AUDIO 426 #ifdef DEBUG_AUDIO
399 OBSD_Status(this); 427 OBSD_Status (this);
400 #endif 428 #endif
401 429
402 /* We're ready to rock and roll. :-) */ 430 /* We're ready to rock and roll. :-) */
403 return(0); 431 return (0);
404 } 432 }
433
434 /* vi: set ts=4 sw=4 expandtab: */