comparison src/audio/alsa/SDL_alsa_audio.c @ 3627:631173ffd68f

Merged r4991:5154 from branches/SDL-1.2/src/audio/alsa: many 1.2.14 ALSA fixes.
author Ryan C. Gordon <icculus@icculus.org>
date Sun, 10 Jan 2010 07:40:12 +0000
parents 4e83cdb58134
children f7b03b6838cb
comparison
equal deleted inserted replaced
3626:596468a8459e 3627:631173ffd68f
39 #endif 39 #endif
40 40
41 /* The tag name used by ALSA audio */ 41 /* The tag name used by ALSA audio */
42 #define DRIVER_NAME "alsa" 42 #define DRIVER_NAME "alsa"
43 43
44 /* The default ALSA audio driver */
45 #define DEFAULT_DEVICE "default"
46
47 static int (*ALSA_snd_pcm_open) 44 static int (*ALSA_snd_pcm_open)
48 (snd_pcm_t **, const char *, snd_pcm_stream_t, int); 45 (snd_pcm_t **, const char *, snd_pcm_stream_t, int);
49 static int (*ALSA_snd_pcm_close) (snd_pcm_t * pcm); 46 static int (*ALSA_snd_pcm_close) (snd_pcm_t * pcm);
50 static snd_pcm_sframes_t(*ALSA_snd_pcm_writei) 47 static snd_pcm_sframes_t(*ALSA_snd_pcm_writei)
51 (snd_pcm_t *, const void *, snd_pcm_uframes_t); 48 (snd_pcm_t *, const void *, snd_pcm_uframes_t);
52 static int (*ALSA_snd_pcm_resume) (snd_pcm_t *); 49 static int (*ALSA_snd_pcm_recover) (snd_pcm_t *, int, int);
53 static int (*ALSA_snd_pcm_prepare) (snd_pcm_t *); 50 static int (*ALSA_snd_pcm_prepare) (snd_pcm_t *);
54 static int (*ALSA_snd_pcm_drain) (snd_pcm_t *); 51 static int (*ALSA_snd_pcm_drain) (snd_pcm_t *);
55 static const char *(*ALSA_snd_strerror) (int); 52 static const char *(*ALSA_snd_strerror) (int);
56 static size_t(*ALSA_snd_pcm_hw_params_sizeof) (void); 53 static size_t(*ALSA_snd_pcm_hw_params_sizeof) (void);
57 static size_t(*ALSA_snd_pcm_sw_params_sizeof) (void); 54 static size_t(*ALSA_snd_pcm_sw_params_sizeof) (void);
55 static void (*ALSA_snd_pcm_hw_params_copy)
56 (snd_pcm_hw_params_t *, const snd_pcm_hw_params_t *);
58 static int (*ALSA_snd_pcm_hw_params_any) (snd_pcm_t *, snd_pcm_hw_params_t *); 57 static int (*ALSA_snd_pcm_hw_params_any) (snd_pcm_t *, snd_pcm_hw_params_t *);
59 static int (*ALSA_snd_pcm_hw_params_set_access) 58 static int (*ALSA_snd_pcm_hw_params_set_access)
60 (snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_access_t); 59 (snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_access_t);
61 static int (*ALSA_snd_pcm_hw_params_set_format) 60 static int (*ALSA_snd_pcm_hw_params_set_format)
62 (snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_format_t); 61 (snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_format_t);
63 static int (*ALSA_snd_pcm_hw_params_set_channels) 62 static int (*ALSA_snd_pcm_hw_params_set_channels)
64 (snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int); 63 (snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int);
64 static int (*ALSA_snd_pcm_hw_params_get_channels)
65 (const snd_pcm_hw_params_t *, unsigned int *);
65 static int (*ALSA_snd_pcm_hw_params_set_rate_near) 66 static int (*ALSA_snd_pcm_hw_params_set_rate_near)
66 (snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int *, int *); 67 (snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int *, int *);
67 static int (*ALSA_snd_pcm_hw_params_set_period_size_near) 68 static int (*ALSA_snd_pcm_hw_params_set_period_size_near)
68 (snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_uframes_t *, int *); 69 (snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_uframes_t *, int *);
69 static int (*ALSA_snd_pcm_hw_params_get_channels) 70 static int (*ALSA_snd_pcm_hw_params_get_period_size)
70 (const snd_pcm_hw_params_t *, unsigned int *); 71 (const snd_pcm_hw_params_t *, snd_pcm_uframes_t *, int *);
71 static snd_pcm_sframes_t(*ALSA_snd_pcm_hw_params_get_period_size)
72 (const snd_pcm_hw_params_t *);
73 static int (*ALSA_snd_pcm_hw_params_set_periods_near) 72 static int (*ALSA_snd_pcm_hw_params_set_periods_near)
74 (snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int *, int *); 73 (snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int *, int *);
75 static int (*ALSA_snd_pcm_hw_params_get_periods) (snd_pcm_hw_params_t *); 74 static int (*ALSA_snd_pcm_hw_params_get_periods)
75 (const snd_pcm_hw_params_t *, unsigned int *, int *);
76 static int (*ALSA_snd_pcm_hw_params_set_buffer_size_near)
77 (snd_pcm_t *pcm, snd_pcm_hw_params_t *, snd_pcm_uframes_t *);
78 static int (*ALSA_snd_pcm_hw_params_get_buffer_size)
79 (const snd_pcm_hw_params_t *, snd_pcm_uframes_t *);
76 static int (*ALSA_snd_pcm_hw_params) (snd_pcm_t *, snd_pcm_hw_params_t *); 80 static int (*ALSA_snd_pcm_hw_params) (snd_pcm_t *, snd_pcm_hw_params_t *);
77 static int (*ALSA_snd_pcm_sw_params_current) (snd_pcm_t *, 81 static int (*ALSA_snd_pcm_sw_params_current) (snd_pcm_t *,
78 snd_pcm_sw_params_t *); 82 snd_pcm_sw_params_t *);
79 static int (*ALSA_snd_pcm_sw_params_set_start_threshold) 83 static int (*ALSA_snd_pcm_sw_params_set_start_threshold)
80 (snd_pcm_t *, snd_pcm_sw_params_t *, snd_pcm_uframes_t); 84 (snd_pcm_t *, snd_pcm_sw_params_t *, snd_pcm_uframes_t);
81 static int (*ALSA_snd_pcm_sw_params_set_avail_min)
82 (snd_pcm_t *, snd_pcm_sw_params_t *, snd_pcm_uframes_t);
83 static int (*ALSA_snd_pcm_sw_params) (snd_pcm_t *, snd_pcm_sw_params_t *); 85 static int (*ALSA_snd_pcm_sw_params) (snd_pcm_t *, snd_pcm_sw_params_t *);
84 static int (*ALSA_snd_pcm_nonblock) (snd_pcm_t *, int); 86 static int (*ALSA_snd_pcm_nonblock) (snd_pcm_t *, int);
87 static int (*ALSA_snd_pcm_wait)(snd_pcm_t *, int);
85 #define snd_pcm_hw_params_sizeof ALSA_snd_pcm_hw_params_sizeof 88 #define snd_pcm_hw_params_sizeof ALSA_snd_pcm_hw_params_sizeof
86 #define snd_pcm_sw_params_sizeof ALSA_snd_pcm_sw_params_sizeof 89 #define snd_pcm_sw_params_sizeof ALSA_snd_pcm_sw_params_sizeof
87 90
88 91
89 #ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC 92 #ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC
114 load_alsa_syms(void) 117 load_alsa_syms(void)
115 { 118 {
116 SDL_ALSA_SYM(snd_pcm_open); 119 SDL_ALSA_SYM(snd_pcm_open);
117 SDL_ALSA_SYM(snd_pcm_close); 120 SDL_ALSA_SYM(snd_pcm_close);
118 SDL_ALSA_SYM(snd_pcm_writei); 121 SDL_ALSA_SYM(snd_pcm_writei);
119 SDL_ALSA_SYM(snd_pcm_resume); 122 SDL_ALSA_SYM(snd_pcm_recover);
120 SDL_ALSA_SYM(snd_pcm_prepare); 123 SDL_ALSA_SYM(snd_pcm_prepare);
121 SDL_ALSA_SYM(snd_pcm_drain); 124 SDL_ALSA_SYM(snd_pcm_drain);
122 SDL_ALSA_SYM(snd_strerror); 125 SDL_ALSA_SYM(snd_strerror);
123 SDL_ALSA_SYM(snd_pcm_hw_params_sizeof); 126 SDL_ALSA_SYM(snd_pcm_hw_params_sizeof);
124 SDL_ALSA_SYM(snd_pcm_sw_params_sizeof); 127 SDL_ALSA_SYM(snd_pcm_sw_params_sizeof);
128 SDL_ALSA_SYM(snd_pcm_hw_params_copy);
125 SDL_ALSA_SYM(snd_pcm_hw_params_any); 129 SDL_ALSA_SYM(snd_pcm_hw_params_any);
126 SDL_ALSA_SYM(snd_pcm_hw_params_set_access); 130 SDL_ALSA_SYM(snd_pcm_hw_params_set_access);
127 SDL_ALSA_SYM(snd_pcm_hw_params_set_format); 131 SDL_ALSA_SYM(snd_pcm_hw_params_set_format);
128 SDL_ALSA_SYM(snd_pcm_hw_params_set_channels); 132 SDL_ALSA_SYM(snd_pcm_hw_params_set_channels);
129 SDL_ALSA_SYM(snd_pcm_hw_params_get_channels); 133 SDL_ALSA_SYM(snd_pcm_hw_params_get_channels);
130 SDL_ALSA_SYM(snd_pcm_hw_params_set_rate_near); 134 SDL_ALSA_SYM(snd_pcm_hw_params_set_rate_near);
131 SDL_ALSA_SYM(snd_pcm_hw_params_set_period_size_near); 135 SDL_ALSA_SYM(snd_pcm_hw_params_set_period_size_near);
132 SDL_ALSA_SYM(snd_pcm_hw_params_get_period_size); 136 SDL_ALSA_SYM(snd_pcm_hw_params_get_period_size);
133 SDL_ALSA_SYM(snd_pcm_hw_params_set_periods_near); 137 SDL_ALSA_SYM(snd_pcm_hw_params_set_periods_near);
134 SDL_ALSA_SYM(snd_pcm_hw_params_get_periods); 138 SDL_ALSA_SYM(snd_pcm_hw_params_get_periods);
139 SDL_ALSA_SYM(snd_pcm_hw_params_set_buffer_size_near);
140 SDL_ALSA_SYM(snd_pcm_hw_params_get_buffer_size);
135 SDL_ALSA_SYM(snd_pcm_hw_params); 141 SDL_ALSA_SYM(snd_pcm_hw_params);
136 SDL_ALSA_SYM(snd_pcm_sw_params_current); 142 SDL_ALSA_SYM(snd_pcm_sw_params_current);
137 SDL_ALSA_SYM(snd_pcm_sw_params_set_start_threshold); 143 SDL_ALSA_SYM(snd_pcm_sw_params_set_start_threshold);
138 SDL_ALSA_SYM(snd_pcm_sw_params_set_avail_min);
139 SDL_ALSA_SYM(snd_pcm_sw_params); 144 SDL_ALSA_SYM(snd_pcm_sw_params);
140 SDL_ALSA_SYM(snd_pcm_nonblock); 145 SDL_ALSA_SYM(snd_pcm_nonblock);
146 SDL_ALSA_SYM(snd_pcm_wait);
141 return 0; 147 return 0;
142 } 148 }
143 149
144 #undef SDL_ALSA_SYM 150 #undef SDL_ALSA_SYM
145 151
194 { 200 {
195 const char *device; 201 const char *device;
196 202
197 device = SDL_getenv("AUDIODEV"); /* Is there a standard variable name? */ 203 device = SDL_getenv("AUDIODEV"); /* Is there a standard variable name? */
198 if (device == NULL) { 204 if (device == NULL) {
199 if (channels == 6) 205 switch (channels) {
200 device = "surround51"; 206 case 6:
201 else if (channels == 4) 207 device = "plug:surround51";
202 device = "surround40"; 208 break;
203 else 209 case 4:
204 device = DEFAULT_DEVICE; 210 device = "plug:surround40";
211 break;
212 default:
213 device = "default";
214 break;
215 }
205 } 216 }
206 return device; 217 return device;
207 } 218 }
208 219
209 220
210 /* This function waits until it is possible to write a full sound buffer */ 221 /* This function waits until it is possible to write a full sound buffer */
211 static void 222 static void
212 ALSA_WaitDevice(_THIS) 223 ALSA_WaitDevice(_THIS)
213 { 224 {
214 /* Check to see if the thread-parent process is still alive */ 225 /* We're in blocking mode, so there's nothing to do here */
215 {
216 static int cnt = 0;
217 /* Note that this only works with thread implementations
218 that use a different process id for each thread.
219 */
220 /* Check every 10 loops */
221 if (this->hidden->parent && (((++cnt) % 10) == 0)) {
222 if (kill(this->hidden->parent, 0) < 0 && errno == ESRCH) {
223 this->enabled = 0;
224 }
225 }
226 }
227 } 226 }
228 227
229 228
230 /* !!! FIXME: is there a channel swizzler in alsalib instead? */ 229 /* !!! FIXME: is there a channel swizzler in alsalib instead? */
231 /* 230 /*
295 294
296 static void 295 static void
297 ALSA_PlayDevice(_THIS) 296 ALSA_PlayDevice(_THIS)
298 { 297 {
299 int status; 298 int status;
300 int sample_len; 299 const Uint8 *sample_buf = (const Uint8 *) this->hidden->mixbuf;
301 signed short *sample_buf; 300 const int frame_size = (((int) (this->spec.format & 0xFF)) / 8) *
301 this->spec.channels;
302 snd_pcm_uframes_t frames_left = ((snd_pcm_uframes_t) this->spec.samples);
302 303
303 swizzle_alsa_channels(this); 304 swizzle_alsa_channels(this);
304 305
305 sample_len = this->spec.samples; 306 while ( frames_left > 0 && this->enabled ) {
306 sample_buf = (signed short *) this->hidden->mixbuf; 307 /* !!! FIXME: This works, but needs more testing before going live */
307 308 /*ALSA_snd_pcm_wait(this->hidden->pcm_handle, -1);*/
308 while (sample_len > 0) {
309 status = ALSA_snd_pcm_writei(this->hidden->pcm_handle, 309 status = ALSA_snd_pcm_writei(this->hidden->pcm_handle,
310 sample_buf, sample_len); 310 sample_buf, frames_left);
311 311
312 if (status < 0) { 312 if (status < 0) {
313 if (status == -EAGAIN) { 313 if (status == -EAGAIN) {
314 /* Apparently snd_pcm_recover() doesn't handle this case -
315 does it assume snd_pcm_wait() above? */
314 SDL_Delay(1); 316 SDL_Delay(1);
315 continue; 317 continue;
316 } 318 }
317 if (status == -ESTRPIPE) { 319 status = ALSA_snd_pcm_recover(this->hidden->pcm_handle, status, 0);
318 do {
319 SDL_Delay(1);
320 status = ALSA_snd_pcm_resume(this->hidden->pcm_handle);
321 } while (status == -EAGAIN);
322 }
323 if (status < 0) {
324 status = ALSA_snd_pcm_prepare(this->hidden->pcm_handle);
325 }
326 if (status < 0) { 320 if (status < 0) {
327 /* Hmm, not much we can do - abort */ 321 /* Hmm, not much we can do - abort */
322 fprintf(stderr, "ALSA write failed (unrecoverable): %s\n",
323 ALSA_snd_strerror(status));
328 this->enabled = 0; 324 this->enabled = 0;
329 return; 325 return;
330 } 326 }
331 continue; 327 continue;
332 } 328 }
333 sample_buf += status * this->spec.channels; 329 sample_buf += status * frame_size;
334 sample_len -= status; 330 frames_left -= status;
335 } 331 }
336 } 332 }
337 333
338 static Uint8 * 334 static Uint8 *
339 ALSA_GetDeviceBuf(_THIS) 335 ALSA_GetDeviceBuf(_THIS)
355 this->hidden->pcm_handle = NULL; 351 this->hidden->pcm_handle = NULL;
356 } 352 }
357 SDL_free(this->hidden); 353 SDL_free(this->hidden);
358 this->hidden = NULL; 354 this->hidden = NULL;
359 } 355 }
356 }
357
358 static int
359 ALSA_finalize_hardware(_THIS, snd_pcm_hw_params_t *hwparams, int override)
360 {
361 int status;
362 snd_pcm_uframes_t bufsize;
363
364 /* "set" the hardware with the desired parameters */
365 status = ALSA_snd_pcm_hw_params(this->hidden->pcm_handle, hwparams);
366 if ( status < 0 ) {
367 return(-1);
368 }
369
370 /* Get samples for the actual buffer size */
371 status = ALSA_snd_pcm_hw_params_get_buffer_size(hwparams, &bufsize);
372 if ( status < 0 ) {
373 return(-1);
374 }
375 if ( !override && bufsize != this->spec.samples * 2 ) {
376 return(-1);
377 }
378
379 /* !!! FIXME: Is this safe to do? */
380 this->spec.samples = bufsize / 2;
381
382 /* This is useful for debugging */
383 if ( SDL_getenv("SDL_AUDIO_ALSA_DEBUG") ) {
384 snd_pcm_uframes_t persize = 0;
385 unsigned int periods = 0;
386
387 ALSA_snd_pcm_hw_params_get_period_size(hwparams, &persize, NULL);
388 ALSA_snd_pcm_hw_params_get_periods(hwparams, &periods, NULL);
389
390 fprintf(stderr,
391 "ALSA: period size = %ld, periods = %u, buffer size = %lu\n",
392 persize, periods, bufsize);
393 }
394
395 return(0);
396 }
397
398 static int
399 ALSA_set_period_size(_THIS, snd_pcm_hw_params_t *params, int override)
400 {
401 const char *env;
402 int status;
403 snd_pcm_hw_params_t *hwparams;
404 snd_pcm_uframes_t frames;
405 unsigned int periods;
406
407 /* Copy the hardware parameters for this setup */
408 snd_pcm_hw_params_alloca(&hwparams);
409 ALSA_snd_pcm_hw_params_copy(hwparams, params);
410
411 if ( !override ) {
412 env = SDL_getenv("SDL_AUDIO_ALSA_SET_PERIOD_SIZE");
413 if ( env ) {
414 override = SDL_atoi(env);
415 if ( override == 0 ) {
416 return(-1);
417 }
418 }
419 }
420
421 frames = this->spec.samples;
422 status = ALSA_snd_pcm_hw_params_set_period_size_near(
423 this->hidden->pcm_handle, hwparams, &frames, NULL);
424 if ( status < 0 ) {
425 return(-1);
426 }
427
428 periods = 2;
429 status = ALSA_snd_pcm_hw_params_set_periods_near(
430 this->hidden->pcm_handle, hwparams, &periods, NULL);
431 if ( status < 0 ) {
432 return(-1);
433 }
434
435 return ALSA_finalize_hardware(this, hwparams, override);
436 }
437
438 static int
439 ALSA_set_buffer_size(_THIS, snd_pcm_hw_params_t *params, int override)
440 {
441 const char *env;
442 int status;
443 snd_pcm_hw_params_t *hwparams;
444 snd_pcm_uframes_t frames;
445
446 /* Copy the hardware parameters for this setup */
447 snd_pcm_hw_params_alloca(&hwparams);
448 ALSA_snd_pcm_hw_params_copy(hwparams, params);
449
450 if ( !override ) {
451 env = SDL_getenv("SDL_AUDIO_ALSA_SET_BUFFER_SIZE");
452 if ( env ) {
453 override = SDL_atoi(env);
454 if ( override == 0 ) {
455 return(-1);
456 }
457 }
458 }
459
460 frames = this->spec.samples * 2;
461 status = ALSA_snd_pcm_hw_params_set_buffer_size_near(
462 this->hidden->pcm_handle, hwparams, &frames);
463 if ( status < 0 ) {
464 return(-1);
465 }
466
467 return ALSA_finalize_hardware(this, hwparams, override);
360 } 468 }
361 469
362 static int 470 static int
363 ALSA_OpenDevice(_THIS, const char *devname, int iscapture) 471 ALSA_OpenDevice(_THIS, const char *devname, int iscapture)
364 { 472 {
365 int status = 0; 473 int status = 0;
366 snd_pcm_t *pcm_handle = NULL; 474 snd_pcm_t *pcm_handle = NULL;
367 snd_pcm_hw_params_t *hwparams = NULL; 475 snd_pcm_hw_params_t *hwparams = NULL;
368 snd_pcm_sw_params_t *swparams = NULL; 476 snd_pcm_sw_params_t *swparams = NULL;
369 snd_pcm_format_t format = 0; 477 snd_pcm_format_t format = 0;
370 snd_pcm_uframes_t frames = 0;
371 SDL_AudioFormat test_format = 0; 478 SDL_AudioFormat test_format = 0;
372 unsigned int rate = 0; 479 unsigned int rate = 0;
373 unsigned int periods = 0;
374 unsigned int channels = 0; 480 unsigned int channels = 0;
375 481
376 /* Initialize all variables that we clean on shutdown */ 482 /* Initialize all variables that we clean on shutdown */
377 this->hidden = (struct SDL_PrivateAudioData *) 483 this->hidden = (struct SDL_PrivateAudioData *)
378 SDL_malloc((sizeof *this->hidden)); 484 SDL_malloc((sizeof *this->hidden));
497 return 0; 603 return 0;
498 } 604 }
499 this->spec.freq = rate; 605 this->spec.freq = rate;
500 606
501 /* Set the buffer size, in samples */ 607 /* Set the buffer size, in samples */
502 frames = this->spec.samples; 608 if ( ALSA_set_period_size(this, hwparams, 0) < 0 &&
503 status = ALSA_snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, 609 ALSA_set_buffer_size(this, hwparams, 0) < 0 ) {
504 &frames, NULL); 610 /* Failed to set desired buffer size, do the best you can... */
505 if ( status < 0 ) { 611 if ( ALSA_set_period_size(this, hwparams, 1) < 0 ) {
506 ALSA_CloseDevice(this); 612 ALSA_CloseDevice(this);
507 SDL_SetError("ALSA: Couldn't set audio frequency: %s", 613 SDL_SetError("Couldn't set hardware audio parameters: %s", ALSA_snd_strerror(status));
508 ALSA_snd_strerror(status)); 614 return(-1);
509 return(-1); 615 }
510 } 616 }
511 this->spec.samples = frames;
512
513 periods = 2;
514 ALSA_snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams,
515 &periods, NULL);
516
517 /* "set" the hardware with the desired parameters */
518 status = ALSA_snd_pcm_hw_params(pcm_handle, hwparams);
519 if (status < 0) {
520 ALSA_CloseDevice(this);
521 SDL_SetError("ALSA: Couldn't set hardware audio parameters: %s",
522 ALSA_snd_strerror(status));
523 return 0;
524 }
525 #if AUDIO_DEBUG
526 {
527 snd_pcm_sframes_t bufsize;
528 int fragments;
529 bufsize = ALSA_snd_pcm_hw_params_get_period_size(hwparams);
530 fragments = ALSA_snd_pcm_hw_params_get_periods(hwparams);
531 fprintf(stderr, "ALSA: bufsize = %ld, fragments = %d\n", bufsize,
532 fragments);
533 }
534 #endif
535
536 /* Set the software parameters */ 617 /* Set the software parameters */
537 snd_pcm_sw_params_alloca(&swparams); 618 snd_pcm_sw_params_alloca(&swparams);
538 status = ALSA_snd_pcm_sw_params_current(pcm_handle, swparams); 619 status = ALSA_snd_pcm_sw_params_current(pcm_handle, swparams);
539 if (status < 0) { 620 if (status < 0) {
540 ALSA_CloseDevice(this); 621 ALSA_CloseDevice(this);
541 SDL_SetError("ALSA: Couldn't get software config: %s", 622 SDL_SetError("ALSA: Couldn't get software config: %s",
542 ALSA_snd_strerror(status)); 623 ALSA_snd_strerror(status));
543 return 0; 624 return 0;
544 } 625 }
545 status = 626 status =
546 ALSA_snd_pcm_sw_params_set_start_threshold(pcm_handle, swparams, 0); 627 ALSA_snd_pcm_sw_params_set_start_threshold(pcm_handle, swparams, 1);
547 if (status < 0) { 628 if (status < 0) {
548 ALSA_CloseDevice(this); 629 ALSA_CloseDevice(this);
549 SDL_SetError("ALSA: Couldn't set start threshold: %s", 630 SDL_SetError("ALSA: Couldn't set start threshold: %s",
550 ALSA_snd_strerror(status)); 631 ALSA_snd_strerror(status));
551 return 0;
552 }
553 status =
554 ALSA_snd_pcm_sw_params_set_avail_min(pcm_handle, swparams, frames);
555 if (status < 0) {
556 ALSA_CloseDevice(this);
557 SDL_SetError("Couldn't set avail min: %s", ALSA_snd_strerror(status));
558 return 0; 632 return 0;
559 } 633 }
560 status = ALSA_snd_pcm_sw_params(pcm_handle, swparams); 634 status = ALSA_snd_pcm_sw_params(pcm_handle, swparams);
561 if (status < 0) { 635 if (status < 0) {
562 ALSA_CloseDevice(this); 636 ALSA_CloseDevice(this);
575 ALSA_CloseDevice(this); 649 ALSA_CloseDevice(this);
576 SDL_OutOfMemory(); 650 SDL_OutOfMemory();
577 return 0; 651 return 0;
578 } 652 }
579 SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size); 653 SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
580
581 /* Get the parent process id (we're the parent of the audio thread) */
582 this->hidden->parent = getpid();
583 654
584 /* Switch to blocking mode for playback */ 655 /* Switch to blocking mode for playback */
585 ALSA_snd_pcm_nonblock(pcm_handle, 0); 656 ALSA_snd_pcm_nonblock(pcm_handle, 0);
586 657
587 /* We're ready to rock and roll. :-) */ 658 /* We're ready to rock and roll. :-) */
613 return 1; /* !!! FIXME: return 2 once device enum is implemented. */ 684 return 1; /* !!! FIXME: return 2 once device enum is implemented. */
614 } 685 }
615 686
616 687
617 AudioBootStrap ALSA_bootstrap = { 688 AudioBootStrap ALSA_bootstrap = {
618 DRIVER_NAME, "ALSA 0.9 PCM audio", ALSA_Init, 0 689 DRIVER_NAME, "ALSA PCM audio", ALSA_Init, 0
619 }; 690 };
620 691
621 /* vi: set ts=4 sw=4 expandtab: */ 692 /* vi: set ts=4 sw=4 expandtab: */