Mercurial > sdl-ios-xcode
comparison src/audio/alsa/SDL_alsa_audio.c @ 3362:4e83cdb58134
Merged r4990:4991 from branches/SDL-1.2: ALSA 1.0 API and dlvsym() removal.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Sat, 10 Oct 2009 07:34:15 +0000 |
parents | b21348d47cab |
children | 631173ffd68f |
comparison
equal
deleted
inserted
replaced
3361:d559edc85610 | 3362:4e83cdb58134 |
---|---|
23 | 23 |
24 /* Allow access to a raw mixing buffer */ | 24 /* Allow access to a raw mixing buffer */ |
25 | 25 |
26 #include <sys/types.h> | 26 #include <sys/types.h> |
27 #include <signal.h> /* For kill() */ | 27 #include <signal.h> /* For kill() */ |
28 #include <dlfcn.h> | |
29 #include <errno.h> | 28 #include <errno.h> |
30 #include <string.h> | 29 #include <string.h> |
31 | 30 |
32 #include "SDL_timer.h" | 31 #include "SDL_timer.h" |
33 #include "SDL_audio.h" | 32 #include "SDL_audio.h" |
34 #include "../SDL_audiomem.h" | 33 #include "../SDL_audiomem.h" |
35 #include "../SDL_audio_c.h" | 34 #include "../SDL_audio_c.h" |
36 #include "SDL_alsa_audio.h" | 35 #include "SDL_alsa_audio.h" |
37 | 36 |
37 #ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC | |
38 #include "SDL_loadso.h" | |
39 #endif | |
38 | 40 |
39 /* The tag name used by ALSA audio */ | 41 /* The tag name used by ALSA audio */ |
40 #define DRIVER_NAME "alsa" | 42 #define DRIVER_NAME "alsa" |
41 | 43 |
42 /* The default ALSA audio driver */ | 44 /* The default ALSA audio driver */ |
58 (snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_access_t); | 60 (snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_access_t); |
59 static int (*ALSA_snd_pcm_hw_params_set_format) | 61 static int (*ALSA_snd_pcm_hw_params_set_format) |
60 (snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_format_t); | 62 (snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_format_t); |
61 static int (*ALSA_snd_pcm_hw_params_set_channels) | 63 static int (*ALSA_snd_pcm_hw_params_set_channels) |
62 (snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int); | 64 (snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int); |
63 static int (*ALSA_snd_pcm_hw_params_get_channels) (const snd_pcm_hw_params_t | 65 static int (*ALSA_snd_pcm_hw_params_set_rate_near) |
64 *); | 66 (snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int *, int *); |
65 static unsigned int (*ALSA_snd_pcm_hw_params_set_rate_near) | 67 static int (*ALSA_snd_pcm_hw_params_set_period_size_near) |
66 (snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int, int *); | 68 (snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_uframes_t *, int *); |
67 static snd_pcm_uframes_t(*ALSA_snd_pcm_hw_params_set_period_size_near) | 69 static int (*ALSA_snd_pcm_hw_params_get_channels) |
68 (snd_pcm_t *, snd_pcm_hw_params_t *, snd_pcm_uframes_t, int *); | 70 (const snd_pcm_hw_params_t *, unsigned int *); |
69 static snd_pcm_sframes_t(*ALSA_snd_pcm_hw_params_get_period_size) | 71 static snd_pcm_sframes_t(*ALSA_snd_pcm_hw_params_get_period_size) |
70 (const snd_pcm_hw_params_t *); | 72 (const snd_pcm_hw_params_t *); |
71 static unsigned int (*ALSA_snd_pcm_hw_params_set_periods_near) | 73 static int (*ALSA_snd_pcm_hw_params_set_periods_near) |
72 (snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int, int *); | 74 (snd_pcm_t *, snd_pcm_hw_params_t *, unsigned int *, int *); |
73 static int (*ALSA_snd_pcm_hw_params_get_periods) (snd_pcm_hw_params_t *); | 75 static int (*ALSA_snd_pcm_hw_params_get_periods) (snd_pcm_hw_params_t *); |
74 static int (*ALSA_snd_pcm_hw_params) (snd_pcm_t *, snd_pcm_hw_params_t *); | 76 static int (*ALSA_snd_pcm_hw_params) (snd_pcm_t *, snd_pcm_hw_params_t *); |
75 static int (*ALSA_snd_pcm_sw_params_current) (snd_pcm_t *, | 77 static int (*ALSA_snd_pcm_sw_params_current) (snd_pcm_t *, |
76 snd_pcm_sw_params_t *); | 78 snd_pcm_sw_params_t *); |
77 static int (*ALSA_snd_pcm_sw_params_set_start_threshold) | 79 static int (*ALSA_snd_pcm_sw_params_set_start_threshold) |
90 static void *alsa_handle = NULL; | 92 static void *alsa_handle = NULL; |
91 | 93 |
92 static int | 94 static int |
93 load_alsa_sym(const char *fn, void **addr) | 95 load_alsa_sym(const char *fn, void **addr) |
94 { | 96 { |
95 /* | 97 *addr = SDL_LoadFunction(alsa_handle, fn); |
96 * !!! FIXME: | 98 if (*addr == NULL) { |
97 * Eventually, this will deal with fallbacks, version changes, and | 99 /* Don't call SDL_SetError(): SDL_LoadFunction already did. */ |
98 * missing symbols we can workaround. But for now, it doesn't. | 100 return 0; |
99 */ | |
100 | |
101 #if HAVE_DLVSYM | |
102 *addr = dlvsym(alsa_handle, fn, "ALSA_0.9"); | |
103 if (*addr == NULL) | |
104 #endif | |
105 { | |
106 *addr = dlsym(alsa_handle, fn); | |
107 if (*addr == NULL) { | |
108 SDL_SetError("dlsym('%s') failed: %s", fn, strerror(errno)); | |
109 return 0; | |
110 } | |
111 } | 101 } |
112 | 102 |
113 return 1; | 103 return 1; |
114 } | 104 } |
115 | 105 |
157 | 147 |
158 static void | 148 static void |
159 UnloadALSALibrary(void) | 149 UnloadALSALibrary(void) |
160 { | 150 { |
161 if (alsa_handle != NULL) { | 151 if (alsa_handle != NULL) { |
162 dlclose(alsa_handle); | 152 SDL_UnloadObject(alsa_handle); |
163 alsa_handle = NULL; | 153 alsa_handle = NULL; |
164 } | 154 } |
165 } | 155 } |
166 | 156 |
167 static int | 157 static int |
168 LoadALSALibrary(void) | 158 LoadALSALibrary(void) |
169 { | 159 { |
170 int retval = 0; | 160 int retval = 0; |
171 if (alsa_handle == NULL) { | 161 if (alsa_handle == NULL) { |
172 alsa_handle = dlopen(alsa_library, RTLD_NOW); | 162 alsa_handle = SDL_LoadObject(alsa_library); |
173 if (alsa_handle == NULL) { | 163 if (alsa_handle == NULL) { |
174 retval = -1; | 164 retval = -1; |
175 SDL_SetError("ALSA: dlopen('%s') failed: %s\n", | 165 /* Don't call SDL_SetError(): SDL_LoadObject already did. */ |
176 alsa_library, strerror(errno)); | |
177 } else { | 166 } else { |
178 retval = load_alsa_syms(); | 167 retval = load_alsa_syms(); |
179 if (retval < 0) { | 168 if (retval < 0) { |
180 UnloadALSALibrary(); | 169 UnloadALSALibrary(); |
181 } | 170 } |
378 snd_pcm_hw_params_t *hwparams = NULL; | 367 snd_pcm_hw_params_t *hwparams = NULL; |
379 snd_pcm_sw_params_t *swparams = NULL; | 368 snd_pcm_sw_params_t *swparams = NULL; |
380 snd_pcm_format_t format = 0; | 369 snd_pcm_format_t format = 0; |
381 snd_pcm_uframes_t frames = 0; | 370 snd_pcm_uframes_t frames = 0; |
382 SDL_AudioFormat test_format = 0; | 371 SDL_AudioFormat test_format = 0; |
372 unsigned int rate = 0; | |
373 unsigned int periods = 0; | |
374 unsigned int channels = 0; | |
383 | 375 |
384 /* Initialize all variables that we clean on shutdown */ | 376 /* Initialize all variables that we clean on shutdown */ |
385 this->hidden = (struct SDL_PrivateAudioData *) | 377 this->hidden = (struct SDL_PrivateAudioData *) |
386 SDL_malloc((sizeof *this->hidden)); | 378 SDL_malloc((sizeof *this->hidden)); |
387 if (this->hidden == NULL) { | 379 if (this->hidden == NULL) { |
481 this->spec.format = test_format; | 473 this->spec.format = test_format; |
482 | 474 |
483 /* Set the number of channels */ | 475 /* Set the number of channels */ |
484 status = ALSA_snd_pcm_hw_params_set_channels(pcm_handle, hwparams, | 476 status = ALSA_snd_pcm_hw_params_set_channels(pcm_handle, hwparams, |
485 this->spec.channels); | 477 this->spec.channels); |
486 if (status < 0) { | 478 channels = this->spec.channels; |
487 status = ALSA_snd_pcm_hw_params_get_channels(hwparams); | 479 if (status < 0) { |
488 if ((status <= 0) || (status > 2)) { | 480 status = ALSA_snd_pcm_hw_params_get_channels(hwparams, &channels); |
481 if (status < 0) { | |
489 ALSA_CloseDevice(this); | 482 ALSA_CloseDevice(this); |
490 SDL_SetError("ALSA: Couldn't set audio channels"); | 483 SDL_SetError("ALSA: Couldn't set audio channels"); |
491 return 0; | 484 return 0; |
492 } | 485 } |
493 this->spec.channels = status; | 486 this->spec.channels = channels; |
494 } | 487 } |
495 | 488 |
496 /* Set the audio rate */ | 489 /* Set the audio rate */ |
490 rate = this->spec.freq; | |
497 status = ALSA_snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, | 491 status = ALSA_snd_pcm_hw_params_set_rate_near(pcm_handle, hwparams, |
498 this->spec.freq, NULL); | 492 &rate, NULL); |
499 if (status < 0) { | 493 if (status < 0) { |
500 ALSA_CloseDevice(this); | 494 ALSA_CloseDevice(this); |
501 SDL_SetError("ALSA: Couldn't set audio frequency: %s", | 495 SDL_SetError("ALSA: Couldn't set audio frequency: %s", |
502 ALSA_snd_strerror(status)); | 496 ALSA_snd_strerror(status)); |
503 return 0; | 497 return 0; |
504 } | 498 } |
505 this->spec.freq = status; | 499 this->spec.freq = rate; |
506 | 500 |
507 /* Set the buffer size, in samples */ | 501 /* Set the buffer size, in samples */ |
508 frames = this->spec.samples; | 502 frames = this->spec.samples; |
509 frames = ALSA_snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, | 503 status = ALSA_snd_pcm_hw_params_set_period_size_near(pcm_handle, hwparams, |
510 frames, NULL); | 504 &frames, NULL); |
505 if ( status < 0 ) { | |
506 ALSA_CloseDevice(this); | |
507 SDL_SetError("ALSA: Couldn't set audio frequency: %s", | |
508 ALSA_snd_strerror(status)); | |
509 return(-1); | |
510 } | |
511 this->spec.samples = frames; | 511 this->spec.samples = frames; |
512 ALSA_snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, 2, NULL); | 512 |
513 periods = 2; | |
514 ALSA_snd_pcm_hw_params_set_periods_near(pcm_handle, hwparams, | |
515 &periods, NULL); | |
513 | 516 |
514 /* "set" the hardware with the desired parameters */ | 517 /* "set" the hardware with the desired parameters */ |
515 status = ALSA_snd_pcm_hw_params(pcm_handle, hwparams); | 518 status = ALSA_snd_pcm_hw_params(pcm_handle, hwparams); |
516 if (status < 0) { | 519 if (status < 0) { |
517 ALSA_CloseDevice(this); | 520 ALSA_CloseDevice(this); |