strange error with dynamic loading of sound extension
Johannes Nix
jnix at cafeconleche.de
Mon Feb 4 18:06:19 EST 2002
I am trying to build a python extension type for real-time audio
processing with Python. The extension module is a wrapper around the
ALSA library (ALSA is the advanced Linux sound architecture); more
specific, the digital audio or PCM device. ALSA has the advantage that
it supports a number of 24-bit sound cards and it is possible to work
with very small latencies, even running Python.
I've suceeded with SWIG-generated wrappers for ALSA-0.5.9 (you can
find them as "rtaudio" in the Vaults), but with ALSA-0.9 I run in a
very strange problem - and I need this version urgently, so I'm
begging for help.
Basically, when I try to initialize a PCM handle (which is wrapped
into the extension type), I get the following error:
-----------------------------------------------------------------------
jnix at sirrah:~/zosma/rtaudio > ./test.py default
ALSA lib dlmisc.c:97:(snd_dlsym_verify) unable to verify version for symbol snd_config_hook_load
ALSA lib conf.c:2452:(snd_config_hooks_call) symbol snd_config_hook_load is not defined inside (null)
ALSA lib conf.c:2859:(snd_config_update_r) hooks failed, removing configuration
errcode is: -6Traceback (most recent call last):
File "./test.py", line 2, in ?
from rtaudio import pcm
File "/home/jnix/lib/python/rtaudio/__init__.py", line 5, in ?
import alsa_pcm
File "/home/jnix/lib/python/rtaudio/alsa_pcm.py", line 13, in ?
from pcm import *
pcm.error: device open error: No such device or address
------------------------------------------------------------------
The location of the error is in the following extension type method,
it is triggered by snd_pcm_open() :
pcmmodule.c ------------------------------------------------------------------
static PyObject*
pcm_open(pcm_device *self, PyObject *args)
{
int err;
snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
char *devicename;
char *mode;
static snd_pcm_t *handle;
if (!PyArg_ParseTuple(args,"ss",&devicename,&mode)){
return NULL;
}
if (strcmp(mode,"w") == 0)
stream = SND_PCM_STREAM_PLAYBACK;
else if (strcmp(mode,"r") == 0)
stream = SND_PCM_STREAM_CAPTURE;
else {
sprintf(errstr,"open failed: illegal mode '%s'\n",mode);
raise_Error(errstr);
}
fprintf(stderr,"trying to open \"%s\"\n",devicename);
err = snd_pcm_open(&(self->pcm_handle), devicename, stream, 0);
fprintf(stderr,"tried to open \"%s\"\n",devicename);
fprintf(stderr,"errcode is: %i",err);
if (err < 0) {
sprintf(errstr,"device open error: %s\n", snd_strerror(err));
raise_Error(errstr);
}
self->closed = 0;
strncpy(self->name, devicename, MAX_NAME_LEN);
if (strlen(devicename) > MAX_NAME_LEN )
self->name[MAX_NAME_LEN-1] = '\0';
return (PyObject*) self;
}
----------------------------------------------------------
Now, I've glazed about four hours at the signature of snd_pcm_open -
which is right. It seems also true that snd_pcm_open() is the first
function that has to be called, it initializes the PCM device. I
concluded that perhaps something is going wrong because of dynamic
loading, which seems to be added in ALSA-0.9.
Next, I took an example program, which plays a sound file in various formats, and stripped off everything beyound snd_pcm_open(). The results looks like this:
ap.c -------------------------------------------------------------
#include <stdio.h>
#include <alsa/asoundlib.h>
static snd_pcm_t *handle;
int main(int argc, char *argv[])
{
int err;
err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
if (err < 0) {
error("audio open error: %s", snd_strerror(err));
return 1;
}
}
--------------------------------------------------------------------
This program runs smoothly, when compiled with this line:
gcc ap.c -lasound -o ap
, it does not produce any error message.
However, when I change the same program into this tiny extension module:
ad.c ----------------------------------------------------------
#include <stdio.h>
#include <alsa/asoundlib.h>
static snd_pcm_t *handle;
int initad(int argc, char *argv[])
{
int err;
err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0);
if (err < 0) {
error("audio open error: %s", snd_strerror(err));
return 1;
}
}
----------------------------------------------------------------
and compile it with
jnix at sirrah:~/tmp > gcc -c ad.c -o ad.o
jnix at sirrah:~/tmp > gcc -shared ad.o -lasound -o ad.so
and try to import it dynamically into python, I get:
jnix at sirrah:~/tmp > python
Python 2.0 (#1, May 16 2001, 00:02:45)
[GCC 2.95.3 20010315 (SuSE)] on linux2
Type "copyright", "credits" or "license" for more information.
>>> import ad
ALSA lib dlmisc.c:97:(snd_dlsym_verify) unable to verify version for symbol snd_config_hook_load
ALSA lib conf.c:2452:(snd_config_hooks_call) symbol snd_config_hook_load is not defined inside (null)
ALSA lib conf.c:2859:(snd_config_update_r) hooks failed, removing configuration
python: : Unknown error 1075756497
jnix at sirrah:~/tmp >
-------------------------------------------------------
which is obviously the same error as with the full extension module.
So I conclude that the difficulty is related to dynamic loading.
ALSA-0.9 seems to load dynamic stuff too, it has a lot of flexibility
built in, e.g. defining abstract device names in configuration
files. It seems that both systems bite each other.
How can I reconcile them ? I would rather prefer to maintain a dynamic
extension.
I appreciate your help very much.
dynamic-ally but a little bit frustrated, Johannes Nix
More information about the Python-list
mailing list