[alsa-devel] is statically linking libasound supported? because if i do it, i cant open the device!
i have a test app that works successfully with hw:0,1 on gnto if i link it dynamically:
dmx-gnto jutz # ./atestminhw1 Playback device is hw:0,1 Stream parameters are 48000Hz, S16_LE, 6 channels Rate set to 48000Hz (requested 48000Hz) Buffer size range from 6 to 5461 Period size range from 3 to 2730 Using max buffer size 5460 Periods = 4 was set period_size = 1365 was set buffer_size = 5460 Channel: 0 Freq: 220.000000
but it fails to find hw:0,1 if i link it statically, is that expected behavior?
dmx-gnto jutz # ./atestminhw1 Playback device is hw:0,1 Stream parameters are 48000Hz, S16_LE, 6 channels ALSA lib pcm.c:2109:(snd_pcm_open_conf) symbol _snd_pcm_hw_open is not defined inside (null) Failed: No such device or address
this line succeeds with a dynamic linking and fails with
if(0 > (iErr = snd_pcm_open(&pPcm, gs_pcNameDev, SND_PCM_STREAM_PLAYBACK, 0))) goto fin;
here is my static link arguments:
gcc -g -static -o atestminhw1 atestmin.c -lasound -lm -lpthread -ldl
here is my dynamic link arguments:
gcc -g -o atestminhw1 atestmin.c -lasound
and, for completeness, here is my lame test app, derived from other test apps that come with the source:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sched.h> #include <errno.h> #include <getopt.h> #include <inttypes.h> #include <ctype.h> #include <byteswap.h>
#define ALSA_PCM_NEW_HW_PARAMS_API #define ALSA_PCM_NEW_SW_PARAMS_API #include <alsa/asoundlib.h> #include <sys/time.h> #include <math.h>
#define MAX_CHANNELS 16
static char *gs_pcNameDev = "hw:0,1"; /* playback device */ //static char *gs_pcNameDev = "plughw"; /* playback device */ //static char *gs_pcNameDev = "default"; /* playback device */ static snd_pcm_format_t gs_SndPcmFmt = SND_PCM_FORMAT_S16; /* sample format */ static unsigned int gs_uRate = 48000; /* stream rate */ static unsigned int gs_uCntChan = 6; /* count of channels */ static unsigned int gs_uTimBuf = 0; /* ring buffer length in us */ static unsigned int gs_uTimPer = 0; /* period time in us */ static unsigned int gs_uCntPer = 4; /* number of periods */ static double gs_dFreq = 440; /* sinusoidal wave frequency in Hz */ static snd_pcm_uframes_t gs_uSizBuf; static snd_pcm_uframes_t gs_uSizPer;
static int set_hwparams(snd_pcm_t *handle, snd_pcm_hw_params_t *params, snd_pcm_access_t access) { unsigned int uRate; int iErr; snd_pcm_uframes_t period_size_min; snd_pcm_uframes_t period_size_max; snd_pcm_uframes_t buffer_size_min; snd_pcm_uframes_t buffer_size_max;
/* choose all parameters */
if (0 > (iErr = snd_pcm_hw_params_any(handle, params))) { printf("Broken configuration for playback: no configurations available: %s\n", snd_strerror(iErr)); return iErr; }
/* set the interleaved read/write format */
if (0 > (iErr = snd_pcm_hw_params_set_access(handle, params, access))) { printf("Access type not available for playback: %s\n", snd_strerror(iErr)); return iErr; }
/* set the sample format */
if (0 > (iErr = snd_pcm_hw_params_set_format(handle, params, gs_SndPcmFmt))) { printf("Sample format not available for playback: %s\n", snd_strerror(iErr)); return iErr; }
/* set the count of channels */
if (0 > (iErr = snd_pcm_hw_params_set_channels(handle, params, gs_uCntChan))) { printf("Channels count (%i) not available for playbacks: %s\n", gs_uCntChan, snd_strerror(iErr)); return iErr; }
/* set the stream rate */ uRate = gs_uRate;
if (0 > (iErr = snd_pcm_hw_params_set_rate(handle, params, gs_uRate, 0))) { printf("Rate %iHz not available for playback: %s\n", gs_uRate, snd_strerror(iErr)); return iErr; }
if (uRate != gs_uRate) { printf("Rate doesn't match (requested %iHz, get %iHz, err %d)\n", gs_uRate, uRate, iErr); return -EINVAL; }
printf("Rate set to %iHz (requested %iHz)\n", uRate, gs_uRate);
/* set the buffer time */
iErr = snd_pcm_hw_params_get_buffer_size_min(params, &buffer_size_min); iErr = snd_pcm_hw_params_get_buffer_size_max(params, &buffer_size_max); iErr = snd_pcm_hw_params_get_period_size_min(params, &period_size_min, NULL); iErr = snd_pcm_hw_params_get_period_size_max(params, &period_size_max, NULL);
printf("Buffer size range from %lu to %lu\n",buffer_size_min, buffer_size_max); printf("Period size range from %lu to %lu\n",period_size_min, period_size_max);
if (gs_uTimPer > 0) { printf("Requested period time %u us\n", gs_uTimPer);
if (0 > (iErr = snd_pcm_hw_params_set_period_time_near(handle, params, &gs_uTimPer, NULL))) { printf("Unable to set period time %u us for playback: %s\n", gs_uTimPer, snd_strerror(iErr)); return iErr; } }
if (gs_uTimBuf > 0) { printf("Requested buffer time %u us\n", gs_uTimBuf);
if (0 > (iErr = snd_pcm_hw_params_set_buffer_time_near(handle, params, &gs_uTimBuf, NULL))) { printf("Unable to set buffer time %u us for playback: %s\n", gs_uTimBuf, snd_strerror(iErr)); return iErr; } }
if (! gs_uTimBuf && ! gs_uTimPer) { gs_uSizBuf = buffer_size_max; if (! gs_uTimPer) gs_uSizBuf = (gs_uSizBuf / gs_uCntPer) * gs_uCntPer;
printf("Using max buffer size %lu\n", gs_uSizBuf);
if (0 > (iErr = snd_pcm_hw_params_set_buffer_size_near(handle, params, &gs_uSizBuf))) { printf("Unable to set buffer size %lu for playback: %s\n", gs_uSizBuf, snd_strerror(iErr)); return iErr; } }
if (! gs_uTimBuf || ! gs_uTimPer) { printf("Periods = %u\n", gs_uCntPer);
if (0 > (iErr = snd_pcm_hw_params_set_periods_near(handle, params, &gs_uCntPer, NULL))) { printf("Unable to set nperiods %u for playback: %s\n", gs_uCntPer, snd_strerror(iErr)); return iErr; } }
snd_pcm_hw_params_get_buffer_size(params, &gs_uSizBuf); snd_pcm_hw_params_get_period_size(params, &gs_uSizPer, NULL); printf("was set period_size = %lu\n",gs_uSizPer); printf("was set buffer_size = %lu\n",gs_uSizBuf); if (2*gs_uSizPer > gs_uSizBuf) { printf("buffer to small, could not use\n"); return iErr; }
/* write the parameters to device */ iErr = snd_pcm_hw_params(handle, params); if (iErr < 0) { printf("Unable to set hw params for playback: %s\n", snd_strerror(iErr)); return iErr; }
return 0; }
static int set_swparams(snd_pcm_t *handle, snd_pcm_sw_params_t *swparams) { int iErr;
/* get the current swparams */
if (0 > (iErr = snd_pcm_sw_params_current(handle, swparams))) { printf("Unable to determine current swparams for playback: %s\n", snd_strerror(iErr)); return iErr; }
/* start the transfer when a buffer is full */
if (0 > (iErr = snd_pcm_sw_params_set_start_threshold(handle, swparams, gs_uSizBuf))) { printf("Unable to set start threshold mode for playback: %s\n", snd_strerror(iErr)); return iErr; }
/* allow the transfer when at least period_size frames can be processed */
if (0 > (iErr = snd_pcm_sw_params_set_avail_min(handle, swparams, gs_uSizPer))) { printf("Unable to set avail min for playback: %s\n", snd_strerror(iErr)); return iErr; }
/* align all transfers to 1 sample */
if (0 > (iErr = snd_pcm_sw_params_set_xfer_align(handle, swparams, 1))) { printf("Unable to set transfer align for playback: %s\n", snd_strerror(iErr)); return iErr; }
/* write the parameters to the playback device */
if (0 > (iErr = snd_pcm_sw_params(handle, swparams))) { printf("Unable to set sw params for playback: %s\n", snd_strerror(iErr)); return iErr; }
return 0; }
static void generate_sine(uint8_t *pu8Frames, int iChannel, int iCntFrames, double *pdPhase, float fFreq) { double dPhase = *pdPhase; double dPhaseMax = 1.0 / fFreq; double dSizStep = 1.0 / (double)gs_uRate; double dRes; int iIdxChan; int32_t i32Res; int16_t *pi16Samp = (int16_t*) pu8Frames;
while (iCntFrames-- > 0) { for(iIdxChan=0;iIdxChan<gs_uCntChan;iIdxChan++) if (iIdxChan==iChannel) { dRes = (sin((dPhase * 2 * M_PI) / dPhaseMax - M_PI)) * 0x03fffffff; /* Don't use MAX volume */ i32Res = dRes; *pi16Samp++ = i32Res >>16; } else *pi16Samp++ = 0;
dPhase += dSizStep;
if (dPhase >= dPhaseMax) dPhase -= dPhaseMax; }
*pdPhase = dPhase; }
/* * Underrun and suspend recovery */
static int xrun_recovery(snd_pcm_t *pPcm, int iErr) { if (iErr == -EPIPE) { /* under-run */ iErr = snd_pcm_prepare(pPcm); if (iErr < 0) printf("Can't recovery from underrun, prepare failed: %s\n", snd_strerror(iErr)); return 0; } else if (iErr == -ESTRPIPE) {
while ((iErr = snd_pcm_resume(pPcm)) == -EAGAIN) sleep(1); /* wait until the suspend flag is released */
if (iErr < 0) { iErr = snd_pcm_prepare(pPcm); if (iErr < 0) printf("Can't recovery from suspend, prepare failed: %s\n", snd_strerror(iErr)); }
return 0; }
return iErr; }
static int write_loop(snd_pcm_t *pPcm, int iChan, int iNumPer, uint8_t *pu8Frames) { double phase = 0; int iErr, iIdxPer, iCntFrames; uint8_t *pu8FramesLocal; float fFreq = gs_dFreq*(iChan+1)/2; // provide an audible chan change cue
printf("Channel: %d Freq: %f\n", iChan, fFreq);
for(iIdxPer = 0; iIdxPer < iNumPer; iIdxPer++) { iCntFrames = gs_uSizPer; pu8FramesLocal = pu8Frames;
generate_sine(pu8FramesLocal, iChan, gs_uSizPer, &phase, fFreq);
while (0 < iCntFrames) { if (-EAGAIN == (iErr = snd_pcm_writei(pPcm, pu8FramesLocal, iCntFrames))) continue;
if (0 > iErr) { printf("Write error: %d,%s\n", iErr, snd_strerror(iErr)); if (0 > xrun_recovery(pPcm, iErr)) { printf("xrun_recovery failed: %d,%s\n", iErr, snd_strerror(iErr)); return -1; } break; // skip one period }
pu8FramesLocal += snd_pcm_frames_to_bytes(pPcm, iErr); iCntFrames -= iErr; } }
if (gs_uSizBuf > iIdxPer * gs_uSizPer) { snd_pcm_drain(pPcm); snd_pcm_prepare(pPcm ); } return 0; }
int main(int argc, char *argv[]) { int iErr; int iIdxChan; uint8_t *pu8Frames = NULL; snd_pcm_t *pPcm = NULL; snd_pcm_hw_params_t *hwparams; snd_pcm_sw_params_t *swparams;
snd_pcm_hw_params_alloca(&hwparams); snd_pcm_sw_params_alloca(&swparams);
printf("Playback device is %s\n", gs_pcNameDev); printf("Stream parameters are %iHz, %s, %i channels\n", gs_uRate, snd_pcm_format_name(gs_SndPcmFmt), gs_uCntChan);
if(0 > (iErr = snd_pcm_open(&pPcm, gs_pcNameDev, SND_PCM_STREAM_PLAYBACK, 0))) goto fin;
if(0 > (iErr = set_hwparams(pPcm, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED))) goto fin;
if(0 > (iErr = set_swparams(pPcm, swparams))) goto fin;
if(!(pu8Frames = malloc(snd_pcm_frames_to_bytes(pPcm, gs_uSizPer)))) goto fin;
while(1) for(iIdxChan = 0; iIdxChan < gs_uCntChan; iIdxChan++) if (0> (iErr = write_loop(pPcm, iIdxChan, (gs_uRate*3)/gs_uSizPer, pu8Frames))) goto fin;
iErr = EXIT_SUCCESS;
fin:
if(iErr) printf("Failed: %s\n",snd_strerror(iErr));
if(pu8Frames) free(pu8Frames);
if(pPcm) snd_pcm_close(pPcm);
exit(iErr); }
At Tue, 27 Mar 2007 18:05:50 -0700, John Utz wrote:
but it fails to find hw:0,1 if i link it statically, is that expected behavior?
Did you check alsa-lib/INSTALL file? For creating a static lib, you have to use --disable-shared _and_ --enable-static.
Takashi
-----Original Message----- From: Takashi Iwai [mailto:tiwai@suse.de] Sent: Wed 3/28/2007 3:13 AM To: John Utz Cc: alsa-devel@alsa-project.org Subject: Re: [alsa-devel] is statically linking libasound supported? because if i do it, i cant open the device!
At Tue, 27 Mar 2007 18:05:50 -0700, John Utz wrote:
but it fails to find hw:0,1 if i link it statically, is that expected behavior?
Did you check alsa-lib/INSTALL file? For creating a static lib, you have to use --disable-shared _and_ --enable-static.
Why would i need to --disable-shared? i wanted both!
I got the libasound.a just find and it linked the app and the app *runs*, it just doesnt find the device!
Takashi
At Wed, 28 Mar 2007 10:06:01 -0700, John Utz wrote:
-----Original Message----- From: Takashi Iwai [mailto:tiwai@suse.de] Sent: Wed 3/28/2007 3:13 AM To: John Utz Cc: alsa-devel@alsa-project.org Subject: Re: [alsa-devel] is statically linking libasound supported? because if i do it, i cant open the device!
At Tue, 27 Mar 2007 18:05:50 -0700, John Utz wrote:
but it fails to find hw:0,1 if i link it statically, is that expected behavior?
Did you check alsa-lib/INSTALL file? For creating a static lib, you have to use --disable-shared _and_ --enable-static.
Why would i need to --disable-shared? i wanted both!
You cannot build both *.a and *.so _at the same time_ for alsa-lib. partly because of bad behavior of libtool, partly because of the design of alsa-lib (embedded plugins in static lib).
Simply build twice, once for a shared lib and once for a static lib.
I got the libasound.a just find and it linked the app and the app *runs*, it just doesnt find the device!
The libasound.a is broken.
Takashi
At Wed, 28 Mar 2007 19:11:17 +0200, I wrote:
At Wed, 28 Mar 2007 10:06:01 -0700, John Utz wrote:
-----Original Message----- From: Takashi Iwai [mailto:tiwai@suse.de] Sent: Wed 3/28/2007 3:13 AM To: John Utz Cc: alsa-devel@alsa-project.org Subject: Re: [alsa-devel] is statically linking libasound supported? because if i do it, i cant open the device!
At Tue, 27 Mar 2007 18:05:50 -0700, John Utz wrote:
but it fails to find hw:0,1 if i link it statically, is that expected behavior?
Did you check alsa-lib/INSTALL file? For creating a static lib, you have to use --disable-shared _and_ --enable-static.
Why would i need to --disable-shared? i wanted both!
You cannot build both *.a and *.so _at the same time_ for alsa-lib. partly because of bad behavior of libtool, partly because of the design of alsa-lib (embedded plugins in static lib).
Simply build twice, once for a shared lib and once for a static lib.
I got the libasound.a just find and it linked the app and the app *runs*, it just doesnt find the device!
The libasound.a is broken.
Well, I meant the libasound.a you made is broken. When you build libasound.a without --disable-shared, it passes -DPIC and it's built with assumption of shared library use.
Takashi
-----Original Message----- From: Takashi Iwai [mailto:tiwai@suse.de]
You cannot build both *.a and *.so _at the same time_ for alsa-lib. partly because of bad behavior of libtool, partly because of the design of alsa-lib (embedded plugins in static lib).
Simply build twice, once for a shared lib and once for a static lib.
I got the libasound.a just find and it linked the app and the app *runs*, it just doesnt find the device!
The libasound.a is broken.
* Well, I meant the libasound.a you made is broken. * When you build libasound.a without --disable-shared, it passes -DPIC * and it's built with assumption of shared library use.
AHH! thankyou for explaining that! i am greatful for the increase in my understanding of library compilation 'dynamics' (for want of a better term :-) )
tnx for the 'schoolin''
i'll report back on my outcome.
Takashi
forgive the top post;
(supposedly IT is gonna turn on IMAP on the exchange server for YT RSN and then i can write rfc compliant email)
i followed tiwai's recommendation and corrected my configure arguments to disable shared and enable static.
once i correctly placed the conf files on the target boxes (rh62, gentoo) i was able to have success with a statically linked app on the gentoo box; however i had a lot of grief on rh62!
on rh62, i would get a segfault parsing the pcm.conf file.
however, once i limited my static linking to libasound only instead of libasound, libc, libpthread and libdl i was able to have success on rh62 as well.
tnx for your help IWAI-san!
johnu
-----Original Message----- From: alsa-devel-bounces@alsa-project.org on behalf of John Utz Sent: Wed 3/28/2007 10:15 AM To: Takashi Iwai Cc: alsa-devel@alsa-project.org Subject: Re: [alsa-devel] is statically linking libasound supported? because if i do it, i cant open the device!
-----Original Message----- From: Takashi Iwai [mailto:tiwai@suse.de]
You cannot build both *.a and *.so _at the same time_ for alsa-lib. partly because of bad behavior of libtool, partly because of the design of alsa-lib (embedded plugins in static lib).
Simply build twice, once for a shared lib and once for a static lib.
I got the libasound.a just find and it linked the app and the app *runs*, it just doesnt find the device!
The libasound.a is broken.
* Well, I meant the libasound.a you made is broken. * When you build libasound.a without --disable-shared, it passes -DPIC * and it's built with assumption of shared library use.
AHH! thankyou for explaining that! i am greatful for the increase in my understanding of library compilation 'dynamics' (for want of a better term :-) )
tnx for the 'schoolin''
i'll report back on my outcome.
Takashi
_______________________________________________ Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
participants (2)
-
John Utz
-
Takashi Iwai