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