comparison src/audio/alsa/SDL_alsa_audio.c @ 4292:464126f4c7db SDL-1.2

Moved to stable ALSA API. This cleans up a few problems with our use of the ancient ALSA 0.9 API. This means we can ditch the dlvsym() nonsense and use SDL_LoadFunction(), too. Fixes Bugzilla #745.
author Ryan C. Gordon <icculus@icculus.org>
date Sat, 10 Oct 2009 07:33:18 +0000
parents a1b03ba2fcd0
children 33d306630296
comparison
equal deleted inserted replaced
4291:6cc2b35ac610 4292:464126f4c7db
31 #include "../SDL_audiomem.h" 31 #include "../SDL_audiomem.h"
32 #include "../SDL_audio_c.h" 32 #include "../SDL_audio_c.h"
33 #include "SDL_alsa_audio.h" 33 #include "SDL_alsa_audio.h"
34 34
35 #ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC 35 #ifdef SDL_AUDIO_DRIVER_ALSA_DYNAMIC
36 #include <dlfcn.h>
37 #include "SDL_name.h" 36 #include "SDL_name.h"
38 #include "SDL_loadso.h" 37 #include "SDL_loadso.h"
39 #else 38 #else
40 #define SDL_NAME(X) X 39 #define SDL_NAME(X) X
41 #endif 40 #endif
72 static size_t (*SDL_NAME(snd_pcm_sw_params_sizeof))(void); 71 static size_t (*SDL_NAME(snd_pcm_sw_params_sizeof))(void);
73 static int (*SDL_NAME(snd_pcm_hw_params_any))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params); 72 static int (*SDL_NAME(snd_pcm_hw_params_any))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
74 static int (*SDL_NAME(snd_pcm_hw_params_set_access))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t access); 73 static int (*SDL_NAME(snd_pcm_hw_params_set_access))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_access_t access);
75 static int (*SDL_NAME(snd_pcm_hw_params_set_format))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t val); 74 static int (*SDL_NAME(snd_pcm_hw_params_set_format))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_format_t val);
76 static int (*SDL_NAME(snd_pcm_hw_params_set_channels))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val); 75 static int (*SDL_NAME(snd_pcm_hw_params_set_channels))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val);
77 static int (*SDL_NAME(snd_pcm_hw_params_get_channels))(const snd_pcm_hw_params_t *params); 76 static int (*SDL_NAME(snd_pcm_hw_params_set_rate_near))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir);
78 static unsigned int (*SDL_NAME(snd_pcm_hw_params_set_rate_near))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int *dir); 77 static int (*SDL_NAME(snd_pcm_hw_params_set_period_size_near))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t *val, int *dir);
79 static snd_pcm_uframes_t (*SDL_NAME(snd_pcm_hw_params_set_period_size_near))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, snd_pcm_uframes_t val, int *dir); 78 static int (*SDL_NAME(snd_pcm_hw_params_get_channels))(const snd_pcm_hw_params_t *params, unsigned int *val);
80 static snd_pcm_sframes_t (*SDL_NAME(snd_pcm_hw_params_get_period_size))(const snd_pcm_hw_params_t *params); 79 static snd_pcm_sframes_t (*SDL_NAME(snd_pcm_hw_params_get_period_size))(const snd_pcm_hw_params_t *params);
81 static unsigned int (*SDL_NAME(snd_pcm_hw_params_set_periods_near))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int val, int *dir); 80 static int (*SDL_NAME(snd_pcm_hw_params_set_periods_near))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params, unsigned int *val, int *dir);
82 static int (*SDL_NAME(snd_pcm_hw_params_get_periods))(snd_pcm_hw_params_t *params); 81 static int (*SDL_NAME(snd_pcm_hw_params_get_periods))(snd_pcm_hw_params_t *params);
83 static int (*SDL_NAME(snd_pcm_hw_params))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params); 82 static int (*SDL_NAME(snd_pcm_hw_params))(snd_pcm_t *pcm, snd_pcm_hw_params_t *params);
84 /* 83 /*
85 */ 84 */
86 static int (*SDL_NAME(snd_pcm_sw_params_current))(snd_pcm_t *pcm, snd_pcm_sw_params_t *swparams); 85 static int (*SDL_NAME(snd_pcm_sw_params_current))(snd_pcm_t *pcm, snd_pcm_sw_params_t *swparams);
123 { "snd_pcm_nonblock", (void**)(char*)&SDL_NAME(snd_pcm_nonblock) }, 122 { "snd_pcm_nonblock", (void**)(char*)&SDL_NAME(snd_pcm_nonblock) },
124 }; 123 };
125 124
126 static void UnloadALSALibrary(void) { 125 static void UnloadALSALibrary(void) {
127 if (alsa_loaded) { 126 if (alsa_loaded) {
128 /* SDL_UnloadObject(alsa_handle);*/ 127 SDL_UnloadObject(alsa_handle);
129 dlclose(alsa_handle);
130 alsa_handle = NULL; 128 alsa_handle = NULL;
131 alsa_loaded = 0; 129 alsa_loaded = 0;
132 } 130 }
133 } 131 }
134 132
135 static int LoadALSALibrary(void) { 133 static int LoadALSALibrary(void) {
136 int i, retval = -1; 134 int i, retval = -1;
137 135
138 /* alsa_handle = SDL_LoadObject(alsa_library);*/ 136 alsa_handle = SDL_LoadObject(alsa_library);
139 alsa_handle = dlopen(alsa_library,RTLD_NOW);
140 if (alsa_handle) { 137 if (alsa_handle) {
141 alsa_loaded = 1; 138 alsa_loaded = 1;
142 retval = 0; 139 retval = 0;
143 for (i = 0; i < SDL_arraysize(alsa_functions); i++) { 140 for (i = 0; i < SDL_arraysize(alsa_functions); i++) {
144 /* *alsa_functions[i].func = SDL_LoadFunction(alsa_handle,alsa_functions[i].name);*/ 141 *alsa_functions[i].func = SDL_LoadFunction(alsa_handle,alsa_functions[i].name);
145 #if HAVE_DLVSYM
146 *alsa_functions[i].func = dlvsym(alsa_handle,alsa_functions[i].name,"ALSA_0.9");
147 if (!*alsa_functions[i].func)
148 #endif
149 *alsa_functions[i].func = dlsym(alsa_handle,alsa_functions[i].name);
150 if (!*alsa_functions[i].func) { 142 if (!*alsa_functions[i].func) {
151 retval = -1; 143 retval = -1;
152 UnloadALSALibrary(); 144 UnloadALSALibrary();
153 break; 145 break;
154 } 146 }
372 int status; 364 int status;
373 snd_pcm_hw_params_t *hwparams; 365 snd_pcm_hw_params_t *hwparams;
374 snd_pcm_sw_params_t *swparams; 366 snd_pcm_sw_params_t *swparams;
375 snd_pcm_format_t format; 367 snd_pcm_format_t format;
376 snd_pcm_uframes_t frames; 368 snd_pcm_uframes_t frames;
369 unsigned int rate;
370 unsigned int periods;
371 unsigned int channels;
377 Uint16 test_format; 372 Uint16 test_format;
378 373
379 /* Open the audio device */ 374 /* Open the audio device */
380 /* Name of device should depend on # channels in spec */ 375 /* Name of device should depend on # channels in spec */
381 status = SDL_NAME(snd_pcm_open)(&pcm_handle, get_audio_device(spec->channels), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); 376 status = SDL_NAME(snd_pcm_open)(&pcm_handle, get_audio_device(spec->channels), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
443 } 438 }
444 spec->format = test_format; 439 spec->format = test_format;
445 440
446 /* Set the number of channels */ 441 /* Set the number of channels */
447 status = SDL_NAME(snd_pcm_hw_params_set_channels)(pcm_handle, hwparams, spec->channels); 442 status = SDL_NAME(snd_pcm_hw_params_set_channels)(pcm_handle, hwparams, spec->channels);
448 if ( status < 0 ) { 443 channels = spec->channels;
449 status = SDL_NAME(snd_pcm_hw_params_get_channels)(hwparams); 444 if ( status < 0 ) {
450 if ( (status <= 0) || (status > 2) ) { 445 status = SDL_NAME(snd_pcm_hw_params_get_channels)(hwparams, &channels);
446 if ( status < 0 ) {
451 SDL_SetError("Couldn't set audio channels"); 447 SDL_SetError("Couldn't set audio channels");
452 ALSA_CloseAudio(this); 448 ALSA_CloseAudio(this);
453 return(-1); 449 return(-1);
454 } 450 }
455 spec->channels = status; 451 spec->channels = channels;
456 } 452 }
457 453
458 /* Set the audio rate */ 454 /* Set the audio rate */
459 status = SDL_NAME(snd_pcm_hw_params_set_rate_near)(pcm_handle, hwparams, spec->freq, NULL); 455 rate = spec->freq;
456
457 status = SDL_NAME(snd_pcm_hw_params_set_rate_near)(pcm_handle, hwparams, &rate, NULL);
460 if ( status < 0 ) { 458 if ( status < 0 ) {
461 SDL_SetError("Couldn't set audio frequency: %s", SDL_NAME(snd_strerror)(status)); 459 SDL_SetError("Couldn't set audio frequency: %s", SDL_NAME(snd_strerror)(status));
462 ALSA_CloseAudio(this); 460 ALSA_CloseAudio(this);
463 return(-1); 461 return(-1);
464 } 462 }
465 spec->freq = status; 463 spec->freq = rate;
466 464
467 /* Set the buffer size, in samples */ 465 /* Set the buffer size, in samples */
468 frames = spec->samples; 466 frames = spec->samples;
469 frames = SDL_NAME(snd_pcm_hw_params_set_period_size_near)(pcm_handle, hwparams, frames, NULL); 467 status = SDL_NAME(snd_pcm_hw_params_set_period_size_near)(pcm_handle, hwparams, &frames, NULL);
468 if ( status < 0 ) {
469 SDL_SetError("Couldn't set audio frequency: %s", SDL_NAME(snd_strerror)(status));
470 ALSA_CloseAudio(this);
471 return(-1);
472 }
473
470 spec->samples = frames; 474 spec->samples = frames;
471 SDL_NAME(snd_pcm_hw_params_set_periods_near)(pcm_handle, hwparams, 2, NULL); 475
476 periods = 2;
477 SDL_NAME(snd_pcm_hw_params_set_periods_near)(pcm_handle, hwparams, &periods, NULL);
472 478
473 /* "set" the hardware with the desired parameters */ 479 /* "set" the hardware with the desired parameters */
474 status = SDL_NAME(snd_pcm_hw_params)(pcm_handle, hwparams); 480 status = SDL_NAME(snd_pcm_hw_params)(pcm_handle, hwparams);
475 if ( status < 0 ) { 481 if ( status < 0 ) {
476 SDL_SetError("Couldn't set hardware audio parameters: %s", SDL_NAME(snd_strerror)(status)); 482 SDL_SetError("Couldn't set hardware audio parameters: %s", SDL_NAME(snd_strerror)(status));