Hello,
The issue:
calling across .so (dynamic linking) produces different behavior in ALSA library calls than normal, and causes ALSA to malfunction.
I have minimized my issue to as small a code section as possible. Note the code is from commonly available internet examples, including Free Electrons "Audio in embedded linux systems".
The run is:
samiam@samiam-home-pc:~/projects/petit_ami$ gcc -fPIC -c test2.c -o test2.o samiam@samiam-home-pc:~/projects/petit_ami$ gcc -g3 -Iinclude linux/playwav.c ./test2.so -lasound -o playwav samiam@samiam-home-pc:~/projects/petit_ami$ ./playwav alsaplaywave: rate: 1 alsaplaywave: rate: 0 samiam@samiam-home-pc:~/projects/petit_ami$ gcc -g3 -Iinclude linux/playwav.c ./test2.o -lasound -o playwav samiam@samiam-home-pc:~/projects/petit_ami$ ./playwav alsaplaywave: rate: 1 alsaplaywave: rate: 1
Note the only difference between the two runs of "playwave" is if the second module, test2, is linked as a .so or linked as a .o.
The code is: ======================================================================================= playwav.c #include <alsa/asoundlib.h> #include <stdio.h> void alsaplaywave1(void) { snd_pcm_t *pcm_handle; snd_pcm_hw_params_t *params; unsigned int val; unsigned int rate; int r; /* open pcm device */ r = snd_pcm_open(&pcm_handle, "default", SND_PCM_STREAM_PLAYBACK, 0); if (r < 0) printf("Cannot open PCM output device"); snd_pcm_hw_params_alloca(¶ms); /* get hw parameter block */ snd_pcm_hw_params_any(pcm_handle, params); r = snd_pcm_hw_params_set_access(pcm_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); if (r < 0) printf("Cannot set interleaved mode"); r = snd_pcm_hw_params_set_format(pcm_handle, params, SND_PCM_FORMAT_S16_LE); if (r < 0) printf("Cannot set format"); r = snd_pcm_hw_params_set_channels(pcm_handle, params, 2); if (r < 0) printf("Cannot set channels number"); val = 44100; r = snd_pcm_hw_params_set_rate_near(pcm_handle, params, &rate, 0); if (r < 0) printf("Cannot set rate"); snd_pcm_hw_params_get_rate(params, &rate, 0); printf("alsaplaywave: rate: %d\n", rate); snd_pcm_close(pcm_handle); } extern void alsaplaywave2(void); int main(int argc, char **argv) { alsaplaywave1(); alsaplaywave2(); return 0; }
================================================================================== test2.c #include <alsa/asoundlib.h> #include <stdio.h> void alsaplaywave2(void) { snd_pcm_t *pcm_handle; snd_pcm_hw_params_t *params; unsigned int val; unsigned int rate; int r; /* open pcm device */ r = snd_pcm_open(&pcm_handle, "default", SND_PCM_STREAM_PLAYBACK, 0); if (r < 0) printf("Cannot open PCM output device"); snd_pcm_hw_params_alloca(¶ms); /* get hw parameter block */ snd_pcm_hw_params_any(pcm_handle, params); r = snd_pcm_hw_params_set_access(pcm_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED); if (r < 0) printf("Cannot set interleaved mode"); r = snd_pcm_hw_params_set_format(pcm_handle, params, SND_PCM_FORMAT_S16_LE); if (r < 0) printf("Cannot set format"); r = snd_pcm_hw_params_set_channels(pcm_handle, params, 2); if (r < 0) printf("Cannot set channels number"); val = 44100; r = snd_pcm_hw_params_set_rate_near(pcm_handle, params, &rate, 0); if (r < 0) printf("Cannot set rate"); snd_pcm_hw_params_get_rate(params, &rate, 0); printf("alsaplaywave: rate: %d\n", rate); snd_pcm_close(pcm_handle); }